diff --git a/TOC-tidb-cloud.md b/TOC-tidb-cloud.md new file mode 100644 index 000000000000..5f3ab1df4b45 --- /dev/null +++ b/TOC-tidb-cloud.md @@ -0,0 +1,857 @@ + + + +# 目录 + +## 快速开始 + +- 为什么选择 TiDB Cloud + - [TiDB Cloud 介绍](/tidb-cloud/tidb-cloud-intro.md) + - [MySQL 兼容性](/mysql-compatibility.md) +- TiDB Cloud 快速开始 + - [试用 TiDB Cloud Serverless](/tidb-cloud/tidb-cloud-quickstart.md) + - [试用 TiDB + AI](/tidb-cloud/vector-search-get-started-using-python.md) + - [试用 HTAP](/tidb-cloud/tidb-cloud-htap-quickstart.md) + - [试用 TiDB Cloud CLI](/tidb-cloud/get-started-with-cli.md) + - [执行 PoC](/tidb-cloud/tidb-cloud-poc.md) +- 关键概念 + - [概览](/tidb-cloud/key-concepts.md) + - [架构](/tidb-cloud/architecture-concepts.md) + - [数据库 Schema](/tidb-cloud/database-schema-concepts.md) + - [事务](/tidb-cloud/transaction-concepts.md) + - [SQL](/tidb-cloud/sql-concepts.md) + - [AI 功能](/tidb-cloud/ai-feature-concepts.md) + - [数据服务](/tidb-cloud/data-service-concepts.md) ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [可扩展性](/tidb-cloud/scalability-concepts.md) + - 高可用性 + - [TiDB Cloud Serverless 中的高可用性](/tidb-cloud/serverless-high-availability.md) + - [TiDB Cloud Dedicated 中的高可用性](/tidb-cloud/high-availability-with-multi-az.md) + - [监控](/tidb-cloud/monitoring-concepts.md) + - [数据流](/tidb-cloud/data-streaming-concepts.md) + - [备份 & 恢复](/tidb-cloud/backup-and-restore-concepts.md) + - [安全性](/tidb-cloud/security-concepts.md) + +## 开发 + +- 开发快速入门 + - [开发者指南概览](/develop/dev-guide-overview.md) + - [构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md) + - [TiDB 中的 CRUD SQL](/develop/dev-guide-tidb-crud-sql.md) +- 连接到 TiDB Cloud + - GUI 数据库工具 + - [JetBrains DataGrip](/develop/dev-guide-gui-datagrip.md) + - [DBeaver](/develop/dev-guide-gui-dbeaver.md) + - [VS Code](/develop/dev-guide-gui-vscode-sqltools.md) + - [MySQL Workbench](/develop/dev-guide-gui-mysql-workbench.md) + - [Navicat](/develop/dev-guide-gui-navicat.md) + - [选择驱动或 ORM](/develop/dev-guide-choose-driver-or-orm.md) + - BI + - [Looker Studio](/tidb-cloud/dev-guide-bi-looker-studio.md) + - Java + - [JDBC](/develop/dev-guide-sample-application-java-jdbc.md) + - [MyBatis](/develop/dev-guide-sample-application-java-mybatis.md) + - [Hibernate](/develop/dev-guide-sample-application-java-hibernate.md) + - [Spring Boot](/develop/dev-guide-sample-application-java-spring-boot.md) + - [连接池和连接参数](/develop/dev-guide-connection-parameters.md) + - Go + - [Go-MySQL-Driver](/develop/dev-guide-sample-application-golang-sql-driver.md) + - [GORM](/develop/dev-guide-sample-application-golang-gorm.md) + - Python + - [mysqlclient](/develop/dev-guide-sample-application-python-mysqlclient.md) + - [MySQL Connector/Python](/develop/dev-guide-sample-application-python-mysql-connector.md) + - [PyMySQL](/develop/dev-guide-sample-application-python-pymysql.md) + - [SQLAlchemy](/develop/dev-guide-sample-application-python-sqlalchemy.md) + - [peewee](/develop/dev-guide-sample-application-python-peewee.md) + - [Django](/develop/dev-guide-sample-application-python-django.md) + - Node.js + - [node-mysql2](/develop/dev-guide-sample-application-nodejs-mysql2.md) + - [mysql.js](/develop/dev-guide-sample-application-nodejs-mysqljs.md) + - [Prisma](/develop/dev-guide-sample-application-nodejs-prisma.md) + - [Sequelize](/develop/dev-guide-sample-application-nodejs-sequelize.md) + - [TypeORM](/develop/dev-guide-sample-application-nodejs-typeorm.md) + - [Next.js](/develop/dev-guide-sample-application-nextjs.md) + - [AWS Lambda](/develop/dev-guide-sample-application-aws-lambda.md) + - Ruby + - [mysql2](/develop/dev-guide-sample-application-ruby-mysql2.md) + - [Rails](/develop/dev-guide-sample-application-ruby-rails.md) + - [WordPress](/tidb-cloud/dev-guide-wordpress.md) + - Serverless Driver ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [TiDB Cloud Serverless Driver](/tidb-cloud/serverless-driver.md) + - [Node.js 示例](/tidb-cloud/serverless-driver-node-example.md) + - [Prisma 示例](/tidb-cloud/serverless-driver-prisma-example.md) + - [Kysely 示例](/tidb-cloud/serverless-driver-kysely-example.md) + - [Drizzle 示例](/tidb-cloud/serverless-driver-drizzle-example.md) +- 开发参考 + - 设计数据库 Schema + - [概览](/develop/dev-guide-schema-design-overview.md) + - [创建数据库](/develop/dev-guide-create-database.md) + - [创建表](/develop/dev-guide-create-table.md) + - [创建二级索引](/develop/dev-guide-create-secondary-indexes.md) + - 写入数据 + - [插入数据](/develop/dev-guide-insert-data.md) + - [更新数据](/develop/dev-guide-update-data.md) + - [删除数据](/develop/dev-guide-delete-data.md) + - [使用 TTL(生存时间)定期删除过期数据](/time-to-live.md) + - [预处理语句](/develop/dev-guide-prepared-statement.md) + - 读取数据 + - [从单表查询数据](/develop/dev-guide-get-data-from-single-table.md) + - [多表连接查询](/develop/dev-guide-join-tables.md) + - [子查询](/develop/dev-guide-use-subqueries.md) + - [分页结果](/develop/dev-guide-paginate-results.md) + - [视图](/develop/dev-guide-use-views.md) + - [临时表](/develop/dev-guide-use-temporary-tables.md) + - [公共表表达式](/develop/dev-guide-use-common-table-expression.md) + - 读取副本数据 + - [Follower Read](/develop/dev-guide-use-follower-read.md) + - [Stale Read](/develop/dev-guide-use-stale-read.md) + - [HTAP 查询](/develop/dev-guide-hybrid-oltp-and-olap-queries.md) + - 事务 + - [概览](/develop/dev-guide-transaction-overview.md) + - [乐观和悲观事务](/develop/dev-guide-optimistic-and-pessimistic-transaction.md) + - [事务约束](/develop/dev-guide-transaction-restraints.md) + - [处理事务错误](/develop/dev-guide-transaction-troubleshoot.md) + - 优化 + - [概览](/develop/dev-guide-optimize-sql-overview.md) + - [SQL 性能调优](/develop/dev-guide-optimize-sql.md) + - [性能调优的最佳实践](/develop/dev-guide-optimize-sql-best-practices.md) + - [索引的最佳实践](/develop/dev-guide-index-best-practice.md) + - 其他优化方法 + - [避免隐式类型转换](/develop/dev-guide-implicit-type-conversion.md) + - [唯一序列号生成](/develop/dev-guide-unique-serial-number-generation.md) + - 故障排除 + - [SQL 或事务问题](/develop/dev-guide-troubleshoot-overview.md) + - [不稳定的结果集](/develop/dev-guide-unstable-result-set.md) + - [超时](/develop/dev-guide-timeouts-in-tidb.md) + - 开发指南 + - [对象命名约定](/develop/dev-guide-object-naming-guidelines.md) + - [SQL 开发规范](/develop/dev-guide-sql-development-specification.md) + - [Bookshop 示例应用程序](/develop/dev-guide-bookshop-schema-design.md) + - 第三方支持 + - [TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md) + - [第三方工具的已知不兼容问题](/develop/dev-guide-third-party-tools-compatibility.md) + +## 指南 + +- 管理集群 + - 规划您的集群 + - [选择您的集群层级](/tidb-cloud/select-cluster-tier.md) + - [确定 TiDB 的大小](/tidb-cloud/size-your-cluster.md) + - [TiDB Cloud 性能参考](/tidb-cloud/tidb-cloud-performance-reference.md) + - 管理 TiDB Cloud Serverless 集群 + - [创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md) + - 连接到您的 TiDB Cloud Serverless 集群 + - [连接概览](/tidb-cloud/connect-to-tidb-cluster-serverless.md) + - [通过公共端点连接](/tidb-cloud/connect-via-standard-connection-serverless.md) + - [通过私有端点连接](/tidb-cloud/set-up-private-endpoint-connections-serverless.md) + - 分支 ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [概览](/tidb-cloud/branch-overview.md) + - [管理分支](/tidb-cloud/branch-manage.md) + - [GitHub 集成](/tidb-cloud/branch-github-integration.md) + - [管理消费限额](/tidb-cloud/manage-serverless-spend-limit.md) + - [备份和恢复 TiDB Cloud Serverless 数据](/tidb-cloud/backup-and-restore-serverless.md) + - [从 TiDB Cloud Serverless 导出数据](/tidb-cloud/serverless-export.md) + - 管理 TiDB Cloud Dedicated 集群 + - [创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md) + - 连接到您的 TiDB Cloud Dedicated 集群 + - [连接方法概览](/tidb-cloud/connect-to-tidb-cluster.md) + - [通过公共连接连接](/tidb-cloud/connect-via-standard-connection.md) + - [通过 AWS 的私有端点连接](/tidb-cloud/set-up-private-endpoint-connections.md) + - [通过 Azure 的私有端点连接](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md) + - [通过 Google Cloud 的私有端点连接](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md) + - [通过 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md) + - [通过 SQL Shell 连接](/tidb-cloud/connect-via-sql-shell.md) + - [伸缩 TiDB Cloud Dedicated 集群](/tidb-cloud/scale-tidb-cluster.md) + - [备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md) + - [暂停或恢复 TiDB Cloud Dedicated 集群](/tidb-cloud/pause-or-resume-tidb-cluster.md) + - [配置维护窗口](/tidb-cloud/configure-maintenance-window.md) + - 使用带有 TiFlash 的 HTAP 集群 + - [TiFlash 概览](/tiflash/tiflash-overview.md) + - [创建 TiFlash 副本](/tiflash/create-tiflash-replicas.md) + - [从 TiFlash 读取数据](/tiflash/use-tidb-to-read-tiflash.md) + - [使用 MPP 模式](/tiflash/use-tiflash-mpp-mode.md) + - [使用 FastScan](/tiflash/use-fastscan.md) + - [支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md) + - [TiFlash 查询结果物化](/tiflash/tiflash-results-materialization.md) + - [TiFlash 延迟物化](/tiflash/tiflash-late-materialization.md) + - [兼容性](/tiflash/tiflash-compatibility.md) + - [Pipeline 执行模型](/tiflash/tiflash-pipeline-model.md) + - 监控和告警 + - [概览](/tidb-cloud/monitor-tidb-cluster.md) + - [内置指标](/tidb-cloud/built-in-monitoring.md) + - [内置告警](/tidb-cloud/monitor-built-in-alerting.md) + - 订阅告警通知 + - [通过电子邮件订阅](/tidb-cloud/monitor-alert-email.md) + - [通过 Slack 订阅](/tidb-cloud/monitor-alert-slack.md) + - [通过 Zoom 订阅](/tidb-cloud/monitor-alert-zoom.md) + - [集群事件](/tidb-cloud/tidb-cloud-events.md) + - [第三方指标集成](/tidb-cloud/third-party-monitoring-integrations.md) ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [TiDB Cloud Clinic](/tidb-cloud/tidb-cloud-clinic.md) + - 调优性能 + - [概览](/tidb-cloud/tidb-cloud-tune-performance-overview.md) + - 分析性能 + - [使用诊断选项卡](/tidb-cloud/tune-performance.md) + - [使用 Index Insight](/tidb-cloud/index-insight.md) ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [使用 Statement Summary 表](/statement-summary-tables.md) + - SQL 调优 + - [概览](/tidb-cloud/tidb-cloud-sql-tuning-overview.md) + - 理解查询执行计划 + - [概览](/explain-overview.md) + - [`EXPLAIN` 演练](/explain-walkthrough.md) + - [索引](/explain-indexes.md) + - [连接](/explain-joins.md) + - [MPP 查询](/explain-mpp.md) + - [子查询](/explain-subqueries.md) + - [聚合](/explain-aggregation.md) + - [视图](/explain-views.md) + - [分区](/explain-partitions.md) + - [索引合并](/explain-index-merge.md) + - 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 重排序](/join-reorder.md) + - [从窗口函数派生 TopN 或 Limit](/derive-topn-from-window.md) + - 物理优化 + - [概览](/sql-physical-optimization.md) + - [索引选择](/choose-index.md) + - [统计信息](/statistics.md) + - [扩展统计信息](/extended-statistics.md) + - [错误的索引解决方案](/wrong-index-solution.md) + - [Distinct 优化](/agg-distinct-optimization.md) + - [成本模型](/cost-model.md) + - [运行时过滤器](/runtime-filter.md) + - [预处理执行计划缓存](/sql-prepared-plan-cache.md) + - [非预处理执行计划缓存](/sql-non-prepared-plan-cache.md) + - 控制执行计划 + - [概览](/control-execution-plan.md) + - [优化器提示](/optimizer-hints.md) + - [SQL 计划管理](/sql-plan-management.md) + - [优化规则和表达式下推的黑名单](/blocklist-control-plan.md) + - [优化器修复控制](/optimizer-fix-controls.md) + - [TiKV Follower Read](/follower-read.md) + - [Coprocessor 缓存](/coprocessor-cache.md) + - 垃圾回收 (GC) + - [概览](/garbage-collection-overview.md) + - [配置](/garbage-collection-configuration.md) + - [调优 TiFlash 性能](/tiflash/tune-tiflash-performance.md) + - 优化资源分配 + - [资源分配概览](/tidb-cloud/optimize-resource-allocation.md) + - [资源控制](/tidb-resource-control.md) + - TiDB 节点组 + - [TiDB 节点组概览](/tidb-cloud/tidb-node-group-overview.md) + - [管理 TiDB 节点组](/tidb-cloud/tidb-node-group-management.md) + - [升级 TiDB 集群](/tidb-cloud/upgrade-tidb-cluster.md) + - [删除 TiDB 集群](/tidb-cloud/delete-tidb-cluster.md) +- 迁移或导入数据 + - [概览](/tidb-cloud/tidb-cloud-migration-overview.md) + - 将数据迁移到 TiDB Cloud + - [使用 Data Migration 迁移现有和增量数据](/tidb-cloud/migrate-from-mysql-using-data-migration.md) + - [使用 Data Migration 迁移增量数据](/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md) + - [迁移和合并大型数据集的 MySQL 分片](/tidb-cloud/migrate-sql-shards.md) + - [从 TiDB 自管理迁移到 TiDB Cloud](/tidb-cloud/migrate-from-op-tidb.md) + - [使用 AWS DMS 从 MySQL 兼容数据库迁移](/tidb-cloud/migrate-from-mysql-using-aws-dms.md) +- [使用 AWS DMS 从 Amazon RDS for Oracle 迁移](/tidb-cloud/migrate-from-oracle-using-aws-dms.md) + - 将数据导入 TiDB Cloud Dedicated + - [导入示例数据](/tidb-cloud/import-sample-data.md) + - [从云存储导入 CSV 文件](/tidb-cloud/import-csv-files.md) + - [从云存储导入 Parquet 文件](/tidb-cloud/import-parquet-files.md) + - [使用 MySQL CLI 导入](/tidb-cloud/import-with-mysql-cli.md) + - 将数据导入 TiDB Cloud Serverless + - [导入示例数据](/tidb-cloud/import-sample-data-serverless.md) + - [导入本地文件](/tidb-cloud/tidb-cloud-import-local-files.md) + - [从云存储导入 CSV 文件](/tidb-cloud/import-csv-files-serverless.md) + - [从云存储导入 Parquet 文件](/tidb-cloud/import-parquet-files-serverless.md) + - [使用 MySQL CLI 导入](/tidb-cloud/import-with-mysql-cli-serverless.md) + - 参考 + - [为 TiDB Cloud Dedicated 配置外部存储访问](/tidb-cloud/dedicated-external-storage.md) + - [为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md) + - [数据导入的命名约定](/tidb-cloud/naming-conventions-for-data-import.md) + - [导入数据的 CSV 配置](/tidb-cloud/csv-config-for-import-data.md) + - [排查从 Amazon S3 导入数据期间的访问被拒绝错误](/tidb-cloud/troubleshoot-import-access-denied-error.md) + - [数据迁移的预检查错误、迁移错误和警报](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md) + - [将 AWS DMS 连接到 TiDB Cloud 集群](/tidb-cloud/tidb-cloud-connect-aws-dms.md) +- 探索数据 + - [SQL 编辑器中的 Chat2Query](/tidb-cloud/explore-data-with-chat2query.md) ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [SQL 代理账户](/tidb-cloud/sql-proxy-account.md) +- 向量搜索 ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [概述](/tidb-cloud/vector-search-overview.md) + - 快速上手 + - [使用 SQL 快速上手](/tidb-cloud/vector-search-get-started-using-sql.md) + - [使用 Python 快速上手](/tidb-cloud/vector-search-get-started-using-python.md) + - 集成 + - [概述](/tidb-cloud/vector-search-integration-overview.md) + - AI 框架 + - [LlamaIndex](/tidb-cloud/vector-search-integrate-with-llamaindex.md) + - [Langchain](/tidb-cloud/vector-search-integrate-with-langchain.md) + - AI 服务 + - [Amazon Bedrock](/tidb-cloud/vector-search-integrate-with-amazon-bedrock.md) + - 嵌入模型/服务 + - [Jina AI](/tidb-cloud/vector-search-integrate-with-jinaai-embedding.md) + - ORM 库 + - [SQLAlchemy](/tidb-cloud/vector-search-integrate-with-sqlalchemy.md) + - [peewee](/tidb-cloud/vector-search-integrate-with-peewee.md) + - [Django ORM](/tidb-cloud/vector-search-integrate-with-django-orm.md) + - 文本搜索 + - [使用 SQL 进行全文搜索](/tidb-cloud/vector-search-full-text-search-sql.md) + - [使用 Python 进行全文搜索](/tidb-cloud/vector-search-full-text-search-python.md) + - [混合搜索](/tidb-cloud/vector-search-hybrid-search.md) + - 参考 + - [向量数据类型](/tidb-cloud/vector-search-data-types.md) + - [向量函数和运算符](/tidb-cloud/vector-search-functions-and-operators.md) + - [向量索引](/tidb-cloud/vector-search-index.md) + - [提高性能](/tidb-cloud/vector-search-improve-performance.md) + - [限制](/tidb-cloud/vector-search-limitations.md) + - [更新日志](/tidb-cloud/vector-search-changelogs.md) +- 数据服务 ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [概述](/tidb-cloud/data-service-overview.md) + - [快速上手](/tidb-cloud/data-service-get-started.md) + - Chat2Query API + - [快速上手](/tidb-cloud/use-chat2query-api.md) + - [启动多轮 Chat2Query](/tidb-cloud/use-chat2query-sessions.md) + - [使用知识库](/tidb-cloud/use-chat2query-knowledge.md) + - [管理数据应用](/tidb-cloud/data-service-manage-data-app.md) + - [管理端点](/tidb-cloud/data-service-manage-endpoint.md) + - [API 密钥](/tidb-cloud/data-service-api-key.md) + - [自定义域名](/tidb-cloud/data-service-custom-domain.md) + - [集成](/tidb-cloud/data-service-integrations.md) + - [在 Postman 中运行](/tidb-cloud/data-service-postman-integration.md) + - [使用 GitHub 自动部署](/tidb-cloud/data-service-manage-github-connection.md) + - [将 OpenAPI 规范与 Next.js 结合使用](/tidb-cloud/data-service-oas-with-nextjs.md) + - [数据应用配置文件](/tidb-cloud/data-service-app-config-files.md) + - [响应和状态代码](/tidb-cloud/data-service-response-and-status-code.md) +- 流式传输数据 + - [Changefeed 概述](/tidb-cloud/changefeed-overview.md) + - [到 MySQL Sink](/tidb-cloud/changefeed-sink-to-mysql.md) + - [到 Kafka Sink](/tidb-cloud/changefeed-sink-to-apache-kafka.md) + - [到 Pulsar Sink](/tidb-cloud/changefeed-sink-to-apache-pulsar.md) + - [到 TiDB Cloud Sink](/tidb-cloud/changefeed-sink-to-tidb-cloud.md) + - [到云存储](/tidb-cloud/changefeed-sink-to-cloud-storage.md) + - 参考 + - [在 AWS 中设置自托管 Kafka Private Link 服务](/tidb-cloud/setup-aws-self-hosted-kafka-private-link-service.md) + - [在 Azure 中设置自托管 Kafka Private Link 服务](/tidb-cloud/setup-azure-self-hosted-kafka-private-link-service.md) + - [在 Google Cloud 中设置自托管 Kafka Private Service Connect](/tidb-cloud/setup-self-hosted-kafka-private-service-connect.md) +- 灾难恢复 + - [恢复组概述](/tidb-cloud/recovery-group-overview.md) + - [快速上手](/tidb-cloud/recovery-group-get-started.md) + - [故障转移和重新保护数据库](/tidb-cloud/recovery-group-failover.md) + - [删除恢复组](/tidb-cloud/recovery-group-delete.md) +- 安全 + - 身份访问控制 + - [密码验证](/tidb-cloud/tidb-cloud-password-authentication.md) + - [标准 SSO 身份验证](/tidb-cloud/tidb-cloud-sso-authentication.md) + - [组织 SSO 身份验证](/tidb-cloud/tidb-cloud-org-sso-authentication.md) + - [身份访问管理](/tidb-cloud/manage-user-access.md) + - [OAuth 2.0](/tidb-cloud/oauth2.md) + - 网络访问控制 + - TiDB Cloud Serverless + - [通过私有终端节点连接](/tidb-cloud/set-up-private-endpoint-connections-serverless.md) + - [为公共端点配置防火墙规则](/tidb-cloud/configure-serverless-firewall-rules-for-public-endpoints.md) + - [到 TiDB Cloud Serverless 的 TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md) + - TiDB Cloud Dedicated + - [配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md) + - [通过 AWS 上的私有终端节点连接](/tidb-cloud/set-up-private-endpoint-connections.md) + - [通过 Azure 上的私有终端节点连接](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md) + - [通过 Google Cloud 上的私有终端节点连接](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md) + - [通过 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md) + - [到 TiDB Cloud Dedicated 的 TLS 连接](/tidb-cloud/tidb-cloud-tls-connect-to-dedicated.md) + - 数据访问控制 + - [使用客户管理的加密密钥进行静态加密](/tidb-cloud/tidb-cloud-encrypt-cmek.md) + - 数据库访问控制 + - [配置集群密码设置](/tidb-cloud/configure-security-settings.md) + - 审计管理 + - [数据库审计日志](/tidb-cloud/tidb-cloud-auditing.md) + - [控制台审计日志](/tidb-cloud/tidb-cloud-console-auditing.md) +- 账单 + - [发票](/tidb-cloud/tidb-cloud-billing.md#invoices) + - [账单详情](/tidb-cloud/tidb-cloud-billing.md#billing-details) + - [成本资源管理器](/tidb-cloud/tidb-cloud-billing.md#cost-explorer) + - [账单资料](/tidb-cloud/tidb-cloud-billing.md#billing-profile) +- [抵扣金](/tidb-cloud/tidb-cloud-billing.md#credits) + - [支付方式设置](/tidb-cloud/tidb-cloud-billing.md#payment-method) + - [来自 AWS、Azure 或 Google Cloud Marketplace 的账单](/tidb-cloud/tidb-cloud-billing.md#billing-from-aws-marketplace-azure-marketplace-or-google-cloud-marketplace) + - [Changefeed 计费](/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md) + - [数据迁移计费](/tidb-cloud/tidb-cloud-billing-dm.md) + - [恢复组计费](/tidb-cloud/tidb-cloud-billing-recovery-group.md) + - [管理预算](/tidb-cloud/tidb-cloud-budget.md) +- 集成 + - [Airbyte](/tidb-cloud/integrate-tidbcloud-with-airbyte.md) + - [Amazon AppFlow](/develop/dev-guide-aws-appflow-integration.md) + - [AWS Lambda](/tidb-cloud/integrate-tidbcloud-with-aws-lambda.md) + - [Cloudflare](/tidb-cloud/integrate-tidbcloud-with-cloudflare.md) + - [Datadog](/tidb-cloud/monitor-datadog-integration.md) + - [dbt](/tidb-cloud/integrate-tidbcloud-with-dbt.md) + - [Gitpod](/develop/dev-guide-playground-gitpod.md) + - [n8n](/tidb-cloud/integrate-tidbcloud-with-n8n.md) + - [Netlify](/tidb-cloud/integrate-tidbcloud-with-netlify.md) + - [New Relic](/tidb-cloud/monitor-new-relic-integration.md) + - [Prometheus 和 Grafana](/tidb-cloud/monitor-prometheus-and-grafana-integration.md) + - [ProxySQL](/develop/dev-guide-proxysql-integration.md) + - Terraform + - [Terraform 集成概览](/tidb-cloud/terraform-tidbcloud-provider-overview.md) + - [获取 TiDB Cloud Terraform Provider](/tidb-cloud/terraform-get-tidbcloud-provider.md) + - [使用集群资源](/tidb-cloud/terraform-use-cluster-resource.md) + - [使用备份资源](/tidb-cloud/terraform-use-backup-resource.md) + - [使用恢复资源](/tidb-cloud/terraform-use-restore-resource.md) + - [使用导入资源](/tidb-cloud/terraform-use-import-resource.md) + - [迁移集群资源](/tidb-cloud/terraform-migrate-cluster-resource.md) + - [Vercel](/tidb-cloud/integrate-tidbcloud-with-vercel.md) + - [Zapier](/tidb-cloud/integrate-tidbcloud-with-zapier.md) + +## 参考 + +- SQL 参考 + - [使用 TiDB 探索 SQL](/basic-sql-operations.md) + - SQL 语言结构和语法 + - 属性 + - [AUTO_INCREMENT](/auto-increment.md) + - [AUTO_RANDOM](/auto-random.md) + - [SHARD_ROW_ID_BITS](/shard-row-id-bits.md) + - [字面值](/literal-values.md) + - [模式对象名称](/schema-object-names.md) + - [关键字和保留字](/keywords.md) + - [用户自定义变量](/user-defined-variables.md) + - [表达式语法](/expression-syntax.md) + - [注释语法](/comment-syntax.md) + - SQL 语句 + - [概述](/sql-statements/sql-statement-overview.md) + - [`ADMIN`](/sql-statements/sql-statement-admin.md) + - [`ADMIN CANCEL DDL`](/sql-statements/sql-statement-admin-cancel-ddl.md) + - [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) + - [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) + - [`ADMIN CLEANUP INDEX`](/sql-statements/sql-statement-admin-cleanup.md) + - [`ADMIN PAUSE DDL`](/sql-statements/sql-statement-admin-pause-ddl.md) + - [`ADMIN RECOVER INDEX`](/sql-statements/sql-statement-admin-recover.md) + - [`ADMIN RESUME DDL`](/sql-statements/sql-statement-admin-resume-ddl.md) + - [`ADMIN SHOW DDL [JOBS|JOB QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) + - [`ALTER DATABASE`](/sql-statements/sql-statement-alter-database.md) + - [`ALTER INSTANCE`](/sql-statements/sql-statement-alter-instance.md) + - [`ALTER PLACEMENT POLICY`](/sql-statements/sql-statement-alter-placement-policy.md) + - [`ALTER RANGE`](/sql-statements/sql-statement-alter-range.md) + - [`ALTER RESOURCE GROUP`](/sql-statements/sql-statement-alter-resource-group.md) + - [`ALTER SEQUENCE`](/sql-statements/sql-statement-alter-sequence.md) + - `ALTER TABLE` + - [概述](/sql-statements/sql-statement-alter-table.md) + - [`ADD COLUMN`](/sql-statements/sql-statement-add-column.md) + - [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) + - [`ALTER INDEX`](/sql-statements/sql-statement-alter-index.md) + - [`CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) + - [`COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) + - [`DROP COLUMN`](/sql-statements/sql-statement-drop-column.md) + - [`DROP INDEX`](/sql-statements/sql-statement-drop-index.md) + - [`MODIFY COLUMN`](/sql-statements/sql-statement-modify-column.md) + - [`RENAME INDEX`](/sql-statements/sql-statement-rename-index.md) + - [`ALTER USER`](/sql-statements/sql-statement-alter-user.md) + - [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) + - [`BACKUP`](/sql-statements/sql-statement-backup.md) + - [`BATCH`](/sql-statements/sql-statement-batch.md) + - [`BEGIN`](/sql-statements/sql-statement-begin.md) + - [`CANCEL IMPORT JOB`](/sql-statements/sql-statement-cancel-import-job.md) + - [`COMMIT`](/sql-statements/sql-statement-commit.md) + - [`CREATE [GLOBAL|SESSION] 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 PLACEMENT POLICY`](/sql-statements/sql-statement-create-placement-policy.md) + - [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) + - [`CREATE ROLE`](/sql-statements/sql-statement-create-role.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 [GLOBAL|SESSION] BINDING`](/sql-statements/sql-statement-drop-binding.md) + - [`DROP DATABASE`](/sql-statements/sql-statement-drop-database.md) + - [`DROP PLACEMENT POLICY`](/sql-statements/sql-statement-drop-placement-policy.md) + - [`DROP RESOURCE GROUP`](/sql-statements/sql-statement-drop-resource-group.md) + - [`DROP ROLE`](/sql-statements/sql-statement-drop-role.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 CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) + - [`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.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) + - [`GRANT `](/sql-statements/sql-statement-grant-role.md) + - [`IMPORT INTO`](/sql-statements/sql-statement-import-into.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) + - [`LOCK STATS`](/sql-statements/sql-statement-lock-stats.md) + - [`LOCK TABLES` 和 `UNLOCK TABLES`](/sql-statements/sql-statement-lock-tables-and-unlock-tables.md) + - [`PREPARE`](/sql-statements/sql-statement-prepare.md) + - [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md) + - [`RECOVER TABLE`](/sql-statements/sql-statement-recover-table.md) + - [`RENAME TABLE`](/sql-statements/sql-statement-rename-table.md) + - [`RENAME USER`](/sql-statements/sql-statement-rename-user.md) + - [`REPLACE`](/sql-statements/sql-statement-replace.md) + - [`RESTORE`](/sql-statements/sql-statement-restore.md) + - [`REVOKE `](/sql-statements/sql-statement-revoke-privileges.md) + - [`REVOKE `](/sql-statements/sql-statement-revoke-role.md) + - [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) + - [`SAVEPOINT`](/sql-statements/sql-statement-savepoint.md) + - [`SELECT`](/sql-statements/sql-statement-select.md) + - [`SET DEFAULT ROLE`](/sql-statements/sql-statement-set-default-role.md) + - [`SET [NAMES|CHARACTER SET]`](/sql-statements/sql-statement-set-names.md) + - [`SET PASSWORD`](/sql-statements/sql-statement-set-password.md) + - [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.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 [BACKUPS|RESTORES]`](/sql-statements/sql-statement-show-backups.md) + - [`SHOW [GLOBAL|SESSION] 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 COLUMN_STATS_USAGE`](/sql-statements/sql-statement-show-column-stats-usage.md) +- [`SHOW COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) +- [`SHOW CREATE DATABASE`](/sql-statements/sql-statement-show-create-database.md) +- [`SHOW CREATE PLACEMENT POLICY`](/sql-statements/sql-statement-show-create-placement-policy.md) +- [`SHOW CREATE RESOURCE GROUP`](/sql-statements/sql-statement-show-create-resource-group.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 ENGINES`](/sql-statements/sql-statement-show-engines.md) +- [`SHOW ERRORS`](/sql-statements/sql-statement-show-errors.md) +- [`SHOW FIELDS FROM`](/sql-statements/sql-statement-show-fields-from.md) +- [`SHOW GRANTS`](/sql-statements/sql-statement-show-grants.md) +- [`SHOW IMPORT JOB`](/sql-statements/sql-statement-show-import-job.md) +- [`SHOW INDEXES [FROM|IN]`](/sql-statements/sql-statement-show-indexes.md) +- [`SHOW MASTER STATUS`](/sql-statements/sql-statement-show-master-status.md) +- [`SHOW PLACEMENT`](/sql-statements/sql-statement-show-placement.md) +- [`SHOW PLACEMENT FOR`](/sql-statements/sql-statement-show-placement-for.md) +- [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md) +- [`SHOW PLUGINS`](/sql-statements/sql-statement-show-plugins.md) +- [`SHOW PRIVILEGES`](/sql-statements/sql-statement-show-privileges.md) +- [`SHOW PROCESSLIST`](/sql-statements/sql-statement-show-processlist.md) +- [`SHOW PROFILES`](/sql-statements/sql-statement-show-profiles.md) +- [`SHOW SCHEMAS`](/sql-statements/sql-statement-show-schemas.md) +- [`SHOW STATS_BUCKETS`](/sql-statements/sql-statement-show-stats-buckets.md) +- [`SHOW STATS_HEALTHY`](/sql-statements/sql-statement-show-stats-healthy.md) +- [`SHOW STATS_HISTOGRAMS`](/sql-statements/sql-statement-show-stats-histograms.md) +- [`SHOW STATS_LOCKED`](/sql-statements/sql-statement-show-stats-locked.md) +- [`SHOW STATS_META`](/sql-statements/sql-statement-show-stats-meta.md) +- [`SHOW STATS_TOPN`](/sql-statements/sql-statement-show-stats-topn.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 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) +- [`SPLIT REGION`](/sql-statements/sql-statement-split-region.md) +- [`START TRANSACTION`](/sql-statements/sql-statement-start-transaction.md) +- [`TABLE`](/sql-statements/sql-statement-table.md) +- [`TRACE`](/sql-statements/sql-statement-trace.md) +- [`TRUNCATE`](/sql-statements/sql-statement-truncate.md) +- [`UNLOCK STATS`](/sql-statements/sql-statement-unlock-stats.md) +- [`UPDATE`](/sql-statements/sql-statement-update.md) +- [`USE`](/sql-statements/sql-statement-use.md) +- [`WITH`](/sql-statements/sql-statement-with.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) + - [转换函数和运算符](/functions-and-operators/cast-functions-and-operators.md) + - [加密和压缩函数](/functions-and-operators/encryption-and-compression-functions.md) + - [锁定函数](/functions-and-operators/locking-functions.md) + - [信息函数](/functions-and-operators/information-functions.md) + - JSON 函数 + - [概述](/functions-and-operators/json-functions.md) + - [创建 JSON 的函数](/functions-and-operators/json-functions/json-functions-create.md) + - [搜索 JSON 的函数](/functions-and-operators/json-functions/json-functions-search.md) + - [修改 JSON 的函数](/functions-and-operators/json-functions/json-functions-modify.md) + - [返回 JSON 的函数](/functions-and-operators/json-functions/json-functions-return.md) + - [JSON 实用函数](/functions-and-operators/json-functions/json-functions-utility.md) + - [聚合 JSON 的函数](/functions-and-operators/json-functions/json-functions-aggregate.md) + - [聚合 (GROUP BY) 函数](/functions-and-operators/aggregate-group-by-functions.md) + - [GROUP BY 修饰符](/functions-and-operators/group-by-modifier.md) + - [窗口函数](/functions-and-operators/window-functions.md) + - [序列函数](/functions-and-operators/sequence-functions.md) + - [实用函数](/functions-and-operators/utility-functions.md) + - [杂项函数](/functions-and-operators/miscellaneous-functions.md) + - [TiDB 特有函数](/functions-and-operators/tidb-functions.md) + - [精确数学](/functions-and-operators/precision-math.md) + - [集合运算](/functions-and-operators/set-operators.md) + - [下推表达式列表](/functions-and-operators/expressions-pushed-down.md) + - [聚集索引](/clustered-indexes.md) + - [约束](/constraints.md) + - [生成列](/generated-columns.md) + - [SQL 模式](/sql-mode.md) + - [表属性](/table-attributes.md) + - 事务 + - [概述](/transaction-overview.md) + - [隔离级别](/transaction-isolation-levels.md) + - [乐观事务](/optimistic-transaction.md) + - [悲观事务](/pessimistic-transaction.md) + - [非事务性 DML 语句](/non-transactional-dml.md) + - [视图](/views.md) + - [分区](/partitioned-table.md) + - [临时表](/temporary-tables.md) + - [缓存表](/cached-tables.md) + - [FOREIGN KEY 约束](/foreign-key.md) + - 字符集和排序规则 + - [概述](/character-set-and-collation.md) + - [GBK](/character-set-gbk.md) + - 读取历史数据 + - 使用过时读取(推荐) + - [过时读取的使用场景](/stale-read.md) + - [使用 `As OF TIMESTAMP` 执行过时读取](/as-of-timestamp.md) + - [使用 `tidb_read_staleness` 执行过时读取](/tidb-read-staleness.md) + - [使用 `tidb_external_ts` 执行过时读取](/tidb-external-ts.md) + - [使用 `tidb_snapshot` 系统变量](/read-historical-data.md) + - [SQL 中的放置规则](/placement-rules-in-sql.md) + - 系统表 + - `mysql` 数据库 + - [概述](/mysql-schema/mysql-schema.md) + - [`user`](/mysql-schema/mysql-schema-user.md) + - INFORMATION_SCHEMA + - [概述](/information-schema/information-schema.md) + - [`ANALYZE_STATUS`](/information-schema/information-schema-analyze-status.md) +- [`CHECK_CONSTRAINTS`](/information-schema/information-schema-check-constraints.md) + - [`CLIENT_ERRORS_SUMMARY_BY_HOST`](/information-schema/client-errors-summary-by-host.md) + - [`CLIENT_ERRORS_SUMMARY_BY_USER`](/information-schema/client-errors-summary-by-user.md) + - [`CLIENT_ERRORS_SUMMARY_GLOBAL`](/information-schema/client-errors-summary-global.md) + - [`CHARACTER_SETS`](/information-schema/information-schema-character-sets.md) + - [`CLUSTER_INFO`](/information-schema/information-schema-cluster-info.md) + - [`COLLATIONS`](/information-schema/information-schema-collations.md) + - [`COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) + - [`COLUMNS`](/information-schema/information-schema-columns.md) + - [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md) + - [`DDL_JOBS`](/information-schema/information-schema-ddl-jobs.md) + - [`DEADLOCKS`](/information-schema/information-schema-deadlocks.md) + - [`ENGINES`](/information-schema/information-schema-engines.md) + - [`KEYWORDS`](/information-schema/information-schema-keywords.md) + - [`KEY_COLUMN_USAGE`](/information-schema/information-schema-key-column-usage.md) + - [`MEMORY_USAGE`](/information-schema/information-schema-memory-usage.md) + - [`MEMORY_USAGE_OPS_HISTORY`](/information-schema/information-schema-memory-usage-ops-history.md) + - [`PARTITIONS`](/information-schema/information-schema-partitions.md) + - [`PLACEMENT_POLICIES`](/information-schema/information-schema-placement-policies.md) + - [`PROCESSLIST`](/information-schema/information-schema-processlist.md) + - [`REFERENTIAL_CONSTRAINTS`](/information-schema/information-schema-referential-constraints.md) + - [`RESOURCE_GROUPS`](/information-schema/information-schema-resource-groups.md) + - [`RUNAWAY_WATCHES`](/information-schema/information-schema-runaway-watches.md) + - [`SCHEMATA`](/information-schema/information-schema-schemata.md) + - [`SEQUENCES`](/information-schema/information-schema-sequences.md) + - [`SESSION_VARIABLES`](/information-schema/information-schema-session-variables.md) + - [`SLOW_QUERY`](/information-schema/information-schema-slow-query.md) + - [`STATISTICS`](/information-schema/information-schema-statistics.md) + - [`TABLES`](/information-schema/information-schema-tables.md) + - [`TABLE_CONSTRAINTS`](/information-schema/information-schema-table-constraints.md) + - [`TABLE_STORAGE_STATS`](/information-schema/information-schema-table-storage-stats.md) + - [`TIDB_CHECK_CONSTRAINTS`](/information-schema/information-schema-tidb-check-constraints.md) + - [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md) + - [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) + - [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) + - [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) + - [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) + - [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) + - [`TIFLASH_SEGMENTS`](/information-schema/information-schema-tiflash-segments.md) + - [`TIFLASH_TABLES`](/information-schema/information-schema-tiflash-tables.md) + - [`TIKV_REGION_PEERS`](/information-schema/information-schema-tikv-region-peers.md) + - [`TIKV_REGION_STATUS`](/information-schema/information-schema-tikv-region-status.md) + - [`TIKV_STORE_STATUS`](/information-schema/information-schema-tikv-store-status.md) + - [`USER_ATTRIBUTES`](/information-schema/information-schema-user-attributes.md) + - [`USER_PRIVILEGES`](/information-schema/information-schema-user-privileges.md) + - [`VARIABLES_INFO`](/information-schema/information-schema-variables-info.md) + - [`VIEWS`](/information-schema/information-schema-views.md) + - PERFORMANCE_SCHEMA + - [概述](/performance-schema/performance-schema.md) + - [`SESSION_CONNECT_ATTRS`](/performance-schema/performance-schema-session-connect-attrs.md) + - SYS + - [概述](/sys-schema/sys-schema.md) + - [`schema_unused_indexes`](/sys-schema/sys-schema-unused-indexes.md) + - [元数据锁](/metadata-lock.md) + - [使用 UUID](/best-practices/uuid.md) + - [TiDB 加速建表](/accelerated-table-creation.md) +- API 参考 ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [概述](/tidb-cloud/api-overview.md) + - v1beta1 + - [计费](https://docs.pingcap.com/tidbcloud/api/v1beta1/billing) + - [数据服务](https://docs.pingcap.com/tidbcloud/api/v1beta1/dataservice) + - [IAM](https://docs.pingcap.com/tidbcloud/api/v1beta1/iam) + - [MSP (已弃用)](https://docs.pingcap.com/tidbcloud/api/v1beta1/msp) + - [v1beta](https://docs.pingcap.com/tidbcloud/api/v1beta) +- CLI 参考 ![BETA](/media/tidb-cloud/blank_transparent_placeholder.png) + - [概述](/tidb-cloud/cli-reference.md) + - auth + - [login](/tidb-cloud/ticloud-auth-login.md) + - [logout](/tidb-cloud/ticloud-auth-logout.md) + - [whoami](/tidb-cloud/ticloud-auth-whoami.md) + - serverless + - [create](/tidb-cloud/ticloud-cluster-create.md) + - [delete](/tidb-cloud/ticloud-cluster-delete.md) + - [describe](/tidb-cloud/ticloud-cluster-describe.md) + - [list](/tidb-cloud/ticloud-cluster-list.md) + - [update](/tidb-cloud/ticloud-serverless-update.md) + - [spending-limit](/tidb-cloud/ticloud-serverless-spending-limit.md) + - [region](/tidb-cloud/ticloud-serverless-region.md) + - [shell](/tidb-cloud/ticloud-serverless-shell.md) + - branch + - [create](/tidb-cloud/ticloud-branch-create.md) + - [delete](/tidb-cloud/ticloud-branch-delete.md) + - [describe](/tidb-cloud/ticloud-branch-describe.md) + - [list](/tidb-cloud/ticloud-branch-list.md) + - [shell](/tidb-cloud/ticloud-branch-shell.md) + - import + - [cancel](/tidb-cloud/ticloud-import-cancel.md) + - [describe](/tidb-cloud/ticloud-import-describe.md) + - [list](/tidb-cloud/ticloud-import-list.md) + - [start](/tidb-cloud/ticloud-import-start.md) + - export + - [create](/tidb-cloud/ticloud-serverless-export-create.md) + - [describe](/tidb-cloud/ticloud-serverless-export-describe.md) + - [list](/tidb-cloud/ticloud-serverless-export-list.md) + - [cancel](/tidb-cloud/ticloud-serverless-export-cancel.md) + - [download](/tidb-cloud/ticloud-serverless-export-download.md) + - sql-user + - [create](/tidb-cloud/ticloud-serverless-sql-user-create.md) + - [delete](/tidb-cloud/ticloud-serverless-sql-user-delete.md) + - [list](/tidb-cloud/ticloud-serverless-sql-user-list.md) + - [update](/tidb-cloud/ticloud-serverless-sql-user-update.md) + - authorized-network + - [create](/tidb-cloud/ticloud-serverless-authorized-network-create.md) + - [delete](/tidb-cloud/ticloud-serverless-authorized-network-delete.md) + - [list](/tidb-cloud/ticloud-serverless-authorized-network-list.md) + - [update](/tidb-cloud/ticloud-serverless-authorized-network-update.md) + - [ai](/tidb-cloud/ticloud-ai.md) + - [completion](/tidb-cloud/ticloud-completion.md) + - config + - [create](/tidb-cloud/ticloud-config-create.md) + - [delete](/tidb-cloud/ticloud-config-delete.md) + - [describe](/tidb-cloud/ticloud-config-describe.md) + - [edit](/tidb-cloud/ticloud-config-edit.md) + - [list](/tidb-cloud/ticloud-config-list.md) + - [set](/tidb-cloud/ticloud-config-set.md) + - [use](/tidb-cloud/ticloud-config-use.md) + - project + - [list](/tidb-cloud/ticloud-project-list.md) + - [upgrade](/tidb-cloud/ticloud-upgrade.md) + - [help](/tidb-cloud/ticloud-help.md) +- 通用参考 + - TiDB 集群架构 + - [概述](/tidb-architecture.md) + - [存储](/tidb-storage.md) +- [计算](/tidb-computing.md) +- [调度](/tidb-scheduling.md) +- [TSO](/tso.md) + - 存储引擎 + - TiKV + - [TiKV 概览](/tikv-overview.md) + - [RocksDB 概览](/storage-engine/rocksdb-overview.md) + - TiFlash + - [TiFlash 概览](/tiflash/tiflash-overview.md) + - [溢写到磁盘](/tiflash/tiflash-spill-disk.md) + - TiDB Cloud 合作伙伴 Web 控制台 + - [TiDB Cloud 合作伙伴](/tidb-cloud/tidb-cloud-partners.md) + - [MSP 客户](/tidb-cloud/managed-service-provider-customer.md) + - [经销商的客户](/tidb-cloud/cppo-customer.md) + - TiDB 分布式执行框架 (DXF) + - [介绍](/tidb-distributed-execution-framework.md) + - [TiDB 全局排序](/tidb-global-sort.md) + - [TiDB Cloud Dedicated 限制和配额](/tidb-cloud/limitations-and-quotas.md) + - [TiDB Cloud Serverless 限制](/tidb-cloud/serverless-limitations.md) + - [TiDB Cloud 上的 SQL 功能限制](/tidb-cloud/limited-sql-features.md) + - [TiDB 限制](/tidb-limitations.md) + - 基准测试 + - TiDB v8.5 + - [性能亮点](/tidb-cloud/v8.5-performance-highlights.md) + - [TPC-C 性能测试报告](/tidb-cloud/v8.5-performance-benchmarking-with-tpcc.md) + - [Sysbench 性能测试报告](/tidb-cloud/v8.5-performance-benchmarking-with-sysbench.md) + - TiDB v8.1 + - [TPC-C 性能测试报告](/tidb-cloud/v8.1-performance-benchmarking-with-tpcc.md) + - [Sysbench 性能测试报告](/tidb-cloud/v8.1-performance-benchmarking-with-sysbench.md) + - TiDB v7.5 + - [TPC-C 性能测试报告](/tidb-cloud/v7.5-performance-benchmarking-with-tpcc.md) + - [Sysbench 性能测试报告](/tidb-cloud/v7.5-performance-benchmarking-with-sysbench.md) + - TiDB v7.1 + - [TPC-C 性能测试报告](/tidb-cloud/v7.1-performance-benchmarking-with-tpcc.md) + - [Sysbench 性能测试报告](/tidb-cloud/v7.1-performance-benchmarking-with-sysbench.md) + - TiDB v6.5 + - [TPC-C 性能测试报告](/tidb-cloud/v6.5-performance-benchmarking-with-tpcc.md) + - [Sysbench 性能测试报告](/tidb-cloud/v6.5-performance-benchmarking-with-sysbench.md) + - [系统变量](/system-variables.md) + - [服务器状态变量](/status-variables.md) + - [表过滤器](/table-filter.md) + - 优化资源分配 + - [资源分配概述](/tidb-cloud/optimize-resource-allocation.md) + - [资源控制](/tidb-resource-control.md) + - TiDB 节点组 + - [TiDB 节点组概述](/tidb-cloud/tidb-node-group-overview.md) + - [管理 TiDB 节点组](/tidb-cloud/tidb-node-group-management.md) + - [外部存储服务的 URI 格式](/external-storage-uri.md) + - [DDL 执行原则和最佳实践](/ddl-introduction.md) + - [解决数据和索引不一致的问题](/troubleshoot-data-inconsistency-errors.md) + - [通知](/tidb-cloud/notifications.md) + - [术语表](/tidb-cloud/tidb-cloud-glossary.md) +- 支持计划 + - [Connected Care 概述](/tidb-cloud/connected-care-overview.md) + - [Connected Care 详情](/tidb-cloud/connected-care-detail.md) + - Connected Care 支持服务功能 + - [Connected: Clinic 服务](/tidb-cloud/tidb-cloud-clinic.md) + - [Connected: IM 中的 AI 聊天](/tidb-cloud/connected-ai-chat-in-im.md) + - Connected: 用于 TiDB Cloud 警报的 IM 订阅 + - [通过 Slack 订阅](/tidb-cloud/monitor-alert-slack.md) + - [通过 Zoom 订阅](/tidb-cloud/monitor-alert-zoom.md) + - Connected: IM 工单创建和更新订阅 + - [通过 Slack 创建工单并订阅工单更新](/tidb-cloud/connected-slack-ticket-creation.md) + - [通过 Lark 创建工单并订阅工单更新](/tidb-cloud/connected-lark-ticket-creation.md) + - Connected: 用于支持工单的 IM 交互 + - [通过 Slack 与支持工单交互](/tidb-cloud/connected-slack-ticket-interaction.md) + - [通过 Lark 与支持工单交互](/tidb-cloud/connected-lark-ticket-interaction.md) + - [获取支持](/tidb-cloud/tidb-cloud-support.md) +- 常见问题 + - [TiDB Cloud 常见问题](/tidb-cloud/tidb-cloud-faq.md) + - [TiDB Cloud Serverless 常见问题](/tidb-cloud/serverless-faqs.md) + +## 发布 + +- 发行说明 + - [2025](/tidb-cloud/tidb-cloud-release-notes.md) + - [2024](/tidb-cloud/release-notes-2024.md) + - [2023](/tidb-cloud/release-notes-2023.md) + - [2022](/tidb-cloud/release-notes-2022.md) + - [2021](/tidb-cloud/release-notes-2021.md) + - [2020](/tidb-cloud/release-notes-2020.md) +- 维护通知 + - [[2024-09-15] TiDB Cloud 控制台维护通知](/tidb-cloud/notification-2024-09-15-console-maintenance.md) + - [[2024-04-18] TiDB Cloud 数据迁移 (DM) 功能维护通知](/tidb-cloud/notification-2024-04-18-dm-feature-maintenance.md) + - [[2024-04-16] TiDB Cloud 监控功能维护通知](/tidb-cloud/notification-2024-04-16-monitoring-features-maintenance.md) + - [[2024-04-11] TiDB Cloud 数据迁移 (DM) 功能维护通知](/tidb-cloud/notification-2024-04-11-dm-feature-maintenance.md) + - [[2024-04-09] TiDB Cloud 监控功能维护通知](/tidb-cloud/notification-2024-04-09-monitoring-features-maintenance.md) + - [[2023-11-14] TiDB Cloud Dedicated Scale 功能维护通知](/tidb-cloud/notification-2023-11-14-scale-feature-maintenance.md) + - [[2023-09-26] TiDB Cloud 控制台维护通知](/tidb-cloud/notification-2023-09-26-console-maintenance.md) + - [[2023-08-31] TiDB Cloud 控制台维护通知](/tidb-cloud/notification-2023-08-31-console-maintenance.md) diff --git a/accelerated-table-creation.md b/accelerated-table-creation.md index 7d9daee2a00f..ead6dcd3c9f6 100644 --- a/accelerated-table-creation.md +++ b/accelerated-table-creation.md @@ -1,40 +1,40 @@ --- -title: 提升 TiDB 建表性能 -aliases: ['/zh/tidb/stable/ddl-v2/'] -summary: 介绍 TiDB 加速建表中的概念、原理、实现和影响。 +title: TiDB 加速表创建 +aliases: ['/tidb/stable/ddl-v2/'] +summary: 了解 TiDB 中创建表的性能优化的概念、原理和实现细节。 --- -# 提升 TiDB 建表性能 +# TiDB 加速表创建 -TiDB v7.6.0 引入了系统变量 [`tidb_ddl_version`](https://docs.pingcap.com/zh/tidb/v7.6/system-variables#tidb_ddl_version-从-v760-版本开始引入) 实现支持加速建表,可提升大批量建表的速度。从 v8.0.0 开始,该系统变量更名为 [`tidb_enable_fast_create_table`](/system-variables.md#tidb_enable_fast_create_table-从-v800-版本开始引入)。 +TiDB v7.6.0 引入了系统变量 [`tidb_ddl_version`](https://docs.pingcap.com/tidb/v7.6/system-variables#tidb_enable_fast_create_table-new-in-v800) 以支持加速表创建,提高批量创建表的效率。从 v8.0.0 开始,该系统变量被重命名为 [`tidb_enable_fast_create_table`](/system-variables.md#tidb_enable_fast_create_table-new-in-v800)。 -在 TiDB 中,对元数据对象的更改采用的是 online DDL 算法(即在线异步变更算法)。所有的 DDL Job 会提交到 `mysql.tidb_ddl_job` 表里,由 owner 节点拉取 DDL Job,执行完 online DDL 算法中的各个阶段后,将该 DDL Job 标记为已完成,移入 `mysql.tidb_ddl_history` 表中。因此 DDL 只能在 owner 节点执行,无法线性拓展。 +TiDB 使用在线异步 schema 变更算法来更改元数据。所有 DDL 任务都提交到 `mysql.tidb_ddl_job` 表中,由 owner 节点拉取 DDL 任务执行。在执行完在线 DDL 算法的每个阶段后,DDL 任务被标记为完成并移动到 `mysql.tidb_ddl_history` 表中。因此,DDL 语句只能在 owner 节点上执行,无法线性扩展。 -然而,对于某些 DDL 而言,并不需要严格按照 online DDL 算法执行。如 `CREATE TABLE` 语句,Job 只有 `none` 和 `public` 两个状态,因此可以简化 DDL 的运行流程,使得建表语句可以在非 owner 节点执行,从而实现加速建表。 +然而,对于某些 DDL 语句,不需要严格遵循在线 DDL 算法。例如,`CREATE TABLE` 语句的任务只有 `none` 和 `public` 两个状态。因此,TiDB 可以简化 DDL 的执行过程,在非 owner 节点上执行 `CREATE TABLE` 语句以加速表创建。 > **警告:** > -> TiDB 加速建表目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 该功能目前是实验性功能,不建议在生产环境中使用。该功能可能会在没有事先通知的情况下发生变更或被移除。如果发现 bug,请通过在 GitHub 上提交 [issue](https://github.com/pingcap/tidb/issues) 来反馈。 ## 与 TiDB 工具的兼容性 -- [TiCDC](/ticdc/ticdc-overview.md) 暂不支持同步通过 TiDB 加速创建的表。 +- [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) 不支持复制通过 `tidb_enable_fast_create_table` 创建的表。 ## 限制 -TiDB 加速建表目前仅适用于 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 语句,且该建表语句不带任何外键约束。 +目前,表创建性能优化仅支持 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 语句,且该语句不能包含任何外键约束。 -## 使用方法 +## 使用 `tidb_enable_fast_create_table` 加速表创建 -你可以通过设置系统变量 [`tidb_enable_fast_create_table`](/system-variables.md#tidb_enable_fast_create_table-从-v800-版本开始引入) 的值来开启或关闭加速建表的功能。 +你可以通过指定系统变量 [`tidb_enable_fast_create_table`](/system-variables.md#tidb_enable_fast_create_table-new-in-v800) 的值来启用或禁用表创建性能优化。 -要开启该功能,将该变量的值设置为 `ON`: +要启用表创建性能优化,将该变量的值设置为 `ON`: ```sql SET GLOBAL tidb_enable_fast_create_table = ON; ``` -要关闭该功能,将该变量的值设置为 `OFF`: +要禁用表创建性能优化,将该变量的值设置为 `OFF`: ```sql SET GLOBAL tidb_enable_fast_create_table = OFF; @@ -42,16 +42,16 @@ SET GLOBAL tidb_enable_fast_create_table = OFF; ## 实现原理 -TiDB 加速建表的实现步骤如下: +表创建性能优化的详细实现原理如下: -1. 创建 `CREATE TABLE` Job。 +1. 创建 `CREATE TABLE` 任务。 - 通过解析 `CREATE TABLE` 语句生成相应的 DDL Job。 + 通过解析 `CREATE TABLE` 语句生成相应的 DDL 任务。 -2. 执行 `CREATE TABLE` Job。 +2. 执行 `CREATE TABLE` 任务。 - 由接收该 `CREATE TABLE` 语句的 TiDB 节点直接执行建表语句,将表结构持久化到 TiKV 中。同时,将 `CREATE TABLE` Job 标记为已完成,插入到 `mysql.tidb_ddl_history` 表中。 + 接收 `CREATE TABLE` 语句的 TiDB 节点直接执行该语句,然后将表结构持久化到 TiKV。同时,将 `CREATE TABLE` 任务标记为完成并插入到 `mysql.tidb_ddl_history` 表中。 3. 同步表信息。 - TiDB 通知其他节点同步该新建的表结构。 + TiDB 通知其他节点同步新创建的表结构。 diff --git a/agg-distinct-optimization.md b/agg-distinct-optimization.md index 6b3068e31191..b2ad6a4333b8 100644 --- a/agg-distinct-optimization.md +++ b/agg-distinct-optimization.md @@ -1,18 +1,18 @@ --- -title: Distinct 优化 -summary: 本文介绍了对于 DISTINCT 的优化,包括简单 DISTINCT 和聚合函数 DISTINCT 的优化。简单的 DISTINCT 通常会被优化成 GROUP BY 来执行。而带有 DISTINCT 的聚合函数会在 TiDB 侧单线程执行,可以通过系统变量或 TiDB 配置项控制优化器是否执行。在优化后,DISTINCT 被下推到了 Coprocessor,在 HashAgg 里新增了一个 group by 列。 +title: DISTINCT 优化 +summary: 介绍 TiDB 查询优化器中的 `distinct` 优化。 --- -# Distinct 优化 +# DISTINCT 优化 -本文档介绍可用于 `DISTINCT` 的优化,包括简单 `DISTINCT` 和聚合函数 `DISTINCT` 的优化。 +本文档介绍 TiDB 查询优化器中的 `distinct` 优化,包括 `SELECT DISTINCT` 和聚合函数中的 `DISTINCT`。 -## 简单 DISTINCT +## `SELECT` 语句中的 `DISTINCT` 修饰符 -通常简单的 `DISTINCT` 会被优化成 GROUP BY 来执行。例如: +`DISTINCT` 修饰符用于从结果集中删除重复的行。`SELECT DISTINCT` 会被转换为 `GROUP BY`,例如: ```sql -mysql> explain select DISTINCT a from t; +mysql> explain SELECT DISTINCT a from t; +--------------------------+---------+-----------+---------------+-------------------------------------------------------+ | id | estRows | task | access object | operator info | +--------------------------+---------+-----------+---------------+-------------------------------------------------------+ @@ -23,11 +23,23 @@ mysql> explain select DISTINCT a from t; 3 rows in set (0.00 sec) ``` -## 聚合函数 DISTINCT +## 聚合函数中的 `DISTINCT` 选项 -通常来说,带有 `DISTINCT` 的聚合函数会单线程的在 TiDB 侧执行。使用系统变量 [`tidb_opt_distinct_agg_push_down`](/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 的优化操作。 +通常,带有 `DISTINCT` 选项的聚合函数在 TiDB 层使用单线程执行模型执行。 -在以下示例中,`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`。 + + +[`tidb_opt_distinct_agg_push_down`](/system-variables.md#tidb_opt_distinct_agg_push_down) 系统变量或 TiDB 中的 [`distinct-agg-push-down`](/tidb-configuration-file.md#distinct-agg-push-down) 配置项控制是否重写 distinct 聚合查询并将其下推到 TiKV 或 TiFlash Coprocessor。 + + + + + +TiDB 中的 [`tidb_opt_distinct_agg_push_down`](/system-variables.md#tidb_opt_distinct_agg_push_down) 系统变量控制是否重写 distinct 聚合查询并将其下推到 TiKV 或 TiFlash Coprocessor。 + + + +以下面的查询为例说明这个优化。`tidb_opt_distinct_agg_push_down` 默认是禁用的,这意味着聚合函数在 TiDB 层执行。通过将其值设置为 `1` 启用此优化后,`count(distinct a)` 中的 `distinct a` 部分会被下推到 TiKV 或 TiFlash Coprocessor:在 TiKV Coprocessor 中有一个 HashAgg_5 用于删除列 a 上的重复值。这可能会减少 TiDB 层 `HashAgg_8` 的计算开销。 ```sql mysql> desc select count(distinct a) from test.t; diff --git a/as-of-timestamp.md b/as-of-timestamp.md index e4c2a41e6787..fe926dab79a2 100644 --- a/as-of-timestamp.md +++ b/as-of-timestamp.md @@ -1,52 +1,52 @@ --- -title: 使用 AS OF TIMESTAMP 语法读取历史数据 -summary: 了解如何使用 AS OF TIMESTAMP 语法读取历史数据。 +title: 使用 `AS OF TIMESTAMP` 子句读取历史数据 +summary: 了解如何使用 `AS OF TIMESTAMP` 语句子句读取历史数据。 --- -# 使用 AS OF TIMESTAMP 语法读取历史数据 +# 使用 `AS OF TIMESTAMP` 子句读取历史数据 -本文档介绍如何通过 `AS OF TIMESTAMP` 语句使用 [Stale Read](/stale-read.md) 功能来读取 TiDB 历史版本数据,包括具体的操作示例以及历史数据的保存策略。 +本文档介绍如何使用 `AS OF TIMESTAMP` 子句执行[历史读取](/stale-read.md)功能来读取 TiDB 中的历史数据,包括具体的使用示例和保存历史数据的策略。 -TiDB 支持通过标准 SQL 接口,即通过 `AS OF TIMESTAMP` SQL 语法的形式读取历史数据,无需特殊的服务器或者驱动器。当数据被更新或删除后,你可以通过 SQL 接口将更新或删除前的数据读取出来。 +TiDB 支持通过标准 SQL 接口读取历史数据,即 `AS OF TIMESTAMP` SQL 子句,无需特殊的客户端或驱动程序。在数据更新或删除后,您可以使用此 SQL 接口读取更新或删除之前的历史数据。 > **注意:** > -> 读取历史数据时,即使当前数据的表结构相较于历史数据的表结构已经发生改变,历史数据也会以当时的历史表结构来返回。 +> 在读取历史数据时,即使当前表结构已经发生变化,TiDB 也会返回旧表结构的数据。 -## 语法方式 +## 语法 -你可以通过以下三种方式使用 `AS OF TIMESTAMP` 语法: +您可以通过以下三种方式使用 `AS OF TIMESTAMP` 子句: - [`SELECT ... FROM ... AS OF TIMESTAMP`](/sql-statements/sql-statement-select.md) - [`START TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-start-transaction.md) - [`SET TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-set-transaction.md) -如果你想要指定一个精确的时间点,可在 `AS OF TIMESTAMP` 中使用日期时间和时间函数,日期时间的格式为:"2016-10-08 16:45:26.999",最小时间精度范围为毫秒,通常可只写到秒,例如 "2016-10-08 16:45:26"。你也可以通过 `NOW(3)` 函数获得精确到毫秒的当前时间。如果想读取几秒前的数据,推荐使用例如 `NOW() - INTERVAL 10 SECOND` 的表达式。(推荐) +如果要指定精确的时间点,可以在 `AS OF TIMESTAMP` 子句中设置日期时间值或使用时间函数。日期时间的格式类似于 "2016-10-08 16:45:26.999",最小时间单位为毫秒,但大多数情况下,秒级的时间单位足以指定日期时间,例如 "2016-10-08 16:45:26"。您也可以使用 `NOW(3)` 函数获取精确到毫秒的当前时间。如果要读取几秒前的数据,**建议**使用 `NOW() - INTERVAL 10 SECOND` 这样的表达式。 -如果你想要指定一个时间范围,需要使用 [`TIDB_BOUNDED_STALENESS()`](/functions-and-operators/tidb-functions.md#tidb_bounded_staleness) 函数。使用该函数,TiDB 会在指定的时间范围内选择一个合适的时间戳,该时间戳能保证所访问的副本上不存在开始于这个时间戳之前且还没有提交的相关事务,即能保证所访问的可用副本上执行读取操作而且不会被阻塞。用法为 `TIDB_BOUNDED_STALENESS(t1, t2)`,其中 `t1` 和 `t2` 为时间范围的两端,支持使用日期时间和时间函数。 +如果要指定时间范围,可以在子句中使用 [`TIDB_BOUNDED_STALENESS()`](/functions-and-operators/tidb-functions.md#tidb_bounded_staleness) 函数。使用此函数时,TiDB 会在指定的时间范围内选择一个合适的时间戳。"合适"意味着在访问的副本上没有在此时间戳之前开始且尚未提交的事务,即 TiDB 可以在访问的副本上执行读取操作,且读取操作不会被阻塞。您需要使用 `TIDB_BOUNDED_STALENESS(t1, t2)` 来调用此函数。`t1` 和 `t2` 是时间范围的两端,可以使用日期时间值或时间函数指定。 -示例如下: +以下是 `AS OF TIMESTAMP` 子句的一些示例: -- `AS OF TIMESTAMP '2016-10-08 16:45:26'` 表示读取在 2016 年 10 月 8 日 16 点 45 分 26 秒时最新的数据。 -- `AS OF TIMESTAMP NOW() - INTERVAL 10 SECOND` 表示读取 10 秒前最新的数据。 -- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS('2016-10-08 16:45:26', '2016-10-08 16:45:29')` 表示读取在 2016 年 10 月 8 日 16 点 45 分 26 秒到 29 秒的时间范围内尽可能新的数据。 -- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS(NOW() - INTERVAL 20 SECOND, NOW())` 表示读取 20 秒前到现在的时间范围内尽可能新的数据。 +- `AS OF TIMESTAMP '2016-10-08 16:45:26'`:告诉 TiDB 读取 2016 年 10 月 8 日 16:45:26 存储的最新数据。 +- `AS OF TIMESTAMP NOW() - INTERVAL 10 SECOND`:告诉 TiDB 读取 10 秒前存储的最新数据。 +- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS('2016-10-08 16:45:26', '2016-10-08 16:45:29')`:告诉 TiDB 读取 2016 年 10 月 8 日 16:45:26 到 16:45:29 时间范围内尽可能新的数据。 +- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS(NOW() - INTERVAL 20 SECOND, NOW())`:告诉 TiDB 读取 20 秒前到现在时间范围内尽可能新的数据。 > **注意:** > -> 除了指定时间戳,`AS OF TIMESTAMP` 语法最常用使用的方式是读几秒前的数据。如果采用这种方式,推荐读 5 秒以上的历史数据。 +> 除了指定时间戳外,`AS OF TIMESTAMP` 子句最常见的用法是读取几秒前的数据。如果采用这种方法,建议读取 5 秒以前的历史数据。 > -> 使用 Stale Read 时需要为 TiDB 和 PD 节点部署 NTP 服务,防止 TiDB 指定的时间戳超过当前最新的 TSO 分配进度(如几秒后的时间戳),或者落后于 GC safe point 的时间戳。当指定的时间戳超过服务范围,TiDB 会返回错误。 +> 使用历史读取时,需要为 TiDB 和 PD 节点部署 NTP 服务。这可以避免 TiDB 使用的指定时间戳超前于最新的 TSO 分配进度(例如超前几秒的时间戳),或晚于 GC 安全点时间戳的情况。当指定的时间戳超出服务范围时,TiDB 会返回错误。 > -> 你可以通过调整 TiKV 的 `advance-ts-interval` 配置项提高 Stale Read 数据的时效性(即减少延时)。详情参见[减少 Stale Read 延时](/stale-read.md#减少-stale-read-延时)。 +> 为了减少延迟并提高历史读取数据的时效性,您可以修改 TiKV 的 `advance-ts-interval` 配置项。详情请参见[减少历史读取延迟](/stale-read.md#reduce-stale-read-latency)。 -## 示例 +## 使用示例 -本节通过多个示例介绍 `AS OF TIMESTAMP` 语法的不同使用方法。在本节中,先介绍如何准备用于恢复的数据,再分别展示如何通过 `SELECT`、`START TRANSACTION READ ONLY AS OF TIMESTAMP`、`SET TRANSACTION READ ONLY AS OF TIMESTAMP` 使用 `AS OF TIMESTAMP`。 +本节通过几个示例介绍使用 `AS OF TIMESTAMP` 子句的不同方式。首先介绍如何准备用于恢复的数据,然后分别展示如何在 `SELECT`、`START TRANSACTION READ ONLY AS OF TIMESTAMP` 和 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 中使用 `AS OF TIMESTAMP`。 -### 准备数据 +### 准备数据样本 -在准备数据阶段,创建一张表,并插入若干行数据: +要准备用于恢复的数据,首先创建一个表并插入几行数据: ```sql create table t (c int); @@ -96,7 +96,7 @@ select now(); 1 row in set (0.00 sec) ``` -更新某一行数据: +更新一行数据: ```sql update t set c=22 where c=2; @@ -106,7 +106,7 @@ update t set c=22 where c=2; Query OK, 1 row affected (0.00 sec) ``` -确认数据已经被更新: +确认该行数据已更新: ```sql select * from t; @@ -123,9 +123,9 @@ select * from t; 3 rows in set (0.00 sec) ``` -### 通过 `SELECT` 读取历史数据 +### 使用 `SELECT` 语句读取历史数据 -通过 [`SELECT ... FROM ... AS OF TIMESTAMP`](/sql-statements/sql-statement-select.md) 语句读取一个基于历史时间的数据。 +您可以使用 [`SELECT ... FROM ... AS OF TIMESTAMP`](/sql-statements/sql-statement-select.md) 语句读取过去某个时间点的数据。 ```sql select * from t as of timestamp '2021-05-26 16:45:26'; @@ -144,11 +144,11 @@ select * from t as of timestamp '2021-05-26 16:45:26'; > **注意:** > -> 通过 `SELECT` 语句读取多个表时要保证 TIMESTAMP EXPRESSION 是一致的。比如:`select * from t as of timestamp NOW() - INTERVAL 2 SECOND, c as of timestamp NOW() - INTERVAL 2 SECOND;`。此外,在 `SELECT` 语句中,你必须要指定相关数据表的 as of 信息,若不指定,`SELECT` 语句会默认读最新的数据。 +> 在使用一个 `SELECT` 语句读取多个表时,需要确保 TIMESTAMP EXPRESSION 的格式一致。例如 `select * from t as of timestamp NOW() - INTERVAL 2 SECOND, c as of timestamp NOW() - INTERVAL 2 SECOND;`。此外,必须为 `SELECT` 语句中的相关表指定 `AS OF` 信息,否则 `SELECT` 语句默认读取最新数据。 -### 通过 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 读取历史数据 +### 使用 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 语句读取历史数据 -通过 [`START TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-start-transaction.md) 语句,你可以开启一个基于历史时间的只读事务,该事务基于所提供的历史时间来读取历史数据。 +您可以使用 [`START TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-start-transaction.md) 语句基于过去的某个时间点启动只读事务。该事务读取给定时间的历史数据。 ```sql start transaction read only as of timestamp '2021-05-26 16:45:26'; @@ -181,7 +181,7 @@ commit; Query OK, 0 rows affected (0.00 sec) ``` -当事务结束后,即可读取最新数据。 +事务提交后,您可以读取最新数据。 ```sql select * from t; @@ -200,11 +200,11 @@ select * from t; > **注意:** > -> 通过 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 开启的事务为只读事务。假如在该事务中执行写入操作,操作将会被该事务拒绝。 +> 如果使用 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 语句启动事务,则该事务为只读事务。在此事务中,写入操作将被拒绝。 -### 通过 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 读取历史数据 +### 使用 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 语句读取历史数据 -通过 [`SET TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-set-transaction.md) 语句,你可以将下一个事务设置为基于指定历史时间的只读事务。该事务将会基于所提供的历史时间来读取历史数据。 +您可以使用 [`SET TRANSACTION READ ONLY AS OF TIMESTAMP`](/sql-statements/sql-statement-set-transaction.md) 语句将下一个事务设置为基于过去某个时间点的只读事务。该事务读取给定时间的历史数据。 ```sql set transaction read only as of timestamp '2021-05-26 16:45:26'; @@ -245,7 +245,7 @@ commit; Query OK, 0 rows affected (0.00 sec) ``` -当事务结束后,即可读取最新数据。 +事务提交后,您可以读取最新数据。 ```sql select * from t; @@ -264,4 +264,4 @@ select * from t; > **注意:** > -> 通过 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 开启的事务为只读事务。假如在该事务中执行写入操作,操作将会被该事务拒绝。 +> 如果使用 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 语句启动事务,则该事务为只读事务。在此事务中,写入操作将被拒绝。 diff --git a/auto-increment.md b/auto-increment.md index a2bea2494498..acf35f559916 100644 --- a/auto-increment.md +++ b/auto-increment.md @@ -1,27 +1,41 @@ --- title: AUTO_INCREMENT -summary: 介绍 TiDB 的 `AUTO_INCREMENT` 列属性。 +summary: 了解 TiDB 的 `AUTO_INCREMENT` 列属性。 --- # AUTO_INCREMENT -本文介绍列属性 `AUTO_INCREMENT` 的基本概念、实现原理、自增相关的特性,以及使用限制。 +本文介绍 `AUTO_INCREMENT` 列属性,包括其概念、实现原理、自增相关特性和限制。 + + + +> **注意:** +> +> `AUTO_INCREMENT` 属性可能在生产环境中造成热点问题。详情请参见[热点问题处理](/troubleshoot-hot-spot-issues.md)。建议使用 [`AUTO_RANDOM`](/auto-random.md) 代替。 + + + + > **注意:** > -> 使用 `AUTO_INCREMENT` 可能会给生产环境带热点问题,因此推荐使用 [`AUTO_RANDOM`](/auto-random.md) 代替。详情请参考 [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md#tidb-热点问题处理)。 +> `AUTO_INCREMENT` 属性可能在生产环境中造成热点问题。详情请参见[热点问题处理](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues#handle-auto-increment-primary-key-hotspot-tables-using-auto_random)。建议使用 [`AUTO_RANDOM`](/auto-random.md) 代替。 -在 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 语句中也可以使用 `AUTO_INCREMENT` 参数来指定自增字段的初始值。 + -## 基本概念 +你也可以在 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 语句中使用 `AUTO_INCREMENT` 参数来指定自增字段的初始值。 -`AUTO_INCREMENT` 是用于自动填充缺省列值的列属性。当 `INSERT` 语句没有指定 `AUTO_INCREMENT` 列的具体值时,系统会自动地为该列分配一个值。 +## 概念 -出于性能原因,自增编号是系统批量分配给每台 TiDB 服务器的值(默认 3 万个值),因此自增编号能保证唯一性,但分配给 `INSERT` 语句的值仅在单台 TiDB 服务器上具有单调性。 +`AUTO_INCREMENT` 是一个列属性,用于自动填充默认列值。当 `INSERT` 语句没有为 `AUTO_INCREMENT` 列指定值时,系统会自动为该列分配值。 + +出于性能考虑,`AUTO_INCREMENT` 数值会按批次(默认为 3 万个)分配给每个 TiDB 服务器。这意味着虽然 `AUTO_INCREMENT` 数值保证是唯一的,但分配给 `INSERT` 语句的值只在每个 TiDB 服务器基础上保持单调递增。 > **注意:** > -> 如果要求自增编号在所有 TiDB 实例上具有单调性,并且你的 TiDB 版本在 v6.5.0 及以上,推荐使用[兼容 MySQL 的自增列模式](#兼容-mysql-的自增列模式)。 +> 如果你希望 `AUTO_INCREMENT` 数值在所有 TiDB 服务器上都保持单调递增,并且你的 TiDB 版本是 v6.5.0 或更高版本,建议启用 [MySQL 兼容模式](#mysql-兼容模式)。 + +以下是 `AUTO_INCREMENT` 的基本示例: {{< copyable "sql" >}} @@ -38,7 +52,7 @@ INSERT INTO t(c) VALUES (3), (4), (5); ``` ```sql -SELECT * FROM t; +mysql> SELECT * FROM t; +----+---+ | id | c | +----+---+ @@ -51,7 +65,7 @@ SELECT * FROM t; 5 rows in set (0.01 sec) ``` -此外,`AUTO_INCREMENT` 还支持显式指定列值的插入语句,此时 TiDB 会保存显式指定的值: +此外,`AUTO_INCREMENT` 也支持显式指定列值的 `INSERT` 语句。在这种情况下,TiDB 会存储显式指定的值: {{< copyable "sql" >}} @@ -60,7 +74,7 @@ INSERT INTO t(id, c) VALUES (6, 6); ``` ```sql -SELECT * FROM t; +mysql> SELECT * FROM t; +----+---+ | id | c | +----+---+ @@ -74,40 +88,43 @@ SELECT * FROM t; 6 rows in set (0.01 sec) ``` -以上用法和 MySQL 的 `AUTO_INCREMENT` 用法一致。但在隐式分配的具体值方面,TiDB 和 MySQL 之间具有较为显著的差异。 +上述用法与 MySQL 中的 `AUTO_INCREMENT` 相同。但是,在隐式分配的具体值方面,TiDB 与 MySQL 有显著的不同。 ## 实现原理 -TiDB 实现 `AUTO_INCREMENT` 隐式分配的原理是,对于每一个自增列,都使用一个全局可见的键值对用于记录当前已分配的最大 ID。由于分布式环境下的节点通信存在一定开销,为了避免写请求放大的问题,每个 TiDB 节点在分配 ID 时,都申请一段 ID 作为缓存,用完之后再去取下一段,而不是每次分配都向存储节点申请。例如,对于以下新建的表: +TiDB 以如下方式实现 `AUTO_INCREMENT` 隐式分配: + +对于每个自增列,使用一个全局可见的键值对来记录已分配的最大 ID。在分布式环境中,节点之间的通信有一定开销。因此,为了避免写放大问题,每个 TiDB 节点在分配 ID 时会申请一批连续的 ID 作为缓存,然后在第一批 ID 分配完后再申请下一批 ID。因此,TiDB 节点在每次分配 ID 时不需要向存储节点申请 ID。例如: ```sql CREATE TABLE t(id int UNIQUE KEY AUTO_INCREMENT, c int); ``` -假设集群中有两个 TiDB 实例 A 和 B,如果向 A 和 B 分别对 `t` 执行一条插入语句: +假设集群中有两个 TiDB 实例 `A` 和 `B`。如果你在 `A` 和 `B` 上分别对 `t` 表执行 `INSERT` 语句: ```sql INSERT INTO t (c) VALUES (1) ``` -实例 A 可能会缓存 `[1,30000]` 的自增 ID,而实例 B 则可能缓存 `[30001,60000]` 的自增 ID。各自实例缓存的 ID 将随着执行将来的插入语句被作为缺省值,顺序地填充到 `AUTO_INCREMENT` 列中。 +实例 `A` 可能会缓存自增 ID `[1,30000]`,实例 `B` 可能会缓存自增 ID `[30001,60000]`。在要执行的 `INSERT` 语句中,这些缓存的 ID 将作为默认值分配给 `AUTO_INCREMENT` 列。 ## 基本特性 -### 唯一性保证 +### 唯一性 > **警告:** > -> 在集群中有多个 TiDB 实例时,如果表结构中有自增 ID,建议不要混用显式插入和隐式分配(即自增列的缺省值和自定义值),否则可能会破坏隐式分配值的唯一性。 +> 当集群有多个 TiDB 实例时,如果表结构包含自增 ID,建议不要同时使用显式插入和隐式分配,即使用自增列的默认值和自定义值。否则,可能会破坏隐式分配值的唯一性。 + +在上面的例子中,按顺序执行以下操作: -例如在上述示例中,依次执行如下操作: +1. 客户端向实例 `B` 插入语句 `INSERT INTO t VALUES (2, 1)`,将 `id` 设置为 `2`。语句成功执行。 -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` 错误。 +2. 客户端向实例 `A` 发送语句 `INSERT INTO t (c) (1)`。此语句没有指定 `id` 的值,所以 ID 由 `A` 分配。目前,由于 `A` 缓存了 `[1, 30000]` 的 ID,它可能会分配 `2` 作为自增 ID 的值,并将本地计数器加 `1`。此时,数据库中已经存在 ID 为 `2` 的数据,所以会返回 `Duplicated Error` 错误。 -### 单调性保证 +### 单调性 -TiDB 保证 `AUTO_INCREMENT` 自增值在单台服务器上单调递增。以下示例在一台服务器上生成连续的 `AUTO_INCREMENT` 自增值 `1`-`3`: +TiDB 保证 `AUTO_INCREMENT` 值在每个服务器上是单调递增的(始终增加)。考虑以下示例,其中生成了连续的 `AUTO_INCREMENT` 值 1-3: {{< copyable "sql" >}} @@ -119,8 +136,10 @@ SELECT * FROM t; ```sql Query OK, 0 rows affected (0.11 sec) + Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 + +---+---------------------+ | a | b | +---+---------------------+ @@ -131,10 +150,12 @@ Records: 3 Duplicates: 0 Warnings: 0 3 rows in set (0.00 sec) ``` -TiDB 能保证自增值的单调性,但并不能保证其连续性。参考以下示例: +单调性与连续性不是相同的保证。考虑以下示例: + +{{< copyable "sql" >}} ```sql -CREATE TABLE t (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, a VARCHAR(10), cnt INT NOT NULL DEFAULT 1, UNIQUE KEY (a)); +CREATE TABLE t (id INT NOT NULL PRIMARY KEY auto_increment, a VARCHAR(10), cnt INT NOT NULL DEFAULT 1, UNIQUE KEY (a)); INSERT INTO t (a) VALUES ('A'), ('B'); SELECT * FROM t; INSERT INTO t (a) VALUES ('A'), ('C') ON DUPLICATE KEY UPDATE cnt = cnt + 1; @@ -168,16 +189,16 @@ Records: 2 Duplicates: 1 Warnings: 0 3 rows in set (0.00 sec) ``` -在以上示例 `INSERT INTO t (a) VALUES ('A'), ('C') ON DUPLICATE KEY UPDATE cnt = cnt + 1;` 语句中,自增值 `3` 被分配为 `A` 键对应的 `id` 值,但实际上 `3` 并未作为 `id` 值插入进表中。这是因为该 `INSERT` 语句包含一个重复键 `A`,使得自增序列不连续,出现了间隙。该行为尽管与 MySQL 不同,但仍是合法的。MySQL 在其他情况下也会出现自增序列不连续的情况,例如事务被中止和回滚时。 +在这个例子中,`AUTO_INCREMENT` 值 `3` 被分配给了 `INSERT INTO t (a) VALUES ('A'), ('C') ON DUPLICATE KEY UPDATE cnt = cnt + 1;` 中键 `A` 的 `INSERT`,但由于这个 `INSERT` 语句包含重复键 `A`,所以这个值从未被使用。这导致了序列中出现非连续的间隙。这种行为被认为是合法的,尽管它与 MySQL 不同。MySQL 在其他场景(如事务被中止和回滚)中也会在序列中出现间隙。 ## AUTO_ID_CACHE -如果在另一台服务器上执行插入操作,那么 `AUTO_INCREMENT` 值的顺序可能会剧烈跳跃,这是由于每台服务器都有各自缓存的 `AUTO_INCREMENT` 自增值。 +如果对不同的 TiDB 服务器执行 `INSERT` 操作,`AUTO_INCREMENT` 序列可能会出现显著的"跳跃"。这是因为每个服务器都有自己的 `AUTO_INCREMENT` 值缓存: {{< copyable "sql" >}} ```sql -CREATE TABLE t (a INT PRIMARY KEY AUTO_INCREMENT, b TIMESTAMP NOT NULL DEFAULT NOW()); +CREATE TABLE t (a int PRIMARY KEY AUTO_INCREMENT, b timestamp NOT NULL DEFAULT NOW()); INSERT INTO t (a) VALUES (NULL), (NULL), (NULL); INSERT INTO t (a) VALUES (NULL); SELECT * FROM t; @@ -197,13 +218,13 @@ Query OK, 1 row affected (0.03 sec) 4 rows in set (0.00 sec) ``` -以下示例在最先的一台服务器上执行一个插入 `INSERT` 操作,生成 `AUTO_INCREMENT` 值 `4`。因为这台服务器上仍有剩余的 `AUTO_INCREMENT` 缓存值可用于分配。在该示例中,值的顺序不具有全局单调性: +对初始 TiDB 服务器执行新的 `INSERT` 操作会生成 `AUTO_INCREMENT` 值 `4`。这是因为初始 TiDB 服务器的 `AUTO_INCREMENT` 缓存中仍有可分配的空间。在这种情况下,序列值不能被视为全局单调的,因为值 `4` 是在值 `2000001` 之后插入的: ```sql -INSERT INTO t (a) VALUES (NULL); +mysql> INSERT INTO t (a) VALUES (NULL); Query OK, 1 row affected (0.01 sec) -SELECT * FROM t ORDER BY b; +mysql> SELECT * FROM t ORDER BY b; +---------+---------------------+ | a | b | +---------+---------------------+ @@ -216,13 +237,13 @@ SELECT * FROM t ORDER BY b; 5 rows in set (0.00 sec) ``` -`AUTO_INCREMENT` 缓存不会持久化,重启会导致缓存值失效。以下示例中,最先的一台服务器重启后,向该服务器执行一条插入操作: +`AUTO_INCREMENT` 缓存不会在 TiDB 服务器重启后持续存在。以下 `INSERT` 语句是在初始 TiDB 服务器重启后执行的: ```sql -INSERT INTO t (a) VALUES (NULL); +mysql> INSERT INTO t (a) VALUES (NULL); Query OK, 1 row affected (0.01 sec) -SELECT * FROM t ORDER BY b; +mysql> SELECT * FROM t ORDER BY b; +---------+---------------------+ | a | b | +---------+---------------------+ @@ -236,27 +257,27 @@ SELECT * FROM t ORDER BY b; 6 rows in set (0.00 sec) ``` -TiDB 服务器频繁重启可能导致 `AUTO_INCREMENT` 缓存值被快速消耗。在以上示例中,最先的一台服务器本来有可用的缓存值 `[5-3000]`。但重启后,这些值便丢失了,无法进行重新分配。 +频繁的 TiDB 服务器重启可能会导致 `AUTO_INCREMENT` 值的耗尽。在上面的例子中,初始 TiDB 服务器的缓存中仍有值 `[5-30000]` 可用。这些值被丢失,不会被重新分配。 -用户不应指望 `AUTO_INCREMENT` 值保持连续。在以下示例中,一台 TiDB 服务器的缓存值为 `[2000001-2030000]`。当手动插入值 `2029998` 时,TiDB 取用了一个新缓存区间的值: +不建议依赖 `AUTO_INCREMENT` 值的连续性。考虑以下示例,其中一个 TiDB 服务器有值 `[2000001-2030000]` 的缓存。通过手动插入值 `2029998`,你可以看到在获取新的缓存范围时的行为: ```sql -INSERT INTO t (a) VALUES (2029998); +mysql> INSERT INTO t (a) VALUES (2029998); Query OK, 1 row affected (0.01 sec) -INSERT INTO t (a) VALUES (NULL); +mysql> INSERT INTO t (a) VALUES (NULL); Query OK, 1 row affected (0.01 sec) -INSERT INTO t (a) VALUES (NULL); +mysql> INSERT INTO t (a) VALUES (NULL); Query OK, 1 row affected (0.00 sec) -INSERT INTO t (a) VALUES (NULL); +mysql> INSERT INTO t (a) VALUES (NULL); Query OK, 1 row affected (0.02 sec) -INSERT INTO t (a) VALUES (NULL); +mysql> INSERT INTO t (a) VALUES (NULL); Query OK, 1 row affected (0.01 sec) -SELECT * FROM t ORDER BY b; +mysql> SELECT * FROM t ORDER BY b; +---------+---------------------+ | a | b | +---------+---------------------+ @@ -275,17 +296,17 @@ SELECT * FROM t ORDER BY b; 11 rows in set (0.00 sec) ``` -以上示例插入 `2030000` 后,下一个值为 `2060001`,即顺序出现跳跃。这是因为另一台 TiDB 服务器获取了中间缓存区间 `[2030001-2060000]`。当部署有多台 TiDB 服务器时,`AUTO_INCREMENT` 值的顺序会出现跳跃,因为对缓存值的请求是交叉出现的。 +在插入值 `2030000` 后,下一个值是 `2060001`。这个序列的跳跃是由于另一个 TiDB 服务器获得了中间缓存范围 `[2030001-2060000]`。当部署多个 TiDB 服务器时,由于缓存请求交错,`AUTO_INCREMENT` 序列中会出现间隙。 ### 缓存大小控制 -TiDB 自增 ID 的缓存大小在早期版本中是对用户透明的。从 v3.1.2、v3.0.14 和 v4.0.rc-2 版本开始,TiDB 引入了 `AUTO_ID_CACHE` 表选项来允许用户自主设置自增 ID 分配缓存的大小。例如: +在早期版本的 TiDB 中,自增 ID 的缓存大小对用户是透明的。从 v3.0.14、v3.1.2 和 v4.0.rc-2 开始,TiDB 引入了 `AUTO_ID_CACHE` 表选项,允许用户设置分配自增 ID 的缓存大小。 ```sql CREATE TABLE t(a int AUTO_INCREMENT key) AUTO_ID_CACHE 100; Query OK, 0 rows affected (0.02 sec) -INSERT INTO t VALUES(); +INSERT INTO t values(); Query OK, 1 row affected (0.00 sec) SELECT * FROM t; @@ -308,7 +329,7 @@ SHOW CREATE TABLE t; 1 row in set (0.00 sec) ``` -此时如果重启 TiDB,自增 ID 缓存将会丢失,新的插入操作将从一个之前缓存范围外的更高的 ID 值开始分配。 +此时,如果重启 TiDB,自增 ID 缓存将丢失,新的插入操作将从超出先前缓存范围的更高值开始分配 ID。 ```sql INSERT INTO t VALUES(); @@ -324,18 +345,28 @@ SELECT * FROM t; 2 rows in set (0.01 sec) ``` -可以看到再一次分配的值为 `101`,说明该表的自增 ID 分配缓存的大小为 `100`。 +新分配的值是 `101`。这表明分配自增 ID 的缓存大小是 `100`。 -此外如果在批量插入的 `INSERT` 语句中所需连续 ID 长度超过 `AUTO_ID_CACHE` 的长度时,TiDB 会适当调大缓存以便能够保证该语句的正常插入。 +此外,当批量 `INSERT` 语句中连续 ID 的长度超过 `AUTO_ID_CACHE` 的长度时,TiDB 会相应地增加缓存大小,以确保语句可以正常插入数据。 ### 清除自增 ID 缓存 -在一些场景中,你可能需要清除自增 ID 缓存,以保证数据一致性。例如: +在某些场景下,你可能需要清除自增 ID 缓存以确保数据一致性。例如: -- 使用 [Data Migration (DM)](/dm/dm-overview.md) 进行增量同步,当同步结束后,下游 TiDB 的数据写入方式将从 DM 切换回正常的业务数据写入,此时自增列 ID 的写入模式通常由显式写入转换成隐式分配。 -- 当业务同时使用了显式写入和隐式分配时,需要清除自增 ID 缓存,以防止后续隐式分配的自增 ID 与已显式写入的 ID 发生冲突,导致主键冲突错误。具体场景参考[唯一性保证](/auto-increment.md#唯一性保证)。 + -你可以执行 `ALTER TABLE` 语句设置 `AUTO_INCREMENT = 0` 来清除集群中所有 TiDB 节点的自增 ID 缓存。例如: +- 在使用 [Data Migration (DM)](/dm/dm-overview.md) 进行增量复制的场景中,一旦复制完成,数据写入下游 TiDB 的方式从 DM 切换到应用程序的写操作。同时,自增列的 ID 写入模式通常从显式插入切换到隐式分配。 + + + + +- 在使用[数据迁移](/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md)功能进行增量复制的场景中,一旦复制完成,数据写入下游 TiDB 的方式从 DM 切换到应用程序的写操作。同时,自增列的 ID 写入模式通常从显式插入切换到隐式分配。 + + + +- 当你的应用程序同时涉及显式 ID 插入和隐式 ID 分配时,你需要清除自增 ID 缓存,以避免未来隐式分配的 ID 与先前显式插入的 ID 发生冲突,这可能导致主键冲突错误。更多信息,请参见[唯一性](/auto-increment.md#唯一性)。 + +要清除集群中所有 TiDB 节点上的自增 ID 缓存,你可以执行带有 `AUTO_INCREMENT = 0` 的 `ALTER TABLE` 语句。例如: ```sql CREATE TABLE t(a int AUTO_INCREMENT key) AUTO_ID_CACHE 100; @@ -383,64 +414,68 @@ SELECT * FROM t; 3 rows in set (0.01 sec) ``` -### 自增步长和偏移量设置 +### 自增步长和偏移量 + +从 v3.0.9 和 v4.0.0-rc.1 开始,与 MySQL 的行为类似,隐式分配给自增列的值由 `@@auto_increment_increment` 和 `@@auto_increment_offset` 会话变量控制。 + +隐式分配给自增列的值(ID)满足以下等式: -从 v3.0.9 和 v4.0.rc-1 开始,和 MySQL 的行为类似,自增列隐式分配的值遵循 session 变量 `@@auto_increment_increment` 和 `@@auto_increment_offset` 的控制,其中自增列隐式分配的值 (ID) 将满足式子 `(ID - auto_increment_offset) % auto_increment_increment == 0`。 +`(ID - auto_increment_offset) % auto_increment_increment == 0` -## 兼容 MySQL 的自增列模式 +## MySQL 兼容模式 -TiDB 提供了一种兼容 MySQL 的自增列模式,该模式能确保 ID 严格递增且间隙最小。要启用此模式,需在建表时将 `AUTO_ID_CACHE` 设置为 `1`: +TiDB 为自增列提供了一个 MySQL 兼容模式,可确保 ID 严格递增且间隙最小。要启用此模式,在创建表时将 `AUTO_ID_CACHE` 设置为 `1`: ```sql CREATE TABLE t(a int AUTO_INCREMENT key) AUTO_ID_CACHE 1; ``` -当 `AUTO_ID_CACHE` 设置为 `1` 时,所有 TiDB 实例生成的 ID 严格全局递增,每个 ID 保证全局唯一,相较于默认缓存模式(`AUTO_ID_CACHE 0` 具有 30000 个缓存值),ID 间隙显著缩小。 +当 `AUTO_ID_CACHE` 设置为 `1` 时,ID 在所有 TiDB 实例上严格递增,每个 ID 都保证是唯一的,并且与默认缓存模式(`AUTO_ID_CACHE 0` 缓存 30000 个值)相比,ID 之间的间隙最小。 -例如,启用 `AUTO_ID_CACHE 1` 后可以生成如下序列: +例如,使用 `AUTO_ID_CACHE 1` 时,你可能会看到如下序列: ```sql -INSERT INTO t VALUES (); -- Returns ID 1 -INSERT INTO t VALUES (); -- Returns ID 2 -INSERT INTO t VALUES (); -- Returns ID 3 --- After failover -INSERT INTO t VALUES (); -- Might return ID 5 +INSERT INTO t VALUES (); -- 返回 ID 1 +INSERT INTO t VALUES (); -- 返回 ID 2 +INSERT INTO t VALUES (); -- 返回 ID 3 +-- 故障转移后 +INSERT INTO t VALUES (); -- 可能返回 ID 5 ``` -相比之下,使用默认缓存(`AUTO_ID_CACHE 0`)时可能出现较大间隙: +相比之下,使用默认缓存(`AUTO_ID_CACHE 0`)时,可能会出现更大的间隙: ```sql -INSERT INTO t VALUES (); -- Returns ID 1 -INSERT INTO t VALUES (); -- Returns ID 2 --- New TiDB instance allocates next batch -INSERT INTO t VALUES (); -- Returns ID 30001 +INSERT INTO t VALUES (); -- 返回 ID 1 +INSERT INTO t VALUES (); -- 返回 ID 2 +-- 新的 TiDB 实例分配下一批 +INSERT INTO t VALUES (); -- 返回 ID 30001 ``` -尽管 `AUTO_ID_CACHE 1` 能保证 ID 严格递增且不会出现类似 `AUTO_ID_CACHE 0` 的大幅间隙,但在以下场景中仍可能出现微小间隙。这些间隙是维持 ID 全局唯一性和严格递增特性的必要代价: +虽然 ID 始终递增且没有像 `AUTO_ID_CACHE 0` 那样的显著间隙,但在以下场景中序列中可能仍会出现小的间隙。这些间隙是必要的,以维持 ID 的唯一性和严格递增的特性。 -- 主实例退出或崩溃的故障恢复期间 +- 主实例退出或崩溃时的故障转移期间 - 使用兼容 MySQL 的自增列模式后,能保证 ID **唯一**、**单调递增**,行为几乎跟 MySQL 完全一致。即使跨 TiDB 实例访问,ID 也不会出现回退。只有在中心化分配自增 ID 服务的“主” TiDB 实例进程退出(如该 TiDB 节点重启)或者异常崩溃时,才有可能造成部分 ID 不连续。这是因为主备切换时,“备” 节点需要丢弃一部分之前的“主” 节点已经分配的 ID,以保证 ID 不出现重复。 + 启用 MySQL 兼容模式后,分配的 ID 是**唯一**且**单调递增**的,行为与 MySQL 几乎相同。即使跨多个 TiDB 实例访问,也保持 ID 的单调性。但是,如果中心化服务的主实例崩溃,少数 ID 可能会变得不连续。这是因为在故障转移期间,备用实例会丢弃主实例分配的一些 ID,以确保 ID 的唯一性。 - TiDB 节点滚动升级期间 -- 正常并发事务场景(与 MySQL 类似) +- 正常并发事务期间(与 MySQL 类似) > **注意:** > -> `AUTO_ID_CACHE 1` 的行为和性能在不同 TiDB 版本中的演进如下: +> `AUTO_ID_CACHE 1` 的行为和性能在不同的 TiDB 版本中有所演变: > -> - v6.4.0 之前:每次 ID 分配需通过一个 TiKV 事务完成,会影响性能。 -> - v6.4.0 起:引入集中式分配服务,ID 分配转为内存操作,性能显著提升。 -> - v8.1.0 起:移除主节点退出时的自动 `forceRebase` 操作以实现快速重启。虽然故障恢复时可能产生额外非连续 ID,但可避免大量表使用 `AUTO_ID_CACHE 1` 时可能出现的写入阻塞。 +> - v6.4.0 之前,每次 ID 分配都需要一个 TiKV 事务,这会影响性能。 +> - 在 v6.4.0 中,TiDB 引入了中心化分配服务,将 ID 分配作为内存操作执行,显著提高了性能。 +> - 从 v8.1.0 开始,TiDB 在主节点退出时移除了自动 `forceRebase` 操作,以实现更快的重启。虽然这可能在故障转移期间导致额外的非连续 ID,但它可以防止当许多表使用 `AUTO_ID_CACHE 1` 时可能出现的写入阻塞。 -## 使用限制 +## 限制 -目前在 TiDB 中使用 `AUTO_INCREMENT` 有以下限制: +目前,在 TiDB 中使用 `AUTO_INCREMENT` 有以下限制: -- 对于 v6.6.0 及更早的 TiDB 版本,定义的列必须为主键或者索引前缀。 -- 只能定义在类型为整数、`FLOAT` 或 `DOUBLE` 的列上。 -- 不支持与列的默认值 `DEFAULT` 同时指定在同一列上。 -- 不支持使用 `ALTER TABLE` 来添加 `AUTO_INCREMENT` 属性,包括使用 `ALTER TABLE ... MODIFY/CHANGE COLUMN` 语法为已存在的列添加 `AUTO_INCREMENT` 属性,以及使用 `ALTER TABLE ... ADD COLUMN` 添加带有 `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` 属性,默认是不允许移除。 -- `ALTER TABLE` 需要 `FORCE` 选项来将 `AUTO_INCREMENT` 设置为较小的值。 -- 将 `AUTO_INCREMENT` 设置为小于 `MAX()` 的值会导致重复键,因为预先存在的值不会被跳过。 +- 对于 TiDB v6.6.0 及更早版本,定义的列必须是主键或索引前缀。 +- 必须定义在 `INTEGER`、`FLOAT` 或 `DOUBLE` 类型的列上。 +- 不能在同一列上同时指定 `DEFAULT` 列值。 +- 不能使用 `ALTER TABLE` 添加或修改带有 `AUTO_INCREMENT` 属性的列,包括使用 `ALTER TABLE ... MODIFY/CHANGE COLUMN` 为现有列添加 `AUTO_INCREMENT` 属性,或使用 `ALTER TABLE ... ADD COLUMN` 添加带有 `AUTO_INCREMENT` 属性的列。 +- 可以使用 `ALTER TABLE` 移除 `AUTO_INCREMENT` 属性。但是,从 v2.1.18 和 v3.0.4 开始,TiDB 使用会话变量 `@@tidb_allow_remove_auto_inc` 来控制是否可以使用 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 移除列的 `AUTO_INCREMENT` 属性。默认情况下,不能使用 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 移除 `AUTO_INCREMENT` 属性。 +- `ALTER TABLE` 需要 `FORCE` 选项才能将 `AUTO_INCREMENT` 值设置为较小的值。 +- 将 `AUTO_INCREMENT` 设置为小于 `MAX()` 的值会导致重复键,因为不会跳过已存在的值。 diff --git a/auto-random.md b/auto-random.md index bd9e6681524b..2ff2f29a22a2 100644 --- a/auto-random.md +++ b/auto-random.md @@ -1,23 +1,27 @@ --- title: AUTO_RANDOM -summary: 本文介绍了 TiDB 的 `AUTO_RANDOM` 列属性。 +summary: 了解 AUTO_RANDOM 属性。 --- -# AUTO_RANDOM 从 v3.1.0 版本开始引入 +# AUTO_RANDOM v3.1.0 新功能 ## 使用场景 -由于 `AUTO_RANDOM` 的值具有随机性和唯一性,因此 `AUTO_RANDOM` 通常用于代替 [`AUTO_INCREMENT`](/auto-increment.md),以避免 TiDB 分配连续的 ID 值造成单个存储节点的写热点问题。如果当前表的 `AUTO_INCREMENT` 列是主键列,且列类型为 `BIGINT`,可以通过 `ALTER TABLE t MODIFY COLUMN id BIGINT AUTO_RANDOM(5);` 从 `AUTO_INCREMENT` 切换成 `AUTO_RANDOM`。 +由于 `AUTO_RANDOM` 的值是随机且唯一的,`AUTO_RANDOM` 通常用于替代 [`AUTO_INCREMENT`](/auto-increment.md),以避免 TiDB 分配连续 ID 导致单个存储节点出现写入热点。如果当前 `AUTO_INCREMENT` 列是主键且类型为 `BIGINT`,你可以执行 `ALTER TABLE t MODIFY COLUMN id BIGINT AUTO_RANDOM(5);` 语句将其从 `AUTO_INCREMENT` 切换为 `AUTO_RANDOM`。 -关于如何在高并发写入场景下调优 TiDB,请参阅 [TiDB 高并发写入场景最佳实践](/best-practices/high-concurrency-best-practices.md)。 + -在 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 语句中的 `AUTO_RANDOM_BASE` 参数,也可以用来指定 `AUTO_RANDOM` 自增部分的初始值,该参数可以被认为属于内部接口的一部分,对于用户而言请忽略。 +有关如何在 TiDB 中处理高并发写入工作负载的更多信息,请参见[高并发写入最佳实践](/best-practices/high-concurrency-best-practices.md)。 + + + +[CREATE TABLE](/sql-statements/sql-statement-create-table.md) 语句中的 `AUTO_RANDOM_BASE` 参数用于设置 `auto_random` 的初始增量部分值。此选项可以视为内部接口的一部分。你可以忽略此参数。 ## 基本概念 -`AUTO_RANDOM` 是应用在 `BIGINT` 类型列的属性,用于列值的自动分配。其自动分配的值满足**随机性**和**唯一性**。 +`AUTO_RANDOM` 是一个用于自动为 `BIGINT` 列分配值的列属性。自动分配的值是**随机**且**唯一**的。 -以下语句均可创建包含 `AUTO_RANDOM` 列的表,其中 `AUTO_RANDOM` 列必须被包含在主键中,并且是主键的第一列。 +要创建带有 `AUTO_RANDOM` 列的表,你可以使用以下语句。`AUTO_RANDOM` 列必须包含在主键中,且 `AUTO_RANDOM` 列是主键中的第一列。 ```sql CREATE TABLE t (a BIGINT AUTO_RANDOM, b VARCHAR(255), PRIMARY KEY (a)); @@ -27,7 +31,7 @@ CREATE TABLE t (a BIGINT AUTO_RANDOM(5, 54), b VARCHAR(255), PRIMARY KEY (a)); CREATE TABLE t (a BIGINT AUTO_RANDOM(5, 54), b VARCHAR(255), PRIMARY KEY (a, b)); ``` -`AUTO_RANDOM` 关键字可以被包裹在 TiDB 可执行注释中,注释语法请参考 [TiDB 可执行注释](/comment-syntax.md#tidb-可执行的注释语法)。 +你可以将关键字 `AUTO_RANDOM` 包装在可执行注释中。有关更多详细信息,请参考 [TiDB 特定注释语法](/comment-syntax.md#tidb-specific-comment-syntax)。 ```sql CREATE TABLE t (a bigint /*T![auto_rand] AUTO_RANDOM */, b VARCHAR(255), PRIMARY KEY (a)); @@ -36,10 +40,10 @@ CREATE TABLE t (a BIGINT /*T![auto_rand] AUTO_RANDOM(6) */, b VARCHAR(255), PRIM CREATE TABLE t (a BIGINT /*T![auto_rand] AUTO_RANDOM(5, 54) */, b VARCHAR(255), PRIMARY KEY (a)); ``` -在用户执行 `INSERT` 语句时: +当你执行 `INSERT` 语句时: -- 如果语句中显式指定了 `AUTO_RANDOM` 列的值,则该值会被正常插入到表中。 -- 如果语句中没有显式指定 `AUTO_RANDOM` 列的值,TiDB 会自动生成一个随机的值插入到表中。 +- 如果你显式指定 `AUTO_RANDOM` 列的值,它将按原样插入表中。 +- 如果你未显式指定 `AUTO_RANDOM` 列的值,TiDB 将生成一个随机值并将其插入表中。 ```sql tidb> CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b VARCHAR(255)) /*T! PRE_SPLIT_REGIONS=2 */ ; @@ -96,54 +100,55 @@ tidb> SHOW TABLE t REGIONS; 4 rows in set (0.00 sec) ``` -TiDB 自动分配的 `AUTO_RANDOM(S, R)` 列值共有 64 位: +TiDB 自动分配的 `AUTO_RANDOM(S, R)` 列值总共有 64 位: -- `S` 表示分片位的数量,取值范围是 `1` 到 `15`。默认为 `5`。 -- `R` 表示自动分配值域的总长度,取值范围是 `32` 到 `64`。默认为 `64`。 +- `S` 是分片位数。值范围从 `1` 到 `15`。默认值为 `5`。 +- `R` 是自动分配范围的总长度。值范围从 `32` 到 `64`。默认值为 `64`。 -有符号位的 `AUTO_RANDOM` 列值的具体结构如下: +带有符号位的 `AUTO_RANDOM` 值的结构如下: -| 符号位 | 保留位 | 分片位 | 自增位 | -|--------|-------------|--------|--------------| -| 1 bit | `64-R` bits | `S` bits | `R-1-S` bits | +| 符号位 | 保留位 | 分片位 | 自增位 | +|---------|-------------|--------|--------------| +| 1 位 | `64-R` 位 | `S` 位 | `R-1-S` 位 | -无符号位的 `AUTO_RANDOM` 列值的具体结构如下: +不带符号位的 `AUTO_RANDOM` 值的结构如下: -| 保留位 | 分片位 | 自增位 | -|-------------|--------|------------| -| `64-R` bits | `S` bits | `R-S` bits | +| 保留位 | 分片位 | 自增位 | +|-------------|--------|--------------| +| `64-R` 位 | `S` 位 | `R-S` 位 | -- 是否有符号位取决于该列是否存在 `UNSIGNED` 属性。 -- 保留位的长度为 `64-R`,保留位的内容始终为 `0`。 -- 分片位的内容通过计算当前事务的开始时间的哈希值而得。要使用不同的分片位数量(例如 10),可以在建表时指定 `AUTO_RANDOM(10)`。 -- 自增位的值保存在存储引擎中,按顺序分配,每次分配完值后会自增 1。自增位保证了 `AUTO_RANDOM` 列值全局唯一。当自增位耗尽后,再次自动分配时会报 `Failed to read auto-increment value from storage engine` 的错误。 -- 关于取值范围:最终生成值包含的最大位数 = 分片位 + 自增位。有符号位的列的取值范围是 `[-(2^(R-1))+1, (2^(R-1))-1]`。无符号位的列的取值范围是 `[0, (2^R)-1]`。 -- `AUTO_RANDOM` 可以与 [`PRE_SPLIT_REGIONS`](/sql-statements/sql-statement-split-region.md#pre_split_regions) 结合使用,用来在建表成功后就开始将表中的数据预均匀切分 `2^(PRE_SPLIT_REGIONS)` 个 Region。 +- 值是否有符号位取决于相应列是否有 `UNSIGNED` 属性。 +- 符号位的长度由是否存在 `UNSIGNED` 属性决定。如果有 `UNSIGNED` 属性,长度为 `0`。否则,长度为 `1`。 +- 保留位的长度为 `64-R`。保留位始终为 `0`。 +- 分片位的内容是通过计算当前事务开始时间的哈希值获得的。要使用不同长度的分片位(例如 10),可以在创建表时指定 `AUTO_RANDOM(10)`。 +- 自增位的值存储在存储引擎中并按顺序分配。每次分配新值时,该值增加 1。自增位确保 `AUTO_RANDOM` 的值在全局范围内是唯一的。当自增位用尽时,再次分配值时会报错 `Failed to read auto-increment value from storage engine`。 +- 值范围:最终生成值的最大位数 = 分片位 + 自增位。有符号列的范围是 `[-(2^(R-1))+1, (2^(R-1))-1]`,无符号列的范围是 `[0, (2^R)-1]`。 +- 你可以将 `AUTO_RANDOM` 与 `PRE_SPLIT_REGIONS` 一起使用。当表创建成功时,`PRE_SPLIT_REGIONS` 会将表中的数据预先分割为 `2^(PRE_SPLIT_REGIONS)` 个 Region。 > **注意:** > -> 分片位长度 (`S`) 的选取: +> 分片位(`S`)的选择: > -> - 由于总位数固定为 64 位,分片位的数量会影响到自增位的数量:当分片位数增加时,自增位数会减少,反之亦然。因此,你需要权衡“自动分配值的随机性”以及“可用空间”。 -> - 最佳实践是将分片位设置为 `log(2, x)`,其中 `x` 为当前集群存储引擎的数量。例如,一个 TiDB 集群中存在 16 个 TiKV,分片位可以设置为 `log(2, 16)`,即 `4`。在所有 Region 被均匀调度到各个 TiKV 上以后,此时大批量写入的负载可被均匀分布到不同 TiKV 节点,以实现资源最大化利用。 +> - 由于总共有 64 个可用位,分片位长度会影响自增位长度。也就是说,随着分片位长度的增加,自增位长度会减少,反之亦然。因此,你需要平衡分配值的随机性和可用空间。 +> - 最佳实践是将分片位设置为 `log(2, x)`,其中 `x` 是当前存储引擎的数量。例如,如果 TiDB 集群中有 16 个 TiKV 节点,你可以将分片位设置为 `log(2, 16)`,即 `4`。在所有 Region 均匀调度到每个 TiKV 节点后,批量写入的负载可以均匀分布到不同的 TiKV 节点,以最大化资源利用率。 > -> 值域长度 (`R`) 的选取: +> 范围(`R`)的选择: > -> - 通常,在应用程序的数值类型无法表示完整的 64 位整数时需要设置 `R` 参数。 -> - 例如:JSON number 类型的取值范围为 `[-(2^53)+1, (2^53)-1]`,而 TiDB 很容易会为 `AUTO_RANDOM(5)` 的列分配超出该范围的整数,导致应用程序读取该列的值时出现异常。此时,对于有符号的列你可以用 `AUTO_RANDOM(5, 54)` 代替 `AUTO_RANDOM(5)`,无符号列可以用 `AUTO_RANDOM(5, 53)` 代替 `AUTO_RANDOM(5)`,这样使得 TiDB 不会分配出大于 `9007199254740991` (2^53-1) 的整数。 +> - 通常,当应用程序的数值类型无法表示完整的 64 位整数时,需要设置 `R` 参数。 +> - 例如,JSON 数字的范围是 `[-(2^53)+1, (2^53)-1]`。TiDB 可以轻松地为定义为 `AUTO_RANDOM(5)` 的列分配超出此范围的整数,导致应用程序读取该列时出现意外行为。在这种情况下,你可以将有符号列的 `AUTO_RANDOM(5)` 替换为 `AUTO_RANDOM(5, 54)`,将无符号列的 `AUTO_RANDOM(5)` 替换为 `AUTO_RANDOM(5, 53)`,确保 TiDB 不会为该列分配大于 `9007199254740991`(2^53-1)的整数。 -`AUTO RANDOM` 列隐式分配的值会影响 `last_insert_id()`。可以使用 `SELECT last_insert_id()` 获取上一次 TiDB 隐式分配的 ID。 +隐式分配给 `AUTO_RANDOM` 列的值会影响 `last_insert_id()`。要获取 TiDB 最后隐式分配的 ID,你可以使用 `SELECT last_insert_id ()` 语句。 -要查看某张含有 `AUTO_RANDOM` 属性的表的分片位数量,除了 `SHOW CREATE TABLE` 以外,还可以在系统表 `INFORMATION_SCHEMA.TABLES` 中 `TIDB_ROW_ID_SHARDING_INFO` 一列中查到模式为 `PK_AUTO_RANDOM_BITS=x` 的值,其中 `x` 为分片位的数量。 +要查看带有 `AUTO_RANDOM` 列的表的分片位数,你可以执行 `SHOW CREATE TABLE` 语句。你还可以在 `information_schema.tables` 系统表的 `TIDB_ROW_ID_SHARDING_INFO` 列中看到 `PK_AUTO_RANDOM_BITS=x` 模式的值。`x` 是分片位数。 -创建完一张含有 `AUTO_RANDOM` 属性的表后,可以使用 `SHOW WARNINGS` 查看当前表可支持的最大隐式分配的次数: +创建带有 `AUTO_RANDOM` 列的表后,你可以使用 `SHOW WARNINGS` 查看最大隐式分配次数: ```sql CREATE TABLE t (a BIGINT AUTO_RANDOM, b VARCHAR(255), PRIMARY KEY (a)); SHOW WARNINGS; ``` -输出结果如下: +输出如下: ```sql +-------+------+---------------------------------------------------------+ @@ -154,19 +159,19 @@ SHOW WARNINGS; 1 row in set (0.00 sec) ``` -## ID 隐式分配规则 +## ID 的隐式分配规则 -`AUTO_RANDOM` 列隐式分配的值和自增列类似,也遵循 session 变量 [`auto_increment_increment`](/system-variables.md#auto_increment_increment) 和 [`auto_increment_offset`](/system-variables.md#auto_increment_offset) 的控制,其中隐式分配值的自增位 (ID) 满足等式 `(ID - auto_increment_offset) % auto_increment_increment == 0`。 +TiDB 对 `AUTO_RANDOM` 列的隐式分配值与 `AUTO_INCREMENT` 列类似。它们也受会话级系统变量 [`auto_increment_increment`](/system-variables.md#auto_increment_increment) 和 [`auto_increment_offset`](/system-variables.md#auto_increment_offset) 的控制。隐式分配值的自增位(ID)符合方程 `(ID - auto_increment_offset) % auto_increment_increment == 0`。 -## 使用限制 +## 限制 -目前在 TiDB 中使用 `AUTO_RANDOM` 有以下限制: +使用 `AUTO_RANDOM` 时请注意以下限制: -- 要使用显式插入的功能,需要将系统变量 `@@allow_auto_random_explicit_insert` 的值设置为 `1`(默认值为 `0`)。不建议自行显式指定含有 `AUTO_RANDOM` 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。 -- 该属性必须指定在 `BIGINT` 类型的主键列上,否则会报错。此外,当主键属性为 `NONCLUSTERED` 时,即使是整型主键列,也不支持使用 `AUTO_RANDOM`。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 -- 不支持使用 `ALTER TABLE` 来修改 `AUTO_RANDOM` 属性,包括添加或移除该属性。 -- 支持将 `AUTO_INCREMENT` 属性改为 `AUTO_RANDOM` 属性。但在 `AUTO_INCREMENT` 的列数据最大值已接近 `BIGINT` 类型最大值的情况下,修改可能会失败。 -- 不支持修改含有 `AUTO_RANDOM` 属性的主键列的列类型。 -- 不支持与 `AUTO_INCREMENT` 同时指定在同一列上。 -- 不支持与列的默认值 `DEFAULT` 同时指定在同一列上。 -- `AUTO_RANDOM` 列的数据很难迁移到 `AUTO_INCREMENT` 列上,因为 `AUTO_RANDOM` 列自动分配的值通常都很大。 +- 要显式插入值,你需要将 `@@allow_auto_random_explicit_insert` 系统变量的值设置为 `1`(默认为 `0`)。**不建议**在插入数据时显式指定具有 `AUTO_RANDOM` 属性的列的值。否则,此表可自动分配的数值可能会提前用尽。 +- 仅为 `BIGINT` 类型的主键列指定此属性。否则,会出现错误。此外,当主键的属性为 `NONCLUSTERED` 时,即使在整数主键上也不支持 `AUTO_RANDOM`。有关 `CLUSTERED` 类型的主键的更多详细信息,请参考[聚簇索引](/clustered-indexes.md)。 +- 你不能使用 `ALTER TABLE` 修改 `AUTO_RANDOM` 属性,包括添加或删除此属性。 +- 如果最大值接近列类型的最大值,则不能使用 `ALTER TABLE` 从 `AUTO_INCREMENT` 更改为 `AUTO_RANDOM`。 +- 你不能更改指定了 `AUTO_RANDOM` 属性的主键列的列类型。 +- 你不能同时为同一列指定 `AUTO_RANDOM` 和 `AUTO_INCREMENT`。 +- 你不能同时为同一列指定 `AUTO_RANDOM` 和 `DEFAULT`(列的默认值)。 +- 当在列上使用 `AUTO_RANDOM` 时,很难将列属性改回 `AUTO_INCREMENT`,因为自动生成的值可能会很大。 diff --git a/basic-sql-operations.md b/basic-sql-operations.md index 00f35a781c7f..f8d79b30f617 100644 --- a/basic-sql-operations.md +++ b/basic-sql-operations.md @@ -1,33 +1,39 @@ --- -title: SQL 基本操作 -summary: TiDB 是一个兼容 MySQL 的数据库,可以执行 DDL、DML、DQL 和 DCL 操作。可以使用 SHOW DATABASES 查看数据库列表,使用 CREATE DATABASE 创建数据库,使用 DROP DATABASE 删除数据库。使用 CREATE TABLE 创建表,使用 SHOW CREATE TABLE 查看建表语句,使用 DROP TABLE 删除表。使用 CREATE INDEX 创建索引,使用 SHOW INDEX 查看表内所有索引,使用 DROP INDEX 删除索引。使用 INSERT 向表内插入记录,使用 UPDATE 修改记录,使用 DELETE 删除记录。使用 SELECT 检索表内数据,使用 WHERE 子句进行筛选。使用 CREATE USER 创建用户,使用 GRANT 授权用户,使用 DROP USER 删除用户。 +title: 使用 TiDB 探索 SQL +summary: 了解 TiDB 数据库的基本 SQL 语句。 --- -# SQL 基本操作 +# 使用 TiDB 探索 SQL -成功部署 TiDB 集群之后,便可以在 TiDB 中执行 SQL 语句了。因为 TiDB 兼容 MySQL,你可以使用 MySQL 客户端连接 TiDB,并且[大多数情况下](/mysql-compatibility.md)可以直接执行 MySQL 语句。 +TiDB 与 MySQL 兼容,在大多数情况下您可以直接使用 MySQL 语句。有关不支持的功能,请参阅[与 MySQL 的兼容性](/mysql-compatibility.md#unsupported-features)。 -SQL 是一门声明性语言,它是数据库用户与数据库交互的方式。它更像是一种自然语言,好像在用英语与数据库进行对话。本文档介绍基本的 SQL 操作。完整的 TiDB SQL 语句列表,参见 [SQL 语句概览](/sql-statements/sql-statement-overview.md)。 + + +要试验 SQL 并测试 TiDB 与 MySQL 查询的兼容性,您可以尝试使用 [TiDB Playground](https://play.tidbcloud.com/?utm_source=docs&utm_medium=basic-sql-operations)。您也可以先部署一个 TiDB 集群,然后在其中运行 SQL 语句。 + + + +本页将指导您了解基本的 TiDB SQL 语句,如 DDL、DML 和 CRUD 操作。有关 TiDB 语句的完整列表,请参阅 [SQL 语句概览](/sql-statements/sql-statement-overview.md)。 ## 分类 -SQL 语言通常按照功能划分成以下的 4 个部分: +SQL 根据其功能分为以下 4 种类型: -- DDL (Data Definition Language):数据定义语言,用来定义数据库对象,包括库、表、视图和索引等。 +- DDL(数据定义语言):用于定义数据库对象,包括数据库、表、视图和索引。 -- DML (Data Manipulation Language):数据操作语言,用来操作和业务相关的记录。 +- DML(数据操作语言):用于操作应用程序相关的记录。 -- DQL (Data Query Language):数据查询语言,用来查询经过条件筛选的记录。 +- DQL(数据查询语言):用于在条件过滤后查询记录。 -- DCL (Data Control Language):数据控制语言,用来定义访问权限和安全级别。 +- DCL(数据控制语言):用于定义访问权限和安全级别。 -常用的 DDL 功能是对象(如表、索引等)的创建、属性修改和删除,对应的命令分别是 CREATE、ALTER 和 DROP。 +常见的 DDL 功能是创建、修改和删除对象(如表和索引)。相应的命令是 `CREATE`、`ALTER` 和 `DROP`。 -## 查看、创建和删除数据库 +## 显示、创建和删除数据库 -TiDB 语境中的 Database 或者说数据库,可以认为是表和索引等对象的集合。 +TiDB 中的数据库可以被视为表和索引等对象的集合。 -使用 `SHOW DATABASES` 语句查看系统中数据库列表: +要显示数据库列表,使用 `SHOW DATABASES` 语句: {{< copyable "sql" >}} @@ -35,7 +41,7 @@ TiDB 语境中的 Database 或者说数据库,可以认为是表和索引等 SHOW DATABASES; ``` -使用名为 `mysql` 的数据库: +要使用名为 `mysql` 的数据库,使用以下语句: {{< copyable "sql" >}} @@ -43,7 +49,7 @@ SHOW DATABASES; USE mysql; ``` -使用 `SHOW TABLES` 语句查看数据库中的所有表。例如: +要显示数据库中的所有表,使用 `SHOW TABLES` 语句: {{< copyable "sql" >}} @@ -51,7 +57,7 @@ USE mysql; SHOW TABLES FROM mysql; ``` -使用 `CREATE DATABASE` 语句创建数据库。语法如下: +要创建数据库,使用 `CREATE DATABASE` 语句: {{< copyable "sql" >}} @@ -59,7 +65,7 @@ SHOW TABLES FROM mysql; CREATE DATABASE db_name [options]; ``` -例如,要创建一个名为 `samp_db` 的数据库,可使用以下语句: +要创建名为 `samp_db` 的数据库,使用以下语句: {{< copyable "sql" >}} @@ -67,9 +73,9 @@ CREATE DATABASE db_name [options]; CREATE DATABASE IF NOT EXISTS samp_db; ``` -添加 `IF NOT EXISTS` 可防止发生错误。 +添加 `IF NOT EXISTS` 可以防止在数据库已存在时出现错误。 -使用 `DROP DATABASE` 语句删除数据库。例如: +要删除数据库,使用 `DROP DATABASE` 语句: {{< copyable "sql" >}} @@ -77,9 +83,9 @@ CREATE DATABASE IF NOT EXISTS samp_db; DROP DATABASE samp_db; ``` -## 创建、查看和删除表 +## 创建、显示和删除表 -使用 `CREATE TABLE` 语句创建表。语法如下: +要创建表,使用 `CREATE TABLE` 语句: {{< copyable "sql" >}} @@ -87,7 +93,7 @@ DROP DATABASE samp_db; CREATE TABLE table_name column_name data_type constraint; ``` -例如,要创建一个名为 `person` 的表,包括编号、名字、生日等字段,可使用以下语句: +例如,要创建一个名为 `person` 的表,其中包括编号、姓名和生日等字段,使用以下语句: {{< copyable "sql" >}} @@ -99,15 +105,15 @@ CREATE TABLE person ( ); ``` -使用 `SHOW CREATE` 语句查看建表语句,即 DDL。例如: +要查看创建表的语句(DDL),使用 `SHOW CREATE` 语句: {{< copyable "sql" >}} ```sql -SHOW CREATE TABLE person; +SHOW CREATE table person; ``` -使用 `DROP TABLE` 语句删除表。例如: +要删除表,使用 `DROP TABLE` 语句: {{< copyable "sql" >}} @@ -115,9 +121,9 @@ SHOW CREATE TABLE person; DROP TABLE person; ``` -## 创建、查看和删除索引 +## 创建、显示和删除索引 -索引通常用于加速索引列上的查询。对于值不唯一的列,可使用 `CREATE INDEX` 或 `ALTER TABLE` 语句创建普通索引。例如: +索引用于加快对索引列的查询。要为值不唯一的列创建索引,使用 `CREATE INDEX` 语句: {{< copyable "sql" >}} @@ -125,7 +131,7 @@ DROP TABLE person; CREATE INDEX person_id ON person (id); ``` -或者: +或使用 `ALTER TABLE` 语句: {{< copyable "sql" >}} @@ -133,7 +139,7 @@ CREATE INDEX person_id ON person (id); ALTER TABLE person ADD INDEX person_id (id); ``` -对于值唯一的列,可以创建唯一索引。例如: +要为值唯一的列创建唯一索引,使用 `CREATE UNIQUE INDEX` 语句: {{< copyable "sql" >}} @@ -141,7 +147,7 @@ ALTER TABLE person ADD INDEX person_id (id); CREATE UNIQUE INDEX person_unique_id ON person (id); ``` -或者: +或使用 `ALTER TABLE` 语句: {{< copyable "sql" >}} @@ -149,7 +155,7 @@ CREATE UNIQUE INDEX person_unique_id ON person (id); ALTER TABLE person ADD UNIQUE person_unique_id (id); ``` -使用 `SHOW INDEX` 语句查看表内所有索引: +要显示表中的所有索引,使用 `SHOW INDEX` 语句: {{< copyable "sql" >}} @@ -157,7 +163,7 @@ ALTER TABLE person ADD UNIQUE person_unique_id (id); SHOW INDEX FROM person; ``` -使用 `ALTER TABLE` 或 `DROP INDEX` 语句来删除索引。与 `CREATE INDEX` 语句类似,`DROP INDEX` 也可以嵌入 `ALTER TABLE` 语句。例如: +要删除索引,使用 `DROP INDEX` 或 `ALTER TABLE` 语句。`DROP INDEX` 可以嵌套在 `ALTER TABLE` 中: {{< copyable "sql" >}} @@ -171,13 +177,15 @@ DROP INDEX person_id ON person; ALTER TABLE person DROP INDEX person_unique_id; ``` -注意:DDL 操作不是事务,在执行 DDL 时,不需要对应 COMMIT 语句。 +> **注意:** +> +> DDL 操作不是事务。执行 DDL 操作时不需要运行 `COMMIT` 语句。 -常用的 DML 功能是对表记录的新增、修改和删除,对应的命令分别是 INSERT、UPDATE 和 DELETE。 +## 插入、更新和删除数据 -## 记录的增删改 +常见的 DML 功能是添加、修改和删除表记录。相应的命令是 `INSERT`、`UPDATE` 和 `DELETE`。 -使用 `INSERT` 语句向表内插入表记录。例如: +要向表中插入数据,使用 `INSERT` 语句: {{< copyable "sql" >}} @@ -185,7 +193,7 @@ ALTER TABLE person DROP INDEX person_unique_id; INSERT INTO person VALUES(1,'tom','20170912'); ``` -使用 `INSERT` 语句向表内插入包含部分字段数据的表记录。例如: +要向表中插入包含某些字段数据的记录,使用 `INSERT` 语句: {{< copyable "sql" >}} @@ -193,7 +201,7 @@ INSERT INTO person VALUES(1,'tom','20170912'); INSERT INTO person(id,name) VALUES('2','bob'); ``` -使用 `UPDATE` 语句向表内修改表记录的部分字段数据。例如: +要更新表中记录的某些字段,使用 `UPDATE` 语句: {{< copyable "sql" >}} @@ -201,7 +209,7 @@ INSERT INTO person(id,name) VALUES('2','bob'); UPDATE person SET birthday='20180808' WHERE id=2; ``` -使用 `DELETE` 语句向表内删除部分表记录。例如: +要删除表中的数据,使用 `DELETE` 语句: {{< copyable "sql" >}} @@ -209,13 +217,15 @@ UPDATE person SET birthday='20180808' WHERE id=2; DELETE FROM person WHERE id=2; ``` -注意:UPDATE 和 DELETE 操作如果不带 WHERE 过滤条件是对全表进行操作。 - -DQL 数据查询语言是从一个表或多个表中检索出想要的数据行,通常是业务开发的核心内容。 +> **注意:** +> +> 没有 `WHERE` 子句作为过滤器的 `UPDATE` 和 `DELETE` 语句会对整个表进行操作。 ## 查询数据 -使用 `SELECT` 语句检索表内数据。例如: +DQL 用于从一个或多个表中检索所需的数据行。 + +要查看表中的数据,使用 `SELECT` 语句: {{< copyable "sql" >}} @@ -223,7 +233,7 @@ DQL 数据查询语言是从一个表或多个表中检索出想要的数据行 SELECT * FROM person; ``` -在 SELECT 后面加上要查询的列名。例如: +要查询特定列,在 `SELECT` 关键字后添加列名: {{< copyable "sql" >}} @@ -240,19 +250,19 @@ SELECT name FROM person; 1 rows in set (0.00 sec) ``` -使用 WHERE 子句,对所有记录进行是否符合条件的筛选后再返回。例如: +使用 `WHERE` 子句过滤所有匹配条件的记录,然后返回结果: {{< copyable "sql" >}} ```sql -SELECT * FROM person WHERE id<5; +SELECT * FROM person where id<5; ``` -常用的 DCL 功能是创建或删除用户,和对用户权限的管理。 - ## 创建、授权和删除用户 -使用 `CREATE USER` 语句创建一个用户 `tiuser`,密码为 `123456`: +DCL 通常用于创建或删除用户,以及管理用户权限。 + +要创建用户,使用 `CREATE USER` 语句。以下示例创建一个名为 `tiuser`,密码为 `123456` 的用户: {{< copyable "sql" >}} @@ -260,7 +270,7 @@ SELECT * FROM person WHERE id<5; CREATE USER 'tiuser'@'localhost' IDENTIFIED BY '123456'; ``` -授权用户 `tiuser` 可检索数据库 `samp_db` 内的表: +要授予 `tiuser` 检索 `samp_db` 数据库中表的权限: {{< copyable "sql" >}} @@ -268,7 +278,7 @@ CREATE USER 'tiuser'@'localhost' IDENTIFIED BY '123456'; GRANT SELECT ON samp_db.* TO 'tiuser'@'localhost'; ``` -查询用户 `tiuser` 的权限: +要检查 `tiuser` 的权限: {{< copyable "sql" >}} @@ -276,7 +286,7 @@ GRANT SELECT ON samp_db.* TO 'tiuser'@'localhost'; SHOW GRANTS for tiuser@localhost; ``` -删除用户 `tiuser`: +要删除 `tiuser`: {{< copyable "sql" >}} diff --git a/best-practices/uuid.md b/best-practices/uuid.md index ab4bd2e15984..3fe61a19251e 100644 --- a/best-practices/uuid.md +++ b/best-practices/uuid.md @@ -1,33 +1,55 @@ --- title: UUID 最佳实践 -summary: 了解在 TiDB 中使用 UUID 的最佳实践和策略。 +summary: UUID 作为主键时具有以下优势:减少网络往返、支持大多数编程语言和数据库、防止枚举攻击。建议将 UUID 以二进制形式存储在 `BINARY(16)` 列中。同时建议在 TiDB 中不要设置 `swap_flag` 以防止热点。MySQL 也支持 UUID。 --- # UUID 最佳实践 ## UUID 概述 -通用唯一标识符 (UUID) 用作主键而不是 [`AUTO_INCREMENT`](/auto-increment.md) 整数值时,可以提供以下好处: +与使用 [`AUTO_INCREMENT`](/auto-increment.md) 整数值相比,使用通用唯一标识符(UUID)作为主键具有以下优势: -- UUID 可以在多个系统生成,而不会产生冲突。某些情况下可以减少到 TiDB 的网络往返次数,从而提高性能。 -- 绝大多数编程语言和数据库系统都支持 UUID。 -- 用在 URL 中时,UUID 不容易被枚举攻击。相比之下,使用 `AUTO_INCREMENT` 数字,则很容易让发票 ID 或用户 ID 被猜出。 +- UUID 可以在多个系统上生成而不会发生冲突。在某些情况下,这意味着可以减少与 TiDB 的网络往返次数,从而提高性能。 +- 大多数编程语言和数据库系统都支持 UUID。 +- 当作为 URL 的一部分使用时,UUID 不容易受到枚举攻击。相比之下,使用 `AUTO_INCREMENT` 数字时,可能会被猜测到发票 ID 或用户 ID。 ## 最佳实践 -### 二进制存储 +### 以二进制形式存储 -UUID 文本是一个包含 36 字符的字符串,如 `ab06f63e-8fe7-11ec-a514-5405db7aad56`。使用 [`UUID_TO_BIN()`](/functions-and-operators/miscellaneous-functions.md#uuid_to_bin) 可将 UUID 文本格式转换为 16 字节的二进制格式。这样,你可以将文本存储在 [`BINARY(16)`](/data-type-string.md#binary-类型) 列中。检索 UUID 时,可以使用 [`BIN_TO_UUID()`](/functions-and-operators/miscellaneous-functions.md#bin_to_uuid) 函数再将其转换回文本格式。 +文本形式的 UUID 格式如下:`ab06f63e-8fe7-11ec-a514-5405db7aad56`,这是一个 36 个字符的字符串。通过使用 [`UUID_TO_BIN()`](/functions-and-operators/miscellaneous-functions.md#uuid_to_bin),可以将文本格式转换为 16 字节的二进制格式。这样你就可以将文本存储在 [`BINARY(16)`](/data-type-string.md#binary-type) 列中。在检索 UUID 时,你可以使用 [`BIN_TO_UUID()`](/functions-and-operators/miscellaneous-functions.md#bin_to_uuid) 函数将其转换回文本格式。 ### UUID 格式二进制顺序和聚簇主键 -`UUID_TO_BIN()` 函数可以接收一个参数 (UUID) 或两个参数(第一个为 UUID,第二个为 `swap_flag`)。建议不要在 TiDB 中设置 `swap_flag`,以避免出现[热点](/best-practices/high-concurrency-best-practices.md)问题。 +`UUID_TO_BIN()` 函数可以使用一个参数(UUID)或两个参数(第二个参数是 `swap_flag`)。 -同时,你也可以在 UUID 主键上显式设置 [`CLUSTERED` 选项](/clustered-indexes.md)来避免热点问题。 + -为了演示 `swap_flag` 的效果,本文以表结构相同的两张表为例。区别在于,`uuid_demo_1` 表中插入的数据使用 `UUID_TO_BIN(?, 0)`,而 `uuid_demo_2` 表中使用 `UUID_TO_BIN(?, 1)`。 +建议在 TiDB 中不要设置 `swap_flag`,以避免[热点问题](/best-practices/high-concurrency-best-practices.md)。 -在如下的[流量可视化页面](/dashboard/dashboard-key-visualizer.md),你可以看到写入操作集中在 `uuid_demo_2` 表的单个 Region 中,而这个表中的二进制格式字段顺序被调换过。 + + + + +建议在 TiDB 中不要设置 `swap_flag`,以避免热点问题。 + + + +你还可以为基于 UUID 的主键显式设置 [`CLUSTERED` 选项](/clustered-indexes.md),以避免热点。 + +为了演示 `swap_flag` 的效果,这里有两个结构相同的表。区别在于插入到 `uuid_demo_1` 的数据使用 `UUID_TO_BIN(?, 0)`,而 `uuid_demo_2` 使用 `UUID_TO_BIN(?, 1)`。 + + + +在下面的 [Key Visualizer](/dashboard/dashboard-key-visualizer.md) 截图中,你可以看到写入集中在 `uuid_demo_2` 表的单个区域,这个表在二进制格式中交换了字段的顺序。 + + + + + +在下面的 [Key Visualizer](/tidb-cloud/tune-performance.md#key-visualizer) 截图中,你可以看到写入集中在 `uuid_demo_2` 表的单个区域,这个表在二进制格式中交换了字段的顺序。 + + ![Key Visualizer](/media/best-practices/uuid_keyviz.png) @@ -47,6 +69,6 @@ CREATE TABLE `uuid_demo_2` ( ) ``` -## 与 MySQL 兼容性 +## MySQL 兼容性 -UUID 也可以在 MySQL 中使用。MySQL 8.0 引入了 `BIN_TO_UUID()` 和 `UUID_TO_BIN()` 函数。`UUID()` 函数在较早的 MySQL 版本中也可以使用。 +MySQL 也可以使用 UUID。`BIN_TO_UUID()` 和 `UUID_TO_BIN()` 函数是在 MySQL 8.0 中引入的。`UUID()` 函数在早期的 MySQL 版本中也可用。 diff --git a/blocklist-control-plan.md b/blocklist-control-plan.md index b8a7de827137..3aa9b263f102 100644 --- a/blocklist-control-plan.md +++ b/blocklist-control-plan.md @@ -1,44 +1,44 @@ --- -title: 优化规则与表达式下推的黑名单 -summary: 了解优化规则与表达式下推的黑名单。 +title: 优化规则和表达式下推的黑名单 +summary: 了解如何使用黑名单来控制优化规则和表达式下推的行为。 --- -# 优化规则与表达式下推的黑名单 +# 优化规则和表达式下推的黑名单 -本文主要介绍优化规则的黑名单与表达式下推的黑名单。 +本文档介绍如何使用优化规则黑名单和表达式下推黑名单来控制 TiDB 的行为。 ## 优化规则黑名单 -**优化规则黑名单**是针对优化规则的调优手段之一,主要用于手动禁用一些优化规则。 +优化规则黑名单是调整优化规则的一种方式,主要用于手动禁用某些优化规则。 ### 重要的优化规则 -|**优化规则**|**规则名称**|**简介**| +|**优化规则**|**规则名称**|**描述**| | :--- | :--- | :--- | -| 列裁剪 | column_prune | 对于上层算子不需要的列,不在下层算子输出该列,减少计算 | -| 子查询去关联 | decorrelate | 尝试对相关子查询进行改写,将其转换为普通 join 或 aggregation 计算 | -| 聚合消除 | 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 确定连接顺序 | -| 从窗口函数中推导 TopN 或 Limit | derive_topn_from_window | 从窗口函数中推导出 TopN 或者 Limit | +| 列剪裁 | column_prune | 如果上层执行器不需要某列,则该操作符会将其剪裁掉。 | +| 子查询去相关 | decorrelate | 尝试将相关子查询重写为非相关连接或聚合。 | +| 聚合消除 | aggregation_eliminate | 尝试从执行计划中移除不必要的聚合操作符。 | +| 投影消除 | projection_eliminate | 从执行计划中移除不必要的投影操作符。 | +| 最大/最小值消除 | max_min_eliminate | 将聚合中的某些 max/min 函数重写为 `order by` + `limit 1` 形式。 | +| 谓词下推 | predicate_push_down | 尝试将谓词下推到更接近数据源的操作符。 | +| 外连接消除 | outer_join_eliminate | 尝试从执行计划中移除不必要的左连接或右连接。 | +| 分区裁剪 | partition_processor | 裁剪被谓词拒绝的分区,并将分区表查询重写为 `UnionAll + Partition Datasource` 形式。 | +| 聚合下推 | aggregation_push_down | 尝试将聚合下推到其子节点。 | +| TopN 下推 | topn_push_down | 尝试将 TopN 操作符下推到更接近数据源的位置。 | +| 连接重排序 | join_reorder | 决定多表连接的顺序。 | +| 从窗口函数推导 TopN 或 Limit | derive_topn_from_window | 从窗口函数推导出 TopN 或 Limit 操作符。 | ### 禁用优化规则 -当某些优化规则在一些特殊查询中的优化结果不理想时,可以使用**优化规则黑名单**禁用一些优化规则。 +如果某些规则导致特定查询的执行计划不够优化,你可以使用优化规则黑名单来禁用这些规则。 #### 使用方法 > **注意:** > -> 以下操作都需要数据库的 super privilege 权限。每个优化规则都有各自的名字,比如列裁剪的名字是 "column_prune"。所有优化规则的名字都可以在[重要的优化规则](#重要的优化规则)表格中第二列查到。 +> 以下所有操作都需要数据库的 `super privilege` 权限。每个优化规则都有一个名称。例如,列剪裁的名称是 `column_prune`。所有优化规则的名称可以在[重要的优化规则](#重要的优化规则)表的第二列中找到。 -- 如果你想禁用某些规则,可以在 `mysql.opt_rule_blacklist` 表中写入规则的名字,例如: +- 如果你想禁用某些规则,将其名称写入 `mysql.opt_rule_blacklist` 表。例如: {{< copyable "sql" >}} @@ -46,40 +46,45 @@ summary: 了解优化规则与表达式下推的黑名单。 INSERT INTO mysql.opt_rule_blacklist VALUES("join_reorder"), ("topn_push_down"); ``` - 执行以下 SQL 语句可让禁用规则立即生效,包括相应 TiDB Server 的所有旧链接: + 执行以下 SQL 语句可以使上述操作立即生效。生效范围包括相应 TiDB 服务器的所有旧连接: {{< copyable "sql" >}} ```sql - ADMIN reload opt_rule_blacklist; + admin reload opt_rule_blacklist; ``` > **注意:** > - > `admin reload opt_rule_blacklist` 只对执行该 SQL 语句的 TiDB server 生效。若需要集群中所有 TiDB server 生效,需要在每台 TiDB server 上执行该 SQL 语句。 + > `admin reload opt_rule_blacklist` 只对运行该语句的 TiDB 服务器生效。如果你想让集群中的所有 TiDB 服务器都生效,需要在每个 TiDB 服务器上运行此命令。 -- 需要解除一条规则的禁用时,需要删除表中禁用该条规则的相应数据,再执行 `admin reload`: +- 如果你想重新启用某个规则,删除表中相应的数据,然后运行 `admin reload` 语句: {{< copyable "sql" >}} ```sql DELETE FROM mysql.opt_rule_blacklist WHERE name IN ("join_reorder", "topn_push_down"); + ``` + + {{< copyable "sql" >}} + + ```sql admin reload opt_rule_blacklist; ``` ## 表达式下推黑名单 -**表达式下推黑名单**是针对表达式下推的调优手段之一,主要用于对于某些存储类型手动禁用一些表达式。 +表达式下推黑名单是调整表达式下推的一种方式,主要用于手动禁用某些特定数据类型的表达式。 -### 已支持下推的表达式 +### 支持下推的表达式 -目前已经支持下推的表达式信息,请参考[表达式列表](/functions-and-operators/expressions-pushed-down.md#已支持下推的表达式列表)。 +关于支持下推的表达式的更多信息,请参见[支持下推到 TiKV 的表达式](/functions-and-operators/expressions-pushed-down.md#支持下推到-tikv-的表达式)。 -### 禁止特定表达式下推 +### 禁用特定表达式的下推 -当函数的计算过程由于下推而出现异常时,可通过黑名单功能禁止其下推来快速恢复业务。具体而言,你可以将上述支持的函数或运算符名加入黑名单 `mysql.expr_pushdown_blacklist` 中,以禁止特定表达式下推。 +当由于表达式下推导致结果错误时,你可以使用黑名单来快速恢复应用程序。具体来说,你可以将一些支持的函数或运算符添加到 `mysql.expr_pushdown_blacklist` 表中,以禁用特定表达式的下推。 -`mysql.expr_pushdown_blacklist` 的 schema 如下: +`mysql.expr_pushdown_blacklist` 的表结构如下: {{< copyable "sql" >}} @@ -98,44 +103,46 @@ DESC mysql.expr_pushdown_blacklist; 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`:用于记录该函数被加入黑名单的原因。 ++ `name`:禁止下推的函数名称。 ++ `store_type`:指定要阻止函数下推到哪个组件进行计算。可用的组件有 `tidb`、`tikv` 和 `tiflash`。`store_type` 不区分大小写。如果需要指定多个组件,使用逗号分隔每个组件。 + - 当 `store_type` 为 `tidb` 时,表示在读取 TiDB 内存表时该函数是否可以在其他 TiDB 服务器中执行。 + - 当 `store_type` 为 `tikv` 时,表示该函数是否可以在 TiKV 服务器的 Coprocessor 组件中执行。 + - 当 `store_type` 为 `tiflash` 时,表示该函数是否可以在 TiFlash 服务器的 Coprocessor 组件中执行。 ++ `reason`:记录将此函数添加到黑名单的原因。 ### 使用方法 -#### 加入黑名单 +本节描述如何使用表达式下推黑名单。 + +#### 添加到黑名单 -如果要将一个或多个函数或运算符加入黑名单,执行以下步骤: +要将一个或多个表达式(函数或运算符)添加到黑名单,请执行以下步骤: -1. 向 `mysql.expr_pushdown_blacklist` 插入对应的函数名或运算符名以及希望禁止下推的存储引擎集合。 +1. 将相应的函数名称或运算符名称,以及你想禁用下推的组件集合,插入到 `mysql.expr_pushdown_blacklist` 表中。 -2. 执行 `admin reload expr_pushdown_blacklist;`。 +2. 执行 `admin reload expr_pushdown_blacklist`。 -#### 移出黑名单 +### 从黑名单中移除 -如果要将一个或多个函数及运算符移出黑名单,执行以下步骤: +要从黑名单中移除一个或多个表达式,请执行以下步骤: -1. 从 `mysql.expr_pushdown_blacklist` 表中删除对应的函数名或运算符名。 +1. 从 `mysql.expr_pushdown_blacklist` 表中删除相应的函数名称或运算符名称,以及你想禁用下推的组件集合。 -2. 执行 `admin reload expr_pushdown_blacklist;`。 +2. 执行 `admin reload expr_pushdown_blacklist`。 > **注意:** > -> `admin reload expr_pushdown_blacklist` 只对执行该 SQL 语句的 TiDB server 生效。若需要集群中所有 TiDB server 生效,需要在每台 TiDB server 上执行该 SQL 语句。 +> `admin reload expr_pushdown_blacklist` 只对运行该语句的 TiDB 服务器生效。如果你想让集群中的所有 TiDB 服务器都生效,需要在每个 TiDB 服务器上运行此命令。 -### 表达式黑名单用法示例 +## 表达式黑名单使用示例 -以下示例首先将运算符 `<` 及 `>` 加入黑名单,然后将运算符 `>` 从黑名单中移出。 +在以下示例中,将 `<` 和 `>` 运算符添加到黑名单,然后将 `>` 运算符从黑名单中移除。 -黑名单是否生效可以从 `explain` 结果中进行观察(参见 [TiDB 执行计划概览](/explain-overview.md))。 +要判断黑名单是否生效,请观察 `EXPLAIN` 的结果(参见 [TiDB 执行计划概览](/explain-overview.md))。 -1. 对于以下 SQL 语句,`where` 条件中的 `a < 2` 和 `a > 2` 可以下推到 TiKV 进行计算。 +1. 以下 SQL 语句中 `WHERE` 子句中的谓词 `a < 2` 和 `a > 2` 可以下推到 TiKV。 {{< copyable "sql" >}} @@ -154,7 +161,7 @@ DESC mysql.expr_pushdown_blacklist; 3 rows in set (0.00 sec) ``` -2. 往 `mysql.expr_pushdown_blacklist` 表中插入禁用表达式,并且执行 `admin reload expr_pushdown_blacklist`。 +2. 将表达式插入到 `mysql.expr_pushdown_blacklist` 表并执行 `admin reload expr_pushdown_blacklist`。 {{< copyable "sql" >}} @@ -170,14 +177,14 @@ DESC mysql.expr_pushdown_blacklist; {{< copyable "sql" >}} ```sql - ADMIN reload expr_pushdown_blacklist; + admin reload expr_pushdown_blacklist; ``` ```sql Query OK, 0 rows affected (0.00 sec) ``` -3. 重新观察执行计划,发现表达式下推黑名单生效,`where` 条件中的 `<` 和 `>` 没有被下推到 TiKV Coprocessor 上。 +3. 再次观察执行计划,你会发现 `<` 和 `>` 运算符都没有下推到 TiKV Coprocessor。 {{< copyable "sql" >}} @@ -196,7 +203,7 @@ DESC mysql.expr_pushdown_blacklist; 3 rows in set (0.00 sec) ``` -4. 将某一表达式(`>` 大于)禁用规则从黑名单表中删除,并且执行 `admin reload expr_pushdown_blacklist`。 +4. 从黑名单中移除一个表达式(这里是 `>`)并执行 `admin reload expr_pushdown_blacklist`。 {{< copyable "sql" >}} @@ -211,14 +218,14 @@ DESC mysql.expr_pushdown_blacklist; {{< copyable "sql" >}} ```sql - ADMIN reload expr_pushdown_blacklist; + admin reload expr_pushdown_blacklist; ``` ```sql Query OK, 0 rows affected (0.00 sec) ``` -5. 重新观察执行计划,可以看到只有 `>` 表达式被重新下推到 TiKV Coprocessor,`<` 表达式仍然被禁用下推。 +5. 再次观察执行计划,你会发现 `<` 没有下推,而 `>` 下推到了 TiKV Coprocessor。 {{< copyable "sql" >}} diff --git a/cached-tables.md b/cached-tables.md index f46972248707..fcf80a3b54da 100644 --- a/cached-tables.md +++ b/cached-tables.md @@ -1,37 +1,37 @@ --- title: 缓存表 -summary: 了解 TiDB 中的缓存表功能,用于很少被修改的热点小表,提升读性能。 +summary: 了解 TiDB 中的缓存表功能,该功能用于提高很少更新的小型热点表的读取性能。 --- # 缓存表 -TiDB 在 v6.0.0 版本中引入了缓存表功能。该功能适用于频繁被访问且很少被修改的热点小表,即把整张表的数据加载到 TiDB 服务器的内存中,直接从内存中获取表数据,避免从 TiKV 获取表数据,从而提升读性能。 +在 v6.0.0 中,TiDB 为经常访问但很少更新的小型热点表引入了缓存表功能。使用此功能时,整个表的数据会加载到 TiDB 服务器的内存中,TiDB 直接从内存获取表数据而无需访问 TiKV,从而提高读取性能。 -本文介绍了 TiDB 缓存表的使用场景、使用示例、与其他 TiDB 功能的兼容性限制。 +本文档描述缓存表的使用场景、示例以及与其他 TiDB 功能的兼容性限制。 ## 使用场景 -TiDB 缓存表功能适用于以下特点的表: +缓存表功能适用于具有以下特征的表: -- 表的数据量不大,例如 4 MiB 以下 -- 只读表,或者几乎很少修改,例如写入 QPS 低于每分钟 10 次 -- 表的访问很频繁,期望有更好的读性能,例如在直接读取 TiKV 时遇到小表热点瓶颈 +- 表的数据量小,例如小于 4 MiB。 +- 表是只读的或很少更新,例如每分钟写入 QPS(每秒查询数)少于 10 次。 +- 表经常被访问,并且你期望更好的读取性能,例如当从 TiKV 直接读取小表时遇到热点。 -当表的数据量不大,访问又特别频繁的情况下,数据会集中在 TiKV 一个 Region 上,形成热点,从而影响性能。因此,TiDB 缓存表的典型使用场景如下: +当表的数据量小但数据经常被访问时,数据会集中在 TiKV 的一个 Region 上并形成热点 Region,这会影响性能。因此,缓存表的典型使用场景如下: -- 配置表,业务通过该表读取配置信息 -- 金融场景中的存储汇率的表,该表不会实时更新,每天只更新一次 -- 银行分行或者网点信息表,该表很少新增记录项 +- 配置表,应用程序从中读取配置信息。 +- 金融领域的汇率表。这些表每天只更新一次,而不是实时更新。 +- 银行分支机构或网络信息表,很少更新。 -以配置表为例,当业务重启的瞬间,全部连接一起加载配置,会造成较高的数据库读延迟。如果使用了缓存表,则可以解决这样的问题。 +以配置表为例。当应用程序重启时,所有连接都会加载配置信息,这会导致较高的读取延迟。在这种情况下,你可以使用缓存表功能来解决这个问题。 -## 使用示例 +## 示例 -本节通过示例介绍缓存表的使用方法。 +本节通过示例描述缓存表的使用方法。 -### 将普通表设为缓存表 +### 将普通表设置为缓存表 -假设已存在普通表 `users`: +假设有一个表 `users`: ```sql CREATE TABLE users ( @@ -41,25 +41,25 @@ CREATE TABLE users ( ); ``` -通过 `ALTER TABLE` 语句,可以将这张表设置成缓存表: +要将此表设置为缓存表,使用 `ALTER TABLE` 语句: ```sql ALTER TABLE users CACHE; ``` -``` +```sql Query OK, 0 rows affected (0.01 sec) ``` -### 验证是否为缓存表 +### 验证缓存表 -要验证一张表是否为缓存表,使用 `SHOW CREATE TABLE` 语句。如果为缓存表,返回结果中会带有 `CACHED ON` 属性: +要验证缓存表,使用 `SHOW CREATE TABLE` 语句。如果表已缓存,返回结果会包含 `CACHED ON` 属性: ```sql SHOW CREATE TABLE users; ``` -``` +```sql +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -72,13 +72,13 @@ SHOW CREATE TABLE users; 1 row in set (0.00 sec) ``` -从缓存表读取数据后,TiDB 会将数据加载到内存中。你可使用 [`TRACE`](/sql-statements/sql-statement-trace.md) 语句查看 TiDB 是否已将数据加载到内存中。当缓存还未加载时,语句的返回结果会出现 `regionRequest.SendReqCtx`,表示 TiDB 从 TiKV 读取了数据。 +从缓存表读取数据后,TiDB 会将数据加载到内存中。你可以使用 [`TRACE`](/sql-statements/sql-statement-trace.md) 语句检查数据是否已加载到内存中。当缓存未加载时,返回结果包含 `regionRequest.SendReqCtx` 属性,这表示 TiDB 从 TiKV 读取数据。 ```sql TRACE SELECT * FROM users; ``` -``` +```sql +------------------------------------------------+-----------------+------------+ | operation | startTS | duration | +------------------------------------------------+-----------------+------------+ @@ -98,9 +98,9 @@ TRACE SELECT * FROM users; 12 rows in set (0.01 sec) ``` -而再次执行 [`TRACE`](/sql-statements/sql-statement-trace.md),返回结果中不再有 `regionRequest.SendReqCtx`,表示 TiDB 已经不再从 TiKV 读取数据,而是直接从内存中读取: +再次执行 [`TRACE`](/sql-statements/sql-statement-trace.md) 后,返回结果不再包含 `regionRequest.SendReqCtx` 属性,这表示 TiDB 不再从 TiKV 读取数据,而是从内存中读取数据。 -``` +```sql +----------------------------------------+-----------------+------------+ | operation | startTS | duration | +----------------------------------------+-----------------+------------+ @@ -115,7 +115,7 @@ TRACE SELECT * FROM users; 7 rows in set (0.00 sec) ``` -注意,读取缓存表会使用 `UnionScan` 算子,所以通过 `explain` 查看缓存表的执行计划时,可能会在结果中看到 `UnionScan`: +注意,`UnionScan` 运算符用于读取缓存表,所以你可以通过 `explain` 在缓存表的执行计划中看到 `UnionScan`: ```sql +-------------------------+---------+-----------+---------------+--------------------------------+ @@ -128,15 +128,15 @@ TRACE SELECT * FROM users; 3 rows in set (0.00 sec) ``` -### 往缓存表写入数据 +### 向缓存表写入数据 -缓存表支持写入数据。例如,往 `users` 表中插入一条记录: +缓存表支持数据写入。例如,你可以向 `users` 表插入一条记录: ```sql INSERT INTO users(id, name) VALUES(1001, 'Davis'); ``` -``` +```sql Query OK, 1 row affected (0.00 sec) ``` @@ -144,7 +144,7 @@ Query OK, 1 row affected (0.00 sec) SELECT * FROM users; ``` -``` +```sql +------+-------+ | id | name | +------+-------+ @@ -155,15 +155,15 @@ SELECT * FROM users; > **注意:** > -> 往缓存表写入数据时,有可能出现秒级别的写入延迟。延迟的时长由全局环境变量 [`tidb_table_cache_lease`](/system-variables.md#tidb_table_cache_lease-从-v600-版本开始引入) 控制。你可根据实际业务能否承受此限制带来的延迟,决定是否适合使用缓存表功能。例如,对于完全只读的场景,可以将 `tidb_table_cache_lease` 调大: +> 向缓存表插入数据时,可能会出现秒级写入延迟。延迟由全局环境变量 [`tidb_table_cache_lease`](/system-variables.md#tidb_table_cache_lease-new-in-v600) 控制。你可以根据应用程序检查延迟是否可接受来决定是否使用缓存表功能。例如,在只读场景中,你可以增加 `tidb_table_cache_lease` 的值: > > ```sql > set @@global.tidb_table_cache_lease = 10; > ``` > -> 缓存表的写入延时高是受到实现的限制。存在多个 TiDB 实例时,一个 TiDB 实例并不知道其它的 TiDB 实例是否缓存了数据,如果该实例直接修改了表数据,而其它 TiDB 实例依然读取旧的缓存数据,就会读到错误的结果。为了保证数据正确性,缓存表的实现使用了一套基于 lease 的复杂机制:读操作在缓存数据同时,还会对于缓存设置一个有效期,也就是 lease。在 lease 过期之前,无法对数据执行修改操作。因为修改操作必须等待 lease 过期,所以会出现写入延迟。 +> 缓存表的写入延迟较高,因为缓存表功能的实现使用了复杂的机制,需要为每个缓存设置租约。当有多个 TiDB 实例时,一个实例不知道其他实例是否已缓存数据。如果一个实例直接修改表数据,其他实例会读取旧的缓存数据。为确保正确性,缓存表实现使用租约机制确保在租约到期前数据不会被修改。这就是写入延迟较高的原因。 -缓存表相关的元信息存储在 `mysql.table_cache_meta` 表中。这张表记录了所有缓存表的 ID、当前的锁状态 `lock_type`,以及锁租约 `lease` 相关的信息。这张表仅供 TiDB 内部使用,不建议用户修改该表,否则可能导致不可预期的错误。 +缓存表的元数据存储在 `mysql.table_cache_meta` 表中。此表记录了所有缓存表的 ID、当前锁定状态(`lock_type`)和锁定租约信息(`lease`)。此表仅供 TiDB 内部使用,不建议修改它。否则,可能会发生意外错误。 ```sql SHOW CREATE TABLE mysql.table_cache_meta\G @@ -183,13 +183,13 @@ Create Table: CREATE TABLE `table_cache_meta` ( > **注意:** > -> 对缓存表执行 DDL 语句会失败。若要对缓存表执行 DDL 语句,需要先去掉缓存属性,将缓存表设回普通表后,才能对其执行 DDL 语句。 +> 在缓存表上执行 DDL 语句将会失败。在对缓存表执行 DDL 语句之前,你需要先移除缓存属性,将缓存表恢复为普通表。 ```sql TRUNCATE TABLE users; ``` -``` +```sql ERROR 8242 (HY000): 'Truncate Table' is unsupported on cache tables. ``` @@ -197,48 +197,48 @@ ERROR 8242 (HY000): 'Truncate Table' is unsupported on cache tables. mysql> ALTER TABLE users ADD INDEX k_id(id); ``` -``` +```sql ERROR 8242 (HY000): 'Alter Table' is unsupported on cache tables. ``` -使用 `ALTER TABLE t NOCACHE` 语句可以将缓存表恢复成普通表: +要将缓存表恢复为普通表,使用 `ALTER TABLE t NOCACHE`: ```sql -ALTER TABLE users NOCACHE +ALTER TABLE users NOCACHE; ``` -``` +```sql Query OK, 0 rows affected (0.00 sec) ``` -## 缓存表大小限制 +## 缓存表的大小限制 -由于 TiDB 将整张缓存表的数据加载到 TiDB 进程的内存中,并且执行修改操作后缓存会失效,需要重新加载,所以 TiDB 缓存表只适用于表比较小的场景。 +缓存表仅适用于小表场景,因为 TiDB 会将整个表的数据加载到内存中,并且缓存的数据在修改后会失效并需要重新加载。 -目前 TiDB 对于每张缓存表的大小限制为 64 MB。如果表的数据超过了 64 MB,执行 `ALTER TABLE t CACHE` 会失败。 +目前,TiDB 中缓存表的大小限制为 64 MB。如果表数据超过 64 MB,执行 `ALTER TABLE t CACHE` 将会失败。 ## 与其他 TiDB 功能的兼容性限制 -以下是缓存表不支持的功能: +缓存表**不支持**以下功能: -- 不支持对分区表执行 `ALTER TABLE t CACHE` 操作 -- 不支持对临时表执行 `ALTER TABLE t CACHE` 操作 -- 不支持对视图执行 `ALTER TABLE t CACHE` 操作 -- 不支持 Stale Read 功能 -- 不支持对缓存表直接做 DDL 操作,需要先通过 `ALTER TABLE t NOCACHE` 将缓存表改回普通表后再进行 DDL 操作。 +- 不支持对分区表执行 `ALTER TABLE t ADD PARTITION` 操作。 +- 不支持对临时表执行 `ALTER TABLE t CACHE` 操作。 +- 不支持对视图执行 `ALTER TABLE t CACHE` 操作。 +- 不支持 Stale Read。 +- 不支持直接对缓存表执行 DDL 操作。在执行 DDL 操作之前,你需要先使用 `ALTER TABLE t NOCACHE` 将缓存表恢复为普通表。 -以下是缓存表无法使用缓存的场景: +缓存表**不能**在以下场景中使用: -- 设置系统变量 `tidb_snapshot` 读取历史数据 -- 执行修改操作期间,已有缓存会失效,直到数据被再次加载 +- 设置系统变量 `tidb_snapshot` 来读取历史数据。 +- 在修改期间,缓存的数据会失效,直到数据重新加载。 -## TiDB 数据迁移工具兼容性 +## 与 TiDB 迁移工具的兼容性 -缓存表并不是标准的 MySQL 功能,而是 TiDB 扩展。只有 TiDB 能识别 `ALTER TABLE ... CACHE` 语句。所有的 TiDB 数据迁移工具均不支持缓存表功能,包括 Backup & Restore (BR)、TiCDC、Dumpling 等组件,它们会将缓存表当作普通表处理。 +缓存表是 TiDB 对 MySQL 语法的扩展。只有 TiDB 能识别 `ALTER TABLE ... CACHE` 语句。TiDB 迁移工具**不支持**缓存表,包括 Backup & Restore (BR)、TiCDC 和 Dumpling。这些工具将缓存表视为普通表。 -这意味着,备份恢复一张缓存表时,它会变成一张普通表。如果下游集群是另一套 TiDB 集群并且你希望继续使用缓存表功能,可以对下游集群中的表执行 `ALTER TABLE ... CACHE` 手动开启缓存表功能。 +也就是说,当缓存表被备份和恢复时,它会变成普通表。如果下游集群是不同的 TiDB 集群,并且你想继续使用缓存表功能,你可以在下游集群上通过对下游表执行 `ALTER TABLE ... CACHE` 手动启用缓存表。 ## 另请参阅 * [ALTER TABLE](/sql-statements/sql-statement-alter-table.md) -* [System Variables](/system-variables.md) +* [系统变量](/system-variables.md) diff --git a/character-set-and-collation.md b/character-set-and-collation.md index 1d23fa32f506..9e8e21601883 100644 --- a/character-set-and-collation.md +++ b/character-set-and-collation.md @@ -1,17 +1,17 @@ --- title: 字符集和排序规则 -summary: TiDB 支持的字符集包括 ascii、binary、gbk、latin1、utf8 和 utf8mb4。排序规则包括 ascii_bin、binary、gbk_bin、gbk_chinese_ci、latin1_bin、utf8_bin、utf8_general_ci、utf8_unicode_ci、utf8mb4_0900_ai_ci、utf8mb4_0900_bin、utf8mb4_bin、utf8mb4_general_ci 和 utf8mb4_unicode_ci。TiDB 强烈建议使用 utf8mb4 字符集,因为它支持更多字符。在 TiDB 中,默认的排序规则受到客户端的连接排序规则设置的影响。如果客户端使用 utf8mb4_0900_ai_ci 作为连接排序规则,TiDB 将遵循客户端的配置。TiDB 还支持新的排序规则框架,用于在语义上支持不同的排序规则。 +summary: 了解 TiDB 支持的字符集和排序规则。 --- # 字符集和排序规则 -本文介绍了 TiDB 中支持的字符集和排序规则。 +本文介绍 TiDB 支持的字符集和排序规则。 -## 字符集和排序规则的概念 +## 概念 -字符集 (character set) 是符号与编码的集合。TiDB 中的默认字符集是 `utf8mb4`,与 MySQL 8.0 及更高版本中的默认字符集匹配。 +字符集是一组符号和编码的集合。TiDB 的默认字符集是 `utf8mb4`,这与 MySQL 8.0 及更高版本的默认字符集相匹配。 -排序规则 (collation) 是在字符集中比较字符以及字符排序顺序的规则。例如,在二进制排序规则中,比较 `A` 和 `a` 的结果是不一样的: +排序规则是一组用于比较字符集中字符的规则,以及字符的排序顺序。例如在二进制排序规则中,`A` 和 `a` 不会被视为相等: {{< copyable "sql" >}} @@ -56,9 +56,9 @@ SELECT 'A' = 'a'; 1 row in set (0.00 sec) ``` -## 支持的字符集和排序规则 +## TiDB 支持的字符集和排序规则 -目前 TiDB 支持以下字符集: +目前,TiDB 支持以下字符集: {{< copyable "sql" >}} @@ -109,17 +109,17 @@ SHOW COLLATION; > **警告:** > -> TiDB 会错误地将 `latin1` 视为 `utf8` 的子集。当用户存储不同于 `latin1` 和 `utf8` 编码的字符时,可能会导致意外情况出现。因此强烈建议使用 `utf8mb4` 字符集。详情参阅 [TiDB #18955](https://github.com/pingcap/tidb/issues/18955)。 +> TiDB 错误地将 latin1 视为 utf8 的子集。当存储 latin1 和 utf8 编码不同的字符时,这可能会导致意外行为。强烈建议使用 utf8mb4 字符集。更多详情请参见 [TiDB #18955](https://github.com/pingcap/tidb/issues/18955)。 > **注意:** > -> TiDB 中的默认排序规则(后缀为 `_bin` 的二进制排序规则)与 [MySQL 中的默认排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html)不同,后者通常是一般排序规则,后缀为 `_general_ci` 或 `_ai_ci`。当用户指定了显式字符集,但依赖于待选的隐式默认排序规则时,这个差异可能导致兼容性问题。 -> 在 TiDB 中,默认的排序规则也受到客户端的[连接排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-system-variables)设置的影响。例如,MySQL 8.x 客户端默认使用 `utf8mb4_0900_ai_ci` 作为 `utf8mb4` 字符集的连接排序规则。 +> TiDB 中的默认排序规则(带有 `_bin` 后缀的二进制排序规则)与 [MySQL 中的默认排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html)(通常是带有 `_general_ci` 或 `_ai_ci` 后缀的通用排序规则)不同。当指定显式字符集但依赖隐式默认排序规则时,这可能会导致不兼容的行为。 > -> - 在 TiDB v7.4.0 之前,如果客户端使用 `utf8mb4_0900_ai_ci` 作为[连接排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-system-variables),因为 TiDB 不支持 `utf8mb4_0900_ai_ci` 排序规则,TiDB 将回退到使用 TiDB 服务器默认的排序规则 `utf8mb4_bin`。 -> - 从 v7.4.0 开始,如果客户端使用 `utf8mb4_0900_ai_ci` 作为[连接排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-system-variables),TiDB 将遵循客户端的配置,使用 `utf8mb4_0900_ai_ci` 作为默认排序规则。 - -利用以下的语句可以查看字符集对应的排序规则(以下是[新的排序规则框架](#新框架下的排序规则支持))下的结果: +> 然而,TiDB 中的默认排序规则也会受到客户端[连接排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-system-variables)设置的影响。例如,MySQL 8.x 客户端默认将 `utf8mb4_0900_ai_ci` 作为 `utf8mb4` 字符集的连接排序规则。 +> +> - 在 TiDB v7.4.0 之前,如果客户端使用 `utf8mb4_0900_ai_ci` 作为[连接排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-system-variables),由于 TiDB 不支持 `utf8mb4_0900_ai_ci` 排序规则,TiDB 会回退使用 TiDB 服务器默认排序规则 `utf8mb4_bin`。 +> - 从 v7.4.0 开始,如果客户端使用 `utf8mb4_0900_ai_ci` 作为[连接排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-system-variables),TiDB 会遵循客户端的配置使用 `utf8mb4_0900_ai_ci` 作为默认排序规则。 +你可以使用以下语句查看对应字符集的排序规则(在[新的排序规则框架](#新的排序规则框架)下): {{< copyable "sql" >}} @@ -140,15 +140,15 @@ SHOW COLLATION WHERE Charset = 'utf8mb4'; 5 rows in set (0.00 sec) ``` -TiDB 对 GBK 字符集的支持详情见 [GBK](/character-set-gbk.md)。 +关于 TiDB 对 GBK 字符集的支持详情,请参见 [GBK](/character-set-gbk.md)。 ## TiDB 中的 `utf8` 和 `utf8mb4` -MySQL 限制字符集 `utf8` 为最多 3 个字节。这足以存储在基本多语言平面 (BMP) 中的字符,但不足以存储表情符号 (emoji) 等字符。因此,建议改用字符集`utf8mb4`。 +在 MySQL 中,字符集 `utf8` 最多只能存储三个字节。这足以存储基本多语言平面(BMP)中的字符,但不足以存储表情符号等字符。为此,建议使用字符集 `utf8mb4`。 -默认情况下,TiDB 同样限制字符集 `utf8` 为最多 3 个字节,以确保 TiDB 中创建的数据可以在 MySQL 中顺利恢复。你可以禁用此功能,方法是将系统变量 [`tidb_check_mb4_value_in_utf8`](/system-variables.md#tidb_check_mb4_value_in_utf8) 的值更改为 `OFF`。 +默认情况下,TiDB 也将字符集 `utf8` 限制为最多三个字节,以确保在 TiDB 中创建的数据仍然可以安全地在 MySQL 中恢复。你可以通过将系统变量 [`tidb_check_mb4_value_in_utf8`](/system-variables.md#tidb_check_mb4_value_in_utf8) 的值更改为 `OFF` 来禁用此限制。 -以下示例演示了在表中插入 4 字节的表情符号字符(emoji 字符)时的默认行为。`utf8` 字符集下 `INSERT` 语句不能执行,`utf8mb4` 字符集下可以执行 `INSERT` 语句: +以下示例演示了在将 4 字节表情符号字符插入表时的默认行为。对于 `utf8` 字符集,`INSERT` 语句失败,但对于 `utf8mb4` 则成功: ```sql CREATE TABLE utf8_test ( @@ -206,14 +206,13 @@ SELECT char_length(c), length(c), c FROM utf8m4_test; +----------------+-----------+------+ 1 row in set (0.00 sec) ``` +## 不同层次的字符集和排序规则 -## 不同范围的字符集和排序规则 +字符集和排序规则可以在不同层次设置。 -字符集和排序规则可以在设置在不同的层次。 +### 数据库字符集和排序规则 -### 数据库的字符集和排序规则 - -每个数据库都有相应的字符集和排序规则。数据库的字符集和排序规则可以通过以下语句来设置: +每个数据库都有一个字符集和一个排序规则。你可以使用以下语句指定数据库字符集和排序规则: ```sql CREATE DATABASE db_name @@ -225,11 +224,9 @@ ALTER DATABASE db_name [[DEFAULT] COLLATE collation_name] ``` -在这里 `DATABASE` 可以跟 `SCHEMA` 互换使用。 - -不同的数据库之间可以使用不一样的字符集和排序规则。 +这里的 `DATABASE` 可以替换为 `SCHEMA`。 -通过系统变量 `character_set_database` 和 `collation_database` 可以查看到当前数据库的字符集以及排序规则: +不同的数据库可以使用不同的字符集和排序规则。使用 `character_set_database` 和 `collation_database` 可以查看当前数据库的字符集和排序规则: {{< copyable "sql" >}} @@ -301,7 +298,7 @@ SELECT @@character_set_database, @@collation_database; 1 row in set (0.00 sec) ``` -在 INFORMATION_SCHEMA 中也可以查看到这两个值: +你也可以在 `INFORMATION_SCHEMA` 中查看这两个值: {{< copyable "sql" >}} @@ -309,10 +306,9 @@ SELECT @@character_set_database, @@collation_database; SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'db_name'; ``` +### 表字符集和排序规则 -### 表的字符集和排序规则 - -表的字符集和排序规则可以通过以下语句来设置: +你可以使用以下语句指定表的字符集和排序规则: ```sql CREATE TABLE tbl_name (column_list) @@ -336,11 +332,11 @@ CREATE TABLE t1(a int) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; Query OK, 0 rows affected (0.08 sec) ``` -如果表的字符集和排序规则没有设置,那么数据库的字符集和排序规则就作为其默认值。在仅指定字符集为 `utf8mb4`,但未设置排序规则时,排序规则为变量 [`default_collation_for_utf8mb4`](/system-variables.md#default_collation_for_utf8mb4-从-v740-版本开始引入) 指定的值。 +如果未指定表字符集和排序规则,则使用数据库字符集和排序规则作为其默认值。如果你只指定字符集为 `utf8mb4` 而不指定排序规则,则排序规则由系统变量 [`default_collation_for_utf8mb4`](/system-variables.md#default_collation_for_utf8mb4-new-in-v740) 的值决定。 -### 列的字符集和排序规则 +### 列字符集和排序规则 -列的字符集和排序规则的语法如下: +你可以使用以下语句指定列的字符集和排序规则: ```sql col_name {CHAR | VARCHAR | TEXT} (col_length) @@ -352,17 +348,19 @@ col_name {ENUM | SET} (val_list) [COLLATE collation_name] ``` -如果列的字符集和排序规则没有设置,那么表的字符集和排序规则就作为其默认值。在仅指定字符集为 `utf8mb4`,但未设置排序规则时,排序规则为变量 [`default_collation_for_utf8mb4`](/system-variables.md#default_collation_for_utf8mb4-从-v740-版本开始引入) 指定的值。 +如果未指定列字符集和排序规则,则使用表字符集和排序规则作为其默认值。如果你只指定字符集为 `utf8mb4` 而不指定排序规则,则排序规则由系统变量 [`default_collation_for_utf8mb4`](/system-variables.md#default_collation_for_utf8mb4-new-in-v740) 的值决定。 + +### 字符串字符集和排序规则 -### 字符串的字符集和排序规则 +每个字符串对应一个字符集和一个排序规则。当你使用字符串时,可以使用以下选项: -每一个字符串都对应一个字符集和一个排序规则,在使用字符串时指此选项可选,如下: +{{< copyable "sql" >}} ```sql [_charset_name]'string' [COLLATE collation_name] ``` -示例如下: +示例: {{< copyable "sql" >}} @@ -372,28 +370,28 @@ 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` 系统变量给出的字符集和排序规则。 ++ 规则 1:如果指定了 `CHARACTER SET charset_name` 和 `COLLATE collation_name`,则直接使用 `charset_name` 字符集和 `collation_name` 排序规则。 ++ 规则 2:如果指定了 `CHARACTER SET charset_name` 但未指定 `COLLATE collation_name`,则使用 `charset_name` 字符集及其默认排序规则。 ++ 规则 3:如果既未指定 `CHARACTER SET charset_name` 也未指定 `COLLATE collation_name`,则使用由系统变量 `character_set_connection` 和 `collation_connection` 给出的字符集和排序规则。 +### 客户端连接字符集和排序规则 -### 客户端连接的字符集和排序规则 ++ 服务器字符集和排序规则是 `character_set_server` 和 `collation_server` 系统变量的值。 -* 服务器的字符集和排序规则可以通过系统变量 `character_set_server` 和 `collation_server` 获取。 -* 数据库的字符集和排序规则可以通过环境变量 `character_set_database` 和 `collation_database` 获取。 ++ 默认数据库的字符集和排序规则是 `character_set_database` 和 `collation_database` 系统变量的值。 -对于每一个客户端的连接,也有相应的变量表示字符集和排序规则:`character_set_connection` 和 `collation_connection`。 +你可以使用 `character_set_connection` 和 `collation_connection` 为每个连接指定字符集和排序规则。`character_set_client` 变量用于设置客户端字符集。 -`character_set_client` 代表客户端的字符集。在返回结果前,服务端会把结果根据 `character_set_results` 转换成对应的字符集,包括结果的元信息等。 +在返回结果之前,`character_set_results` 系统变量指示服务器向客户端返回查询结果的字符集,包括结果的元数据。 -可以用以下的语句来影响这些跟客户端相关的字符集变量: +你可以使用以下语句设置与客户端相关的字符集和排序规则: -* `SET NAMES 'charset_name' [COLLATE 'collation_name']` ++ `SET NAMES 'charset_name' [COLLATE 'collation_name']` - `SET NAMES` 用来设定客户端会在之后的请求中使用的字符集。`SET NAMES utf8mb4` 表示客户端会在接下来的请求中,都使用 utf8mb4 字符集。服务端也会在之后返回结果的时候使用 utf8mb4 字符集。`SET NAMES 'charset_name'` 语句其实等于下面语句的组合: + `SET NAMES` 表示客户端将使用什么字符集向服务器发送 SQL 语句。`SET NAMES utf8mb4` 表示客户端的所有请求都使用 utf8mb4,服务器的结果也是如此。 - {{< copyable "sql" >}} + `SET NAMES 'charset_name'` 语句等同于以下语句组合: ```sql SET character_set_client = charset_name; @@ -401,13 +399,11 @@ SELECT _utf8mb4'string' COLLATE utf8mb4_general_ci; SET character_set_connection = charset_name; ``` - `COLLATE` 是可选的,如果没有提供,将会用 `charset_name` 对应的默认排序规则设置 `collation_connection`。 + `COLLATE` 是可选的,如果不存在,则使用 `charset_name` 的默认排序规则来设置 `collation_connection`。 -* `SET CHARACTER SET 'charset_name'` ++ `SET CHARACTER SET 'charset_name'` - 跟 `SET NAMES` 类似,等价于下面语句的组合: - - {{< copyable "sql" >}} + 类似于 `SET NAMES`,`SET NAMES 'charset_name'` 语句等同于以下语句组合: ```sql SET character_set_client = charset_name; @@ -416,39 +412,46 @@ SELECT _utf8mb4'string' COLLATE utf8mb4_general_ci; 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` 都未指定,则使用更高优先级的字符集和排序规则。 ++ 规则 1:如果指定了 `CHARACTER SET charset_name` 和 `COLLATE collation_name`,则直接使用 `charset_name` 字符集和 `collation_name` 排序规则。 ++ 规则 2:如果指定了 `CHARACTER SET charset_name` 但未指定 `COLLATE collation_name`,则使用 `charset_name` 字符集及其默认排序规则。 ++ 规则 3:如果既未指定 `CHARACTER SET charset_name` 也未指定 `COLLATE collation_name`,则使用优化级别更高的字符集和排序规则。 -## 字符合法性检查 +## 字符有效性检查 -当指定的字符集为 utf8 或 utf8mb4 时,TiDB 仅支持合法的 utf8 字符。对于不合法的字符,会报错:`incorrect utf8 value`。该字符合法性检查与 MySQL 8.0 兼容,与 MySQL 5.7 及以下版本不兼容。 +如果指定的字符集是 `utf8` 或 `utf8mb4`,TiDB 仅支持有效的 `utf8` 字符。对于无效字符,TiDB 会报告 `incorrect utf8 value` 错误。TiDB 中的这种字符有效性检查与 MySQL 8.0 兼容,但与 MySQL 5.7 或更早版本不兼容。 -如果不希望报错,可以通过 `set @@tidb_skip_utf8_check=1;` 跳过字符检查。 +要禁用此错误报告,请使用 `set @@tidb_skip_utf8_check=1;` 跳过字符检查。 > **注意:** > -> 跳过字符检查可能会使 TiDB 检测不到应用写入的非法 UTF-8 字符,进一步导致执行 `ANALYZE` 时解码错误,以及引入其他未知的编码问题。如果应用不能保证写入字符串的合法性,不建议跳过该检查。 +> 如果跳过字符检查,TiDB 可能无法检测到应用程序写入的非法 UTF-8 字符,在执行 `ANALYZE` 时可能会导致解码错误,并引入其他未知的编码问题。如果你的应用程序无法保证写入字符串的有效性,不建议跳过字符检查。 +## 排序规则支持框架 + + + +排序规则的语法支持和语义支持受 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 配置项的影响。语法支持和语义支持是不同的。前者表示 TiDB 可以解析和设置排序规则。后者表示 TiDB 可以在比较字符串时正确使用排序规则。 + + + + -## 排序规则支持 +排序规则的语法支持和语义支持是不同的。前者表示 TiDB 可以解析和设置排序规则。后者表示 TiDB 可以在比较字符串时正确使用排序规则。 -排序规则的语法支持和语义支持受到配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 的影响。这里语法支持和语义支持有所区别。语法支持是指 TiDB 能够解析和设置排序规则;而语义支持是指 TiDB 能够在比较字符串时正确地使用排序规则。 + -在 4.0 版本之前,TiDB 只提供了旧的排序规则框架,能够在语法上支持的绝大部分 MySQL 排序规则,但语义上所有的排序规则都当成二进制排序规则。 +在 v4.0 之前,TiDB 仅提供[旧的排序规则框架](#旧的排序规则框架)。在这个框架中,TiDB 支持语法解析大多数 MySQL 排序规则,但在语义上将所有排序规则视为二进制排序规则。 -4.0 版本中,TiDB 增加了新的排序规则框架用于在语义上支持不同的排序规则,保证字符串比较时严格遵循对应的排序规则,详情请见下文。 +从 v4.0 开始,TiDB 支持[新的排序规则框架](#新的排序规则框架)。在这个框架中,TiDB 语义解析不同的排序规则,并在比较字符串时严格遵循排序规则。 -### 旧框架下的排序规则支持 +### 旧的排序规则框架 -在 4.0 版本之前,TiDB 中可以指定大部分 MySQL 中的排序规则,并把这些排序规则按照默认排序规则处理,即以编码字节序为字符定序。和 MySQL 不同的是,TiDB 不会处理字符末尾的空格,因此会造成以下的行为区别: +在 v4.0 之前,你可以在 TiDB 中指定大多数 MySQL 排序规则,这些排序规则按照默认排序规则处理,这意味着字节顺序决定字符顺序。与 MySQL 不同,TiDB 不处理字符的尾随空格,这导致以下行为差异: {{< copyable "sql" >}} @@ -476,29 +479,31 @@ INSERT INTO t VALUES ('a'); Query OK, 1 row affected ``` -以上语句,在 TiDB 会执行成功,而在 MySQL 中,由于 `utf8mb4_general_ci` 大小写不敏感,报错 `Duplicate entry 'a'`。 +在 TiDB 中,上述语句成功执行。在 MySQL 中,由于 `utf8mb4_general_ci` 不区分大小写,会报告 `Duplicate entry 'a'` 错误。 ```sql -INSERT INTO t VALUES ('a '); +INSERT INTO t1 VALUES ('a '); ``` ```sql Query OK, 1 row affected ``` -以上语句,在 TiDB 会执行成功,而在 MySQL 中,由于补齐空格比较,报错 `Duplicate entry 'a '`。 +在 TiDB 中,上述语句成功执行。在 MySQL 中,由于在填充空格后进行比较,会返回 `Duplicate entry 'a '` 错误。 + +### 新的排序规则框架 + +从 TiDB v4.0 开始,引入了一个完整的排序规则框架。 -### 新框架下的排序规则支持 + -TiDB 4.0 新增了完整的排序规则支持框架,从语义上支持了排序规则,并新增了配置开关 `new_collations_enabled_on_first_bootstrap`,在集群初次初始化时决定是否启用新排序规则框架。如需启用新排序规则框架,可将 `new_collations_enabled_on_first_bootstrap` 的值设为 `true`,详情参见 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap)。 +这个新框架支持语义解析排序规则,并引入了 `new_collations_enabled_on_first_bootstrap` 配置项来决定在集群首次初始化时是否启用新框架。要启用新框架,请将 `new_collations_enabled_on_first_bootstrap` 设置为 `true`。详情请参见 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap)。 -对于一个已经初始化完成的 TiDB 集群,可以通过 `mysql.tidb` 表中的 `new_collation_enabled` 变量确认是否启用了新排序规则框架。 +对于已经初始化的 TiDB 集群,你可以通过 `mysql.tidb` 表中的 `new_collation_enabled` 变量检查新排序规则是否启用: > **注意:** > -> 当 `mysql.tidb` 表查询结果和 `new_collations_enabled_on_first_bootstrap` 的值不同时,以 `mysql.tidb` 表的结果为准。 - -{{< copyable "sql" >}} +> 如果 `mysql.tidb` 表的查询结果与 `new_collations_enabled_on_first_bootstrap` 的值不同,则 `mysql.tidb` 表的结果为实际值。 ```sql SELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME='new_collation_enabled'; @@ -513,9 +518,17 @@ SELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME='new_collation_enabled 1 row in set (0.00 sec) ``` -在新的排序规则框架下,TiDB 能够支持 `utf8_general_ci`、`utf8mb4_general_ci`、`utf8_unicode_ci`、`utf8mb4_unicode_ci`、`utf8mb4_0900_bin`、`utf8mb4_0900_ai_ci`、`gbk_chinese_ci` 和 `gbk_bin` 这几种排序规则,与 MySQL 兼容。 + + + -使用 `utf8_general_ci`、`utf8mb4_general_ci`、`utf8_unicode_ci`、`utf8mb4_unicode_ci`、`utf8mb4_0900_ai_ci` 和 `gbk_chinese_ci` 中任一种时,字符串之间的比较是大小写不敏感 (case-insensitive) 和口音不敏感 (accent-insensitive) 的。同时,TiDB 还修正了排序规则的 `PADDING` 行为: +这个新框架支持语义解析排序规则。TiDB 在集群首次初始化时默认启用新框架。 + + + +在新框架下,TiDB 支持 `utf8_general_ci`、`utf8mb4_general_ci`、`utf8_unicode_ci`、`utf8mb4_unicode_ci`、`utf8mb4_0900_bin`、`utf8mb4_0900_ai_ci`、`gbk_chinese_ci` 和 `gbk_bin` 排序规则,这与 MySQL 兼容。 + +当使用 `utf8_general_ci`、`utf8mb4_general_ci`、`utf8_unicode_ci`、`utf8mb4_unicode_ci`、`utf8mb4_0900_ai_ci` 和 `gbk_chinese_ci` 其中之一时,字符串比较不区分大小写和重音。同时,TiDB 还纠正了排序规则的 `PADDING` 行为: {{< copyable "sql" >}} @@ -540,49 +553,44 @@ INSERT INTO t VALUES ('a'); ``` ```sql -ERROR 1062 (23000): Duplicate entry 'a' for key 't.PRIMARY' +ERROR 1062 (23000): Duplicate entry 'a' for key 't.PRIMARY' -- TiDB 与 MySQL 的不区分大小写排序规则兼容。 ``` -TiDB 兼容了 MySQL 的 case insensitive collation。 - ```sql INSERT INTO t VALUES ('a '); ``` ```sql -ERROR 1062 (23000): Duplicate entry 'a ' for key 't.PRIMARY' +ERROR 1062 (23000): Duplicate entry 'a ' for key 't.PRIMARY' -- TiDB 修改了 `PADDING` 行为以与 MySQL 兼容。 ``` -TiDB 修正了 `PADDING` 行为,与 MySQL 兼容。 - > **注意:** > -> TiDB 中 padding 的实现方式与 MySQL 的不同。在 MySQL 中,padding 是通过补齐空格实现的。而在 TiDB 中 padding 是通过裁剪掉末尾的空格来实现的。两种做法在绝大多数情况下是一致的,唯一的例外是字符串尾部包含小于空格 (0x20) 的字符时,例如 `'a' < 'a\t'` 在 TiDB 中的结果为 `1`,而在 MySQL 中,其等价于 `'a ' < 'a\t'`,结果为 `0`。 - -## 表达式中排序规则的 Coercibility 值 +> TiDB 中的填充实现与 MySQL 不同。在 MySQL 中,填充是通过填充空格实现的。在 TiDB 中,填充是通过切掉末尾的空格实现的。这两种方法在大多数情况下是相同的。唯一的例外是当字符串末尾包含小于空格 (0x20) 的字符时。例如,在 TiDB 中 `'a' < 'a\t'` 的结果是 `1`,但在 MySQL 中,`'a' < 'a\t'` 等同于 `'a ' < 'a\t'`,结果是 `0`。 +## 表达式中排序规则的强制性值 -如果一个表达式涉及多个不同排序规则的子表达式时,需要对计算时用的排序规则进行推断,规则如下: +如果一个表达式涉及多个具有不同排序规则的子句,你需要推断计算中使用的排序规则。规则如下: -+ 显式 `COLLATE` 子句的 coercibility 值为 `0`。 -+ 如果两个字符串的排序规则不兼容,这两个字符串 `concat` 结果的 coercibility 值为 `1`。 -+ 列或者 `CAST()`、`CONVERT()` 和 `BINARY()` 的排序规则的 coercibility 值为 `2`。 -+ 系统常量(`USER()` 或者 `VERSION()` 返回的字符串)的 coercibility 值为 `3`。 -+ 常量的 coercibility 值为 `4`。 -+ 数字或者中间变量的 coercibility 值为 `5`。 -+ `NULL` 或者由 `NULL` 派生出的表达式的 coercibility 值为 `6`。 ++ 显式 `COLLATE` 子句的强制性值为 `0`。 ++ 如果两个字符串的排序规则不兼容,则具有不同排序规则的两个字符串的连接的强制性值为 `1`。 ++ 列、`CAST()`、`CONVERT()` 或 `BINARY()` 的排序规则的强制性值为 `2`。 ++ 系统常量(由 `USER()` 或 `VERSION()` 返回的字符串)的强制性值为 `3`。 ++ 常量的强制性值为 `4`。 ++ 数字或中间变量的强制性值为 `5`。 ++ `NULL` 或从 `NULL` 派生的表达式的强制性值为 `6`。 -在推断排序规则时,TiDB 优先使用 coercibility 值较低的表达式的排序规则。如果 coercibility 值相同,则按以下优先级确定排序规则: +在推断排序规则时,TiDB 倾向于使用强制性值较低的表达式的排序规则。如果两个子句的强制性值相同,则根据以下优先级确定排序规则: binary > utf8mb4_bin > (utf8mb4_general_ci = utf8mb4_unicode_ci) > utf8_bin > (utf8_general_ci = utf8_unicode_ci) > latin1_bin > ascii_bin -以下情况 TiDB 无法推断排序规则并报错: +在以下情况下,TiDB 无法推断排序规则并报错: -- 如果两个子表达式的排序规则不相同,而且表达式的 coercibility 值都为 `0`。 -- 如果两个子表达式的排序规则不兼容,而且表达式的返回类型为 `String` 类。 +- 如果两个子句的排序规则不同且两个子句的强制性值都为 `0`。 +- 如果两个子句的排序规则不兼容且表达式的返回类型为 `String`。 ## `COLLATE` 子句 -TiDB 支持使用 `COLLATE` 子句来指定一个表达式的排序规则,该表达式的 coercibility 值为 `0`,具有最高的优先级。示例如下: +TiDB 支持使用 `COLLATE` 子句指定表达式的排序规则。此表达式的强制性值为 `0`,具有最高优先级。请看以下示例: {{< copyable "sql" >}} @@ -599,4 +607,4 @@ SELECT 'a' = _utf8mb4 'A' collate utf8mb4_general_ci; 1 row in set (0.00 sec) ``` -更多细节,参考 [Connection Character Sets and Collations](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html)。 +更多详情,请参见[连接字符集和排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html)。 diff --git a/character-set-gbk.md b/character-set-gbk.md index b10200ab89e0..eb3d76ba29fb 100644 --- a/character-set-gbk.md +++ b/character-set-gbk.md @@ -1,13 +1,13 @@ --- title: GBK -summary: 本文介绍 TiDB 对 GBK 字符集的支持情况。 +summary: 本文档提供了 TiDB 对 GBK 字符集支持的详细信息。 --- # GBK -TiDB 从 v5.4.0 开始支持 GBK 字符集。本文档介绍 TiDB 对 GBK 字符集的支持和兼容情况。 +从 v5.4.0 版本开始,TiDB 支持 GBK 字符集。本文档提供了 TiDB 对 GBK 字符集的支持和兼容性信息。 -从 TiDB v6.0.0 开始,[新的排序规则框架](/character-set-and-collation.md#新框架下的排序规则支持)默认启用,即 TiDB GBK 字符集的默认排序规则为 `gbk_chinese_ci`,与 MySQL 保持一致。 +从 v6.0.0 版本开始,TiDB 默认启用[新的排序规则框架](/character-set-and-collation.md#new-framework-for-collations)。TiDB GBK 字符集的默认排序规则是 `gbk_chinese_ci`,这与 MySQL 保持一致。 ```sql SHOW CHARACTER SET WHERE CHARSET = 'gbk'; @@ -28,41 +28,51 @@ SHOW COLLATION WHERE CHARSET = 'gbk'; 2 rows in set (0.00 sec) ``` -## 与 MySQL 的兼容性 +## MySQL 兼容性 -本节介绍 TiDB 中 GBK 字符集与 MySQL 的兼容情况。 +本节提供 MySQL 和 TiDB 之间的兼容性信息。 -### 排序规则兼容性 +### 排序规则 -MySQL 的 GBK 字符集默认排序规则是 `gbk_chinese_ci`。TiDB 的 GBK 字符集的默认排序规则取决于 TiDB 配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 的值: + -- 默认情况下,TiDB 配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 为 `true`,表示开启[新的排序规则框架](/character-set-and-collation.md#新框架下的排序规则支持)。GBK 字符集的默认排序规则是 `gbk_chinese_ci`。 -- 当 TiDB 配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 为 `false` 时,表示关闭新的排序规则框架,GBK 字符集的默认排序规则是 `gbk_bin`。 +MySQL 中 GBK 字符集的默认排序规则是 `gbk_chinese_ci`。TiDB 中 GBK 字符集的默认排序规则取决于 TiDB 配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 的值: -另外,TiDB 支持的 `gbk_bin` 与 MySQL 支持的 `gbk_bin` 排序规则不一致,TiDB 是将 GBK 转换成 `utf8mb4`,然后再进行二进制排序。 +- 默认情况下,TiDB 配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 设置为 `true`,这意味着启用了[新的排序规则框架](/character-set-and-collation.md#new-framework-for-collations),GBK 字符集的默认排序规则是 `gbk_chinese_ci`。 +- 当 TiDB 配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 设置为 `false` 时,[新的排序规则框架](/character-set-and-collation.md#new-framework-for-collations)被禁用,GBK 字符集的默认排序规则是 `gbk_bin`。 + + + + + +默认情况下,TiDB Cloud 启用[新的排序规则框架](/character-set-and-collation.md#new-framework-for-collations),GBK 字符集的默认排序规则是 `gbk_chinese_ci`。 + + + +此外,由于 TiDB 将 GBK 转换为 `utf8mb4` 后再使用二进制排序规则,因此 TiDB 中的 `gbk_bin` 排序规则与 MySQL 中的 `gbk_bin` 排序规则不同。 ### 非法字符兼容性 -* 在系统变量 [`character_set_client`](/system-variables.md#character_set_client) 和 [`character_set_connection`](/system-variables.md#character_set_connection) 不同时设置为 `gbk` 的情况下,TiDB 处理非法字符的方式与 MySQL 一致。 -* 在 `character_set_client` 和 `character_set_connection` 同时为 `gbk` 的情况下,TiDB 处理非法字符的方式与 MySQL 有所区别。 +* 如果系统变量 [`character_set_client`](/system-variables.md#character_set_client) 和 [`character_set_connection`](/system-variables.md#character_set_connection) 没有同时设置为 `gbk`,TiDB 处理非法字符的方式与 MySQL 相同。 +* 如果 `character_set_client` 和 `character_set_connection` 都设置为 `gbk`,TiDB 处理非法字符的方式与 MySQL 不同。 - - MySQL 处理非法 GBK 字符集时,对读和写操作的处理方式不同。 - - TiDB 处理非法 GBK 字符集时,对读和写操作的处理方式相同。TiDB 在严格模式下读写非法 GBK 字符都会报错,在非严格模式下,读写非法 GBK 字符都会用 `?` 替换。 + - MySQL 对读写操作中的非法 GBK 字符集处理方式不同。 + - TiDB 对读写操作中的非法 GBK 字符集处理方式相同。在 SQL 严格模式下,TiDB 在读写非法 GBK 字符时都会报错。在非严格模式下,TiDB 在读写非法 GBK 字符时都会将非法 GBK 字符替换为 `?`。 -例如,当 `SET NAMES gbk` 时,如果分别在 MySQL 和 TiDB 上通过 `CREATE TABLE gbk_table(a VARCHAR(32) CHARACTER SET gbk)` 语句建表,然后按照下表中的 SQL 语句进行操作,就能看到具体的区别。 +例如,在执行 `SET NAMES gbk` 后,如果您分别在 MySQL 和 TiDB 中使用 `CREATE TABLE gbk_table(a VARCHAR(32) CHARACTER SET gbk)` 语句创建表,然后执行下表中的 SQL 语句,您可以看到详细的差异。 -| 数据库 | 如果设置的 SQL 模式包含 `STRICT_ALL_TABLES` 或 `STRICT_TRANS_TABLES` | 如果设置的 SQL 模式不包含 `STRICT_ALL_TABLES` 和 `STRICT_TRANS_TABLES` | +| 数据库 | 如果配置的 SQL 模式包含 `STRICT_ALL_TABLES` 或 `STRICT_TRANS_TABLES` 中的任一个 | 如果配置的 SQL 模式既不包含 `STRICT_ALL_TABLES` 也不包含 `STRICT_TRANS_TABLES` | |-------|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------| | MySQL | `SELECT HEX('一a');`
`e4b88061`

`INSERT INTO gbk_table values('一a');`
`Incorrect Error` | `SELECT HEX('一a');`
`e4b88061`

`INSERT INTO gbk_table VALUES('一a');`
`SELECT HEX(a) FROM gbk_table;`
`e4b8` | | TiDB | `SELECT HEX('一a');`
`Incorrect Error`

`INSERT INTO gbk_table VALUES('一a');`
`Incorrect Error` | `SELECT HEX('一a');`
`e4b83f`

`INSERT INTO gbk_table VALUES('一a');`
`SELECT HEX(a) FROM gbk_table;`
`e4b83f` | -说明:该表中 `SELECT HEX('一a');` 在 `utf8mb4` 字节集下的结果为 `e4b88061`。 +在上表中,在 `utf8mb4` 字节集中 `SELECT HEX('a');` 的结果是 `e4b88061`。 -### 其它 +### 其他 MySQL 兼容性 -* 目前 TiDB 不支持通过 `ALTER TABLE` 语句将其它字符集类型改成 `gbk` 或者从 `gbk` 转成其它字符集类型。 +- 目前,TiDB 不支持使用 `ALTER TABLE` 语句将其他字符集类型转换为 `gbk` 或从 `gbk` 转换为其他字符集类型。 -* TiDB 不支持使用 `_gbk`,比如: +* TiDB 不支持使用 `_gbk`。例如: ```sql CREATE TABLE t(a CHAR(10) CHARSET BINARY); @@ -71,16 +81,16 @@ MySQL 的 GBK 字符集默认排序规则是 `gbk_chinese_ci`。TiDB 的 GBK 字 ERROR 1115 (42000): Unsupported character introducer: 'gbk' ``` -* 对于 `ENUM` 和 `SET` 类型中的二进制字符,TiDB 目前都会将其作为 `utf8mb4` 字符集处理。 +- 目前,对于 `ENUM` 和 `SET` 类型的二进制字符,TiDB 将其作为 `utf8mb4` 字符集处理。 ## 组件兼容性 -* TiFlash 目前不支持 GBK 字符集。 +- 目前,TiFlash 不支持 GBK 字符集。 -* TiDB Data Migration (DM) 在 v5.4.0 之前不支持将 `charset=GBK` 的表迁移到 TiDB。 +- TiDB Data Migration (DM) 不支持将 `charset=GBK` 的表迁移到 v5.4.0 之前的 TiDB 集群。 -* TiDB Lightning 在 v5.4.0 之前不支持导入 `charset=GBK` 的表。 +- TiDB Lightning 不支持将 `charset=GBK` 的表导入到 v5.4.0 之前的 TiDB 集群。 -* TiCDC 在 v6.1.0 之前不支持同步 `charset=GBK` 的表。另外,任何版本的 TiCDC 都不支持同步 `charset=GBK` 的表到 6.1.0 之前的 TiDB 集群。 +- v6.1.0 之前的 TiCDC 版本不支持复制 `charset=GBK` 的表。所有版本的 TiCDC 都不支持将 `charset=GBK` 的表复制到 v6.1.0 之前的 TiDB 集群。 -* TiDB Backup & Restore(BR)在 v5.4.0 之前不支持恢复 `charset=GBK` 的表。另外,任何版本的 BR 都不支持恢复 `charset=GBK` 的表到 5.4.0 之前的 TiDB 集群。 \ No newline at end of file +- v5.4.0 之前的 Backup & Restore (BR) 版本不支持恢复 `charset=GBK` 的表。所有版本的 BR 都不支持将 `charset=GBK` 的表恢复到 v5.4.0 之前的 TiDB 集群。 diff --git a/choose-index.md b/choose-index.md index b620943f135f..b7a0d9fc2e53 100644 --- a/choose-index.md +++ b/choose-index.md @@ -1,54 +1,54 @@ --- -title: 索引的选择 -summary: 介绍 TiDB 如何选择索引去读入数据,以及相关的一些控制索引选择的方式。 +title: 索引选择 +summary: 为 TiDB 查询优化选择最佳索引。 --- -# 索引的选择 +# 索引选择 -从存储层读取数据是 SQL 计算过程中最为耗时的部分之一,TiDB 目前支持从不同的存储和不同的索引中读取数据,索引选择得是否合理将很大程度上决定一个查询的运行速度。 +从存储引擎读取数据是 SQL 执行过程中最耗时的步骤之一。目前,TiDB 支持从不同的存储引擎和不同的索引读取数据。查询执行性能在很大程度上取决于是否选择了合适的索引。 -本章节将介绍 TiDB 如何选择索引去读入数据,以及相关的一些控制索引选择的方式。 +本文档介绍如何选择索引来访问表,以及一些相关的索引选择控制方法。 -## 读表 +## 访问表 -在介绍索引的选择之前,首先要了解 TiDB 有哪些读表的方式,这些方式的触发条件是什么,不同方式有什么区别,各有什么优劣。 +在介绍索引选择之前,了解 TiDB 访问表的方式、每种方式的触发条件、各自的差异以及优缺点非常重要。 -### 读表算子 +### 访问表的操作符 -| 读表算子 | 触发条件 | 适用场景 | 说明 | +| 操作符 | 触发条件 | 适用场景 | 说明 | | :------- | :------- | :------- | :---- | -| PointGet/BatchPointGet | 读表的范围是一个或多个单点范围 | 任何场景 | 如果能被触发,通常被认为是最快的算子,因为其直接调用 kvget 的接口进行计算,不走 coprocessor | -| TableReader | 无 | 任何场景 | 该 TableReader 算子用于 TiKV。从 TiKV 端直接扫描表数据,一般被认为是效率最低的算子,除非在 `_tidb_rowid` 这一列上存在范围查询,或者无其他可以选择的读表算子时,才会选择这个算子 | -| TableReader | 表在 TiFlash 节点上存在副本 | 需要读取的列比较少,但是需要计算的行很多 | 该 TableReader 算子用于 TiFlash。TiFlash 是列式存储,如果需要对少量的列和大量的行进行计算,一般会选择这个算子 | -| IndexReader | 表有一个或多个索引,且计算所需的列被包含在索引里 | 存在较小的索引上的范围查询,或者对索引列有顺序需求的时候 | 当存在多个索引的时候,会根据估算代价选择合理的索引 | -| IndexLookupReader | 表有一个或多个索引,且计算所需的列**不完全**被包含在索引里 | 同 IndexReader | 因为计算列不完全被包含在索引里,所以读完索引后需要回表,这里会比 IndexReader 多一些开销 | -| IndexMerge | 表有多个索引或多值索引 | 使用多值索引或同时使用多个索引的时候 | 可以通过 [optimizer hints](/optimizer-hints.md) 指定使用该算子,或让优化器根据代价估算自动选择该算子,参见[用 EXPLAIN 查看索引合并的 SQL 执行计划](/explain-index-merge.md) | +| PointGet / BatchPointGet | 在一个或多个单点范围内访问表时。 | 任何场景 | 如果触发,通常被认为是最快的操作符,因为它直接调用 kvget 接口执行计算,而不是调用 coprocessor 接口。 | +| TableReader | 无 | 任何场景 | 这个 TableReader 操作符是针对 TiKV 的。它通常被认为是效率最低的操作符,直接从 TiKV 层扫描表数据。只有在 `_tidb_rowid` 列上有范围查询,或者没有其他可选的访问表的操作符时才会被选择。 | +| TableReader | 表在 TiFlash 节点上有副本。 | 需要读取的列较少,但需要评估的行较多。 | 这个 TableReader 操作符是针对 TiFlash 的。TiFlash 是列式存储。如果需要计算少量列和大量行,建议选择此操作符。 | +| IndexReader | 表有一个或多个索引,且计算所需的列都包含在索引中。 | 当索引上有较小范围的查询,或者对索引列有排序要求时。 | 当存在多个索引时,基于成本估算选择合理的索引。 | +| IndexLookupReader | 表有一个或多个索引,但计算所需的列不完全包含在索引中。 | 与 IndexReader 相同。 | 由于索引不完全覆盖计算列,TiDB 需要在读取索引后从表中检索行。相比 IndexReader 操作符有额外的成本。 | +| IndexMerge | 表有多个索引或多值索引。 | 当使用多值索引或多个索引时。 | 要使用此操作符,可以指定[优化器提示](/optimizer-hints.md),或让优化器基于成本估算自动选择此操作符。详情请参见[使用 Index Merge 的执行计划](/explain-index-merge.md)。 | > **注意:** -> -> TableReader 是基于 `_tidb_rowid` 的索引,TiFlash 是列存索引,所以索引的选择即是读表算子的选择。 +> +> TableReader 操作符基于 `_tidb_rowid` 列索引,而 TiFlash 使用列存储索引,所以索引的选择就是访问表的操作符的选择。 -## 索引的选择 +## 索引选择规则 -TiDB 基于规则或基于代价来选择索引。基于的规则包括前置规则和 Skyline-Pruning。在选择索引时,TiDB 会先尝试前置规则。如果存在索引满足某一条前置规则,则直接选择该索引。否则,TiDB 会采用 Skyline-Pruning 来排除不合适的索引,然后基于每个读表算子的代价估算,选择代价最小的索引。 +TiDB 基于规则或成本选择索引。基于规则包括预规则和天际线剪枝。在选择索引时,TiDB 首先尝试预规则。如果某个索引满足预规则,TiDB 直接选择该索引。否则,TiDB 使用天际线剪枝排除不合适的索引,然后基于每个访问表操作符的成本估算选择成本最低的索引。 -### 基于规则选择 +### 基于规则的选择 -#### 前置规则 +#### 预规则 -TiDB 采用如下的启发式前置规则来选择索引: +TiDB 使用以下启发式预规则来选择索引: -+ 规则 1:如果存在索引满足“唯一性索引全匹配 + 不需要回表(即该索引生成的计划是 IndexReader)”时,直接选择该索引。 ++ 规则 1:如果某个索引满足"唯一索引完全匹配 + 不需要从表中检索行(即索引生成的计划是 IndexReader 操作符)",TiDB 直接选择该索引。 -+ 规则 2:如果存在索引满足“唯一性索引全匹配 + 需要回表(即该索引生成的计划是 IndexLookupReader)”时,选择满足该条件且回表行数最小的索引作为候选索引。 ++ 规则 2:如果某个索引满足"唯一索引完全匹配 + 需要从表中检索行(即索引生成的计划是 IndexLookupReader 操作符)",TiDB 选择需要从表中检索行数最少的索引作为候选索引。 -+ 规则 3:如果存在索引满足“普通索引不需要回表 + 读取行数小于一定阈值”时,选择满足该条件且读取行数最小的索引作为候选索引。 ++ 规则 3:如果某个索引满足"普通索引 + 不需要从表中检索行 + 需要读取的行数小于某个阈值",TiDB 选择需要读取行数最少的索引作为候选索引。 -+ 规则 4:如果规则 2 和 3 之中仅选出一条候选索引,则选择该候选索引。如果规则 2 和 3 均选出候选索引,则选择读取行数(读索引行数 + 回表行数)较小的索引。 ++ 规则 4:如果基于规则 2 和 3 只选出一个候选索引,选择该候选索引。如果分别基于规则 2 和 3 选出两个候选索引,选择需要读取行数较少的索引(索引行数 + 需要从表中检索的行数)。 -上述规则中的“索引全匹配”指每个索引列上均存在等值条件。在执行 `EXPLAIN FORMAT = 'verbose' ...` 语句时,如果前置规则匹配了某一索引,TiDB 会输出一条 NOTE 级别的 warning 提示该索引匹配了前置规则。 +上述规则中的"索引完全匹配"指每个索引列都有等值条件。执行 `EXPLAIN FORMAT = 'verbose' ...` 语句时,如果预规则匹配到某个索引,TiDB 会输出一个 NOTE 级别的警告,表明该索引匹配了预规则。 -在以下示例中,因为索引 `idx_b` 满足规则 2 中“唯一性索引全匹配 + 需要回表”的条件,TiDB 选择索引 `idx_b` 作为访问路径,`SHOW WARNING` 返回了索引 `idx_b` 命中前置规则的提示。 +在下面的示例中,因为索引 `idx_b` 满足规则 2 中的"唯一索引完全匹配 + 需要从表中检索行"条件,TiDB 选择索引 `idx_b` 作为访问路径,`SHOW WARNING` 返回一个说明索引 `idx_b` 匹配预规则的提示。 ```sql mysql> CREATE TABLE t(a INT PRIMARY KEY, b INT, c INT, UNIQUE INDEX idx_b(b)); @@ -71,19 +71,19 @@ mysql> SHOW WARNINGS; 1 row in set (0.00 sec) ``` -#### Skyline-Pruning +### 天际线剪枝 -Skyline-Pruning 是一个针对索引的启发式过滤规则,能降低错误估算导致选错索引的概率。Skyline-Pruning 从以下三个维度衡量一个索引的优劣: +天际线剪枝是一种启发式的索引过滤规则,可以减少由于错误估计导致的错误索引选择的概率。要判断一个索引,需要以下三个维度: -- 索引的列涵盖了多少访问条件。“访问条件”指的是可以转化为某列范围的 `where` 条件,如果某个索引的列集合涵盖的访问条件越多,那么它在这个维度上更优。 +- 索引列覆盖了多少访问条件。"访问条件"是可以转换为列范围的 where 条件。在这个维度上,索引列集覆盖的访问条件越多越好。 -- 选择该索引读表时,是否需要回表(即该索引生成的计划是 IndexReader 还是 IndexLookupReader)。不用回表的索引在这个维度上优于需要回表的索引。如果均需要回表,则比较索引的列涵盖了多少过滤条件。过滤条件指的是可以根据索引判断的 `where` 条件。如果某个索引的列集合涵盖的访问条件越多,则回表数量越少,那么它在这个维度上越优。 +- 选择该索引访问表时是否需要从表中检索行(即索引生成的计划是 IndexReader 操作符还是 IndexLookupReader 操作符)。在这个维度上,不需要从表中检索行的索引优于需要检索行的索引。如果两个索引都需要 TiDB 从表中检索行,则比较索引列覆盖的过滤条件数量。过滤条件指可以基于索引判断的 `where` 条件。如果一个索引的列集覆盖更多的访问条件,从表中检索的行数就越少,在这个维度上该索引就越好。 -+ 选择该索引是否能满足一定的顺序。因为索引的读取可以保证某些列集合的顺序,所以满足查询要求顺序的索引在这个维度上优于不满足的索引。 +- 选择索引是否满足某种顺序。因为索引读取可以保证某些列集的顺序,所以在这个维度上,满足查询顺序的索引优于不满足的索引。 -对于以上三种维度,如果索引 `idx_a` 在这三个维度上都不比 `idx_b` 差,且有一个维度比 `idx_b` 好,那么 TiDB 会优先选择 `idx_a`。在执行 `EXPLAIN FORMAT = 'verbose' ...` 语句时,如果 Skyline-Pruning 排除了某些索引,TiDB 会输出一条 NOTE 级别的 warning 提示哪些索引在 Skyline-Pruning 排除之后保留下来。 +对于上述三个维度,如果索引 `idx_a` 在所有三个维度上都不比索引 `idx_b` 差,并且在其中一个维度上比 `idx_b` 好,那么 `idx_a` 是更优选择。执行 `EXPLAIN FORMAT = 'verbose' ...` 语句时,如果天际线剪枝排除了某些索引,TiDB 会输出一个 NOTE 级别的警告,列出天际线剪枝排除后剩余的索引。 -在以下示例中,索引 `idx_b` 和 `idx_e` 均劣于 `idx_b_c`,因而被 Skyline-Pruning 排除,`SHOW WARNING` 的返回结果显示了经过 Skyline-Pruning 后剩余的索引。 +在下面的示例中,索引 `idx_b` 和 `idx_e` 都不如 `idx_b_c`,所以它们被天际线剪枝排除。`SHOW WARNING` 的返回结果显示了天际线剪枝后剩余的索引。 ```sql mysql> CREATE TABLE t(a INT PRIMARY KEY, b INT, c INT, d INT, e INT, INDEX idx_b(b), INDEX idx_b_c(b, c), INDEX idx_e(e)); @@ -108,48 +108,47 @@ mysql> SHOW WARNINGS; 1 row in set (0.00 sec) ``` -### 基于代价选择 +### 基于成本估算的选择 -在使用 Skyline-Pruning 规则排除了不合适的索引之后,索引的选择完全基于代价估算,读表的代价估算需要考虑以下几个方面: +在使用天际线剪枝规则排除不合适的索引后,索引的选择完全基于成本估算。访问表的成本估算需要考虑以下因素: -- 索引的每行数据在存储层的平均长度。 -- 索引生成的查询范围的行数量。 -- 索引的回表代价。 -- 索引查询时的范围数量。 +- 存储引擎中每行索引数据的平均长度。 +- 索引生成的查询范围中的行数。 +- 从表中检索行的成本。 +- 索引在查询执行过程中生成的范围数量。 -根据这些因子和代价模型,优化器会选择一个代价最低的索引进行读表。 +根据这些因素和成本模型,优化器选择成本最低的索引来访问表。 -#### 代价选择调优的常见问题 +#### 基于成本估算选择的常见调优问题 -1. 估算的行数量不准确? +1. 估计的行数不准确? - 一般是统计信息过期或者准确度不够造成的,可以重新执行 `ANALYZE TABLE` 或者修改 `ANALYZE TABLE` 的参数。 + 这通常是由于统计信息过期或不准确导致的。您可以重新执行 `ANALYZE TABLE` 语句或修改 `ANALYZE TABLE` 语句的参数。 -2. 统计信息准确,为什么读 TiFlash 更快,而优化器选择了 TiKV? +2. 统计信息准确,从 TiFlash 读取更快,但为什么优化器选择从 TiKV 读取? - 目前区别 TiFlash 和 TiKV 的代价模型还比较粗糙,可以调小 [`tidb_opt_seek_factor`](/system-variables.md#tidb_opt_seek_factor) 的值,让优化器倾向于选择 TiFlash。 + 目前,区分 TiFlash 和 TiKV 的成本模型仍然比较粗糙。您可以降低 [`tidb_opt_seek_factor`](/system-variables.md#tidb_opt_seek_factor) 参数的值,这样优化器会倾向于选择 TiFlash。 -3. 统计信息准确,某个索引要回表,但是它比另一个不用回表的索引实际执行更快,为什么选择了不用回表的索引? +3. 统计信息准确,索引 A 需要从表中检索行,但实际执行速度比不需要从表中检索行的索引 B 更快。为什么优化器选择索引 B? - 碰到这种情况,可能是代价估算时对于回表的代价计算得过大,可以调小 [`tidb_opt_network_factor`](/system-variables.md#tidb_opt_network_factor),降低回表的代价。 + 在这种情况下,可能是从表中检索行的成本估算过大。您可以降低 [`tidb_opt_network_factor`](/system-variables.md#tidb_opt_network_factor) 参数的值来减少从表中检索行的成本。 -## 控制索引的选择 +## 控制索引选择 -通过 [Optimizer Hints](/optimizer-hints.md) 可以实现单条查询对索引选择的控制。 +可以通过[优化器提示](/optimizer-hints.md)控制单个查询的索引选择。 -- `USE_INDEX`/`IGNORE_INDEX` 可以强制优化器使用/不使用某些索引。`FORCE_INDEX` 和 `USE_INDEX` 的作用相同。 - -- `READ_FROM_STORAGE` 可以强制优化器对于某些表选择 TiKV/TiFlash 的存储引擎进行查询。 +- `USE_INDEX` / `IGNORE_INDEX` 可以强制优化器使用/不使用某些索引。`FORCE_INDEX` 和 `USE_INDEX` 效果相同。 +- `READ_FROM_STORAGE` 可以强制优化器为某些表选择 TiKV / TiFlash 存储引擎来执行查询。 ## 使用多值索引 -[多值索引](/sql-statements/sql-statement-create-index.md#多值索引)和普通索引有所不同,TiDB 目前只会使用 [IndexMerge](/explain-index-merge.md) 来访问多值索引。因此要想使用多值索引进行数据访问,请确保 [`tidb_enable_index_merge`](/system-variables.md#tidb_enable_index_merge-从-v40-版本开始引入) 被设置为 `ON`。 +[多值索引](/sql-statements/sql-statement-create-index.md#多值索引)与普通索引不同。TiDB 目前只使用 [IndexMerge](/explain-index-merge.md) 来访问多值索引。因此,要使用多值索引进行数据访问,请确保系统变量 [`tidb_enable_index_merge`](/system-variables.md#tidb_enable_index_merge-new-in-v40) 的值设置为 `ON`。 -多值索引的使用限制请参考 [`CREATE INDEX`](/sql-statements/sql-statement-create-index.md#特性与限制)。 +关于多值索引的限制,请参考 [`CREATE INDEX`](/sql-statements/sql-statement-create-index.md#限制)。 -### 支持多值索引的场景 +### 支持的场景 -目前 TiDB 支持将 `json_member_of`、`json_contains` 和 `json_overlaps` 条件自动转换成 IndexMerge 来访问多值索引。既可以依赖优化器根据代价自动选择,也可通过 [`use_index_merge`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) optimizer hint 或 [`use_index`](/optimizer-hints.md#use_indext1_name-idx1_name--idx2_name-) 指定选择多值索引,见下面例子: +目前,TiDB 支持使用 IndexMerge 访问由 `json_member_of`、`json_contains` 和 `json_overlaps` 条件自动转换的多值索引。您可以依赖优化器基于成本自动选择 IndexMerge,或通过优化器提示 [`use_index_merge`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) 或 [`use_index`](/optimizer-hints.md#use_indext1_name-idx1_name--idx2_name-) 指定选择多值索引。请参见以下示例: ```sql mysql> CREATE TABLE t1 (j JSON, INDEX idx((CAST(j->'$.path' AS SIGNED ARRAY)))); -- 使用 '$.path' 作为路径创建多值索引 @@ -192,7 +191,7 @@ mysql> EXPLAIN SELECT /*+ use_index_merge(t1, idx) */ * FROM t1 WHERE JSON_OVERL 6 rows in set, 1 warning (0.00 sec) ``` -复合的多值索引,也一样可以使用 IndexMerge 进行访问: +复合多值索引也可以通过 IndexMerge 访问: ```sql CREATE TABLE t2 (a INT, j JSON, b INT, k JSON, INDEX idx(a, (CAST(j->'$.path' AS SIGNED ARRAY)), b), INDEX idx2(b, (CAST(k->'$.path' AS SIGNED ARRAY)))); @@ -201,7 +200,6 @@ EXPLAIN SELECT /*+ use_index_merge(t2, idx) */ * FROM t2 WHERE a=1 AND JSON_CONT EXPLAIN SELECT /*+ use_index_merge(t2, idx) */ * FROM t2 WHERE a=1 AND JSON_OVERLAPS((j->'$.path'), '[1, 2, 3]'); EXPLAIN SELECT /*+ use_index_merge(t2, idx, idx2) */ * FROM t2 WHERE (a=1 AND 1 member of (j->'$.path')) AND (b=1 AND 2 member of (k->'$.path')); ``` - ```sql > EXPLAIN SELECT /*+ use_index_merge(t2, idx) */ * FROM t2 WHERE a=1 AND (1 MEMBER OF (j->'$.path')) AND b=2; +-------------------------------+---------+-----------+-----------------------------------------------------------------------------------+-----------------------------------------------------+ @@ -246,7 +244,7 @@ EXPLAIN SELECT /*+ use_index_merge(t2, idx, idx2) */ * FROM t2 WHERE (a=1 AND 1 +-------------------------------+---------+-----------+-----------------------------------------------------------------------------------+-----------------------------------------------------+ ``` -同时,多值索引可以和普通索引共同组成 IndexMerge 使用。例如: +TiDB 也可以使用 IndexMerge 同时访问多值索引和普通索引。例如: ```sql CREATE TABLE t3(j1 JSON, j2 JSON, a INT, INDEX k1((CAST(j1->'$.path' AS SIGNED ARRAY))), INDEX k2((CAST(j2->'$.path' AS SIGNED ARRAY))), INDEX ka(a)); @@ -277,13 +275,13 @@ EXPLAIN SELECT /*+ use_index_merge(t3, k1, k2, ka) */ * FROM t3 WHERE 1 member o +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+---------------------------------------------+ ``` -对于由 `OR` 或 `AND` 连接而成的多个 `json_member_of`、`json_contains` 或 `json_overlaps` 条件,需要满足以下条件才能使用 IndexMerge 访问: +如果几个 `json_member_of`、`json_contains` 或 `json_overlaps` 条件通过 `OR` 或 `AND` 连接,它们需要满足以下要求才能使用 IndexMerge 访问多值索引: ```sql CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), INDEX mvi2((CAST(j->'$.b' AS UNSIGNED ARRAY)))); ``` -- 对于由 `OR` 连接而成的条件,其中每个子条件都需要分别能够使用 IndexMerge 访问。例如: +- 对于用 `OR` 连接的条件,每个条件都需要能够分别用 IndexMerge 访问。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t4, mvi1) */ * FROM t4 WHERE json_overlaps(j->'$.a', '[1, 2]') OR json_overlaps(j->'$.a', '[3, 4]'); @@ -305,7 +303,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I | └─TableRowIDScan_10(Probe) | 39.94 | cop[tikv] | table:t4 | keep order:false, stats:pseudo | +----------------------------------+---------+-----------+-----------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -- json_length(j->'$.a') = 3 无法使用 IndexMerge 访问,因此该 SQL 整体无法使用 IndexMerge 访问 + -- json_length(j->'$.a') = 3 不能直接用 IndexMerge 访问,所以 TiDB 不能为这个 SQL 语句使用 IndexMerge。 > EXPLAIN SELECT /*+ use_index_merge(t4, mvi1) */ * FROM t4 WHERE json_overlaps(j->'$.a', '[1, 2]') OR json_length(j->'$.a') = 3; +-------------------------+----------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -323,7 +321,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I +---------+------+----------------------------+ ``` -- 对于由 `AND` 连接而成的条件,其中一部分子条件需要分别能够使用 IndexMerge 访问。最终使用 IndexMerge 访问时,也只能利用这一部分条件。例如: +- 对于用 `AND` 连接的条件,其中一些条件需要能够分别用 IndexMerge 访问。TiDB 只能使用 IndexMerge 访问这些条件的多值索引。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t4, mvi1) */ * FROM t4 WHERE json_contains(j->'$.a', '[1, 2]') AND json_contains(j->'$.a', '[3, 4]'); @@ -343,7 +341,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I | └─TableRowIDScan_9(Probe) | 0.00 | cop[tikv] | table:t4 | keep order:false, stats:pseudo | +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+---------------------------------------------+ - -- json_length(j->'$.a') = 3 无法使用 IndexMerge 访问,因此只有另外两个 json_contains 表达式可以使用 IndexMerge 访问,而 json_length(j->'$.a') = 3 成为一个单独的 Selection 算子 + -- json_length(j->'$.a') = 3 不能直接用 IndexMerge 访问,所以 TiDB 使用 IndexMerge 访问其他两个 json_contains 条件,而 json_length(j->'$.a') = 3 成为一个 Selection 操作符。 > EXPLAIN SELECT /*+ use_index_merge(t4, mvi1) */ * FROM t4 WHERE json_contains(j->'$.a', '[1, 2]') AND json_contains(j->'$.a', '[3, 4]') AND json_length(j->'$.a') = 2; +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+----------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -357,10 +355,9 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I | └─TableRowIDScan_9 | 0.00 | cop[tikv] | table:t4 | keep order:false, stats:pseudo | +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+----------------------------------------------------+ ``` +- 所有用于 IndexMerge 的条件必须匹配连接它们的 `OR` 或 `AND` 的语义。 -- 用于构成整体 IndexMerge 计划的每个子条件,需要分别符合用于连接的 `OR` 或 `AND` 的语义。具体如下: - - - `json_contains` 由 `AND` 连接,符合语义。例如: + - 如果 `json_contains` 用 `AND` 连接,它匹配语义。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE json_contains(j->'$.a', '[1]') AND json_contains(j->'$.b', '[2, 3]'); @@ -379,7 +376,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I | └─TableRowIDScan_8(Probe) | 0.00 | cop[tikv] | table:t4 | keep order:false, stats:pseudo | +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+---------------------------------------------+ - -- 不符合语义,如前文所述,该 SQL 整体无法使用 IndexMerge 访问 + -- 条件不匹配语义,所以 TiDB 不能为这个 SQL 语句使用 IndexMerge,如上所述。 > EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE json_contains(j->'$.a', '[1]') OR json_contains(j->'$.b', '[2, 3]'); +-------------------------+----------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -390,7 +387,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I +-------------------------+----------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ ``` - - `json_overlaps` 由 `OR` 连接,符合语义。例如: + - 如果 `json_overlaps` 用 `OR` 连接,它匹配语义。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE json_overlaps(j->'$.a', '[1]') OR json_overlaps(j->'$.b', '[2, 3]'); @@ -410,7 +407,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I | └─TableRowIDScan_9(Probe) | 29.97 | cop[tikv] | table:t4 | keep order:false, stats:pseudo | +---------------------------------+---------+-----------+-----------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ - -- 不符合语义,如前文所述,只能利用一部分条件使用 IndexMerge 访问 + -- 条件不匹配语义,所以 TiDB 只能为这个 SQL 语句的部分条件使用 IndexMerge,如上所述。 > EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE json_overlaps(j->'$.a', '[1]') AND json_overlaps(j->'$.b', '[2, 3]'); +---------------------------------+---------+-----------+-----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -422,7 +419,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I +---------------------------------+---------+-----------+-----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+ ``` - - `json_member_of` 由 `OR` 或 `AND` 连接,均符合语义。例如: + - 如果 `json_member_of` 用 `OR` 或 `AND` 连接,它匹配语义。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE 1 member of (j->'$.a') AND 2 member of (j->'$.b') AND 3 member of (j->'$.a'); @@ -453,10 +450,10 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+---------------------------------------------+ ``` - - 包含多个值的 `json_contains` 由 `OR` 连接,或包含多个值的 `json_overlaps` 由 `AND` 连接,不符合语义,而如果它们只包含一个值则符合语义。例如: + - 如果包含多个值的 `json_contains` 条件用 `OR` 连接,或包含多个值的 `json_overlaps` 条件用 `AND` 连接,它们不匹配语义,但如果它们只包含一个值,则匹配语义。例如: ```sql - -- 不符合语义的例子可参考前文,此处只举符合语义的例子 + -- 参考前面的示例了解不匹配语义的条件。以下仅提供匹配语义的条件示例。 EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE json_overlaps(j->'$.a', '[1]') AND json_overlaps(j->'$.b', '[2]'); EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE json_contains(j->'$.a', '[1]') OR json_contains(j->'$.b', '[2]'); ``` @@ -483,8 +480,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I | └─TableRowIDScan_7(Probe) | 19.99 | cop[tikv] | table:t4 | keep order:false, stats:pseudo | +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+---------------------------------------------+ ``` - - - 当 `OR` 和 `AND` 同时出现(本质上是 `OR` 和 `AND` 嵌套)时,构成 IndexMerge 的条件只能全部符合 `OR` 的语义或者全部符合 `AND` 的语义,不能部分符合 `OR` 的语义而另一部分符合 `AND` 的语义。例如: + - 当同时使用 `OR` 和 `AND` 连接条件(本质上是嵌套的 `OR` 和 `AND`)时,构成 IndexMerge 的条件必须要么全部匹配 `OR` 的语义,要么全部匹配 `AND` 的语义,不能部分匹配 `OR` 的语义,部分匹配 `AND` 的语义。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE 1 member of (j->'$.a') AND (2 member of (j->'$.b') OR 3 member of (j->'$.a')); @@ -492,7 +488,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I ``` ```sql - -- 只有符合 OR 语义的 2 member of (j->'$.b') 和 3 member of (j->'$.a') 构成了 IndexMerge,而符合 AND 语义的 1 member of (j->'$.a') 没有构成 IndexMerge + -- 只有匹配 OR 语义的 2 member of (j->'$.b') 和 3 member of (j->'$.a') 构成 IndexMerge。匹配 AND 语义的 1 member of (j->'$.a') 不包括在内。 > EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE 1 member of (j->'$.a') AND (2 member of (j->'$.b') OR 3 member of (j->'$.a')); +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -504,7 +500,7 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I | └─TableRowIDScan_7 | 19.99 | cop[tikv] | table:t4 | keep order:false, stats:pseudo | +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -- 只有符合 OR 语义的 1 member of (j->'$.a') 和 3 member of (j->'$.a') 构成了 IndexMerge,而嵌套的符合 AND 语义的 2 member of (j->'$.b') 没有构成 IndexMerge + -- 只有匹配 OR 语义的 1 member of (j->'$.a') 和 2 member of (j->'$.a') 构成 IndexMerge。匹配 AND 语义的 2 member of (j->'$.b') 不包括在内。 > EXPLAIN SELECT /*+ use_index_merge(t4, mvi1, mvi2) */ * FROM t4 WHERE 1 member of (j->'$.a') OR (2 member of (j->'$.b') AND 3 member of (j->'$.a')); +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -517,14 +513,16 @@ CREATE TABLE t4(a INT, j JSON, INDEX mvi1((CAST(j->'$.a' AS UNSIGNED ARRAY))), I +-------------------------------+---------+-----------+-----------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ``` -如果表达式包含嵌套的 `OR` 或 `AND`,或者表达式需要进行展开等变形之后才能直接一一对应各索引列,TiDB 可能无法使用 IndexMerge 或不能充分利用所有过滤条件。建议针对具体场景预先进行测试验证。以下是部分场景示例: +如果条件包含嵌套的 `OR`/`AND`,或者条件在转换(如展开)后才对应索引列,TiDB 可能无法使用 IndexMerge 或无法充分利用所有条件。建议验证每个具体情况的行为。 + +以下是一些示例: ```sql CREATE TABLE t5 (a INT, j JSON, b INT, k JSON, INDEX idx(a, (CAST(j AS SIGNED ARRAY))), INDEX idx2(b, (CAST(k as SIGNED ARRAY)))); CREATE TABLE t6 (a INT, j JSON, b INT, k JSON, INDEX idx(a, (CAST(j AS SIGNED ARRAY)), b), INDEX idx2(a, (CAST(k as SIGNED ARRAY)), b)); ``` -当 `AND` 嵌套在由 `OR` 连接的条件中,且嵌套的 `AND` 所连接的子条件与多列索引的各个列能够一一对应时,TiDB 通常能够充分利用过滤条件。例如: +如果 `AND` 嵌套在用 `OR` 连接的条件中,且用 `AND` 连接的子条件对应多列索引的精确列,TiDB 通常可以充分利用这些条件。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t5, idx, idx2) */ * FROM t5 WHERE (a=1 AND 1 member of (j)) OR (b=2 AND 2 member of (k)); @@ -542,7 +540,7 @@ EXPLAIN SELECT /*+ use_index_merge(t5, idx, idx2) */ * FROM t5 WHERE (a=1 AND 1 +-------------------------------+---------+-----------+----------------------------------------------------+-------------------------------------------------+ ``` -当单个 `OR` 嵌套在由 `AND` 连接的条件中,且 `OR` 所连接的子条件通过展开表达式可以直接对应索引列时,TiDB 通常能够充分利用过滤条件。例如: +如果单个 `OR` 嵌套在用 `AND` 连接的条件中,且用 `OR` 连接的子条件在展开后对应索引列,TiDB 通常可以充分利用这些条件。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t6, idx, idx2) */ * FROM t6 WHERE a=1 AND (1 member of (j) OR 2 member of (k)); @@ -560,7 +558,7 @@ EXPLAIN SELECT /*+ use_index_merge(t6, idx, idx2) */ * FROM t6 WHERE a=1 AND (1 +-------------------------------+---------+-----------+-------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ ``` -当多个 `OR` 嵌套在由 `AND` 连接的条件中,且 `OR` 所连接的子条件需要展开表达式才能直接对应索引列的时候,TiDB 可能无法充分利用过滤条件。例如: +如果多个 `OR` 嵌套在用 `AND` 连接的条件中,且用 `OR` 连接的子条件需要展开才能对应索引列,TiDB 可能无法充分利用所有条件。例如: ```sql EXPLAIN SELECT /*+ use_index_merge(t6, idx, idx2) */ * FROM t6 WHERE a=1 AND (1 member of (j) OR 2 member of (k)) and (b = 1 OR b = 2); @@ -568,34 +566,34 @@ EXPLAIN SELECT /*+ use_index_merge(t6, idx, idx2) */ * FROM t6 WHERE a=1 AND ((1 ``` ```sql --- 由于目前实现上的限制,(b = 1 or b = 2) 没有参与构成 IndexMerge,而是成为了一个单独的 Selection 算子 +-- 由于当前实现的限制,(b = 1 or b = 2) 不构成 IndexMerge,而是成为一个 Selection 操作符 > EXPLAIN SELECT /*+ use_index_merge(t6, idx, idx2) */ * FROM t6 WHERE a=1 AND (1 member of (j) OR 2 member of (k)) AND (b = 1 OR b = 2); +-------------------------------+---------+-----------+-------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | +-------------------------------+---------+-----------+-------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | IndexMerge_9 | 0.20 | root | | type: union | -| ├─IndexRangeScan_5(Build) | 0.10 | cop[tikv] | table:t6, index:idx(a, cast(`j` as signed array), b) | range:[1 1,1 1], keep order:false, stats:pseudo | -| ├─IndexRangeScan_6(Build) | 0.10 | cop[tikv] | table:t6, index:idx2(a, cast(`k` as signed array), b) | range:[1 2,1 2], keep order:false, stats:pseudo | +| ├─IndexRangeScan_5(Build) | 0.10 | cop[tikv] | table:t6, index:idx(a, cast(`j`, _utf8'$.a') as unsigned array), b) | range:[1 1,1 1], keep order:false, stats:pseudo | +| ├─IndexRangeScan_6(Build) | 0.10 | cop[tikv] | table:t6, index:idx2(a, cast(`k`, _utf8'$.a') as unsigned array), b) | range:[1 2,1 2], keep order:false, stats:pseudo | | └─Selection_8(Probe) | 0.20 | cop[tikv] | | eq(test.t6.a, 1), or(eq(test.t6.b, 1), eq(test.t6.b, 2)), or(json_memberof(cast(1, json BINARY), test.t6.j), json_memberof(cast(2, json BINARY), test.t6.k)) | | └─TableRowIDScan_7 | 0.20 | cop[tikv] | table:t6 | keep order:false, stats:pseudo | +-------------------------------+---------+-----------+-------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ --- 将 SQL 中由 AND 连接的两个 OR 表达式手动展开之后,TiDB 能够充分利用这些条件 +-- 如果手动展开两个 OR 条件,TiDB 可以充分利用这些条件 > EXPLAIN SELECT /*+ use_index_merge(t6, idx, idx2) */ * FROM t6 WHERE a=1 AND ((1 member of (j) AND b = 1) OR (1 member of (j) AND b = 2) OR (2 member of (k) AND b = 1) OR (2 member of (k) AND b = 2)); -+-------------------------------+---------+-----------+-------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+-------------------------------+---------+-----------+-------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| IndexMerge_11 | 0.00 | root | | type: union | -| ├─IndexRangeScan_5(Build) | 0.00 | cop[tikv] | table:t6, index:idx(a, cast(`j` as signed array), b) | range:[1 1 1,1 1 1], keep order:false, stats:pseudo | -| ├─IndexRangeScan_6(Build) | 0.00 | cop[tikv] | table:t6, index:idx(a, cast(`j` as signed array), b) | range:[1 1 2,1 1 2], keep order:false, stats:pseudo | -| ├─IndexRangeScan_7(Build) | 0.00 | cop[tikv] | table:t6, index:idx2(a, cast(`k` as signed array), b) | range:[1 2 1,1 2 1], keep order:false, stats:pseudo | -| ├─IndexRangeScan_8(Build) | 0.00 | cop[tikv] | table:t6, index:idx2(a, cast(`k` as signed array), b) | range:[1 2 2,1 2 2], keep order:false, stats:pseudo | ++-------------------------------+---------+-----------+-------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------------+---------+-----------+-------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| IndexMerge_11 | 0.00 | root | | type: union | +| ├─IndexRangeScan_5(Build) | 0.00 | cop[tikv] | table:t6, index:idx(a, cast(`j` as signed array), b) | range:[1 1 1,1 1 1], keep order:false, stats:pseudo | +| ├─IndexRangeScan_6(Build) | 0.00 | cop[tikv] | table:t6, index:idx(a, cast(`j` as signed array), b) | range:[1 1 2,1 1 2], keep order:false, stats:pseudo | +| ├─IndexRangeScan_7(Build) | 0.00 | cop[tikv] | table:t6, index:idx2(a, cast(`k` as signed array), b) | range:[1 2 1,1 2 1], keep order:false, stats:pseudo | +| ├─IndexRangeScan_8(Build) | 0.00 | cop[tikv] | table:t6, index:idx2(a, cast(`k` as signed array), b) | range:[1 2 2,1 2 2], keep order:false, stats:pseudo | | └─Selection_10(Probe) | 0.00 | cop[tikv] | | eq(test.t6.a, 1), or(or(and(json_memberof(cast(1, json BINARY), test.t6.j), eq(test.t6.b, 1)), and(json_memberof(cast(1, json BINARY), test.t6.j), eq(test.t6.b, 2))), or(and(json_memberof(cast(2, json BINARY), test.t6.k), eq(test.t6.b, 1)), and(json_memberof(cast(2, json BINARY), test.t6.k), eq(test.t6.b, 2)))) | -| └─TableRowIDScan_9 | 0.00 | cop[tikv] | table:t6 | keep order:false, stats:pseudo | -+-------------------------------+---------+-----------+-------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| └─TableRowIDScan_9 | 0.00 | cop[tikv] | table:t6 | keep order:false, stats:pseudo | ++-------------------------------+---------+-----------+-------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ``` -受限于多值索引的特性,当多值索引无法生效时,使用 [`use_index`](/optimizer-hints.md#use_indext1_name-idx1_name--idx2_name-) 可能会返回 `Can't find a proper physical plan for this query` 的错误,而使用 [`use_index_merge`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) 不会,因此建议使用 `use_index_merge`: +受多值索引当前实现的限制,使用 [`use_index`](/optimizer-hints.md#use_indext1_name-idx1_name--idx2_name-) 可能会返回 `Can't find a proper physical plan for this query` 错误,而使用 [`use_index_merge`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) 不会返回这样的错误。因此,如果您想使用多值索引,建议使用 `use_index_merge`。 ```sql mysql> EXPLAIN SELECT /*+ use_index(t3, idx) */ * FROM t3 WHERE ((1 member of (j)) AND (2 member of (j))) OR ((3 member of (j)) AND (4 member of (j))); @@ -612,11 +610,11 @@ mysql> EXPLAIN SELECT /*+ use_index_merge(t3, idx) */ * FROM t3 WHERE ((1 member 3 rows in set, 2 warnings (0.00 sec) ``` -### 多值索引与执行计划缓存 +### 多值索引和计划缓存 -通过 `member of` 条件选择的多值索引的执行计划可以被缓存。如果执行计划是通过 `JSON_CONTAINS()` 或 `JSON_OVERLAPS()` 函数选择的多值索引,则该计划暂时无法被缓存。 +使用 `member of` 选择多值索引的查询计划可以被缓存。使用 `JSON_CONTAINS()` 或 `JSON_OVERLAPS()` 函数选择多值索引的查询计划不能被缓存。 -下面是可以缓存的例子: +以下是一些查询计划可以被缓存的示例: ```sql mysql> CREATE TABLE t5 (j1 JSON, j2 JSON, INDEX idx1((CAST(j1 AS SIGNED ARRAY)))); @@ -654,7 +652,7 @@ Empty set (0.00 sec) mysql> EXECUTE st USING @a, @b; Empty set (0.00 sec) -mysql> SELECT @@LAST_PLAN_FROM_CACHE; -- can hit plan cache if the JSON_CONTAINS doesn't impact index selection +mysql> SELECT @@LAST_PLAN_FROM_CACHE; -- 如果 JSON_CONTAINS 不影响索引选择,可以命中计划缓存 +------------------------+ | @@LAST_PLAN_FROM_CACHE | +------------------------+ @@ -663,7 +661,7 @@ mysql> SELECT @@LAST_PLAN_FROM_CACHE; -- can hit plan cache if the JSON_CONTAINS 1 row in set (0.00 sec) ``` -下面是无法缓存的例子: +以下是一些查询计划不能被缓存的示例: ```sql mysql> PREPARE st2 FROM 'SELECT /*+ use_index(t5, idx1) */ * FROM t5 WHERE JSON_CONTAINS(j1, ?)'; @@ -675,7 +673,7 @@ Query OK, 0 rows affected (0.01 sec) mysql> EXECUTE st2 USING @a; Empty set, 1 warning (0.00 sec) -mysql> SHOW WARNINGS; -- cannot hit plan cache since the JSON_CONTAINS predicate might affect index selection +mysql> SHOW WARNINGS; -- 由于 JSON_CONTAINS 谓词可能影响索引选择,无法命中计划缓存 +---------+------+-------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+-------------------------------------------------------------------------------------------------------+ diff --git a/clustered-indexes.md b/clustered-indexes.md index 447f065ae1e8..c01ed6f1617f 100644 --- a/clustered-indexes.md +++ b/clustered-indexes.md @@ -1,43 +1,45 @@ --- title: 聚簇索引 -summary: 本文档介绍了聚簇索引的概念、使用场景、使用方法、限制和兼容性。 +summary: 了解聚簇索引的概念、使用场景、用法、限制和兼容性。 --- # 聚簇索引 -聚簇索引 (clustered index) 是 TiDB 从 v5.0 开始支持的特性,用于控制含有主键的表数据的存储方式。通过使用聚簇索引,TiDB 可以更好地组织数据表,从而提高某些查询的性能。有些数据库管理系统将聚簇索引表称为“索引组织表” (index-organized tables)。 +TiDB 从 v5.0 开始支持聚簇索引功能。此功能控制包含主键的表中数据的存储方式。它使 TiDB 能够以一种可以提高某些查询性能的方式组织表。 -目前 TiDB 中含有主键的表分为以下两类: +这里的 _聚簇_ 指的是 _数据存储的组织方式_,而不是 _一组协同工作的数据库服务器_。某些数据库管理系统将聚簇索引表称为 _索引组织表_ (IOT)。 -- `NONCLUSTERED`,表示该表的主键为非聚簇索引。在非聚簇索引表中,行数据的键由 TiDB 内部隐式分配的 `_tidb_rowid` 构成,而主键本质上是唯一索引,因此非聚簇索引表存储一行至少需要两个键值对,分别为 +目前,TiDB 中包含主键的表分为以下两类: + +- `NONCLUSTERED`:表的主键是非聚簇索引。在具有非聚簇索引的表中,行数据的键由 TiDB 隐式分配的内部 `_tidb_rowid` 组成。由于主键本质上是唯一索引,具有非聚簇索引的表需要至少两个键值对来存储一行数据,即: - `_tidb_rowid`(键)- 行数据(值) - - 主键列数据(键) - `_tidb_rowid`(值) -- `CLUSTERED`,表示该表的主键为聚簇索引。在聚簇索引表中,行数据的键由用户给定的主键列数据构成,因此聚簇索引表存储一行至少只要一个键值对,即 - - 主键列数据(键) - 行数据(值) + - 主键数据(键)- `_tidb_rowid`(值) +- `CLUSTERED`:表的主键是聚簇索引。在具有聚簇索引的表中,行数据的键由用户提供的主键数据组成。因此,具有聚簇索引的表只需要一个键值对来存储一行数据,即: + - 主键数据(键)- 行数据(值) > **注意:** > -> TiDB 仅支持根据表的主键来进行聚簇操作。聚簇索引启用时,“主键”和“聚簇索引”两个术语在一些情况下可互换使用。主键指的是约束(一种逻辑属性),而聚簇索引描述的是数据存储的物理实现。 +> TiDB 仅支持通过表的 `PRIMARY KEY` 进行聚簇。启用聚簇索引后,_`PRIMARY KEY`_ 和 _聚簇索引_ 这两个术语可能会互换使用。`PRIMARY KEY` 指的是约束(逻辑属性),而聚簇索引描述了数据存储的物理实现方式。 ## 使用场景 -相较于非聚簇索引表,聚簇索引表在以下几个场景中,性能和吞吐量都有较大优势: +与具有非聚簇索引的表相比,具有聚簇索引的表在以下场景中具有更大的性能和吞吐量优势: -- 插入数据时会减少一次从网络写入索引数据。 -- 等值条件查询仅涉及主键时会减少一次从网络读取数据。 -- 范围条件查询仅涉及主键时会减少多次从网络读取数据。 -- 等值或范围条件查询仅涉及主键的前缀时会减少多次从网络读取数据。 ++ 当插入数据时,聚簇索引减少了一次网络写入索引数据的操作。 ++ 当查询只涉及主键的等值条件时,聚簇索引减少了一次网络读取索引数据的操作。 ++ 当查询只涉及主键的范围条件时,聚簇索引减少了多次网络读取索引数据的操作。 ++ 当查询只涉及主键前缀的等值或范围条件时,聚簇索引减少了多次网络读取索引数据的操作。 -另一方面,聚簇索引表也存在一定的劣势: +另一方面,具有聚簇索引的表也有一些缺点。请参见以下内容: -- 批量插入大量取值相邻的主键时,可能会产生较大的写热点问题。 -- 当使用大于 64 位的数据类型作为主键时,可能导致表数据需要占用更多的存储空间。该现象在存在多个二级索引时尤为明显。 +- 当插入大量值相近的主键时,可能会出现写入热点问题。 +- 如果主键的数据类型大于 64 位,表数据会占用更多存储空间,特别是当存在多个二级索引时。 -## 使用方法 +## 用法 -### 创建聚簇索引表 +### 创建具有聚簇索引的表 -从 TiDB 版本 5.0 开始,要指定一个表的主键是否使用聚簇索引,可以在 `CREATE TABLE` 语句中将 `CLUSTERED` 或者 `NONCLUSTERED` 非保留关键字标注在 `PRIMARY KEY` 后面,例如: +从 TiDB v5.0 开始,你可以在 `CREATE TABLE` 语句中的 `PRIMARY KEY` 后添加非保留关键字 `CLUSTERED` 或 `NONCLUSTERED` 来指定表的主键是否为聚簇索引。例如: ```sql CREATE TABLE t (a BIGINT PRIMARY KEY CLUSTERED, b VARCHAR(255)); @@ -48,9 +50,9 @@ CREATE TABLE t (a BIGINT, b VARCHAR(255), PRIMARY KEY(a, b) CLUSTERED); CREATE TABLE t (a BIGINT, b VARCHAR(255), PRIMARY KEY(a, b) NONCLUSTERED); ``` -注意,列定义中的 `KEY` 和 `PRIMARY KEY` 含义相同。 +注意,在列定义中,关键字 `KEY` 和 `PRIMARY KEY` 具有相同的含义。 -此外,TiDB 支持使用[可执行的注释语法](/comment-syntax.md)指定聚簇索引属性: +你也可以使用 TiDB 中的[注释语法](/comment-syntax.md)来指定主键的类型。例如: ```sql CREATE TABLE t (a BIGINT PRIMARY KEY /*T![clustered_index] CLUSTERED */, b VARCHAR(255)); @@ -59,44 +61,44 @@ CREATE TABLE t (a BIGINT, b VARCHAR(255), PRIMARY KEY(a, b) /*T![clustered_index CREATE TABLE t (a BIGINT, b VARCHAR(255), PRIMARY KEY(a, b) /*T![clustered_index] NONCLUSTERED */); ``` -对于未显式指定该关键字的语句,默认行为受系统变量 [`@@global.tidb_enable_clustered_index`](/system-variables.md#tidb_enable_clustered_index-从-v50-版本开始引入) 影响。该变量有三个取值: +对于未明确指定关键字 `CLUSTERED`/`NONCLUSTERED` 的语句,默认行为由系统变量 [`@@global.tidb_enable_clustered_index`](/system-variables.md#tidb_enable_clustered_index-new-in-v50) 控制。该变量支持的值如下: -- `OFF` 表示所有主键默认使用非聚簇索引。 -- `ON` 表示所有主键默认使用聚簇索引。 -- `INT_ONLY` 此时的行为受配置项 `alter-primary-key` 控制。如果该配置项取值为 `true`,则所有主键默认使用非聚簇索引;如果该配置项取值为 `false`,则由单个整数类型的列构成的主键默认使用聚簇索引,其他类型的主键默认使用非聚簇索引。 +- `OFF` 表示默认将主键创建为非聚簇索引。 +- `ON` 表示默认将主键创建为聚簇索引。 +- `INT_ONLY` 表示行为由配置项 `alter-primary-key` 控制。如果 `alter-primary-key` 设置为 `true`,则默认将主键创建为非聚簇索引。如果设置为 `false`,则仅将由整数列组成的主键创建为聚簇索引。 -系统变量 `@@global.tidb_enable_clustered_index` 本身的默认值为 `ON`。 +`@@global.tidb_enable_clustered_index` 的默认值为 `ON`。 -### 添加、删除聚簇索引 +### 添加或删除聚簇索引 -目前 TiDB 不支持在建表之后添加或删除聚簇索引,也不支持聚簇索引和非聚簇索引的互相转换。例如: +TiDB 不支持在表创建后添加或删除聚簇索引。也不支持聚簇索引和非聚簇索引之间的相互转换。例如: ```sql -ALTER TABLE t ADD PRIMARY KEY(b, a) CLUSTERED; -- 暂不支持 -ALTER TABLE t DROP PRIMARY KEY; -- 如果主键为聚簇索引,则不支持 -ALTER TABLE t DROP INDEX `PRIMARY`; -- 如果主键为聚簇索引,则不支持 +ALTER TABLE t ADD PRIMARY KEY(b, a) CLUSTERED; -- 当前不支持。 +ALTER TABLE t DROP PRIMARY KEY; -- 如果主键是聚簇索引,则不支持。 +ALTER TABLE t DROP INDEX `PRIMARY`; -- 如果主键是聚簇索引,则不支持。 ``` -### 添加、删除非聚簇索引 +### 添加或删除非聚簇索引 -TiDB 支持在建表之后添加或删除非聚簇索引。此时可以选择显式指定 `NONCLUSTERED` 关键字或省略关键字: +TiDB 支持在表创建后添加或删除非聚簇索引。你可以显式指定关键字 `NONCLUSTERED` 或省略它。例如: ```sql ALTER TABLE t ADD PRIMARY KEY(b, a) NONCLUSTERED; -ALTER TABLE t ADD PRIMARY KEY(b, a); -- 不指定关键字,则为非聚簇索引 +ALTER TABLE t ADD PRIMARY KEY(b, a); -- 如果省略关键字,主键默认为非聚簇索引。 ALTER TABLE t DROP PRIMARY KEY; ALTER TABLE t DROP INDEX `PRIMARY`; ``` -### 查询主键是否为聚簇索引 +### 检查主键是否为聚簇索引 -可通过以下方式来确定一张表的主键是否使用了聚簇索引: +你可以使用以下方法之一来检查表的主键是否为聚簇索引: -- 执行语句 `SHOW CREATE TABLE`。 -- 执行语句 `SHOW INDEX FROM`。 +- 执行 `SHOW CREATE TABLE` 命令。 +- 执行 `SHOW INDEX FROM` 命令。 - 查询系统表 `information_schema.tables` 中的 `TIDB_PK_TYPE` 列。 -通过 `SHOW CREATE TABLE` 查看,`PRIMARY KEY` 的属性可能为 `CLUSTERED` 或 `NONCLUSTERED`: +通过运行 `SHOW CREATE TABLE` 命令,你可以看到 `PRIMARY KEY` 的属性是 `CLUSTERED` 还是 `NONCLUSTERED`。例如: ```sql mysql> SHOW CREATE TABLE t; @@ -112,7 +114,7 @@ mysql> SHOW CREATE TABLE t; 1 row in set (0.01 sec) ``` -通过 `SHOW INDEX FROM` 查看,`Clustered` 一列可能的结果为 `Yes` 或 `No`: +通过运行 `SHOW INDEX FROM` 命令,你可以检查结果中 `Clustered` 列是否显示 `YES` 或 `NO`。例如: ```sql mysql> SHOW INDEX FROM t; @@ -124,7 +126,7 @@ mysql> SHOW INDEX FROM t; 1 row in set (0.01 sec) ``` -查询 `information_schema.tables` 系统表中的 `TIDB_PK_TYPE` 列,可能的结果为 `CLUSTERED` 或 `NONCLUSTERED`: +你也可以查询系统表 `information_schema.tables` 中的 `TIDB_PK_TYPE` 列,看结果是 `CLUSTERED` 还是 `NONCLUSTERED`。例如: ```sql mysql> SELECT TIDB_PK_TYPE FROM information_schema.tables WHERE table_schema = 'test' AND table_name = 't'; @@ -138,24 +140,24 @@ mysql> SELECT TIDB_PK_TYPE FROM information_schema.tables WHERE table_schema = ' ## 限制 -目前 TiDB 的聚簇索引具有以下几类限制: +目前,聚簇索引功能有几种不同类型的限制。请参见以下内容: -- 明确不支持且没有支持计划的使用限制: - - 不支持与 [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md) 一起使用;[`PRE_SPLIT_REGIONS`](/sql-statements/sql-statement-split-region.md#pre_split_regions) 在非 [`AUTO_RANDOM`](/auto-random.md) 的聚簇索引表上不生效。 - - 不支持对聚簇索引表进行降级。如需降级,请使用逻辑备份工具迁移数据。 -- 尚未支持,但未来有计划支持的使用限制: - - 尚未支持通过 `ALTER TABLE` 语句增加、删除、修改聚簇索引。 -- 特定版本的限制: - - 在 v5.0 版本中,聚簇索引不支持与 TiDB Binlog 一起使用。开启 TiDB Binlog 后,TiDB 只允许创建单个整数列作为主键的聚簇索引;已创建的聚簇索引表的数据插入、删除和更新动作不会通过 TiDB Binlog 同步到下游。如需同步聚簇索引表,请升级至 v5.1 版本或使用 [TiCDC](/ticdc/ticdc-overview.md)。 +- 不支持且不在支持计划中的情况: + - 不支持将聚簇索引与属性 [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md) 一起使用。此外,属性 [`PRE_SPLIT_REGIONS`](/sql-statements/sql-statement-split-region.md#pre_split_regions) 对非 [`AUTO_RANDOM`](/auto-random.md) 的聚簇索引表不生效。 + - 不支持降级具有聚簇索引的表。如果需要降级此类表,请使用逻辑备份工具迁移数据。 +- 目前不支持但在支持计划中的情况: + - 不支持使用 `ALTER TABLE` 语句添加、删除和修改聚簇索引。 +- 特定版本的限制: + - 在 v5.0 中,不支持将聚簇索引功能与 TiDB Binlog 一起使用。启用 TiDB Binlog 后,TiDB 仅允许创建单个整数列作为主键的聚簇索引。TiDB Binlog 不会将现有聚簇索引表上的数据变更(如插入、删除和更新)复制到下游。如果需要将具有聚簇索引的表复制到下游,请将集群升级到 v5.1 或使用 [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) 进行复制。 -开启 TiDB Binlog 之后,要创建的聚簇索引如果不是由单个整数列构成,会报以下错误: +启用 TiDB Binlog 后,如果创建的聚簇索引不是单个整数主键,TiDB 会返回以下错误: ```sql mysql> CREATE TABLE t (a VARCHAR(255) PRIMARY KEY CLUSTERED); ERROR 8200 (HY000): Cannot create clustered index table when the binlog is ON ``` -与 `SHARD_ROW_ID_BITS` 一起使用时会报以下错误: +如果将聚簇索引与属性 `SHARD_ROW_ID_BITS` 一起使用,TiDB 会报告以下错误: ```sql mysql> CREATE TABLE t (a VARCHAR(255) PRIMARY KEY CLUSTERED) SHARD_ROW_ID_BITS = 3; @@ -164,45 +166,42 @@ ERROR 8200 (HY000): Unsupported shard_row_id_bits for table with primary key as ## 兼容性 -### 升降级兼容性 +### 与早期和后期 TiDB 版本的兼容性 -TiDB 支持对聚簇索引表的升级兼容,但不支持降级兼容,即高版本 TiDB 聚簇索引表的数据在低版本 TiDB 上不可用。 +TiDB 支持升级具有聚簇索引的表,但不支持降级此类表,这意味着后期 TiDB 版本中具有聚簇索引的表中的数据在早期版本中不可用。 -聚簇索引在 TiDB v3.0 和 v4.0 中已完成部分支持,当表中存在单个整数列作为主键时默认启用,即: +TiDB v3.0 和 v4.0 部分支持聚簇索引功能。当完全满足以下要求时,该功能默认启用: -- 表设置了主键 -- 主键只有一列 -- 主键的数据类型为整数类型 +- 表包含 `PRIMARY KEY`。 +- `PRIMARY KEY` 仅由一个列组成。 +- `PRIMARY KEY` 是 `INTEGER` 类型。 -TiDB v5.0 完成了所有类型主键的支持,但默认行为与 TiDB v3.0 和 v4.0 保持一致。要修改默认行为,请设置系统变量 `@@tidb_enable_clustered_index` 为 `ON` 或 `OFF`。 +从 TiDB v5.0 开始,聚簇索引功能完全支持所有类型的主键,但默认行为与 TiDB v3.0 和 v4.0 一致。要更改默认行为,你可以将系统变量 `@@tidb_enable_clustered_index` 配置为 `ON` 或 `OFF`。更多详情,请参见[创建具有聚簇索引的表](#创建具有聚簇索引的表)。 -### MySQL 兼容性 +### 与 MySQL 的兼容性 -TiDB 支持使用可执行注释的语法来包裹 `CLUSTERED` 或 `NONCLUSTERED` 关键字,且 `SHOW CREATE TABLE` 的结果均包含 TiDB 特有的可执行注释,这些注释在 MySQL 或低版本的 TiDB 中会被忽略。 +TiDB 特定的注释语法支持将关键字 `CLUSTERED` 和 `NONCLUSTERED` 包装在注释中。`SHOW CREATE TABLE` 的结果也包含 TiDB 特定的 SQL 注释。MySQL 数据库和早期版本的 TiDB 数据库会忽略这些注释。 -### TiDB 数据迁移工具兼容性 +### 与 TiDB 迁移工具的兼容性 -聚簇索引仅与 v5.0 及以后版本的以下数据迁移工具兼容: +聚簇索引功能仅与 v5.0 及更高版本的以下迁移工具兼容: -- 备份与恢复工具 BR、Dumpling、TiDB Lightning。 -- 数据迁移和同步工具 DM、TiCDC。 +- 备份和恢复工具:BR、Dumpling 和 TiDB Lightning。 +- 数据迁移和复制工具:DM 和 TiCDC。 -v5.0 的 BR 不能通过备份恢复将非聚簇索引表转换成聚簇索引表,反之亦然。 +但是,你不能通过使用 v5.0 BR 工具备份和恢复表来将具有非聚簇索引的表转换为具有聚簇索引的表,反之亦然。 -### 与 TiDB 其他特性的兼容性 +### 与其他 TiDB 功能的兼容性 -在非单整数列作为主键的表中,从非聚簇索引变为聚簇索引之后,在 v5.0 之前版本的 TiDB 能够执行的 `SPLIT TABLE BY/BETWEEN` 语句在 v5.0 及以后版本的 TiDB 上不再可用,原因是行数据键的构成发生了变化。在聚簇索引表上执行 `SPLIT TABLE BY/BETWEEN` 时需要依据主键列指定值,而不是指定一个整数值。例如: +对于具有组合主键或单个非整数主键的表,如果将主键从非聚簇索引更改为聚簇索引,其行数据的键也会改变。因此,在 TiDB v5.0 之前版本中可执行的 `SPLIT TABLE BY/BETWEEN` 语句在 v5.0 及更高版本的 TiDB 中不再适用。如果要使用 `SPLIT TABLE BY/BETWEEN` 拆分具有聚簇索引的表,需要提供主键列的值,而不是指定整数值。请参见以下示例: ```sql mysql> create table t (a int, b varchar(255), primary key(a, b) clustered); Query OK, 0 rows affected (0.01 sec) - mysql> split table t between (0) and (1000000) regions 5; ERROR 1105 (HY000): Split table region lower value count should be 2 - mysql> split table t by (0), (50000), (100000); ERROR 1136 (21S01): Column count doesn't match value count at row 0 - mysql> split table t between (0, 'aaa') and (1000000, 'zzz') regions 5; +--------------------+----------------------+ | TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO | @@ -210,7 +209,6 @@ mysql> split table t between (0, 'aaa') and (1000000, 'zzz') regions 5; | 4 | 1 | +--------------------+----------------------+ 1 row in set (0.00 sec) - mysql> split table t by (0, ''), (50000, ''), (100000, ''); +--------------------+----------------------+ | TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO | @@ -220,7 +218,7 @@ mysql> split table t by (0, ''), (50000, ''), (100000, ''); 1 row in set (0.01 sec) ``` -[`AUTO_RANDOM`](/auto-random.md) 属性只能在聚簇索引表上使用。在非聚簇索引上使用 `AUTO_RANDOM` 会报以下错误: +属性 [`AUTO_RANDOM`](/auto-random.md) 只能用于聚簇索引。否则,TiDB 会返回以下错误: ```sql mysql> create table t (a bigint primary key nonclustered auto_random); diff --git a/column-pruning.md b/column-pruning.md index 64184eb23442..de1179e02f50 100644 --- a/column-pruning.md +++ b/column-pruning.md @@ -1,20 +1,20 @@ --- -title: 列裁剪 -summary: 列裁剪是优化器在优化过程中删除不需要的列的基本思想。这样可以减少 I/O 资源占用并为后续优化带来便利。TiDB 会在逻辑优化阶段进行列裁剪,减少资源浪费。该扫描过程称作“列裁剪”,对应逻辑优化规则中的 columnPruner。如果要关闭这个规则,可以参照优化规则及表达式下推的黑名单中的关闭方法。 +title: 列剪裁 +summary: 了解 TiDB 中列剪裁的使用。 --- -# 列裁剪 +# 列剪裁 -列裁剪的基本思想在于:对于算子中实际用不上的列,优化器在优化的过程中没有必要保留它们。对这些列的删除会减少 I/O 资源占用,并为后续的优化带来便利。下面给出一个列重复的例子: +列剪裁的基本思想是,对于算子中未使用的列,优化器在优化过程中不需要保留它们。移除这些列可以减少 I/O 资源的使用,并有助于后续的优化。以下是列重复的示例: -假设表 t 里面有 a b c d 四列,执行如下语句: +假设表 t 中有四列(a、b、c 和 d)。你可以执行以下语句: {{< copyable "sql" >}} ```sql -select a from t where b > 5 +select a from t where b> 5 ``` -在该查询的过程中,t 表实际上只有 a, b 两列会被用到,而 c, d 的数据则显得多余。对应到该语句的查询计划,Selection 算子会用到 b 列,下面接着的 DataSource 算子会用到 a, b 两列,而剩下 c, d 两列则都可以裁剪掉,DataSource 算子在读数据时不需要将它们读进来。 +在这个查询中,只使用了列 a 和列 b,而列 c 和列 d 是冗余的。关于这个语句的查询计划,`Selection` 算子使用列 b,然后 `DataSource` 算子使用列 a 和列 b。由于 `DataSource` 算子不读取列 c 和列 d,所以可以对它们进行剪裁。 -出于上述考量,TiDB 会在逻辑优化阶段进行自上而下的扫描,裁剪不需要的列,减少资源浪费。该扫描过程称作 “列裁剪”,对应逻辑优化规则中的 `columnPruner`。如果要关闭这个规则,可以在参照[优化规则及表达式下推的黑名单](/blocklist-control-plan.md)中的关闭方法。 +因此,当 TiDB 在逻辑优化阶段执行自上而下的扫描时,会剪裁冗余列以减少资源浪费。这个扫描过程称为"列剪裁",对应于 `columnPruner` 规则。如果你想禁用这个规则,请参考[优化规则和表达式下推的黑名单](/blocklist-control-plan.md)。 diff --git a/comment-syntax.md b/comment-syntax.md index 4130d2564883..7d2be02df3a4 100644 --- a/comment-syntax.md +++ b/comment-syntax.md @@ -5,16 +5,16 @@ summary: 本文介绍 TiDB 支持的注释语法。 # 注释语法 -本文档介绍 TiDB 支持的注释语法。 +本文描述 TiDB 支持的注释语法。 TiDB 支持三种注释风格: -* 用 `#` 注释一行: +- 使用 `#` 注释一行: {{< copyable "sql" >}} ```sql - SELECT 1+1; # 注释文字 + SELECT 1+1; # comments ``` ``` @@ -26,12 +26,12 @@ TiDB 支持三种注释风格: 1 row in set (0.00 sec) ``` -* 用 `--` 注释一行: +- 使用 `--` 注释一行: {{< copyable "sql" >}} ```sql - SELECT 1+1; -- 注释文字 + SELECT 1+1; -- comments ``` ``` @@ -42,10 +42,10 @@ TiDB 支持三种注释风格: +------+ 1 row in set (0.00 sec) ``` + + 这种风格要求在 `--` 后至少有一个空格: - 用 `--` 注释时,必须要在其之后留出至少一个空格,否则注释不生效: - - {{< copyable "sql" >}} + {{< copyable "sql" >}} ```sql SELECT 1+1--1; @@ -60,12 +60,12 @@ TiDB 支持三种注释风格: 1 row in set (0.01 sec) ``` -* 用 `/* */` 注释一块,可以注释多行: +- 使用 `/* */` 注释一个块或多行: - {{< copyable "sql" >}} + {{< copyable "sql" >}} ```sql - SELECT 1 /* 这是行内注释文字 */ + 1; + SELECT 1 /* this is an in-line comment */ + 1; ``` ``` @@ -82,8 +82,8 @@ TiDB 支持三种注释风格: ```sql SELECT 1+ /* - /*> 这是一条 - /*> 多行注释 + /*> this is a + /*> multiple-line comment /*> */ 1; ``` @@ -91,7 +91,6 @@ TiDB 支持三种注释风格: ``` +-------------------+ | 1+ - 1 | +-------------------+ | 2 | @@ -101,37 +100,44 @@ TiDB 支持三种注释风格: ## MySQL 兼容的注释语法 -TiDB 也跟 MySQL 保持一致,支持一种 C 风格注释的变体: +与 MySQL 一样,TiDB 支持 C 风格注释语法的变体: ``` -/*! Specific code */ +/*! 特定代码 */ ``` -或者 +或 ``` -/*!50110 Specific code */ +/*!50110 特定代码 */ ``` -和 MySQL 一样,TiDB 会执行注释中的语句。 +在这种风格中,TiDB 会执行注释中的语句。 -例如:`SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ...` +例如: -在 TiDB 中,这种写法等价于 `SELECT STRAIGHT_JOIN col1 FROM table1,table2 WHERE ...` +```sql +SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ... +``` + +在 TiDB 中,你也可以使用另一个版本: -如果注释中指定了 Server 版本号,例如 `/*!50110 KEY_BLOCK_SIZE=1024 */`,在 MySQL 中表示只有 MySQL 的版本大于等于 5.1.10 才会处理这个 comment 中的内容。但是在 TiDB 中,这个 MySQL 版本号不会起作用,所有的 comment 都被会处理。 +```sql +SELECT STRAIGHT_JOIN col1 FROM table1,table2 WHERE ... +``` -## TiDB 可执行的注释语法 +如果在注释中指定了服务器版本号,例如 `/*!50110 KEY_BLOCK_SIZE=1024 */`,在 MySQL 中这意味着只有当 MySQL 版本是或高于 5.1.10 时才处理此注释中的内容。但在 TiDB 中,MySQL 版本号不起作用,注释中的所有内容都会被处理。 -TiDB 也有独立的注释语法,称为 TiDB 可执行注释语法。主要分为两种: +## TiDB 特有的注释语法 -* `/*T! Specific code */`:该语法只能被 TiDB 解析执行,而在其他数据库中会被忽略。 +TiDB 有自己的注释语法(即 TiDB 特有的注释语法),可以分为以下两种: -* `/*T![feature_id] Specific code */`:该语法用于保证 TiDB 不同版本之间的兼容性。只有在当前版本中实现了 `feature_id` 对应的功能特性的 TiDB,才会试图解析该注释里的 SQL 片段。例如 v3.1.1 中引入了 `AUTO_RANDOM` 特性,该版本能够将 `/*T![auto_rand] auto_random */` 解析为 `auto_random`;而 v3.0.0 中没有实现 `AUTO_RANDOM` 特性,则上述 SQL 语句片段会被忽略。**注意前几个字符 `/*T![` 中,各字符之间没有任何空格**。 +* `/*T! 特定代码 */`:这种语法只能被 TiDB 解析和执行,在其他数据库中会被忽略。 +* `/*T![feature_id] 特定代码 */`:这种语法用于确保不同版本的 TiDB 之间的兼容性。TiDB 只有在当前版本实现了相应的 `feature_id` 功能时才能解析这个注释中的 SQL 片段。例如,由于 `AUTO_RANDOM` 功能是在 v3.1.1 中引入的,因此这个版本的 TiDB 可以将 `/*T![auto_rand] auto_random */` 解析为 `auto_random`。因为 v3.0.0 中没有实现 `AUTO_RANDOM` 功能,所以上述 SQL 语句片段会被忽略。**不要在 `/*T![` 字符内留有任何空格**。 ## 优化器注释语法 -还有一种注释会被当做是优化器 Hint 特殊对待: +另一种注释类型被特别处理为优化器提示: {{< copyable "sql" >}} @@ -139,10 +145,10 @@ TiDB 也有独立的注释语法,称为 TiDB 可执行注释语法。主要分 SELECT /*+ hint */ FROM ...; ``` -TiDB 支持的相关优化器 hint 详见 [Optimizer Hints](/optimizer-hints.md)。 +关于 TiDB 支持的优化器提示的详细信息,请参见[优化器提示](/optimizer-hints.md)。 > **注意:** > -> 在 MySQL 客户端中,TiDB 可执行注释语法会被默认当成注释被清除掉。在 MySQL 客户端 5.7.7 之前的版本中,Hint 也会被默认当成注释被清除掉。推荐在启动客户端时加上 `--comments` 选项,例如 `mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 +> 在 MySQL 客户端中,TiDB 特有的注释语法默认被视为注释并被清除。在 MySQL 5.7.7 之前的客户端中,提示也被视为注释并默认被清除。建议在启动客户端时使用 `--comments` 选项。例如,`mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 -更多细节,请参考 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/comments.html)。 +更多信息,请参见 [Comment Syntax](https://dev.mysql.com/doc/refman/8.0/en/comments.html)。 diff --git a/constraints.md b/constraints.md index 4e348b8ba696..37ba0917b403 100644 --- a/constraints.md +++ b/constraints.md @@ -1,15 +1,17 @@ --- title: 约束 -summary: TiDB 支持的约束与 MySQL 基本相同,包括非空约束和 CHECK 约束。非空约束规则与 MySQL 相同,而 CHECK 约束需要在 tidb_enable_check_constraint 设置为 ON 后才能开启。可以通过 CREATE TABLE 或 ALTER TABLE 语句添加 CHECK 约束。唯一约束和主键约束也与 MySQL 相似,但 TiDB 目前仅支持对 NONCLUSTERED 的主键进行添加和删除操作。外键约束从 v6.6.0 开始支持,可以使用 CREATE TABLE 和 ALTER TABLE 命令来添加和删除外键。 +summary: 了解 SQL 约束如何应用于 TiDB。 --- # 约束 -TiDB 支持的约束与 MySQL 的基本相同。 +TiDB 支持几乎与 MySQL 相同的约束。 -## 非空约束 +## NOT NULL -TiDB 支持的非空约束规则与 MySQL 支持的一致。例如: +TiDB 支持的 NOT NULL 约束与 MySQL 支持的相同。 + +例如: ```sql CREATE TABLE users ( @@ -43,21 +45,19 @@ 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` 语句成功,因为可以将 `NULL` 分配给 `AUTO_INCREMENT` 列。TiDB 会自动生成序列号。 +* 第二个 `INSERT` 语句失败,因为 `age` 列被定义为 `NOT NULL`。 +* 第三个 `INSERT` 语句成功,因为 `last_login` 列没有显式定义为 `NOT NULL`。默认允许 NULL 值。 -* 第三条 `INSERT` 语句成功,因为 `last_login` 列没有被明确地指定为 `NOT NULL`。默认允许 `NULL` 值。 - -## `CHECK` 约束 +## CHECK > **注意:** > -> `CHECK` 约束功能默认关闭,需要将变量 [`tidb_enable_check_constraint`](/system-variables.md#tidb_enable_check_constraint-从-v720-版本开始引入) 设置为 `ON` 后才能开启。 +> `CHECK` 约束功能默认是禁用的。要启用它,你需要将 [`tidb_enable_check_constraint`](/system-variables.md#tidb_enable_check_constraint-new-in-v720) 变量设置为 `ON`。 -`CHECK` 约束用于限制表中某个字段的值必须满足指定条件。当为表添加 `CHECK` 约束后,在插入或者更新表的数据时,TiDB 会检查约束条件是否满足,如果不满足,则会报错。 +`CHECK` 约束限制表中列的值必须满足你指定的条件。当向表中插入或更新数据时,TiDB 会检查是否满足约束条件。如果不满足约束条件,则会返回错误。 -TiDB 中 `CHECK` 约束的语法如下,与 MySQL 中一致: +TiDB 中的 `CHECK` 约束语法与 MySQL 相同: ```sql [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED] @@ -65,34 +65,34 @@ TiDB 中 `CHECK` 约束的语法如下,与 MySQL 中一致: 语法说明: -- `[]` 中的内容表示可选项。 -- `CONSTRAINT [symbol]` 表示 `CHECK` 约束的名称。 -- `CHECK (expr)` 表示约束条件,其中 `expr` 需要为一个布尔表达式。对于表中的每一行,该表达式的计算结果必须为 `TRUE`、`FALSE` 或 `UNKNOWN` (对于 `NULL` 值) 中的一个。对于某行数据,如果该表达式计算结果为 `FALSE`,则表示违反约束条件。 -- `[NOT] ENFORCED` 表示是否执行约束,可以用于启用或者禁用 `CHECK` 约束。 +- `[]`:`[]` 中的内容是可选的。 +- `CONSTRAINT [symbol]`:指定 `CHECK` 约束的名称。 +- `CHECK (expr)`:指定约束条件,其中 `expr` 需要是一个布尔表达式。对于表中的每一行,该表达式的计算结果必须是 `TRUE`、`FALSE` 或 `UNKNOWN`(对于 `NULL` 值)中的一个。如果某一行的计算结果为 `FALSE`,表示违反了约束。 +- `[NOT] ENFORCED`:指定是否执行约束检查。你可以用它来启用或禁用 `CHECK` 约束。 ### 添加 `CHECK` 约束 -在 TiDB 中,你可以在 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 或者 [`ALTER TABLE`](/sql-statements/sql-statement-modify-column.md) 语句中为表添加 `CHECK` 约束。 +在 TiDB 中,你可以使用 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 或 [`ALTER TABLE`](/sql-statements/sql-statement-modify-column.md) 语句向表添加 `CHECK` 约束。 -- 在 `CREATE TABLE` 语句中添加 `CHECK` 约束的示例: +- 使用 `CREATE TABLE` 语句添加 `CHECK` 约束的示例: ```sql CREATE TABLE t(a INT CHECK(a > 10) NOT ENFORCED, b INT, c INT, CONSTRAINT c1 CHECK (b > c)); ``` -- 在 `ALTER TABLE` 语句中添加 `CHECK` 约束的示例: +- 使用 `ALTER TABLE` 语句添加 `CHECK` 约束的示例: ```sql ALTER TABLE t ADD CONSTRAINT CHECK (1 < c); ``` -在添加或者启用 `CHECK` 约束时,TiDB 会对表中的存量数据进行校验。如果存在违反约束的数据,添加 `CHECK` 约束操作将失败并且报错。 +添加或启用 `CHECK` 约束时,TiDB 会检查表中现有的数据。如果有任何数据违反约束,添加 `CHECK` 约束的操作将失败并返回错误。 -在添加 `CHECK` 约束时,可以指定约束名,也可以不指定约束名。如果不指定约束名,那么 TiDB 会自动生成一个格式为 `_chk_<1, 2, 3...>` 的约束名。 +添加 `CHECK` 约束时,你可以指定约束名称,也可以不指定。如果不指定约束名称,TiDB 会自动生成一个格式为 `<表名>_chk_<1, 2, 3...>` 的约束名称。 ### 查看 `CHECK` 约束 -你可以通过 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 查看表中的约束信息。例如: +你可以使用 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 语句查看表中的约束信息。例如: ```sql SHOW CREATE TABLE t; @@ -113,7 +113,7 @@ CONSTRAINT `t_chk_2` CHECK ((1 < `c`)) ### 删除 `CHECK` 约束 -删除 `CHECK` 约束时,你需要指定需要删除的约束名。例如: +删除 `CHECK` 约束时,需要指定要删除的约束名称。例如: ```sql ALTER TABLE t DROP CONSTRAINT t_chk_1; @@ -121,29 +121,31 @@ ALTER TABLE t DROP CONSTRAINT t_chk_1; ### 启用或禁用 `CHECK` 约束 -在为表[添加 `CHECK` 约束](#添加-check-约束)的时候,可以指定当插入或者更新数据时 TiDB 是否执行约束检查。 +在[添加 `CHECK` 约束](#添加-check-约束)到表时,你可以指定 TiDB 在插入或更新数据时是否需要执行约束检查。 -- 如果指定了 `NOT ENFORCED`,当插入或者更新数据时,TiDB 不会检查约束条件。 -- 如果未指定 `NOT ENFORCED` 或者指定了 `ENFORCED`,当插入或者更新数据时,TiDB 会检查约束条件。 +- 如果指定了 `NOT ENFORCED`,TiDB 在插入或更新数据时不会检查约束条件。 +- 如果未指定 `NOT ENFORCED` 或指定了 `ENFORCED`,TiDB 在插入或更新数据时会检查约束条件。 -除了在添加约束时候指定 `[NOT] ENFORCED`,你还可以在 `ALTER TABLE` 语句中启用或者禁用 `CHECK` 约束。例如: +除了在添加约束时指定 `[NOT] ENFORCED`,你还可以使用 `ALTER TABLE` 语句启用或禁用 `CHECK` 约束。例如: ```sql ALTER TABLE t ALTER CONSTRAINT c1 NOT ENFORCED; ``` -### 与 MySQL 的兼容性 +### MySQL 兼容性 -- 不支持在添加列的同时添加 `CHECK` 约束(例如,`ALTER TABLE t ADD COLUMN a CHECK(a > 0)`)),否则只有列会被添加成功,TiDB 会忽略 `CHECK` 约束但不会报错。 -- 不支持使用 `ALTER TABLE t CHANGE a b int CHECK(b > 0)` 添加 `CHECK` 约束,使用该语句时 TiDB 会报错。 +- 不支持在添加列时添加 `CHECK` 约束(例如,`ALTER TABLE t ADD COLUMN a CHECK(a > 0)`)。在这种情况下,只有列添加成功,TiDB 会忽略 `CHECK` 约束而不报错。 +- 不支持使用 `ALTER TABLE t CHANGE a b int CHECK(b > 0)` 添加 `CHECK` 约束。执行此语句时,TiDB 会报错。 -## 唯一约束 +## UNIQUE KEY -唯一约束是指唯一索引和主键列中所有的非空值都是唯一的。 +唯一约束意味着唯一索引和主键列中的所有非空值都是唯一的。 ### 乐观事务 -在 TiDB 的乐观事务中,默认会对唯一约束进行[惰性检查](/transaction-overview.md#惰性检查)。通过在事务提交时再进行批量检查,TiDB 能够减少网络开销、提升性能。例如: +默认情况下,对于乐观事务,TiDB 在执行阶段[延迟检查](/transaction-overview.md#延迟检查约束)唯一约束,在提交阶段严格检查,这有助于减少网络开销并提高性能。 + +例如: ```sql DROP TABLE IF EXISTS users; @@ -155,7 +157,7 @@ CREATE TABLE users ( INSERT INTO users (username) VALUES ('dave'), ('sarah'), ('bill'); ``` -乐观事务模式下且 `tidb_constraint_check_in_place=OFF`: +使用乐观锁并且 `tidb_constraint_check_in_place=OFF`: ```sql BEGIN OPTIMISTIC; @@ -184,9 +186,11 @@ COMMIT; ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' ``` -在以上乐观事务的示例中,唯一约束的检查推迟到事务提交时才进行。由于 `bill` 值已经存在,这一行为导致了重复键错误。 +在上述乐观示例中,唯一性检查被推迟到事务提交时。这导致了重复键错误,因为值 `bill` 已经存在。 -你可通过设置 [`tidb_constraint_check_in_place`](/system-variables.md#tidb_constraint_check_in_place) 为 `ON` 停用此行为(该变量仅适用于乐观事务,悲观事务需通过 `tidb_constraint_check_in_place_pessimistic` 设置)。当 `tidb_constraint_check_in_place` 设置为 `ON` 时,TiDB 会在执行语句时就对唯一约束进行检查。例如: +你可以通过将 [`tidb_constraint_check_in_place`](/system-variables.md#tidb_constraint_check_in_place) 设置为 `ON` 来禁用此行为。当 `tidb_constraint_check_in_place=ON` 时,唯一约束在语句执行时检查。请注意,此变量仅适用于乐观事务。对于悲观事务,你可以使用 [`tidb_constraint_check_in_place_pessimistic`](/system-variables.md#tidb_constraint_check_in_place_pessimistic-new-in-v630) 变量来控制此行为。 + +例如: ```sql DROP TABLE IF EXISTS users; @@ -222,11 +226,11 @@ INSERT INTO users (username) VALUES ('jane'), ('chris'), ('bill'); ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' ``` -第一条 `INSERT` 语句导致了重复键错误。这会造成额外的网络通信开销,并可能降低插入操作的吞吐量。 +第一个 `INSERT` 语句导致重复键错误。这会导致额外的网络通信开销,可能会降低插入操作的吞吐量。 ### 悲观事务 -在 TiDB 的悲观事务中,默认在执行任何一条需要插入或更新唯一索引的 SQL 语句时都会进行唯一约束检查: +在悲观事务中,默认情况下,TiDB 在执行需要插入或更新唯一索引的 SQL 语句时检查 `UNIQUE` 约束。 ```sql DROP TABLE IF EXISTS users; @@ -245,11 +249,11 @@ INSERT INTO users (username) VALUES ('jane'), ('chris'), ('bill'); ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' ``` -对于悲观事务,你可以设置变量 [`tidb_constraint_check_in_place_pessimistic`](/system-variables.md#tidb_constraint_check_in_place_pessimistic-从-v630-版本开始引入) 为 `OFF` 来推迟唯一约束检查,到下一次对该唯一索引项加锁时或事务提交时再进行检查,同时也跳过对该悲观锁加锁,以获得更好的性能。此时需要注意: +为了获得更好的悲观事务性能,你可以将 [`tidb_constraint_check_in_place_pessimistic`](/system-variables.md#tidb_constraint_check_in_place_pessimistic-new-in-v630) 变量设置为 `OFF`,这允许 TiDB 延迟唯一索引的唯一约束检查(到下次需要锁定该索引时或事务提交时)并跳过相应的悲观锁。使用此变量时,请注意以下几点: -- 由于推迟了唯一约束检查,TiDB 可能会读取到不满足唯一约束的结果,执行 `COMMIT` 语句时可能返回 `Duplicate entry` 错误。返回该错误时,TiDB 会回滚当前事务。 +- 由于延迟的唯一约束检查,TiDB 可能会读取到不满足唯一约束的结果,并在提交悲观事务时返回 `Duplicate entry` 错误。当出现此错误时,TiDB 会回滚当前事务。 - 下面这个例子跳过了对 `bill` 的加锁,因此 TiDB 可能读到不满足唯一性约束的结果: + 以下示例跳过对 `bill` 的锁定,因此 TiDB 可能会获取不满足唯一性约束的结果。 ```sql SET tidb_constraint_check_in_place_pessimistic = OFF; @@ -258,7 +262,7 @@ ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' SELECT * FROM users FOR UPDATE; ``` - TiDB 读到了不满足唯一性约束的结果:有两个 `bill`。 + 如下例所示,TiDB 的查询结果包含两个 `bill`,这不满足唯一性约束。 ```sql +----+----------+ @@ -273,7 +277,7 @@ ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' +----+----------+ ``` - 此时,如果提交事务,TiDB 将进行唯一约束检查,报出 `Duplicate entry` 错误并回滚事务。 + 此时,如果提交事务,TiDB 将执行唯一约束检查,报告 `Duplicate entry` 错误,并回滚事务。 ```sql COMMIT; @@ -283,9 +287,9 @@ ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' ``` -- 关闭该变量时,如果在事务中写入数据,执行 `COMMIT` 语句可能会返回 `Write conflict` 错误。返回该错误时,TiDB 会回滚当前事务。 +- 当此变量被禁用时,提交需要写入数据的悲观事务可能会返回 `Write conflict` 错误。当出现此错误时,TiDB 会回滚当前事务。 - 在下面这个例子中,当有并发事务写入时,跳过悲观锁导致事务提交时报出 `Write conflict` 错误并回滚。 + 如下例所示,如果两个并发事务需要向同一个表插入数据,跳过悲观锁会导致 TiDB 在提交事务时返回 `Write conflict` 错误。事务将被回滚。 ```sql DROP TABLE IF EXISTS users; @@ -300,13 +304,13 @@ ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' INSERT INTO users (username) VALUES ('jane'), ('chris'), ('bill'); -- Query OK, 3 rows affected ``` - 然后另一个会话中写入了 `bill`: + 同时,另一个会话向同一个表插入 `bill`。 ```sql INSERT INTO users (username) VALUES ('bill'); -- Query OK, 1 row affected ``` - 在第一个会话中提交时,TiDB 会报出 `Write conflict` 错误。 + 然后,当你在第一个会话中提交事务时,TiDB 会报告 `Write conflict` 错误。 ```sql COMMIT; @@ -316,15 +320,15 @@ ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' ERROR 9007 (HY000): Write conflict, txnStartTS=435688780611190794, conflictStartTS=435688783311536129, conflictCommitTS=435688783311536130, key={tableID=74, indexID=1, indexValues={bill, }} primary={tableID=74, indexID=1, indexValues={bill, }}, reason=LazyUniquenessCheck [try again later] ``` -- 关闭该变量时,如果多个悲观事务之间存在写冲突,悲观锁可能会在其它悲观事务提交时被强制回滚,因此产生 `PessimisticLockNotFound` 错误。发生该错误时,说明该业务不适合推迟悲观事务的唯一约束检查,应考虑调整业务避免冲突,或在发生错误后重试事务。 +- 当此变量被禁用时,如果多个悲观事务之间存在写冲突,当其他悲观事务提交时,悲观锁可能会被强制回滚,从而导致 `Pessimistic lock not found` 错误。当出现此错误时,这意味着延迟悲观事务的唯一约束检查不适合你的应用场景。在这种情况下,考虑调整应用逻辑以避免冲突,或在发生错误后重试事务。 -- 关闭该变量会导致悲观事务中可能报出错误 `8147: LazyUniquenessCheckFailure`。 +- 当此变量被禁用时,在悲观事务中执行 DML 语句可能会返回错误 `8147: LazyUniquenessCheckFailure`。 > **注意:** > - > 返回 8147 错误时当前事务回滚。 + > 当出现 `8147` 错误时,TiDB 会回滚当前事务。 - 下面的例子在 INSERT 语句执行时跳过了一次加锁后,在 DELETE 语句执行时对该唯一索引加锁并检查,即会在该语句报错: + 如下例所示,在执行 `INSERT` 语句时,TiDB 跳过了锁定。然后,在执行 `DELETE` 语句时,TiDB 锁定唯一索引并检查唯一约束,因此你会看到在 `DELETE` 语句处报告了一个错误。 ```sql SET tidb_constraint_check_in_place_pessimistic = OFF; @@ -337,11 +341,13 @@ ERROR 1062 (23000): Duplicate entry 'bill' for key 'users.username' ERROR 8147 (23000): transaction aborted because lazy uniqueness check is enabled and an error occurred: [kv:1062]Duplicate entry 'bill' for key 'users.username' ``` -- 关闭该变量时,`1062 Duplicate entry` 报错不一定是当前执行的 SQL 语句所发生的错误。因此,在一个事务操作多个表,且这些表有同名索引时,请注意 `1062` 报错信息中提示的是哪个表的哪个索引发生了错误。 +- 当此变量被禁用时,`1062 Duplicate entry` 错误可能不是来自当前 SQL 语句。因此,当事务操作多个具有相同名称索引的表时,你需要检查 `1062` 错误消息以找出错误实际来自哪个索引。 + +## PRIMARY KEY -## 主键约束 +与 MySQL 一样,主键约束包含唯一约束,即创建主键约束相当于具有唯一约束。此外,TiDB 的其他主键约束也与 MySQL 类似。 -与 MySQL 行为一样,主键约束包含了唯一约束,即创建了主键约束相当于拥有了唯一约束。此外,TiDB 其他的主键约束规则也与 MySQL 相似。例如: +例如: ```sql CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); @@ -375,13 +381,11 @@ 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 支持将多个列定义为复合主键。 -* 表 `t2` 创建失败,因为定义为主键的列 `a` 不能允许 `NULL` 值。 -* 表 `t3` 创建失败,因为一张表只能有一个主键。 -* 表 `t4` 创建成功,因为虽然只能有一个主键,但 TiDB 支持定义一个多列组合作为复合主键。 - -除上述规则外,TiDB 目前仅支持对 `NONCLUSTERED` 的主键进行添加和删除操作。例如: +除了上述规则外,TiDB 目前只支持添加和删除 `NONCLUSTERED` 类型的主键。例如: ```sql CREATE TABLE t5 (a INT NOT NULL, b INT NOT NULL, PRIMARY KEY (a,b) CLUSTERED); @@ -401,15 +405,17 @@ ALTER TABLE t5 DROP PRIMARY KEY; Query OK, 0 rows affected (0.10 sec) ``` -要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 +有关 `CLUSTERED` 类型的主键的更多详细信息,请参考[聚簇索引](/clustered-indexes.md)。 -## 外键约束 +## FOREIGN KEY > **注意:** > -> TiDB 从 v6.6.0 开始支持[外键约束](/foreign-key.md)(实验特性)。在 v6.6.0 之前,TiDB 支持创建和删除外键约束,但外键约束并不生效。升级到 v6.6.0 后,可以先删除不生效的外键后再创建外键使外键约束生效。 +> 从 v6.6.0 开始,TiDB 支持[外键约束](/foreign-key.md)作为实验性功能。在 v6.6.0 之前,TiDB 支持创建和删除外键约束,但约束实际上并不生效。将 TiDB 升级到 v6.6.0 后,你可以删除无效的外键并创建新的外键,以使外键约束生效。 + +TiDB 支持在 DDL 命令中创建 `FOREIGN KEY` 约束。 -TiDB 支持创建外键约束。例如: +例如: ```sql CREATE TABLE users ( @@ -440,7 +446,7 @@ FROM information_schema.key_column_usage WHERE table_name IN ('users', 'orders') 3 rows in set (0.00 sec) ``` -TiDB 也支持使用 `ALTER TABLE` 命令来删除外键 (`DROP FOREIGN KEY`) 和添加外键 (`ADD FOREIGN KEY`): +TiDB 还支持通过 `ALTER TABLE` 命令使用 `DROP FOREIGN KEY` 和 `ADD FOREIGN KEY` 语法。 ```sql ALTER TABLE orders DROP FOREIGN KEY fk_user_id; diff --git a/control-execution-plan.md b/control-execution-plan.md index 36505dd03fbd..5c743f3d2c55 100644 --- a/control-execution-plan.md +++ b/control-execution-plan.md @@ -1,14 +1,24 @@ --- title: 控制执行计划 -summary: 本章节介绍了控制执行计划的方法,包括使用提示指导执行计划、执行计划管理、优化规则及表达式下推的黑名单。此外,还介绍了一些系统变量对执行计划的影响,以及引入的特殊变量 `tidb_opt_fix_control`,用于更细粒度地控制优化器的行为。 +summary: 本章介绍在 TiDB 中控制执行计划生成的方法。包括使用 Hints、SQL 计划管理和优化规则黑名单。此外,还可以通过修改系统变量和 `tidb_opt_fix_control` 变量来控制执行计划。这些方法有助于防止集群升级后优化器行为变化导致的性能回退。 --- # 控制执行计划 -SQL 性能调优的前两个章节介绍了如何理解 TiDB 的执行计划以及 TiDB 如何生成一个执行计划。本章节将介绍当你确定了执行计划所存在的问题时,可以使用哪些手段来控制执行计划的生成。本章节主要包括以下三方面内容: +SQL 调优的前两章介绍了如何理解 TiDB 的执行计划以及 TiDB 如何生成执行计划。本章介绍当你确定执行计划存在问题时,可以使用哪些方法来控制执行计划的生成。本章主要包括以下三个方面: -- [Optimizer Hints](/optimizer-hints.md)中,我们会介绍如何使用 Hint 来指导 TiDB 生成执行计划。 -- 但是使用 Hint 会侵入性地更改 SQL,在一些场景下并不能简单的插入 Hint。在[执行计划管理](/sql-plan-management.md)中,我们会介绍 TiDB 如何使用另一种语法来非侵入地控制执行计划的生成,同时还会介绍后台自动对执行计划进行演进的手段。该手段可用来减轻诸如版本升级等原因造成的执行计划不稳定和集群性能下降的问题。 -- 最后在[优化规则及表达式下推的黑名单](/blocklist-control-plan.md)中,我们会介绍黑名单的使用。 +- 在[优化器 Hints](/optimizer-hints.md)中,你将学习如何使用 hints 来指导 TiDB 生成执行计划。 +- 但是 hints 会对 SQL 语句产生侵入性修改。在某些场景下,无法简单地插入 hints。在 [SQL 计划管理](/sql-plan-management.md)中,你将了解 TiDB 如何使用另一种语法来非侵入式地控制执行计划的生成,以及后台自动执行计划演进的方法。这种方法有助于解决版本升级导致的执行计划不稳定和集群性能下降等问题。 +- 最后,你将学习如何使用[优化规则和表达式下推的黑名单](/blocklist-control-plan.md)。 -除以上手段之外,执行计划还会被一部分系统变量所影响。通过在系统级或会话级对变量进行修改,能够控制执行计划的生成。自 v6.5.3 和 v7.1.0 起,TiDB 引入了一个相对特殊的变量 [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-从-v653-和-v710-版本开始引入)。这个变量能够接受多个控制项,用来更细粒度地控制优化器的行为,避免集群升级后优化器行为变化导致的性能回退。详细介绍请参考 [Optimizer Fix Controls](/optimizer-fix-controls.md)。 + + +除了上述方法外,执行计划还受一些系统变量的影响。通过在系统级别或会话级别修改这些变量,可以控制执行计划的生成。从 v6.5.3 和 v7.1.0 版本开始,TiDB 引入了一个相对特殊的变量 [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710)。这个变量可以接受多个控制项,以更细粒度的方式控制优化器的行为,防止集群升级后优化器行为变化导致的性能回退。更详细的介绍请参考[优化器修复控制](/optimizer-fix-controls.md)。 + + + + + +除了上述方法外,执行计划还受一些系统变量的影响。通过在系统级别或会话级别修改这些变量,可以控制执行计划的生成。从 v6.5.3 和 v7.1.0 版本开始,TiDB 引入了一个相对特殊的变量 [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710)。这个变量可以接受多个控制项,以更细粒度的方式控制优化器的行为,防止集群升级后优化器行为变化导致的性能回退。更详细的介绍请参考[优化器修复控制](https://docs.pingcap.com/tidb/v7.2/optimizer-fix-controls)。 + + diff --git a/coprocessor-cache.md b/coprocessor-cache.md index 6d64580ce759..6c8429906f9f 100644 --- a/coprocessor-cache.md +++ b/coprocessor-cache.md @@ -1,45 +1,55 @@ --- -title: 下推计算结果缓存 -summary: TiDB 4.0 支持下推计算结果缓存,配置位于 `tikv-client.copr-cache`,缓存仅存储在 TiDB 内存中,不共享缓存,对 Region 写入会导致缓存失效。缓存命中率可通过 `EXPLAIN ANALYZE` 或 Grafana 监控面板查看。 +title: Coprocessor 缓存 +summary: 了解 Coprocessor 缓存的功能特性。 --- -# 下推计算结果缓存 +# Coprocessor 缓存 -TiDB 从 4.0 起支持下推计算结果缓存(即 Coprocessor Cache 功能)。开启该功能后,将在 TiDB 实例侧缓存下推给 TiKV 计算的结果,在部分场景下起到加速效果。 +从 v4.0 开始,TiDB 实例支持缓存下推到 TiKV 的计算结果(Coprocessor 缓存功能),这可以在某些场景下加速计算过程。 ## 配置 -Coprocessor Cache 的配置均位于 TiDB 的 `tikv-client.copr-cache` 配置项中。Coprocessor 的具体开启和配置方法,见 [TiDB 配置文件描述](/tidb-configuration-file.md#tikv-clientcopr-cache-从-v400-版本开始引入)。 + -## 特性说明 +您可以通过 TiDB 配置文件中的 `tikv-client.copr-cache` 配置项配置 Coprocessor 缓存。有关如何启用和配置 Coprocessor 缓存的详细信息,请参见 [TiDB 配置文件](/tidb-configuration-file.md#tikv-clientcopr-cache-new-in-v400)。 -+ 所有 SQL 在单个 TiDB 实例上的首次执行都不会被缓存。 -+ 缓存仅存储在 TiDB 内存中,TiDB 重启后缓存会失效。 -+ 不同 TiDB 实例之间不共享缓存。 -+ 缓存的是下推计算结果,即使缓存命中,后续仍有 TiDB 计算。 -+ 缓存以 Region 为单位。对 Region 的写入会导致涉及该 Region 的缓存失效。基于此原因,该功能主要会对很少变更的数据有效果。 -+ 下推计算请求相同时,缓存会被命中。通常在以下场景下,下推计算的请求是相同或部分相同的: - - SQL 语句完全一致,例如重复执行相同的 SQL 语句。 + - 该场景下所有下推计算的请求都是一致的,所有请求都能利用上下推计算缓存。 + - - SQL 语句包含一个变化的条件,其他部分一致,变化的条件是表主键或分区主键。 +Coprocessor 缓存功能默认启用。可以缓存的数据的最大大小为 1000 MB。 - 该场景下一部分下推计算的请求会与之前出现过的一致,部分请求能利用上下推计算结果缓存。 + - - SQL 语句包含多个变化的条件,其他部分一致,变化的条件完全匹配一个复合索引列。 +## 功能说明 - 该场景下一部分下推计算的请求会与之前出现过的一致,部分请求能利用上下推计算结果缓存。 ++ 当 SQL 语句第一次在单个 TiDB 实例上执行时,执行结果不会被缓存。 ++ 计算结果缓存在 TiDB 的内存中。如果 TiDB 实例重启,缓存将失效。 ++ 缓存不在 TiDB 实例之间共享。 ++ 只缓存下推计算结果。即使命中缓存,TiDB 仍然需要执行后续计算。 ++ 缓存以 Region 为单位。向 Region 写入数据会导致该 Region 的缓存失效。因此,Coprocessor 缓存功能主要对很少变化的数据有效。 ++ 当下推计算请求相同时,缓存会命中。通常在以下场景中,下推计算请求相同或部分相同: + - SQL 语句相同。例如,重复执行相同的 SQL 语句。 -+ 该功能对用户透明,开启和关闭都不影响计算结果,仅影响 SQL 执行时间。 + 在这种场景下,所有下推计算请求都一致,所有请求都可以使用下推计算缓存。 -## 检验缓存效果 + - SQL 语句包含一个变化的条件,其他部分一致。变化的条件是表的主键或分区。 -可以通过执行 `EXPLAIN ANALYZE` 或查看 Grafana 监控面板来检查 Coprocessor 的缓存效果。 + 在这种场景下,一些下推计算请求与之前的某些请求相同,这些计算请求可以使用缓存的(之前的)下推计算结果。 + + - SQL 语句包含多个变化的条件,其他部分一致。变化的条件恰好匹配复合索引列。 + + 在这种场景下,一些下推计算请求与之前的某些请求相同,这些计算请求可以使用缓存的(之前的)下推计算结果。 + ++ 此功能对用户透明。启用或禁用此功能不会影响计算结果,只会影响 SQL 执行时间。 + +## 检查缓存效果 + +您可以通过执行 `EXPLAIN ANALYZE` 或查看 Grafana 监控面板来检查 Coprocessor 的缓存效果。 ### 使用 `EXPLAIN ANALYZE` -用户可以通过 [`EXPLAIN ANALYZE` 语句](/sql-statements/sql-statement-explain-analyze.md)查看[读表算子](/choose-index.md#读表算子)中的缓存命中率,示例如下: +您可以使用 [`EXPLAIN ANALYZE` 语句](/sql-statements/sql-statement-explain-analyze.md)在[访问表的算子](/choose-index.md#访问表的算子)中查看缓存命中率。请看以下示例: ```sql EXPLAIN ANALYZE SELECT * FROM t USE INDEX(a); @@ -53,8 +63,8 @@ EXPLAIN ANALYZE SELECT * FROM t USE INDEX(a); 3 rows in set (0.62 sec) ``` -执行结果的 `execution info` 列有 `copr_cache_hit_ratio` 信息,表示下推计算结果缓存的命中率。以上示例的 `0.75` 表示命中率大约是 75%。 +执行结果的 `execution info` 列给出了 `copr_cache_hit_ratio` 信息,表示 Coprocessor 缓存的命中率。上述示例中的 `0.75` 表示命中率约为 75%。 ### 查看 Grafana 监控面板 -在 Grafana 监控中,`tidb` 命名空间下 `distsql` 子系统中可见 **copr-cache** 面板,该面板监控整个集群中下推计算结果缓存的命中次数、未命中次数和缓存丢弃次数。 +在 Grafana 中,您可以在 `tidb` 命名空间下的 `distsql` 子系统中看到 **copr-cache** 面板。此面板监控整个集群中 Coprocessor 缓存的命中次数、未命中次数和缓存丢弃次数。 diff --git a/correlated-subquery-optimization.md b/correlated-subquery-optimization.md index 650b79452480..5cdeda02a3b1 100644 --- a/correlated-subquery-optimization.md +++ b/correlated-subquery-optimization.md @@ -1,25 +1,25 @@ --- -title: 关联子查询去关联 -summary: 了解如何给关联子查询解除关联。 +title: 相关子查询去关联化 +summary: 了解如何对相关子查询进行去关联化。 --- -# 关联子查询去关联 +# 相关子查询去关联化 -[子查询相关的优化](/subquery-optimization.md)中介绍了当没有关联列时,TiDB 是如何处理子查询的。由于为关联子查询解除关联依赖比较复杂,本文档中会介绍一些简单的场景以及这个优化规则的适用范围。 +[子查询相关优化](/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` 的形式。 +以 `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` 值的不同而发生变化。当通过一些手段将关联依赖解除后,这个子查询就只需要被执行一次了。 +TiDB 需要进行这种重写的原因是,相关子查询每次执行时都会绑定到其外部查询结果。在上面的例子中,如果 `t1.a` 有 1000 万个值,这个子查询就会重复 1000 万次,因为条件 `t2.b=t1.b` 会随着 `t1.a` 的值而变化。当以某种方式去除关联后,这个子查询只需执行一次。 ## 限制 -这种改写的弊端在于,在关联没有被解除时,优化器是可以使用关联列上的索引的。也就是说,虽然这个子查询可能被重复执行多次,但是每次都可以使用索引过滤数据。而解除关联的变换上,通常是会导致关联列的位置发生改变而导致虽然子查询只被执行了一次,但是单次执行的时间会比没有解除关联时的单次执行时间长。 +这种重写的缺点是,当关联没有被去除时,优化器可以使用相关列上的索引。也就是说,虽然这个子查询可能重复多次,但每次都可以使用索引来过滤数据。使用重写规则后,相关列的位置通常会发生变化。虽然子查询只执行一次,但单次执行时间可能会比不去关联化时更长。 -因此,在外部的值比较少的情况下,不解除关联依赖反而可能对执行性能更有帮助。这时可以通过使用 Optimizer Hint [`NO_DECORRELATE`](/optimizer-hints.md#no_decorrelate) 或[优化规则及表达式下推的黑名单](/blocklist-control-plan.md)中关闭“子查询去关联”优化规则的方式来关闭这个优化。在一般情况下,推荐使用 Optimizer Hint 并在需要时配合[执行计划管理](/sql-plan-management.md)功能来禁止解除关联。 +因此,当外部值较少时,不执行去关联化可能会带来更好的执行性能。在这种情况下,您可以使用 [`NO_DECORRELATE`](/optimizer-hints.md#no_decorrelate) 优化器提示或在[优化规则和表达式下推的黑名单](/blocklist-control-plan.md)中禁用"子查询去关联化"优化规则。在大多数情况下,建议将优化器提示与 [SQL 计划管理](/sql-plan-management.md)结合使用来禁用去关联化。 -## 样例 +## 示例 {{< copyable "sql" >}} @@ -46,9 +46,9 @@ explain select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1. ``` -上面是优化生效的情况,可以看到 `HashJoin_11` 是一个普通的 `inner join`。 +上面是优化生效的示例。`HashJoin_11` 是一个普通的 `inner join`。 -接下来,通过 Optimizer Hint `NO_DECORRELATE` 提示优化器不对该子查询解除关联: +然后,您可以使用 `NO_DECORRELATE` 优化器提示来告诉优化器不要对子查询进行去关联化: {{< copyable "sql" >}} @@ -73,7 +73,7 @@ explain select * from t1 where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) +------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ``` -也可以通过全局关闭关联规则达到同样的效果: +禁用去关联化规则也可以达到相同的效果: {{< copyable "sql" >}} @@ -83,7 +83,7 @@ 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 | +------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ @@ -100,4 +100,4 @@ explain select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1. +------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ``` -在执行了关闭关联规则的语句后,可以在 `IndexRangeScan_42(Build)` 的 `operator info` 中看到 `range: decided by [eq(test.t2.b, test.t1.b)]`。这部分信息就是关联依赖未被解除时,TiDB 使用关联条件进行索引范围查询的显示结果。 +禁用子查询去关联化规则后,您可以在 `IndexRangeScan_42(Build)` 的 `operator info` 中看到 `range: decided by [eq(test.t2.b, test.t1.b)]`。这意味着没有执行相关子查询的去关联化,TiDB 使用了索引范围查询。 diff --git a/cost-model.md b/cost-model.md index 984d85e9e704..2f7bd1fd9728 100644 --- a/cost-model.md +++ b/cost-model.md @@ -1,17 +1,17 @@ --- -title: 代价模型 -summary: 介绍 TiDB 进行物理优化时所使用的代价模型的原理。 +title: 成本模型 +summary: 了解 TiDB 在物理优化过程中使用的成本模型是如何工作的。 --- -# 代价模型 +# 成本模型 -TiDB 在进行[物理优化](/sql-physical-optimization.md)时会使用代价模型来进行索引选择和算子选择,如下图所示: +TiDB 在[物理优化](/sql-physical-optimization.md)过程中使用成本模型来选择索引和运算符。该过程如下图所示: ![CostModel](/media/cost-model.png) -TiDB 会计算每个索引的访问代价和计划中每个物理算子的执行代价(如 HashJoin、IndexJoin 等),选择代价最低的计划。 +TiDB 计算计划中每个索引的访问成本和每个物理运算符(如 HashJoin 和 IndexJoin)的执行成本,并选择成本最小的计划。 -下面是一个简化的例子,用来解释代价模型的原理,比如有这样一张表: +以下是一个简化的示例,用于解释成本模型的工作原理。假设有一个表 `t`: ```sql mysql> SHOW CREATE TABLE t; @@ -29,23 +29,23 @@ mysql> SHOW CREATE TABLE t; 1 row in set (0.00 sec) ``` -在处理查询 `SELECT * FROM t WHERE b < 100 and c < 100` 时,假设 TiDB 对 `b < 100` 和 `c < 100` 的行数估计分别为 20 和 500,`INT` 类型索引行宽为 8,则 TiDB 会分别计算两个索引的代价: +在执行 `SELECT * FROM t WHERE b < 100 and c < 100` 语句时,假设 TiDB 估计有 20 行满足 `b < 100` 条件,500 行满足 `c < 100`,且 `INT` 类型索引的长度为 8。那么 TiDB 计算两个索引的成本: -+ 索引 `b` 的扫描代价 = `b < 100` 的行数 \* 索引 `b` 的行宽 = 20 * 8 = 160 -+ 索引 `c` 的扫描代价 = `c < 100` 的行数 \* 索引 `c` 的行宽 = 500 * 8 = 4000 ++ 索引 `b` 的成本 = `b < 100` 的行数 \* 索引 `b` 的长度 = 20 * 8 = 160 ++ 索引 `c` 的成本 = `c < 100` 的行数 \* 索引 `c` 的长度 = 500 * 8 = 4000 -由于扫描 `b` 的代价更低,因此 TiDB 会选择 `b` 索引。 +因为索引 `b` 的成本较低,TiDB 选择 `b` 作为索引。 -上述是一个简化后的例子,只是用于做原理解释,实际 TiDB 的代价模型会更加复杂。 +上述示例是简化的,仅用于解释基本原理。在实际的 SQL 执行中,TiDB 成本模型更为复杂。 -## Cost Model Version 2 +## 成本模型版本 2 -TiDB v6.2.0 引入了新的代价模型 Cost Model Version 2。 +TiDB v6.2.0 引入了成本模型版本 2,这是一个新的成本模型。 -Cost Model Version 2 对代价公式进行了更精确的回归校准,调整了部分代价公式,比此前版本的代价公式更加准确。 +成本模型版本 2 对成本公式进行了更准确的回归校准,调整了一些成本公式,比之前版本的成本公式更准确。 -你可以通过设置变量 [`tidb_cost_model_version`](/system-variables.md#tidb_cost_model_version-从-v620-版本开始引入) 来控制代价模型的版本。 +要切换成本模型的版本,您可以设置 [`tidb_cost_model_version`](/system-variables.md#tidb_cost_model_version-new-in-v620) 变量。 > **注意:** > -> 切换代价模型版本可能引起执行计划的变动。 \ No newline at end of file +> 切换成本模型的版本可能会导致查询计划发生变化。 diff --git a/data-type-date-and-time.md b/data-type-date-and-time.md index 87ca9b493a64..7066e37e2fd4 100644 --- a/data-type-date-and-time.md +++ b/data-type-date-and-time.md @@ -1,27 +1,22 @@ --- title: 日期和时间类型 -summary: TiDB 支持 MySQL 的所有日期和时间类型,包括 DATE、TIME、DATETIME、TIMESTAMP 和 YEAR。每种类型都有有效值范围,值为 0 表示无效值。TIMESTAMP 和 DATETIME 类型能自动生成新的时间值。关于日期和时间值类型,需要注意日期部分必须是“年 - 月 - 日”的格式,如果日期的年份部分是 2 位数,TiDB 会根据具体规则进行转换。不同类型的零值如下表所示: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 值,无效值会自动转换为相应的零值。 +summary: 了解支持的日期和时间类型。 --- # 日期和时间类型 -TiDB 支持 MySQL 所有的日期和时间类型,包括 [`DATE`](#date-类型)、[`TIME`](#time-类型)、[`DATETIME`](#datetime-类型)、[`TIMESTAMP`](#timestamp-类型) 以及 [`YEAR`](#year-类型)。完整信息可以参考 [MySQL 中的时间和日期类型](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html)。 +TiDB 支持所有 MySQL 日期和时间数据类型来存储时间值:[`DATE`](#date-类型)、[`TIME`](#time-类型)、[`DATETIME`](#datetime-类型)、[`TIMESTAMP`](#timestamp-类型) 和 [`YEAR`](#year-类型)。更多信息,请参见 [MySQL 中的日期和时间数据类型](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html)。 -每种类型都有有效值范围,值为 0 表示无效值。此外,`TIMESTAMP` 和 `DATETIME` 类型能自动生成新的时间值。 +每种类型都有其有效值范围,并使用零值来表示无效值。此外,`TIMESTAMP` 和 `DATETIME` 类型可以在修改时自动生成新的时间值。 -关于日期和时间值类型,需要注意: +在处理日期和时间值类型时,请注意: -- 日期部分必须是“年-月-日”的格式(例如 `1998-09-04`),而不是“月-日-年”或“日-月-年”的格式。 -- 如果日期的年份部分是 2 位数,TiDB 会根据[年份为两位数的具体规则](#年份为两位数)进行转换。 -- 如果格式必须是数值类型,TiDB 会自动将日期或时间值转换为数值类型。例如: - - {{< copyable "sql" >}} - - ```sql - SELECT NOW(), NOW()+0, NOW(3)+0; - ``` ++ 虽然 TiDB 尝试解释不同的格式,但日期部分必须采用年-月-日格式(例如 '1998-09-04'),而不是月-日-年或日-月-年格式。 ++ 如果日期的年份部分指定为 2 位数字,TiDB 会根据[特定规则](#日期中包含的两位数年份)进行转换。 ++ 如果在上下文中需要数值,TiDB 会自动将日期或时间值转换为数值类型。例如: ```sql + mysql> SELECT NOW(), NOW()+0, NOW(3)+0; +---------------------+----------------+--------------------+ | NOW() | NOW()+0 | NOW(3)+0 | +---------------------+----------------+--------------------+ @@ -29,15 +24,10 @@ TiDB 支持 MySQL 所有的日期和时间类型,包括 [`DATE`](#date-类型) +---------------------+----------------+--------------------+ ``` -- TiDB 可以自动将无效值转换同一类型的零值。是否进行转换取决于 SQL 模式的设置。比如: - - {{< copyable "sql" >}} - - ```sql - show create table t1; - ``` ++ TiDB 可能会自动将无效值或超出支持范围的值转换为该类型的零值。此行为取决于设置的 SQL 模式。例如: ```sql + mysql> show create table t1; +-------+---------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+---------------------------------------------------------------------------------------------------------+ @@ -46,60 +36,23 @@ TiDB 支持 MySQL 所有的日期和时间类型,包括 [`DATE`](#date-类型) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin | +-------+---------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) - ``` - - {{< copyable "sql" >}} - ```sql - select @@sql_mode; - ``` - - ```sql + mysql> select @@sql_mode; +-------------------------------------------------------------------------------------------------------------------------------------------+ | @@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" >}} + mysql> insert into t1 values ('2090-11-32:22:33:44'); + ERROR 1292 (22007): Truncated incorrect time value: '2090-11-32:22:33:44' + mysql> set @@sql_mode=''; Query OK, 0 rows affected (0.01 sec) - ```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 + mysql> insert into t1 values ('2090-11-32:22:33:44'); Query OK, 1 row affected, 1 warning (0.01 sec) - ``` - - {{< copyable "sql" >}} - - ```sql - select * from t1; - ``` - ```sql + mysql> select * from t1; +----------+ | a | +----------+ @@ -108,29 +61,27 @@ TiDB 支持 MySQL 所有的日期和时间类型,包括 [`DATE`](#date-类型) 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` 这样的零值。 ++ 设置不同的 SQL 模式可以改变 TiDB 的行为。 ++ 如果未启用 SQL 模式 `NO_ZERO_DATE`,TiDB 允许 `DATE` 和 `DATETIME` 列中的月份或日期为零值,例如 '2009-00-00' 或 '2009-01-00'。如果这种日期类型要在函数中计算,例如在 `DATE_SUB()` 或 `DATE_ADD()` 中,结果可能不正确。 ++ 默认情况下,TiDB 启用 SQL 模式 `NO_ZERO_DATE`。此模式防止存储零值,如 '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` | +| 日期类型 | "零" 值 | +| :------ | :---- | +| 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`)。 +如果 SQL 模式允许这种用法,无效的 `DATE`、`DATETIME`、`TIMESTAMP` 值会自动转换为相应类型的零值('0000-00-00' 或 '0000-00-00 00:00:00')。 -## 类型定义 +## 支持的类型 ### `DATE` 类型 -`DATE` 类型只包含日期部分,不包含时间部分。`DATE` 类型的格式为 `YYYY-MM-DD`,支持的范围是 `0000-01-01` 到 `9999-12-31`。 - -{{< copyable "sql" >}} +`DATE` 只包含日期部分而没有时间部分,以 `YYYY-MM-DD` 格式显示。支持的范围是 '0000-01-01' 到 '9999-12-31': ```sql DATE @@ -138,9 +89,7 @@ DATE ### `TIME` 类型 -`TIME` 类型的格式为 `HH:MM:SS[.fraction]`,支持的范围是 `-838:59:59.000000` 到 `838:59:59.000000`。`TIME` 不仅可用于指示一天内的时间,还可用于指两个事件之间的时间间隔。`fsp` 参数表示秒精度,取值范围为:0 ~ 6,默认值为 0。 - -{{< copyable "sql" >}} +对于 `TIME` 类型,格式为 `HH:MM:SS[.fraction]`,有效值范围从 '-838:59:59.000000' 到 '838:59:59.000000'。`TIME` 不仅用于表示一天内的时间,还用于表示两个事件之间的时间间隔。可以指定一个可选的 `fsp` 值,范围从 0 到 6,用于指定小数秒精度。如果省略,默认精度为 0: ```sql TIME[(fsp)] @@ -148,13 +97,13 @@ TIME[(fsp)] > **注意:** > -> 注意 `TIME` 的缩写形式。例如,`11:12` 表示 `11:12:00` 而不是 `00:11:12`。但是,`1112` 表示 `00:11:12`。这些差异取决于 `:` 字符的存在与否。 +> 注意 `TIME` 的缩写形式。例如,'11:12' 表示 '11:12:00' 而不是 '00:11:12'。但是,'1112' 表示 '00:11:12'。这些差异是由 `:` 字符的存在或缺失造成的。 ### `DATETIME` 类型 -`DATETIME` 类型是日期和时间的组合,格式为 `YYYY-MM-DD HH:MM:SS[.fraction]`。支持的范围是 `0000-01-01 00:00:00.000000` 到 `9999-12-31 23:59:59.999999`。`fsp` 参数表示秒精度,取值范围为 0~6,默认值为 0。TiDB 支持字符串或数字转换为 `DATETIME` 类型。 +`DATETIME` 同时包含日期部分和时间部分。有效值范围从 '0000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'。 -{{< copyable "sql" >}} +TiDB 以 `YYYY-MM-DD HH:MM:SS[.fraction]` 格式显示 `DATETIME` 值,但允许使用字符串或数字为 `DATETIME` 列赋值。可以指定一个可选的 fsp 值,范围从 0 到 6,用于指定小数秒精度。如果省略,默认精度为 0: ```sql DATETIME[(fsp)] @@ -162,9 +111,9 @@ 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`。 +`TIMESTAMP` 同时包含日期部分和时间部分。有效值范围从 '1970-01-01 00:00:01.000000' 到 '2038-01-19 03:14:07.999999'(UTC 时间)。可以指定一个可选的 fsp 值,范围从 0 到 6,用于指定小数秒精度。如果省略,默认精度为 0。 -{{< copyable "sql" >}} +在 `TIMESTAMP` 中,不允许月份部分或日期部分出现零值。唯一的例外是零值本身 '0000-00-00 00:00:00'。 ```sql TIMESTAMP[(fsp)] @@ -172,41 +121,37 @@ TIMESTAMP[(fsp)] #### 时区处理 -当存储 `TIMESTAMP` 时,TiDB 会将当前时区的 `TIMESTAMP` 值转换为 UTC 时区。当读取 `TIMESTAMP` 时,TiDB 将存储的 `TIMESTAMP` 值从 UTC 时区转换为当前时区(注意:`DATETIME` 不会这样处理)。每次连接的默认时区是服务器的本地时区,可以通过环境变量 `time_zone` 进行修改。 +当存储 `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` 类型。 +> 与 MySQL 一样,`TIMESTAMP` 数据类型受到 [2038 年问题](https://en.wikipedia.org/wiki/Year_2038_problem)的影响。对于可能跨越 2038 年的值,请考虑使用 `DATETIME` 类型。 ### `YEAR` 类型 -`YEAR` 类型的格式为 `YYYY`,支持的值范围是 `1901` 到 `2155`,也支持零值 `0000`。 - -{{< copyable "sql" >}} +`YEAR` 类型以 'YYYY' 格式指定。支持的值范围从 1901 到 2155,或零值 0000: ```sql YEAR[(4)] ``` -`YEAR` 类型遵循以下格式规则: +`YEAR` 遵循以下格式规则: -+ 如果是四位数的数值,支持的范围是 `1901` 至 `2155`。 -+ 如果是四位数的字符串,支持的范围是 `'1901'` 到 `'2155'`。 -+ 如果是 1~99 之间的一位数或两位数的数字,1~69 换算成 2001~2069,70~99 换算成 1970~1999。 -+ 支持 `'0'` 到 `'99'` 之间的一位数或两位数字符串的范围 -+ 将数值 `0` 转换为 `0000`,将字符串 `'0'` 或 `'00'` 转换为 `'2000'`。 ++ 四位数字范围从 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 模式)。 +无效的 `YEAR` 值会自动转换为 0000(如果用户没有使用 `NO_ZERO_DATE` SQL 模式)。 -## 自动初始化和更新 `TIMESTAMP` 或 `DATETIME` +## `TIMESTAMP` 和 `DATETIME` 的自动初始化和更新 -带有 `TIMESTAMP` 或 `DATETIME` 数据类型的列可以自动初始化为或更新为当前时间。 +具有 `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" >}} +这些属性可以通过在定义列时设置 `DEFAULT CURRENT_TIMESTAMP` 和 `ON UPDATE CURRENT_TIMESTAMP` 来设置。DEFAULT 也可以设置为特定值,如 `DEFAULT 0` 或 `DEFAULT '2000-01-01 00:00:00'`。 ```sql CREATE TABLE t1 ( @@ -215,63 +160,40 @@ CREATE TABLE t1 ( ); ``` -除非指定 `DATETIME` 的值为 `NOT NULL`,否则默认 `DATETIME` 的值为 `NULL`。指定 `DATETIME` 的值为 `NOT NULL` 时,如果没有设置默认值,则默认值为 `0`。 - -{{< copyable "sql" >}} +`DATETIME` 的默认值是 `NULL`,除非指定为 `NOT NULL`。对于后者,如果没有设置默认值,默认值为 0。 ```sql CREATE TABLE t1 ( - dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP, -- default NULL - dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0 + dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP, -- 默认 NULL + dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- 默认 0 ); ``` ## 时间值的小数部分 -`DATETIME` 和 `TIMESTAMP` 值最多可以有 6 位小数,精确到微秒。如果包含小数部分,值的格式为 `YYYY-MM-DD HH:MM:SS[.fraction]`,小数部分的范围为 `000000` 到`999999`。必须使用小数点分隔小数部分与其他部分。 - -+ 使用 `type_name(fsp)` 可以定义精确到小数的列,其中 `type_name` 可以是`TIME`、`DATETIME` 或 `TIMESTAMP`。例如: +`DATETIME` 和 `TIMESTAMP` 值可以包含最多 6 位的小数部分,精确到微秒。在 `DATETIME` 或 `TIMESTAMP` 类型的任何列中,小数部分会被存储而不是被丢弃。带有小数部分的值的格式为 'YYYY-MM-DD HH:MM:SS[.fraction]',小数部分范围从 000000 到 999999。必须使用小数点来分隔小数部分和其余部分。 - {{< copyable "sql" >}} ++ 使用 `type_name(fsp)` 定义支持小数精度的列,其中 `type_name` 可以是 `TIME`、`DATETIME` 或 `TIMESTAMP`。例如, ```sql CREATE TABLE t1 (t TIME(3), dt DATETIME(6)); ``` - `fsp` 范围是 `0` 到 `6`。 + `fsp` 必须在 0 到 6 之间。 - `0` 表示没有小数部分。如果省略了 `fsp`,默认为 `0`。 + `0` 表示没有小数部分。如果省略 `fsp`,默认为 0。 -+ 当插入包含小数部分的 `TIME`、`DATETIME` 或 `TIMESTAMP` 时,如果小数部分的位数过少或过多,可能需要进行四舍五入。例如: - - {{< copyable "sql" >}} - - ```sql - CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) ); - ``` ++ 当插入包含小数部分的 `TIME`、`DATETIME` 或 `TIMESTAMP` 时,如果小数部分的位数太少或太多,可能需要进行舍入。例如: ```sql + mysql> CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) ); Query OK, 0 rows affected (0.33 sec) - ``` - {{< copyable "sql" >}} - - ```sql - INSERT INTO fractest VALUES + mysql> 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 + mysql> SELECT * FROM fractest; +-------------|------------------------|------------------------+ | c1 | c2 | c3 | +-------------|------------------------|------------------------+ @@ -280,55 +202,40 @@ CREATE TABLE t1 ( 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`、`DATETIME` 和 `TIMESTAMP` 值都有各自的范围。`TIMESTAMP` 在 UTC 时间中不应早于 1970 年或晚于 UTC 时间 '2038-01-19 03:14:07'。基于此规则,'1968-01-01' 是 `DATE` 或 `DATETIME` 的有效日期值,但当转换为 `TIMESTAMP` 时变为 0。 `DATE` 的转换: -+ 当 `DATE` 转换为 `DATETIME` 或 `TIMESTAMP` 时,会添加时间部分 `00:00:00`,因为 `DATE` 不包含任何时间信息。 -+ 当 `DATE` 转换为 `TIME` 时,结果是 `00:00:00`。 ++ 当 `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` 不包含任何日期信息。 ++ 当 `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` 转换为其他时间和日期格式时,日期部分会自动指定为 `CURRENT_DATE()`。最终转换的结果是由 `TIME` 和 `CURRENT_DATE()` 组成的日期。这意味着如果 TIME 的值超出 '00:00:00' 到 '23:59:59' 的范围,转换后的日期部分不表示当前日期。 -当 `TIME` 转换为 `DATE` 时,转换过程类似,时间部分被舍弃。 +当 `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; -``` +将 `TIME` 和 `DATETIME` 转换为数值格式。例如: ```sql +mysql> SELECT CURTIME(), CURTIME()+0, CURTIME(3)+0; +-----------|-------------|--------------+ | CURTIME() | CURTIME()+0 | CURTIME(3)+0 | +-----------|-------------|--------------+ | 09:28:00 | 92800 | 92800.887 | +-----------|-------------|--------------+ -``` - -{{< copyable "sql" >}} - -```sql -SELECT NOW(), NOW()+0, NOW(3)+0; -``` - -```sql +mysql> SELECT NOW(), NOW()+0, NOW(3)+0; +---------------------|----------------|--------------------+ | NOW() | NOW()+0 | NOW(3)+0 | +---------------------|----------------|--------------------+ @@ -336,17 +243,19 @@ SELECT NOW(), NOW()+0, NOW(3)+0; +---------------------|----------------|--------------------+ ``` -## 年份为两位数 +## 日期中包含的两位数年份 + +日期中包含的两位数年份不能明确表示实际年份,具有歧义性。 -如果日期中包含年份为两位数,这个年份是有歧义的,并不显式地表示实际年份。 +对于 `DATETIME`、`DATE` 和 `TIMESTAMP` 类型,TiDB 遵循以下规则来消除歧义: -对于 `DATETIME`、`DATE` 和 `TIMESTAMP` 类型,TiDB 使用如下规则来消除歧义。 +- 01 到 69 之间的值转换为 2001 到 2069 之间的值 +- 70 到 99 之间的值转换为 1970 到 1999 之间的值 -- 将 01 至 69 之间的值转换为 2001 至 2069 之间的值。 -- 将 70 至 99 之间的值转化为 1970 至 1999 之间的值。 +这些规则也适用于 `YEAR` 类型,但有一个例外: -上述规则也适用于 `YEAR` 类型,但有一个例外。将数字 `00` 插入到 `YEAR(4)` 中时,结果是 0000 而不是 2000。 +当数字 `00` 插入到 `YEAR(4)` 时,结果是 0000 而不是 2000。 -如果想让结果是 2000,需要指定值为 `2000`。 +如果你想要结果为 2000,请指定值为 2000。 -对于 `MIN()` 和 `MAX()` 等函数,年份为两位数时可能会得到错误的计算结果。建议年份为四位数时使用这类函数。 +两位数年份在某些函数(如 `MIN()` 和 `MAX()`)中可能无法正确计算。对于这些函数,四位数格式更适合。 diff --git a/data-type-default-values.md b/data-type-default-values.md index e1e6d2ae551c..5559370cb685 100644 --- a/data-type-default-values.md +++ b/data-type-default-values.md @@ -1,52 +1,52 @@ --- -title: 数据类型的默认值 -summary: 数据类型的默认值描述了列的默认值设置规则。默认值必须是常量,对于时间类型可以使用特定函数。从 v8.0.0 开始,BLOB、TEXT 和 JSON 可以设置表达式默认值。如果列没有设置 DEFAULT,TiDB 会根据规则添加隐式默认值。对于 NOT NULL 列,根据 SQL_MODE 进行不同行为。表达式默认值是实验特性,不建议在生产环境中使用。MySQL 8.0.13 开始支持在 DEFAULT 子句中指定表达式为默认值。TiDB 支持为 BLOB、TEXT 和 JSON 数据类型分配默认值,但仅支持通过表达式来设置。 +title: TiDB 数据类型 +summary: 了解 TiDB 中数据类型的默认值。 --- -# 数据类型的默认值 +# 默认值 -在一个数据类型描述中的 `DEFAULT value` 段描述了一个列的默认值。 +数据类型规范中的 `DEFAULT` 值子句表示列的默认值。 -所有数据类型都可以设置默认值。这个默认值通常情况下必须是常量,不可以是一个函数或者是表达式,但也存在以下例外情况: +你可以为所有数据类型设置默认值。通常,默认值必须是常量,不能是函数或表达式,但有一些例外: -- 对于时间类型,可以使用 `NOW`、`CURRENT_TIMESTAMP`、`LOCALTIME`、`LOCALTIMESTAMP` 等函数作为 `DATETIME` 或者 `TIMESTAMP` 列的默认值。 -- 对于整数类型,可以使用 `NEXT VALUE FOR` 函数将序列的下一个值作为列的默认值,使用 [`RAND()`](/functions-and-operators/numeric-functions-and-operators.md) 函数生成随机浮点值作为列的默认值。 -- 对于字符串类型,可以使用 [`UUID()`](/functions-and-operators/miscellaneous-functions.md) 函数生成[通用唯一标识符 (UUID)](/best-practices/uuid.md) 作为列的默认值。 -- 对于二进制类型,可以使用 [`UUID_TO_BIN()`](/functions-and-operators/miscellaneous-functions.md) 函数将 UUID 转换为二进制格式后作为列的默认值。 -- 从 v8.0.0 开始,新增支持 [`BLOB`](/data-type-string.md#blob-类型)、[`TEXT`](/data-type-string.md#text-类型) 以及 [`JSON`](/data-type-json.md#json-数据类型) 这三种数据类型设置默认值,但仅支持使用表达式设置[默认值](#表达式默认值)。 +- 对于时间类型,你可以使用 `NOW`、`CURRENT_TIMESTAMP`、`LOCALTIME` 和 `LOCALTIMESTAMP` 函数作为 `TIMESTAMP` 和 `DATETIME` 列的默认值。 +- 对于整数类型,你可以使用 `NEXT VALUE FOR` 函数将序列的下一个值设置为列的默认值,并使用 [`RAND()`](/functions-and-operators/numeric-functions-and-operators.md) 函数生成随机浮点值作为列的默认值。 +- 对于字符串类型,你可以使用 [`UUID()`](/functions-and-operators/miscellaneous-functions.md) 函数生成[通用唯一标识符 (UUID)](/best-practices/uuid.md) 作为列的默认值。 +- 对于二进制类型,你可以使用 [`UUID_TO_BIN()`](/functions-and-operators/miscellaneous-functions.md) 函数将 UUID 转换为二进制格式,并将转换后的值设置为列的默认值。 +- 从 v8.0.0 开始,TiDB 额外支持为 [`BLOB`](/data-type-string.md#blob-type)、[`TEXT`](/data-type-string.md#text-type) 和 [`JSON`](/data-type-json.md#json-data-type) 数据类型[指定默认值](#指定表达式作为默认值),但你只能使用表达式为它们设置[默认值](#默认值)。 -如果一个列的定义中没有 `DEFAULT` 的设置。TiDB 按照如下的规则决定: +如果列定义中不包含显式的 `DEFAULT` 值,TiDB 将按如下方式确定默认值: -* 如果该类型可以使用 `NULL` 作为值,那么这个列会在定义时添加隐式的默认值设置 `DEFAULT NULL`。 -* 如果该类型无法使用 `NULL` 作为值,那么这个列在定义时不会添加隐式的默认值设置。 +- 如果列可以接受 `NULL` 作为值,则该列使用显式的 `DEFAULT NULL` 子句定义。 +- 如果列不能接受 `NULL` 作为值,则 TiDB 定义该列时不使用显式的 `DEFAULT` 子句。 -对于一个设置了 `NOT NULL` 但是没有显式设置 `DEFAULT` 的列,当 `INSERT`、`REPLACE` 没有涉及到该列的值时,TiDB 根据当时的 `SQL_MODE` 进行不同的行为: +对于没有显式 `DEFAULT` 子句的 `NOT NULL` 列,如果 `INSERT` 或 `REPLACE` 语句没有为该列包含值,TiDB 将根据当时生效的 SQL 模式处理该列: -* 如果此时是 `strict sql mode`,在事务中的语句会导致事务失败并回滚,非事务中的语句会直接报错。 -* 如果此时不是 `strict sql mode`,TiDB 会为这列赋值为列数据类型的隐式默认值。 +- 如果启用了严格 SQL 模式,对于事务表会发生错误并回滚语句。对于非事务表,会发生错误。 +- 如果未启用严格模式,TiDB 将该列设置为该列数据类型的隐式默认值。 -此时隐式默认值的设置按照如下规则: +隐式默认值定义如下: -* 对于数值类型,它们的默认值是 0。当有 `AUTO_INCREMENT` 参数时,默认值会按照增量情况赋予正确的值。 -* 对于除了时间戳外的日期时间类型,默认值会是该类型的“零值”。时间戳类型的默认值会是当前的时间。 -* 对于除枚举以外的字符串类型,默认值会是空字符串。对于枚举类型,默认值是枚举中的第一个值。 +- 对于数值类型,默认值为 0。如果声明了 `AUTO_INCREMENT` 属性,默认值为序列中的下一个值。 +- 对于除 `TIMESTAMP` 以外的日期和时间类型,默认值为该类型的适当"零"值。对于 `TIMESTAMP`,默认值为当前日期和时间。 +- 对于除 `ENUM` 以外的字符串类型,默认值为空字符串。对于 `ENUM`,默认值为第一个枚举值。 -## 表达式默认值 +## 指定表达式作为默认值 -MySQL 从 8.0.13 开始支持在 `DEFAULT` 子句中指定表达式为默认值。具体可参考 [Explicit Default Handling as of MySQL 8.0.13](https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html#data-type-defaults-explicit)。 +从 8.0.13 开始,MySQL 支持在 `DEFAULT` 子句中指定表达式作为默认值。更多信息,请参见 [MySQL 8.0.13 中的显式默认值处理](https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html#data-type-defaults-explicit)。 -从 v8.0.0 开始,TiDB 在 `DEFAULT` 子句中新增支持指定以下表达式作为字段的默认值: +从 v8.0.0 开始,TiDB 额外支持在 `DEFAULT` 子句中指定以下表达式作为默认值。 * `UPPER(SUBSTRING_INDEX(USER(), '@', 1))` * `REPLACE(UPPER(UUID()), '-', '')` -* `DATE_FORMAT` 相关表达式,具体格式如下: +* 以下格式的 `DATE_FORMAT` 表达式: * `DATE_FORMAT(NOW(), '%Y-%m')` * `DATE_FORMAT(NOW(), '%Y-%m-%d')` * `DATE_FORMAT(NOW(), '%Y-%m-%d %H.%i.%s')` * `DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')` * `STR_TO_DATE('1980-01-01', '%Y-%m-%d')` -此外,从 v8.0.0 开始,TiDB 额外支持 `BLOB`、`TEXT` 以及 `JSON` 数据类型分配默认值,但是默认值仅支持通过表达式来设置。以下是 `BLOB` 的示例: +从 v8.0.0 开始,TiDB 额外支持为 `BLOB`、`TEXT` 和 `JSON` 数据类型分配默认值。但是,你只能使用表达式为这些数据类型设置默认值。以下是 `BLOB` 的示例: ```sql CREATE TABLE t2 (b BLOB DEFAULT (RAND())); diff --git a/data-type-json.md b/data-type-json.md index 1196238adb1b..abd738952cb6 100644 --- a/data-type-json.md +++ b/data-type-json.md @@ -1,16 +1,16 @@ --- -title: JSON 类型 -summary: JSON 类型存储半结构化数据,使用 Binary 格式序列化,加快查询和解析速度。JSON 字段不能创建索引,但可以对 JSON 文档中的子字段创建索引。TiDB 仅支持下推部分 JSON 函数到 TiFlash,不建议使用 BR 恢复包含 JSON 列的数据到 v6.3.0 之前的 TiDB 集群。请勿同步非标准 JSON 类型的数据。MySQL 误标记二进制类型数据为 STRING 类型,TiDB 保持正确的二进制类型。ENUM 或 SET 数据类型转换为 JSON 时,TiDB 会检查格式正确性。TiDB 支持使用 ORDER BY 对 JSON Array 或 JSON Object 进行排序。在 INSERT JSON 列时,TiDB 会将值隐式转换为 JSON。 +title: TiDB 数据类型 +summary: 了解 TiDB 中的 JSON 数据类型。 --- # JSON 数据类型 -JSON 类型可以存储 JSON 这种半结构化的数据,相比于直接将 JSON 存储为字符串,它的好处在于: +TiDB 支持 `JSON`(JavaScript Object Notation)数据类型,这对于存储半结构化数据很有用。与在字符串列中存储 `JSON` 格式字符串相比,`JSON` 数据类型提供以下优势: -1. 使用 Binary 格式进行序列化,对 JSON 的内部字段的查询、解析加快; -2. 多了 JSON 合法性验证的步骤,只有合法的 JSON 文档才可以放入这个字段中; +- 使用二进制格式进行序列化。内部格式允许快速读取 `JSON` 文档元素。 +- 自动验证存储在 `JSON` 列中的 JSON 文档。只能存储有效的文档。 -JSON 字段本身上,并不能创建索引,但是可以对 JSON 文档中的某个子字段创建索引。例如: +`JSON` 列与其他二进制类型的列一样,不能直接索引,但你可以以生成列的形式索引 `JSON` 文档中的字段: ```sql CREATE TABLE city ( @@ -18,49 +18,49 @@ CREATE TABLE city ( 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 函数](/functions-and-operators/json-functions.md)和[生成列](/generated-columns.md)。 +更多信息,请参见 [JSON 函数](/functions-and-operators/json-functions.md)和[生成列](/generated-columns.md)。 -## JSON 值的类型 +## JSON 值类型 -JSON 文档中的每个值都属于一种特定的数据类型。可以通过 [`JSON_TYPE`()](/functions-and-operators/json-functions/json-functions-return.md#json_type) 的输出结果查看。 +JSON 文档内的值具有类型。这在 [`JSON_TYPE`()](/functions-and-operators/json-functions/json-functions-return.md#json_type) 的输出中可以看到。 -| 类型 | 示例 | +| 类型 | 示例 | |------------------|--------------------------------| -| ARRAY | `[]` | -| BIT | | -| BLOB | `0x616263` | -| BOOLEAN | `true` | -| DATE | `"2025-06-14"` | -| DATETIME | `"2025-06-14 09:05:10.000000"` | -| DOUBLE | `1.14` | -| INTEGER | `5` | -| NULL | `null` | -| OBJECT | `{}` | -| OPAQUE | | -| STRING | `"foobar"` | -| TIME | `"09:10:00.000000"` | -| UNSIGNED INTEGER | `9223372036854776000` | - -## 使用限制 - -- 目前 TiDB 仅支持下推部分 JSON 函数到 TiFlash。详情请参考 [TiFlash 支持下推的表达式](/tiflash/tiflash-supported-pushdown-calculations.md#支持下推的表达式)。 -- TiDB Backup & Restore(BR)在 v6.3.0 版本对 JSON 列的数据的编码进行了修改。因此不建议使用 BR 恢复包含 JSON 列的数据到 v6.3.0 之前的 TiDB 集群。 -- 请勿使用任何同步工具同步非标准 JSON 类型(例如 DATE、DATETIME、TIME 等)的数据。 +| ARRAY | `[]` | +| BIT | | +| BLOB | `0x616263` | +| BOOLEAN | `true` | +| DATE | `"2025-06-14"` | +| DATETIME | `"2025-06-14 09:05:10.000000"` | +| DOUBLE | `1.14` | +| INTEGER | `5` | +| NULL | `null` | +| OBJECT | `{}` | +| OPAQUE | | +| STRING | `"foobar"` | +| TIME | `"09:10:00.000000"` | +| UNSIGNED INTEGER | `9223372036854776000` | + +## 限制 + +- 目前,TiDB 仅支持将有限的 `JSON` 函数下推到 TiFlash。更多信息,请参见[下推表达式](/tiflash/tiflash-supported-pushdown-calculations.md#push-down-expressions)。 +- TiDB Backup & Restore (BR) 在 v6.3.0 中更改了 JSON 列数据的编码方式。因此,不建议使用 BR 将包含 JSON 列的数据恢复到早于 v6.3.0 的 TiDB 集群。 +- 不要使用任何复制工具复制包含非标准 `JSON` 数据类型(如 `DATE`、`DATETIME` 和 `TIME`)的数据。 ## MySQL 兼容性 -- 当使用二进制类型数据创建 JSON 时,目前 MySQL 会将其误标记为 STRING 类型,而 TiDB 会保持正确的二进制类型。 +- 当你使用 `BINARY` 类型的数据创建 JSON 列时,MySQL 目前错误地将数据标记为 `STRING` 类型,而 TiDB 正确地将其处理为 `BINARY` 类型。 ```sql CREATE TABLE test(a json); INSERT INTO test SELECT json_objectagg('a', b'01010101'); - -- 在 TiDB 中,执行以下 SQL 语句返回结果如下所示。在 MySQL 中,执行以下 SQL 语句的结果为 `0, 1`。 + -- 在 TiDB 中,执行以下 SQL 语句返回 `0, 0`。在 MySQL 中,执行以下 SQL 语句返回 `0, 1`。 mysql> SELECT JSON_EXTRACT(JSON_OBJECT('a', b'01010101'), '$.a') = "base64:type15:VQ==" AS r1, JSON_EXTRACT(a, '$.a') = "base64:type15:VQ==" AS r2 FROM test; +------+------+ | r1 | r2 | @@ -70,9 +70,9 @@ JSON 文档中的每个值都属于一种特定的数据类型。可以通过 [` 1 row in set (0.01 sec) ``` - 详情可见此 [issue](https://github.com/pingcap/tidb/issues/37443)。 + 更多信息,请参见 issue [#37443](https://github.com/pingcap/tidb/issues/37443)。 -- 当将 ENUM 或 SET 数据类型转换为 JSON 时,TiDB 会检查其格式正确性。例如,当执行下面的 SQL 语句时,TiDB 中会报错: +- 当将数据类型从 `ENUM` 或 `SET` 转换为 `JSON` 时,TiDB 会检查数据格式的正确性。例如,在 TiDB 中执行以下 SQL 语句将返回错误。 ```sql CREATE TABLE t(e ENUM('a')); @@ -81,11 +81,11 @@ JSON 文档中的每个值都属于一种特定的数据类型。可以通过 [` ERROR 3140 (22032): Invalid JSON text: The document root must not be followed by other values. ``` - 详情可见此 [issue](https://github.com/pingcap/tidb/issues/9999)。 + 更多信息,请参见 issue [#9999](https://github.com/pingcap/tidb/issues/9999)。 -- TiDB 支持使用 `ORDER BY` 对 JSON Array 或 JSON Object 进行排序。 +- 在 TiDB 中,你可以使用 `ORDER BY` 对 JSON 数组或 JSON 对象进行排序。 - 当使用 `ORDER BY` 对 JSON Array 或 JSON Object 进行排序时,MySQL 会返回一个警告,且排序结果与比较运算结果不一致: + 在 MySQL 中,如果使用 `ORDER BY` 对 JSON 数组或 JSON 对象进行排序,MySQL 会返回警告,并且排序结果与比较操作的结果不匹配: ```sql CREATE TABLE t(j JSON); @@ -100,7 +100,7 @@ JSON 文档中的每个值都属于一种特定的数据类型。可以通过 [` +--------------+ 1 row in set (0.00 sec) - -- 在 TiDB 中,执行以下 SQL 语句返回结果如下所示。在 MySQL 中,执行以下 SQL 语句会返回警告 “This version of MySQL doesn't yet support 'sorting of non-scalar JSON values'. ”,且排序结果与 `<` 比较结果不一致。 + -- 在 TiDB 中,执行以下 SQL 语句返回正确的排序结果。在 MySQL 中,执行以下 SQL 语句会返回"This version of MySQL doesn't yet support 'sorting of non-scalar JSON values'."警告,且排序结果与 `<` 的比较结果不一致。 mysql> SELECT j FROM t ORDER BY j; +--------------+ | j | @@ -111,15 +111,15 @@ JSON 文档中的每个值都属于一种特定的数据类型。可以通过 [` 2 rows in set (0.00 sec) ``` - 详情可见此 [issue](https://github.com/pingcap/tidb/issues/37506)。 + 更多信息,请参见 issue [#37506](https://github.com/pingcap/tidb/issues/37506)。 -- 在 INSERT JSON 列时,TiDB 会将值隐式转换为 JSON: +- 当你向 JSON 列插入数据时,TiDB 会隐式地将数据的值转换为 `JSON` 类型。 ```sql CREATE TABLE t(col JSON); - -- 在 TiDB 中,执行以下 INSERT 语句成功。在 MySQL 中,执行以下 INSERT 语句将返回 Invalid JSON text 错误。 + -- 在 TiDB 中,以下 INSERT 语句成功执行。在 MySQL 中,执行以下 INSERT 语句会返回"Invalid JSON text"错误。 INSERT INTO t VALUES (3); ``` -有关 JSON 的更多信息,可以参考 [JSON 函数](/functions-and-operators/json-functions.md)和[生成列](/generated-columns.md)。 +有关 `JSON` 数据类型的更多信息,请参见 [JSON 函数](/functions-and-operators/json-functions.md)和[生成列](/generated-columns.md)。 diff --git a/data-type-numeric.md b/data-type-numeric.md index d09b2234dc04..ae848efba750 100644 --- a/data-type-numeric.md +++ b/data-type-numeric.md @@ -1,75 +1,73 @@ --- title: 数值类型 -summary: TiDB 支持 MySQL 的所有数值类型,包括整数类型、浮点类型和定点类型。整数类型包括 BIT、BOOLEAN、TINYINT、SMALLINT、MEDIUMINT、INTEGER 和 BIGINT,存储空间和取值范围各不相同。浮点类型包括 FLOAT 和 DOUBLE,存储空间分别为 4 和 8 字节。定点类型包括 DECIMAL 和 NUMERIC,可设置小数位数和小数点后位数。建议使用 DECIMAL 类型存储精确值。 +summary: 了解 TiDB 支持的数值数据类型。 --- # 数值类型 -TiDB 支持 MySQL 所有的数值类型,按照精度可以分为: +TiDB 支持所有 MySQL 数值类型,包括: -+ [整数类型(精确值)](#整数类型) -+ [浮点类型(近似值)](#浮点类型) -+ [定点类型(精确值)](#定点类型) ++ [整数类型](#整数类型)(精确值) ++ [浮点数类型](#浮点数类型)(近似值) ++ [定点数类型](#定点数类型)(精确值) ## 整数类型 -TiDB 支持 MySQL 所有的整数类型,包括 `INTEGER`/`INT`、`TINYINT`、`SMALLINT`、`MEDIUMINT` 以及 `BIGINT`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/8.0/en/integer-types.html)文档。 +TiDB 支持所有 MySQL 整数类型,包括 `INTEGER`/`INT`、`TINYINT`、`SMALLINT`、`MEDIUMINT` 和 `BIGINT`。更多信息,请参见 [MySQL 中的整数数据类型语法](https://dev.mysql.com/doc/refman/8.0/en/integer-types.html)。 -字段说明: +下表总结了字段描述: -| 语法元素 | 说明 | -| ---- | --------| -| M | 类型显示宽度,可选 | -| UNSIGNED | 无符号数,如果不加这个标识,则为有符号数 | -| ZEROFILL | 补零标识,如果有这个标识,TiDB 会自动给类型增加 UNSIGNED 标识,但是没有做补零的操作 | +| 语法元素 | 描述 | +| -------- | ------------------------------- | +| M | 类型的显示宽度。可选。 | +| UNSIGNED | 无符号。如果省略,则为有符号。 | +| ZEROFILL | 如果为数值列指定 ZEROFILL,TiDB 会自动为该列添加 UNSIGNED 属性。 | -### 类型定义 +下表总结了 TiDB 支持的整数类型所需的存储空间和范围: -#### `BIT` 类型 +| 数据类型 | 存储空间(字节) | 最小值(有符号/无符号) | 最大值(有符号/无符号) | +| ------- | -------- | ----------- | ------------ | +| `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 | -比特值类型。M 表示比特位的长度,取值范围从 1 到 64,其默认值是 1。 +### `BIT` 类型 -{{< copyable "sql" >}} +BIT 数据类型。BIT(M) 类型允许存储 M 位值。M 的范围是 1 到 64,默认值是 1: ```sql BIT[(M)] ``` -#### `BOOLEAN` 类型 - -布尔类型,别名为 `BOOL`,和 `TINYINT(1)` 等价。零值被认为是 `False`,非零值认为是 `True`。在 TiDB 内部,`True` 存储为 `1`,`False` 存储为 `0`。 +### `BOOLEAN` 类型 -{{< copyable "sql" >}} +`BOOLEAN` 类型及其别名 `BOOL` 等同于 `TINYINT(1)`。如果值为 `0`,则被视为 `False`;否则被视为 `True`。与 MySQL 一样,`True` 是 `1`,`False` 是 `0`: ```sql BOOLEAN ``` -#### `TINYINT` 类型 - -`TINYINT` 类型。有符号数的范围是 `[-128, 127]`。无符号数的范围是 `[0, 255]`。 +### `TINYINT` 类型 -{{< copyable "sql" >}} +`TINYINT` 数据类型存储有符号值范围 [-128, 127] 和无符号值范围 [0, 255]: ```sql TINYINT[(M)] [UNSIGNED] [ZEROFILL] ``` -#### `SMALLINT` 类型 +### `SMALLINT` 类型 -`SMALLINT` 类型。有符号数的范围是 `[-32768, 32767]`。无符号数的范围是 `[0, 65535]`。 - -{{< copyable "sql" >}} +`SMALLINT` 数据类型存储有符号值范围 [-32768, 32767] 和无符号值范围 [0, 65535]: ```sql SMALLINT[(M)] [UNSIGNED] [ZEROFILL] ``` -#### `MEDIUMINT` 类型 - -`MEDIUMINT` 类型。有符号数的范围是 `[-8388608, 8388607]`。无符号数的范围是 `[0, 16777215]`。 +### `MEDIUMINT` 类型 -{{< copyable "sql" >}} +`MEDIUMINT` 数据类型存储有符号值范围 [-8388608, 8388607] 和无符号值范围 [0, 16777215]: ```sql MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] @@ -77,17 +75,13 @@ MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] ### `INTEGER` 类型 -`INTEGER` 类型,别名 `INT`。有符号数的范围是 `[-2147483648, 2147483647]`。无符号数的范围是 `[0, 4294967295]`。 - -{{< copyable "sql" >}} +`INTEGER` 类型及其别名 `INT` 存储有符号值范围 [-2147483648, 2147483647] 和无符号值范围 [0, 4294967295]: ```sql INT[(M)] [UNSIGNED] [ZEROFILL] ``` -或者: - -{{< copyable "sql" >}} +你也可以使用另一种形式: ```sql INTEGER[(M)] [UNSIGNED] [ZEROFILL] @@ -95,48 +89,38 @@ INTEGER[(M)] [UNSIGNED] [ZEROFILL] ### `BIGINT` 类型 -`BIGINT` 类型。有符号数的范围是 `[-9223372036854775808, 9223372036854775807]`。无符号数的范围是 `[0, 18446744073709551615]`。 - -{{< copyable "sql" >}} +`BIGINT` 数据类型存储有符号值范围 [-9223372036854775808, 9223372036854775807] 和无符号值范围 [0, 18446744073709551615]: ```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`。更多信息,请参见 [MySQL 中的浮点数类型(近似值)- FLOAT, DOUBLE](https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)。 -TiDB 支持 MySQL 所有的浮点类型,包括 `FLOAT`、`DOUBLE`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)文档。 +下表总结了字段描述: -字段说明: - -| 语法元素 | 说明 | +| 语法元素 | 描述 | | -------- | ------------------------------- | -| M | 小数总位数 | -| D | 小数点后位数 | -| UNSIGNED | 无符号数,如果不加这个标识,则为有符号数 | -| ZEROFILL | 补零标识,如果有这个标识,TiDB 会自动给类型增加 UNSIGNED 标识 | +| M | 总位数 | +| D | 小数点后的位数 | +| UNSIGNED | 无符号。如果省略,则为有符号。 | +| ZEROFILL | 如果为数值列指定 ZEROFILL,TiDB 会自动为该列添加 UNSIGNED 属性。 | -### 类型定义 +下表总结了 TiDB 支持的浮点数类��所需的存储空间: -#### `FLOAT` 类型 +| 数据类型 | 存储空间(字节)| +| ----------- |----------| +| `FLOAT` | 4 | +| `FLOAT(p)` | 如果 0 <= p <= 24,则为 4;如果 25 <= p <= 53,则为 8| +| `DOUBLE` | 8 | -单精度浮点数。允许的值范围为 -2^128 ~ +2^128,也即 -3.402823466E+38 到 -1.175494351E-38、0 和 1.175494351E-38 到 3.402823466E+38。这些是基于 IEEE 标准的理论限制。实际的范围根据硬件或操作系统的不同可能稍微小些。 +### `FLOAT` 类型 -`FLOAT(p)` 类型中,`p` 表示精度(以位数表示)。只使用该值来确定是否结果列的数据类型为 `FLOAT` 或 `DOUBLE`。如果 `p` 为从 0 到 24,数据类型变为没有 M 或 D 值的 `FLOAT`。如果 `p` 为从 25 到 53,数据类型变为没有 M 或 D 值的 `DOUBLE`。结果列范围与本节前面描述的单精度 `FLOAT` 或双精度 `DOUBLE` 数据类型相同。 +`FLOAT` 类型存储单精度浮点数。允许的值范围是 -3.402823466E+38 到 -1.175494351E-38、0 以及 1.175494351E-38 到 3.402823466E+38。这些是基于 IEEE 标准的理论限制。实际范围可能因硬件或操作系统而略有不同。 -{{< copyable "sql" >}} +`FLOAT(p)` 可用于表示所需的以位为单位的精度。TiDB 仅使用此值来确定是否使用 `FLOAT` 或 `DOUBLE` 作为结果数据类型。如果 p 是 0 到 24,数据类型变为不带 M 或 D 值的 FLOAT。如果 p 是 25 到 53,数据类型变为不带 M 或 D 值的 `DOUBLE`。结果列的范围与单精度 `FLOAT` 或双精度 `DOUBLE` 数据类型相同。 ```sql FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] @@ -145,14 +129,13 @@ FLOAT(p) [UNSIGNED] [ZEROFILL] > **注意:** > -> + 与在 MySQL 中一样,`FLOAT` 数据类型用于存储近似值。对于类似货币的精确值,建议使用 `DECIMAL` 类型。 -> + 在 TiDB 中,`FLOAT` 数据类型默认的精度是 8 位,这与 MySQL 不同。在 MySQL 中,`FLOAT` 数据类型默认的精度是 6 位。例如,同时往 MySQL 和 TiDB 中类型为 `FLOAT` 的列中插入数据 `123456789` 和 `1.23456789`。在 MySQL 中查询对应的值,将会得到结果 `123457000` 和 `1.23457`。而在 TiDB 中查询对应的值,将会得到 `123456790` 和 `1.2345679`。 - -#### `DOUBLE` 类型 +> 与 MySQL 一样,`FLOAT` 数据类型存储近似值。对于货币等值,建议使用 `DECIMAL` 类型代替。 +> +> 在 TiDB 中,`FLOAT` 数据类型的默认精度是 8 位,但在 MySQL 中,默认精度是 6 位。例如,假设你在 TiDB 和 MySQL 中都向 `FLOAT` 类型的列插入 `123456789` 和 `1.23456789`,当你在 MySQL 中查询相应的值时,得到的是 `123457000` 和 `1.23457`,而在 TiDB 中,得到的是 `123456790` 和 `1.2345679`。 -双精度浮点数,别名为 `DOUBLE PRECISION`。允许的值范围为:-2^1024 ~ +2^1024,也即是 -1.7976931348623157E+308 到 -2.2250738585072014E-308、0 和 2.2250738585072014E-308 到 1.7976931348623157E+308。这些是基于 IEEE 标准的理论限制。实际的范围根据硬件或操作系统的不同可能稍微小些。 +### `DOUBLE` 类型 -{{< copyable "sql" >}} +`DOUBLE` 类型及其别名 `DOUBLE PRECISION` 存储双精度浮点数。允许的值范围是 -1.7976931348623157E+308 到 -2.2250738585072014E-308、0 以及 2.2250738585072014E-308 到 1.7976931348623157E+308。这些是基于 IEEE 标准的理论限制。实际范围可能因硬件或操作系统而略有不同。 ```sql DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] @@ -161,42 +144,28 @@ DOUBLE PRECISION [(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL > **警告:** > -> 与在 MySQL 中一样,`DOUBLE` 数据类型存储近似值。对于货币之类的精确值,建议使用 `DECIMAL` 类型。 +> 与 MySQL 一样,`DOUBLE` 数据类型存储近似值。对于货币等值,建议使用 `DECIMAL` 类型代替。 > **注意:** > -> 当 TiDB 将用科学计数法表示的双精度浮点数转换到 `CHAR` 类型时,其结果在显示上与 MySQL 不一致,详情参见 [Cast 函数和操作符](/functions-and-operators/cast-functions-and-operators.md)。 - -### 存储空间 +> 当 TiDB 将以科学计数法表示的双精度浮点数转换为 `CHAR` 类型时,显示结果与 MySQL 不一致。详情请参见[类型转换函数和运算符](/functions-and-operators/cast-functions-and-operators.md)。 -每种类型对存储空间的需求如下表所示: +## 定点数类型 -| 类型 | 存储空间 | -| ----------- |----------| -| `FLOAT` | 4 | -| `FLOAT(p)` | 如果 0 <= p <= 24 为 4 个字节,如果 25 <= p <= 53 为 8 个字节| -| `DOUBLE` | 8 | - -## 定点类型 - -TiDB 支持 MySQL 所有的定点类型,包括 `DECIMAL`、`NUMERIC`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html)文档。 +TiDB 支持所有 MySQL 定点数类型,包括 DECIMAL 和 NUMERIC。更多信息,请参见 [MySQL 中的定点数类型(精确值)- DECIMAL, NUMERIC](https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html)。 -字段说明: +字段含义: -| 语法元素 | 说明 | +| 语法元素 | 描述 | | -------- | ------------------------------- | -| M | 小数总位数 | -| D | 小数点后位数 | -| UNSIGNED | 无符号数,如果不加这个标识,则为有符号数 | -| ZEROFILL | 补零标识,如果有这个标识,TiDB 会自动给类型增加 UNSIGNED 标识 | - -### 类型定义 - -#### `DECIMAL` 类型 +| M | 十进制数字的总数(精度) | +| D | 小数点后的位数(标度) | +| UNSIGNED | 无符号。如果省略,则为有符号。 | +| ZEROFILL | 如果为数值列指定 ZEROFILL,TiDB 会自动为该列添加 UNSIGNED 属性。 | -定点数,别名为 `NUMERIC`。M 是小数位数(精度)的总数,D 是小数点(标度)后面的位数。小数点和 `-`(负数)符号不包括在 M 中。如果 D 是 0,则值没有小数点或分数部分。如果 D 被省略,默认是 0。如果 M 被省略,默认是 10。 +### `DECIMAL` 类型 -{{< copyable "sql" >}} +`DECIMAL` 及其别名 `NUMERIC` 存储一个压缩的"精确"定点数。M 是十进制数字的总数(精度),D 是小数点后的位数(标度)。小数点和(对于负数)负号不计入 M。如果 D 为 0,则值没有小数点或小数部分。DECIMAL 的最大位数 (M) 是 65。支持的最大小数位数 (D) 是 30。如果省略 D,默认值为 0。如果省略 M,默认值为 10。 ```sql DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL] diff --git a/data-type-overview.md b/data-type-overview.md index 9996b56391df..273a3da3d2d4 100644 --- a/data-type-overview.md +++ b/data-type-overview.md @@ -1,15 +1,15 @@ --- -title: 数据类型概述 -summary: TiDB 支持除了空间类型(SPATIAL)之外的所有 MySQL 数据类型,包括数值型类型、字符串类型、时间和日期类型、JSON 类型。数据类型定义一般为 T(M[, D]),其中 T 表示具体的类型,M 在整数类型中表示最大显示长度,在浮点数或者定点数中表示精度,在字符类型中表示最大长度,D 表示浮点数、定点数的小数位长度,fsp 在时间和日期类型里的 TIME、DATETIME 以及 TIMESTAMP 中表示秒的精度,其取值范围是 0 到 6,值为 0 表示没有小数部分,如果省略,则默认精度为 0。 +title: 数据类型 +summary: 了解 TiDB 支持的数据类型。 --- -# 数据类型概述 +# 数据类型 -TiDB 支持除空间类型 (`SPATIAL`) 之外的所有 MySQL 数据类型,包括[数值型类型](/data-type-numeric.md)、[字符串类型](/data-type-string.md)、[时间和日期类型](/data-type-date-and-time.md)、[JSON 类型](/data-type-json.md)。 +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[, D])` 格式指定。其中: -* `T` 表示具体的类型。 -* `M` 在整数类型中表示最大显示长度;在浮点数或者定点数中表示精度;在字符类型中表示最大长度。`M` 的最大值取决于具体的类型。 -* `D` 表示浮点数、定点数的小数位长度。 -* `fsp` 在时间和日期类型里的 `TIME`、`DATETIME` 以及 `TIMESTAMP` 中表示秒的精度,其取值范围是 0 到 6。值为 0 表示没有小数部分。如果省略,则默认精度为 0。 +- `T` 表示具体的数据类型。 +- `M` 表示整数类型的最大显示宽度。对于浮点数和定点数类型,`M` 是可以存储的总位数(精度)。对于字符串类型,`M` 是最大长度。`M` 的最大允许值取决于数据类型。 +- `D` 适用于浮点数和定点数类型,表示小数点后的位数(标度)。 +- `fsp` 适用于 `TIME`、`DATETIME` 和 `TIMESTAMP` 类型,表示小数秒的精度。如果指定了 `fsp` 值,必须在 0 到 6 的范围内。值为 0 表示没有小数部分。如果省略,默认精度为 0。 diff --git a/data-type-string.md b/data-type-string.md index 6895af7a2ed1..b2941bf2d0e6 100644 --- a/data-type-string.md +++ b/data-type-string.md @@ -1,19 +1,17 @@ --- title: 字符串类型 -summary: TiDB 支持 MySQL 所有字符串类型,包括 CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM 和 SET。CHAR 是定长字符串,长度固定为创建表时声明的长度。VARCHAR 是变长字符串,空间占用大小不得超过 65535 字节。TEXT 是文本串,最大列长为 65535 字节。TINYTEXT 最大列长度为 255。MEDIUMTEXT 最大列长度为 16777215。LONGTEXT 最大列长度为 4294967295。BINARY 存储二进制字符串。VARBINARY 存储二进制字符串。BLOB 是二进制大文件,最大列长度为 65535 字节。TINYBLOB 最大列长度为 255。MEDIUMBLOB 最大列长度为 16777215。LONGBLOB 最大列长度为 4294967295。ENUM 是枚举类型,值必须从固定集合中选取。SET 是集合类型,包含零个或多个值的字符串。 +summary: 了解 TiDB 支持的字符串类型。 --- # 字符串类型 -TiDB 支持 MySQL 所有的字符串类型,包括 `CHAR`、`VARCHAR`、`BINARY`、`VARBINARY`、`BLOB`、`TEXT`、`ENUM` 以及 `SET`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/8.0/en/string-types.html)文档。 +TiDB 支持所有 MySQL 字符串类型,包括 `CHAR`、`VARCHAR`、`BINARY`、`VARBINARY`、`BLOB`、`TEXT`、`ENUM` 和 `SET`。更多信息,请参见 [MySQL 中的字符串类型](https://dev.mysql.com/doc/refman/8.0/en/string-types.html)。 -## 类型定义 +## 支持的类型 ### `CHAR` 类型 -定长字符串。`CHAR` 列的长度固定为创建表时声明的长度。M 表示列长度(字符的个数,不是字节的个数)。长度可以为从 0 到 255 的任何值。和 `VARCHAR` 类型不同,`CHAR` 列在写入时会对数据末尾的空格进行截断。 - -{{< copyable "sql" >}} +`CHAR` 是固定长度的字符串。M 表示列长度(以字符为单位,而不是字节)。M 的范围是 0 到 255。与 `VARCHAR` 类型不同,当数据插入到 `CHAR` 列时,尾部的空格会被截断。 ```sql [NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE collation_name] @@ -21,11 +19,11 @@ TiDB 支持 MySQL 所有的字符串类型,包括 `CHAR`、`VARCHAR`、`BINARY ### `VARCHAR` 类型 -变长字符串。M 表示最大列长度(字符的最大个数)。`VARCHAR` 的空间占用大小不得超过 65535 字节。在选择 `VARCHAR` 长度时,应当根据最长的行的大小和使用的字符集确定。 +`VARCHAR` 是可变长度的字符串。M 表示最大列长度(以字符为单位,而不是字节)。`VARCHAR` 的最大大小不能超过 65,535 字节。最大行长度和使用的字符集决定了 `VARCHAR` 的长度。 -对于不同的字符集,单个字符所占用的空间可能有所不同。以下表格是各个字符集下单个字符占用的字节数,以及 `VARCHAR` 列长度的取值范围: +不同字符集中单个字符占用的空间可能不同。下表显示了每个字符集中单个字符消耗的字节数,以及 `VARCHAR` 列长度的范围: -| 字符集 | 单个字符字节数 | VARCHAR 最大列长度的取值范围 | +| 字符集 | 每个字符的字节数 | 最大 `VARCHAR` 列长度的范围 | | ----- | ---- | ---- | | ascii | 1 | (0, 65535] | | latin1 | 1 | (0, 65535] | @@ -33,17 +31,13 @@ TiDB 支持 MySQL 所有的字符串类型,包括 `CHAR`、`VARCHAR`、`BINARY | utf8 | 3 | (0, 21845] | | utf8mb4 | 4 | (0, 16383] | -{{< copyable "sql" >}} - ```sql [NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name] ``` ### `TEXT` 类型 -文本串。最大列长为 65,535 字节。可选的 M 参数以字符为单位,用于自动选择 `TEXT` 列的最合适类型。例如 `TEXT(60)` 会产生一个 `TINYTEXT` 数据类型,最多可容纳 255 字节,即容纳一个 60 字符的 UTF-8 字符串,每个字符最多包含 4 字节(即 4×60=240)。不推荐使用 M 参数。 - -{{< copyable "sql" >}} +`TEXT` 是可变长度的字符串。最大列长度为 65,535 字节。可选参数 M 以字符为单位,用于自动选择最适合的 `TEXT` 列类型。例如,`TEXT(60)` 将生成一个 `TINYTEXT` 数据类型,可以存储最多 255 字节,这足以容纳一个最多有 60 个字符的 UTF-8 字符串(每个字符最多 4 字节,4×60=240)。不建议使用 M 参数。 ```sql TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name] @@ -51,9 +45,7 @@ TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name] ### `TINYTEXT` 类型 -类似于 [`TEXT`](#text-类型),区别在于最大列长度为 255。 - -{{< copyable "sql" >}} +`TINYTEXT` 类型与 [`TEXT` 类型](#text-类型)类似。区别在于 `TINYTEXT` 的最大列长度为 255。 ```sql TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name] @@ -61,9 +53,16 @@ TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name] ### `MEDIUMTEXT` 类型 -类似于 [`TEXT`](#text-类型),区别在于最大列长度为 16,777,215。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v4010-和-v500-版本开始引入) 的限制,TiDB 中默认单行存储最大不超过 6 MiB,可通过配置项将该限制调整至 120 MiB。 + -{{< copyable "sql" >}} +`MEDIUMTEXT` 类型与 [`TEXT` 类型](#text-类型)类似。区别在于 `MEDIUMTEXT` 的最大列长度为 16,777,215。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 + + + + +`MEDIUMTEXT` 类型与 [`TEXT` 类型](#text-类型)类似。区别在于 `MEDIUMTEXT` 的最大列长度为 16,777,215。但由于 [`txn-entry-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 + + ```sql MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name] @@ -71,9 +70,16 @@ MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name] ### `LONGTEXT` 类型 -类似于 [`TEXT`](#text-类型),区别在于最大列长度为 4,294,967,295。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v4010-和-v500-版本开始引入) 的限制,TiDB 中默认单行存储最大不超过 6 MiB,可通过配置项将该限制调整至 120 MiB。 + + +`LONGTEXT` 类型与 [`TEXT` 类型](#text-类型)类似。区别在于 `LONGTEXT` 的最大列长度为 4,294,967,295。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 -{{< copyable "sql" >}} + + + +`LONGTEXT` 类型与 [`TEXT` 类型](#text-类型)类似。区别在于 `LONGTEXT` 的最大列长度为 4,294,967,295。但由于 [`txn-entry-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 + + ```sql LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name] @@ -81,9 +87,7 @@ LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name] ### `BINARY` 类型 -类似于 [`CHAR`](#char-类型),区别在于 `BINARY` 存储的是二进制字符串。 - -{{< copyable "sql" >}} +`BINARY` 类型与 [`CHAR` 类型](#char-类型)类似。区别在于 `BINARY` 存储二进制字节字符串。 ```sql BINARY(M) @@ -91,9 +95,7 @@ BINARY(M) ### `VARBINARY` 类型 -类似于 [`VARCHAR`](#varchar-类型),区别在于 `VARBINARY` 存储的是二进制字符串。 - -{{< copyable "sql" >}} +`VARBINARY` 类型与 [`VARCHAR` 类型](#varchar-类型)类似。区别在于 `VARBINARY` 存储二进制字节字符串。 ```sql VARBINARY(M) @@ -101,9 +103,7 @@ VARBINARY(M) ### `BLOB` 类型 -二进制大文件。M 表示最大列长度,单位是字节,范围是 0 到 65535。 - -{{< copyable "sql" >}} +`BLOB` 是大型二进制文件。M 表示最大列长度(以字节为单位),范围从 0 到 65,535。 ```sql BLOB[(M)] @@ -111,9 +111,7 @@ BLOB[(M)] ### `TINYBLOB` 类型 -类似于 [`BLOB`](#blob-类型),区别在于最大列长度为 255。 - -{{< copyable "sql" >}} +`TINYBLOB` 类型与 [`BLOB` 类型](#blob-类型)类似。区别在于 `TINYBLOB` 的最大列长度为 255。 ```sql TINYBLOB @@ -121,9 +119,16 @@ TINYBLOB ### `MEDIUMBLOB` 类型 -类似于 [`BLOB`](#blob-类型),区别在于最大列长度为 16,777,215。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v4010-和-v500-版本开始引入) 的限制,TiDB 中默认单行存储最大不超过 6 MiB,可通过配置项将该限制调整至 120 MiB。 + + +`MEDIUMBLOB` 类型与 [`BLOB` 类型](#blob-类型)类似。区别在于 `MEDIUMBLOB` 的最大列长度为 16,777,215。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 -{{< copyable "sql" >}} + + + +`MEDIUMBLOB` 类型与 [`BLOB` 类型](#blob-类型)类似。区别在于 `MEDIUMBLOB` 的最大列长度为 16,777,215。但由于 [`txn-entry-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 + + ```sql MEDIUMBLOB @@ -131,9 +136,16 @@ MEDIUMBLOB ### `LONGBLOB` 类型 -类似于 [`BLOB`](#blob-类型),区别在于最大列长度为 4,294,967,295。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v4010-和-v500-版本开始引入) 的限制,TiDB 中默认单行存储最大不超过 6 MiB,可通过配置项将该限制调整至 120 MiB。 + + +`LONGBLOB` 类型与 [`BLOB` 类型](#blob-类型)类似。区别在于 `LONGBLOB` 的最大列长度为 4,294,967,295。但由于 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 + + + -{{< copyable "sql" >}} +`LONGBLOB` 类型与 [`BLOB` 类型](#blob-类型)类似。区别在于 `LONGBLOB` 的最大列长度为 4,294,967,295。但由于 [`txn-entry-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-entry-size-limit-new-in-v4010-and-v500) 的限制,TiDB 中单行的最大存储大小默认为 6 MiB,可以通过更改配置增加到 120 MiB。 + + ```sql LONGBLOB @@ -141,53 +153,39 @@ LONGBLOB ### `ENUM` 类型 -枚举类型是一个字符串,它只能有一个值的字符串对象。其值必须是从一个固定集合中选取,这个固定集合在创建表的时候定义,语法是: - -{{< copyable "sql" >}} +`ENUM` 是一个字符串对象,其值必须是在创建表时在列规格中明确枚举的允许值列表中选择的。语法为: ```sql ENUM('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name] -``` - -例如: -{{< copyable "sql" >}} - -```sql +# 例如: ENUM('apple', 'orange', 'pear') ``` -枚举类型的值在 TiDB 内部使用数值来存储,每个值会按照定义的顺序转换为一个数字,比如上面的例子中,每个字符串值都会映射为一个数字: +`ENUM` 数据类型的值以数字形式存储。每个值根据定义顺序转换为数字。在前面的示例中,每个字符串映射到一个数字: | 值 | 数字 | | ---- | ---- | -| NULL | NULL | +| NULL | NULL | | '' | 0 | | 'apple' | 1 | | 'orange' | 2 | | 'pear' | 3 | -更多信息参考 [MySQL 枚举文档](https://dev.mysql.com/doc/refman/8.0/en/enum.html)。 +更多信息,请参见 [MySQL 中的 ENUM 类型](https://dev.mysql.com/doc/refman/8.0/en/enum.html)。 ### `SET` 类型 -集合类型是一个包含零个或多个值的字符串,其中每个值必须是从一个固定集合中选取,这个固定集合在创建表的时候定义,语法是: - -{{< copyable "sql" >}} +`SET` 是一个字符串对象,可以有零个或多个值,每个值都必须从创建表时指定的允许值列表中选择。语法为: ```sql SET('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name] -``` -例如: - -{{< copyable "sql" >}} - -```sql +# 例如: SET('1', '2') NOT NULL ``` -上面的例子中,这列的有效值可以是: +在示例中,以下任何值都可以是有效的: ``` '' @@ -196,15 +194,15 @@ SET('1', '2') NOT NULL '1,2' ``` -集合类型的值在 TiDB 内部会转换为一个 Int64 数值,每个元素是否存在用一个二进制位的 0/1 值来表示,比如这个例子 `SET('a','b','c','d')`,每一个元素都被映射为一个数字,且每个数字的二进制表示只会有一位是 1: +在 TiDB 中,`SET` 类型的值在内部转换为 `Int64`。每个元素的存在使用二进制表示:0 或 1。对于指定为 `SET('a','b','c','d')` 的列,成员具有以下十进制和二进制值。 -| 成员 | 十进制表示 | 二进制表示 | +| 成员 | 十进制值 | 二进制值 | | ---- | ---- | ------ | -| 'a' | 1 | 0001 | +| 'a' | 1 | 0001 | | 'b' | 2 | 0010 | | 'c' | 4 | 0100 | | 'd' | 8 | 1000 | -这样对于值为 `('a', 'c')` 的元素,其二进制表示即为 0101。 +在这种情况下,对于元素 `('a', 'c')`,它在二进制中是 `0101`。 -更多信息参考 [MySQL 集合文档](https://dev.mysql.com/doc/refman/8.0/en/set.html)。 +更多信息,请参见 [MySQL 中的 SET 类型](https://dev.mysql.com/doc/refman/8.0/en/set.html)。 diff --git a/ddl-introduction.md b/ddl-introduction.md index 32d810258406..85dfb0c16ca5 100644 --- a/ddl-introduction.md +++ b/ddl-introduction.md @@ -1,51 +1,51 @@ --- -title: DDL 语句的执行原理及最佳实践 -summary: 介绍 TiDB 中 DDL 语句的实现原理、在线变更过程、最佳实践等内容。 +title: DDL 语句的执行原理和最佳实践 +summary: 了解 TiDB 中 DDL 语句的实现原理、在线变更过程和最佳实践。 --- -# DDL 语句的执行原理及最佳实践 +# DDL 语句的执行原理和最佳实践 -本文介绍了 TiDB 中 DDL 语句的执行原理(包括 DDL Owner 模块和在线变更 DDL 的流程)和最佳实践。 +本文介绍了 TiDB 中与 DDL 语句相关的执行原理和最佳实践。这些原理包括 DDL Owner 模块和在线 DDL 变更过程。 ## DDL 执行原理 -TiDB 采用在线异步变更的方式执行 DDL 语句,从而实现 DDL 语句的执行不会阻塞其他会话中的 DML 语句。因此,在业务执行过程中,你可以通过在线异步变更 DDL 对数据库对象定义进行变更。 +TiDB 使用在线和异步的方式来执行 DDL 语句。这意味着在执行 DDL 语句时,不会阻塞其他会话中的 DML 语句。换句话说,你可以在应用程序运行时使用在线和异步的 DDL 语句来更改数据库对象的定义。 -### DDL 语句类型简介 +### DDL 语句类型 -按照执行期间是否阻塞用户业务,DDL 语句可以划分为: +根据 DDL 语句在执行过程中是否阻塞用户应用,DDL 语句可以分为以下类型: -- **离线 DDL 语句**:即数据库接收到用户的 DDL 语句后,会先对要修改的数据库对象进行加锁,再执行元数据变更,在 DDL 执行过程中将阻塞用户业务对数据的修改。 +- **离线 DDL 语句**:当数据库收到用户的 DDL 语句时,首先锁定要修改的数据库对象,然后更改元数据。在 DDL 执行期间,数据库会阻止用户应用修改数据。 -- **在线 DDL 语句**:即数据库在执行 DDL 语句时,通过一定的方法,使得 DDL 执行不阻塞用户业务,且能够保证用户业务可在 DDL 执行期间提交修改,在执行过程中保证对应对象的数据正确性与一致性。 +- **在线 DDL 语句**:当在数据库中执行 DDL 语句时,使用特定方法确保语句不会阻塞用户应用。这允许用户在 DDL 执行期间提交修改。该方法还确保在执行过程中相应数据库对象的正确性和一致性。 -按照是否需要操作 DDL 目标对象所包括的数据来划分,DDL 语句可以划分为: +根据是否操作目标 DDL 对象中包含的数据,DDL 语句可以分为以下类型: -- **逻辑 DDL 语句**:通常只修改数据库对象的元数据,不对变更对象存储的数据进行处理,例如变更表名或变更列名。 +- **逻辑 DDL 语句**:逻辑 DDL 语句通常只修改数据库对象的元数据,而不处理存储在对象中的数据,例如更改表名或更改列名。 - 在 TiDB 中,逻辑 DDL 语句又被称为 General DDL。General DDL 的执行时间通常较短,只需要几十毫秒或者几秒。执行这类 DDL 语句几乎不消耗系统资源,因此不会影响业务负载。 + 在 TiDB 中,逻辑 DDL 语句也称为"一般 DDL"。这些语句通常执行时间较短,通常只需要几十毫秒或几秒钟就能完成。因此,它们不会消耗太多系统资源,也不会影响应用程序的工作负载。 -- **物理 DDL 语句**:不但会修改变更对象的元数据,同时也修改变更对象所存储的用户数据。例如,为表创建索引,不仅需要变更表的定义,同时也需要做一次全表扫描以构建新增加的索引。 +- **物理 DDL 语句**:物理 DDL 语句不仅修改要更改对象的元数据,还修改存储在对象中的用户数据。例如,当 TiDB 为表创建索引时,它不仅更改表的定义,还执行全表扫描以构建新添加的索引。 - 在 TiDB 中,物理 DDL 被称为 Reorg DDL(Reorg 即 Reorganization)。目前物理 DDL 只包含 `ADD INDEX` 以及有损列类型变更(例如从 `INT` 转成 `CHAR` 类型)这两种类型。物理 DDL 的特点是执行时间较长,且执行时间与表的数据量、机器配置以及业务负载有关。 + 在 TiDB 中,物理 DDL 语句也称为"reorg DDL",即重组。目前,物理 DDL 语句仅包括 `ADD INDEX` 和有损列类型更改(例如从 `INT` 类型更改为 `CHAR` 类型)。这些语句执行时间较长,执行时间受表中数据量、机器配置和应用程序工作负载的影响。 - 执行物理 DDL 会影响业务负载,具体有两个方面。一方面需要从 TiKV 中读取数据并写入新数据,因此会消耗 TiKV 的 CPU 及 I/O 资源。另一方面,**DDL Owner 所在的 TiDB 节点**或者**被 TiDB 分布式执行框架调度而执行 `ADD INDEX` 任务的 TiDB 节点**需要进行相应的计算,因此会消耗 TiDB 的 CPU 资源。 + 执行物理 DDL 语句可能会影响应用程序的工作负载,原因有两个。一方面,它消耗 TiKV 的 CPU 和 I/O 资源来读取数据和写入新数据。另一方面,**作为 DDL Owner 的 TiDB 节点**或**那些被 TiDB 分布式执行框架(DXF)调度执行 `ADD INDEX` 任务的 TiDB 节点**消耗 TiDB 的 CPU 资源来执行相应的计算。 > **注意:** > - > DDL 语句对用户业务的影响通常都是由于执行物理 DDL 任务造成的。因此要优化 DDL 语句对于用户业务的影响,重点在于对物理 DDL 任务执行期间的设计,降低对于用户业务的影响。 + > 物理 DDL 任务的执行通常会对用户应用造成最大影响。因此,为了最小化这种影响,关键点是在执行期间优化物理 DDL 语句的设计。这有助于减少对用户应用的影响。 ### TiDB DDL 模块 -TiDB DDL 模块引入 DDL Owner(简称 Owner)角色来代理执行所有进入到 TiDB 集群中的 DDL 语句。对于当前 TiDB DDL 模块的实现,在同一时间,整个 TiDB 集群中只有一个 TiDB 节点能当选为 Owner。当选 Owner 后,TiDB 节点中启动的 worker 才能处理集群中的 DDL 任务。 +TiDB DDL 模块引入了 DDL Owner(或 Owner)的角色,它作为在 TiDB 集群内执行所有 DDL 语句的代理。在当前实现中,整个集群中任何时候只能有一个 TiDB 节点被选举为 Owner。一旦一个 TiDB 节点被选举为 Owner,该 TiDB 节点中启动的 worker 就可以处理集群中的 DDL 任务。 -TiDB 通过 etcd 的选举功能从多个 TiDB 节点中选举出一个节点来担任 Owner 的宿主节点。默认情况下,每个 TiDB 节点都可能当选 Owner(你可以通过配置 `run-ddl` 控制某个 TiDB 节点是否竞选 Owner)。Owner 节点是有任期的,并会主动维护自己的任期,即续约。当 Owner 节点宕机后,其他节点可以通过 etcd 感知到并重新选举出新的 Owner,在集群中继续担任 DDL 任务执行者的角色。 +TiDB 使用 etcd 的选举机制从多个 TiDB 节点中选举一个节点来承载 Owner。默认情况下,每个 TiDB 节点都可能被选举为 Owner(你可以配置 `run-ddl` 来管理节点参与选举)。被选举的 Owner 节点有一个任期,它通过续期来主动维护任期。当 Owner 节点宕机时,另一个节点可以通过 etcd 被选举为新的 Owner,并继续执行集群中的 DDL 任务。 DDL Owner 的简单示意图如下: ![DDL Owner](/media/ddl-owner.png) -你可以通过 `ADMIN SHOW DDL` 语句查看当前 DDL owner: +你可以使用 `ADMIN SHOW DDL` 语句查看当前的 DDL owner: ```sql ADMIN SHOW DDL; @@ -60,132 +60,132 @@ ADMIN SHOW DDL; 1 row in set (0.00 sec) ``` -### TiDB 在线 DDL 异步变更的原理 +### TiDB 中在线 DDL 异步变更的工作原理 -TiDB DDL 模块从设计之初就选择了在线异步变更的模式,为 TiDB 的用户提供了不停机变更业务的服务能力。 +从设计之初,TiDB DDL 模块就选择了在线异步变更模式,这让你可以在不停机的情况下修改应用程序。 -DDL 变更即两个状态之间的切换(变更前 -> 变更后)。在线变更 DDL,是在两个状态之间引入多个相互兼容的小版本状态。同时,在同一个 DDL 语句在执行期间,对于同一集群中不同 TiDB 节点,允许不同节点的变更对象小版本存在不同(集群中各 TiDB 节点变更对象的小版本差距不超过两个版本),因为相邻两个小版本之间可以相互兼容。 +DDL 变更涉及从一个状态转换到另一个状态,通常是从"变更前"状态转换到"变更后"状态。通过在线 DDL 变更,这种转换是通过引入多个相互兼容的小版本状态来实现的。在执行 DDL 语句期间,同一集群中的 TiDB 节点允许有不同的小版本变更,只要变更对象的小版本之间的差异不超过两个版本即可。这是可能的,因为相邻的小版本可以相互兼容。 -通过多个小版本演进的方式,确保多个 TiDB 节点能够正确同步元数据,并保证期间执行用户事务更改数据的正确性与一致性。 +通过这种方式,通过多个小版本的演进确保元数据可以在多个 TiDB 节点之间正确同步。这有助于在过程中维护涉及变更数据的用户事务的正确性和一致性。 -以 `ADD INDEX` 为例,整个变更状态流程如下: +以 `ADD INDEX` 为例,整个状态变更过程如下: ``` absent -> delete only -> write only -> write reorg -> public ``` -对于用户来说,新建的索引在 `public` 状态前都不可用。 +对于用户来说,新创建的索引在 `public` 状态之前是不可用的。 -
+
-在 TiDB v6.2 之前,由于 Owner 每次只能执行一个同种类型(逻辑或物理)的 DDL 任务,这个约束较为严格,同时影响用户体验。 +在 TiDB v6.2.0 之前,由于 Owner 一次只能执行一个相同类型(逻辑或物理)的 DDL 任务,这种限制相对严格,影响了用户体验。 -当 DDL 任务之间不存在相关依赖时,并行执行并不会影响数据正确性和一致性。例如:用户 A 在 `T1` 表上增加一个索引,同时用户 B 从 `T2` 表删除一列。这两条 DDL 语句可以并行执行。 +如果 DDL 任务之间没有依赖关系,并行执行不会影响数据的正确性和一致性。例如,用户 A 为 `T1` 表添加索引,而用户 B 从 `T2` 表删除列。这两个 DDL 语句可以并行执行。 -为了提升 DDL 执行的用户体验,从 v6.2.0 起,TiDB 对原有的 DDL Owner 角色进行了升级,使得 Owner 能对 DDL 任务做相关性判断,判断逻辑如下: +为了改善 DDL 执行的用户体验,从 v6.2.0 开始,TiDB 使 Owner 能够确定 DDL 任务的相关性。逻辑如下: -+ 涉及同一张表的 DDL 相互阻塞。 -+ `DROP DATABASE` 和数据库内所有对象的 DDL 互相阻塞。 -+ 涉及不同表的加索引和列类型变更可以并发执行。 -+ 逻辑 DDL 需要等待之前正在执行的逻辑 DDL 执行完才能执行。 -+ 其他情况下 DDL 可以根据 Concurrent DDL 并行度可用情况确定是否可以执行。 ++ 对同一个表执行的 DDL 语句相互阻塞。 ++ `DROP DATABASE` 和影响数据库中所有对象的 DDL 语句相互阻塞。 ++ 在不同表上添加索引和列类型更改可以并发执行。 ++ 逻辑 DDL 语句必须等待前一个逻辑 DDL 语句执行完成后才能执行。 ++ 在其他情况下,DDL 可以根据并发 DDL 执行的可用性级别执行。 -具体来说,TiDB 在 v6.2.0 中对 DDL 执行框架进行了如下升级: +具体来说,TiDB 6.2.0 在以下方面增强了 DDL 执行框架: -+ DDL Owner 能够根据以上判断逻辑并行执行 DDL 任务。 -+ 改善了 DDL Job 队列先入先出的问题。DDL Owner 不再选择当前队列最前面的 DDL Job,而是选择当前可以执行的 DDL Job。 -+ 扩充了处理物理 DDL 的 worker 数量,使得能够并行地添加多个物理 DDL。 ++ DDL Owner 可以根据上述逻辑并行执行 DDL 任务。 ++ 解决了 DDL Job 队列中先进先出的问题。DDL Owner 不再选择队列中的第一个任务,而是选择当前时间可以执行的任务。 ++ 增加了处理物理 DDL 语句的 worker 数量,使多个物理 DDL 语句能够并行执行。 - 因为 TiDB 中所有支持的 DDL 任务都是以在线变更的方式来实现的,TiDB 通过 Owner 即可对新的 DDL Job 进行相关性判断,并根据相关性结果进行 DDL 任务的调度,从而使分布式数据库实现了和传统数据库中 DDL 并发相同的效果。 + 因为 TiDB 中的所有 DDL 任务都是使用在线变更方式实现的,TiDB 可以通过 Owner 确定新 DDL 任务的相关性,并基于这些信息调度 DDL 任务。这种方法使分布式数据库能够实现与传统数据库相同级别的 DDL 并发性。 -并发 DDL 框架的实现进一步加强了 TiDB 中 DDL 语句的执行能力,并更符合商用数据库的使用习惯。 +并发 DDL 框架增强了 TiDB 中 DDL 语句的执行能力,使其更加符合商业数据库的使用模式。
-
+
-在 v6.2.0 之前,TiDB SQL 层中处理异步 Schema 变更的基本流程如下: +在 v6.2.0 之前,TiDB SQL 层处理异步 schema 变更的过程如下: -1. MySQL Client 发送给 TiDB server 一个 DDL 操作请求。 +1. MySQL Client 向 TiDB 服务器发送 DDL 请求。 -2. 某个 TiDB server 收到请求(即 TiDB server 的 MySQL Protocol 层对请求进行解析优化),然后发送到 TiDB SQL 层进行执行。 +2. TiDB 服务器在 MySQL 协议层接收到请求后,对请求进行解析和优化,然后将其发送到 TiDB SQL 层执行。 - TiDB SQL 层接到 DDL 请求后,会启动 `start job` 模块根据请求将请求封装成特定的 DDL Job(即 DDL 任务),然后将此 Job 按语句类型分类,分别存储到 KV 层的对应 DDL Job 队列,并通知自身对应的 worker 有 Job 需要处理。 + 一旦 TiDB 的 SQL 层收到 DDL 请求,它就启动 `start job` 模块将请求封装成特定的 DDL job(即 DDL 任务),然后根据语句类型将这个 job 存储在 KV 层相应的 DDL job 队列中。通知相应的 worker 有需要处理的 job。 -3. 接收到处理 Job 通知的 worker,会判断自身是否处于 DDL Owner 的角色。如果是 Owner 角色则直接处理此 Job。如果没有处于 Owner 角色则退出不做任何处理。 +3. 当收到处理 job 的通知时,worker 确定它是否具有 DDL Owner 角色。如果是,它直接处理 job。否则,它退出而不进行任何处理。 - 假设某台 TiDB server 不是 Owner 角色,那么其他某个节点一定有一个是 Owner。处于 Owner 角色的节点的 worker 通过定期检测机制来检查是否有 Job 可以被执行。如果发现有 Job ,那么 worker 就会处理该 Job。 + 如果一个 TiDB 服务器不是 Owner 角色,那么另一个节点一定是 Owner。Owner 角色节点的 worker 会定期检查是否有可以执行的可用 job。如果发现这样的 job,worker 将处理它。 -4. Worker 处理完 Job 后,会将此 Job 从 KV 层对应的 Job queue 中移除,并放入 `job history queue`。之前封装 Job 的 `start job` 模块会定期在 `job history queue` 中查看是否有已经处理完成的 Job 的 ID。如果有,则这个 Job 对应的整个 DDL 操作结束执行。 +4. worker 处理完 Job 后,将 job 从 KV 层的 job 队列中移除,并将其放入 `job history queue`。封装 job 的 `start job` 模块会定期检查 `job history queue` 中 job 的 ID,看它是否已被处理。如果已处理,则 job 对应的整个 DDL 操作结束。 -5. TiDB server 将 DDL 处理结果返回至 MySQL Client。 +5. TiDB 服务器将 DDL 处理结果返回给 MySQL Client。 -在 TiDB v6.2.0 前,该 DDL 执行框架存在以下限制: +在 TiDB v6.2.0 之前,DDL 执行框架有以下限制: -- TiKV 集群中只有 `general job queue` 和 `add index job queue` 两个队列,分别处理逻辑 DDL 和物理 DDL。 -- DDL Owner 总是以先入先出的方式处理 DDL Job。 -- DDL Owner 每次只能执行一个同种类型(逻辑或物理)的 DDL 任务,这个约束较为严格。 +- TiKV 集群只有两个队列:`general job queue` 和 `add index job queue`,分别处理逻辑 DDL 和物理 DDL。 +- DDL Owner 总是按照先进先出的方式处理 DDL job。 +- DDL Owner 一次只能执行一个相同类型(逻辑或物理)的 DDL 任务,这种限制相对严格,影响了用户体验。 -这些限制可能会导致一些“非预期”的 DDL 阻塞行为。具体可以参考 [SQL FAQ - DDL 执行](/faq/sql-faq.md#ddl-执行)。 +这些限制可能会导致一些"意外"的 DDL 阻塞行为。更多详情,请参见 [SQL FAQ - DDL 执行](https://docs.pingcap.com/tidb/stable/sql-faq#ddl-execution)。
## 最佳实践 -### 通过系统变量来平衡物理 DDL 的执行速度与对业务负载的影响 +### 通过系统变量平衡物理 DDL 执行速度和对应用负载的影响 -执行物理 DDL(包括添加索引或列类型变更)时,适当调整以下系统变量可以平衡 DDL 执行速度与对业务负载的影响: +在执行物理 DDL 语句(包括添加索引或列类型更改)时,你可以调整以下系统变量的值来平衡 DDL 执行速度和对应用负载的影响: -- [`tidb_ddl_reorg_worker_cnt`](/system-variables.md#tidb_ddl_reorg_worker_cnt):这个变量用来设置 DDL 操作 reorg worker 的数量,控制回填的并发度。 +- [`tidb_ddl_reorg_worker_cnt`](/system-variables.md#tidb_ddl_reorg_worker_cnt):此变量设置 DDL 操作的 reorg worker 数量,控制回填的并发度。 -- [`tidb_ddl_reorg_batch_size`](/system-variables.md#tidb_ddl_reorg_batch_size):这个变量用来设置 DDL 操作 `re-organize` 阶段的 batch size,以控制回填的数据量。 +- [`tidb_ddl_reorg_batch_size`](/system-variables.md#tidb_ddl_reorg_batch_size):此变量设置 DDL 操作在 `re-organize` 阶段的批处理大小,控制要回填的数据量。 推荐值: - - 在无其他负载情况下,如需让 `ADD INDEX` 尽快完成,可以将 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 的值适当调大,例如将两个变量值分别调为 `20` 和 `2048`。 - - 在有其他负载情况下,如需让 `ADD INDEX` 尽量不影响其他业务,可以将 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 适当调小,例如将两个变量值分别调为 `4` 和 `256`。 + - 如果没有其他负载,你可以增加 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 的值来加快 `ADD INDEX` 操作。例如,你可以将这两个变量的值分别设置为 `20` 和 `2048`。 + - 如果有其他负载,你可以减小 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 的值以最小化对其他应用的影响。例如,你可以将这些变量的值分别设置为 `4` 和 `256`。 -> **建议:** +> **提示:** > -> - 以上两个变量均可以在 DDL 任务执行过程中动态调整,并且在下一个事务批次中生效。 -> - 根据 DDL 操作的类型,并结合业务负载压力,选择合适的时间点执行,例如建议在业务负载比较低的情况运行 `ADD INDEX` 操作。 -> - 由于添加索引的时间跨度较长,发送相关的指令后,TiDB 会在后台执行任务,TiDB server 宕机不会影响继续执行。 +> - 上述两个变量可以在 DDL 任务执行期间动态调整,并在下一个事务批次中生效。 +> - 根据操作类型和应用负载压力选择适当的时间执行 DDL 操作。例如,建议在应用负载较低时运行 `ADD INDEX` 操作。 +> - 由于添加索引的持续时间相对较长,TiDB 会在发送命令后在后台执行任务。如果 TiDB 服务器宕机,执行不会受到影响。 -### 并发发送 DDL 请求实现快速建大量表 +### 通过并发发送 DDL 请求快速创建多个表 -一个建表的操作耗时大约 50 毫秒。受框架的限制,建表耗时可能更长。 +创建表操作大约需要 50 毫秒。由于框架限制,实际创建表所需的时间可能会更长。 -为了更快地建表,推荐通过并发发送多个 DDL 请求以达到最快建表速度。如果串行地发送 DDL 请求,并且没有发给 Owner 节点,则建表速度会很慢。 +为了更快地创建表,建议并发发送多个 DDL 请求以实现最快的表创建速度。如果你串行发送 DDL 请求且不发送到 Owner 节点,表创建速度会非常慢。 -### 在一条 `ALTER` 语句中进行多次变更 +### 在单个 `ALTER` 语句中进行多个更改 -自 v6.2.0 起,TiDB 支持在一条 `ALTER` 语句中修改一张表的多个模式对象(如列、索引),同时保证整个语句的原子性。因此推荐在一条 `ALTER` 语句中进行多次变更。 +从 v6.2.0 开始,TiDB 支持在单个 `ALTER` 语句中修改表的多个 schema 对象(如列和索引),同时确保整个语句的原子性。因此,建议在单个 `ALTER` 语句中进行多个更改。 ### 检查读写性能 -在添加索引时,回填数据阶段会对集群造成一定的读写压力。在 `ADD INDEX` 的命令发送成功后,并且在 `write reorg` 阶段,建议检查 Grafana 面板上 TiDB 和 TiKV 读写相关的性能指标,以及业务响应时间,来确定 `ADD INDEX` 操作对集群是否造成影响。 +当 TiDB 添加索引时,回填数据的阶段会对集群造成读写压力。在发送 `ADD INDEX` 命令并开始 `write reorg` 阶段后,建议在 Grafana 仪表板上检查 TiDB 和 TiKV 的读写性能指标以及应用程序响应时间,以确定 `ADD INDEX` 操作是否影响集群。 -## DDL 相关的命令介绍 +## DDL 相关命令 -- `ADMIN SHOW DDL`:用于查看 TiDB DDL 的状态,包括当前 schema 版本号、DDL Owner 的 DDL ID 和地址、正在执行的 DDL 任务和 SQL、当前 TiDB 实例的 DDL ID。详情参阅 [`ADMIN SHOW DDL`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl)。 +- `ADMIN SHOW DDL`:用于查看 TiDB DDL 操作的状态,包括当前 schema 版本号、DDL Owner 的 DDL ID 和地址、正在执行的 DDL 任务和 SQL,以及当前 TiDB 实例的 DDL ID。详情请参见 [`ADMIN SHOW DDL`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl)。 -- `ADMIN SHOW DDL JOBS`:查看集群环境中的 DDL 任务运行中详细的状态。详情参阅 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl-jobs)。 +- `ADMIN SHOW DDL JOBS`:用于查看集群环境中运行的 DDL 任务的详细状态。详情请参见 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl-jobs)。 -- `ADMIN SHOW DDL JOB QUERIES job_id [, job_id]`:用于查看 job_id 对应的 DDL 任务的原始 SQL 语句。详情参阅 [`ADMIN SHOW DDL JOB QUERIES`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl-job-queries)。 +- `ADMIN SHOW DDL JOB QUERIES job_id [, job_id]`:用于查看与 `job_id` 对应的 DDL 任务的原始 SQL 语句。详情请参见 [`ADMIN SHOW DDL JOB QUERIES`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl-job-queries)。 -- `ADMIN CANCEL DDL JOBS job_id [, job_id]`:用于取消已经提交但未执行完成的 DDL 任务。取消完成后,执行 DDL 任务的 SQL 语句会返回 `ERROR 8214 (HY000): Cancelled DDL job` 错误。 +- `ADMIN CANCEL DDL JOBS job_id, [, job_id]`:用于取消已提交但未完成的 DDL 任务。取消完成后,执行 DDL 任务的 SQL 语句会返回 `ERROR 8214 (HY000): Cancelled DDL job` 错误。 - 取消一个已经执行完成的 DDL 任务会在 `RESULT` 列看到 `DDL Job:90 not found` 的错误,表示该任务已从 DDL 等待队列中被移除。 + 如果取消已完成的 DDL 任务,你可以在 `RESULT` 列中看到 `DDL Job:90 not found` 错误,这意味着该任务已从 DDL 等待队列中移除。 -- `ADMIN PAUSE DDL JOBS job_id [, job_id]`:用于暂停正在执行的 DDL 任务。执行该命令后,执行 DDL 任务的 SQL 语句体现为正在执行,后台任务暂停执行。详情参阅 [`ADMIN PAUSE DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md)。 +- `ADMIN PAUSE DDL JOBS job_id [, job_id]`:用于暂停正在执行的 DDL 任务。命令执行后,执行 DDL 任务的 SQL 语句显示为正在执行,而后台任务已被暂停。详情请参见 [`ADMIN PAUSE DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md)。 - 只有处于执行中或仍在等待中的 DDL 任务可以暂停,否则会在 `RESULT` 列看到 `Job 3 can't be paused now`。 + 你只能暂停正在进行或仍在队列中的 DDL 任务。否则,`RESULT` 列中会显示 `Job 3 can't be paused now` 错误。 -- `ADMIN RESUME DDL JOBS job_id [, job_id]`:用于恢复已被暂停的 DDL 任务。执行该命令后,执行 DDL 任务的 SQL 语句体现为正在执行,后台任务正常执行。详情参阅 [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md)。 +- `ADMIN RESUME DDL JOBS job_id [, job_id]`:用于恢复已暂停的 DDL 任务。命令执行后,执行 DDL 任务的 SQL 语句显示为正在执行,后台任务恢复执行。详情请参见 [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md)。 - 你只能对暂停状态的 DDL 任务进行恢复操作,否则会在 `RESULT` 列看到 `Job 3 can't be resumed`。 + 你只能恢复已暂停的 DDL 任务。否则,`RESULT` 列中会显示 `Job 3 can't be resumed` 错误。 ## 常见问题 -DDL 语句执行相关的常见问题,参考 [SQL FAQ - DDL 执行](/faq/sql-faq.md#ddl-执行)。 +关于 DDL 执行的常见问题,请参见 [SQL FAQ - DDL 执行](https://docs.pingcap.com/tidb/stable/sql-faq)。 diff --git a/derive-topn-from-window.md b/derive-topn-from-window.md index f089b967d95a..3d024014acb1 100644 --- a/derive-topn-from-window.md +++ b/derive-topn-from-window.md @@ -1,45 +1,45 @@ --- -title: 从窗口函数中推导 TopN 或 Limit -summary: 介绍从窗口函数中推导 TopN 或 Limit 的优化规则,以及如何开启该规则。 +title: 从窗口函数推导 TopN 或 Limit +summary: 介绍从窗口函数推导 TopN 或 Limit 的优化规则以及如何启用此规则。 --- -# 从窗口函数中推导 TopN 或 Limit +# 从窗口函数推导 TopN 或 Limit -[窗口函数](/functions-and-operators/window-functions.md)是一种常见的 SQL 函数。对于 `ROW_NUMBER()` 或者 `RANK()` 等编号相关的窗口函数,一种常见的用法是在进行窗口函数求值之后,对求值的结果进行过滤,例如: +[窗口函数](/functions-and-operators/window-functions.md)是一种常见的 SQL 函数。当您使用窗口函数进行行编号时,例如 `ROW_NUMBER()` 或 `RANK()`,通常会在窗口函数计算后对结果进行过滤。例如: ```sql SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY a) AS rownumber FROM t) dt WHERE rownumber <= 3 ``` -按照正常的 SQL 执行流程,TiDB 需要先对 `t` 表的所有数据进行排序,然后为每一行都求得相应的 `ROW_NUMBER()` 结果,最后再进行 `rownumber <= 3` 的过滤。 +在典型的 SQL 执行过程中,TiDB 首先对表 `t` 中的所有数据进行排序,然后为每一行计算 `ROW_NUMBER()` 结果,最后使用 `rownumber <= 3` 进行过滤。 -从 v7.0.0 开始,TiDB 支持从窗口函数中推导 TopN 或 Limit 算子。通过该优化规则,TiDB 可以将原始 SQL 等价改写成以下形式: +从 v7.0.0 开始,TiDB 支持从窗口函数推导 TopN 或 Limit 运算符。通过此优化规则,TiDB 可以将原始 SQL 重写为以下等价形式: ```sql WITH t_topN AS (SELECT a FROM t1 ORDER BY a LIMIT 3) SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY a) AS rownumber FROM t_topN) dt WHERE rownumber <= 3 ``` -可以看出,改写后,TiDB 可以从窗口函数与后续的过滤条件中推导出一个 TopN 算子,相比于原始 SQL 中的 Sort 算子(对应 `ORDER BY`),TopN 算子的运行效率远高于 Sort 算子,而且 TiKV 和 TiFlash 均支持 TopN 算子的下推,因此能进一步提升改写后的 SQL 的性能。 +重写后,TiDB 可以从窗口函数和后续的过滤条件推导出 TopN 运算符。与原始 SQL 中的 Sort 运算符(`ORDER BY`)相比,TopN 运算符具有更高的执行效率。此外,TiKV 和 TiFlash 都支持下推 TopN 运算符,这进一步提高了重写后 SQL 的性能。 -从窗口函数中推导 TopN 或 Limit 默认关闭。你可以通过将 session 变量 [tidb_opt_derive_topn](/system-variables.md#tidb_opt_derive_topn-从-v700-版本开始引入) 设置为 `ON` 开启该功能。 +从窗口函数推导 TopN 或 Limit 默认是禁用的。要启用此功能,您可以将会话变量 [tidb_opt_derive_topn](/system-variables.md#tidb_opt_derive_topn-new-in-v700) 设置为 `ON`。 -开启后,如需关闭,可以进行以下操作之一: +启用此功能后,您可以通过执行以下操作之一来禁用它: -* 设置 session 变量 [tidb_opt_derive_topn](/system-variables.md#tidb_opt_derive_topn-从-v700-版本开始引入) 为 `false`。 -* 可参照[优化规则及表达式下推的黑名单](/blocklist-control-plan.md)中的关闭方法。 +* 将会话变量 [tidb_opt_derive_topn](/system-variables.md#tidb_opt_derive_topn-new-in-v700) 设置为 `OFF`。 +* 按照[优化规则和表达式下推的黑名单](/blocklist-control-plan.md)中描述的步骤操作。 ## 限制 -* 目前仅 `ROW_NUMBER()` 窗口函数支持 SQL 语句改写。 -* 只有当 SQL 语句的过滤条件是针对 `ROW_NUMBER()` 结果而且过滤条件为 `<` 或者 `<=` 时,TiDB 才支持改写 SQL 语句。 +* 仅支持对 `ROW_NUMBER()` 窗口函数进行 SQL 重写。 +* TiDB 只能在对 `ROW_NUMBER()` 结果进行过滤且过滤条件为 `<` 或 `<=` 时重写 SQL。 -## 示例 +## 使用示例 -以下通过一些例子对该优化规则进行说明。 +以下示例演示如何使用此优化规则。 -### 不包含 PARTITION BY 的窗口函数 +### 不带 PARTITION BY 的窗口函数 -#### 示例 1:不包含 ORDER BY 的窗口函数 +#### 示例 1:不带 ORDER BY 的窗口函数 ```sql CREATE TABLE t(id int, value int); @@ -47,6 +47,8 @@ SET tidb_opt_derive_topn=on; EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER () AS rownumber FROM t) dt WHERE rownumber <= 3; ``` +结果如下: + ``` +----------------------------------+---------+-----------+---------------+-----------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -61,9 +63,9 @@ EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER () AS rownumber FROM t) dt WHERE +----------------------------------+---------+-----------+---------------+-----------------------------------------------------------------------+ ``` -在该查询中,优化器从窗口函数中推导出来了 Limit 并将它下推给了 TiKV。 +在此查询中,优化器从窗口函数推导出 Limit 运算符并将其下推到 TiKV。 -#### 示例 2:包含 ORDER BY 的窗口函数 +#### 示例 2:带 ORDER BY 的窗口函数 ```sql CREATE TABLE t(id int, value int); @@ -71,6 +73,8 @@ SET tidb_opt_derive_topn=on; EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY value) AS rownumber FROM t) dt WHERE rownumber <= 3; ``` +结果如下: + ``` +----------------------------------+----------+-----------+---------------+---------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -85,15 +89,15 @@ EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY value) AS rownumber FR +----------------------------------+----------+-----------+---------------+---------------------------------------------------------------------------------------------+ ``` -在该查询中,优化器从窗口函数中推导出来了 TopN 并将它下推给了 TiKV。 +在此查询中,优化器从窗口函数推导出 TopN 运算符并将其下推到 TiKV。 -### 包含 PARTITION BY 的窗口函数 +### 带 PARTITION BY 的窗口函数 > **注意:** > -> 当窗口函数包含 PARTITION BY 时,该优化规则仅在 partition 列是主键的前缀且主键是聚簇索引的时候才能生效。 +> 对于包含 `PARTITION BY` 的窗口函数,只有当分区列是主键的前缀且主键是聚簇索引时,优化规则才会生效。 -#### 示例 3:不包含 ORDER BY 的窗口函数 +#### 示例 3:不带 ORDER BY 的窗口函数 ```sql CREATE TABLE t(id1 int, id2 int, value1 int, value2 int, primary key(id1,id2) clustered); @@ -101,6 +105,8 @@ SET tidb_opt_derive_topn=on; EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY id1) AS rownumber FROM t) dt WHERE rownumber <= 3; ``` +结果如下: + ``` +------------------------------------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -116,9 +122,9 @@ EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY id1) AS rownumber +------------------------------------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------+ ``` -在该查询中,优化器从窗口函数中推导出来了 Limit 并将它下推给了 TiKV。值得一提的是这个 Limit 其实是 partition Limit,也就是说对于每个相同 `id1` 值组成的一组数据上都会进行一次 Limit。 +在此查询中,优化器从窗口函数推导出 Limit 运算符并将其下推到 TiKV。注意,这个 Limit 实际上是一个分区 Limit,这意味着 Limit 将应用于具有相同 `id1` 值的每组数据。 -#### 示例 4:包含 ORDER BY 的窗口函数 +#### 示例 4:带 ORDER BY 的窗口函数 ```sql CREATE TABLE t(id1 int, id2 int, value1 int, value2 int, primary key(id1,id2) clustered); @@ -126,6 +132,8 @@ SET tidb_opt_derive_topn=on; EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY id1 ORDER BY value1) AS rownumber FROM t) dt WHERE rownumber <= 3; ``` +结果如下: + ``` +------------------------------------+----------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -141,7 +149,7 @@ EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY id1 ORDER BY value +------------------------------------+----------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------+ ``` -在该查询中,优化器从窗口函数中推导出来了 TopN 并将它下推给了 TiKV。需要注意的是,这个 TopN 其实是 partition 的 TopN, 也就是说对于每个相同 `id1` 值组成的一组数据上都会进行一次 TopN。 +在此查询中,优化器从窗口函数推导出 TopN 运算符并将其下推到 TiKV。注意,这个 TopN 实际上是一个分区 TopN,这意味着 TopN 将应用于具有相同 `id1` 值的每组数据。 #### 示例 5:PARTITION BY 列不是主键的前缀 @@ -151,6 +159,8 @@ SET tidb_opt_derive_topn=on; EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY value1) AS rownumber FROM t) dt WHERE rownumber <= 3; ``` +结果如下: + ``` +----------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -165,9 +175,9 @@ EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY value1) AS rownumb +----------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------+ ``` -在该查询中,因为 partition 的列不是主键的前缀,所以 SQL 没有被改写。 +在此查询中,由于 `PARTITION BY` 列不是主键的前缀,SQL 没有被重写。 -#### 示例 6:PARTITION BY 列是主键的前缀,但主键不是聚簇索引 +#### 示例 6:PARTITION BY 列是主键的前缀但不是聚簇索引 ```sql CREATE TABLE t(id1 int, id2 int, value1 int, value2 int, primary key(id1,id2) nonclustered); @@ -175,6 +185,8 @@ SET tidb_opt_derive_topn=on; EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY id1) AS rownumber FROM t use index()) dt WHERE rownumber <= 3; ``` +结果如下: + ``` +----------------------------------+----------+-----------+---------------+-----------------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | @@ -189,4 +201,4 @@ EXPLAIN SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY id1) AS rownumber +----------------------------------+----------+-----------+---------------+-----------------------------------------------------------------------------------------------+ ``` -在该查询中,即使 PARTITION 的列是主键的前缀,但是因为主键不是聚簇索引,所以 SQL 没被改写。 +在此查询中,虽然 `PARTITION BY` 列是主键的前缀,但由于主键不是聚簇索引,SQL 没有被重写。 diff --git a/develop/dev-guide-aws-appflow-integration.md b/develop/dev-guide-aws-appflow-integration.md new file mode 100644 index 000000000000..cb8ccdde096c --- /dev/null +++ b/develop/dev-guide-aws-appflow-integration.md @@ -0,0 +1,262 @@ +--- +title: 将 TiDB 与 Amazon AppFlow 集成 +summary: 介绍如何逐步将 TiDB 与 Amazon AppFlow 集成。 +--- + +# 将 TiDB 与 Amazon AppFlow 集成 + +[Amazon AppFlow](https://aws.amazon.com/appflow/) 是一个完全托管的 API 集成服务,您可以使用它将软件即服务(SaaS)应用程序连接到 AWS 服务,并安全地传输数据。使用 Amazon AppFlow,您可以在 TiDB 和许多类型的数据提供商之间导入和导出数据,例如 Salesforce、Amazon S3、LinkedIn 和 GitHub。有关更多信息,请参见 AWS 文档中的[支持的源和目标应用程序](https://docs.aws.amazon.com/appflow/latest/userguide/app-specific.html)。 + +本文介绍如何将 TiDB 与 Amazon AppFlow 集成,并以集成 TiDB Cloud Serverless 集群为例。 + +如果您没有 TiDB 集群,可以[创建一个 TiDB Cloud Serverless 集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless),这是免费的,大约 30 秒即可创建完成。 + +## 前提条件 + +- [Git](https://git-scm.com/) +- [JDK](https://openjdk.org/install/) 11 或更高版本 +- [Maven](https://maven.apache.org/install.html) 3.8 或更高版本 +- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 版本 2 +- [AWS Serverless Application Model Command Line Interface (AWS SAM CLI)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) 1.58.0 或更高版本 +- 一个具有以下要求的 AWS [Identity and Access Management (IAM) 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html): + + - 用户可以使用[访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)访问 AWS。 + - 用户具有以下权限: + + - `AWSCertificateManagerFullAccess`:用于读写 [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/)。 + - `AWSCloudFormationFullAccess`:SAM CLI 使用 [AWS CloudFormation](https://aws.amazon.com/cloudformation/) 声明 AWS 资源。 + - `AmazonS3FullAccess`:AWS CloudFormation 使用 [Amazon S3](https://aws.amazon.com/s3/?nc2=h_ql_prod_fs_s3) 进行发布。 + - `AWSLambda_FullAccess`:目前,[AWS Lambda](https://aws.amazon.com/lambda/?nc2=h_ql_prod_fs_lbd) 是为 Amazon AppFlow 实现新连接器的唯一方式。 + - `IAMFullAccess`:SAM CLI 需要为连接器创建 `ConnectorFunctionRole`。 + +- 一个 [SalesForce](https://developer.salesforce.com) 账户。 + +## 步骤 1. 注册 TiDB 连接器 + +### 克隆代码 + +克隆 TiDB 和 Amazon AppFlow 的[集成示例代码仓库](https://github.com/pingcap-inc/tidb-appflow-integration): + +```bash +git clone https://github.com/pingcap-inc/tidb-appflow-integration +``` + +### 构建和上传 Lambda + +1. 构建包: + + ```bash + cd tidb-appflow-integration + mvn clean package + ``` + +2. (可选)如果您尚未配置 AWS 访问密钥 ID 和密钥,请进行配置。 + + ```bash + aws configure + ``` + +3. 将您的 JAR 包作为 Lambda 上传: + + ```bash + sam deploy --guided + ``` + + > **注意:** + > + > - `--guided` 选项使用提示来引导您完成部署。您的输入将存储在配置文件中,默认为 `samconfig.toml`。 + > - `stack_name` 指定您正在部署的 AWS Lambda 的名称。 + > - 此提示指南使用 AWS 作为 TiDB Cloud Serverless 的云提供商。要使用 Amazon S3 作为源或目标,您需要将 AWS Lambda 的 `region` 设置为与 Amazon S3 相同的区域。 + > - 如果您之前已经运行过 `sam deploy --guided`,您可以直接运行 `sam deploy`,SAM CLI 将使用配置文件 `samconfig.toml` 来简化交互。 + + 如果您看到类似以下的输出,则说明此 Lambda 已成功部署。 + + ``` + Successfully created/updated stack - in + ``` + +4. 转到 [AWS Lambda 控制台](https://console.aws.amazon.com/lambda/home),您可以看到刚刚上传的 Lambda。请注意,您需要在窗口右上角选择正确的区域。 + + ![lambda 仪表板](/media/develop/aws-appflow-step-lambda-dashboard.png) + +### 使用 Lambda 注册连接器 + +1. 在 [AWS 管理控制台](https://console.aws.amazon.com)中,导航到 [Amazon AppFlow > 连接器](https://console.aws.amazon.com/appflow/home#/gallery),然后点击**注册新连接器**。 + + ![注册连接器](/media/develop/aws-appflow-step-register-connector.png) + +2. 在**注册新连接器**对话框中,选择您上传的 Lambda 函数,并使用连接器名称指定连接器标签。 + + ![注册连接器对话框](/media/develop/aws-appflow-step-register-connector-dialog.png) + +3. 点击**注册**。然后,TiDB 连接器就注册成功了。 + +## 步骤 2. 创建流 + +导航到 [Amazon AppFlow > 流](https://console.aws.amazon.com/appflow/home#/list),然后点击**创建流**。 + +![创建流](/media/develop/aws-appflow-step-create-flow.png) + +### 设置流名称 + +输入流名称,然后点击**下一步**。 + +![命名流](/media/develop/aws-appflow-step-name-flow.png) + +### 设置源和目标表 + +选择**源详情**和**目标详情**。TiDB 连接器可以在两者中使用。 + +1. 选择源名称。本文以 **Salesforce** 作为示例源。 + + ![salesforce 源](/media/develop/aws-appflow-step-salesforce-source.png) + + 注册到 Salesforce 后,Salesforce 会向您的平台添加一些示例数据。以下步骤将使用 **Account** 对象作为示例源对象。 + + ![salesforce 数据](/media/develop/aws-appflow-step-salesforce-data.png) + +2. 点击**连接**。 + + 1. 在**连接到 Salesforce** 对话框中,指定此连接的名称,然后点击**继续**。 + + ![连接到 salesforce](/media/develop/aws-appflow-step-connect-to-salesforce.png) + + 2. 点击**允许**以确认 AWS 可以读取您的 Salesforce 数据。 + + ![允许 salesforce](/media/develop/aws-appflow-step-allow-salesforce.png) + + > **注意:** + > + > 如果您的公司已经使用了 Salesforce 专业版,REST API 默认是禁用的。您可能需要注册一个新的开发者版本来使用 REST API。有关更多信息,请参见 [Salesforce 论坛主题](https://developer.salesforce.com/forums/?id=906F0000000D9Y2IAK)。 + +3. 在**目标详情**区域,选择 **TiDB-Connector** 作为目标。此时会显示**连接**按钮。 + + ![tidb 目标](/media/develop/aws-appflow-step-tidb-dest.png) + +4. 在点击**连接**之前,您需要在 TiDB 中为 Salesforce **Account** 对象创建一个 `sf_account` 表。请注意,此表架构与 [Amazon AppFlow 教程](https://docs.aws.amazon.com/appflow/latest/userguide/flow-tutorial-set-up-source.html)中的示例数据不同。 + + ```sql + CREATE TABLE `sf_account` ( + `id` varchar(255) NOT NULL, + `name` varchar(150) NOT NULL DEFAULT '', + `type` varchar(150) NOT NULL DEFAULT '', + `billing_state` varchar(255) NOT NULL DEFAULT '', + `rating` varchar(255) NOT NULL DEFAULT '', + `industry` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`id`) + ); + ``` + +5. 创建 `sf_account` 表后,点击**连接**。此时会显示一个连接对话框。 +6. 在**连接到 TiDB-Connector** 对话框中,输入 TiDB 集群的连接属性。如果您使用 TiDB Cloud Serverless 集群,需要将 **TLS** 选项设置为 `Yes`,这样 TiDB 连接器就会使用 TLS 连接。然后,点击**连接**。 + + ![tidb 连接消息](/media/develop/aws-appflow-step-tidb-connection-message.png) + +7. 现在您可以获取为连接指定的数据库中的所有表。从下拉列表中选择 **sf_account** 表。 + + ![数据库](/media/develop/aws-appflow-step-database.png) + + 以下截图显示了将数据从 Salesforce **Account** 对象传输到 TiDB 中的 `sf_account` 表的配置: + + ![完成流](/media/develop/aws-appflow-step-complete-flow.png) + +8. 在**错误处理**区域,选择**停止当前流运行**。在**流触发器**区域,选择**按需运行**触发器类型,这意味着您需要手动运行流。然后,点击**下一步**。 + + ![完成步骤 1](/media/develop/aws-appflow-step-complete-step1.png) + +### 设置映射规则 + +将 Salesforce 中 **Account** 对象的字段映射到 TiDB 中的 `sf_account` 表,然后点击**下一步**。 + +- `sf_account` 表是在 TiDB 中新创建的,它是空的。 + + ```sql + test> SELECT * FROM sf_account; + +----+------+------+---------------+--------+----------+ + | id | name | type | billing_state | rating | industry | + +----+------+------+---------------+--------+----------+ + +----+------+------+---------------+--------+----------+ + ``` + +- 要设置映射规则,您可以在左侧选择源字段名称,在右侧选择目标字段名称。然后,点击**映射字段**,规则就设置好了。 + + ![添加映射规则](/media/develop/aws-appflow-step-add-mapping-rule.png) + +- 本文需要以下映射规则(源字段名称 -> 目标字段名称): + + - Account ID -> id + - Account Name -> name + - Account Type -> type + - Billing State/Province -> billing_state + - Account Rating -> rating + - Industry -> industry + + ![映射规则](/media/develop/aws-appflow-step-mapping-a-rule.png) + + ![显示所有映射规则](/media/develop/aws-appflow-step-show-all-mapping-rules.png) + +### (可选)设置过滤器 + +如果您想为数据字段添加一些过滤器,可以在此处设置。否则,跳过此步骤并点击**下一步**。 + +![过滤器](/media/develop/aws-appflow-step-filters.png) + +### 确认并创建流 + +确认要创建的流的信息。如果一切看起来都没问题,点击**创建流**。 + +![审查](/media/develop/aws-appflow-step-review.png) + +## 步骤 3. 运行流 + +在新创建的流的页面上,点击右上角的**运行流**。 + +![运行流](/media/develop/aws-appflow-step-run-flow.png) + +以下截图显示了流运行成功的示例: + +![运行成功](/media/develop/aws-appflow-step-run-success.png) + +查询 `sf_account` 表,您可以看到来自 Salesforce **Account** 对象的记录已经写入其中: + +```sql +test> SELECT * FROM sf_account; ++--------------------+-------------------------------------+--------------------+---------------+--------+----------------+ +| id | name | type | billing_state | rating | industry | ++--------------------+-------------------------------------+--------------------+---------------+--------+----------------+ +| 001Do000003EDTlIAO | Sample Account for Entitlements | null | null | null | null | +| 001Do000003EDTZIA4 | Edge Communications | Customer - Direct | TX | Hot | Electronics | +| 001Do000003EDTaIAO | Burlington Textiles Corp of America | Customer - Direct | NC | Warm | Apparel | +| 001Do000003EDTbIAO | Pyramid Construction Inc. | Customer - Channel | null | null | Construction | +| 001Do000003EDTcIAO | Dickenson plc | Customer - Channel | KS | null | Consulting | +| 001Do000003EDTdIAO | Grand Hotels & Resorts Ltd | Customer - Direct | IL | Warm | Hospitality | +| 001Do000003EDTeIAO | United Oil & Gas Corp. | Customer - Direct | NY | Hot | Energy | +| 001Do000003EDTfIAO | Express Logistics and Transport | Customer - Channel | OR | Cold | Transportation | +| 001Do000003EDTgIAO | University of Arizona | Customer - Direct | AZ | Warm | Education | +| 001Do000003EDThIAO | United Oil & Gas, UK | Customer - Direct | UK | null | Energy | +| 001Do000003EDTiIAO | United Oil & Gas, Singapore | Customer - Direct | Singapore | null | Energy | +| 001Do000003EDTjIAO | GenePoint | Customer - Channel | CA | Cold | Biotechnology | +| 001Do000003EDTkIAO | sForce | null | CA | null | null | ++--------------------+-------------------------------------+--------------------+---------------+--------+----------------+ +``` + +## 注意事项 + +- 如果出现任何问题,您可以导航到 AWS 管理控制台上的 [CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 页面获取日志。 +- 本文中的步骤基于[使用 Amazon AppFlow Custom Connector SDK 构建自定义连接器](https://aws.amazon.com/blogs/compute/building-custom-connectors-using-the-amazon-appflow-custom-connector-sdk/)。 +- [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) **不是**生产环境。 +- 为了防止篇幅过长,本文中的示例仅显示了 `Insert` 策略,但 `Update` 和 `Upsert` 策略也经过测试并可以使用。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-bookshop-schema-design.md b/develop/dev-guide-bookshop-schema-design.md index b971f9beccd5..d788dcd29ed4 100644 --- a/develop/dev-guide-bookshop-schema-design.md +++ b/develop/dev-guide-bookshop-schema-design.md @@ -1,41 +1,61 @@ --- -title: Bookshop 应用 -summary: Bookshop 应用设计、数据导入、连接数据库等操作。 +title: Bookshop 示例应用程序 +summary: Bookshop 是一个用于购买和评价图书的在线书店应用程序。您可以通过 TiUP 或 TiDB Cloud 导入表结构和数据。方法 1 使用 TiUP 快速生成和导入示例数据,而方法 2 从 Amazon S3 导入数据到 TiDB Cloud。数据库表包括 books、authors、users、ratings、book_authors 和 orders。数据库初始化脚本 `dbinit.sql` 创建 Bookshop 应用程序的表结构。 --- -# Bookshop 应用 +# Bookshop 示例应用程序 -Bookshop 是一个虚拟的在线书店应用,你可以在 Bookshop 当中便捷地购买到各种类别的书,也可以对你看过的书进行点评。 +Bookshop 是一个虚拟的在线书店应用程序,通过它您可以购买各种类别的图书并对您读过的图书进行评分。 -为了方便你阅读应用开发指南中的内容,我们将以 Bookshop 应用的[数据表结构](#数据表详解)和数据为基础来编写示例 SQL。本章节将为你介绍如何导入该应用的表结构和数据,以及其数据表结构的定义。 +为了使您更顺利地阅读应用程序开发者指南,我们基于 Bookshop 应用程序的[表结构](#表说明)和数据展示示例 SQL 语句。本文重点介绍导入表结构和数据的方法以及表结构的定义。 ## 导入表结构和数据 -你可以[通过 TiUP](#方法一通过-tiup-demo-命令行) 或[通过 TiDB Cloud Import](#方法二通过-tidb-cloud-import-功能) 两种方式导入 Bookshop 应用的表结构和数据。 + -### 方法一:通过 `tiup demo` 命令行 +您可以通过 [TiUP](#方法-1通过-tiup-demo) 或 [TiDB Cloud 的导入功能](#方法-2通过-tidb-cloud-导入)导入 Bookshop 表结构和数据。 -如果你使用 [TiUP](/tiup/tiup-reference.md#tiup-命令概览) 部署 TiDB 集群或者你可以直接连接到你的 TiDB 服务器,你可以通过如下命令快速生成并导入 Bookshop 应用的示例数据: + + + + +对于 TiDB Cloud,您可以跳过[方法 1:通过 `tiup demo`](#方法-1通过-tiup-demo),直接[通过 TiDB Cloud 的导入功能](#方法-2通过-tidb-cloud-导入)导入 Bookshop 表结构。 + + + +### 方法 1:通过 `tiup demo` + + + +如果您的 TiDB 集群是使用 [TiUP](/tiup/tiup-reference.md#tiup-reference) 部署的,或者您可以连接到您的 TiDB 服务器,您可以通过运行以下命令快速生成和导入 Bookshop 应用程序的示例数据: + + + + + +如果您的 TiDB 集群是使用 [TiUP](https://docs.pingcap.com/tidb/stable/tiup-reference) 部署的,或者您可以连接到您的 TiDB 服务器,您可以通过运行以下命令快速生成和导入 Bookshop 应用程序的示例数据: + + ```shell tiup demo bookshop prepare ``` -该命令默认会连接到 `127.0.0.1` 地址上的 `4000` 端口,使用 `root` 用户名进行无密码登录,默认在名为 `bookshop` 的数据库中创建[表结构](#数据表详解)。 +默认情况下,此命令使您的应用程序能够连接到地址 `127.0.0.1` 的端口 `4000`,使您能够以无密码的 `root` 用户身份登录,并在名为 `bookshop` 的数据库中创建[表结构](#表说明)。 #### 配置连接信息 -你可以通过如下参数修改默认的连接信息: +下表列出了连接参数。您可以更改它们的默认设置以匹配您的环境。 -| 参数 | 简写 | 默认值 | 解释 | +| 参数名称 | 缩写 | 默认值 | 描述 | | ------------ | ---- | ----------- | -------------- | +| `--password` | `-p` | 无 | 数据库用户密码 | | `--host` | `-H` | `127.0.0.1` | 数据库地址 | | `--port` | `-P` | `4000` | 数据库端口 | -| `--user` | `-U` | `root` | 数据库用户 | -| `--password` | `-p` | 无 | 数据库用户密码 | | `--db` | `-D` | `bookshop` | 数据库名称 | +| `--user` | `-U` | `root` | 数据库用户 | -例如,你想要连接到 TiDB Cloud 上的数据库,你可以如下命令指定连接信息进行连接: +例如,如果您想连接到 TiDB Cloud 上的数据库,可以按如下方式指定连接信息: ```shell tiup demo bookshop prepare -U -H -P 4000 -p @@ -43,56 +63,68 @@ tiup demo bookshop prepare -U -H -P 4000 -p #### 设置数据量 -另外,你还可以通过如下参数指定各个数据库表生成的数据量: +您可以通过配置以下参数来指定在每个数据库表中生成的数据量: -| 参数 | 默认值 | 解释 | +| 参数名称 | 默认值 | 描述 | | ----------- | -------- | --------------------------------- | -| `--users` | `10000` | 指定在 `users` 表生成的数据行数 | -| `--authors` | `20000` | 指定在 `authors` 表生成的数据行数 | -| `--books` | `20000` | 指定在 `books` 表生成的数据行数 | -| `--orders` | `300000` | 指定在 `orders` 表生成的数据行数 | -| `--ratings` | `300000` | 指定在 `ratings` 表生成的数据行数 | +| `--users` | `10000` | 在 `users` 表中生成的数据行数 | +| `--authors` | `20000` | 在 `authors` 表中生成的行数 | +| `--books` | `20000` | 在 `books` 表中生成的数据行数 | +| `--orders` | `300000` | 在 `orders` 表中生成的数据行数 | +| `--ratings` | `300000` | 在 `ratings` 表中生成的数据行数 | + +例如,执行以下命令生成: -例如,以下命令通过 `--users` 参数指定生成 20 万行用户信息,通过 `--books` 参数指定生成 50 万行书籍的基本信息,通过 `--authors` 参数指定生成 10 万的作者信息,通过 `--ratings` 参数指定生成 100 万的评分记录,通过 `--orders` 参数指定生成 100 万的订单记录。 +- 通过 `--users` 参数生成 200,000 行用户信息 +- 通过 `--books` 参数生成 500,000 行图书信息 +- 通过 `--authors` 参数生成 100,000 行作者信息 +- 通过 `--ratings` 参数生成 1,000,000 行评分记录 +- 通过 `--orders` 参数生成 1,000,000 行订单记录 ```shell tiup demo bookshop prepare --users=200000 --books=500000 --authors=100000 --ratings=1000000 --orders=1000000 --drop-tables ``` -通过 `--drop-tables` 参数你可以删除原有的表结构,更多的参数说明你可以通过命令 `tiup demo bookshop --help` 进行了解。 +您可以通过 `--drop-tables` 参数删除原有的表结构。有关更多参数说明,请运行 `tiup demo bookshop --help` 命令。 -### 方法二:通过 TiDB Cloud Import 功能 +### 方法 2:通过 TiDB Cloud 导入 -1. 打开目标集群的 **Import** 页面。 +1. 打开目标集群的**导入**页面。 - 1. 登录 [TiDB Cloud](https://tidbcloud.com/),导航至 [**Clusters**](https://tidbcloud.com/console/clusters) 页面。 + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 - > **Tip:** + > **提示:** > - > 如果你有多个 TiDB Cloud 项目,可以点击左下角的 切换项目。 + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 - 2. 点击目标集群的名称,进入集群的 **Overview** 页面,然后在左侧导航栏中点击 **Import**。 + 2. 点击目标集群的名称进入其概览页面,然后点击左侧导航栏中的**导入**。 -2. 选择 **Import data from Cloud Storage**,然后点击 **Amazon S3**. +2. 选择**从云存储导入数据**,然后点击 **Amazon S3**。 -3. 在 **Import Data from Amazon S3** 页面,配置以下源数据信息: +3. 在**从 Amazon S3 导入数据**页面上,配置以下源数据信息: - - **Import File Count**:对于 TiDB Cloud Serverless,选择 **Multiple files**。TiDB Cloud Dedicated 中没有该字段。 - - **Included Schema Files**:选择 **Yes** - - **Data Format**:选择 **SQL** - - **Folder URI**:输入 `s3://developer.pingcap.com/bookshop/` - - **Bucket Access**:选择 **AWS Role ARN** - - **Role ARN**:输入 `arn:aws:iam::494090988690:role/s3-tidb-cloud-developer-access` + - **导入文件数量**:对于 TiDB Cloud Serverless,选择**多个文件**。此字段在 TiDB Cloud Dedicated 中不可用。 + - **包含模式文件**:选择**是**。 + - **数据格式**:选择 **SQL**。 + - **文件夹 URI**:输入 `s3://developer.pingcap.com/bookshop/`。 + - **存储桶访问**:选择 **AWS Role ARN**。 + - **Role ARN**:输入 `arn:aws:iam::494090988690:role/s3-tidb-cloud-developer-access`。 - 在这个示例数据当中,预先生成了 20 万的用户信息、50 万条书籍信息、10 万条作者信息、100 万条评分记录以及 100 万条订单信息。 + 在此示例中,预先生成了以下数据: -4. 点击 **Connect** > **Start Import** 开始导入数据,等待 TiDB Cloud 完成数据导入。 + - 200,000 行用户信息 + - 500,000 行图书信息 + - 100,000 行作者信息 + - 1,000,000 行评分记录 + - 1,000,000 行订单记录 -你可以通过 [TiDB Cloud Migration Overview](https://docs.pingcap.com/tidbcloud/tidb-cloud-migration-overview) 文档获取更多有关 TiDB Cloud 数据导入和迁移的信息。 +4. 点击**连接** > **开始导入**以启动导入过程,并等待 TiDB Cloud 完成导入。 -### 查看数据导入情况 +有关如何向 TiDB Cloud 导入或迁移数据的更多信息,请参见 [TiDB Cloud 迁移概述](https://docs.pingcap.com/tidbcloud/tidb-cloud-migration-overview)。 -导入完成后,你可以通过下面的 SQL 语句查看各个表的数据量信息: +### 查看数据导入状态 + +导入完成后,您可以通过执行以下 SQL 语句查看每个表的数据量信息: ```sql SELECT @@ -106,7 +138,7 @@ FROM WHERE table_schema LIKE 'bookshop'; ``` -运行结果为: +结果如下: ``` +-----------------------+----------------+-----------+------------+---------+ @@ -122,80 +154,80 @@ WHERE table_schema LIKE 'bookshop'; 6 rows in set (0.03 sec) ``` -## 数据表详解 +## 表说明 -以下将详细介绍 Bookshop 应用程序的数据库表结构: +本节详细说明 Bookshop 应用程序的数据库表。 ### `books` 表 -该表用于存储书籍的基本信息。 +此表存储图书的基本信息。 -| 字段名 | 类型 | 含义 | -|--------------|---------------|---------------------------------------| -| id | bigint(20) | 书籍的唯一标识 | -| title | varchar(100) | 书籍名称 | -| type | enum | 书籍类型(如:杂志、动漫、教辅等) | -| stock | bigint(20) | 库存 | -| price | decimal(15,2) | 价格 | -| published_at | datetime | 出版时间 | +| 字段名称 | 类型 | 描述 | +|--------------|---------------|------------------------------------------------------------------| +| id | bigint(20) | 图书的唯一标识符 | +| title | varchar(100) | 图书标题 | +| type | enum | 图书类型(例如,杂志、动漫或教学辅助材料) | +| stock | bigint(20) | 库存 | +| price | decimal(15,2) | 价格 | +| published_at | datetime | 出版日期 | ### `authors` 表 -该表用于存储作者的基本信息。 +此表存储作者的基本信息。 -| 字段名 | 类型 | 含义 | -|------------|--------------|-------------------------------------| -| id | bigint(20) | 作者的唯一标识 | -| name | varchar(100) | 姓名 | -| gender | tinyint(1) | 生理性别 (0: 女, 1: 男,NULL: 未知) | -| birth_year | smallint(6) | 生年 | -| death_year | smallint(6) | 卒年 | +| 字段名称 | 类型 | 描述 | +|------------|--------------|-------------------------------------------------------| +| id | bigint(20) | 作者的唯一标识符 | +| name | varchar(100) | 作者姓名 | +| gender | tinyint(1) | 生理性别(0:女性,1:男性,NULL:未知) | +| birth_year | smallint(6) | 出生年份 | +| death_year | smallint(6) | 死亡年份 | ### `users` 表 -该表用于存储使用 Bookshop 应用程序的用户。 +此表存储 Bookshop 用户的信息。 -| 字段名 | 类型 | 含义 | -|----------|---------------|----------------| -| id | bigint(20) | 用户的唯一标识 | -| balance | decimal(15,2) | 余额 | -| nickname | varchar(100) | 昵称 | +| 字段名称 | 类型 | 描述 | +|------------|---------------|-----------------------| +| id | bigint(20) | 用户的唯一标识符 | +| balance | decimal(15,2) | 余额 | +| nickname | varchar(100) | 昵称 | ### `ratings` 表 -该表用于存储用户对书籍的评分记录。 +此表存储用户对图书的评分记录。 -| 字段名 | 类型 | 含义 | -|----------|----------|---------------------------------------------| -| book_id | bigint | 书籍的唯一标识(关联至 [books](#books-表)) | -| user_id | bigint | 用户的唯一标识(关联至 [users](#users-表)) | -| score | tinyint | 用户评分 (1-5) | -| rated_at | datetime | 评分时间 | +| 字段名称 | 类型 | 描述 | +|------------|----------|------------------------------------------------------------| +| book_id | bigint | 图书的唯一标识符(关联到 [books](#books-表)) | +| user_id | bigint | 用户的唯一标识符(关联到 [users](#users-表)) | +| score | tinyint | 用户评分(1-5) | +| rated_at | datetime | 评分时间 | ### `book_authors` 表 -一个作者可能会编写多本书,一本书可能需要多个作者同时编写,该表用于存储书籍与作者之间的对应关系。 +一个作者可能写多本书,一本书可能涉及多个作者。此表存储图书和作者之间的对应关系。 -| 字段名 | 类型 | 含义 | -|-----------|------------|--------------------------------------------| -| book_id | bigint(20) | 书籍的唯一标识(关联至 [books](#books-表)) | -| author_id | bigint(20) | 作者的唯一标识(关联至 [authors](#authors-表)) | +| 字段名称 | 类型 | 描述 | +|------------|------------|--------------------------------------------------------------| +| book_id | bigint(20) | 图书的唯一标识符(关联到 [books](#books-表)) | +| author_id | bigint(20) | 作者的唯一标识符(关联到 [authors](#authors-表)) | ### `orders` 表 -该表用于存储用户购买书籍的订单信息。 +此表存储用户的购买信息。 -| 字段名 | 类型 | 含义 | -|------------|------------|--------------------------------------------| -| id | bigint(20) | 订单的唯一标识 | -| book_id | bigint(20) | 书籍的唯一标识(关联至 [books](#books-表)) | -| user_id | bigint(20) | 用户唯一标识(关联至 [users](#users-表)) | -| quantity | tinyint(4) | 购买数量 | -| ordered_at | datetime | 购买时间 | +| 字段名称 | 类型 | 描述 | +|------------|------------|----------------------------------------------------------------| +| id | bigint(20) | 订单的唯一标识符 | +| book_id | bigint(20) | 图书的唯一标识符(关联到 [books](#books-表)) | +| user_id | bigint(20) | 用户的唯一标识符(关联到 [users](#users-表)) | +| quantity | tinyint(4) | 购买数量 | +| ordered_at | datetime | 购买时间 | -## 数据库初始化 `dbinit.sql` 脚本 +## 数据库初始化脚本 `dbinit.sql` -如果你希望手动创建 Bookshop 应用的数据库表结构,你可以运行以下 SQL 语句: +如果您想手动创建 Bookshop 应用程序的数据库表结构,请运行以下 SQL 语句: ```sql CREATE DATABASE IF NOT EXISTS `bookshop`; @@ -258,3 +290,17 @@ CREATE TABLE `bookshop`.`orders` ( KEY `orders_book_id_idx` (`book_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ``` + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-build-cluster-in-cloud.md b/develop/dev-guide-build-cluster-in-cloud.md index 031cd352268c..eedc568af040 100644 --- a/develop/dev-guide-build-cluster-in-cloud.md +++ b/develop/dev-guide-build-cluster-in-cloud.md @@ -1,135 +1,172 @@ --- -title: 使用 TiDB Cloud Serverless 构建 TiDB 集群 -summary: 使用 TiDB Cloud Serverless 构建 TiDB 集群,并连接 TiDB Cloud Serverless 集群。 +title: 构建 TiDB Cloud Serverless 集群 +summary: 了解如何在 TiDB Cloud 中构建 TiDB Cloud Serverless 集群并连接到它。 --- -# 使用 TiDB Cloud Serverless 构建 TiDB 集群 +# 构建 TiDB Cloud Serverless 集群 -本文将介绍如何以最快的方式开始使用 TiDB。你将创建并启动一个 [TiDB Cloud Serverless](https://www.pingcap.com/tidb-serverless/) 集群,使用 TiDB SQL 客户端,插入数据。随后将从示例程序读取出数据。 + -若你需要在本地计算机上启动 TiDB,请参阅[本地启动 TiDB](/quick-start-with-tidb.md)。 +本文将指导你快速开始使用 TiDB。你将使用 [TiDB Cloud](https://www.pingcap.com/tidb-cloud) 创建一个 TiDB Cloud Serverless 集群,连接到它,并在其上运行示例应用程序。 + +如果你需要在本地机器上运行 TiDB,请参阅[在本地启动 TiDB](/quick-start-with-tidb.md)。 + + + + + +本文将指导你快速开始使用 TiDB Cloud。你将创建一个 TiDB 集群,连接到它,并在其上运行示例应用程序。 + + ## 第 1 步:创建 TiDB Cloud Serverless 集群 -1. 如果你还未拥有 TiDB Cloud 账号,请先在此[注册](https://tidbcloud.com/free-trial)。 -2. 使用你的 TiDB Cloud 账号[登录](https://tidbcloud.com/)。 +1. 如果你还没有 TiDB Cloud 账号,请点击[这里](https://tidbcloud.com/free-trial)注册账号。 + +2. [登录](https://tidbcloud.com/)你的 TiDB Cloud 账号。 + +3. 在[**集群**](https://tidbcloud.com/project/clusters)页面,点击**创建集群**。 + +4. 在**创建集群**页面,默认选择 **Serverless**。根据需要更新默认集群名称,然后选择要创建集群的区域。 - 登录后,默认进入 [**Clusters**](https://tidbcloud.com/console/clusters) 页面。 +5. 点击**创建**来创建 TiDB Cloud Serverless 集群。 -3. 对于新注册的用户,TiDB Cloud 会自动为你创建一个 TiDB Cloud Serverless 集群 `Cluster0`。你可以使用这个默认集群进行后续操作,也可以自行创建一个新的 TiDB Cloud Serverless 集群。 + 你的 TiDB Cloud 集群将在大约 30 秒内创建完成。 - 如果你想创建一个新的 TiDB Cloud Serverless 集群,请进行以下操作: +6. 集群创建完成后,点击集群名称进入集群概览页面,然后点击右上角的**连接**。此时会显示一个连接对话框。 - 1. 点击 **Create Cluster**。 - 2. **Create Cluster** 页面默认选择 **Serverless**。你可以根据需要修改集群名称、选择可用区,然后点击 **Create**。你的 TiDB Cloud Serverless 集群将于 30 秒后创建完毕。 +7. 在对话框中,选择你偏好的连接方式和操作系统,以获取相应的连接字符串。本文以 MySQL 客户端为例。 -4. 点击目标集群名称,进入集群概览页面,然后点击右上角的 **Connect** 按钮,弹出连接对话框。 +8. 点击**生成密码**来生成随机密码。生成的密码不会再次显示,因此请将密码保存在安全的位置。如果你不设置 root 密码,就无法连接到集群。 -5. 在对话框中,选择你需要的连接方式和操作系统并保存对应的连接字符串。下面连接到集群的步骤将以 MySQL 客户端为例。 + -6. 点击 **Generate Password** 生成随机密码。生成的密码不会再次显示,因此请将密码妥善保存。如果没有设置 root 密码,你将无法连接到集群。 +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群,当你连接到集群时,必须在用户名中包含集群的前缀,并用引号将名称括起来。更多信息,请参阅[用户名前缀](https://docs.pingcap.com/tidbcloud/select-cluster-tier#user-name-prefix)。 + + + + + +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群,当你连接到集群时,必须在用户名中包含集群的前缀,并用引号将名称括起来。更多信息,请参阅[用户名前缀](/tidb-cloud/select-cluster-tier.md#user-name-prefix)。 - > **注意:** - > - > 在连接到 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群时,你需要给用户名加上前缀并使用单引号包裹用户名。你可以在 [TiDB Cloud Serverless 用户名前缀](https://docs.pingcap.com/tidbcloud/select-cluster-tier#user-name-prefix) 中获得更多信息。 + ## 第 2 步:连接到集群 -1. 若未安装 MySQL 客户端,请选择自己的操作系统,按以下步骤安装。 +1. 如果未安装 MySQL 客户端,请选择你的操作系统并按照以下步骤进行安装。 - + -
+
- 对于 macOS 操作系统,如果你没有安装 Homebrew,请参考 [Homebrew 官网](https://brew.sh/zh-cn/)进行安装。 +对于 macOS,如果你还没有安装 [Homebrew](https://brew.sh/index),请先安装它,然后运行以下命令来安装 MySQL 客户端: - ```shell - brew install mysql-client - ``` +```shell +brew install mysql-client +``` - 在安装完成的命令行输出中,得到以下信息: +输出如下: - ``` - mysql-client is keg-only, which means it was not symlinked into /opt/homebrew, - because it conflicts with mysql (which contains client libraries). +``` +mysql-client is keg-only, which means it was not symlinked into /opt/homebrew, +because it conflicts with mysql (which contains client libraries). - If you need to have mysql-client first in your PATH, run: - echo 'export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH"' >> ~/.zshrc +If you need to have mysql-client first in your PATH, run: + echo 'export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH"' >> ~/.zshrc - For compilers to find mysql-client you may need to set: - export LDFLAGS="-L/opt/homebrew/opt/mysql-client/lib" - export CPPFLAGS="-I/opt/homebrew/opt/mysql-client/include" - ``` +For compilers to find mysql-client you may need to set: + export LDFLAGS="-L/opt/homebrew/opt/mysql-client/lib" + export CPPFLAGS="-I/opt/homebrew/opt/mysql-client/include" +``` - 请运行其中的此行(命令行输出若与此处文档不一致,请以命令行输出为准): +要将 MySQL 客户端添加到你的 PATH 中,请在上述输出中找到以下命令(如果你的输出与文档中的上述输出不一致,请使用你的输出中相应的命令)并运行它: - ```shell - echo 'export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH"' >> ~/.zshrc - ``` +```shell +echo 'export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH"' >> ~/.zshrc +``` - 完成后,生效该配置文件(例如 `~/.zshrc`),并验证 MySQL 客户端是否安装成功: +然后,使用 `source` 命令声明全局环境变量,并验证 MySQL 客户端是否安装成功: - ```shell - source ~/.zshrc - mysql --version - ``` +```shell +source ~/.zshrc +mysql --version +``` - 预期会得到形如以下的输出: +预期输出示例: - ``` - mysql Ver 8.0.28 for macos12.0 on arm64 (Homebrew) - ``` +``` +mysql Ver 8.0.28 for macos12.0 on arm64 (Homebrew) +``` -
+
-
+
- 对于 Linux 操作系统,下面以 CentOS 7 为例: +对于 Linux,以下以 CentOS 7 为例: - ```shell - yum install mysql - ``` +```shell +yum install mysql +``` - 完成后,请验证 MySQL 客户端是否安装成功: +然后,验证 MySQL 客户端是否安装成功: - ```shell - mysql --version - ``` +```shell +mysql --version +``` - 预期会得到形如以下的输出: +预期输出示例: - ``` - mysql Ver 15.1 Distrib 5.5.68-MariaDB, for Linux (x86_64) using readline 5.1 - ``` +``` +mysql Ver 15.1 Distrib 5.5.68-MariaDB, for Linux (x86_64) using readline 5.1 +``` + +
-
+
-
+2. 运行在[第 1 步](#第-1-步创建-tidb-cloud-serverless-集群)中获取的连接字符串。 -2. 运行第 1 步中得到的连接字符串。 + {{< copyable "shell-regular" >}} ```shell mysql --connect-timeout 15 -u '.root' -h -P 4000 -D test --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p ``` + + > **注意:** > -> - 在连接 TiDB Cloud Serverless 集群时,[必须使用 TLS 连接](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-tier-clusters)。 -> - 如果你在连接时遇到问题,可阅读 [TiDB Cloud Serverless 集群安全连接](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-tier-clusters) 来获得更多信息。 +> - 连接到 TiDB Cloud Serverless 集群时,你必须[使用 TLS 连接](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters)。 +> - 如果你在连接 TiDB Cloud Serverless 集群时遇到问题,可以阅读[连接到 TiDB Cloud Serverless 集群的安全连接](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters)获取更多信息。 + + + + + +> **注意:** +> +> - 连接到 TiDB Cloud Serverless 集群时,你必须[使用 TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md)。 +> - 如果你在连接 TiDB Cloud Serverless 集群时遇到问题,可以阅读[连接到 TiDB Cloud Serverless 集群的安全连接](/tidb-cloud/secure-connections-to-serverless-clusters.md)获取更多信息。 + + -3. 填写密码,完成登录。 +3. 输入密码以登录。 -## 第 3 步:运行 SQL +## 第 3 步:执行 SQL 语句 -尝试运行一下你在 TiDB Cloud 上的的第一个 SQL 吧: +让我们尝试在 TiDB Cloud 上执行你的第一条 SQL 语句。 ```sql SELECT 'Hello TiDB Cloud!'; ``` -你将看到这样的输出: +预期输出: ```sql +-------------------+ @@ -139,4 +176,18 @@ SELECT 'Hello TiDB Cloud!'; +-------------------+ ``` -如果你的实际输出与预期输出一致,表示你已经在 TiDB Cloud 上成功地运行了 SQL 语句。 +如果你的实际输出与预期输出类似,恭喜你已经成功在 TiDB Cloud 上执行了一条 SQL 语句。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-choose-driver-or-orm.md b/develop/dev-guide-choose-driver-or-orm.md index 0e56b01bcf57..df6730533001 100644 --- a/develop/dev-guide-choose-driver-or-orm.md +++ b/develop/dev-guide-choose-driver-or-orm.md @@ -1,50 +1,50 @@ --- -title: 选择驱动或 ORM 框架 -summary: 选择驱动或 ORM 框架连接 TiDB。 +title: 选择驱动或 ORM +summary: 了解如何选择驱动或 ORM 框架来连接 TiDB。 --- -# 选择驱动或 ORM 框架 +# 选择驱动或 ORM > **注意:** > -> TiDB 支持等级说明: +> TiDB 为驱动和 ORM 提供以下两个支持级别: > -> - **Full**:表明 TiDB 已经兼容该工具的绝大多数功能,并且在该工具的新版本中对其保持兼容。PingCAP 将定期地对 [TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md)中的新版本进行兼容性测试。 -> - **Compatible**:表明由于该工具已适配 MySQL,而 TiDB 高度兼容 MySQL 协议,因此 TiDB 可以兼容该工具的大部分功能。但 PingCAP 并未对该工具作出完整的兼容性验证,有可能出现一些意外的行为。 +> - **完全支持**:表示 TiDB 与该工具的大多数功能兼容,并保持与其新版本的兼容性。PingCAP 会定期对[TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md)的最新版本进行兼容性测试。 +> - **兼容**:表示由于相应的第三方工具适配了 MySQL,而 TiDB 与 MySQL 协议高度兼容,因此 TiDB 可以使用该工具的大多数功能。但是,PingCAP 尚未对该工具的所有功能进行完整测试,这可能会导致一些意外行为。 > -> 关于更多 TiDB 支持的第三方工具,你可以查看 [TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md)。 +> 更多信息,请参考 [TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md)。 -TiDB 兼容 MySQL 的协议,但存在部分与 MySQL 不兼容或有差异的特性,具体信息可查看[与 MySQL 兼容性对比](/mysql-compatibility.md)。 +TiDB 与 MySQL 协议高度兼容,但某些功能与 MySQL 不兼容。有关兼容性差异的完整列表,请参阅 [MySQL 兼容性](/mysql-compatibility.md)。 ## Java -本节介绍 Java 语言的 Driver 及 ORM 的使用方式。 +本节介绍如何在 Java 中使用驱动和 ORM 框架。 -### Java Drivers +### Java 驱动
-支持等级:**Full** +支持级别:**完全支持** -按照 [MySQL 文档](https://dev.mysql.com/doc/connector-j/en/)中的说明下载并配置 Java JDBC 驱动程序即可使用。对于 TiDB v6.3.0 及以上版本,建议使用 MySQL Connector/J 最新 GA 版本。 +你可以按照 [MySQL 文档](https://dev.mysql.com/doc/connector-j/)下载和配置 Java JDBC 驱动。建议在 TiDB v6.3.0 或更高版本中使用最新的 GA 版本 MySQL Connector/J。 > **警告:** > -> 在 8.0.31 及之前的 MySQL Connector/J 8.0 版本中存在一个 [bug](https://bugs.mysql.com/bug.php?id=106252)(详见 [MySQL JDBC Bug](/develop/dev-guide-third-party-tools-compatibility.md#mysql-jdbc-bug)),当与 TiDB v6.3.0 之前的版本一起使用时,可能会导致线程卡死。为了避免此问题,请**勿**使用 MySQL Connector/J 8.0.31 或更低版本。 +> MySQL Connector/J 8.0.31 之前的 8.0 版本中存在一个[错误](https://bugs.mysql.com/bug.php?id=106252)(详见 [MySQL JDBC 错误](/develop/dev-guide-third-party-tools-compatibility.md#mysql-jdbc-bugs)),在使用早于 v6.3.0 的 TiDB 版本时可能会导致线程挂起。为避免此问题,请**不要**使用 MySQL Connector/J 8.0.31 或更早版本。 -有关一个完整的实例应用程序,可参阅 [TiDB 和 JDBC 的简单 CRUD 应用程序](/develop/dev-guide-sample-application-java-jdbc.md)。 +有关如何构建完整应用程序的示例,请参阅[使用 TiDB 和 JDBC 构建简单的 CRUD 应用程序](/develop/dev-guide-sample-application-java-jdbc.md)。
-支持等级:**Full** +支持级别:**完全支持** -[TiDB-JDBC](https://github.com/pingcap/mysql-connector-j) 是基于 MySQL 8.0.29 的定制版本。TiDB-JDBC 基于 MySQL 官方 8.0.29 版本编译,修复了原 JDBC 在 prepare 模式下多参数、多字段 EOF 的错误,并新增 TiCDC snapshot 自动维护和 SM3 认证插件等功能。 +[TiDB-JDBC](https://github.com/pingcap/mysql-connector-j) 是基于 MySQL 8.0.29 的定制 Java 驱动。TiDB-JDBC 基于 MySQL 官方版本 8.0.29 编译,修复了原始 JDBC 在预处理模式下多参数和多字段 EOF 的错误,并添加了自动 TiCDC 快照维护和 SM3 认证插件等功能。 基于 SM3 的认证仅在 TiDB 的 TiDB-JDBC 中支持。 -如果你使用的是 Maven,请将以下内容添加到你的 ``: +如果你使用 Maven,请在 `pom.xml` 文件的 `` 部分添加以下内容: ```xml @@ -54,7 +54,7 @@ TiDB 兼容 MySQL 的协议,但存在部分与 MySQL 不兼容或有差异的 ``` -如果你需要使用 SM3 认证,请将以下内容添加到你的 ``: +如果你需要启用 SM3 认证,请在 `pom.xml` 文件的 `` 部分添加以下内容: ```xml @@ -74,7 +74,7 @@ TiDB 兼容 MySQL 的协议,但存在部分与 MySQL 不兼容或有差异的 ``` -如果你使用的是 Gradle,请将以下内容添加到你的 `dependencies`: +如果你使用 Gradle,请在 `dependencies` 中添加以下内容: ```gradle implementation group: 'io.github.lastincisor', name: 'mysql-connector-java', version: '8.0.29-tidb-1.0.0' @@ -92,14 +92,15 @@ implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: '1.67 > **注意:** > -> - Hibernate 当前[不支持嵌套事务](https://stackoverflow.com/questions/37927208/nested-transaction-in-spring-app-with-jpa-postgres)。 -> - TiDB 从 v6.2.0 版本开始支持 [Savepoint](/sql-statements/sql-statement-savepoint.md)。如需在 `@Transactional` 中使用 `Propagation.NESTED` 事务传播选项,即 `@Transactional(propagation = Propagation.NESTED)`,请确认你的 TiDB 版本为 v6.2.0 或以上。 +> - 目前,Hibernate [不支持嵌套事务](https://stackoverflow.com/questions/37927208/nested-transaction-in-spring-app-with-jpa-postgres)。 +> +> - 从 v6.2.0 开始,TiDB 支持[保存点](/sql-statements/sql-statement-savepoint.md)。要在 `@Transactional` 中使用 `Propagation.NESTED` 事务传播选项,即设置 `@Transactional(propagation = Propagation.NESTED)`,请确保你的 TiDB 是 v6.2.0 或更高版本。 -支持等级:**Full** +支持级别:**完全支持** -你可以使用 [Gradle](https://gradle.org/install) 或 [Maven](https://maven.apache.org/install.html) 获取你的应用程序的所有依赖项,且会帮你下载依赖项的间接依赖,而无需你手动管理复杂的依赖关系。注意,只有 Hibernate `6.0.0.Beta2` 及以上版本才支持 TiDB 方言。 +为避免手动管理应用程序不同依赖项之间的复杂关系,你可以使用 [Gradle](https://gradle.org/install) 或 [Maven](https://maven.apache.org/install.html) 获取应用程序的所有依赖项,包括那些间接依赖项。请注意,只有 Hibernate `6.0.0.Beta2` 或更高版本支持 TiDB 方言。 -如果你使用的是 Maven,请将以下内容添加到你的 ``: +如果你使用 Maven,请在 `` 中添加以下内容: ```xml @@ -115,27 +116,31 @@ implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: '1.67 ``` -如果你使用的是 Gradle,请将以下内容添加到你的 `dependencies`: +如果你使用 Gradle,请在 `dependencies` 中添加以下内容: ```gradle implementation 'org.hibernate:hibernate-core:6.2.3.Final' implementation 'mysql:mysql-connector-java:8.0.33' ``` -- 有关原生 Java 使用 Hibernate 进行 TiDB 应用程序构建的例子,可参阅 [TiDB 和 Hibernate 的简单 CRUD 应用程序](/develop/dev-guide-sample-application-java-hibernate.md)。 -- 有关 Spring 使用 Spring Data JPA、Hibernate 进行 TiDB 应用程序构建的例子,可参阅[使用 Spring Boot 构建 TiDB 应用程序](/develop/dev-guide-sample-application-java-spring-boot.md)。 +- 有关使用原生 Java 的 Hibernate 构建 TiDB 应用程序的示例,请参阅[使用 TiDB 和 Hibernate 构建简单的 CRUD 应用程序](/develop/dev-guide-sample-application-java-hibernate.md)。 +- 有关使用 Spring Data JPA 或 Hibernate 通过 Spring 构建 TiDB 应用程序的示例,请参阅[使用 Spring Boot 构建 TiDB 应用程序](/develop/dev-guide-sample-application-java-spring-boot.md)。 -额外的,你需要在 [Hibernate 配置文件](https://www.tutorialspoint.com/hibernate/hibernate_configuration.htm)中指定 TiDB 方言 `org.hibernate.dialect.TiDBDialect`,此方言在 Hibernate `6.0.0.Beta2` 以上才可支持。若你无法升级 Hibernate 版本,那么请你直接使用 MySQL 5.7 的方言 `org.hibernate.dialect.MySQL57Dialect`。但这可能造成不可预料的使用结果,及部分 TiDB 特有特性的缺失,如:[序列](/sql-statements/sql-statement-create-sequence.md)等。 +此外,你需要在 [Hibernate 配置文件](https://www.tutorialspoint.com/hibernate/hibernate_configuration.htm)中指定 TiDB 方言:`org.hibernate.dialect.TiDBDialect`,该方言仅在 Hibernate `6.0.0.Beta2` 或更高版本中支持。如果你的 `Hibernate` 版本早于 `6.0.0.Beta2`,请先升级。 + +> **注意:** +> +> 如果你无法升级 `Hibernate` 版本,请使用 MySQL 5.7 方言 `org.hibernate.dialect.MySQL57Dialect` 代替。但是,此设置可能会导致不可预测的结果,并且缺少一些 TiDB 特有的功能,例如[序列](/sql-statements/sql-statement-create-sequence.md)。
-支持等级:**Full** +支持级别:**完全支持** -你可以使用 [Gradle](https://gradle.org/install) 或 [Maven](https://maven.apache.org/install.html) 获取应用程序的所有依赖项包括间接依赖,无需手动管理复杂的依赖关系。 +为避免手动管理应用程序不同依赖项之间的复杂关系,你可以使用 [Gradle](https://gradle.org/install) 或 [Maven](https://maven.apache.org/install.html) 获取应用程序的所有依赖项,包括那些间接依赖项。 -如果你使用的是 Maven,请将以下内容添加到你的 ``: +如果你使用 Maven,请在 `` 中添加以下内容: ```xml @@ -151,14 +156,14 @@ implementation 'mysql:mysql-connector-java:8.0.33' ``` -如果你使用的是 Gradle,请将以下内容添加到你的 `dependencies`: +如果你使用 Gradle,请在 `dependencies` 中添加以下内容: ```gradle implementation 'org.mybatis:mybatis:3.5.13' implementation 'mysql:mysql-connector-java:8.0.33' ``` -使用 MyBatis 进行 TiDB 应用程序构建的例子,可参阅 [TiDB 和 MyBatis 的简单 CRUD 应用程序](/develop/dev-guide-sample-application-java-mybatis.md)。 +有关使用 MyBatis 构建 TiDB 应用程序的示例,请参阅[使用 TiDB 和 MyBatis 构建简单的 CRUD 应用程序](/develop/dev-guide-sample-application-java-mybatis.md)。
@@ -168,17 +173,17 @@ implementation 'mysql:mysql-connector-java:8.0.33' **tidb-loadbalance** -支持等级:**Full** +支持级别:**完全支持** -[tidb-loadbalance](https://github.com/pingcap/tidb-loadbalance) 是应用端的负载均衡组件。通过 tidb-loadbalance,你可以实现自动维护 TiDB server 的节点信息,根据节点信息使用 tidb-loadbalance 策略在客户端分发 JDBC 连接。客户端应用与 TiDB server 之间使用 JDBC 直连,性能高于使用负载均衡组件。 +[tidb-loadbalance](https://github.com/pingcap/tidb-loadbalance) 是应用程序端的负载均衡组件。使用 tidb-loadbalance,你可以自动维护 TiDB 服务器的节点信息,并使用 tidb-loadbalance 策略在客户端分配 JDBC 连接。客户端应用程序和 TiDB 服务器之间使用直接 JDBC 连接的性能比使用负载均衡组件更高。 -目前 tidb-loadbalance 已实现轮询、随机、权重等负载均衡策略。 +目前,tidb-loadbalance 支持以下策略:轮询、随机和权重。 > **注意:** > -> tidb-loadbalance 需配合 mysql-connector-j 一起使用。 +> tidb-loadbalance 必须与 [mysql-connector-j](https://github.com/pingcap/mysql-connector-j) 一起使用。 -如果你使用的是 Maven,请将以下内容添加到你的 ``: +如果你使用 Maven,请在 `pom.xml` 文件的 `` 元素体中添加以下内容: ```xml @@ -193,7 +198,7 @@ implementation 'mysql:mysql-connector-java:8.0.33' ``` -如果你使用的是 Gradle,请将以下内容添加到你的 `dependencies`: +如果你使用 Gradle,请在 `dependencies` 中添加以下内容: ```gradle implementation group: 'io.github.lastincisor', name: 'mysql-connector-java', version: '8.0.29-tidb-1.0.0' @@ -202,65 +207,65 @@ implementation group: 'io.github.lastincisor', name: 'tidb-loadbalance', version ## Golang -本节介绍 Golang 语言的 Driver 及 ORM 的使用方式。 +本节介绍如何在 Golang 中使用驱动和 ORM 框架。 -### Golang Drivers +### Golang 驱动 **go-sql-driver/mysql** -支持等级:**Full** +支持级别:**完全支持** -按照 [go-sql-driver/mysql 文档](https://github.com/go-sql-driver/mysql)中的说明获取并配置 Golang 驱动程序即可使用。 +要下载和配置 Golang 驱动,请参考 [go-sql-driver/mysql 文档](https://github.com/go-sql-driver/mysql)。 -有关一个完整的实例应用程序,可参阅[使用 Go-MySQL-Driver 连接到 TiDB](/develop/dev-guide-sample-application-golang-sql-driver.md)。 +有关如何构建完整应用程序的示例,请参阅[使用 Go-MySQL-Driver 连接到 TiDB](/develop/dev-guide-sample-application-golang-sql-driver.md)。 ### Golang ORM 框架 **GORM** -支持等级:**Full** +支持级别:**完全支持** -GORM 是一个流行的 Golang 的 ORM 框架,你可以使用 `go get` 获取你的应用程序的所有依赖项。 +GORM 是一个流行的 Golang ORM 框架。要获取应用程序中的所有依赖项,你可以使用 `go get` 命令。 ```shell go get -u gorm.io/gorm go get -u gorm.io/driver/mysql ``` -使用 GORM 进行 TiDB 应用程序构建的例子,可参阅[使用 GORM 连接到 TiDB](/develop/dev-guide-sample-application-golang-gorm.md)。 +有关使用 GORM 构建 TiDB 应用程序的示例,请参阅[使用 GORM 连接到 TiDB](/develop/dev-guide-sample-application-golang-gorm.md)。 ## Python -本节介绍 Python 语言的 Driver 及 ORM 的使用方式。 +本节介绍如何在 Python 中使用驱动和 ORM 框架。 -### Python Drivers +### Python 驱动
-支持等级:**Compatible** +支持级别:**兼容** -按照 [PyMySQL 文档](https://pypi.org/project/PyMySQL/)中的说明下载并配置驱动程序即可使用。建议使用 **1.0.2** 及以上版本。 +你可以按照 [PyMySQL 文档](https://pypi.org/project/PyMySQL/)下载和配置驱动。建议使用 PyMySQL 1.0.2 或更高版本。 -使用 PyMySQL 构建 TiDB 应用程序的例子,可参阅[使用 PyMySQL 连接到 TiDB](/develop/dev-guide-sample-application-python-pymysql.md)。 +有关使用 PyMySQL 构建 TiDB 应用程序的示例,请参阅[使用 PyMySQL 连接到 TiDB](/develop/dev-guide-sample-application-python-pymysql.md)。
-支持等级:**Compatible** +支持级别:**兼容** -按照 [mysqlclient 文档](https://pypi.org/project/mysqlclient/)中的说明下载并配置驱动程序即可使用。建议使用 **2.1.1** 及以上版本。 +你可以按照 [mysqlclient 文档](https://pypi.org/project/mysqlclient/)下载和配置驱动。建议使用 mysqlclient 2.1.1 或更高版本。 -使用 mysqlclient 构建 TiDB 应用程序的例子,可参阅[使用 mysqlclient 连接到 TiDB](/develop/dev-guide-sample-application-python-mysqlclient.md)。 +有关使用 mysqlclient 构建 TiDB 应用程序的示例,请参阅[使用 mysqlclient 连接到 TiDB](/develop/dev-guide-sample-application-python-mysqlclient.md)。
-支持等级:**Compatible** +支持级别:**兼容** -按照 [MySQL Connector/Python 文档](https://dev.mysql.com/doc/connector-python/en/connector-python-installation-binary.html)中的说明下载并配置驱动程序即可使用。建议使用 **8.0.31** 及以上版本。 +你可以按照 [MySQL Connector/Python 文档](https://dev.mysql.com/doc/connector-python/en/connector-python-installation-binary.html)下载和配置驱动。建议使用 Connector/Python 8.0.31 或更高版本。 -使用 MySQL Connector/Python 构建 TiDB 应用程序的例子,可参阅[使用 MySQL Connector/Python 连接到 TiDB](/develop/dev-guide-sample-application-python-mysql-connector.md)。 +有关使用 MySQL Connector/Python 构建 TiDB 应用程序的示例,请参阅[使用 MySQL Connector/Python 连接到 TiDB](/develop/dev-guide-sample-application-python-mysql-connector.md)。
@@ -268,35 +273,51 @@ go get -u gorm.io/driver/mysql ### Python ORM 框架 -
-支持等级:**Full** +支持级别:**完全支持** -[Django](https://docs.djangoproject.com/) 是一个流行的 Python Web 开发框架。为解决 TiDB 与 Django 的兼容性问题,PingCAP 开发了一个专门的适配器 `django-tidb`。你可以参考 [`django-tidb` 文档](https://github.com/pingcap/django-tidb#installation-guide)进行安装。 +[Django](https://docs.djangoproject.com/) 是一个流行的 Python Web 框架。为解决 TiDB 和 Django 之间的兼容性问题,PingCAP 提供了 TiDB 方言 `django-tidb`。要安装它,你可以参考 [`django-tidb` 文档](https://github.com/pingcap/django-tidb#installation-guide)。 -使用 Django 构建 TiDB 应用程序的例子,可参阅[使用 Django 连接到 TiDB](/develop/dev-guide-sample-application-python-django.md)。 +有关使用 Django 构建 TiDB 应用程序的示例,请参阅[使用 Django 连接到 TiDB](/develop/dev-guide-sample-application-python-django.md)。
-
-支持等级:**Full** +支持级别:**完全支持** -[SQLAlchemy](https://www.sqlalchemy.org/) 是一个流行的 Python 的 ORM 框架,你可以使用 `pip install SQLAlchemy==1.4.44` 获取你的应用程序的所有依赖项。建议使用 **1.4.44** 及以上版本。 +[SQLAlchemy](https://www.sqlalchemy.org/) 是一个流行的 Python ORM 框架。要获取应用程序中的所有依赖项,你可以使用 `pip install SQLAlchemy==1.4.44` 命令。建议使用 SQLAlchemy 1.4.44 或更高版本。 -使用 SQLAlchemy 构建 TiDB 应用程序的例子,可参阅[使用 SQLAlchemy 连接到 TiDB](/develop/dev-guide-sample-application-python-sqlalchemy.md)。 +有关使用 SQLAlchemy 构建 TiDB 应用程序的示例,请参阅[使用 SQLAlchemy 连接到 TiDB](/develop/dev-guide-sample-application-python-sqlalchemy.md)。
-
-支持等级:**Compatible** +支持级别:**兼容** -[peewee](http://docs.peewee-orm.com/en/latest/) 是一个流行的 Python 的 ORM 框架,你可以使用 `pip install peewee==3.15.4` 获取你的应用程序的所有依赖项。建议使用 **3.15.4** 及以上版本。 +[peewee](http://docs.peewee-orm.com/en/latest/) 是一个流行的 Python ORM 框架。要获取应用程序中的所有依赖项,你可以使用 `pip install peewee==3.15.4` 命令。建议使用 peewee 3.15.4 或更高版本。 -使用 peewee 构建 TiDB 应用程序的例子,可参阅[使用 peewee 连接到 TiDB](/develop/dev-guide-sample-application-python-peewee.md)。 +有关使用 peewee 构建 TiDB 应用程序的示例,请参阅[使用 peewee 连接到 TiDB](/develop/dev-guide-sample-application-python-peewee.md)。
-
+ + + +在确定了驱动或 ORM 之后,你可以[连接到你的 TiDB 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + + + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-connection-parameters.md b/develop/dev-guide-connection-parameters.md index b71fea7d0603..3170824be58d 100644 --- a/develop/dev-guide-connection-parameters.md +++ b/develop/dev-guide-connection-parameters.md @@ -1,69 +1,81 @@ --- -title: 连接池与连接参数 -summary: 针对开发者的 TiDB 连接池与连接参数的说明。 +title: 连接池和连接参数 +summary: 本文介绍如何配置 TiDB 的连接池和参数。涵盖了连接池大小、探测配置和最佳吞吐量公式。还讨论了 JDBC API 的使用和 MySQL Connector/J 参数配置以优化性能。 --- -# 连接池与连接参数 +# 连接池和连接参数 -> - 连接池参数 - 连接数配置、探活配置两节摘自[开发 Java 应用使用 TiDB 的最佳实践 - 连接池](/best-practices/java-app-best-practices.md#连接池)。 -> - 连接参数摘自[开发 Java 应用使用 TiDB 的最佳实践 - JDBC](/best-practices/java-app-best-practices.md#jdbc)。 +本文介绍在使用驱动或 ORM 框架连接 TiDB 时如何配置连接池和连接参数。 -## 连接池参数 + -TiDB (MySQL) 连接建立是比较昂贵的操作(至少对于 OLTP 来讲),除了建立 TCP 连接外还需要进行连接鉴权操作,所以客户端通常会把 TiDB (MySQL) 连接保存到连接池中进行复用。 +如果你对 Java 应用程序开发的更多技巧感兴趣,请参阅[使用 TiDB 开发 Java 应用的最佳实践](/best-practices/java-app-best-practices.md#connection-pool)。 -Java 的连接池实现很多 ([HikariCP](https://github.com/brettwooldridge/HikariCP), [tomcat-jdbc](https://tomcat.apache.org/tomcat-10.1-doc/jdbc-pool.html), [druid](https://github.com/alibaba/druid), [c3p0](https://www.mchange.com/projects/c3p0/), [dbcp](https://commons.apache.org/proper/commons-dbcp/)),TiDB 不会限定使用的连接池,应用可以根据业务特点自行选择连接池实现。 + -### 连接数配置 + -比较常见的是应用需要根据自身情况配置合适的连接池大小,以 HikariCP 为例: +如果你对 Java 应用程序开发的更多技巧感兴趣,请参阅[使用 TiDB 开发 Java 应用的最佳实践](https://docs.pingcap.com/tidb/stable/java-app-best-practices)。 -**maximumPoolSize**:连接池最大连接数,配置过大会导致 TiDB 消耗资源维护无用连接,配置过小则会导致应用获取连接变慢,所以需根据应用自身特点配置合适的值,可参考[这篇文章](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing)。 + -**minimumIdle**:连接池最小空闲连接数,主要用于在应用空闲时存留一些连接以应对突发请求,同样是需要根据业务情况进行配置。 +## 连接池 -应用在使用连接池时,需要注意连接使用完成后归还连接,推荐应用使用对应的连接池相关监控(如 **metricRegistry**),通过监控能及时定位连接池问题。 +建立 TiDB (MySQL) 连接的成本相对较高(至少对于 OLTP 场景而言)。因为除了建立 TCP 连接外,还需要进行连接认证。因此,客户端通常会将 TiDB (MySQL) 连接保存到连接池中以重复使用。 -### 探活配置 +Java 有许多连接池实现,如 [HikariCP](https://github.com/brettwooldridge/HikariCP)、[tomcat-jdbc](https://tomcat.apache.org/tomcat-10.1-doc/jdbc-pool.html)、[druid](https://github.com/alibaba/druid)、[c3p0](https://www.mchange.com/projects/c3p0/) 和 [dbcp](https://commons.apache.org/proper/commons-dbcp/)。TiDB 不限制你使用哪种连接池,因此你可以根据应用程序的需要选择任何一种。 -连接池维护客户端到 TiDB 的长连接的方式如下: +### 配置连接数量 -- v5.4 版本前,TiDB 默认不会主动关闭客户端连接,除非出现报错情况。 -- 从 v5.4 起,TiDB 默认会在连接空闲超过 `28800` 秒(即 8 小时)后,自动关闭客户端连接。你可以使用 TiDB 与 MySQL 兼容的 `wait_timeout` 变量控制此超时时间,详见 [JDBC 查询超时](/develop/dev-guide-timeouts-in-tidb.md#jdbc-查询超时)文档。 +根据应用程序自身需求调整连接池大小是一种常见做法。以 HikariCP 为例: -此外,客户端到 TiDB 之间通常还会有 [LVS](https://en.wikipedia.org/wiki/Linux_Virtual_Server) 或 [HAProxy](https://en.wikipedia.org/wiki/HAProxy) 之类的网络代理。这些代理通常会在连接空闲超过特定时间(由代理的 idle 配置决定)后主动清理连接。除了关注代理的 idle 配置外,连接池还需要进行保活或探测连接。 +- **maximumPoolSize**:连接池中的最大连接数。如果这个值太大,TiDB 会消耗资源来维护无用的连接。如果这个值太小,应用程序获取连接的速度会变慢。因此,你需要根据应用程序特点来配置这个值。详情请参阅[关于连接池大小](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing)。 +- **minimumIdle**:连接池中的最小空闲连接数。主要用于在应用程序空闲时保留一些连接以响应突发请求。你也需要根据应用程序特点来配置它。 -如果常在 Java 应用中看到以下错误: +应用程序在使用完连接后需要归还连接。建议应用程序使用相应的连接池监控(如 **metricRegistry**)来及时定位连接池问题。 + +### 探测配置 + +连接池维护从客户端到 TiDB 的持久连接,具体如下: + +- 在 v5.4 之前,TiDB 默认不会主动关闭客户端连接(除非报错)。 +- 从 v5.4 开始,TiDB 默认会在连接空闲 `28800` 秒(即 `8` 小时)后自动关闭客户端连接。你可以使用 TiDB 和 MySQL 兼容的 `wait_timeout` 变量来控制这个超时设置。更多信息,请参阅 [JDBC 查询超时](/develop/dev-guide-timeouts-in-tidb.md#jdbc-query-timeout)。 + +此外,客户端和 TiDB 之间可能存在网络代理,如 [LVS](https://en.wikipedia.org/wiki/Linux_Virtual_Server) 或 [HAProxy](https://en.wikipedia.org/wiki/HAProxy)。这些代理通常会在特定空闲时间后(由代理的空闲配置决定)主动清理连接。除了监控代理的空闲配置外,连接池还需要维护或探测连接以保持活跃。 + +如果你在 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 配置,还可以让连接池执行以下操作: +如果 `n milliseconds ago` 中的 `n` 是 `0` 或一个很小的值,通常是因为执行的 SQL 操作导致 TiDB 异常退出。建议检查 TiDB stderr 日志以找出原因。 + +如果 `n` 是一个很大的值(如上例中的 `3600000`),很可能是这个连接空闲了很长时间后被代理关闭。通常的解决方案是增加代理的空闲配置值,并允许连接池: - 每次使用连接前检查连接是否可用。 -- 使用单独线程定期检查连接是否可用。 -- 定期发送 test query 保活连接。 +- 使用单独的线程定期检查连接是否可用。 +- 定期发送测试查询以保持连接活跃。 -不同的连接池实现可能会支持其中一种或多种方式,可以查看所使用的连接池文档来寻找对应配置。 +不同的连接池实现可能支持上述一种或多种方法。你可以查看连接池文档以找到相应的配置。 ### 经验公式 -在 HikariCP 的 [About Pool Sizing](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing) 一文中可以了解到,在完全不知道如何设置数据库连接池大小的时候,可以考虑以以下[经验公式](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing#connections--core_count--2--effective_spindle_count)为起点,在此基础上,围绕该结果进行尝试,以得到最高性能的连接池大小。 +根据 HikariCP 的[关于连接池大小](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing)文章,如果你不知道如何为数据库连接池设置合适的大小,可以从[经验公式](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing#connections--core_count--2--effective_spindle_count)开始。然后,根据公式计算出的连接池大小的性能结果,进一步调整大小以达到最佳性能。 -该经验公式描述如下: +经验公式如下: ``` connections = ((core_count * 2) + effective_spindle_count) ``` -解释一下参数含义: +公式中各参数的说明如下: -- **connections**: 得出的连接数大小。 -- **core_count**: CPU 核心数。 -- **effective_spindle_count**: 直译为**有效主轴数**,实际上是说你有多少个硬盘(非 [SSD](https://en.wikipedia.org/wiki/Solid-state_drive)),因为每个旋转的硬盘可以被称为是一个旋转轴。例如,你使用的是一个有 16 个磁盘组成的 [RAID](https://en.wikipedia.org/wiki/RAID) 阵列的服务器,那么 **effective_spindle_count** 应为 16。此处经验公式,实际上是衡量你的服务器可以管理多少 I/O 并发请求,因为 **HDD** 通常只能串行请求。 +- **connections**:获得的连接数大小。 +- **core_count**:CPU 核心数。 +- **effective_spindle_count**:硬盘数量(不是 [SSD](https://en.wikipedia.org/wiki/Solid-state_drive))。因为每个旋转硬盘可以称为一个主轴。例如,如果你使用的是具有 16 个磁盘的 RAID 服务器,那么 **effective_spindle_count** 应该是 16。因为 **HDD** 通常一次只能处理一个请求,这里的公式实际上是在衡量你的服务器可以管理多少个并发 I/O 请求。 -要特别说明的是,在这个经验公式的的下方,也看到了一处说明: +特别注意[公式](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing#the-formula)下面的说明。 > ``` > A formula which has held up pretty well across a lot of benchmarks for years is @@ -75,108 +87,130 @@ connections = ((core_count * 2) + effective_spindle_count) > how well the formula works with SSDs. > ``` -这个说明指出: +这个说明表明: -1. **core_count** 就是_物理核心数_,与你是否开启[超线程](https://en.wikipedia.org/wiki/Hyper-threading)无关。 -2. 数据被全量缓存时,**effective_spindle_count** 应被设置为 0,随着命中率的下降,会更加接近实际的 HDD 个数。 -3. **这里没有任何基于 _SSD_ 的经验公式。** +- **core_count** 是物理核心数,无论你是否启用了 [Hyper-Threading](https://en.wikipedia.org/wiki/Hyper-threading)。 +- 当数据完全缓存时,需要将 **effective_spindle_count** 设置为 `0`。随着缓存命中率的降低,该数值会接近实际的 `HDD` 数量。 +- **该公式对 _SSD_ 的适用性尚未测试,未知。** -这里的说明让你在使用 SSD 时,需探求其他的经验公式。 - -可以参考 CockroachDB 对[数据库连接池](https://www.cockroachlabs.com/docs/stable/connection-pooling.html?#sizing-connection-pools)中的描述,推荐的连接数大小公式为: +在使用 SSD 时,建议使用以下经验公式代替: ``` -connections = (number of cores * 4) +connections = (核心数 * 4) ``` -因此,你在使用 SSD 的情况下可以将连接数设置为 `CPU 核心数 * 4`。以此来达到初始的连接池最大连接数大小,并以此数据周围进行进一步的调整。 +因此,在使用 SSD 的情况下,你可以将初始连接池的最大连接数设置为 `核心数 * 4`,然后进一步调整大小以优化性能。 -### 调整方向 +### 调优方向 -可以看到,在上方的[经验公式](#经验公式)中得到的,是一个推荐的初始值,若需得到某台具体机器上的最佳值,需在推荐值周围,通过尝试,得到最佳值。 +如你所见,从[经验公式](#经验公式)计算出的大小只是一个推荐的基准值。要在特定机器上获得最佳大小,你需要尝试基准值附近的其他值并测试性能。 -此最佳值的获取,会有一些基本规律,此处罗列如下: +以下是一些基本规则,可以帮助你获得最佳大小: -1. 如果你的网络或存储延迟较大,请增大你的最大连接数,可以进行等待,从而让线程在被阻塞时,其他的线程可继续进行处理。 -2. 如果你的服务器上部署了多个服务,并且每个服务拥有独立的连接池时,请关注它们的连接池的最大连接数总和。 +- 如果你的网络或存储延迟较高,增加最大连接数以减少延迟等待时间。当一个线程被延迟阻塞时,其他线程可以接管并继续处理。 +- 如果你在服务器上部署了多个服务,每个服务都有单独的连接池,请考虑所有连接池的最大连接数之和。 ## 连接参数 -Java 应用尽管可以选择在不同的框架中封装,但在最底层一般会通过调用 JDBC 来与数据库服务器进行交互。对于 JDBC,需要关注的主要有:API 的使用选择和 API Implementer 的参数配置。 +Java 应用程序可以用各种框架封装。在大多数框架中,JDBC API 在最底层被调用来与数据库服务器交互。对于 JDBC,建议你关注以下几点: + +- JDBC API 使用选择 +- API 实现者的参数配置 ### JDBC API -对于基本的 JDBC API 使用可以参考 [JDBC 官方教程](https://docs.oracle.com/javase/tutorial/jdbc/),本文主要强调几个比较重要的 API 选择。 +关于 JDBC API 的使用,请参阅 [JDBC 官方教程](https://docs.oracle.com/javase/tutorial/jdbc/)。本节介绍几个重要 API 的使用。 -### 使用 Prepare 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 执行计划的开销。 +对于 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),并重用 Prepared Statements 直接执行。这避免了在 TiDB 中重复解析和生成 SQL 执行计划的开销。 -目前多数上层框架都会调用 Prepare API 进行 SQL 执行,如果直接使用 JDBC API 进行开发,注意选择使用 Prepare API。 +目前,大多数上层框架都会调用 Prepare API 来执行 SQL。如果你直接使用 JDBC API 进行开发,请注意选择 Prepare API。 -另外需要注意 MySQL Connector/J 实现中默认只会做客户端的语句预处理,会将 `?` 在客户端替换后以文本形式发送到服务端,所以除了要使用 Prepare API,还需要在 JDBC 连接参数中配置 `useServerPrepStmts = true`,才能在 TiDB 服务器端进行语句预处理(下面参数配置章节有详细介绍)。 +此外,在 MySQL Connector/J 的默认实现中,只有客户端语句被预处理,语句在客户端替换 `?` 后以文本文件形式发送到服务器。因此,除了使用 Prepare API 外,你还需要在 JDBC 连接参数中配置 `useServerPrepStmts = true`,才能在 TiDB 服务器上进行语句预处理。有关详细的参数配置,请参阅 [MySQL JDBC 参数](#mysql-jdbc-参数)。 -### 使用 Batch 批量插入更新 +#### 使用 Batch API -对于批量插入更新,如果插入记录较多,可以选择使用 [addBatch/executeBatch API](https://www.tutorialspoint.com/jdbc/jdbc-batch-processing)。通过 addBatch 的方式将多条 SQL 的插入更新记录先缓存在客户端,然后在 executeBatch 时一起发送到数据库服务器。 +对于批量插入,你可以使用 [`addBatch`/`executeBatch` API](https://www.tutorialspoint.com/jdbc/jdbc-batch-processing)。`addBatch()` 方法用于先在客户端缓存多个 SQL 语句,然后在调用 `executeBatch` 方法时一起发送到数据库服务器。 > **注意:** > -> 对于 MySQL Connector/J 实现,默认 Batch 只是将多次 addBatch 的 SQL 发送时机延迟到调用 executeBatch 的时候,但实际网络发送还是会一条条的发送,通常不会降低与数据库服务器的网络交互次数。 +> 在默认的 MySQL Connector/J 实现中,使用 `addBatch()` 添加到批处理的 SQL 语句的发送时间被延迟到调用 `executeBatch()` 时,但在实际网络传输过程中,语句仍然会一条一条发送。因此,这种方法通常不会减少通信开销。 > -> 如果希望 Batch 网络发送,需要在 JDBC 连接参数中配置 `rewriteBatchedStatements = true`(下面参数配置章节有详细介绍)。 +> 如果你想批量网络传输,需要在 JDBC 连接参数中配置 `rewriteBatchedStatements = true`。有关详细的参数配置,请参阅[批处理相关参数](#批处理相关参数)。 + +#### 使用 `StreamingResult` 获取执行结果 -### 使用 StreamingResult 流式获取执行结果 +在大多数场景中,为了提高执行效率,JDBC 默认会提前获取查询结果并保存在客户端内存中。但当查询返回超大结果集时,客户端通常希望数据库服务器一次返回较少的记录,等到客户端内存就绪后再请求下一批。 -一般情况下,为提升执行效率,JDBC 会默认提前获取查询结果并将其保存在客户端内存中。但在查询返回超大结果集的场景中,客户端会希望数据库服务器减少向客户端一次返回的记录数,等客户端在有限内存处理完一部分后再去向服务器要下一批。 +通常,JDBC 中有两种处理方法: -在 JDBC 中通常有以下两种处理方式: +- [将 **FetchSize** 设置为 `Integer.MIN_VALUE`](https://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html#ResultSet) 以确保客户端不缓存。客户端将通过网络连接使用 `StreamingResult` 读取执行结果。 -- 设置 [**FetchSize** 为 `Integer.MIN_VALUE`](https://dev.mysql.com/doc/connector-j/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`。 + 当客户端使用流式读取方法时,需要在继续使用语句进行查询之前完成读取或关闭 `resultset`。否则,会返回错误 `No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.`。 -TiDB 中同时支持两种方式,但更推荐使用第一种将 **FetchSize** 设置为 `Integer.MIN_VALUE` 的方式,比第二种功能实现更简单且执行效率更高。 + 要避免在客户端完成读取或关闭 `resultset` 之前的查询中出现此类错误,可以在 URL 中添加 `clobberStreamingResults=true` 参数。这样,`resultset` 会自动关闭,但之前流式查询中要读取的结果集会丢失。 + +- 要使用游标获取,首先[将 `FetchSize` 设置为正整数](http://makejavafaster.blogspot.com/2015/06/jdbc-fetch-size-performance.html),并在 JDBC URL 中配置 `useCursorFetch=true`。 + +TiDB 支持这两种方法,但建议使用第一种方法,因为它的实现更简单,执行效率更高。 ### MySQL JDBC 参数 -JDBC 实现通常通过 JDBC URL 参数的形式来提供实现相关的配置。这里以 MySQL 官方的 Connector/J 来介绍[参数配置](https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html)(如果使用的是 MariaDB,可以参考 [MariaDB 的类似配置](https://mariadb.com/kb/en/library/about-mariadb-connector-j/#optional-url-parameters))。因为配置项较多,这里主要关注几个可能影响到性能的参数。 +JDBC 通常以 JDBC URL 参数的形式提供与实现相关的配置。本节介绍 [MySQL Connector/J 的参数配置](https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html)(如果你使用 MariaDB,请参阅 [MariaDB 的参数配置](https://mariadb.com/kb/en/library/about-mariadb-connector-j/#optional-url-parameters))。由于本文无法涵盖所有配置项,主要关注几个可能影响性能的参数。 #### Prepare 相关参数 +本节介绍与 `Prepare` 相关的参数。 + - **useServerPrepStmts** - 默认情况下,**useServerPrepStmts** 的值为 `false`,即尽管使用了 Prepare API,也只会在客户端做 “prepare”。因此为了避免服务器重复解析的开销,如果同一条 SQL 语句需要多次使用 Prepare API,则建议设置该选项为 `true`。 + **useServerPrepStmts** 默认设置为 `false`,即使你使用 Prepare API,"prepare" 操作也只会在客户端完成。为避免服务器的解析开销,如果同一个 SQL 语句多次使用 Prepare API,建议将此配置设置为 `true`。 - 在 TiDB 监控中可以通过 **Query Summary > CPS By Instance** 查看请求命令类型,如果请求中 `COM_QUERY` 被 `COM_STMT_EXECUTE` 或 `COM_STMT_PREPARE` 代替即生效。 + 要验证此设置是否已生效,你可以: + + - 进入 TiDB 监控面板,通过 **Query Summary** > **CPS By Instance** 查看请求命令类型。 + - 如果请求中的 `COM_QUERY` 被 `COM_STMT_EXECUTE` 或 `COM_STMT_PREPARE` 替换,说明此设置已生效。 - **cachePrepStmts** - 虽然 `useServerPrepStmts = true` 能让服务端执行预处理语句,但默认情况下客户端每次执行完后会 close 预处理语句,并不会复用,这样预处理的效率甚至不如文本执行。所以建议开启 `useServerPrepStmts = true` 后同时配置 `cachePrepStmts = true`,这会让客户端缓存预处理语句。 + 虽然 `useServerPrepStmts=true` 允许服务器执行 Prepared Statements,但默认情况下,客户端会在每次执行后关闭 Prepared Statements 而不重用它们。这意味着 "prepare" 操作的效率甚至不如文本文件执行。要解决这个问题,建议在设置 `useServerPrepStmts=true` 后,还要配置 `cachePrepStmts=true`。这允许客户端缓存 Prepared Statements。 + + 要验证此设置是否已生效,你可以: - 在 TiDB 监控中可以通过 **Query Summary > CPS By Instance** 查看请求命令类型,如果请求中 `COM_STMT_EXECUTE` 数目远远多于 `COM_STMT_PREPARE` 即生效。 + - 进入 TiDB 监控面板,通过 **Query Summary** > **CPS By Instance** 查看请求命令类型。 + - 如果请求中 `COM_STMT_EXECUTE` 的数量远多于 `COM_STMT_PREPARE` 的数量,说明此设置已生效。 - 另外,通过 `useConfigs = maxPerformance` 配置会同时配置多个参数,其中也包括 `cachePrepStmts = true`。 + 此外,配置 `useConfigs=maxPerformance` 将同时配置多个参数,包括 `cachePrepStmts=true`。 - **prepStmtCacheSqlLimit** - 在配置 **cachePrepStmts** 后还需要注意 **prepStmtCacheSqlLimit** 配置(默认为 `256`),该配置控制客户端缓存预处理语句的最大长度,超过该长度将不会被缓存。 + 配置 `cachePrepStmts` 后,还要注意 `prepStmtCacheSqlLimit` 配置(默认值为 `256`)。此配置控制客户端缓存的 Prepared Statements 的最大长度。 + + 超过此最大长度的 Prepared Statements 将不会被缓存,因此无法重用。在这种情况下,你可以根据应用程序的实际 SQL 长度考虑增加此配置的值。 - 在一些场景 SQL 的长度可能超过该配置,导致预处理 SQL 不能复用,建议根据应用 SQL 长度情况决定是否需要调大该值。 + 如果你: - 在 TiDB 监控中通过 **Query Summary > CPS By Instance** 查看请求命令类型,如果已经配置了 `cachePrepStmts = true`,但 `COM_STMT_PREPARE` 还是和 `COM_STMT_EXECUTE` 基本相等且有 `COM_STMT_CLOSE`,需要检查这个配置项是否设置得太小。 + - 进入 TiDB 监控面板,通过 **Query Summary** > **CPS By Instance** 查看请求命令类型。 + - 发现已配置 `cachePrepStmts=true`,但 `COM_STMT_PREPARE` 仍然基本等于 `COM_STMT_EXECUTE` 且存在 `COM_STMT_CLOSE`。 + + 则需要检查此设置是否太小。 - **prepStmtCacheSize** - 控制缓存的预处理语句数目(默认为 `25`),如果应用需要预处理的 SQL 种类很多且希望复用预处理语句,可以调大该值。 + **prepStmtCacheSize** 控制缓存的 Prepared Statements 的数量(默认值为 `25`)。如果你的应用程序需要 "prepare" 多种类型的 SQL 语句并希望重用 Prepared Statements,可以增加此值。 + + 要验证此设置是否已生效,你可以: - 和上一条类似,在监控中通过 **Query Summary > CPS By Instance** 查看请求中 `COM_STMT_EXECUTE` 数目是否远远多于 `COM_STMT_PREPARE` 来确认是否正常。 + - 进入 TiDB 监控面板,通过 **Query Summary** > **CPS By Instance** 查看请求命令类型。 + - 如果请求中 `COM_STMT_EXECUTE` 的数量远多于 `COM_STMT_PREPARE` 的数量,说明此设置已生效。 -#### Batch 相关参数 +#### 批处理相关参数 -在进行 batch 写入处理时推荐配置 `rewriteBatchedStatements = true`,在已经使用 `addBatch` 或 `executeBatch` 后默认 JDBC 还是会一条条 SQL 发送,例如: +在处理批量写入时,建议配置 `rewriteBatchedStatements=true`。在使用 `addBatch()` 或 `executeBatch()` 后,JDBC 默认仍然一条一条地发送 SQL,例如: ```java -pstmt = prepare("INSERT INTO `t` (`a`) VALUES(?)"); +pstmt = prepare("INSERT INTO `t` (a) values(?)"); pstmt.setInt(1, 10); pstmt.addBatch(); pstmt.setInt(1, 11); @@ -185,7 +219,7 @@ pstmt.setInt(1, 12); pstmt.executeBatch(); ``` -虽然使用了 batch 但发送到 TiDB 语句还是单独的多条 insert: +虽然使用了 `Batch` 方法,但发送到 TiDB 的 SQL 语句仍然是单独的 `INSERT` 语句: ```sql INSERT INTO `t` (`a`) VALUES(10); @@ -193,13 +227,13 @@ INSERT INTO `t` (`a`) VALUES(11); INSERT INTO `t` (`a`) VALUES(12); ``` -如果设置 `rewriteBatchedStatements = true`,发送到 TiDB 的 SQL 将是: +但如果设置 `rewriteBatchedStatements=true`,发送到 TiDB 的 SQL 语句将是一条 `INSERT` 语句: ```sql -INSERT INTO `t` (`a`) VALUES(10),(11),(12); +INSERT INTO `t` (`a`) values(10),(11),(12); ``` -需要注意的是,insert 语句的改写,只能将多个 values 后的值拼接成一整条 SQL, insert 语句如果有其他差异将无法被改写。例如: +注意,`INSERT` 语句的重写是将多个 "values" 关键字后的值连接成一个完整的 SQL 语句。如果 `INSERT` 语句有其他差异,它们就不能被重写,例如: ```sql INSERT INTO `t` (`a`) VALUES (10) ON DUPLICATE KEY UPDATE `a` = 10; @@ -207,42 +241,54 @@ 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 改写成如下形式: +上述 `INSERT` 语句不能重写为一条语句。但如果你将这三条语句改为以下形式: ```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`); +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`); ``` -即可满足改写条件,最终被改写成: +那么它们就满足重写要求。上述 `INSERT` 语句将被重写为以下一条语句: ```sql -INSERT INTO `t` (`a`) VALUES (10), (11), (12) ON DUPLICATE KEY UPDATE `a` = values(`a`); +INSERT INTO `t` (`a`) VALUES (10), (11), (12) ON DUPLICATE KEY UPDATE a = VALUES(`a`); ``` -批量更新时如果有 3 处或 3 处以上更新,则 SQL 语句会改写为 multiple-queries 的形式并发送,这样可以有效减少客户端到服务器的请求开销,但副作用是会产生较大的 SQL 语句,例如这样: +如果在批量更新期间有三个或更多更新,SQL 语句将被重写并作为多个查询发送。这有效减少了客户端到服务器的请求开销,但副作用是生成了一个更大的 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; +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。 +此外,由于[客户端错误](https://bugs.mysql.com/bug.php?id=96623),如果你想在批量更新期间配置 `rewriteBatchedStatements=true` 和 `useServerPrepStmts=true`,建议你也配置 `allowMultiQueries=true` 参数以避免此错误。 #### 集成参数 -通过监控可能会发现,虽然业务只向集群进行 insert 操作,却看到有很多多余的 select 语句。通常这是因为 JDBC 发送了一些查询设置类的 SQL 语句(例如 `select @@session.transaction_read_only`)。这些 SQL 对 TiDB 无用,推荐配置 `useConfigs = maxPerformance` 来避免额外开销。 +通过监控,你可能会注意到,虽然应用程序只对 TiDB 集群执行 `INSERT` 操作,但有很多冗余的 `SELECT` 语句。通常这是因为 JDBC 发送一些 SQL 语句来查询设置,例如 `select @@session.transaction_read_only`。这些 SQL 语句对 TiDB 来说是无用的,因此建议配置 `useConfigs=maxPerformance` 以避免额外开销。 + +`useConfigs=maxPerformance` 包含一组配置。要获取 MySQL Connector/J 8.0 和 MySQL Connector/J 5.1 中的详细配置,请分别参阅 [mysql-connector-j 8.0](https://github.com/mysql/mysql-connector-j/blob/release/8.0/src/main/resources/com/mysql/cj/configurations/maxPerformance.properties) 和 [mysql-connector-j 5.1](https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/configs/maxPerformance.properties)。 + +配置后,你可以通过监控查看 `SELECT` 语句数量的减少。 + +#### 超时相关参数 + +TiDB 提供两个与 MySQL 兼容的参数来控制超时:[`wait_timeout`](/system-variables.md#wait_timeout) 和 [`max_execution_time`](/system-variables.md#max_execution_time)。这两个参数分别控制与 Java 应用程序的连接空闲超时和连接中 SQL 执行的超时;也就是说,这些参数控制 TiDB 与 Java 应用程序之间连接的最长空闲时间和最长忙碌时间。从 TiDB v5.4 开始,`wait_timeout` 的默认值为 `28800` 秒,即 8 小时。对于早于 v5.4 的 TiDB 版本,默认值为 `0`,表示超时时间无限制。`max_execution_time` 的默认值为 `0`,表示 SQL 语句的最大执行时间无限制。 + +[`wait_timeout`](/system-variables.md#wait_timeout) 的默认值相对较大。在事务已启动但既未提交也未回滚的场景中,你可能需要更细粒度的控制和更短的超时时间以防止长时间持有锁。在这种情况下,你可以使用 [`tidb_idle_transaction_timeout`](/system-variables.md#tidb_idle_transaction_timeout-new-in-v760)(在 TiDB v7.6.0 中引入)来控制用户会话中事务的空闲超时。 + +然而,在实际生产环境中,空闲连接和执行时间过长的 SQL 语句会对数据库和应用程序产生负面影响。为避免空闲连接和执行时间过长的 SQL 语句,你可以在应用程序的连接字符串中配置这两个参数。例如,设置 `sessionVariables=wait_timeout=3600`(1 小时)和 `sessionVariables=max_execution_time=300000`(5 分钟)。 + +## 需要帮助? -`useConfigs = maxPerformance` 会包含一组配置,可查看 MySQL Connector/J [8.0 版本](https://github.com/mysql/mysql-connector-j/blob/release/8.0/src/main/resources/com/mysql/cj/configurations/maxPerformance.properties) 或 [5.1 版本](https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/configs/maxPerformance.properties) 来确认当前 MySQL Connector/J 中 `maxPerformance` 包含的具体配置。 + -配置后查看监控,可以看到多余语句减少。 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 -#### 超时参数 + -TiDB 提供两个与 MySQL 兼容的超时控制参数,[`wait_timeout`](/system-variables.md#wait_timeout) 和 [`max_execution_time`](/system-variables.md#max_execution_time)。这两个参数分别控制与 Java 应用连接的空闲超时时间和连接中 SQL 执行的超时时间,即控制 TiDB 与 Java 应用的连接最长闲多久和最长忙多久。在 TiDB v5.4 及以上版本中,`wait_timeout` 参数默认值为 `28800` 秒,即空闲超时为 8 小时。在 v5.4 之前,`wait_timeout` 参数的默认值为 `0`,即没有时间限制。 `max_execution_time` 参数的默认值为 `0`,即不限制一条 SQL 语句的执行时间。 + -但是 [`wait_timeout`](/system-variables.md#wait_timeout) 的默认值比较大,在事务已启动但未提交或回滚的情况下,你可能需要更细粒度的控制和更短的超时,以避免持有锁的时间过长。此时,你可以使用 TiDB 在 v7.6.0 引入的 [`tidb_idle_transaction_timeout`](/system-variables.md#tidb_idle_transaction_timeout-从-v760-版本开始引入) 控制用户会话中事务的空闲超时。 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -但在实际生产环境中,空闲连接和一直无限执行的 SQL 对数据库和应用都有不好的影响。你可以通过在应用的连接字符串中配置这两个参数来避免空闲连接和执行时间过长的 SQL 语句。例如,设置 `sessionVariables=wait_timeout=3600`(1 小时)和 `sessionVariables=max_execution_time=300000`(5 分钟)。 + diff --git a/develop/dev-guide-create-database.md b/develop/dev-guide-create-database.md index 36a0777cd4ad..9d582b5204b0 100644 --- a/develop/dev-guide-create-database.md +++ b/develop/dev-guide-create-database.md @@ -1,36 +1,36 @@ --- title: 创建数据库 -summary: 创建数据库的方法、规范及例子。 +summary: 了解创建数据库的步骤、规则和示例。 --- # 创建数据库 -在这个章节当中,将开始介绍如何使用 SQL 来创建数据库,及创建数据库时应遵守的规则。将在这个章节中围绕 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 这个应用程序来对 TiDB 的创建数据库部分展开介绍。 +本文档介绍如何使用 SQL 和各种编程语言创建数据库,并列出了数据库创建的规则。在本文档中,以 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序为例,指导您完成数据库创建的步骤。 -> **注意:** -> -> 此处仅对 `CREATE DATABASE` 语句进行简单描述,详细参考文档(包含其他示例),可参阅 [CREATE DATABASE](/sql-statements/sql-statement-create-database.md) 文档。 +## 开始之前 -## 在开始之前 +在创建数据库之前,请执行以下操作: -在阅读本页面之前,你需要准备以下事项: - -- [使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 -- 阅读[数据库模式概览](/develop/dev-guide-schema-design-overview.md)。 +- [构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 +- 阅读[架构设计概述](/develop/dev-guide-schema-design-overview.md)。 ## 什么是数据库 -在 TiDB 中[数据库](/develop/dev-guide-schema-design-overview.md#数据库-database)对象可以包含**表**、**视图**、**序列**等对象。 +TiDB 中的[数据库](/develop/dev-guide-schema-design-overview.md)对象包含**表**、**视图**、**序列**和其他对象。 + +## 创建数据库 -## 创建数据库过程 +要创建数据库,您可以使用 `CREATE DATABASE` 语句。 -可使用 `CREATE DATABASE` 语句来创建数据库。 +例如,要创建一个名为 `bookshop` 的数据库(如果它不存在),请使用以下语句: ```sql CREATE DATABASE IF NOT EXISTS `bookshop`; ``` -此语句会创建一个名为 `bookshop` 的数据库(如果尚不存在)。请以 `root` 用户身份执行文件中的建库语句,运行以下命令: +有关 `CREATE DATABASE` 语句的更多信息和示例,请参见 [`CREATE DATABASE`](/sql-statements/sql-statement-create-database.md) 文档。 + +要以 `root` 用户身份执行库构建语句,请运行以下命令: ```shell mysql @@ -41,7 +41,11 @@ mysql -e "CREATE DATABASE IF NOT EXISTS bookshop;" ``` -要查看集群中的数据库,可在命令行执行一条 `SHOW DATABASES` 语句: +## 查看数据库 + +要查看集群中的数据库,请使用 [`SHOW DATABASES`](/sql-statements/sql-statement-show-databases.md) 语句。 + +例如: ```shell mysql @@ -52,7 +56,7 @@ mysql -e "SHOW DATABASES;" ``` -运行结果为: +以下是示例输出: ``` +--------------------+ @@ -66,15 +70,27 @@ mysql +--------------------+ ``` -## 数据库创建时应遵守的规则 +## 数据库创建规则 + +- 遵循[数据库命名约定](/develop/dev-guide-object-naming-guidelines.md),为数据库命名时要有意义。 +- TiDB 自带一个名为 `test` 的默认数据库。但是,如果不是必须,建议不要在生产环境中使用它。您可以使用 `CREATE DATABASE` 语句创建自己的数据库,并在 SQL 会话中使用 [`USE {databasename};`](/sql-statements/sql-statement-use.md) 语句更改当前数据库。 +- 使用 `root` 用户创建数据库、角色和用户等对象。仅向角色和用户授予必要的权限。 +- 作为最佳实践,建议使用 **MySQL 命令行客户端**或 **MySQL GUI 客户端**而不是驱动程序或 ORM 来执行数据库架构更改。 + +## 下一步 + +创建数据库后,您可以向其添加**表**。更多信息,请参见[创建表](/develop/dev-guide-create-table.md)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 -- 遵循[数据库命名规范](/develop/dev-guide-object-naming-guidelines.md#数据库命名规范),给你的数据库起一个有意义的名字。 -- `test` 数据库是 TiDB 提供的一个默认数据库。如果没有必要,尽量不要在生产环境使用它。你可以自行使用 `CREATE DATABASE` 语句来创建数据库,并且在 SQL 会话中使用 `USE {databasename};` 语句来[更改当前数据库](/sql-statements/sql-statement-use.md)。 -- 使用 root 用户创建数据库、角色、用户等,并只赋予必要的权限。 -- 作为通用的规则,不推荐使用 Driver、ORM 进行数据库模式的定义与更改。相反,请使用 **MySQL 命令行客户端**或其他你喜欢的 **MySQL GUI 客户端**来进行操作。 + -## 更进一步 + -至此,你已经准备完毕 `bookshop` 数据库,可以将**表**添加到该数据库中。 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -你可继续阅读[创建表](/develop/dev-guide-create-table.md)文档获得相关指引。 + diff --git a/develop/dev-guide-create-secondary-indexes.md b/develop/dev-guide-create-secondary-indexes.md index e85204734950..a6474f4e0698 100644 --- a/develop/dev-guide-create-secondary-indexes.md +++ b/develop/dev-guide-create-secondary-indexes.md @@ -1,68 +1,86 @@ --- title: 创建二级索引 -summary: 创建二级索引的方法、规范及例子。 +summary: 学习创建二级索引的步骤、规则和示例。 --- # 创建二级索引 -在这个章节当中,将开始介绍如何使用 SQL 来创建二级索引,及创建二级索引时应遵守的规则。将在这个章节中围绕 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 这个应用程序来对 TiDB 的创建二级索引部分展开介绍。 +本文介绍如何使用 SQL 和各种编程语言创建二级索引,并列出了索引创建的规则。在本文中,以 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序为例,引导你完成二级索引创建的步骤。 -## 在开始之前 +## 开始之前 -在阅读本页面之前,你需要准备以下事项: +在创建二级索引之前,请执行以下操作: -- [使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 -- 阅读[数据库模式概览](/develop/dev-guide-schema-design-overview.md)。 -- [创建一个数据库](/develop/dev-guide-create-database.md)。 +- [构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 +- 阅读[架构设计概述](/develop/dev-guide-schema-design-overview.md)。 +- [创建数据库](/develop/dev-guide-create-database.md)。 - [创建表](/develop/dev-guide-create-table.md)。 ## 什么是二级索引 -二级索引是集群中的逻辑对象,你可以简单地认为它就是一种对数据的排序,TiDB 使用这种有序性来加速查询。TiDB 的创建二级索引的操作为在线操作,不会阻塞表中的数据读写。TiDB 会创建表中各行的引用,并按选择的列进行排序。而并非对表本身的数据进行排序。可在[二级索引](/best-practices/tidb-best-practices.md#二级索引)中查看更多信息。二级索引可[跟随表进行创建](#新建表的同时创建二级索引),也可[在已有的表上进行添加](#在已有表中添加二级索引)。 +二级索引是 TiDB 集群中的一个逻辑对象。你可以简单地将其视为 TiDB 用来提高查询性能的一种数据排序方式。在 TiDB 中,创建二级索引是一个在线操作,不会阻塞表上的任何数据读写操作。对于每个索引,TiDB 为表中的每一行创建引用,并按选定的列对引用进行排序,而不是直接对数据进行排序。 -## 在已有表中添加二级索引 + -如果需要对已有表中添加二级索引,可使用 [CREATE INDEX](/sql-statements/sql-statement-create-index.md) 语句。在 TiDB 中,`CREATE INDEX` 为在线操作,不会阻塞表中的数据读写。二级索引创建一般如以下形式: +有关二级索引的更多信息,请参阅[二级索引](/best-practices/tidb-best-practices.md#secondary-index)。 + + + + + +有关二级索引的更多信息,请参阅[二级索引](https://docs.pingcap.com/tidb/stable/tidb-best-practices#secondary-index)。 + + + +在 TiDB 中,你可以[为现有表添加二级索引](#为现有表添加二级索引)或[在创建新表时创建二级索引](#在创建新表时创建二级索引)。 + +## 为现有表添加二级索引 + +要为现有表添加二级索引,你可以使用 [CREATE INDEX](/sql-statements/sql-statement-create-index.md) 语句,如下所示: ```sql CREATE INDEX {index_name} ON {table_name} ({column_names}); ``` -**参数描述** +参数说明: -- `{index_name}`: 二级索引名。 -- `{table_name}`: 表名。 -- `{column_names}`: 将需要索引的列名列表,以半角逗号分隔。 +- `{index_name}`:二级索引的名称。 +- `{table_name}`:表名。 +- `{column_names}`:要建立索引的列名,用逗号分隔。 -## 新建表的同时创建二级索引 +## 在创建新表时创建二级索引 -如果你希望在创建表的同时,同时创建二级索引,可在 [CREATE TABLE](/sql-statements/sql-statement-create-table.md) 的末尾使用包含 `KEY` 关键字的子句来创建二级索引: +要在创建表的同时创建二级索引,你可以在 [CREATE TABLE](/sql-statements/sql-statement-create-table.md) 语句的末尾添加包含 `KEY` 关键字的子句: ```sql KEY `{index_name}` (`{column_names}`) ``` -**参数描述** +参数说明: -- `{index_name}`: 二级索引名。 -- `{column_names}`: 将需要索引的列名列表,以半角逗号分隔。 +- `{index_name}`:二级索引的名称。 +- `{column_names}`:要建立索引的列名,用逗号分隔。 -## 创建二级索引时应遵守的规则 +## 创建二级索引的规则 -见[索引的最佳实践](/develop/dev-guide-index-best-practice.md)。 +请参阅[索引的最佳实践](/develop/dev-guide-index-best-practice.md)。 -## 例子 +## 示例 -假设你希望 `bookshop` 应用程序有 **查询某个年份出版的所有书籍** 的功能。`books` 表如下所示: +假设你希望 `bookshop` 应用程序支持**搜索指定年份发布的所有图书**。 -| 字段名 | 类型 | 含义 | -| :----------: | :-----------: | :-----------------------------------: | -| id | bigint(20) | 书籍的唯一标识 | -| title | varchar(100) | 书籍名称 | -| type | enum | 书籍类型(如:杂志、动漫、教辅等) | -| stock | bigint(20) | 库存 | -| price | decimal(15,2) | 价格 | -| published_at | datetime | 出版时间 | +`books` 表中的字段如下: + +| 字段名 | 类型 | 字段说明 | +|--------------|---------------|------------------------------------------------------------------| +| id | bigint(20) | 图书的唯一 ID | +| title | varchar(100) | 图书标题 | +| type | enum | 图书类型(例如,杂志、动漫和教辅) | +| stock | bigint(20) | 库存 | +| price | decimal(15,2) | 价格 | +| published_at | datetime | 发布日期 | + +使用以下 SQL 语句创建 `books` 表: ```sql CREATE TABLE `bookshop`.`books` ( @@ -76,19 +94,19 @@ CREATE TABLE `bookshop`.`books` ( ) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; ``` -因此,就需要对 **查询某个年份出版的所有书籍** 的 SQL 进行编写,以 2022 年为例,如下所示: +要支持按年份搜索功能,你需要编写一个 SQL 语句来**搜索指定年份发布的所有图书**。以 2022 年为例,编写如下 SQL 语句: ```sql SELECT * FROM `bookshop`.`books` WHERE `published_at` >= '2022-01-01 00:00:00' AND `published_at` < '2023-01-01 00:00:00'; ``` -可以使用 [EXPLAIN](/sql-statements/sql-statement-explain.md) 进行 SQL 语句的执行计划检查: +要检查 SQL 语句的执行计划,你可以使用 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 语句。 ```sql EXPLAIN SELECT * FROM `bookshop`.`books` WHERE `published_at` >= '2022-01-01 00:00:00' AND `published_at` < '2023-01-01 00:00:00'; ``` -运行结果为: +以下是执行计划的示例输出: ``` +-------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------+ @@ -101,15 +119,17 @@ EXPLAIN SELECT * FROM `bookshop`.`books` WHERE `published_at` >= '2022-01-01 00: 3 rows in set (0.61 sec) ``` -可以看到返回的计划中,出现了类似 **TableFullScan** 的字样,这代表 TiDB 准备在这个查询中对 `books` 表进行全表扫描,这在数据量较大的情况下,几乎是致命的。 +在示例输出中,`id` 列显示了 **TableFullScan**,这意味着 TiDB 准备在这个查询中对 `books` 表进行全表扫描。然而,在数据量较大的情况下,全表扫描可能会非常慢,并造成致命影响。 -在 `books` 表增加一个 `published_at` 列的索引: +为避免这种影响,你可以为 `books` 表的 `published_at` 列添加一个索引,如下所示: ```sql CREATE INDEX `idx_book_published_at` ON `bookshop`.`books` (`bookshop`.`books`.`published_at`); ``` -添加索引后,再次运行 `EXPLAIN` 语句检查执行计划: +添加索引后,再次执行 `EXPLAIN` 语句来检查执行计划。 + +以下是示例输出: ``` +-------------------------------+---------+-----------+--------------------------------------------------------+-------------------------------------------------------------------+ @@ -122,23 +142,33 @@ CREATE INDEX `idx_book_published_at` ON `bookshop`.`books` (`bookshop`.`books`.` 3 rows in set (0.18 sec) ``` -可以看到执行计划中没有了 **TableFullScan** 的字样,取而代之的是 **IndexRangeScan**,这代表已经 TiDB 在进行这个查询时准备使用索引。 +在输出中,显示了 **IndexRangeScan** 而不是 **TableFullScan**,这意味着 TiDB 准备使用索引来执行这个查询。 + +执行计划中的 **TableFullScan** 和 **IndexRangeScan** 等词是 TiDB 中的[算子](/explain-overview.md#operator-overview)。有关执行计划和算子的更多信息,请参阅 [TiDB 执行计划概览](/explain-overview.md)。 + + + +执行计划不会每次都返回相同的算子。这是因为 TiDB 使用**基于成本的优化 (CBO)** 方法,其中执行计划取决于规则和数据分布。有关 TiDB SQL 性能的更多信息,请参阅 [SQL 调优概述](/sql-tuning-overview.md)。 + + + + + +执行计划不会每次都返回相同的算子。这是因为 TiDB 使用**基于成本的优化 (CBO)** 方法,其中执行计划取决于规则和数据分布。有关 TiDB SQL 性能的更多信息,请参阅 [SQL 调优概述](/tidb-cloud/tidb-cloud-sql-tuning-overview.md)。 + + > **注意:** > -> 上方执行计划中的的 **TableFullScan**、**IndexRangeScan** 等在 TiDB 内被称为[算子](/explain-overview.md#算子简介)。这里对执行计划的解读及算子等不做进一步的展开,若你对此感兴趣,可前往 [TiDB 执行计划概览](/explain-overview.md)文档查看更多关于执行计划与 TiDB 算子的相关知识。 -> -> 执行计划并非每次返回使用的算子都相同,这是由于 TiDB 使用的优化方式为 **基于代价的优化方式 (CBO)**,执行计划不仅与规则相关,还和数据分布相关。你可以前往 [SQL 性能调优](/sql-tuning-overview.md)文档查看更多 TiDB SQL 性能的描述。 -> -> TiDB 在查询时,还支持显式地使用索引,你可以使用 [Optimizer Hints](/optimizer-hints.md) 或[执行计划管理 (SPM)](/sql-plan-management.md) 来人为的控制索引的使用。但如果你不了解它内部发生了什么,请你**_暂时先不要使用它_**。 +> TiDB 还支持在查询时显式使用索引,你可以使用[优化器提示](/optimizer-hints.md)或 [SQL 计划管理 (SPM)](/sql-plan-management.md)来人为控制索引的使用。但如果你对索引、优化器提示或 SPM 不够了解,**不要**使用此功能,以避免任何意外结果。 -可以使用 [SHOW INDEXES](/sql-statements/sql-statement-show-indexes.md) 语句查询表中的索引: +要查询表上的索引,你可以使用 [SHOW INDEXES](/sql-statements/sql-statement-show-indexes.md) 语句: ```sql SHOW INDEXES FROM `bookshop`.`books`; ``` -运行结果为: +以下是示例输出: ``` +-------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+-----------+ @@ -150,6 +180,20 @@ SHOW INDEXES FROM `bookshop`.`books`; 2 rows in set (1.63 sec) ``` -## 更进一步 +## 下一步 + +在创建数据库并向其添加表和二级索引后,你可以开始向应用程序添加数据[写入](/develop/dev-guide-insert-data.md)和[读取](/develop/dev-guide-get-data-from-single-table.md)功能。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -至此,你已经完成数据库、表及二级索引的创建,接下来,数据库模式已经准备好给你的应用程序提供[写入](/develop/dev-guide-insert-data.md)和[读取](/develop/dev-guide-get-data-from-single-table.md)的能力了。 + diff --git a/develop/dev-guide-create-table.md b/develop/dev-guide-create-table.md index f926ac1a3b1b..64645a539264 100644 --- a/develop/dev-guide-create-table.md +++ b/develop/dev-guide-create-table.md @@ -1,31 +1,27 @@ --- title: 创建表 -summary: 创建表的方法、规范及例子。 +summary: 了解表创建中的定义、规则和指南。 --- # 创建表 -本文档介绍如何使用 SQL 语句来创建表以及创建表的最佳实践。本文档提供了一个基于 TiDB 的 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库的示例加以说明。 +本文介绍如何使用 SQL 语句创建表以及相关的最佳实践。文档提供了基于 TiDB 的 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序示例来说明这些最佳实践。 -> **注意:** -> -> 此处仅对 `CREATE TABLE` 语句进行简单描述,详细参考文档(包含其他示例),可参阅 [CREATE TABLE](/sql-statements/sql-statement-create-table.md) 文档。 +## 开始之前 -## 在开始之前 +在阅读本文之前,请确保完成以下任务: -在阅读本页面之前,你需要准备以下事项: - -- [使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 -- 阅读[数据库模式概览](/develop/dev-guide-schema-design-overview.md)。 -- [创建一个数据库](/develop/dev-guide-create-database.md)。 +- [构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md) +- 阅读[数据库设计概述](/develop/dev-guide-schema-design-overview.md) +- [创建数据库](/develop/dev-guide-create-database.md) ## 什么是表 -[表](/develop/dev-guide-schema-design-overview.md#表-table)是集群中的一种逻辑对象,它从属于[数据库](/develop/dev-guide-schema-design-overview.md#数据库-database),用于保存从 SQL 中发送的数据。表以行和列的形式组织数据记录,一张表至少有一列。若在表中定义了 n 个列,那么每一行数据都将拥有与这 n 个列中完全一致的字段。 +[表](/develop/dev-guide-schema-design-overview.md#table)是 TiDB 集群中从属于[数据库](/develop/dev-guide-schema-design-overview.md#database)的逻辑对象。它用于存储从 SQL 语句发送的数据。表以行和列的形式保存数据记录。一个表至少有一列。如果你定义了 `n` 列,每行数据都具有与这 `n` 列完全相同的字段。 ## 命名表 -创建表的第一步,就是给你的表起个名字。请不要使用无意义的表名,将给未来的你或者你的同事带来极大的困扰。推荐你遵循公司或组织的表命名规范。 +创建表的第一步是为表命名。不要使用会给自己或同事带来困扰的无意义名称。建议你遵循公司或组织的表命名约定。 `CREATE TABLE` 语句通常采用以下形式: @@ -33,14 +29,14 @@ summary: 创建表的方法、规范及例子。 CREATE TABLE {table_name} ( {elements} ); ``` -**参数描述** +**参数说明** -- `{table_name}`: 表名。 -- `{elements}`: 以逗号分隔的表元素列表,比如列定义,主键定义等。 +- `{table_name}`:要创建的表的名称。 +- `{elements}`:以逗号分隔的表元素列表,如列定义和主键定义。 -假设你需要创建一个表来存储 `bookshop` 库中的用户信息。 +假设你需要在 `bookshop` 数据库中创建一个表来存储用户信息。 -注意,此时因为一个列都没被添加,所以下方这条 SQL 暂时还不能被运行: +注意,你还不能执行以下 SQL 语句,因为还没有添加任何列。 ```sql CREATE TABLE `bookshop`.`users` ( @@ -49,21 +45,21 @@ CREATE TABLE `bookshop`.`users` ( ## 定义列 -**列**从属于表,每张表都至少有一**列**。**列**通过将每行中的值分成一个个单一数据类型的小单元来为表提供结构。 +**列**从属于表。每个表至少有一列。列通过将每行中的值划分为单一数据类型的小单元,为表提供结构。 -列定义通常使用以下形式: +列定义通常采用以下形式: ``` {column_name} {data_type} {column_qualification} ``` -**参数描述** +**参数说明** - `{column_name}`:列名。 -- `{data_type}`:列的[数据类型](/basic-features.md#数据类型函数和操作符)。 -- `{column_qualification}`:列的限定条件,如**列级约束**或[生成列](/generated-columns.md)子句。 +- `{data_type}`:列的[数据类型](/data-type-overview.md)。 +- `{column_qualification}`:列限定符,如**列级约束**或[生成列](/generated-columns.md)子句。 -可以为 `users` 表添加一些列,如他们的唯一标识 `id`,余额 `balance` 及昵称 `nickname`。 +你可以向 `users` 表添加一些列,如唯一标识符 `id`、`balance` 和 `nickname`。 ```sql CREATE TABLE `bookshop`.`users` ( @@ -73,15 +69,15 @@ CREATE TABLE `bookshop`.`users` ( ); ``` -其中,定义了一个字段名为 `id`,类型为 [bigint](/data-type-numeric.md#bigint-类型) 的字段。用以表示用户唯一标识。这意味着,所有的用户标识都应该是 `bigint` 类型的。 +在上述语句中,定义了一个名为 `id` 且类型为 [bigint](/data-type-numeric.md#bigint-type) 的字段。这用于表示唯一的用户标识符。这意味着所有用户标识符都应该是 `bigint` 类型。 -而在其后,又定义了一个字段名为 `nickname`,类型为 [varchar](/data-type-string.md#varchar-类型),且长度不得超过 100 字符的字段。用以表示用户的昵称。这意味着,所用用户的昵称都是 `varchar` 类型,且不超过 100 字符的。 +然后,定义了一个名为 `nickname` 的字段,它是 [varchar](/data-type-string.md#varchar-type) 类型,长度限制为 100 个字符。这意味着用户的 `nicknames` 使用 `varchar` 类型,且不超过 100 个字符。 -最后,又加入了一个字段名为 `balance` 用以表示用户的余额,类型为 [decimal](/data-type-numeric.md#decimal-类型),且其精度为 15,比例为 2。简单的说明一下精度和比例代表的含义,精度代表字段数值的总位数,而比例代表小数点后有多少位。例如: `decimal(5,2)`,即精度为 5,比例为 2 时,其取值范围为 `-999.99` 到 `999.99`。`decimal(6,1)`,即精度为 6,比例为 1 时,其取值范围为 `-99999.9` 到 `99999.9`。`decimal` 类型为定点数,可精确保存数字,在需要精确数字的场景(如用户财产相关)中,请确保使用[定点数](/data-type-numeric.md#定点类型)类型。 +最后,添加了一个名为 `balance` 的字段,它是 [decimal](/data-type-numeric.md#decimal-type) 类型,具有 `15` 的**精度**和 `2` 的**小数位数**。**精度**表示字段中的总位数,**小数位数**表示小数点后的位数。例如,`decimal(5,2)` 表示精度为 `5`,小数位数为 `2`,范围从 `-999.99` 到 `999.99`。`decimal(6,1)` 表示精度为 `6`,小数位数为 `1`,范围从 `-99999.9` 到 `99999.9`。**decimal** 是一种[定点类型](/data-type-numeric.md#fixed-point-types),可以用来精确存储数字。在需要精确数字的场景(例如,与用户资产相关的场景)中,请确保使用 **decimal** 类型。 -TiDB 支持许多其他的列数据类型,包含[整数](/data-type-numeric.md#整数类型)、[浮点数](/data-type-numeric.md#浮点类型)、[定点数](/data-type-numeric.md#定点类型)、[时间](/data-type-date-and-time.md#datetime-类型)、[枚举](/data-type-string.md#enum-类型) 等,可参考支持的列的[数据类型](/basic-features.md#数据类型函数和操作符),并使用与你准备保存在数据库内的数据匹配的**数据类型**。 +TiDB 支持许多其他列数据类型,包括[整数类型](/data-type-numeric.md#integer-types)、[浮点类型](/data-type-numeric.md#floating-point-types)、[定点类型](/data-type-numeric.md#fixed-point-types)、[日期和时间类型](/data-type-date-and-time.md)以及[枚举类型](/data-type-string.md#enum-type)。你可以参考支持的列[数据类型](/data-type-overview.md),并使用与你想要在数据库中保存的数据相匹配的**数据类型**。 -稍微提升一下复杂度,例如选择定义一张 `books` 表,这张表将是 `bookshop` 数据的核心。它包含书的唯一标识、名称、书籍类型(如:杂志、动漫、教辅等)、库存、价格、出版时间等字段。 +让我们再复杂一点,你可以定义一个 `books` 表,这将是 `bookshop` 数据的核心。`books` 表包含书籍的 ID、标题、类型(例如,杂志、小说、生活、艺术)、库存、价格和出版日期等字段。 ```sql CREATE TABLE `bookshop`.`books` ( @@ -94,31 +90,37 @@ CREATE TABLE `bookshop`.`books` ( ); ``` -这张表比 `users` 表包含更多的数据类型: +这个表包含的数据类型比 `users` 表更多。 -- [int](/data-type-numeric.md#integer-类型): 推荐使用合适大小的类型,防止使用过量的硬盘甚至影响性能(类型范围过大)或数据溢出(类型范围过小)。 -- [datetime](/basic-features.md#数据类型函数和操作符): 可以使用 **datetime** 类型保存时间值。 -- [enum](/data-type-string.md#enum-类型): 可以使用 **enum** 类型的枚举来保存有限选择的值。 +- [int](/data-type-numeric.md#integer-types):建议使用合适大小的类型,以避免使用过多磁盘空间甚至影响性能(类型范围过大)或数据溢出(数据类型范围过小)。 +- [datetime](/data-type-date-and-time.md):**datetime** 类型可用于存储时间值。 +- [enum](/data-type-string.md#enum-type):枚举类型可用于存储有限的选择值。 ## 选择主键 -[主键](/constraints.md#主键约束)是一个或一组列,这个由所有主键列组合起来的值是数据行的唯一标识。 +[主键](/constraints.md#primary-key)是表中的一列或一组列,其值唯一标识表中的一行。 > **注意:** > -> TiDB 中,关于 **Primary Key** 的默认定义与 MySQL 常用存储引擎 [InnoDB](https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html) 不一致。**InnoDB** 中,**Primary Key** 的语义为:唯一,不为空,**且为聚簇索引**。 +> TiDB 中**主键**的默认定义与 [InnoDB](https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html)(MySQL 的常用存储引擎)中的不同。 +> +> - 在 **InnoDB** 中:**主键**是唯一的、非空的,并且是**聚簇索引**。 > -> 而在 TiDB 中,**Primary Key** 的定义为:唯一,不为空。但主键不保证为**聚簇索引**。而是由另一组关键字 `CLUSTERED`、`NONCLUSTERED` 额外控制 **Primary Key** 是否为聚簇索引,若不指定,则由系统变量 `@@global.tidb_enable_clustered_index` 影响,具体说明请看[此文档](/clustered-indexes.md)。 +> - 在 TiDB 中:**主键**是唯一的且非空的。但主键不保证是**聚簇索引**。相反,另一组关键字 `CLUSTERED` / `NONCLUSTERED` 额外控制**主键**是否为**聚簇索引**。如果未指定关键字,则由系统变量 `@@global.tidb_enable_clustered_index` 控制,如[聚簇索引](https://docs.pingcap.com/tidb/stable/clustered-indexes)中所述。 -主键在 `CREATE TABLE` 语句中定义。[主键约束](/constraints.md#主键约束)要求所有受约束的列仅包含非 `NULL` 值。 +**主键**在 `CREATE TABLE` 语句中定义。[主键约束](/constraints.md#primary-key)要求所有受约束的列只包含非空值。 -一个表可以没有主键,主键也可以是非整数类型。但此时 TiDB 就会创建一个 `_tidb_rowid` 作为隐式主键。隐式主键 `_tidb_rowid` 因为其单调递增的特性,可能在大批量写入场景下会导致写入热点,如果你写入量密集,可考虑通过 [SHARD_ROW_ID_BITS](/shard-row-id-bits.md) 和 [PRE_SPLIT_REGIONS](/sql-statements/sql-statement-split-region.md#pre_split_regions) 两参数控制打散。但这可能导致读放大,请自行取舍。 +可以创建没有**主键**或具有非整数**主键**的表。在这种情况下,TiDB 会创建一个 `_tidb_rowid` 作为**隐式主键**。隐式主键 `_tidb_rowid` 由于其单调递增的特性,可能会在写入密集的场景中造成写入热点。因此,如果你的应用程序是写入密集型的,请考虑使用 [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md) 和 [`PRE_SPLIT_REGIONS`](/sql-statements/sql-statement-split-region.md#pre_split_regions) 参数对数据进行分片。但是,这可能会导致读放大,所以你需要权衡取舍。 -表的主键为[整数类型](/data-type-numeric.md#整数类型)且使用了 `AUTO_INCREMENT` 时,无法使用 `SHARD_ROW_ID_BITS` 消除热点。需解决此热点问题,且无需使用主键的连续和递增时,可使用 [AUTO_RANDOM](/auto-random.md) 替换 `AUTO_INCREMENT` 属性来消除行 ID 的连续性。 +当表的**主键**是[整数类型](/data-type-numeric.md#integer-types)并且使用 `AUTO_INCREMENT` 时,无法通过使用 `SHARD_ROW_ID_BITS` 来避免热点。如果你需要避免热点并且不需要连续递增的主键,可以使用 [`AUTO_RANDOM`](/auto-random.md) 代替 `AUTO_INCREMENT` 来消除行 ID 的连续性。 -更多有关热点问题的处理办法,请参考[TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md)。 + -需遵循[选择主键时应遵守的规则](#选择主键时应遵守的规则),举一个 `users` 表中定义 `AUTO_RANDOM` 主键的例子: +有关如何处理热点问题的更多信息,请参考[热点问题处理](/troubleshoot-hot-spot-issues.md)。 + + + +按照[选择主键的指南](#选择主键时需要遵循的指南),以下示例展示了如何在 `users` 表中定义 `AUTO_RANDOM` 主键。 ```sql CREATE TABLE `bookshop`.`users` ( @@ -129,25 +131,27 @@ CREATE TABLE `bookshop`.`users` ( ); ``` -## 选择聚簇索引 +## 聚簇或非聚簇 + +TiDB 从 v5.0 开始支持[聚簇索引](/clustered-indexes.md)功能。此功能控制包含主键的表中数据的存储方式。它使 TiDB 能够以可以提高某些查询性能的方式组织表。 -[聚簇索引](/clustered-indexes.md) (clustered index) 是 TiDB 从 v5.0 开始支持的特性,用于控制含有主键的表数据的存储方式。通过使用聚簇索引,TiDB 可以更好地组织数据表,从而提高某些查询的性能。有些数据库管理系统将聚簇索引表称为“索引组织表” (index-organized tables)。 +此上下文中的聚簇指的是数据存储的组织方式,而不是一组数据库服务器的协同工作。一些数据库管理系统将聚簇索引表称为索引组织表(IOT)。 -目前 TiDB 中 **_含有主键_** 的表分为以下两类: +目前,TiDB 中**包含主键**的表分为以下两类: -- `NONCLUSTERED`,表示该表的主键为非聚簇索引。在非聚簇索引表中,行数据的键由 TiDB 内部隐式分配的 `_tidb_rowid` 构成,而主键本质上是唯一索引,因此非聚簇索引表存储一行至少需要两个键值对,分别为: +- `NONCLUSTERED`:表的主键是非聚簇索引。在具有非聚簇索引的表中,行数据的键由 TiDB 隐式分配的内部 `_tidb_rowid` 组成。由于主键本质上是唯一索引,具有非聚簇索引的表需要至少两个键值对来存储一行,即: - `_tidb_rowid`(键)- 行数据(值) - - 主键列数据(键) - `_tidb_rowid`(值) -- `CLUSTERED`,表示该表的主键为聚簇索引。在聚簇索引表中,行数据的键由用户给定的主键列数据构成,因此聚簇索引表存储一行至少只要一个键值对,即: - - 主键列数据(键) - 行数据(值) + - 主键数据(键)- `_tidb_rowid`(值) +- `CLUSTERED`:表的主键是聚簇索引。在具有聚簇索引的表中,行数据的键由用户给定的主键数据组成。因此,具有聚簇索引的表只需要一个键值对来存储一行,即: + - 主键数据(键)- 行数据(值) -如[主键](#选择主键)中所述,聚簇索引在 TiDB 中,使用关键字 `CLUSTERED`、`NONCLUSTERED` 进行控制。 +如[选择主键](#选择主键)中所述,TiDB 使用关键字 `CLUSTERED` 和 `NONCLUSTERED` 来控制**聚簇索引**。 > **注意:** > -> TiDB 仅支持根据表的主键来进行聚簇操作。聚簇索引启用时,“主键”和“聚簇索引”两个术语在一些情况下可互换使用。主键指的是约束(一种逻辑属性),而聚簇索引描述的是数据存储的物理实现。 +> TiDB 仅支持通过表的 `PRIMARY KEY` 进行聚簇。启用聚簇索引后,术语 `PRIMARY KEY` 和聚簇索引可能会互换使用。`PRIMARY KEY` 指的是约束(逻辑属性),而聚簇索引描述了数据存储的物理实现方式。 -需遵循[选择聚簇索引时应遵守的规则](#选择聚簇索引时应遵守的规则),假设需要建立一张 `books` 和 `users` 之间关联的表,代表用户对某书籍的评分。使用表名 `ratings` 来创建该表,并使用 `book_id` 和 `user_id` 构建[复合主键](/constraints.md#主键约束),并在该主键上建立聚簇索引: +按照[选择聚簇索引的指南](#选择聚簇索引时需要遵循的指南),以下示例创建了一个 `books` 和 `users` 之间的关联表,表示用户对书籍的 `ratings`。该示例创建表并使用 `book_id` 和 `user_id` 构造复合主键,并在该**主键**上创建**聚簇索引**。 ```sql CREATE TABLE `bookshop`.`ratings` ( @@ -158,16 +162,15 @@ CREATE TABLE `bookshop`.`ratings` ( PRIMARY KEY (`book_id`,`user_id`) CLUSTERED ); ``` - ## 添加列约束 -除[主键约束](#选择主键)外,TiDB 还支持其他的列约束,如:[非空约束 `NOT NULL`](/constraints.md#非空约束)、[唯一约束 `UNIQUE KEY`](/constraints.md#唯一约束)、默认值 `DEFAULT` 等。完整约束,请查看 [TiDB 约束](/constraints.md)文档。 +除了[主键约束](#选择主键)外,TiDB 还支持其他**列约束**,如 [NOT NULL](/constraints.md#not-null) 约束、[UNIQUE KEY](/constraints.md#unique-key) 约束和 `DEFAULT`。有关完整约束,请参考 [TiDB 约束](/constraints.md)文档。 -### 填充默认值 +### 设置默认值 -如需在列上设置默认值,请使用 `DEFAULT` 约束。默认值将可以使你无需指定每一列的值,就可以插入数据。 +要在列上设置默认值,请使用 `DEFAULT` 约束。默认值允许你在不为每列指定值的情况下插入数据。 -你可以将 `DEFAULT` 与[支持的 SQL 函数](/basic-features.md#数据类型函数和操作符)结合使用,将默认值的计算移出应用层,从而节省应用层的资源(当然,计算所消耗的资源并不会凭空消失,只是被转移到了 TiDB 集群中)。常见的,希望实现数据插入时,可默认填充默认的时间。还是使用 `ratings` 作为示例,可使用以下语句: +你可以将 `DEFAULT` 与[支持的 SQL 函数](/functions-and-operators/functions-and-operators-overview.md)一起使用,将默认值的计算从应用层移出,从而节省应用层的资源。计算消耗的资源并没有消失,而是移到了 TiDB 集群。通常,你可以使用默认时间插入数据。以下示例展示了在 `ratings` 表中设置默认值: ```sql CREATE TABLE `bookshop`.`ratings` ( @@ -179,7 +182,7 @@ CREATE TABLE `bookshop`.`ratings` ( ); ``` -此外,如需在数据更新时也默认填入当前时间,可使用以下语句(但 `ON UPDATE` 后仅可填入与当前时间相关的表达式): +此外,如果在更新数据时也需要默认填充当前时间,可以使用以下语句(但在 `ON UPDATE` 后只能填写与当前时间相关的表达式): ```sql CREATE TABLE `bookshop`.`ratings` ( @@ -191,13 +194,13 @@ CREATE TABLE `bookshop`.`ratings` ( ); ``` -关于不同数据类型默认值的更多信息,请参阅[数据类型的默认值](/data-type-default-values.md)。 +有关不同数据类型的默认值的更多信息,请参见[默认值](/data-type-default-values.md)。 -### 防止重复 +### 防止重复值 -如果你需要防止列中出现重复值,那你可以使用 `UNIQUE` 约束。 +如果你需要防止列中出现重复值,可以使用 `UNIQUE` 约束。 -例如,你需要确保用户的昵称唯一,可以这样改写 `users` 表的创建 SQL: +例如,要确保用户昵称是唯一的,你可以这样重写 `users` 表的创建 SQL 语句: ```sql CREATE TABLE `bookshop`.`users` ( @@ -208,13 +211,13 @@ CREATE TABLE `bookshop`.`users` ( ); ``` -如果你在 `users` 表中尝试插入相同的 `nickname`,将返回错误。 +如果你尝试在 `users` 表中插入相同的 `nickname`,将返回错误。 ### 防止空值 -如果你需要防止列中出现空值,那就可以使用 `NOT NULL` 约束。 +如果你需要防止列中出现空值,可以使用 `NOT NULL` 约束。 -还是使用用户昵称来举例子,除了昵称唯一,还希望昵称不可为空,于是此处可以这样改写 `users` 表的创建 SQL: +以用户昵称为例。要确保昵称不仅唯一而且不为空,你可以这样重写创建 `users` 表的 SQL 语句: ```sql CREATE TABLE `bookshop`.`users` ( @@ -225,38 +228,62 @@ CREATE TABLE `bookshop`.`users` ( ); ``` -## 使用 HTAP 能力 +## 使用 HTAP 功能 + + + +> **注意:** +> +> 本指南中提供的步骤**仅**适用于测试环境的快速入门。对于生产环境,请参考[探索 HTAP](/explore-htap.md)。 + + + + > **注意:** > -> 本指南中有关 HTAP 的步骤仅适用于快速上手体验,不适用于生产环境。如需探索 HTAP 更多功能,请参考[深入探索 HTAP](/explore-htap.md)。 +> 本指南中提供的步骤**仅**适用于快速入门。有关更多说明,请参考[使用带有 TiFlash 的 HTAP 集群](/tiflash/tiflash-overview.md)。 + + + +假设你想对 `bookshop` 应用程序中的 `ratings` 表进行 OLAP 分析,例如,查询**书籍评分是否与评分时间有显著相关性**,这是为了分析用户对书籍的评分是否客观。那么你需要查询整个 `ratings` 表的 `score` 和 `rated_at` 字段。这个操作对于仅支持 OLTP 的数据库来说是资源密集型的。或者你可以使用一些 ETL 或其他数据同步工具将数据从 OLTP 数据库导出到专用的 OLAP 数据库进行分析。 + +在这种场景下,TiDB 作为一个支持 OLTP 和 OLAP 场景的 **HTAP(混合事务和分析处理)**数据库,是一个理想的一站式数据库解决方案。 + +### 复制列式数据 + + + +目前,TiDB 支持两个数据分析引擎,**TiFlash** 和 **TiSpark**。对于大数据场景(100 T),推荐使用 **TiFlash MPP** 作为 HTAP 的主要解决方案,**TiSpark** 作为补充解决方案。 -假设 `bookshop` 应用程序,有对用户评价的 `ratings` 表进行 OLAP 分析查询的需求,例如需查询: **书籍的评分,是否和评价的时间具有显著的相关性** 的需求,用以分析用户的书籍评分是否客观。那么会要求查询整个 `ratings` 表中的 `score` 和 `rated_at` 字段。这对普通仅支持的 OLTP 的数据库来说,是一个非常消耗资源的操作。或者使用一些 ETL 或其他数据同步工具,将 OLTP 数据库中的数据,导出到专用的 OLAP 数据库,再进行分析。 +要了解更多关于 TiDB HTAP 功能的信息,请参考以下文档:[TiDB HTAP 快速入门指南](/quick-start-with-htap.md)和[探索 HTAP](/explore-htap.md)。 -这种场景下,TiDB 就是一个比较理想的一站式数据库解决方案,TiDB 是一个 **HTAP (Hybrid Transactional and Analytical Processing)** 数据库,同时支持 OLTP 和 OLAP 场景。 + -### 同步列存数据 + -当前,TiDB 支持两种数据分析引擎:**TiFlash** 和 **TiSpark**。大数据场景 (100 T) 下,推荐使用 TiFlash MPP 作为 HTAP 的主要方案,TiSpark 作为补充方案。希望了解更多关于 TiDB 的 HTAP 能力,可参考以下文章:[快速上手 HTAP](/quick-start-with-htap.md) 和[深入探索 HTAP](/explore-htap.md)。 +要了解更多关于 TiDB HTAP 功能的信息,请参见 [TiDB Cloud HTAP 快速入门](/tidb-cloud/tidb-cloud-htap-quickstart.md)和[使用带有 TiFlash 的 HTAP 集群](/tiflash/tiflash-overview.md)。 -此处选用 [TiFlash](/tiflash/tiflash-overview.md) 为 `bookshop` 数据库的数据分析引擎。 + -TiFlash 部署完成后并不会自动同步数据,而需要手动指定需要同步的表,开启同步副本仅需一行 SQL,如下所示: +在本例中,选择了 [TiFlash](https://docs.pingcap.com/tidb/stable/tiflash-overview) 作为 `bookshop` 数据库的数据分析引擎。 + +TiFlash 在部署后不会自动复制数据。因此,你需要手动指定要复制的表: ```sql ALTER TABLE {table_name} SET TIFLASH REPLICA {count}; ``` -**参数描述** +**参数说明** -- `{table_name}`: 表名。 -- `{count}`: 同步副本数,若为 0,则表示删除同步副本。 +- `{table_name}`:表名。 +- `{count}`:复制副本的数量。如果为 0,则删除复制副本。 -随后,TiFlash 将同步该表,查询时,TiDB 将会自动基于成本优化,考虑使用 **TiKV (行存)** 或 **TiFlash (列存)** 进行数据查询。当然,除了自动的方法,你也可以直接指定查询是否使用 TiFlash 副本,使用方法可查看[使用 TiDB 读取 TiFlash](/tiflash/use-tidb-to-read-tiflash.md) 文档。 +**TiFlash** 随后将复制该表。当执行查询时,TiDB 会根据成本优化自动选择使用 TiKV(行式)或 TiFlash(列式)进行查询。或者,你可以手动指定查询是否使用 **TiFlash** 副本。要了解如何指定,请参考[使用 TiDB 读取 TiFlash 副本](/tiflash/use-tidb-to-read-tiflash.md)。 -### 使用 HTAP 的示例 +### HTAP 功能使用示例 -`ratings` 表开启 1 个 TiFlash 副本: +为 `ratings` 表开启 `1` 个 TiFlash 副本: ```sql ALTER TABLE `bookshop`.`ratings` SET TIFLASH REPLICA 1; @@ -264,23 +291,23 @@ ALTER TABLE `bookshop`.`ratings` SET TIFLASH REPLICA 1; > **注意:** > -> 如果你的集群,不包含 TiFlash 节点,此 SQL 语句将会报错:`1105 - the tiflash replica count: 1 should be less than the total tiflash server count: 0` 你可以[使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群) 来创建一个含有 TiFlash 的集群。 +> 如果你的集群不包含 **TiFlash** 节点,这条 SQL 语句会报错:`1105 - the tiflash replica count: 1 should be less than the total tiflash server count: 0`。你可以使用[构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#step-1-create-a-tidb-cloud-serverless-cluster)来创建一个包含 **TiFlash** 的 TiDB Cloud Serverless 集群。 -随后正常进行查询即可: +然后你可以执行以下查询: ```sql SELECT HOUR(`rated_at`), AVG(`score`) FROM `bookshop`.`ratings` GROUP BY HOUR(`rated_at`); ``` -也可使用 [EXPLAIN ANALYZE](/sql-statements/sql-statement-explain-analyze.md) 语句查看此语句是否使用了 TiFlash 引擎: +你还可以执行 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句来查看此语句是否使用了 **TiFlash**: ```sql EXPLAIN ANALYZE SELECT HOUR(`rated_at`), AVG(`score`) FROM `bookshop`.`ratings` GROUP BY HOUR(`rated_at`); ``` -运行结果为: +运行结果: -``` +```sql +-----------------------------+-----------+---------+--------------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-----------------------------+-----------+---------+--------------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+ @@ -292,13 +319,12 @@ EXPLAIN ANALYZE SELECT HOUR(`rated_at`), AVG(`score`) FROM `bookshop`.`ratings` +-----------------------------+-----------+---------+--------------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+ ``` -在出现 `cop[tiflash]` 字样时,表示该任务发送至 TiFlash 进行处理。 - +当出现字段 `cop[tiflash]` 时,表示任务被发送到 **TiFlash** 进行处理。 ## 执行 `CREATE TABLE` 语句 -按以上步骤创建所有表后,[数据库初始化](/develop/dev-guide-bookshop-schema-design.md#数据库初始化-dbinitsql-脚本)脚本应该如此所示。若需查看表信息详解,请参阅[数据表详解](/develop/dev-guide-bookshop-schema-design.md#数据表详解)。 +按照上述规则创建所有表后,我们的[数据库初始化](/develop/dev-guide-bookshop-schema-design.md#database-initialization-script-dbinitsql)脚本应该是这样的。如果你需要查看详细的表信息,请参考[表的描述](/develop/dev-guide-bookshop-schema-design.md#description-of-the-tables)。 -如果将数据库初始化脚本命名为 `init.sql` 并保存,可使用以下语句来执行数据库初始化: +将数据库初始化脚本命名为 `init.sql` 并保存,你可以执行以下语句来初始化数据库。 ```shell mysql @@ -309,13 +335,13 @@ mysql < init.sql ``` -需查看 `bookshop` 数据库下的所有表,可使用 [SHOW TABLES](/sql-statements/sql-statement-show-tables.md#show-full-tables) 语句: +要查看 `bookshop` 数据库下的所有表,使用 [`SHOW TABLES`](/sql-statements/sql-statement-show-tables.md#show-full-tables) 语句。 ```sql SHOW TABLES IN `bookshop`; ``` -运行结果为: +运行结果: ``` +--------------------+ @@ -330,60 +356,68 @@ SHOW TABLES IN `bookshop`; +--------------------+ ``` -## 创建表时应遵守的规则 +## 创建表时需要遵循的指南 + +本节提供了创建表时需要遵循的指南。 + +### 命名表时需要遵循的指南 -本小节给出了一些在创建表时应遵守的规则。 +- 使用**完全限定**的表名(例如,`CREATE TABLE {database_name}. {table_name}`)。如果不指定数据库名称,TiDB 将使用你的 **SQL 会话**中的当前数据库。如果你没有使用 `USE {databasename};` 在 SQL 会话中指定数据库,TiDB 将返回错误。 +- 使用有意义的表名。例如,如果你需要创建一个用户表,你可以使用以下名称:`user`、`t_user`、`users`,或遵循你公司或组织的命名约定。如果你的公司或组织没有命名约定,你可以参考[表命名约定](/develop/dev-guide-object-naming-guidelines.md#table-naming-convention)。不要使用这样的表名:`t1`、`table1`。 +- 多个单词用下划线分隔,建议名称不超过 32 个字符。 +- 为不同业务模块的表创建单独的 `DATABASE`,并添加相应的注释。 -### 命名表时应遵守的规则 +### 定义列时需要遵循的指南 -- 使用**完全限定**的表名称(例如:`CREATE TABLE {database_name}.{table_name}`)。这是因为你在不指定数据库名称时,TiDB 将使用你 **SQL 会话**中的[当前数据库](/sql-statements/sql-statement-use.md)。若你未在 SQL 会话中使用 `USE {databasename};` 来指定数据库,TiDB 将会返回错误。 -- 请使用有意义的表名,例如,若你需要创建一个用户表,你可以使用名称:`user`, `t_user`, `users` 等,或遵循你公司或组织的命名规范。如果你的公司或组织没有相应的命名规范,可参考[表命名规范](/develop/dev-guide-object-naming-guidelines.md#表命名规范)。请勿使用这样的表名,如:`t1`, `table1` 等。 -- 多个单词以下划线分隔,不推荐超过 32 个字符。 -- 不同业务模块的表单独建立 `DATABASE`,并增加相应注释。 +- 检查列支持的[数据类型](/data-type-overview.md),并根据数据类型限制组织数据。为计划存储在列中的数据选择适当的类型。 +- 检查[选择主键的指南](#选择主键时需要遵循的指南),并决定是否使用主键列。 +- 检查[选择聚簇索引的指南](#选择聚簇索引时需要遵循的指南),并决定是否指定**聚簇索引**。 +- 检查[添加列约束](#添加列约束),并决定是否向列添加约束。 +- 使用有意义的列名。建议遵循你公司或组织的表命名约定。如果你的公司或组织没有相应的命名约定,请参考[列命名约定](/develop/dev-guide-object-naming-guidelines.md#column-naming-convention)。 -### 定义列时应遵守的规则 +### 选择主键时需要遵循的指南 -- 查看支持的列的[数据类型](/basic-features.md#数据类型函数和操作符),并按照数据类型的限制来组织你的数据。为你计划被存在列中的数据选择合适的类型。 -- 查看[选择主键时应遵守的规则](#选择主键时应遵守的规则),决定是否使用主键列。 -- 查看[选择聚簇索引时应遵守的规则](#选择聚簇索引时应遵守的规则),决定是否指定聚簇索引。 -- 查看[添加列约束](#添加列约束),决定是否添加约束到列中。 -- 请使用有意义的列名,推荐你遵循公司或组织的表命名规范。如果你的公司或组织没有相应的命名规范,可参考[列命名规范](/develop/dev-guide-object-naming-guidelines.md#字段命名规范)。 +- 在表中定义**主键**或**唯一索引**。 +- 尽量选择有意义的**列**作为**主键**。 +- 出于性能考虑,尽量避免存储过宽的表。不建议表字段数超过 `60` 个,单行数据总大小超过 `64K`。建议将数据长度过大的字段拆分到另一个表。 +- 不建议使用复杂的数据类型。 +- 对于要进行连接的字段,确保数据类型一致,避免隐式转换。 +- 避免在单个单调数据列上定义**主键**。如果你使用单个单调数据列(例如,具有 `AUTO_INCREMENT` 属性的列)来定义**主键**,可能会影响写入性能。如果可能,使用 `AUTO_RANDOM` 代替 `AUTO_INCREMENT`,这样可以放弃主键的连续和递增属性。 +- 如果你确实需要在写入密集的场景下在单个单调数据列上创建索引,不要将这个单调数据列定义为**主键**,你可以使用 `AUTO_RANDOM` 为该表创建**主键**,或使用 [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md) 和 [`PRE_SPLIT_REGIONS`](/sql-statements/sql-statement-split-region.md#pre_split_regions) 对 `_tidb_rowid` 进行分片。 -### 选择主键时应遵守的规则 +### 选择聚簇索引时需要遵循的指南 -- 在表内定义一个主键或唯一索引。 -- 尽量选择有意义的列作为主键。 -- 出于为性能考虑,尽量避免存储超宽表,表字段数不建议超过 60 个,建议单行的总数据大小不要超过 64K,数据长度过大字段最好拆到另外的表。 -- 不推荐使用复杂的数据类型。 -- 需要 JOIN 的字段,数据类型保障绝对一致,避免隐式转换。 -- 避免在单个单调数据列上定义主键。如果你使用单个单调数据列(例如:`AUTO_INCREMENT` 的列)来定义主键,有可能会对写性能产生负面影响。可能的话,使用 `AUTO_RANDOM` 替换 `AUTO_INCREMENT`(这会失去主键的连续和递增特性)。 -- 如果你 **_必须_** 在单个单调数据列上创建索引,且有大量写入的话。请不要将这个单调数据列定义为主键,而是使用 `AUTO_RANDOM` 创建该表的主键,或使用 [SHARD_ROW_ID_BITS](/shard-row-id-bits.md) 和 [PRE_SPLIT_REGIONS](/sql-statements/sql-statement-split-region.md#pre_split_regions) 打散 `_tidb_rowid`。 +- 遵循[选择主键的指南](#选择主键时需要遵循的指南)来构建**聚簇索引**。 +- 与具有非聚簇索引的表相比,具有聚簇索引的表在以下场景中提供更大的性能和吞吐量优势: + - 插入数据时,聚簇索引减少了一次网络中索引数据的写入。 + - 当查询只涉及主键的等值条件时,聚簇索引减少了一次网络中索引数据的读取。 + - 当查询只涉及主键的范围条件时,聚簇索引减少了多次网络中索引数据的读取。 + - 当查询只涉及主键前缀的等值或范围条件时,聚簇索引减少了多次网络中索引数据的读取。 +- 另一方面,具有聚簇索引的表可能会有以下问题: + - 当你插入大量值接近的主键时,可能会出现写入热点问题。遵循[选择主键时需要遵循的指南](#选择主键时需要遵循的指南)。 + - 如果主键的数据类型大于 64 位,特别是当有多个二级索引时,表数据会占用更多存储空间。 -### 选择聚簇索引时应遵守的规则 +- 要控制[是否使用聚簇索引的默认行为](/clustered-indexes.md#create-a-table-with-clustered-indexes),你可以显式指定是否使用聚簇索引,而不是使用系统变量 `@@global.tidb_enable_clustered_index` 和配置 `alter-primary-key`。 -- 遵循[选择主键时应遵守的规则](#选择主键时应遵守的规则): +### 执行 `CREATE TABLE` 语句时需要遵循的指南 - 聚簇索引将基于主键建立,请遵循选择主键时应遵守的规则,此为选择聚簇索引时应遵守规则的基础。 +- 不建议使用客户端 Driver 或 ORM 进行数据库架构更改。建议使用 [MySQL 客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)或使用 GUI 客户端进行数据库架构更改。在本文档中,大多数场景下使用 **MySQL 客户端**传入 SQL 文件来执行数据库架构更改。 +- 遵循[创建和删除表的 SQL 开发规范](/develop/dev-guide-sql-development-specification.md#create-and-delete-tables)。建议在业务应用程序内部包装构建和删除语句,添加判断逻辑。 -- 在以下场景中,尽量使用聚簇索引,将带来性能和吞吐量的优势: +## 下一步 - - 插入数据时会减少一次从网络写入索引数据。 - - 等值条件查询仅涉及主键时会减少一次从网络读取数据。 - - 范围条件查询仅涉及主键时会减少多次从网络读取数据。 - - 等值或范围条件查询仅涉及主键的前缀时会减少多次从网络读取数据。 +请注意,本文档中创建的所有表都不包含二级索引。有关添加二级索引的指南,请参考[创建二级索引](/develop/dev-guide-create-secondary-indexes.md)。 -- 在以下场景中,尽量避免使用聚簇索引,将带来性能劣势: +## 需要帮助? - - 批量插入大量取值相邻的主键时,可能会产生较大的写热点问题,请遵循[选择主键时应遵守的规则](#选择主键时应遵守的规则)。 - - 当使用大于 64 位的数据类型作为主键时,可能导致表数据需要占用更多的存储空间。该现象在存在多个二级索引时尤为明显。 + -- 显式指定是否使用聚簇索引,而非使用系统变量 `@@global.tidb_enable_clustered_index` 及配置项 `alter-primary-key` 控制是否使用[聚簇索引的默认行为](/clustered-indexes.md#创建聚簇索引表)。 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](/support.md)。 -### `CREATE TABLE` 执行时应遵守的规则 + -- 不推荐使用客户端的 Driver 或 ORM 来执行数据库模式的更改。基于过往经验,建议使用 [MySQL 客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)或使用任意你喜欢的 GUI 客户端来进行数据库模式的更改。本文档中,将在大多数场景下,使用 **MySQL 客户端** 传入 SQL 文件来执行数据库模式的更改。 -- 遵循 SQL 开发规范中的[建表删表规范](/develop/dev-guide-sql-development-specification.md#建表删表规范),建议业务应用内部封装建表删表语句增加判断逻辑。 + -## 更进一步 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](https://tidb.support.pingcap.com/)。 -请注意,到目前为止,创建的所有表都不包含二级索引。添加二级索引的指南,请参考[创建二级索引](/develop/dev-guide-create-secondary-indexes.md)。 + diff --git a/develop/dev-guide-delete-data.md b/develop/dev-guide-delete-data.md index 88283b6f7509..486898716713 100644 --- a/develop/dev-guide-delete-data.md +++ b/develop/dev-guide-delete-data.md @@ -1,76 +1,89 @@ --- title: 删除数据 -summary: 删除数据、批量删除数据的方法、最佳实践及例子。 +summary: 了解删除数据的 SQL 语法、最佳实践和示例。 --- # 删除数据 -此页面将使用 [DELETE](/sql-statements/sql-statement-delete.md) SQL 语句,对 TiDB 中的数据进行删除。如果需要周期性地删除过期数据,可以考虑使用 TiDB 的 [TTL 功能](/time-to-live.md)。 +本文档介绍如何使用 [DELETE](/sql-statements/sql-statement-delete.md) SQL 语句在 TiDB 中删除数据。如果你需要定期删除过期数据,请使用[数据生命周期管理](/time-to-live.md)功能。 -## 在开始之前 +## 开始之前 -在阅读本页面之前,你需要准备以下事项: +在阅读本文档之前,你需要准备以下内容: -- [使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 -- 阅读[数据库模式概览](/develop/dev-guide-schema-design-overview.md),并[创建数据库](/develop/dev-guide-create-database.md)、[创建表](/develop/dev-guide-create-table.md)、[创建二级索引](/develop/dev-guide-create-secondary-indexes.md)。 -- 需先[插入数据](/develop/dev-guide-insert-data.md)才可删除。 +- [创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md) +- 阅读[架构设计概述](/develop/dev-guide-schema-design-overview.md)、[创建数据库](/develop/dev-guide-create-database.md)、[创建表](/develop/dev-guide-create-table.md)和[创建二级索引](/develop/dev-guide-create-secondary-indexes.md) +- [插入数据](/develop/dev-guide-insert-data.md) ## SQL 语法 -在 SQL 中,`DELETE` 语句一般为以下形式: +`DELETE` 语句通常采用以下形式: ```sql DELETE FROM {table} WHERE {filter} ``` -| 参数 | 描述 | +| 参数名称 | 描述 | | :--------: | :------------: | -| `{table}` | 表名 | -| `{filter}` | 过滤器匹配条件 | +| `{table}` | 表名 | +| `{filter}` | 过滤条件的匹配条件 | -此处仅展示 `DELETE` 的简单用法,详细文档可参考 TiDB 的 [DELETE 语法](/sql-statements/sql-statement-delete.md)。 +此示例仅展示了 `DELETE` 的简单用法。有关详细信息,请参阅 [DELETE 语法](/sql-statements/sql-statement-delete.md)。 ## 最佳实践 -以下是删除行时需要遵循的一些最佳实践: +删除数据时,请遵循以下最佳实践: -- 始终在删除语句中指定 `WHERE` 子句。如果 `DELETE` 没有 `WHERE` 子句,TiDB 将删除这个表内的**_所有行_**。 -- 需要删除大量行(数万或更多)的时候,使用[批量删除](#批量删除),这是因为 TiDB 单个事务大小限制为 [txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit)(默认为 100MB)。 -- 如果你需要删除表内的所有数据,请勿使用 `DELETE` 语句,而应该使用 [TRUNCATE](/sql-statements/sql-statement-truncate.md) 语句。 -- 查看[性能注意事项](#性能注意事项)。 -- 在需要大批量删除数据的场景下,[非事务批量删除](#非事务批量删除)对性能的提升十分明显。但与之相对的,这将丢失删除的事务性,因此**无法**进行回滚,请务必正确进行操作选择。 +- 在 `DELETE` 语句中始终指定 `WHERE` 子句。如果未指定 `WHERE` 子句,TiDB 将删除表中的**_所有行_**。 -## 例子 + -假设在开发中发现在特定时间段内,发生了业务错误,需要删除这期间内的所有 [rating](/develop/dev-guide-bookshop-schema-design.md#ratings-表) 的数据,例如,`2022-04-15 00:00:00` 至 `2022-04-15 00:15:00` 的数据。此时,可使用 `SELECT` 语句查看需删除的数据条数: +- 当删除大量行(例如,超过一万行)时,请使用[批量删除](#批量删除),因为 TiDB 限制单个事务的大小([txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit),默认为 100 MB)。 + + + + + +- 当删除大量行(例如,超过一万行)时,请使用[批量删除](#批量删除),因为 TiDB 限制单个事务的大小默认为 100 MB。 + + + +- 如果要删除表中的所有数据,请不要使用 `DELETE` 语句。相反,请使用 [`TRUNCATE`](/sql-statements/sql-statement-truncate.md) 语句。 +- 关于性能考虑,请参阅[性能考虑事项](#性能考虑事项)。 +- 在需要删除大批量数据的场景中,[非事务性批量删除](#非事务性批量删除)可以显著提高性能。但是,这将失去删除操作的事务性,因此**无法**回滚。请确保你选择了正确的操作。 + +## 示例 + +假设你发现在特定时间段内出现了应用程序错误,需要删除这段时间内的所有 [ratings](/develop/dev-guide-bookshop-schema-design.md#ratings-table) 数据,例如从 `2022-04-15 00:00:00` 到 `2022-04-15 00:15:00`。在这种情况下,你可以使用 `SELECT` 语句检查要删除的记录数。 ```sql -SELECT COUNT(*) FROM `ratings` WHERE `rated_at` >= "2022-04-15 00:00:00" AND `rated_at` <= "2022-04-15 00:15:00"; +SELECT COUNT(*) FROM `ratings` WHERE `rated_at` >= "2022-04-15 00:00:00" AND `rated_at` <= "2022-04-15 00:15:00"; ``` -- 若返回数量大于 1 万条,请参考[批量删除](#批量删除)。 -- 若返回数量小于 1 万条,可参考下面的示例进行删除: +如果返回的记录超过 10,000 条,请使用[批量删除](#批量删除)来删除它们。 + +如果返回的记录少于 10,000 条,请使用以下示例删除它们。
-在 SQL 中,删除数据的示例如下: +在 SQL 中,示例如下: ```sql -DELETE FROM `ratings` WHERE `rated_at` >= "2022-04-15 00:00:00" AND `rated_at` <= "2022-04-15 00:15:00"; +DELETE FROM `ratings` WHERE `rated_at` >= "2022-04-15 00:00:00" AND `rated_at` <= "2022-04-15 00:15:00"; ```
-在 Java 中,删除数据的示例如下: +在 Java 中,示例如下: ```java -// ds is an entity of com.mysql.cj.jdbc.MysqlDataSource +// ds 是 com.mysql.cj.jdbc.MysqlDataSource 的实例 try (Connection connection = ds.getConnection()) { - String sql = "DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ?"; + String sql = "DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MILLISECOND, 0); @@ -91,7 +104,7 @@ try (Connection connection = ds.getConnection()) {
-在 Golang 中,删除数据的示例如下: +在 Golang 中,示例如下: ```go package main @@ -114,7 +127,7 @@ func main() { startTime := time.Date(2022, 04, 15, 0, 0, 0, 0, time.UTC) endTime := time.Date(2022, 04, 15, 0, 15, 0, 0, time.UTC) - bulkUpdateSql := fmt.Sprintf("DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ?") + bulkUpdateSql := fmt.Sprintf("DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ?") result, err := db.Exec(bulkUpdateSql, startTime, endTime) if err != nil { panic(err) @@ -130,13 +143,12 @@ func main() {
-在 Python 中,删除数据的示例如下: +在 Python 中,示例如下: ```python import MySQLdb import datetime import time - connection = MySQLdb.connect( host="127.0.0.1", port=4000, @@ -145,7 +157,6 @@ connection = MySQLdb.connect( database="bookshop", autocommit=True ) - with connection: with connection.cursor() as cursor: start_time = datetime.datetime(2022, 4, 15) @@ -159,83 +170,100 @@ with connection: + + +`rated_at` 字段是 [日期和时间类型](/data-type-date-and-time.md) 中的 `DATETIME` 类型。你可以假设它在 TiDB 中存储为一个字面量,与时区无关。另一方面,`TIMESTAMP` 类型存储时间戳,因此在不同的[时区](/configure-time-zone.md)中显示不同的时间字符串。 + + + + + +`rated_at` 字段是 [日期和时间类型](/data-type-date-and-time.md) 中的 `DATETIME` 类型。你可以假设它在 TiDB 中存储为一个字面量,与时区无关。另一方面,`TIMESTAMP` 类型存储时间戳,因此在不同的时区中显示不同的时间字符串。 + + + > **注意:** > -> `rated_at` 字段为[日期和时间类型](/data-type-date-and-time.md) 中的 `DATETIME` 类型,你可以认为它在 TiDB 保存时,存储为一个字面量,与时区无关。而 `TIMESTAMP` 类型,将会保存一个时间戳,从而在不同的[时区配置](/configure-time-zone.md)时,展示不同的时间字符串。 -> -> 另外,和 MySQL 一样,`TIMESTAMP` 数据类型受 [2038 年问题](https://zh.wikipedia.org/wiki/2038%E5%B9%B4%E9%97%AE%E9%A2%98)的影响。如果存储的值大于 2038,建议使用 `DATETIME` 类型。 +> 与 MySQL 一样,`TIMESTAMP` 数据类型受到 [2038 年问题](https://en.wikipedia.org/wiki/Year_2038_problem)的影响。如果你存储大于 2038 年的值,建议使用 `DATETIME` 类型。 -## 性能注意事项 +## 性能考虑事项 ### TiDB GC 机制 -`DELETE` 语句运行之后 TiDB 并非立刻删除数据,而是将这些数据标记为可删除。然后等待 TiDB GC (Garbage Collection) 来清理不再需要的旧数据。因此,你的 `DELETE` 语句**_并不会_**立即减少磁盘用量。 +TiDB 在执行 `DELETE` 语句后不会立即删除数据。相反,它会将数据标记为准备删除。然后等待 TiDB GC(垃圾回收)清理过期数据。因此,`DELETE` 语句**_不会_**立即减少磁盘使用量。 -GC 在默认配置中,为 10 分钟触发一次,每次 GC 都会计算出一个名为 **safe_point** 的时间点,这个时间点前的数据,都不会再被使用到,因此,TiDB 可以安全的对数据进行清除。 +默认情况下,GC 每 10 分钟触发一次。每次 GC 都会计算一个称为 **safe_point** 的时间点。任何早于此时间点的数据都不会再被使用,因此 TiDB 可以安全地清理它。 -GC 的具体实现方案和细节此处不再展开,请参考 [GC 机制简介](/garbage-collection-overview.md) 了解更详细的 GC 说明。 +有关更多信息,请参阅 [GC 机制](/garbage-collection-overview.md)。 ### 更新统计信息 -TiDB 使用[常规统计信息](/statistics.md)来决定索引的选择,因此,在大批量的数据删除之后,很有可能会导致索引选择不准确的情况发生。你可以使用[手动收集](/statistics.md#手动收集)的办法,更新统计信息。用以给 TiDB 优化器以更准确的统计信息来提供 SQL 性能优化。 +TiDB 使用[统计信息](/statistics.md)来确定索引选择。在删除大量数据后,索引未被正确选择的风险很高。你可以使用[手动收集](/statistics.md#手动收集)来更新统计信息。它为 TiDB 优化器提供更准确的统计信息,以优化 SQL 性能。 ## 批量删除 -需要删除表中多行的数据,可选择 [`DELETE` 示例](#例子),并使用 `WHERE` 子句过滤需要删除的数据。 +当你需要从表中删除多行数据时,可以选择 [`DELETE` 示例](#示例)并使用 `WHERE` 子句过滤需要删除的数据。 -但如果你需要删除大量行(数万或更多)的时候,建议使用一个迭代,每次都只删除一部分数据,直到删除全部完成。这是因为 TiDB 单个事务大小限制为 [txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit)(默认为 100MB)。你可以在程序或脚本中使用循环来完成操作。 + -本页提供了编写脚本来处理循环删除的示例,该示例演示了应如何进行 `SELECT` 和 `DELETE` 的组合,完成循环删除。 +但是,如果你需要删除大量行(超过一万行),建议你以迭代方式删除数据,即每次迭代删除一部分数据,直到删除完成。这是因为 TiDB 限制单个事务的大小([`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit),默认为 100 MB)。你可以在程序或脚本中使用循环来执行此类操作。 + + + + + +但是,如果你需要删除大量行(超过一万行),建议你以迭代方式删除数据,即每次迭代删除一部分数据,直到删除完成。这是因为 TiDB 限制单个事务的大小默认为 100 MB。你可以在程序或脚本中使用循环来执行此类操作。 + + + +本节提供了一个编写脚本处理迭代删除操作的示例,演示了如何组合使用 `SELECT` 和 `DELETE` 来完成批量删除。 ### 编写批量删除循环 -在你的应用或脚本的循环中,编写一个 `DELETE` 语句,使用 `WHERE` 子句过滤需要删除的行,并使用 `LIMIT` 限制单次删除的数据条数。 +你可以在应用程序或脚本的循环中编写 `DELETE` 语句,使用 `WHERE` 子句过滤数据,并使用 `LIMIT` 限制单个语句要删除的行数。 -### 批量删除例子 +### 批量删除示例 -假设发现在特定时间段内,发生了业务错误,需要删除这期间内的所有 [rating](/develop/dev-guide-bookshop-schema-design.md#ratings-表) 的数据,例如,`2022-04-15 00:00:00` 至 `2022-04-15 00:15:00` 的数据。并且在 15 分钟内,有大于 1 万条数据被写入,此时请使用循环删除的方式进行删除: +假设你发现在特定时间段内出现了应用程序错误。你需要删除这段时间内的所有 [rating](/develop/dev-guide-bookshop-schema-design.md#ratings-table) 数据,例如从 `2022-04-15 00:00:00` 到 `2022-04-15 00:15:00`,并且在 15 分钟内写入了超过 10,000 条记录。你可以执行以下操作。
-在 Java 中,批量删除程序类似于以下内容: +在 Java 中,批量删除示例如下: ```java package com.pingcap.bulkDelete; import com.mysql.cj.jdbc.MysqlDataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Calendar; +import java.sql.*; +import java.util.*; import java.util.concurrent.TimeUnit; public class BatchDeleteExample { public static void main(String[] args) throws InterruptedException { - // Configure the example database connection. + // 配置示例数据库连接。 - // Create a mysql data source instance. + // 创建 mysql 数据源实例。 MysqlDataSource mysqlDataSource = new MysqlDataSource(); - // Set server name, port, database name, username and password. + // 设置服务器名称、端口、数据库名称、用户名和密码。 mysqlDataSource.setServerName("localhost"); mysqlDataSource.setPortNumber(4000); mysqlDataSource.setDatabaseName("bookshop"); mysqlDataSource.setUser("root"); mysqlDataSource.setPassword(""); - Integer updateCount = -1; - while (updateCount != 0) { - updateCount = batchDelete(mysqlDataSource); + while (true) { + batchDelete(mysqlDataSource); + TimeUnit.SECONDS.sleep(1); } } - public static Integer batchDelete (MysqlDataSource ds) { + public static void batchDelete (MysqlDataSource ds) { try (Connection connection = ds.getConnection()) { - String sql = "DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ? LIMIT 1000"; + String sql = "DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ? LIMIT 1000"; PreparedStatement preparedStatement = connection.prepareStatement(sql); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MILLISECOND, 0); @@ -248,24 +276,20 @@ public class BatchDeleteExample int count = preparedStatement.executeUpdate(); System.out.println("delete " + count + " data"); - - return count; } catch (SQLException e) { e.printStackTrace(); } - - return -1; } } ``` -每次迭代中,`DELETE` 最多删除 1000 行时间段为 `2022-04-15 00:00:00` 至 `2022-04-15 00:15:00` 的数据。 +在每次迭代中,`DELETE` 从 `2022-04-15 00:00:00` 到 `2022-04-15 00:15:00` 删除最多 1000 行。
-在 Golang 中,批量删除程序类似于以下内容: +在 Golang 中,批量删除示例如下: ```go package main @@ -297,9 +321,9 @@ func main() { } } -// deleteBatch delete at most 1000 lines per batch +// deleteBatch 每批最多删除 1000 行 func deleteBatch(db *sql.DB, startTime, endTime time.Time) (int64, error) { - bulkUpdateSql := fmt.Sprintf("DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ? LIMIT 1000") + bulkUpdateSql := fmt.Sprintf("DELETE FROM `bookshop`.`ratings` WHERE `rated_at` >= ? AND `rated_at` <= ? LIMIT 1000") result, err := db.Exec(bulkUpdateSql, startTime, endTime) if err != nil { return -1, err @@ -314,19 +338,18 @@ func deleteBatch(db *sql.DB, startTime, endTime time.Time) (int64, error) { } ``` -每次迭代中,`DELETE` 最多删除 1000 行时间段为 `2022-04-15 00:00:00` 至 `2022-04-15 00:15:00` 的数据。 +在每次迭代中,`DELETE` 从 `2022-04-15 00:00:00` 到 `2022-04-15 00:15:00` 删除最多 1000 行。
-在 Python 中,批量删除程序类似于以下内容: +在 Python 中,批量删除示例如下: ```python import MySQLdb import datetime import time - connection = MySQLdb.connect( host="127.0.0.1", port=4000, @@ -335,7 +358,6 @@ connection = MySQLdb.connect( database="bookshop", autocommit=True ) - with connection: with connection.cursor() as cursor: start_time = datetime.datetime(2022, 4, 15) @@ -348,44 +370,58 @@ with connection: time.sleep(1) ``` -每次迭代中,`DELETE` 最多删除 1000 行时间段为 `2022-04-15 00:00:00` 至 `2022-04-15 00:15:00` 的数据。 +在每次迭代中,`DELETE` 从 `2022-04-15 00:00:00` 到 `2022-04-15 00:15:00` 删除最多 1000 行。
-## 非事务批量删除 +## 非事务性批量删除 > **注意:** > -> TiDB 从 v6.1.0 版本开始支持[非事务 DML 语句](/non-transactional-dml.md)特性。在 TiDB v6.1.0 以下版本中无法使用此特性。 +> 从 v6.1.0 开始,TiDB 支持[非事务性 DML 语句](/non-transactional-dml.md)。此功能在早于 TiDB v6.1.0 的版本中不可用。 -### 使用前提 +### 非事务性批量删除的前提条件 -在使用非事务批量删除前,请先**仔细**阅读[非事务 DML 语句](/non-transactional-dml.md)。非事务批量删除,本质是以牺牲事务的原子性、隔离性为代价,增强批量数据处理场景下的性能和易用性。 +在使用非事务性批量删除之前,请确保你已经阅读了[非事务性 DML 语句文档](/non-transactional-dml.md)。非事务性批量删除提高了批量数据处理场景下的性能和易用性,但牺牲了事务的原子性和隔离性。 -因此在使用过程中,需要极为小心,否则,因为操作的非事务特性,在误操作时会导致严重的后果(如数据丢失等)。 +因此,你应该谨慎使用它,以避免由于操作不当而导致严重后果(如数据丢失)。 -### 非事务批量删除 SQL 语法 +### 非事务性批量删除的 SQL 语法 -非事务批量删除的 SQL 语法如下: +非事务性批量删除语句的 SQL 语法如下: ```sql BATCH ON {shard_column} LIMIT {batch_size} {delete_statement}; ``` -| 参数 | 描述 | +| 参数名称 | 描述 | | :--------: | :------------: | -| `{shard_column}` | 非事务批量删除的划分列 | -| `{batch_size}` | 非事务批量删除的每批大小 | -| `{delete_statement}` | 删除语句 | +| `{shard_column}` | 用于划分批次的列。 | +| `{batch_size}` | 控制每个批次的大小。 | +| `{delete_statement}` | `DELETE` 语句。 | -此处仅展示非事务批量删除的简单用法,详细文档可参考 TiDB 的[非事务 DML 语句](/non-transactional-dml.md)。 +上述示例仅展示了非事务性批量删除语句的简单用法。有关详细信息,请参阅[非事务性 DML 语句](/non-transactional-dml.md)。 -### 非事务批量删除使用示例 +### 非事务性批量删除示例 -以上方[批量删除例子](#批量删除例子)场景为例,可使用以下 SQL 语句进行非事务批量删除: +在与[批量删除示例](#批量删除示例)相同的场景中,以下 SQL 语句展示了如何执行非事务性批量删除: ```sql -BATCH ON `rated_at` LIMIT 1000 DELETE FROM `ratings` WHERE `rated_at` >= "2022-04-15 00:00:00" AND `rated_at` <= "2022-04-15 00:15:00"; +BATCH ON `rated_at` LIMIT 1000 DELETE FROM `ratings` WHERE `rated_at` >= "2022-04-15 00:00:00" AND `rated_at` <= "2022-04-15 00:15:00"; ``` + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-get-data-from-single-table.md b/develop/dev-guide-get-data-from-single-table.md index aea2b0f41866..21975dd8384c 100644 --- a/develop/dev-guide-get-data-from-single-table.md +++ b/develop/dev-guide-get-data-from-single-table.md @@ -1,32 +1,54 @@ --- -title: 单表查询 -summary: 介绍 TiDB 中的单表查询功能。 +title: 从单个表中查询数据 +summary: 本文档介绍如何从数据库的单个表中查询数据。 --- -# 单表查询 +# 从单个表中查询数据 -在这个章节当中,将开始介绍如何使用 SQL 来对数据库中的数据进行查询。 +本文档介绍如何使用 SQL 和各种编程语言从数据库的单个表中查询数据。 ## 开始之前 -下面将围绕 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 这个应用程序来对 TiDB 的数据查询部分展开介绍。 +以下内容以[书店](/develop/dev-guide-bookshop-schema-design.md)应用程序为例,展示如何从 TiDB 中的单个表查询数据。 -在阅读本章节之前,你需要做以下准备工作: +在查询数据之前,请确保你已完成以下步骤: + + + +1. 搭建 TiDB 集群(推荐使用 [TiDB Cloud](/develop/dev-guide-build-cluster-in-cloud.md) 或 [TiUP](/production-deployment-using-tiup.md))。 + + + + + +1. 使用 [TiDB Cloud](/develop/dev-guide-build-cluster-in-cloud.md) 搭建 TiDB 集群。 + + + +2. [导入书店应用程序的表结构和示例数据](/develop/dev-guide-bookshop-schema-design.md#import-table-structures-and-data)。 + + -1. 构建 TiDB 集群(推荐使用 [TiDB Cloud](/develop/dev-guide-build-cluster-in-cloud.md) 或 [TiUP](/production-deployment-using-tiup.md))。 -2. [导入 Bookshop 应用程序的表结构和示例数据](/develop/dev-guide-bookshop-schema-design.md#导入表结构和数据)。 3. [连接到 TiDB](/develop/dev-guide-connect-to-tidb.md)。 -## 简单的查询 + + + + +3. [连接到 TiDB](/tidb-cloud/connect-to-tidb-cluster.md)。 -在 Bookshop 应用程序的数据库当中,`authors` 表存放了作家们的基础信息,可以通过 `SELECT ... FROM ...` 语句将数据从数据库当中调取出去。 + + +## 执行简单查询 + +在书店应用程序的数据库中,`authors` 表存储了作者的基本信息。你可以使用 `SELECT ... FROM ...` 语句从数据库中查询数据。
-在 MySQL Client 等客户端输入并执行如下 SQL 语句: +在 MySQL 客户端中执行以下 SQL 语句: ```sql SELECT id, name FROM authors; @@ -56,13 +78,12 @@ SELECT id, name FROM authors;
-在 Java 语言当中,可以通过声明一个 `Author` 类来定义如何存放作者的基础信息,根据数据的[类型](/data-type-overview.md)和[取值范围](/data-type-numeric.md)从 Java 语言当中选择合适的数据类型来存放对应的数据,例如: +在 Java 中,要存储作者的基本信息,你可以声明一个 `Author` 类。你应该根据数据库中的[数据类型](/data-type-overview.md)和[取值范围](/data-type-numeric.md)选择适当的 Java 数据类型。例如: -- 使用 `Int` 类型变量存放 `int` 类型的数据。 -- 使用 `Long` 类型变量存放 `bigint` 类型的数据。 -- 使用 `Short` 类型变量存放 `tinyint` 类型的数据。 -- 使用 `String` 类型变量存放 `varchar` 类型的数据。 -- ... +- 使用 `Int` 类型的变量存储 `int` 类型的数据。 +- 使用 `Long` 类型的变量存储 `bigint` 类型的数据。 +- 使用 `Short` 类型的变量存储 `tinyint` 类型的数据。 +- 使用 `String` 类型的变量存储 `varchar` 类型的数据。 ```java public class Author { @@ -74,14 +95,14 @@ public class Author { public Author() {} - // Skip the getters and setters. + // 省略 getter 和 setter 方法。 } ``` ```java public class AuthorDAO { - // Omit initialization of instance variables. + // 省略实例变量的初始化。 public List getAuthors() throws SQLException { List authors = new ArrayList<>(); @@ -101,23 +122,34 @@ public class AuthorDAO { } ``` -- 在[获得数据库连接](/develop/dev-guide-connect-to-tidb.md#jdbc)之后,你可以通过 `conn.createStatement()` 语句创建一个 `Statement` 实例对象。 -- 然后调用 `stmt.executeQuery("query_sql")` 方法向 TiDB 发起一个数据库查询请求。 -- 数据库返回的查询结果将会存放到 `ResultSet` 当中,通过遍历 `ResultSet` 对象可以将返回结果映射到此前准备的 `Author` 类对象当中。 + + +- 在[使用 JDBC 驱动程序连接到 TiDB](/develop/dev-guide-connect-to-tidb.md#jdbc) 之后,你可以使用 `conn.createStatus()` 创建一个 `Statement` 对象。 + + + + + +- 在[使用 JDBC 驱动程序连接到 TiDB](/develop/dev-guide-choose-driver-or-orm.md#java-drivers) 之后,你可以使用 `conn.createStatus()` 创建一个 `Statement` 对象。 + + + +- 然后调用 `stmt.executeQuery("query_sql")` 向 TiDB 发起数据库查询请求。 +- 查询结果存储在 `ResultSet` 对象中。通过遍历 `ResultSet`,可以将返回的结果映射到 `Author` 对象。
-## 对结果进行筛选 +## 过滤结果 -查询得到的结果非常多,但是并不都是你想要的?可以通过 `WHERE` 语句对查询的结果进行过滤,从而找到想要查询的部分。 +要过滤查询结果,你可以使用 `WHERE` 语句。 -例如,想要查找众多作家当中找出在 1998 年出生的作家: +例如,以下命令查询所有作者中出生于 1998 年的作者:
-在 SQL 中,可以使用 `WHERE` 子句添加筛选的条件: +在 `WHERE` 语句中添加过滤条件: ```sql SELECT * FROM authors WHERE birth_year = 1998; @@ -126,11 +158,11 @@ SELECT * FROM authors WHERE birth_year = 1998;
-对于 Java 程序而言,可以通过同一个 SQL 来处理带有动态参数的数据查询请求。 +在 Java 中,你可以使用相同的 SQL 来处理带有动态参数的数据查询请求。 -将参数拼接到 SQL 语句当中也许是一种方法,但是这可能不是一个好的主意,因为这会给应用程序带来潜在的 [SQL 注入](https://zh.wikipedia.org/wiki/SQL%E6%B3%A8%E5%85%A5)风险。 +这可以通过将参数连接到 SQL 语句中来完成。但是,这种方法可能会给应用程序的安全性带来 [SQL 注入](https://en.wikipedia.org/wiki/SQL_injection)风险。 -在处理这类查询时,应该使用 [PreparedStatement](/develop/dev-guide-prepared-statement.md) 来替代普通的 Statement。 +要处理此类查询,应使用[预处理语句](/develop/dev-guide-prepared-statement.md)而不是普通语句。 ```java public List getAuthorsByBirthYear(Short birthYear) throws SQLException { @@ -155,11 +187,11 @@ public List getAuthorsByBirthYear(Short birthYear) throws SQLException {
-## 对结果进行排序 +## 排序结果 -使用 `ORDER BY` 语句可以让查询结果按照期望的方式进行排序。 +要对查询结果进行排序,你可以使用 `ORDER BY` 语句。 -例如,可以通过下面的 SQL 语句对 `authors` 表的数据按照 `birth_year` 列进行降序 (`DESC`) 排序,从而得到最年轻的作家列表。 +例如,以下 SQL 语句是通过按照 `birth_year` 列降序(`DESC`)排序 `authors` 表来获取最年轻作者的列表。
@@ -200,7 +232,7 @@ public List getAuthorsSortByBirthYear() throws SQLException {
-查询结果如下: +结果如下: ``` +-----------+------------------------+------------+ @@ -222,7 +254,7 @@ public List getAuthorsSortByBirthYear() throws SQLException { ## 限制查询结果数量 -如果希望 TiDB 只返回部分结果,可以使用 `LIMIT` 语句限制查询结果返回的记录数。 +要限制查询结果的数量,你可以使用 `LIMIT` 语句。
@@ -265,7 +297,7 @@ public List getAuthorsWithLimit(Integer limit) throws SQLException {
-查询结果如下: +结果如下: ``` +-----------+------------------------+------------+ @@ -285,19 +317,19 @@ public List getAuthorsWithLimit(Integer limit) throws SQLException { 10 rows in set (0.11 sec) ``` -通过观察查询结果你会发现,在使用 `LIMIT` 语句之后,查询的时间明显缩短,这是 TiDB 对 `LIMIT` 子句进行优化后的结果,你可以通过 [TopN 和 Limit 下推](/topn-limit-push-down.md)章节了解更多细节。 +使用 `LIMIT` 语句后,在本例中查询时间从 `0.23 秒` 显著减少到 `0.11 秒`。更多信息,请参见 [TopN 和 Limit](/topn-limit-push-down.md)。 ## 聚合查询 -如果你想要关注数据整体的情况,而不是部分数据,你可以通过使用 `GROUP BY` 语句配合聚合函数,构建一个聚合查询来帮助你对数据的整体情况有一个更好的了解。 +要更好地了解整体数据情况,你可以使用 `GROUP BY` 语句来聚合查询结果。 -比如说,你希望知道哪些年出生的作家比较多,你可以将作家基本信息按照 `birth_year` 列进行分组,然后分别统计在当年出生的作家数量: +例如,如果你想知道哪些年份出生的作者较多,可以按 `birth_year` 列对 `authors` 表进行分组,然后统计每年的数量:
```sql -SELECT birth_year, COUNT(DISTINCT id) AS author_count +SELECT birth_year, COUNT (DISTINCT id) AS author_count FROM authors GROUP BY birth_year ORDER BY author_count DESC; @@ -314,7 +346,7 @@ public class AuthorCount { public AuthorCount() {} - // Skip the getters and setters. + // 省略 getter 和 setter 方法。 } public List getAuthorCountsByBirthYear() throws SQLException { @@ -342,7 +374,7 @@ public List getAuthorCountsByBirthYear() throws SQLException {
-查询结果如下: +结果如下: ``` +------------+--------------+ @@ -363,4 +395,18 @@ public List getAuthorCountsByBirthYear() throws SQLException { 71 rows in set (0.00 sec) ``` -除了 `COUNT` 函数外,TiDB 还支持了其他聚合函数。详情请参考 [GROUP BY 聚合函数](/functions-and-operators/aggregate-group-by-functions.md)。 +除了 `COUNT` 函数外,TiDB 还支持其他聚合函数。更多信息,请参见[聚合(GROUP BY)函数](/functions-and-operators/aggregate-group-by-functions.md)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-gui-datagrip.md b/develop/dev-guide-gui-datagrip.md new file mode 100644 index 000000000000..6d8bc44806a6 --- /dev/null +++ b/develop/dev-guide-gui-datagrip.md @@ -0,0 +1,190 @@ +--- +title: 使用 JetBrains DataGrip 连接 TiDB +summary: 了解如何使用 JetBrains DataGrip 连接 TiDB。本教程同样适用于其他 JetBrains IDE(如 IntelliJ、PhpStorm 和 PyCharm)中可用的 Database Tools and SQL 插件。 +--- + +# 使用 JetBrains DataGrip 连接 TiDB + +TiDB 是一个兼容 MySQL 的数据库,而 [JetBrains DataGrip](https://www.jetbrains.com/help/datagrip/getting-started.html) 是一个功能强大的数据库和 SQL 集成开发环境(IDE)。本教程将指导您使用 DataGrip 连接到 TiDB 集群。 + +> **注意:** +> +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 + +您可以通过两种方式使用 DataGrip: + +- 作为独立工具使用 [DataGrip IDE](https://www.jetbrains.com/datagrip/download)。 +- 在 JetBrains IDE(如 IntelliJ、PhpStorm 和 PyCharm)中使用 [Database Tools and SQL 插件](https://www.jetbrains.com/help/idea/relational-databases.html)。 + +本教程主要关注独立的 DataGrip IDE。使用 JetBrains IDE 中的 Database Tools and SQL 插件连接 TiDB 的步骤类似。当您从任何 JetBrains IDE 连接到 TiDB 时,也可以参考本文档中的步骤。 + +## 前提条件 + +要完成本教程,您需要: + +- [DataGrip **2023.2.1** 或更高版本](https://www.jetbrains.com/datagrip/download/)或非社区版的 [JetBrains](https://www.jetbrains.com/) IDE。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 + + + +## 连接到 TiDB + +根据您选择的 TiDB 部署选项连接到 TiDB 集群。 + + +
+ +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示连接对话框。 + +3. 确保连接对话框中的配置与您的操作环境匹配。 + + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `DataGrip` + - **操作系统**与您的环境匹配。 + +4. 点击**生成密码**创建随机密码。 + + > **提示:** + > + > 如果您之前已经创建了密码,可以使用原始密码或点击**重置密码**生成新密码。 + +5. 启动 DataGrip 并创建一个项目来管理您的连接。 + + ![在 DataGrip 中创建项目](/media/develop/datagrip-create-project.jpg) + +6. 在新创建的项目中,点击**数据库浏览器**面板左上角的 **+**,然后选择**数据源** > **其他** > **TiDB**。 + + ![在 DataGrip 中选择数据源](/media/develop/datagrip-data-source-select.jpg) + +7. 从 TiDB Cloud 连接对话框复制连接字符串。然后,将其粘贴到 **URL** 字段中,其余参数将自动填充。示例结果如下: + + ![为 TiDB Cloud Serverless 配置 URL 字段](/media/develop/datagrip-url-paste.jpg) + + 如果显示**下载缺失的驱动程序文件**警告,点击**下载**获取驱动程序文件。 + +8. 点击**测试连接**验证与 TiDB Cloud Serverless 集群的连接。 + + ![测试与 TiDB Cloud Serverless 集群的连接](/media/develop/datagrip-test-connection.jpg) + +9. 点击**确定**保存连接配置。 + +
+
+ +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示连接对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA 证书**下载 CA 证书。 + + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 + + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + +4. 启动 DataGrip 并创建一个项目来管理您的连接。 + + ![在 DataGrip 中创建项目](/media/develop/datagrip-create-project.jpg) + +5. 在新创建的项目中,点击**数据库浏览器**面板左上角的 **+**,然后选择**数据源** > **其他** > **TiDB**。 + + ![在 DataGrip 中选择数据源](/media/develop/datagrip-data-source-select.jpg) + +6. 将适当的连接字符串复制并粘贴到 DataGrip 的**数据源和驱动程序**窗口中。DataGrip 字段与 TiDB Cloud Dedicated 连接字符串的映射关系如下: + + | DataGrip 字段 | TiDB Cloud Dedicated 连接字符串 | + | -------------- | ------------------------------- | + | Host | `{host}` | + | Port | `{port}` | + | User | `{user}` | + | Password | `{password}` | + + 示例如下: + + ![为 TiDB Cloud Dedicated 配置连接参数](/media/develop/datagrip-dedicated-connect.jpg) + +7. 点击 **SSH/SSL** 标签,选中**使用 SSL** 复选框,并在 **CA 文件**字段中输入 CA 证书路径。 + + ![为 TiDB Cloud Dedicated 配置 CA](/media/develop/datagrip-dedicated-ssl.jpg) + + 如果显示**下载缺失的驱动程序文件**警告,点击**下载**获取驱动程序文件。 + +8. 点击**高级**标签,滚动找到 **enabledTLSProtocols** 参数,并将其值设置为 `TLSv1.2,TLSv1.3`。 + + ![为 TiDB Cloud Dedicated 配置 TLS](/media/develop/datagrip-dedicated-advanced.jpg) + +9. 点击**测试连接**验证与 TiDB Cloud Dedicated 集群的连接。 + + ![测试与 TiDB Cloud Dedicated 集群的连接](/media/develop/datagrip-dedicated-test-connection.jpg) + +10. 点击**确定**保存连接配置。 + +
+
+ +1. 启动 DataGrip 并创建一个项目来管理您的连接。 + + ![在 DataGrip 中创建项目](/media/develop/datagrip-create-project.jpg) + +2. 在新创建的项目中,点击**数据库浏览器**面板左上角的 **+**,然后选择**数据源** > **其他** > **TiDB**。 + + ![在 DataGrip 中选择数据源](/media/develop/datagrip-data-source-select.jpg) + +3. 配置以下连接参数: + + - **Host**:您的 TiDB Self-Managed 集群的 IP 地址或域名。 + - **Port**:您的 TiDB Self-Managed 集群的端口号。 + - **User**:用于连接到 TiDB Self-Managed 集群的用户名。 + - **Password**:用户名的密码。 + + 示例如下: + + ![为 TiDB Self-Managed 配置连接参数](/media/develop/datagrip-self-hosted-connect.jpg) + + 如果显示**下载缺失的驱动程序文件**警告,点击**下载**获取驱动程序文件。 + +4. 点击**测试连接**验证与 TiDB Self-Managed 集群的连接。 + + ![测试与 TiDB Self-Managed 集群的连接](/media/develop/datagrip-self-hosted-test-connection.jpg) + +5. 点击**确定**保存连接配置。 + +
+
+ +## 下一步 + +- 从 [DataGrip 文档](https://www.jetbrains.com/help/datagrip/getting-started.html)了解更多 DataGrip 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-gui-dbeaver.md b/develop/dev-guide-gui-dbeaver.md new file mode 100644 index 000000000000..cba10b83a775 --- /dev/null +++ b/develop/dev-guide-gui-dbeaver.md @@ -0,0 +1,179 @@ +--- +title: 使用 DBeaver 连接 TiDB +summary: 了解如何使用 DBeaver Community 连接 TiDB。 +--- + +# 使用 DBeaver 连接 TiDB + +TiDB 是一个兼容 MySQL 的数据库,而 [DBeaver Community](https://dbeaver.io/download/) 是一个免费的跨平台数据库工具,适用于开发人员、数据库管理员、分析师以及所有处理数据的人员。 + +在本教程中,您将学习如何使用 DBeaver Community 连接到您的 TiDB 集群。 + +> **注意:** +> +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 + +## 前提条件 + +要完成本教程,您需要: + +- [DBeaver Community **23.0.3** 或更高版本](https://dbeaver.io/download/)。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 + + + +## 连接到 TiDB + +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 + + +
+ +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个连接对话框。 + +3. 确保连接对话框中的配置与您的操作环境相匹配。 + + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `DBeaver` + - **操作系统**与您的环境匹配。 + +4. 点击**生成密码**创建一个随机密码。 + + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码,也可以点击**重置密码**生成一个新密码。 + +5. 启动 DBeaver 并点击左上角的**新建数据库连接**。在**连接到数据库**对话框中,从列表中选择 **TiDB**,然后点击**下一步**。 + + ![在 DBeaver 中选择 TiDB 作为数据库](/media/develop/dbeaver-select-database.jpg) + +6. 从 TiDB Cloud 连接对话框中复制连接字符串。在 DBeaver 中,选择 **URL** 作为**连接方式**,并将连接字符串粘贴到 **URL** 字段中。 + +7. 在**身份验证(数据库原生)**部分,输入您的**用户名**和**密码**。示例如下: + + ![配置 TiDB Cloud Serverless 的连接设置](/media/develop/dbeaver-connection-settings-serverless.jpg) + +8. 点击**测试连接**以验证与 TiDB Cloud Serverless 集群的连接。 + + 如果显示**下载驱动程序文件**对话框,点击**下载**获取驱动程序文件。 + + ![下载驱动程序文件](/media/develop/dbeaver-download-driver.jpg) + + 如果连接测试成功,将显示如下的**连接测试**对话框。点击**确定**关闭它。 + + ![连接测试结果](/media/develop/dbeaver-connection-test.jpg) + +9. 点击**完成**保存连接配置。 + +
+
+ +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个连接对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 + + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 + + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + +4. 启动 DBeaver 并点击左上角的**新建数据库连接**。在**连接到数据库**对话框中,从列表中选择 **TiDB**,然后点击**下一步**。 + + ![在 DBeaver 中选择 TiDB 作为数据库](/media/develop/dbeaver-select-database.jpg) + +5. 将适当的连接字符串复制并粘贴到 DBeaver 连接面板中。DBeaver 字段与 TiDB Cloud Dedicated 连接字符串的映射关系如下: + + | DBeaver 字段 | TiDB Cloud Dedicated 连接字符串 | + |---------------| ------------------------------- | + | 服务器主机 | `{host}` | + | 端口 | `{port}` | + | 用户名 | `{user}` | + | 密码 | `{password}` | + + 示例如下: + + ![配置 TiDB Cloud Dedicated 的连接设置](/media/develop/dbeaver-connection-settings-dedicated.jpg) + +6. 点击**测试连接**以验证与 TiDB Cloud Dedicated 集群的连接。 + + 如果显示**下载驱动程序文件**对话框,点击**下载**获取驱动程序文件。 + + ![下载驱动程序文件](/media/develop/dbeaver-download-driver.jpg) + + 如果连接测试成功,将显示如下的**连接测试**对话框。点击**确定**关闭它。 + + ![连接测试结果](/media/develop/dbeaver-connection-test.jpg) + +7. 点击**完成**保存连接配置。 + +
+
+ +1. 启动 DBeaver 并点击左上角的**新建数据库连接**。在**连接到数据库**对话框中,从列表中选择 **TiDB**,然后点击**下一步**。 + + ![在 DBeaver 中选择 TiDB 作为数据库](/media/develop/dbeaver-select-database.jpg) + +2. 配置以下连接参数: + + - **服务器主机**:您的 TiDB Self-Managed 集群的 IP 地址或域名。 + - **端口**:您的 TiDB Self-Managed 集群的端口号。 + - **用户名**:用于连接到您的 TiDB Self-Managed 集群的用户名。 + - **密码**:该用户名的密码。 + + 示例如下: + + ![配置 TiDB Self-Managed 的连接设置](/media/develop/dbeaver-connection-settings-self-hosted.jpg) + +3. 点击**测试连接**以验证与 TiDB Self-Managed 集群的连接。 + + 如果显示**下载驱动程序文件**对话框,点击**下载**获取驱动程序文件。 + + ![下载驱动程序文件](/media/develop/dbeaver-download-driver.jpg) + + 如果连接测试成功,将显示如下的**连接测试**对话框。点击**确定**关闭它。 + + ![连接测试结果](/media/develop/dbeaver-connection-test.jpg) + +4. 点击**完成**保存连接配置。 + +
+
+ +## 下一步 + +- 从 [DBeaver 的文档](https://github.com/dbeaver/dbeaver/wiki)了解更多 DBeaver 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-gui-mysql-workbench.md b/develop/dev-guide-gui-mysql-workbench.md index 99784e5d1e89..77cf8b7bca52 100644 --- a/develop/dev-guide-gui-mysql-workbench.md +++ b/develop/dev-guide-gui-mysql-workbench.md @@ -1,163 +1,185 @@ --- -title: 使用 MySQL Workbench 连接到 TiDB -summary: 了解如何使用 MySQL Workbench 连接到 TiDB。 +title: 使用 MySQL Workbench 连接 TiDB +summary: 了解如何使用 MySQL Workbench 连接 TiDB。 --- -# 使用 MySQL Workbench 连接到 TiDB +# 使用 MySQL Workbench 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[MySQL Workbench](https://www.mysql.com/products/workbench/) 是为 MySQL 数据库用户提供的 GUI 工具集。 +TiDB 是一个兼容 MySQL 的数据库,而 [MySQL Workbench](https://www.mysql.com/products/workbench/) 是一个面向 MySQL 数据库用户的 GUI 工具集。 -> **警告** +> **警告:** > -> - 尽管由于 MySQL Workbench 兼容 MySQL,你可以使用 MySQL Workbench 连接到 TiDB,但 MySQL Workbench 并不完全支持 TiDB。由于 MySQL Workbench 将 TiDB 视为 MySQL,因此在使用过程中可能会遇到一些问题。 -> - 建议使用其它 TiDB 完全支持的 GUI 工具进行连接,例如 DataGrip,DBeaver 以及 VS Code SQLTools。TiDB 完全支持的 GUI 工具的完整列表,参考 [TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md#gui)。 +> - 虽然由于 TiDB 的 MySQL 兼容性,您可以使用 MySQL Workbench 连接到 TiDB,但 MySQL Workbench 并不完全支持 TiDB。由于它将 TiDB 视为 MySQL,在使用过程中可能会遇到一些问题。 +> - 建议使用其他官方支持 TiDB 的 GUI 工具,如 [DataGrip](/develop/dev-guide-gui-datagrip.md)、[DBeaver](/develop/dev-guide-gui-dbeaver.md) 和 [VS Code SQLTools](/develop/dev-guide-gui-vscode-sqltools.md)。有关 TiDB 完全支持的 GUI 工具的完整列表,请参见[TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md#gui)。 -在本文档中,你可以学习如何使用 MySQL Workbench 连接到 TiDB 集群。 +在本教程中,您可以学习如何使用 MySQL Workbench 连接到您的 TiDB 集群。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本文中的操作,你需要: +要完成本教程,您需要: -- [MySQL Workbench](https://dev.mysql.com/downloads/workbench/) **8.0.31** 或以上版本。 -- 准备一个 TiDB 集群。 +- [MySQL Workbench](https://dev.mysql.com/downloads/workbench/) **8.0.31** 或更高版本。 +- 一个 TiDB 集群。 -**如果你还没有 TiDB 集群,可以按如下方式创建一个:** + -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md),创建一个 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建一个本地集群。 +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 + + ## 连接到 TiDB -根据你选择的 TiDB 部署方式连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你目标集群的名字,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 选择 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `MySQL Workbench`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接工具**设置为 `MySQL Workbench`。 + - **操作系统**与您的环境匹配。 -4. 点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建随机密码。 - > **建议:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经创建了密码,您可以使用原始密码或点击**重置密码**生成新密码。 -5. 启动 MySQL Workbench,并点击 **MySQL Connections** 标题旁边的 **+**。 +5. 启动 MySQL Workbench,点击 **MySQL 连接**标题附近的 **+**。 - ![MySQL Workbench: add new connection](/media/develop/mysql-workbench-add-new-connection.png) + ![MySQL Workbench:添加新连接](/media/develop/mysql-workbench-add-new-connection.png) -6. 在 **Setup New Connection** 对话框中,配置以下连接参数: +6. 在**设置新连接**对话框中,配置以下连接参数: - - **Connection Name**:为该连接指定一个有意义的名称。 - - **Hostname**:输入从 TiDB Cloud 连接对话框中的得到的 `HOST` 参数。 - - **Port**:输入从 TiDB Cloud 连接对话框中的得到的 `PORT` 参数。 - - **Username**:输入从 TiDB Cloud 连接对话框中的得到的 `USERNAME` 参数。 - - **Password**:点击 **Store in Keychain ...** 或 **Store in Vault**,输入 TiDB Cloud Serverless 集群的密码,然后点击 **OK** 保存密码。 + - **连接名称**:为此连接指定一个有意义的名称。 + - **主机名**:输入 TiDB Cloud 连接对话框中的 `HOST` 参数。 + - **端口**:输入 TiDB Cloud 连接对话框中的 `PORT` 参数。 + - **用户名**:输入 TiDB Cloud 连接对话框中的 `USERNAME` 参数。 + - **密码**:点击**存储在钥匙串中...**或**存储在保管库中**,输入 TiDB Cloud Serverless 集群的密码,然后点击**确定**存储密码。 - ![MySQL Workbench: store the password of TiDB Cloud Serverless in keychain](/media/develop/mysql-workbench-store-password-in-keychain.png) + ![MySQL Workbench:在钥匙串中存储 TiDB Cloud Serverless 的密码](/media/develop/mysql-workbench-store-password-in-keychain.png) - 下图显示了连接参数的示例: + 以下图片显示了连接参数的示例: - ![MySQL Workbench: configure connection settings for TiDB Cloud Serverless](/media/develop/mysql-workbench-connection-config-serverless-parameters.png) + ![MySQL Workbench:为 TiDB Cloud Serverless 配置连接设置](/media/develop/mysql-workbench-connection-config-serverless-parameters.png) -7. 点击 **Test Connection** 以验证与 TiDB Cloud Serverless 集群的连接。 +7. 点击**测试连接**验证与 TiDB Cloud Serverless 集群的连接。 -8. 如果连接测试成功,你可以看到 **Successfully made the MySQL connection** 信息。点击 **OK** 保存连接配置。 +8. 如果连接测试成功,您会看到**成功建立 MySQL 连接**消息。点击**确定**保存连接配置。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你目标集群的名字,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 启动 MySQL Workbench,并点击 **MySQL Connections** 标题旁边的 **+**。 +4. 启动 MySQL Workbench,点击 **MySQL 连接**标题附近的 **+**。 - ![MySQL Workbench: add new connection](/media/develop/mysql-workbench-add-new-connection.png) + ![MySQL Workbench:添加新连接](/media/develop/mysql-workbench-add-new-connection.png) -5. 在 **Setup New Connection** 对话框中,配置以下连接参数: +5. 在**设置新连接**对话框中,配置以下连接参数: - - **Connection Name**:为该连接指定一个有意义的名称。 - - **Hostname**: 输入从 TiDB Cloud 连接对话框中的得到的 `HOST` 参数。 - - **Port**:输入从 TiDB Cloud 连接对话框中的得到的 `PORT` 参数。 - - **Username**:输入从 TiDB Cloud 连接对话框中的得到的 `USERNAME` 参数。 - - **Password**:点击 **Store in Keychain ...**,输入 TiDB Cloud Dedicated 集群的密码,然后点击 **OK** 保存密码。 + - **连接名称**:为此连接指定一个有意义的名称。 + - **主机名**:输入 TiDB Cloud 连接对话框中的 `HOST` 参数。 + - **端口**:输入 TiDB Cloud 连接对话框中的 `PORT` 参数。 + - **用户名**:输入 TiDB Cloud 连接对话框中的 `USERNAME` 参数。 + - **密码**:点击**存储在钥匙串中...**,输入 TiDB Cloud Dedicated 集群的密码,然后点击**确定**存储密码。 - ![MySQL Workbench: store the password of TiDB Cloud Dedicated in keychain](/media/develop/mysql-workbench-store-dedicated-password-in-keychain.png) + ![MySQL Workbench:在钥匙串中存储 TiDB Cloud Dedicated 的密码](/media/develop/mysql-workbench-store-dedicated-password-in-keychain.png) - 下图显示了连接参数的示例: + 以下图片显示了连接参数的示例: - ![MySQL Workbench: configure connection settings for TiDB Cloud Dedicated](/media/develop/mysql-workbench-connection-config-dedicated-parameters.png) + ![MySQL Workbench:为 TiDB Cloud Dedicated 配置连接设置](/media/develop/mysql-workbench-connection-config-dedicated-parameters.png) -6. 点击 **Test Connection** 以验证与 TiDB Cloud Dedicated 集群的连接。 +6. 点击**测试连接**验证与 TiDB Cloud Dedicated 集群的连接。 -7. 如果连接测试成功,你可以看到 **Successfully made the MySQL connection** 信息。点击 **OK** 保存连接配置。 +7. 如果连接测试成功,您会看到**成功建立 MySQL 连接**消息。点击**确定**保存连接配置。
-
+
-1. 启动 MySQL Workbench,并点击 **MySQL Connections** 标题旁边的 **+**。 +1. 启动 MySQL Workbench,点击 **MySQL 连接**标题附近的 **+**。 - ![MySQL Workbench: add new connection](/media/develop/mysql-workbench-add-new-connection.png) + ![MySQL Workbench:添加新连接](/media/develop/mysql-workbench-add-new-connection.png) -2. 在 **Setup New Connection** 对话框中,配置以下连接参数: +2. 在**设置新连接**对话框中,配置以下连接参数: - - **Connection Name**:为该连接指定一个有意义的名称。 - - **Hostname**:输入本地部署 TiDB 集群的 IP 地址或域名。 - - **Port**:输入本地部署 TiDB 集群的端口号。 - - **Username**:输入用于连接到 TiDB 的用户名。 - - **Password**:点击 **Store in Keychain ...**,输入用于连接 TiDB 集群的密码,然后点击 **OK** 保存密码。 + - **连接名称**:为此连接指定一个有意义的名称。 + - **主机名**:输入您的 TiDB Self-Managed 集群的 IP 地址或域名。 + - **端口**:输入您的 TiDB Self-Managed 集群的端口号。 + - **用户名**:输入用于连接 TiDB 的用户名。 + - **密码**:点击**存储在钥匙串中...**,输入用于连接 TiDB 集群的密码,然后点击**确定**存储密码。 - ![MySQL Workbench: store the password of TiDB Self-Managed in keychain](/media/develop/mysql-workbench-store-self-hosted-password-in-keychain.png) + ![MySQL Workbench:在钥匙串中存储 TiDB Self-Managed 的密码](/media/develop/mysql-workbench-store-self-hosted-password-in-keychain.png) - 下图显示了连接参数的示例: + 以下图片显示了连接参数的示例: - ![MySQL Workbench: configure connection settings for TiDB Self-Managed](/media/develop/mysql-workbench-connection-config-self-hosted-parameters.png) + ![MySQL Workbench:为 TiDB Self-Managed 配置连接设置](/media/develop/mysql-workbench-connection-config-self-hosted-parameters.png) -3. 点击 **Test Connection** 以验证与本地部署 TiDB 集群的连接。 +3. 点击**测试连接**验证与 TiDB Self-Managed 集群的连接。 -4. 如果连接测试成功,你可以看到 **Successfully made the MySQL connection** 信息。点击 **OK** 保存连接配置。 +4. 如果连接测试成功,您会看到**成功建立 MySQL 连接**消息。点击**确定**保存连接配置。
## 常见问题 -### 如何处理连接超时错误 "Error Code: 2013. Lost connection to MySQL server during query"? +### 如何处理连接超时错误"错误代码:2013。在查询期间与 MySQL 服务器的连接丢失"? -这个错误表示查询执行时间超过了超时限制。要解决这个问题,可以按照以下步骤调整超时设置: +此错误表示查询执行时间超过了超时限制。要解决此问题,您可以通过以下步骤调整超时设置: -1. 启动 MySQL Workbench 并打开 **Workbench Preferences** 页面。 -2. 在 **SQL Editor** > **MySQL Session** 部分,调整 **DBMS connection read timeout interval (in seconds)** 的设置。该字段控制了 MySQL Workbench 在断开与服务器的连接之前查询可以执行的最长时间(以秒为单位)。 +1. 启动 MySQL Workbench 并导航到**工作台首选项**页面。 +2. 在 **SQL 编辑器** > **MySQL 会话**部分,配置 **DBMS 连接读取超时间隔(秒)**选项。这设置了查询在 MySQL Workbench 与服务器断开连接之前可以花费的最长时间(以秒为单位)。 - ![MySQL Workbench: adjust timeout option in SQL Editor settings](/media/develop/mysql-workbench-adjust-sqleditor-read-timeout.jpg) + ![MySQL Workbench:在 SQL 编辑器设置中调整超时选项](/media/develop/mysql-workbench-adjust-sqleditor-read-timeout.jpg) -更多信息,可以参考 [MySQL Workbench 常见问题](https://dev.mysql.com/doc/workbench/en/workbench-faq.html)。 +更多信息,请参见 [MySQL Workbench 常见问题](https://dev.mysql.com/doc/workbench/en/workbench-faq.html)。 ## 下一步 -- 关于 MySQL Workbench 的更多使用方法,可以参考 [MySQL Workbench 官方文档](https://dev.mysql.com/doc/workbench/en/)。 -- 你可以继续阅读[开发者文档](/develop/dev-guide-overview.md),以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide) 支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [MySQL Workbench 文档](https://dev.mysql.com/doc/workbench/en/)了解更多 MySQL Workbench 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,或从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。 + diff --git a/develop/dev-guide-gui-navicat.md b/develop/dev-guide-gui-navicat.md index d8e39fde4bf5..f5695961b9aa 100644 --- a/develop/dev-guide-gui-navicat.md +++ b/develop/dev-guide-gui-navicat.md @@ -1,143 +1,165 @@ --- -title: 使用 Navicat 连接到 TiDB -summary: 了解如何使用 Navicat 连接到 TiDB。 +title: 使用 Navicat 连接 TiDB +summary: 了解如何使用 Navicat 连接 TiDB。 --- -# 使用 Navicat 连接到 TiDB +# 使用 Navicat 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[Navicat](https://www.navicat.com) 是为数据库用户提供的 GUI 工具集。本教程使用 [Navicat Premium](https://www.navicat.com/en/products/navicat-premium) 工具连接 TiDB。 +TiDB 是一个兼容 MySQL 的数据库,而 [Navicat](https://www.navicat.com) 是一套面向数据库用户的 GUI 工具。本教程使用 [Navicat Premium](https://www.navicat.com/en/products/navicat-premium) 工具连接 TiDB。 -在本文档中,你可以学习如何使用 Navicat 连接到 TiDB 集群。 +在本教程中,你将学习如何使用 Navicat 连接到你的 TiDB 集群。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本文中的操作,你需要: +要完成本教程,你需要: -- [Navicat Premium](https://www.navicat.com/en/products/navicat-premium) **17.1.6** 或以上版本。 -- 一个 Navicat Premium 的付费账号。 -- 准备一个 TiDB 集群。 +- [Navicat Premium](https://www.navicat.com) **17.1.6** 或更高版本。 +- Navicat Premium 的付费账户。 +- 一个 TiDB 集群。 -**如果你还没有 TiDB 集群,可以按如下方式创建一个:** + -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md),创建一个 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建一个本地集群。 +**如果你还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + + +**如果你还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 + + ## 连接到 TiDB -根据你选择的 TiDB 部署方式连接到 TiDB 集群。 +根据你选择的 TiDB 部署选项连接到你的 TiDB 集群。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你目标集群的名字,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示一个连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与你的操作环境匹配。 - - **Connection Type** 选择 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `Navicat`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接工具**设置为 `Navicat`。 + - **操作系统**与你的环境匹配。 -4. 点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建一个随机密码。 - > **建议:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果你之前已经创建了密码,你可以使用原始密码,也可以点击**重置密码**生成一个新密码。 -5. 启动 Navicat Premium,点击左上角的 **Connection**,在 **Vendor Filter** 中勾选 **PingCAP**,并双击右侧面板中的 **TiDB**。 +5. 启动 Navicat Premium,点击左上角的**连接**,从**供应商过滤器**列表中选择 **PingCAP**,然后双击右侧面板中的 **TiDB**。 - ![Navicat: add new connection](/media/develop/navicat-premium-add-new-connection.png) + ![Navicat:添加新连接](/media/develop/navicat-premium-add-new-connection.png) -6. 在 **New Connection (TiDB)** 对话框中,配置以下连接参数: +6. 在**新建连接 (TiDB)** 对话框中,配置以下连接参数: - - **Connection Name**:为该连接指定一个有意义的名称。 - - **Host**:输入从 TiDB Cloud 连接对话框中的得到的 `HOST` 参数。 - - **Port**:输入从 TiDB Cloud 连接对话框中的得到的 `PORT` 参数。 - - **User Name**:输入从 TiDB Cloud 连接对话框中的得到的 `USERNAME` 参数。 - - **Password**:输入 TiDB Cloud Serverless 集群的密码。 + - **连接名**:为此连接指定一个有意义的名称。 + - **主机**:输入 TiDB Cloud 连接对话框中的 `HOST` 参数。 + - **端口**:输入 TiDB Cloud 连接对话框中的 `PORT` 参数。 + - **用户名**:输入 TiDB Cloud 连接对话框中的 `USERNAME` 参数。 + - **密码**:输入 TiDB Cloud Serverless 集群的密码。 - ![Navicat: configure connection general panel for TiDB Cloud Serverless](/media/develop/navicat-premium-connection-config-serverless-general.png) + ![Navicat:为 TiDB Cloud Serverless 配置连接常规面板](/media/develop/navicat-premium-connection-config-serverless-general.png) -7. 点击 **SSL** 选项卡,选择 **Use SSL**,**Use authentication** 以及 **Verify server certificate against CA** 复选框。并在 **CA Certificate** 字段中填入从 TiDB Cloud 连接对话框中获取的 `CA` 文件路径。 +7. 点击 **SSL** 标签,选中**使用 SSL**、**使用身份验证**和**根据 CA 验证服务器证书**复选框。然后,将 TiDB Cloud 连接对话框中的 `CA` 文件选择到 **CA 证书**字段中。 - ![Navicat: configure connection SSL panel for TiDB Cloud Serverless](/media/develop/navicat-premium-connection-config-serverless-ssl.png) + ![Navicat:为 TiDB Cloud Serverless 配置连接 SSL 面板](/media/develop/navicat-premium-connection-config-serverless-ssl.png) -8. 点击 **Test Connection** 以验证与 TiDB Cloud Serverless 集群的连接。 +8. 点击**测试连接**以验证与 TiDB Cloud Serverless 集群的连接。 -9. 如果连接测试成功,你可以看到 **Connection Successful** 信息。点击 **OK** 完成连接配置。 +9. 如果连接测试成功,你会看到**连接成功**消息。点击**确定**完成连接配置。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你目标集群的名字,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示一个连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果你还没有配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。更多信息,请参见[连接到你的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 点击 **CA cert** 下载 CA 文件。 +4. 点击 **CA cert** 下载 CA 证书。 -5. 启动 Navicat Premium,点击左上角的 **Connection**,在 **Vendor Filter** 中勾选 **PingCAP**,并双击右侧面板中的 **TiDB**。 +5. 启动 Navicat Premium,点击左上角的**连接**,从**供应商过滤器**列表中选择 **PingCAP**,然后双击右侧面板中的 **TiDB**。 - ![Navicat: add new connection](/media/develop/navicat-premium-add-new-connection.png) + ![Navicat:添加新连接](/media/develop/navicat-premium-add-new-connection.png) -6. 在 **New Connection (TiDB)** 对话框中,配置以下连接参数: +6. 在**新建连接 (TiDB)** 对话框中,配置以下连接参数: - - **Connection Name**:为该连接指定一个有意义的名称。 - - **Host**: 输入从 TiDB Cloud 连接对话框中的得到的 `HOST` 参数。 - - **Port**:输入从 TiDB Cloud 连接对话框中的得到的 `PORT` 参数。 - - **User Name**: 输入从 TiDB Cloud 连接对话框中的得到的 `USERNAME` 参数。 - - **Password**:输入 TiDB Cloud Dedicated 集群的密码。 + - **连接名**:为此连接指定一个有意义的名称。 + - **主机**:输入 TiDB Cloud 连接对话框中的 `HOST` 参数。 + - **端口**:输入 TiDB Cloud 连接对话框中的 `PORT` 参数。 + - **用户名**:输入 TiDB Cloud 连接对话框中的 `USERNAME` 参数。 + - **密码**:输入 TiDB Cloud Dedicated 集群的密码。 - ![Navicat: configure connection general panel for TiDB Cloud Dedicated](/media/develop/navicat-premium-connection-config-dedicated-general.png) + ![Navicat:为 TiDB Cloud Dedicated 配置连接常规面板](/media/develop/navicat-premium-connection-config-dedicated-general.png) -7. 点击 **SSL** 选项卡,选择 **Use SSL**,**Use authentication** 以及 **Verify server certificate against CA** 复选框。然后,在 **CA Certificate** 字段中选择第 4 步下载的 CA 文件。 +7. 点击 **SSL** 标签,选中**使用 SSL**、**使用身份验证**和**根据 CA 验证服务器证书**复选框。然后,将步骤 4 中下载的 CA 文件选择到 **CA 证书**字段中。 - ![Navicat: configure connection SSL panel for TiDB Cloud Dedicated](/media/develop/navicat-premium-connection-config-dedicated-ssl.png) + ![Navicat:为 TiDB Cloud Dedicated 配置连接 SSL 面板](/media/develop/navicat-premium-connection-config-dedicated-ssl.png) -8. 点击 **Test Connection** 以验证与 TiDB Cloud Dedicated 集群的连接。 +8. 点击**测试连接**以验证与 TiDB Cloud Dedicated 集群的连接。 -9. 如果连接测试成功,你可以看到 **Connection Successful** 信息。点击 **OK** 完成连接配置。 +9. 如果连接测试成功,你会看到**连接成功**消息。点击**确定**完成连接配置。
-
+
-1. 启动 Navicat Premium,点击左上角的 **Connection**,在 **Vendor Filter** 中勾选 **PingCAP**,并双击右侧面板中的 **TiDB**。 +1. 启动 Navicat Premium,点击左上角的**连接**,从**供应商过滤器**列表中选择 **PingCAP**,然后双击右侧面板中的 **TiDB**。 - ![Navicat: add new connection](/media/develop/navicat-premium-add-new-connection.png) + ![Navicat:添加新连接](/media/develop/navicat-premium-add-new-connection.png) -2. 在 **New Connection (TiDB)** 对话框中,配置以下连接参数: +2. 在**新建连接 (TiDB)** 对话框中,配置以下连接参数: - - **Connection Name**:为该连接指定一个有意义的名称。 - - **Host**:输入本地部署 TiDB 集群的 IP 地址或域名。 - - **Port**:输入本地部署 TiDB 集群的端口号。 - - **User Name**:输入用于连接到 TiDB 的用户名。 - - **Password**:输入用于连接到 TiDB 的密码。 + - **连接名**:为此连接指定一个有意义的名称。 + - **主机**:输入你的 TiDB Self-Managed 集群的 IP 地址或域名。 + - **端口**:输入你的 TiDB Self-Managed 集群的端口号。 + - **用户名**:输入用于连接 TiDB 的用户名。 + - **密码**:输入用于连接 TiDB 的密码。 - ![Navicat: configure connection general panel for self-hosted TiDB](/media/develop/navicat-premium-connection-config-self-hosted-general.png) + ![Navicat:为自托管 TiDB 配置连接常规面板](/media/develop/navicat-premium-connection-config-self-hosted-general.png) -3. 点击 **Test Connection** 以验证与本地部署 TiDB 集群的连接。 +3. 点击**测试连接**以验证与 TiDB Self-Managed 集群的连接。 -4. 如果连接测试成功,你可以看到 **Connection Successful** 信息。点击 **OK** 完成连接配置。 +4. 如果连接测试成功,你会看到**连接成功**消息。点击**确定**完成连接配置。
## 下一步 -- 你可以继续阅读[开发者文档](/develop/dev-guide-overview.md),以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide) 支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,或从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。 + diff --git a/develop/dev-guide-gui-vscode-sqltools.md b/develop/dev-guide-gui-vscode-sqltools.md new file mode 100644 index 000000000000..8fa90c1ed102 --- /dev/null +++ b/develop/dev-guide-gui-vscode-sqltools.md @@ -0,0 +1,208 @@ +--- +title: 使用 Visual Studio Code 连接 TiDB +summary: 了解如何使用 Visual Studio Code 或 GitHub Codespaces 连接 TiDB。 +--- + +# 使用 Visual Studio Code 连接 TiDB + +TiDB 是一个兼容 MySQL 的数据库,而 [Visual Studio Code (VS Code)](https://code.visualstudio.com/) 是一个轻量级但功能强大的源代码编辑器。本教程使用 [SQLTools](https://marketplace.visualstudio.com/items?itemName=mtxr.sqltools) 扩展,该扩展将 TiDB 作为[官方驱动程序](https://marketplace.visualstudio.com/items?itemName=mtxr.sqltools-driver-mysql)支持。 + +在本教程中,您将学习如何使用 Visual Studio Code 连接到您的 TiDB 集群。 + +> **注意:** +> +> - 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 +> - 本教程也适用于 Visual Studio Code 远程开发环境,如 [GitHub Codespaces](https://github.com/features/codespaces)、[Visual Studio Code Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) 和 [Visual Studio Code WSL](https://code.visualstudio.com/docs/remote/wsl)。 + +## 前提条件 + +要完成本教程,您需要: + +- [Visual Studio Code](https://code.visualstudio.com/#alt-downloads) **1.72.0** 或更高版本。 +- Visual Studio Code 的 [SQLTools MySQL/MariaDB/TiDB](https://marketplace.visualstudio.com/items?itemName=mtxr.sqltools-driver-mysql) 扩展。要安装它,您可以使用以下方法之一: + - 点击此链接直接启动 VS Code 并安装扩展。 + - 导航到 [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=mtxr.sqltools-driver-mysql) 并点击**安装**。 + - 在 VS Code 的**扩展**标签页中,搜索 `mtxr.sqltools-driver-mysql` 找到 **SQLTools MySQL/MariaDB/TiDB** 扩展,然后点击**安装**。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 + + + +## 连接到 TiDB + +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 + + +
+ +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个连接对话框。 + +3. 确保连接对话框中的配置与您的操作环境相匹配。 + + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接方式**设置为 `VS Code`。 + - **操作系统**与您的环境匹配。 + + > **提示:** + > + > 如果您的 VS Code 运行在远程开发环境中,请从列表中选择远程操作系统。例如,如果您使用的是 Windows Subsystem for Linux (WSL),请切换到相应的 Linux 发行版。如果您使用的是 GitHub Codespaces,则无需这样做。 + +4. 点击**生成密码**创建一个随机密码。 + + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码,也可以点击**重置密码**生成一个新密码。 + +5. 启动 VS Code 并在导航窗格中选择 **SQLTools** 扩展。在 **CONNECTIONS** 部分下,点击 **Add New Connection** 并选择 **TiDB** 作为数据库驱动程序。 + + ![VS Code SQLTools:添加新连接](/media/develop/vsc-sqltools-add-new-connection.jpg) + +6. 在设置窗格中,配置以下连接参数: + + - **Connection name**:为此连接指定一个有意义的名称。 + - **Connection group**:(可选)为此连接组指定一个有意义的名称。具有相同组名的连接将被分组在一起。 + - **Connect using**:选择 **Server and Port**。 + - **Server Address**:输入 TiDB Cloud 连接对话框中的 `HOST` 参数。 + - **Port**:输入 TiDB Cloud 连接对话框中的 `PORT` 参数。 + - **Database**:输入要连接的数据库。 + - **Username**:输入 TiDB Cloud 连接对话框中的 `USERNAME` 参数。 + - **Password mode**:选择 **SQLTools Driver Credentials**。 + - 在 **MySQL driver specific options** 区域,配置以下参数: + + - **Authentication Protocol**:选择 **default**。 + - **SSL**:选择 **Enabled**。TiDB Cloud Serverless 需要安全连接。在 **SSL Options (node.TLSSocket)** 区域,将 **Certificate Authority (CA) Certificate File** 字段配置为 TiDB Cloud 连接对话框中的 `CA` 参数。 + + > **注意:** + > + > 如果您在 Windows 或 GitHub Codespaces 上运行,可以将 **SSL** 留空。默认情况下,SQLTools 信任由 Let's Encrypt 策划的知名 CA。更多信息,请参见 [TiDB Cloud Serverless 根证书管理](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters#root-certificate-management)。 + + ![VS Code SQLTools:配置 TiDB Cloud Serverless 的连接设置](/media/develop/vsc-sqltools-connection-config-serverless.jpg) + +7. 点击 **TEST CONNECTION** 以验证与 TiDB Cloud Serverless 集群的连接。 + + 1. 在弹出窗口中,点击 **Allow**。 + 2. 在 **SQLTools Driver Credentials** 对话框中,输入您在步骤 4 中创建的密码。 + + ![VS Code SQLTools:输入密码连接到 TiDB Cloud Serverless](/media/develop/vsc-sqltools-password.jpg) + +8. 如果连接测试成功,您会看到 **Successfully connected!** 消息。点击 **SAVE CONNECTION** 保存连接配置。 + +
+
+ +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个连接对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 + + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 + + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + +4. 启动 VS Code 并在导航窗格中选择 **SQLTools** 扩展。在 **CONNECTIONS** 部分下,点击 **Add New Connection** 并选择 **TiDB** 作为数据库驱动程序。 + + ![VS Code SQLTools:添加新连接](/media/develop/vsc-sqltools-add-new-connection.jpg) + +5. 在设置窗格中,配置以下连接参数: + + - **Connection name**:为此连接指定一个有意义的名称。 + - **Connection group**:(可选)为此连接组指定一个有意义的名称。具有相同组名的连接将被分组在一起。 + - **Connect using**:选择 **Server and Port**。 + - **Server Address**:输入 TiDB Cloud 连接对话框中的 `host` 参数。 + - **Port**:输入 TiDB Cloud 连接对话框中的 `port` 参数。 + - **Database**:输入要连接的数据库。 + - **Username**:输入 TiDB Cloud 连接对话框中的 `user` 参数。 + - **Password mode**:选择 **SQLTools Driver Credentials**。 + - 在 **MySQL driver specific options** 区域,配置以下参数: + + - **Authentication Protocol**:选择 **default**。 + - **SSL**:选择 **Disabled**。 + + ![VS Code SQLTools:配置 TiDB Cloud Dedicated 的连接设置](/media/develop/vsc-sqltools-connection-config-dedicated.jpg) + +6. 点击 **TEST CONNECTION** 以验证与 TiDB Cloud Dedicated 集群的连接。 + + 1. 在弹出窗口中,点击 **Allow**。 + 2. 在 **SQLTools Driver Credentials** 对话框中,输入 TiDB Cloud Dedicated 集群的密码。 + + ![VS Code SQLTools:输入密码连接到 TiDB Cloud Dedicated](/media/develop/vsc-sqltools-password.jpg) + +7. 如果连接测试成功,您会看到 **Successfully connected!** 消息。点击 **SAVE CONNECTION** 保存连接配置。 + +
+
+ +1. 启动 VS Code 并在导航窗格中选择 **SQLTools** 扩展。在 **CONNECTIONS** 部分下,点击 **Add New Connection** 并选择 **TiDB** 作为数据库驱动程序。 + + ![VS Code SQLTools:添加新连接](/media/develop/vsc-sqltools-add-new-connection.jpg) + +2. 在设置窗格中,配置以下连接参数: + + - **Connection name**:为此连接指定一个有意义的名称。 + - **Connection group**:(可选)为此连接组指定一个有意义的名称。具有相同组名的连接将被分组在一起。 + - **Connect using**:选择 **Server and Port**。 + - **Server Address**:输入您的 TiDB Self-Managed 集群的 IP 地址或域名。 + - **Port**:输入您的 TiDB Self-Managed 集群的端口号。 + - **Database**:输入要连接的数据库。 + - **Username**:输入用于连接到您的 TiDB Self-Managed 集群的用户名。 + - **Password mode**: + + - 如果密码为空,选择 **Use empty password**。 + - 否则,选择 **SQLTools Driver Credentials**。 + + - 在 **MySQL driver specific options** 区域,配置以下参数: + + - **Authentication Protocol**:选择 **default**。 + - **SSL**:选择 **Disabled**。 + + ![VS Code SQLTools:配置 TiDB Self-Managed 的连接设置](/media/develop/vsc-sqltools-connection-config-self-hosted.jpg) + +3. 点击 **TEST CONNECTION** 以验证与 TiDB Self-Managed 集群的连接。 + + 如果密码不为空,在弹出窗口中点击 **Allow**,然后输入 TiDB Self-Managed 集群的密码。 + + ![VS Code SQLTools:输入密码连接到 TiDB Self-Managed](/media/develop/vsc-sqltools-password.jpg) + +4. 如果连接测试成功,您会看到 **Successfully connected!** 消息。点击 **SAVE CONNECTION** 保存连接配置。 + +
+
+ +## 下一步 + +- 从 [Visual Studio Code 的文档](https://code.visualstudio.com/docs)了解更多 Visual Studio Code 的用法。 +- 从 SQLTools 的[文档](https://marketplace.visualstudio.com/items?itemName=mtxr.sqltools)和 [GitHub 仓库](https://github.com/mtxr/vscode-sqltools)了解更多 VS Code SQLTools 扩展的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-hybrid-oltp-and-olap-queries.md b/develop/dev-guide-hybrid-oltp-and-olap-queries.md index b584f702e7f6..2643ba13bd68 100644 --- a/develop/dev-guide-hybrid-oltp-and-olap-queries.md +++ b/develop/dev-guide-hybrid-oltp-and-olap-queries.md @@ -1,35 +1,35 @@ --- title: HTAP 查询 -summary: 介绍 TiDB 中的 HTAP 查询功能。 +summary: 介绍 TiDB 中的 HTAP 查询。 --- # HTAP 查询 -HTAP 是 Hybrid Transactional / Analytical Processing 的缩写。传统意义上,数据库往往专为交易或者分析场景设计,因而数据平台往往需要被切分为 Transactional Processing 和 Analytical Processing 两个部分,而数据需要从交易库复制到分析型数据库以便快速响应分析查询。而 TiDB 数据库则可以同时承担交易和分析两种职能,这大大简化了数据平台的建设,也能让用户使用更新鲜的数据进行分析。 +HTAP 代表混合事务和分析处理(Hybrid Transactional and Analytical Processing)。传统上,数据库通常针对事务或分析场景进行设计,因此数据平台经常需要拆分为事务处理和分析处理,并且需要将数据从事务数据库复制到分析数据库以快速响应分析查询。TiDB 数据库可以同时执行事务和分析任务,这大大简化了数据平台的构建,并允许用户使用更新鲜的数据进行分析。 -在 TiDB 当中,同时拥有面向在线事务处理的行存储引擎 TiKV 与面向实时分析场景的列存储引擎 TiFlash 两套存储引擎。数据在行存 (Row-Store) 与列存 (Columnar-Store) 同时存在,自动同步,保持强一致性。行存为在线事务处理 OLTP 提供优化,列存则为在线分析处理 OLAP 提供性能优化。 +TiDB 使用行式存储引擎 TiKV 进行在线事务处理(OLTP),使用列式存储引擎 TiFlash 进行在线分析处理(OLAP)。行式存储引擎和列式存储引擎共存以实现 HTAP。两种存储引擎都可以自动复制数据并保持强一致性。行式存储引擎优化 OLTP 性能,列式存储引擎优化 OLAP 性能。 -在[创建数据库](/develop/dev-guide-create-table.md#使用-htap-能力)章节当中,已经介绍了如何开启 TiDB 的 HTAP 能力。下面将进一步介绍如何使用 HTAP 能力更快地分析数据。 +[创建表](/develop/dev-guide-create-table.md#use-htap-capabilities)部分介绍了如何启用 TiDB 的 HTAP 功能。以下介绍如何使用 HTAP 更快地分析数据。 ## 数据准备 -在开始之前,你可以[通过 `tiup demo` 命令导入](/develop/dev-guide-bookshop-schema-design.md#方法一通过-tiup-demo-命令行)更加大量的示例数据,例如: +在开始之前,你可以[通过 `tiup demo` 命令](/develop/dev-guide-bookshop-schema-design.md#method-1-via-tiup-demo)导入更多示例数据。例如: ```shell tiup demo bookshop prepare --users=200000 --books=500000 --authors=100000 --ratings=1000000 --orders=1000000 --host 127.0.0.1 --port 4000 --drop-tables ``` -或[使用 TiDB Cloud 的 Import 功能导入](/develop/dev-guide-bookshop-schema-design.md#方法二通过-tidb-cloud-import-功能)预先准备好的示例数据。 +或者你可以[使用 TiDB Cloud 的导入功能](/develop/dev-guide-bookshop-schema-design.md#method-2-via-tidb-cloud-import)导入预先准备好的示例数据。 ## 窗口函数 -在使用数据库时,除了希望它能够存储想要记录的数据,能够实现诸如下单买书、给书籍评分等业务功能外,可能还需要对已有的数据进行分析,以便根据数据作出进一步的运营和决策。 +在使用数据库时,除了存储数据和提供应用功能(如订购和评价图书)外,你可能还需要分析数据库中的数据以进行进一步的操作和决策。 -在[单表读取](/develop/dev-guide-get-data-from-single-table.md)章节当中,已经介绍了如何使用聚合查询来分析数据的整体情况,在更为复杂的使用场景下,你可能希望多个聚合查询的结果汇总在一个查询当中。例如:你想要对某一本书的订单量的历史趋势有所了解,就需要在每个月都对所有订单数据进行一次聚合求 `sum`,然后将 `sum` 结果汇总在一起才能够得到历史的趋势变化数据。 +[从单表查询数据](/develop/dev-guide-get-data-from-single-table.md)文档介绍了如何使用聚合查询来整体分析数据。在更复杂的场景中,你可能想要将多个聚合查询的结果聚合到一个查询中。如果你想知道特定图书订单金额的历史趋势,你可以对每个月的所有订单数据进行 `sum` 聚合,然后将 `sum` 结果聚合在一起以获得历史趋势。 -为了方便用户进行此类分析,TiDB 从 3.0 版本开始便支持了窗口函数功能,窗口函数为每一行数据提供了跨行数据访问的能力,不同于常规的聚合查询,窗口函数在对数据行进行聚合时不会导致结果集被合并成单行数据。 +为了便于此类分析,从 TiDB v3.0 开始,TiDB 支持窗口函数。对于每一行数据,此函数提供了跨多行访问数据的能力。与常规聚合查询不同,窗口函数在聚合行时不会将结果集合并为单行。 -与聚合函数类似,窗口函数在使用时也需要搭配一套固定的语法: +与聚合函数类似,在使用窗口函数时也需要遵循固定的语法集: ```sql SELECT @@ -40,7 +40,7 @@ FROM ### `ORDER BY` 子句 -例如:可以利用聚合窗口函数 `sum()` 函数的累加效果来实现对某一本书的订单量的历史趋势的分析: +使用聚合窗口函数 `sum()`,你可以分析特定图书订单金额的历史趋势。例如: ```sql WITH orders_group_by_month AS ( @@ -56,7 +56,7 @@ FROM orders_group_by_month ORDER BY month ASC; ``` -`sum()` 函数会在 `OVER` 子句当中通过 `ORDER BY` 子句指定的排序方式按顺序对数据进行累加,累加的结果如下: +`sum()` 函数按照 `OVER` 子句中 `ORDER BY` 语句指定的顺序累积数据。结果如下: ``` +---------+-------+ @@ -79,13 +79,13 @@ ORDER BY month ASC; 13 rows in set (0.01 sec) ``` -将得到的数据通过一个横轴为时间,纵轴为累计订单量的折线图进行可视化,便可以轻松地通过折线图的斜率变化宏观地了解到这本书的历史订单的增长趋势。 +通过以时间为横轴、累计订单金额为纵轴的折线图可视化上述数据。你可以通过斜率的变化轻松了解该书的历史订购趋势。 ### `PARTITION BY` 子句 -把需求变得更复杂一点,假设想要分析不同类型书的历史订单增长趋势,并且希望将这些数据通过同一个多系列折线图进行呈现。 +假设你想分析不同类型图书的历史订购趋势,并在同一个折线图中以多个系列进行可视化。 -可以利用 `PARTITION BY` 子句根据书的类型进行分组,对不同类型的书籍分别统计它们的订单历史订单累计量。 +你可以使用 `PARTITION BY` 子句按类型对图书进行分组,并分别统计每种类型的历史订单。 ```sql WITH orders_group_by_month AS ( @@ -108,7 +108,7 @@ WITH orders_group_by_month AS ( SELECT * FROM acc; ``` -查询结果如下: +结果如下: ``` +------------------------------+---------+------+ @@ -136,31 +136,31 @@ SELECT * FROM acc; ### 非聚合窗口函数 -除此之外,TiDB 还提供了一些非聚合的[窗口函数](/functions-and-operators/window-functions.md),可以借助这些函数实现更加丰富分析查询。 +TiDB 还提供了一些非聚合的[窗口函数](/functions-and-operators/window-functions.md)用于更多分析语句。 -例如,在前面的[分页查询](/develop/dev-guide-paginate-results.md)章节当中,已经介绍了如何巧妙地利用 `row_number()` 函数实现高效的分页批处理能力。 +例如,[分页查询](/develop/dev-guide-paginate-results.md)文档介绍了如何使用 `row_number()` 函数实现高效的分页批处理。 ## 混合负载 -当将 TiDB 应用于在线实时分析处理的混合负载场景时,开发人员只需要提供一个入口,TiDB 将自动根据业务类型选择不同的处理引擎。 +在混合负载场景中使用 TiDB 进行实时在线分析处理时,你只需要为你的数据提供一个 TiDB 入口点。TiDB 会根据具体业务自动选择不同的处理引擎。 -### 开启列存副本 +### 创建 TiFlash 副本 -TiDB 默认使用的存储引擎 TiKV 是行存的,你可以通过阅读[开启 HTAP 能力](/develop/dev-guide-create-table.md#使用-htap-能力)章节,在进行后续步骤前,先通过如下 SQL 对 `books` 与 `orders` 表添加 TiFlash 列存副本: +TiDB 默认使用行式存储引擎 TiKV。要使用列式存储引擎 TiFlash,请参阅[启用 HTAP 功能](/develop/dev-guide-create-table.md#use-htap-capabilities)。在通过 TiFlash 查询数据之前,你需要使用以下语句为 `books` 和 `orders` 表创建 TiFlash 副本: ```sql ALTER TABLE books SET TIFLASH REPLICA 1; ALTER TABLE orders SET TIFLASH REPLICA 1; ``` -通过执行下面的 SQL 语句可以查看到 TiDB 创建列存副本的进度: +你可以使用以下语句检查 TiFlash 副本的进度: ```sql SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = 'bookshop' and TABLE_NAME = 'books'; SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = 'bookshop' and TABLE_NAME = 'orders'; ``` -当 `PROGRESS` 列为 1 时表示同步进度完成度达到 100%,`AVAILABLE` 列为 1 表示副本当前可用。 +`PROGRESS` 列为 1 表示进度为 100% 完成,`AVAILABLE` 列为 1 表示副本当前可用。 ``` +--------------+------------+----------+---------------+-----------------+-----------+----------+ @@ -177,9 +177,9 @@ SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = 'bookshop' 1 row in set (0.07 sec) ``` -副本添加完成之后,你可以通过使用 `EXPLAIN` 语句查看上面窗口函数[示例 SQL](#partition-by-子句) 的执行计划。你会发现执行计划当中已经出现了 `cop[tiflash]` 字样,说明 TiFlash 引擎已经开始发挥作用了。 +添加副本后,你可以使用 `EXPLAIN` 语句检查上述窗口函数 [`PARTITION BY` 子句](#partition-by-子句)的执行计划。如果执行计划中出现 `cop[tiflash]`,表示 TiFlash 引擎已开始工作。 -再次执行[示例 SQL](#partition-by-子句),查询结果如下: +然后,再次执行 [`PARTITION BY` 子句](#partition-by-子句)中的示例 SQL 语句。结果如下: ``` +------------------------------+---------+------+ @@ -205,18 +205,18 @@ SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = 'bookshop' 1500 rows in set (0.79 sec) ``` -通过对比前后两次的执行结果,你会发现使用 TiFlash 处理有查询速度有了较为明显的提升(当数据量更大时,提升会更为显著)。这是因为在使用窗口函数时往往需要对某些列的数据进行全表扫描,相比行存的 TiKV,列存的 TiFlash 更加适合来处理这类分析型任务的负载。而对于 TiKV 来说,如果能够通过主键或索引快速地将所要查询的行数减少,往往查询速度也会非常快,而且所消耗的资源一般相对 TiFlash 而言会更少。 +通过比较两次执行结果,你可以发现使用 TiFlash 后查询速度显著提高(在数据量大的情况下提升更明显)。这是因为窗口函数通常依赖于对某些列的全表扫描,而列式的 TiFlash 比行式的 TiKV 更适合处理这类分析任务。对于 TiKV,如果你使用主键或索引来减少需要查询的行数,查询也可以很快,并且与 TiFlash 相比消耗更少的资源。 ### 指定查询引擎 -尽管 TiDB 会使用基于成本的优化器(CBO)自动地根据代价估算选择是否使用 TiFlash 副本。但是在实际使用当中,如果你非常确定查询的类型,推荐你使用 [Optimizer Hints](/optimizer-hints.md) 明确的指定查询所使用的执行引擎,避免因为优化器的优化结果不同,导致应用程序性能出现波动。 +TiDB 使用基于成本的优化器(CBO)根据成本估算自动选择是否使用 TiFlash 副本。但是,如果你确定你的查询是事务性的还是分析性的,你可以使用[优化器提示](/optimizer-hints.md)指定要使用的查询引擎。 -你可以像下面的 SQL 一样在 SELECT 语句中通过 Hint `/*+ read_from_storage(engine_name[table_name]) */` 指定查询时需要使用的查询引擎。 +要在查询中指定使用哪个引擎,你可以使用 `/*+ read_from_storage(engine_name[table_name]) */` 提示,如以下语句所示。 > **注意:** > -> 1. 如果你的表使用了别名,你应该将 Hints 当中的 table_name 替代为 alias_name,否则 Hints 会失效。 -> 2. 另外,对[公共表表达式](/develop/dev-guide-use-common-table-expression.md)设置 read_from_storage Hint 是不起作用的。 +> - 如果表有别名,在提示中使用别名而不是表名,否则提示不会生效。 +> - `read_from_storage` 提示对[公共表表达式](/develop/dev-guide-use-common-table-expression.md)不起作用。 ```sql WITH orders_group_by_month AS ( @@ -240,13 +240,38 @@ WITH orders_group_by_month AS ( SELECT * FROM acc; ``` -如果你通过 `EXPLAIN` 语句查看上面 SQL 的执行计划,你会发现 task 列中会同时出现 `cop[tiflash]` 和 `cop[tikv]`,这意味着 TiDB 在处理这个查询的时候会同时调度行存查询引擎和列存查询引擎来完成查询任务。需要指出的是,因为 tiflash 和 tikv 存储引擎通常属于不同的计算节点,所以两种查询类型互相之间不受影响。 +你可以使用 `EXPLAIN` 语句检查上述 SQL 语句的执行计划。如果任务列中同时出现 `cop[tiflash]` 和 `cop[tikv]`,表示 TiFlash 和 TiKV 都被调度来完成此查询。注意,TiFlash 和 TiKV 存储引擎通常使用不同的 TiDB 节点,因此两种查询类型不会相互影响。 -你可以通过阅读[使用 TiDB 读取 TiFlash](/tiflash/use-tidb-to-read-tiflash.md) 小节进一步了解 TiDB 如何选择使用 TiFlash 作为查询引擎。 +有关 TiDB 如何选择使用 TiFlash 的更多信息,请参阅[使用 TiDB 读取 TiFlash 副本](/tiflash/use-tidb-to-read-tiflash.md)。 -## 扩展阅读 +## 阅读更多 + + + +- [HTAP 快速上手](/quick-start-with-htap.md) +- [探索 HTAP](/explore-htap.md) + + + + + +- [TiDB Cloud HTAP 快速上手](/tidb-cloud/tidb-cloud-htap-quickstart.md) + + -- [HTAP 快速上手指南](/quick-start-with-htap.md) -- [HTAP 深入探索指南](/explore-htap.md) - [窗口函数](/functions-and-operators/window-functions.md) -- [使用 TiFlash](/tiflash/tiflash-overview.md#使用-tiflash) +- [使用 TiFlash](/tiflash/tiflash-overview.md#use-tiflash) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-implicit-type-conversion.md b/develop/dev-guide-implicit-type-conversion.md index 8dbef52490fe..223750b3e128 100644 --- a/develop/dev-guide-implicit-type-conversion.md +++ b/develop/dev-guide-implicit-type-conversion.md @@ -1,36 +1,36 @@ --- title: 避免隐式类型转换 -summary: 介绍 TiDB 中隐式类型转换可能会带来的后果和避免方法。 +summary: 介绍 TiDB 中隐式类型转换可能带来的后果以及避免方法。 --- # 避免隐式类型转换 -本章内容将介绍 TiDB 中的隐式类型转换规则、可能带来的后果及避免方法。 +本文档介绍 TiDB 中隐式类型转换的规则和可能带来的后果,以及如何避免隐式类型转换。 ## 转换规则 -当 SQL 中谓词两侧的数据类型不一致时,TiDB 将隐式地将一侧或两侧的数据类型进行转换,将其变为兼容的数据类型,以进行谓词运算。 +当 SQL 语句中谓词两侧的数据类型不匹配时,TiDB 会隐式地将一侧或双侧的数据类型转换为兼容的数据类型以进行谓词运算。 -TiDB 中隐式类型转换规则如下: +TiDB 中隐式类型转换的规则如下: -- 如果一个或两个参数都是 NULL,比较的结果是 NULL(NULL 安全的 `<=>` 相等比较运算符除外,对于 NULL `<=>` NULL,结果为 true,不需要转换)。 -- 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。 -- 如果两个参数都是整数,则将它们作为整数进行比较。 -- 如果不与数字进行比较,则将十六进制值视为二进制字符串。 -- 如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将参数与十进制值进行比较,如果另一个参数是浮点值,则将参数与浮点值进行比较。 -- 如果其中一个参数是 TIMESTAMP 或 DATETIME 列,另一个参数是常量,则在执行比较之前将常量转换为时间戳。 -- 在所有其他情况下,参数都是作为浮点数(DOUBLE 类型)比较的。 +- 如果一个或两个参数为 `NULL`,比较的结果为 `NULL`。NULL 安全的 `<=>` 等价比较运算符不需要转换,因为 NULL `<=>` NULL 的结果为 `true`。 +- 如果比较操作中的两个参数都是字符串,则按字符串进行比较。 +- 如果两个参数都是整数,则按整数进行比较。 +- 如果没有与数字进行比较,则十六进制值被视为二进制字符串。 +- 如果其中一个参数是小数值,比较取决于另一个参数。如果另一个参数是小数值或整数值,则与小数值进行比较。如果另一个参数是浮点值,则与浮点值进行比较。 +- 如果其中一个参数是 `TIMESTAMP` 或 `DATETIME` 列,另一个参数是常量,则在执行比较之前将常量转换为时间戳。 +- 在所有其他情况下,参数都作为浮点数(`DOUBLE` 类型)进行比较。 -## 隐式类型转换引起的后果 +## 隐式类型转换带来的后果 -隐式类型转换增强了人机交互的易用性,但在应用代码中,应尽量避免隐式类型转换出现,这是由于隐式类型转换会导致: +隐式类型转换增加了人机交互的可用性。但是,应避免在应用程序代码中使用隐式类型转换,因为它们可能会导致以下问题: - 索引失效 -- 精度丢失 +- 精度损失 ### 索引失效 -如下案例,account_id 为主键,其数据类型为 `varchar`。通过执行计划可见,该 SQL 发生了隐式类型转换,无法使用索引。 +在以下情况中,`account_id` 是主键,其数据类型为 `varchar`。在执行计划中,这条 SQL 语句存在隐式类型转换,无法使用索引。 ```sql DESC SELECT * FROM `account` WHERE `account_id`=6010000000009801; @@ -44,11 +44,11 @@ DESC SELECT * FROM `account` WHERE `account_id`=6010000000009801; 3 rows in set (0.00 sec) ``` -**运行结果简述**:从以上执行计划中,可见 Cast 算子。 +**运行结果简述**:从上述执行计划中,可以看到 `Cast` 运算符。 -### 精度丢失 +### 精度损失 -如下案例,字段 a 的数据类型为 `decimal(32,0)`,从执行计划可以得知,出现了隐式类型转换,decimal 字段和字符串常值都被转换为 double 类型,而 `double` 类型的精度没有 `decimal` 高,出现了精度丢失,在这个 case 中,造成了筛选出范围之外的结果集的错误。 +在以下情况中,`a` 字段的数据类型为 `decimal(32,0)`。在执行计划中,发生了隐式类型转换,小数字段和字符串常量都被转换为 double 类型。由于 double 类型的精度不如 decimal,会出现精度损失。在这种情况下,SQL 语句错误地过滤了超出范围的结果集。 ```sql DESC SELECT * FROM `t1` WHERE `a` BETWEEN '12123123' AND '1111222211111111200000'; @@ -62,7 +62,7 @@ DESC SELECT * FROM `t1` WHERE `a` BETWEEN '12123123' AND '1111222211111111200000 3 rows in set (0.00 sec) ``` -**运行结果简述**:从以上执行计划中,可见 Cast 算子。 +**运行结果简述**:从上述执行计划中,可以看到 `Cast` 运算符。 ```sql SELECT * FROM `t1` WHERE `a` BETWEEN '12123123' AND '1111222211111111200000'; @@ -75,4 +75,18 @@ SELECT * FROM `t1` WHERE `a` BETWEEN '12123123' AND '1111222211111111200000'; ``` -**运行结果简述**:以上执行出现了错误结果。 +**运行结果简述**:上述执行给出了错误的结果。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-index-best-practice.md b/develop/dev-guide-index-best-practice.md index 380fe93ee1c6..509925559f3d 100644 --- a/develop/dev-guide-index-best-practice.md +++ b/develop/dev-guide-index-best-practice.md @@ -1,17 +1,17 @@ --- -title: 索引的最佳实践 -summary: 介绍 TiDB 中索引的最佳实践。 +title: 索引最佳实践 +summary: 了解在 TiDB 中创建和使用索引的一些最佳实践。 --- -# 索引的最佳实践 +# 索引最佳实践 -本章会介绍在 TiDB 中使用索引的一些最佳实践。 +本文档介绍在 TiDB 中创建和使用索引的一些最佳实践。 -## 准备工作 +## 开始之前 -本章内容将会用 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库中的 `books` 表作为示例。 +本节以 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库中的 `books` 表为例。 ```sql CREATE TABLE `books` ( @@ -27,21 +27,21 @@ CREATE TABLE `books` ( ## 创建索引的最佳实践 -- 建立你需要使用的数据的所有列的组合索引,这种优化技巧被称为[覆盖索引优化 (covering index optimization)](/explain-indexes.md#indexreader)。**覆盖索引优化**将使得 TiDB 可以直接在索引上得到该查询所需的所有数据,可以大幅提升性能。 -- 避免创建你不需要的二级索引,有用的二级索引能加速查询,但是要注意新增一个索引是有副作用的。每增加一个索引,在插入一条数据的时候,就要额外新增一个 Key-Value,所以索引越多,写入越慢,并且空间占用越大。另外过多的索引也会影响优化器运行时间,并且不合适的索引会误导优化器。所以索引并不是越多越好。 -- 根据具体的业务特点创建合适的索引。原则上需要对查询中需要用到的列创建索引,目的是提高性能。下面几种情况适合创建索引: +- 创建包含多个列的联合索引,这是一种称为[覆盖索引优化](/explain-indexes.md#indexreader)的优化。**覆盖索引优化**允许 TiDB 直接在索引上查询数据,这有助于提高性能。 +- 避免在不经常查询的列上创建二级索引。有用的二级索引可以加快查询速度,但要注意它也有副作用。每次添加索引时,插入一行时都会添加一个额外的 Key-Value。索引越多,写入速度越慢,占用的空间也越多。此外,过多的索引会影响优化器运行时间,不恰当的索引可能会误导优化器。因此,更多的索引并不总是意味着更好的性能。 +- 根据你的应用程序创建适当的索引。原则上,只在需要用于查询的列上创建索引以提高性能。以下情况适合创建索引: - - 区分度比较大的列,通过索引能显著地减少过滤后的行数。例如推荐在人的身份证号码这一列上创建索引,但不推荐在人的性别这一列上创建索引。 - - 有多个查询条件时,可以选择组合索引,注意需要把等值条件的列放在组合索引的前面。这里举一个例子,假设常用的查询是 `SELECT * FROM t where c1 = 10 and c2 = 100 and c3 > 10`,那么可以考虑建立组合索引 `Index cidx (c1, c2, c3)`,这样可以用查询条件构造出一个索引前缀进行 Scan。 + - 区分度高的列可以显著减少过滤的行数。例如,建议在身份证号码上创建索引,但不建议在性别上创建索引。 + - 在使用多个条件查询时使用联合索引。注意,等值条件的列需要放在联合索引的前面。这里有一个例子:如果经常使用 `select* from t where c1 = 10 and c2 = 100 and c3 > 10` 查询,考虑创建联合索引 `Index cidx (c1, c2, c3)`,这样可以根据查询条件构建索引前缀进行扫描。 -- 请使用有意义的二级索引名,推荐你遵循公司或组织的表命名规范。如果你的公司或组织没有相应的命名规范,可参考[索引命名规范](/develop/dev-guide-object-naming-guidelines.md#索引命名规范)。 +- 为二级索引命名时要有意义,建议遵循公司或组织的表命名约定。如果不存在这样的命名约定,请遵循[索引命名规范](/develop/dev-guide-object-naming-guidelines.md)中的规则。 ## 使用索引的最佳实践 -- 建立索引的目的是为了加速查询,所以请确保索引能在一些查询中被用上。如果一个索引不会被任何查询语句用到,那这个索引是没有意义的,请删除这个索引。 -- 使用组合索引时,需要满足最左前缀原则。 +- 索引是为了加快查询速度,所以要确保现有的索引实际上被某些查询使用。如果一个索引没有被任何查询使用,这个索引就是无意义的,你需要删除它。 +- 使用联合索引时,遵循最左前缀原则。 - 例如假设在列 `title, published_at` 上新建一个组合索引索引: + 假设你在 `title` 和 `published_at` 列上创建一个新的联合索引: {{< copyable "sql" >}} @@ -49,7 +49,7 @@ CREATE TABLE `books` ( CREATE INDEX title_published_at_idx ON books (title, published_at); ``` - 下面这个查询依然能用上这个组合索引: + 以下查询仍然可以使用联合索引: {{< copyable "sql" >}} @@ -57,7 +57,7 @@ CREATE TABLE `books` ( SELECT * FROM books WHERE title = 'database'; ``` - 但下面这个查询由于未指定组合索引中最左边第一列的条件,所以无法使用组合索引: + 但是,以下查询无法使用联合索引,因为没有指定索引中最左边第一列的条件: {{< copyable "sql" >}} @@ -65,9 +65,9 @@ CREATE TABLE `books` ( SELECT * FROM books WHERE published_at = '2018-08-18 21:42:08'; ``` -- 在查询条件中使用索引列作为条件时,不要在索引列上做计算,函数,或者类型转换的操作,会导致优化器无法使用该索引。 +- 在查询中使用索引列作为条件时,不要对其进行计算、函数运算或类型转换,这会阻止 TiDB 优化器使用索引。 - 例如假设在时间类型的列 `published_at` 上新建一个索引: + 假设你在时间类型列 `published_at` 上创建一个新索引: {{< copyable "sql" >}} @@ -75,7 +75,7 @@ CREATE TABLE `books` ( CREATE INDEX published_at_idx ON books (published_at); ``` - 但下面查询是无法使用 `published_at` 上的索引的: + 但是,以下查询无法使用 `published_at` 上的索引: {{< copyable "sql" >}} @@ -83,7 +83,7 @@ CREATE TABLE `books` ( SELECT * FROM books WHERE YEAR(published_at)=2022; ``` - 可以改写成下面查询,避免在索引列上做函数计算后,即可使用 `published_at` 上的索引: + 要使用 `published_at` 上的索引,你可以将查询重写如下,这样可以避免在索引列上使用任何函数: {{< copyable "sql" >}} @@ -91,7 +91,7 @@ CREATE TABLE `books` ( SELECT * FROM books WHERE published_at >= '2022-01-01' AND published_at < '2023-01-01'; ``` - 也可以使用表达式索引,例如对查询条件中的 `YEAR(published_at)` 创建一个表达式索引: + 你也可以使用表达式索引为查询条件中的 `YEAR(published_at)` 创建一个表达式索引: {{< copyable "sql" >}} @@ -99,15 +99,15 @@ CREATE TABLE `books` ( CREATE INDEX published_year_idx ON books ((YEAR(published_at))); ``` - 然后通过 `SELECT * FROM books WHERE YEAR(published_at)=2022;` 查询就能使用 `published_year_idx` 索引来加速查询了。 + 现在,如果你执行 `SELECT * FROM books WHERE YEAR(published_at)=2022;` 查询,查询可以使用 `published_year_idx` 索引来加速执行。 - > **注意:** + > **警告:** > - > 表达式索引目前是 TiDB 的实验特性,需要在 TiDB 配置文件中开启表达式索引特性,详情可以参考[表达式索引文档](/sql-statements/sql-statement-create-index.md#表达式索引)。 + > 目前,表达式索引是一个实验性功能,需要在 TiDB 配置文件中启用。更多详情,请参阅[表达式索引](/sql-statements/sql-statement-create-index.md#expression-index)。 -- 尽量使用覆盖索引,即索引列包含查询列,避免总是 `SELECT *` 查询所有列的语句。 +- 尽量使用覆盖索引,其中索引中的列包含要查询的列,避免使用 `SELECT *` 语句查询所有列。 - 例如下面查询只需扫描索引 `title_published_at_idx` 数据即可获取查询列的数据: + 以下查询只需要扫描索引 `title_published_at_idx` 就能获取数据: {{< copyable "sql" >}} @@ -115,7 +115,7 @@ CREATE TABLE `books` ( SELECT title, published_at FROM books WHERE title = 'database'; ``` - 但下面查询语句虽然能用上组合索引 `(title, published_at)`,但会多一个回表查询非索引列数据的额外开销,回表查询是指根据索引数据中存储的引用(一般是主键信息),到表中查询相应行的数据。 + 虽然以下查询语句可以使用联合索引 `(title, published_at)`,但它会导致查询非索引列的额外开销,这需要 TiDB 根据索引数据中存储的引用(通常是主键信息)来查询行数据。 {{< copyable "sql" >}} @@ -123,7 +123,7 @@ CREATE TABLE `books` ( SELECT * FROM books WHERE title = 'database'; ``` -- 查询条件使用 `!=`,`NOT IN` 时,无法使用索引。例如下面查询无法使用任何索引: +- 当查询条件包含 `!=` 或 `NOT IN` 时,查询无法使用索引。例如,以下查询无法使用任何索引: {{< copyable "sql" >}} @@ -131,7 +131,7 @@ CREATE TABLE `books` ( SELECT * FROM books WHERE title != 'database'; ``` -- 使用 `LIKE` 时如果条件是以通配符 `%` 开头,也无法使用索引。例如下面查询无法使用任何索引: +- 如果 `LIKE` 条件在查询中以通配符 `%` 开头,查询无法使用索引。例如,以下查询无法使用任何索引: {{< copyable "sql" >}} @@ -139,9 +139,9 @@ CREATE TABLE `books` ( SELECT * FROM books WHERE title LIKE '%database'; ``` -- 当查询条件有多个索引可供使用,但你知道用哪一个索引是最优的时,推荐使用[优化器 Hint](/optimizer-hints.md) 来强制优化器使用这个索引,这样可以避免优化器因为统计信息不准或其他问题时,选错索引。 +- 当查询条件有多个可用索引,并且你在实践中知道哪个索引是最好的,建议使用[优化器提示](/optimizer-hints.md)强制 TiDB 优化器使用这个索引。这可以防止 TiDB 优化器由于统计信息不准确或其他问题而选择错误的索引。 - 例如下面查询中,假设在列 `id` 和列 `title` 上都各自有索引 `id_idx` 和 `title_idx`,你知道 `id_idx` 的过滤性更好,就可以在 SQL 中使用 `USE INDEX` Hint 来强制优化器使用 `id_idx` 索引。 + 在以下查询中,假设列 `id` 和 `title` 分别有可用的索引 `id_idx` 和 `title_idx`,如果你知道 `id_idx` 更好,你可以在 SQL 中使用 `USE INDEX` 提示强制 TiDB 优化器使用 `id_idx` 索引。 {{< copyable "sql" >}} @@ -149,4 +149,18 @@ CREATE TABLE `books` ( SELECT * FROM t USE INDEX(id_idx) WHERE id = 1 and title = 'database'; ``` -- 查询条件使用 `IN` 表达式时,后面匹配的条件数量建议不要超过 300 个,否则执行效率会较差。 +- 在查询条件中使用 `IN` 表达式时,建议其后匹配的值不要超过 300 个,否则执行效率会很差。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-insert-data.md b/develop/dev-guide-insert-data.md index 06038cf34ef0..c39fdc2bffce 100644 --- a/develop/dev-guide-insert-data.md +++ b/develop/dev-guide-insert-data.md @@ -1,26 +1,26 @@ --- title: 插入数据 -summary: 插入数据、批量导入数据的方法、最佳实践及例子。 +summary: 了解如何插入数据。 --- # 插入数据 -此页面将展示使用 SQL 语言,配合各种编程语言将数据插入到 TiDB 中。 +本文档介绍如何使用不同编程语言通过 SQL 语言向 TiDB 插入数据。 -## 在开始之前 +## 开始之前 -在阅读本页面之前,你需要准备以下事项: +在阅读本文档之前,你需要准备以下内容: -- [使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 -- 阅读[数据库模式概览](/develop/dev-guide-schema-design-overview.md),并[创建数据库](/develop/dev-guide-create-database.md)、[创建表](/develop/dev-guide-create-table.md)、[创建二级索引](/develop/dev-guide-create-secondary-indexes.md)。 +- [构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 +- 阅读[架构设计概述](/develop/dev-guide-schema-design-overview.md)、[创建数据库](/develop/dev-guide-create-database.md)、[创建表](/develop/dev-guide-create-table.md)和[创建二级索引](/develop/dev-guide-create-secondary-indexes.md)。 ## 插入行 -假设你需要插入多行数据,那么会有两种插入的办法,假设需要插入 3 个玩家数据: +有两种方式可以插入多行数据。例如,如果你需要插入 **3** 个玩家的数据。 -- 一个**多行插入语句**: +- **多行插入语句**: {{< copyable "sql" >}} @@ -38,26 +38,22 @@ summary: 插入数据、批量导入数据的方法、最佳实践及例子。 INSERT INTO `player` (`id`, `coins`, `goods`) VALUES (3, 300, 5); ``` -一般来说使用一个`多行插入语句`,会比多个`单行插入语句`快。 +通常,`多行插入语句`的运行速度比多个`单行插入语句`更快。
-在 SQL 中插入多行数据的示例: - ```sql CREATE TABLE `player` (`id` INT, `coins` INT, `goods` INT); INSERT INTO `player` (`id`, `coins`, `goods`) VALUES (1, 1000, 1), (2, 230, 2); ``` -有关如何使用此 SQL,可查阅[连接到 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-2-步连接到集群)文档部分,按文档步骤使用客户端连接到 TiDB 集群后,输入 SQL 语句即可。 +有关如何使用此 SQL 的更多信息,请参阅[连接到 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md#step-2-connect-to-a-cluster),并在使用客户端连接到 TiDB 集群后按照步骤输入 SQL 语句。
-在 Java 中插入多行数据的示例: - ```java // ds is an entity of com.mysql.cj.jdbc.MysqlDataSource try (Connection connection = ds.getConnection()) { @@ -84,18 +80,18 @@ try (Connection connection = ds.getConnection()) { } ``` -另外,由于 MySQL JDBC Driver 默认设置问题,你需更改部分参数,以获得更好的批量插入性能: +由于 MySQL JDBC Driver 的默认设置,你需要更改一些参数以获得更好的批量插入性能。 -| 参数 | 作用 | 推荐场景 | 推荐配置 | +| 参数 | 含义 | 推荐场景 | 推荐配置 | | :------------------------: | :-----------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------: | -| `useServerPrepStmts` | 是否使用服务端开启预处理语句支持 | 在需要多次使用预处理语句时 | `true` | -| `cachePrepStmts` | 客户端是否缓存预处理语句 | `useServerPrepStmts=true` 时 | `true` | -| `prepStmtCacheSqlLimit` | 预处理语句最大大小(默认 256 字符) | 预处理语句大于 256 字符时 | 按实际预处理语句大小配置 | -| `prepStmtCacheSize` | 预处理语句最大缓存数量 (默认 25 条) | 预处理语句数量大于 25 条时 | 按实际预处理语句数量配置 | -| `rewriteBatchedStatements` | 是否重写 Batch 语句 | 需要批量操作时 | `true` | -| `allowMultiQueries` | 开启批量操作 | 因为一个[客户端 Bug](https://bugs.mysql.com/bug.php?id=96623) 在 `rewriteBatchedStatements = true` 和 `useServerPrepStmts = true` 时,需设置此项 | `true` | +| `useServerPrepStmts` | 是否使用服务器端预处理语句 | 当你需要多次使用预处理语句时 | `true` | +| `cachePrepStmts` | 客户端是否缓存预处理语句 | `useServerPrepStmts=true` | `true` | +| `prepStmtCacheSqlLimit` | 预处理语句的最大大小(默认 256 字符) | 当预处理语句大于 256 字符时 | 根据预处理语句的实际大小配置 | +| `prepStmtCacheSize` | 预处理语句缓存的最大数量(默认 25) | 当预处理语句数量大于 25 时 | 根据预处理语句的实际数量配置 | +| `rewriteBatchedStatements` | 是否重写 **批处理** 语句 | 当需要批处理操作时 | `true` | +| `allowMultiQueries` | 启用批处理操作 | 由于[客户端 bug](https://bugs.mysql.com/bug.php?id=96623),当 `rewriteBatchedStatements = true` 且 `useServerPrepStmts = true` 时需要设置此项 | `true` | -MySQL JDBC Driver 还提供了一个集成配置项:`useConfigs`。当它配置为 `maxPerformance` 时,相当于配置了一组配置,以 `mysql:mysql-connector-java:8.0.28` 为例,`useConfigs=maxPerformance` 包含: +MySQL JDBC Driver 还提供了一个集成配置:`useConfigs`。当配置为 `maxPerformance` 时,相当于配置了一组配置。以 `mysql:mysql-connector-java:8.0.28` 为例,`useConfigs=maxPerformance` 包含: ```properties cachePrepStmts=true @@ -109,26 +105,24 @@ connectionAttributes=none useInformationSchema=true ``` -你可以自行查看 `mysql-connector-java-{version}.jar!/com/mysql/cj/configurations/maxPerformance.properties` 来获得对应版本 MySQL JDBC Driver 的 `useConfigs=maxPerformance` 包含配置。 +你可以查看 `mysql-connector-java-{version}.jar!/com/mysql/cj/configurations/maxPerformance.properties` 获取相应版本 MySQL JDBC Driver 中 `useConfigs=maxPerformance` 包含的配置。 -在此处给出一个较为的通用场景的 JDBC 连接字符串配置,以 Host: `127.0.0.1`,Port: `4000`,用户名: `root`,密码: 空,默认数据库: `test`为例: +以下是 JDBC 连接字符串配置的典型场景。在此示例中,主机:`127.0.0.1`,端口:`4000`,用户名:`root`,密码:null,默认数据库:`test`: ``` jdbc:mysql://127.0.0.1:4000/test?user=root&useConfigs=maxPerformance&useServerPrepStmts=true&prepStmtCacheSqlLimit=2048&prepStmtCacheSize=256&rewriteBatchedStatements=true&allowMultiQueries=true ``` -有关 Java 的完整示例,可参阅: +有关 Java 的完整示例,请参阅: -- [TiDB 和 JDBC 的简单 CRUD 应用程序](/develop/dev-guide-sample-application-java-jdbc.md) -- [TiDB 和 Hibernate 的简单 CRUD 应用程序](/develop/dev-guide-sample-application-java-hibernate.md) -- [使用 Spring Boot 构建 TiDB 应用程序](/develop/dev-guide-sample-application-java-spring-boot.md) +- [使用 JDBC 连接到 TiDB](/develop/dev-guide-sample-application-java-jdbc.md) +- [使用 Hibernate 连接到 TiDB](/develop/dev-guide-sample-application-java-hibernate.md) +- [使用 Spring Boot 连接到 TiDB](/develop/dev-guide-sample-application-java-spring-boot.md)
-在 Golang 中插入多行数据的示例: - ```go package main @@ -195,7 +189,7 @@ func buildBulkInsertSQL(amount int) string { } ``` -有关 Golang 的完整示例,可参阅: +有关 Golang 的完整示例,请参阅: - [使用 Go-MySQL-Driver 连接到 TiDB](/develop/dev-guide-sample-application-golang-sql-driver.md) - [使用 GORM 连接到 TiDB](/develop/dev-guide-sample-application-golang-gorm.md) @@ -204,11 +198,8 @@ func buildBulkInsertSQL(amount int) string {
-在 Python 中插入多行数据的示例: - ```python import MySQLdb - connection = MySQLdb.connect( host="127.0.0.1", port=4000, @@ -217,21 +208,20 @@ connection = MySQLdb.connect( database="bookshop", autocommit=True ) -with get_connection(autocommit=True) as connection: +with get_connection(autocommit=True) as connection: with connection.cursor() as cur: player_list = random_player(1919) for idx in range(0, len(player_list), 114): cur.executemany("INSERT INTO player (id, coins, goods) VALUES (%s, %s, %s)", player_list[idx:idx + 114]) ``` -有关 Python 的完整示例,可参阅: +有关 Python 的完整示例,请参阅: - [使用 PyMySQL 连接到 TiDB](/develop/dev-guide-sample-application-python-pymysql.md) -- [使用 mysqlclient 连接到 TiDB](/develop/dev-guide-sample-application-python-mysqlclient.md) +- [使用 mysqlclient 连接到 TiDB](https://github.com/tidb-samples/tidb-python-mysqlclient-quickstart) - [使用 MySQL Connector/Python 连接到 TiDB](/develop/dev-guide-sample-application-python-mysql-connector.md) - [使用 SQLAlchemy 连接到 TiDB](/develop/dev-guide-sample-application-python-sqlalchemy.md) -- [使用 Django 连接到 TiDB](/develop/dev-guide-sample-application-python-django.md) - [使用 peewee 连接到 TiDB](/develop/dev-guide-sample-application-python-peewee.md)
@@ -240,38 +230,59 @@ with get_connection(autocommit=True) as connection: ## 批量插入 -如果你需要快速地将大量数据导入 TiDB 集群,最好的方式并不是使用 `INSERT` 语句,这并不是最高效的方法,而且需要你自行处理异常等问题。推荐使用 PingCAP 提供的一系列工具进行数据迁移: +如果你需要快速将大量数据导入到 TiDB 集群中,建议使用 **PingCAP** 提供的一系列数据迁移工具。使用 `INSERT` 语句不是最佳方式,因为它效率不高,并且需要自行处理异常和其他问题。 + +以下是推荐的批量插入工具: + +- 数据导出:[Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview)。你可以将 MySQL 或 TiDB 数据导出到本地或 Amazon S3。 + + + +- 数据导入:[TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md)。你可以导入 **Dumpling** 导出的数据、**CSV** 文件或[从 Amazon Aurora 迁移数据到 TiDB](/migrate-aurora-to-tidb.md)。它还支持从本地磁盘或 Amazon S3 云盘读取数据。 +- 数据复制:[TiDB Data Migration](/dm/dm-overview.md)。你可以将 MySQL、MariaDB 和 Amazon Aurora 数据库复制到 TiDB。它还支持合并和迁移源数据库中的分片实例和表。 +- 数据备份和恢复:[Backup & Restore (BR)](/br/backup-and-restore-overview.md)。与 **Dumpling** 相比,**BR** 更适合**大数据**场景。 + + -- 数据导出工具:[Dumpling](/dumpling-overview.md)。可以导出 MySQL 或 TiDB 的数据到本地或 Amazon S3 中。 -- 数据导入工具:[TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md)。可以导入 `Dumpling` 导出的数据、CSV 文件,或者 [Amazon Aurora 生成的 Apache Parquet 文件](/migrate-aurora-to-tidb.md)。同时支持在本地盘或 Amazon S3 云盘读取数据。 -- 数据同步工具:[TiDB Data Migration](/dm/dm-overview.md)。可同步 MySQL、MariaDB、Amazon Aurora 数据库到 TiDB 中。且支持分库分表数据库的迁移。 -- 数据备份恢复工具:[Backup & Restore (BR)](/br/backup-and-restore-overview.md)。相对于 `Dumpling`,BR 更适合**_大数据量_**的场景。 + + +- 数据导入:[TiDB Cloud 控制台](https://tidbcloud.com/)中的[创建导入](/tidb-cloud/import-sample-data.md)页面。你可以上传本地 CSV 文件(仅限 TiDB Cloud Serverless),并导入存储在云存储中的 **Dumpling** 逻辑转储(架构和数据)、**CSV** 或 **Parquet** 文件。详情请参阅[将 CSV 文件导入到 TiDB Cloud Serverless](/tidb-cloud/import-csv-files-serverless.md)或[将 CSV 文件导入到 TiDB Cloud Dedicated](/tidb-cloud/import-csv-files.md)。 +- 数据复制:[TiDB Data Migration](https://docs.pingcap.com/tidb/stable/dm-overview)。你可以将 MySQL、MariaDB 和 Amazon Aurora 数据库复制到 TiDB。它还支持合并和迁移源数据库中的分片实例和表。 +- 数据备份和恢复:TiDB Cloud 控制台中的[备份](/tidb-cloud/backup-and-restore.md)页面。与 **Dumpling** 相比,备份和恢复更适合**大数据**场景。 + + ## 避免热点 -在设计表时需要考虑是否存在大量插入行为,若有,需在表设计期间对热点进行规避。请查看[创建表 - 选择主键](/develop/dev-guide-create-table.md#选择主键)部分,并遵从[选择主键时应遵守的规则](/develop/dev-guide-create-table.md#选择主键时应遵守的规则)。 +在设计表时,你需要考虑是否有大量的插入操作。如果有,则需要在表设计时避免热点。请参阅[选择主键](/develop/dev-guide-create-table.md#select-primary-key)部分,并遵循[选择主键时的规则](/develop/dev-guide-create-table.md#guidelines-to-follow-when-selecting-primary-key)。 + + -更多有关热点问题的处理办法,请参考 [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md)文档。 +有关如何处理热点问题的更多信息,请参阅[热点问题处理](/troubleshoot-hot-spot-issues.md)。 -## 主键为 `AUTO_RANDOM` 表插入数据 + -在插入的表主键为 `AUTO_RANDOM` 时,这时默认情况下,不能指定主键。例如 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库中,可以看到 [users 表](/develop/dev-guide-bookshop-schema-design.md#users-表) 的 `id` 字段含有 `AUTO_RANDOM` 属性。 +## 向带有 `AUTO_RANDOM` 主键的表插入数据 -此时,不可使用类似以下 SQL 进行插入: +如果要插入的表的主键具有 `AUTO_RANDOM` 属性,则默认情况下不能指定主键。例如,在 [`bookshop`](/develop/dev-guide-bookshop-schema-design.md) 数据库中,你可以看到 [`users` 表](/develop/dev-guide-bookshop-schema-design.md#users-table)的 `id` 字段包含 `AUTO_RANDOM` 属性。 + +在这种情况下,你**不能**使用如下 SQL 进行插入: ```sql INSERT INTO `bookshop`.`users` (`id`, `balance`, `nickname`) VALUES (1, 0.00, 'nicky'); ``` -将会产生错误: +会出现错误: ``` ERROR 8216 (HY000): Invalid auto random: Explicit insertion on auto_random column is disabled. Try to set @@allow_auto_random_explicit_insert = true. ``` -这是旨在提示你,不建议在插入时手动指定 `AUTO_RANDOM` 的列。这时,你有两种解决办法处理此错误: +不建议在插入时手动指定 `AUTO_RANDOM` 列。 + +有两种解决方案来处理这个错误: -- (推荐) 插入语句中去除此列,使用 TiDB 帮你初始化的 `AUTO_RANDOM` 值。这样符合 `AUTO_RANDOM` 的语义。 +- (推荐)从插入语句中删除此列,使用 TiDB 为你初始化的 `AUTO_RANDOM` 值。这符合 `AUTO_RANDOM` 的语义。 {{< copyable "sql" >}} @@ -279,7 +290,7 @@ ERROR 8216 (HY000): Invalid auto random: Explicit insertion on auto_random colum INSERT INTO `bookshop`.`users` (`balance`, `nickname`) VALUES (0.00, 'nicky'); ``` -- 如果你确认一定需要指定此列,那么可以使用 [SET 语句](/sql-statements/sql-statement-set-variable.md)通过更改用户变量的方式,允许在插入时,指定 `AUTO_RANDOM` 的列。 +- 如果你确定**必须**指定此列,则可以使用 [`SET` 语句](https://docs.pingcap.com/tidb/stable/sql-statement-set-variable)通过更改用户变量来允许在插入时指定 `AUTO_RANDOM` 列。 {{< copyable "sql" >}} @@ -290,4 +301,18 @@ ERROR 8216 (HY000): Invalid auto random: Explicit insertion on auto_random colum ## 使用 HTAP -在 TiDB 中,使用 HTAP 能力无需你在插入数据时进行额外操作。不会有任何额外的插入逻辑,由 TiDB 自动进行数据的一致性保证。你只需要在创建表后,[开启列存副本同步](/develop/dev-guide-create-table.md#使用-htap-能力),就可以直接使用列存副本来加速你的查询。 +在 TiDB 中,HTAP 功能可以让你在插入数据时无需执行额外操作。没有额外的插入逻辑。TiDB 自动保证数据一致性。你只需要在创建表后[开启列式副本同步](/develop/dev-guide-create-table.md#use-htap-capabilities),然后直接使用列式副本来加速查询即可。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-join-tables.md b/develop/dev-guide-join-tables.md index f7e3e9b5fe81..bf9ea61a085e 100644 --- a/develop/dev-guide-join-tables.md +++ b/develop/dev-guide-join-tables.md @@ -1,28 +1,28 @@ --- -title: 多表连接查询 -summary: 介绍 TiDB 中的多表连接查询功能。 +title: 多表联接查询 +summary: 本文介绍如何使用多表联接查询。 --- -# 多表连接查询 +# 多表联接查询 -很多时候,应用程序需要在一个查询当中使用到多张表的数据,这个时候可以通过 `JOIN` 语句将两张或多张表的数据组合在一起。 +在许多场景中,你需要使用一个查询从多个表中获取数据。你可以使用 `JOIN` 语句来组合来自两个或多个表的数据。 -## Join 类型 +## 联接类型 -此节将详细叙述 Join 的连接类型。 +本节详细介绍联接类型。 -### 内连接 INNER JOIN +### INNER JOIN -内连接的连接结果只返回匹配连接条件的行。 - -例如,想要知道编写过最多书的作家是谁,需要将作家基础信息表 `authors` 与书籍作者表 `book_authors` 进行连接。 +内联接的联接结果仅返回满足联接条件的行。 ![Inner Join](/media/develop/inner-join.png) +例如,如果你想知道最多产的作者,你需要将名为 `authors` 的作者表与名为 `book_authors` 的图书作者表联接起来。 +
-在下面的 SQL 语句当中,通过关键字 `JOIN` 声明要将左表 `authors` 和右表 `book_authors` 的数据行以内连接的方式进行连接,连接条件为 `a.id = ba.author_id`,那么连接的结果集当中将只会包含满足连接条件的行。假设有一个作家没有编写过任何书籍,那么他在 `authors` 表当中的记录将无法满足连接条件,因此也不会出现在结果集当中。 +在以下 SQL 语句中,使用关键字 `JOIN` 声明你要将左表 `authors` 和右表 `book_authors` 的行作为内联接进行联接,联接条件为 `a.id = ba.author_id`。结果集将只包含满足联接条件的行。如果一个作者没有写过任何书,那么他在 `authors` 表中的记录将不满足联接条件,因此不会出现在结果集中。 ```sql SELECT ANY_VALUE(a.id) AS author_id, ANY_VALUE(a.name) AS author_name, COUNT(ba.book_id) AS books @@ -56,8 +56,6 @@ LIMIT 10;
-在 Java 中内连接的示例如下: - ```java public List getTop10AuthorsOrderByBooks() throws SQLException { List authors = new ArrayList<>(); @@ -86,20 +84,20 @@ public List getTop10AuthorsOrderByBooks() throws SQLException {
-### 左外连接 LEFT OUTER JOIN +### LEFT OUTER JOIN -左外连接会返回左表中的所有数据行,以及右表当中能够匹配连接条件的值,如果在右表当中没有找到能够匹配的行,则使用 `NULL` 填充。 +左外联接返回左表中的所有行以及右表中满足联接条件的值。如果在右表中没有匹配的行,将用 `NULL` 填充。 ![Left Outer Join](/media/develop/left-outer-join.png) -在一些情况下,希望使用多张表来完成数据的查询,但是并不希望因为不满足连接条件而导致数据集变小。 +在某些情况下,你想使用多个表来完成数据查询,但不希望因为不满足联接条件而使数据集变得太小。 -例如,在 Bookshop 应用的首页,希望展示一个带有平均评分的最新书籍列表。在这种情况下,最新的书籍可能是还没有经过任何人评分的,如果使用内连接就会导致这些无人评分的书籍信息被过滤掉,而这并不是期望的结果。 +例如,在 Bookshop 应用的主页上,你想显示带有平均评分的新书列表。在这种情况下,新书可能还没有被任何人评分。使用内联接会导致这些未评分书籍的信息被过滤掉,这不是你期望的。
-在下面的 SQL 语句当中,通过 `LEFT JOIN` 关键字声明左表 `books` 将以左外连接的方式与右表 `ratings` 进行连接,从而确保 `books` 表当中的所有记录都能得到返回。 +在以下 SQL 语句中,使用 `LEFT JOIN` 关键字声明左表 `books` 将以左外联接的方式与右表 `ratings` 联接,从而确保返回 `books` 表中的所有行。 ```sql SELECT b.id AS book_id, ANY_VALUE(b.title) AS book_title, AVG(r.score) AS average_score @@ -130,13 +128,13 @@ LIMIT 10; 10 rows in set (0.30 sec) ``` -看起来最新出版的书籍已经有了很多评分,为了验证上面所说的,通过 SQL 语句把 **The Documentary of lion** 这本书的所有评分给删掉: +看起来最新发布的书已经有很多评分了。为了验证上述方法,让我们通过 SQL 语句删除《The Documentary of lion》这本书的所有评分: ```sql DELETE FROM ratings WHERE book_id = 3438991610; ``` -再次查询,你会发现 **The Documentary of lion** 这本书依然出现在结果集当中,但是通过右表 `ratings` 的 `score` 列计算得到的 `average_score` 列被填上了 `NULL`。 +再次查询。《The Documentary of lion》这本书仍然出现在结果集中,但从右表 `ratings` 的 `score` 计算得出的 `average_score` 列被填充为 `NULL`。 ``` +------------+---------------------------------+---------------+ @@ -156,13 +154,11 @@ DELETE FROM ratings WHERE book_id = 3438991610; 10 rows in set (0.30 sec) ``` -如果改成使用的是内连接 `JOIN` 结果会怎样?这就交给你来尝试了。 +如果使用 `INNER JOIN` 会发生什么?你可以自己尝试一下。
-在 Java 中左外连接的示例如下: - ```java public List getLatestBooksWithAverageScore() throws SQLException { List books = new ArrayList<>(); @@ -191,35 +187,37 @@ public List getLatestBooksWithAverageScore() throws SQLException {
-### 右外连接 RIGHT OUTER JOIN +### RIGHT OUTER JOIN -右外连接返回右表中的所有记录,以及左表当中能够匹配连接条件的值,没有匹配的值则使用 `NULL` 填充。 +右外联接返回右表中的所有记录以及左表中满足联接条件的值。如果没有匹配的值,则用 `NULL` 填充。 ![Right Outer Join](/media/develop/right-outer-join.png) -### 交叉连接 CROSS JOIN +### CROSS JOIN -当连接条件恒成立时,两表之间的内连接称为[交叉连接](https://zh.wikipedia.org/wiki/%E8%BF%9E%E6%8E%A5#%E4%BA%A4%E5%8F%89%E8%BF%9E%E6%8E%A5)(又被称为“笛卡尔连接”)。交叉连接会把左表的每一条记录和右表的所有记录相连接,如果左表的记录数为 m,右表的记录数为 n,则结果集中会产生 m \* n 条记录。 +当联接条件为常量时,两个表之间的内联接称为[交叉联接](https://en.wikipedia.org/wiki/Join_(SQL)#Cross_join)。交叉联接将左表的每条记录与右表的所有记录联接。如果左表中的记录数为 `m`,右表中的记录数为 `n`,则结果集中将生成 `m \* n` 条记录。 -### 左半连接 LEFT SEMI JOIN +### LEFT SEMI JOIN -TiDB 在 SQL 语法层面上不支持 `LEFT SEMI JOIN table_name`,但是在执行计划层面,[子查询相关的优化](/subquery-optimization.md)会将 `semi join` 作为改写后的等价 JOIN 查询默认的连接方式。 +TiDB 在 SQL 语法级别不支持 `LEFT SEMI JOIN table_name`。但在执行计划级别,[子查询相关优化](/subquery-optimization.md)会使用 `semi join` 作为重写等价 JOIN 查询的默认联接方法。 -## 隐式连接 +## 隐式联接 -在显式声明连接的 `JOIN` 语句作为 SQL 标准出现之前,在 SQL 语句当中可以通过 `FROM t1, t2` 子句来连接两张或多张表,通过 `WHERE t1.id = t2.id` 子句来指定连接的条件。你可以将其理解为隐式声明的连接,隐式连接会使用内连接的方式进行连接。 +在明确声明联接的 `JOIN` 语句被添加到 SQL 标准之前,可以使用 `FROM t1, t2` 子句在 SQL 语句中联接两个或多个表,并使用 `WHERE t1.id = t2.id` 子句指定联接条件。你可以将其理解为隐式联接,它使用内联接来联接表。 -## Join 相关算法 +## 联接相关算法 -TiDB 支持下列三种常规的表连接算法,优化器会根据所连接表的数据量等因素来选择合适的 Join 算法去执行。你可以通过 `EXPLAIN` 语句来查看查询使用了何种算法进行 Join。 +TiDB 支持以下通用表联接算法。 - [Index Join](/explain-joins.md#index-join) - [Hash Join](/explain-joins.md#hash-join) - [Merge Join](/explain-joins.md#merge-join) -如果发现 TiDB 的优化器没有按照最佳的 Join 算法去执行。你也可以通过 [Optimizer Hints](/optimizer-hints.md) 强制 TiDB 使用更好的 Join 算法去执行。 +优化器会根据联接表中的数据量等因素选择合适的联接算法来执行。你可以使用 `EXPLAIN` 语句查看查询使用了哪种联接算法。 + +如果 TiDB 的优化器没有按照最优的联接算法执行,你可以使用[优化器提示](/optimizer-hints.md)强制 TiDB 使用更好的联接算法。 -例如,假设上文当中的左连接查询的示例 SQL 使用 Hash Join 算法执行更快,而优化器并没有选择这种算法,你可以在 `SELECT` 关键字后面加上 Hint `/*+ HASH_JOIN(b, r) */`(注意:如果表名添加了别名,Hint 当中也应该使用表别名)。 +例如,假设上面的左联接查询示例使用 Hash Join 算法执行得更快,但优化器没有选择它,你可以在 `SELECT` 关键字后面添加提示 `/*+ HASH_JOIN(b, r) */`。注意,如果表有别名,在提示中使用别名。 ```sql EXPLAIN SELECT /*+ HASH_JOIN(b, r) */ b.id AS book_id, ANY_VALUE(b.title) AS book_title, AVG(r.score) AS average_score @@ -230,18 +228,18 @@ ORDER BY b.published_at DESC LIMIT 10; ``` -Join 算法相关的 Hints: +与联接算法相关的提示: - [MERGE_JOIN(t1_name [, tl_name ...])](/optimizer-hints.md#merge_joint1_name--tl_name-) - [INL_JOIN(t1_name [, tl_name ...])](/optimizer-hints.md#inl_joint1_name--tl_name-) - [INL_HASH_JOIN(t1_name [, tl_name ...])](/optimizer-hints.md#inl_hash_join) - [HASH_JOIN(t1_name [, tl_name ...])](/optimizer-hints.md#hash_joint1_name--tl_name-) -## Join 顺序 +## 联接顺序 -在实际的业务场景中,多个表的 Join 语句是很常见的,而 Join 的执行效率和各个表参与 Join 的顺序有关。TiDB 使用 Join Reorder 算法来确定多个表进行 Join 的顺序。 +在实际业务场景中,多表联接语句非常常见。联接的执行效率与每个表在联接中的顺序有关。TiDB 使用联接重排算法来确定多个表联接的顺序。 -当优化器选择的 Join 顺序并不够好时,你可以使用 `STRAIGHT_JOIN` 语法让 TiDB 强制按照 FROM 子句中所使用的表的顺序做联合查询。 +如果优化器选择的联接顺序不是最优的,你可以使用 `STRAIGHT_JOIN` 强制 TiDB 按照 `FROM` 子句中使用的表的顺序进行联接查询。 ```sql EXPLAIN SELECT * @@ -249,9 +247,23 @@ FROM authors a STRAIGHT_JOIN book_authors ba STRAIGHT_JOIN books b WHERE b.id = ba.book_id AND ba.author_id = a.id; ``` -关于该算法的实现细节和限制你可以通过查看[Join Reorder 算法简介](/join-reorder.md)章节进行了解。 +有关此联接重排算法的实现细节和限制的更多信息,请参阅[联接重排算法简介](/join-reorder.md)。 + +## 另请参阅 + +- [使用联接的语句的执行计划](/explain-joins.md) +- [联接重排简介](/join-reorder.md) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 扩展阅读 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -- [用 EXPLAIN 查看 JOIN 查询的执行计划](/explain-joins.md) -- [Join Reorder 算法简介](/join-reorder.md) + diff --git a/develop/dev-guide-object-naming-guidelines.md b/develop/dev-guide-object-naming-guidelines.md index 1f615150c996..0dc2647d4a93 100644 --- a/develop/dev-guide-object-naming-guidelines.md +++ b/develop/dev-guide-object-naming-guidelines.md @@ -1,46 +1,60 @@ --- title: 对象命名规范 -summary: 介绍 TiDB 中的对象命名规范。 +summary: 了解 TiDB 中的对象命名规范。 --- # 对象命名规范 -用于规范数据库对象的命名,如数据库(DATABASE)、表(TABLE)、索引(INDEX)、用户(USER)等的命名约定。 +本文介绍数据库对象(如数据库、表、索引和用户)的命名规则。 -## 原则 +## 通用规则 -- 命名建议使用具有意义的英文词汇,词汇中间以下划线分隔。 -- 命名只能使用英文字母、数字、下划线。 -- 避免用 TiDB 的保留字如:group,order 等作为单个字段名。 -- 建议所有数据库对象使用小写字母。 +- 建议使用有意义的英文单词,用下划线分隔。 +- 名称中只使用字母、数字和下划线。 +- 避免使用 TiDB 保留字(如 `group` 和 `order`)作为列名。 +- 建议对所有数据库对象使用小写字母。 ## 数据库命名规范 -建议按照业务、产品线或者其它指标进行区分,一般不要超过 20 个字符。如:临时库 (tmp_crm)、测试库 (test_crm)。 +建议按业务、产品或其他指标区分数据库名称,数据库名称不超过 20 个字符。例如,可以将临时库命名为 `tmp_crm`,将测试库命名为 `test_crm`。 ## 表命名规范 -- 同一业务或者模块的表尽可能使用相同的前缀,表名称尽可能表达含义。 -- 多个单词以下划线分隔,不推荐超过 32 个字符。 -- 建议对表的用途进行注释说明,以便于统一认识。如: - - 临时表(tmp_t_crm_relation_0425) - - 备份表(bak_t_crm_relation_20170425) - - 业务运营临时统计表(`tmp_st_{business code}_{creator abbreviation}_{date}`) - - 账期归档表(`t_crm_ec_record_YYYY{MM}{dd}`) -- 不同业务模块的表单独建立 DATABASE,并增加相应注释。 +- 同一业务或模块的表使用相同的前缀,并尽可能确保表名是自解释的。 +- 名称中的单词用下划线分隔。建议表名不超过 32 个字符。 +- 建议注释表的用途以便更好地理解。例如: + - 临时表:`tmp_t_crm_relation_0425` + - 备份表:`bak_t_crm_relation_20170425` + - 业务操作临时表:`tmp_st_{业务代码}_{创建者缩写}_{日期}` + - 账期记录表:`t_crm_ec_record_YYYY{MM}{dd}` +- 为不同业务模块的表创建单独的数据库,并添加相应的注释。 -## 字段命名规范 +## 列命名规范 -- 字段命名需要表示其实际含义的英文单词或简写。 -- 建议各表之间相同意义的字段应同名。 -- 字段也尽量添加注释,枚举型需指明主要值的含义,如”0 - 离线,1 - 在线”。 -- 布尔值列命名为 `is_{description}`。如 member 表上表示为 enabled 的会员的列命名为 is_enabled。 -- 字段名不建议超过 30 个字符,字段个数不建议大于 60。 -- 尽量避免使用保留字,如 order、from、desc 等,请参考附录部分的官方保留字。 +- 列命名为该列的实际含义或缩写。 +- 建议在具有相同含义的表之间使用相同的列名。 +- 建议为列添加注释,并为枚举类型指定命名值,例如"0:离线,1:在线"。 +- 建议将布尔列命名为 `is_{description}`。例如,`member` 表中表示成员是否启用的列可以命名为 `is_enabled`。 +- 不建议列名超过 30 个字符,列数应少于 60 个。 +- 避免使用 TiDB 保留字作为列名,如 `order`、`from` 和 `desc`。要检查关键字是否为保留字,请参阅 [TiDB 关键字](/keywords.md)。 ## 索引命名规范 -- 主键索引:`pk_{表名称简写}_{字段名简写}` -- 唯一索引:`uk_{表名称简写}_{字段名简写}` -- 普通索引:`idx_{表名称简写}_{字段名简写}` -- 多单词组成的 column_name,取尽可能代表意义的缩写。 +- 主键索引:`pk_{表名缩写}_{字段名缩写}` +- 唯一索引:`uk_{表名缩写}_{字段名缩写}` +- 普通索引:`idx_{表名缩写}_{字段名缩写}` +- 多个单词的列名:使用有意义的缩写 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-optimistic-and-pessimistic-transaction.md b/develop/dev-guide-optimistic-and-pessimistic-transaction.md index c82ae9e688b7..5600f09f2d00 100644 --- a/develop/dev-guide-optimistic-and-pessimistic-transaction.md +++ b/develop/dev-guide-optimistic-and-pessimistic-transaction.md @@ -1,43 +1,43 @@ --- title: 乐观事务和悲观事务 -summary: 介绍 TiDB 中的乐观事务和悲观事务,乐观事务的重试等。 +summary: 了解 TiDB 中的乐观事务和悲观事务。 --- # 乐观事务和悲观事务 -简单的讲,[乐观事务](/optimistic-transaction.md)模型就是直接提交,遇到冲突就回滚,[悲观事务](/pessimistic-transaction.md)模型就是在真正提交事务前,先尝试对需要修改的资源上锁,只有在确保事务一定能够执行成功后,才开始提交。 +[乐观事务](/optimistic-transaction.md)模型直接提交事务,并在发生冲突时回滚。相比之下,[悲观事务](/pessimistic-transaction.md)模型会在实际提交事务之前尝试锁定需要修改的资源,只有在确保事务可以成功执行后才开始提交。 -对于乐观事务模型来说,比较适合冲突率不高的场景,因为直接提交大概率会成功,冲突是小概率事件,但是一旦遇到事务冲突,回滚的代价会比较大。 +乐观事务模型适用于冲突率较低的场景,因为直接提交有较高的成功概率。但一旦发生事务冲突,回滚的成本相对较高。 -悲观事务的好处是对于冲突率高的场景,提前上锁的代价小于事后回滚的代价,而且还能以比较低的代价解决多个并发事务互相冲突导致谁也成功不了的场景。不过悲观事务在冲突率不高的场景并没有乐观事务处理高效。 +悲观事务模型的优点是对于冲突率较高的场景,提前锁定的成本低于事后回滚的成本。而且,它可以解决多个并发事务由于冲突而无法提交的问题。然而,在冲突率较低的场景中,悲观事务模型的效率不如乐观事务模型。 -从应用端实现的复杂度而言,悲观事务更直观,更容易实现。而乐观事务需要复杂的应用端重试机制来保证。 +悲观事务模型在应用程序端更直观且更容易实现。乐观事务模型需要复杂的应用程序端重试机制。 -下面用 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库中的表实现一个购书的例子来演示乐观事务和悲观事务的区别以及优缺点。购书流程主要包括: +以下是一个[书店](/develop/dev-guide-bookshop-schema-design.md)的示例。它使用购买书籍的例子来展示乐观和悲观事务的优缺点。购买书籍的过程主要包括以下几个步骤: 1. 更新库存数量 2. 创建订单 -3. 付款 +3. 支付 -这三个操作需要保证全部成功或者全部失败,并且在并发情况下要保证不超卖。 +这些操作必须要么全部成功,要么全部失败。你必须确保在并发事务的情况下不会发生超卖。 ## 悲观事务 -下面代码以悲观事务的方式,用两个线程模拟了两个用户并发买同一本书的过程,书店剩余 10 本,Bob 购买了 6 本,Alice 购买了 4 本。两个人几乎同一时间完成订单,最终,这本书的剩余库存为零。 +以下代码使用两个线程来模拟两个用户在悲观事务模式下购买同一本书的过程。书店里还剩 10 本书。Bob 买 6 本,Alice 买 4 本。他们几乎同时完成订单。最终,库存中的所有书籍都售罄。
-当使用多个线程模拟多用户同时插入的情况时,需要使用一个线程安全的连接对象,这里使用 Java 当前较流行的连接池 [HikariCP](https://github.com/brettwooldridge/HikariCP)。 +因为你使用多个线程来模拟多个用户同时插入数据的情况,所以需要使用线程安全的连接对象。这里使用 Java 流行的连接池 [HikariCP](https://github.com/brettwooldridge/HikariCP) 进行演示。
-Golang 的 `sql.DB` 是并发安全的,无需引入外部包。 +Golang 中的 `sql.DB` 是并发安全的,所以不需要导入第三方包。 -封装一个用于适配 TiDB 事务的工具包 [util](https://github.com/pingcap-inc/tidb-example-golang/tree/main/util),编写以下代码备用: +为了适配 TiDB 事务,根据以下代码编写工具包 [util](https://github.com/pingcap-inc/tidb-example-golang/tree/main/util): ```go package util @@ -93,1303 +93,10 @@ func (tx *TiDBSqlTx) Rollback() error {
-使用 Python 的 mysqlclient Driver 开启多个连接对象进行交互,线程之间不共享连接,以保证其线程安全。 - -
- - -### 1. 编写悲观事务示例 - - - -
- -**配置文件** - -在 Java 中,如果你使用 Maven 作为包管理,在 `pom.xml` 中的 `` 节点中,加入以下依赖来引入 `HikariCP`,同时设定打包目标,及 JAR 包启动的主类,完整的 `pom.xml` 如下所示: - -```xml - - - - 4.0.0 - - com.pingcap - plain-java-txn - 0.0.1 - - plain-java-jdbc - - - UTF-8 - 17 - 17 - - - - - junit - junit - 4.13.2 - test - - - - - mysql - mysql-connector-java - 8.0.28 - - - - com.zaxxer - HikariCP - 5.0.1 - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.3.0 - - - jar-with-dependencies - - - - com.pingcap.txn.TxnExample - - - - - - - make-assembly - package - - single - - - - - - - - -``` - -**代码** - -随后编写代码: - -```java -package com.pingcap.txn; - -import com.zaxxer.hikari.HikariDataSource; - -import java.math.BigDecimal; -import java.sql.*; -import java.util.Arrays; -import java.util.concurrent.*; - -public class TxnExample { - public static void main(String[] args) throws SQLException, InterruptedException { - System.out.println(Arrays.toString(args)); - int aliceQuantity = 0; - int bobQuantity = 0; - - for (String arg: args) { - if (arg.startsWith("ALICE_NUM")) { - aliceQuantity = Integer.parseInt(arg.replace("ALICE_NUM=", "")); - } - - if (arg.startsWith("BOB_NUM")) { - bobQuantity = Integer.parseInt(arg.replace("BOB_NUM=", "")); - } - } - - HikariDataSource ds = new HikariDataSource(); - ds.setJdbcUrl("jdbc:mysql://localhost:4000/bookshop?useServerPrepStmts=true&cachePrepStmts=true"); - ds.setUsername("root"); - ds.setPassword(""); - - // prepare data - Connection connection = ds.getConnection(); - createBook(connection, 1L, "Designing Data-Intensive Application", "Science & Technology", - Timestamp.valueOf("2018-09-01 00:00:00"), new BigDecimal(100), 10); - createUser(connection, 1L, "Bob", new BigDecimal(10000)); - createUser(connection, 2L, "Alice", new BigDecimal(10000)); - - CountDownLatch countDownLatch = new CountDownLatch(2); - ExecutorService threadPool = Executors.newFixedThreadPool(2); - - final int finalBobQuantity = bobQuantity; - threadPool.execute(() -> { - buy(ds, 1, 1000L, 1L, 1L, finalBobQuantity); - countDownLatch.countDown(); - }); - final int finalAliceQuantity = aliceQuantity; - threadPool.execute(() -> { - buy(ds, 2, 1001L, 1L, 2L, finalAliceQuantity); - countDownLatch.countDown(); - }); - - countDownLatch.await(5, TimeUnit.SECONDS); - } - - public static void createUser(Connection connection, Long id, String nickname, BigDecimal balance) throws SQLException { - PreparedStatement insert = connection.prepareStatement( - "INSERT INTO `users` (`id`, `nickname`, `balance`) VALUES (?, ?, ?)"); - insert.setLong(1, id); - insert.setString(2, nickname); - insert.setBigDecimal(3, balance); - insert.executeUpdate(); - } - - public static void createBook(Connection connection, Long id, String title, String type, Timestamp publishedAt, BigDecimal price, Integer stock) throws SQLException { - PreparedStatement insert = connection.prepareStatement( - "INSERT INTO `books` (`id`, `title`, `type`, `published_at`, `price`, `stock`) values (?, ?, ?, ?, ?, ?)"); - insert.setLong(1, id); - insert.setString(2, title); - insert.setString(3, type); - insert.setTimestamp(4, publishedAt); - insert.setBigDecimal(5, price); - insert.setInt(6, stock); - - insert.executeUpdate(); - } - - public static void buy (HikariDataSource ds, Integer threadID, - Long orderID, Long bookID, Long userID, Integer quantity) { - String txnComment = "/* txn " + threadID + " */ "; - - try (Connection connection = ds.getConnection()) { - try { - connection.setAutoCommit(false); - connection.createStatement().executeUpdate(txnComment + "begin pessimistic"); - - // waiting for other thread ran the 'begin pessimistic' statement - TimeUnit.SECONDS.sleep(1); - - BigDecimal price = null; - - // read price of book - PreparedStatement selectBook = connection.prepareStatement(txnComment + "select price from books where id = ? for update"); - selectBook.setLong(1, bookID); - ResultSet res = selectBook.executeQuery(); - if (!res.next()) { - throw new RuntimeException("book not exist"); - } else { - price = res.getBigDecimal("price"); - } - - // update book - String updateBookSQL = "update `books` set stock = stock - ? where id = ? and stock - ? >= 0"; - PreparedStatement updateBook = connection.prepareStatement(txnComment + updateBookSQL); - updateBook.setInt(1, quantity); - updateBook.setLong(2, bookID); - updateBook.setInt(3, quantity); - int affectedRows = updateBook.executeUpdate(); - - if (affectedRows == 0) { - // stock not enough, rollback - connection.createStatement().executeUpdate(txnComment + "rollback"); - return; - } - - // insert order - String insertOrderSQL = "insert into `orders` (`id`, `book_id`, `user_id`, `quality`) values (?, ?, ?, ?)"; - PreparedStatement insertOrder = connection.prepareStatement(txnComment + insertOrderSQL); - insertOrder.setLong(1, orderID); - insertOrder.setLong(2, bookID); - insertOrder.setLong(3, userID); - insertOrder.setInt(4, quantity); - insertOrder.executeUpdate(); - - // update user - String updateUserSQL = "update `users` set `balance` = `balance` - ? where id = ?"; - PreparedStatement updateUser = connection.prepareStatement(txnComment + updateUserSQL); - updateUser.setBigDecimal(1, price.multiply(new BigDecimal(quantity))); - updateUser.setLong(2, userID); - updateUser.executeUpdate(); - - connection.createStatement().executeUpdate(txnComment + "commit"); - } catch (Exception e) { - connection.createStatement().executeUpdate(txnComment + "rollback"); - e.printStackTrace(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} -``` - -
- -
- -首先编写一个封装了所需的数据库操作的 `helper.go` 文件: - -```go -package main - -import ( - "context" - "database/sql" - "fmt" - "time" - - "github.com/go-sql-driver/mysql" - "github.com/pingcap-inc/tidb-example-golang/util" - "github.com/shopspring/decimal" -) - -type TxnFunc func(txn *util.TiDBSqlTx) error - -const ( - ErrWriteConflict = 9007 // Transactions in TiKV encounter write conflicts. - ErrInfoSchemaChanged = 8028 // table schema changes - ErrForUpdateCantRetry = 8002 // "SELECT FOR UPDATE" commit conflict - ErrTxnRetryable = 8022 // The transaction commit fails and has been rolled back -) - -const retryTimes = 5 - -var retryErrorCodeSet = map[uint16]interface{}{ - ErrWriteConflict: nil, - ErrInfoSchemaChanged: nil, - ErrForUpdateCantRetry: nil, - ErrTxnRetryable: nil, -} - -func runTxn(db *sql.DB, optimistic bool, optimisticRetryTimes int, txnFunc TxnFunc) { - txn, err := util.TiDBSqlBegin(db, !optimistic) - if err != nil { - panic(err) - } - - err = txnFunc(txn) - if err != nil { - txn.Rollback() - if mysqlErr, ok := err.(*mysql.MySQLError); ok && optimistic && optimisticRetryTimes != 0 { - if _, retryableError := retryErrorCodeSet[mysqlErr.Number]; retryableError { - fmt.Printf("[runTxn] got a retryable error, rest time: %d\n", optimisticRetryTimes-1) - runTxn(db, optimistic, optimisticRetryTimes-1, txnFunc) - return - } - } - - fmt.Printf("[runTxn] got an error, rollback: %+v\n", err) - } else { - err = txn.Commit() - if mysqlErr, ok := err.(*mysql.MySQLError); ok && optimistic && optimisticRetryTimes != 0 { - if _, retryableError := retryErrorCodeSet[mysqlErr.Number]; retryableError { - fmt.Printf("[runTxn] got a retryable error, rest time: %d\n", optimisticRetryTimes-1) - runTxn(db, optimistic, optimisticRetryTimes-1, txnFunc) - return - } - } - - if err == nil { - fmt.Println("[runTxn] commit success") - } - } -} - -func prepareData(db *sql.DB, optimistic bool) { - runTxn(db, optimistic, retryTimes, func(txn *util.TiDBSqlTx) error { - publishedAt, err := time.Parse("2006-01-02 15:04:05", "2018-09-01 00:00:00") - if err != nil { - return err - } - - if err = createBook(txn, 1, "Designing Data-Intensive Application", - "Science & Technology", publishedAt, decimal.NewFromInt(100), 10); err != nil { - return err - } - - if err = createUser(txn, 1, "Bob", decimal.NewFromInt(10000)); err != nil { - return err - } - - if err = createUser(txn, 2, "Alice", decimal.NewFromInt(10000)); err != nil { - return err - } - - return nil - }) -} - -func buyPessimistic(db *sql.DB, goroutineID, orderID, bookID, userID, amount int) { - txnComment := fmt.Sprintf("/* txn %d */ ", goroutineID) - if goroutineID != 1 { - txnComment = "\t" + txnComment - } - - fmt.Printf("\nuser %d try to buy %d books(id: %d)\n", userID, amount, bookID) - - runTxn(db, false, retryTimes, func(txn *util.TiDBSqlTx) error { - time.Sleep(time.Second) - - // read the price of book - selectBookForUpdate := "select `price` from books where id = ? for update" - bookRows, err := txn.Query(selectBookForUpdate, bookID) - if err != nil { - return err - } - fmt.Println(txnComment + selectBookForUpdate + " successful") - defer bookRows.Close() - - price := decimal.NewFromInt(0) - if bookRows.Next() { - err = bookRows.Scan(&price) - if err != nil { - return err - } - } else { - return fmt.Errorf("book ID not exist") - } - bookRows.Close() - - // update book - updateStock := "update `books` set stock = stock - ? where id = ? and stock - ? >= 0" - result, err := txn.Exec(updateStock, amount, bookID, amount) - if err != nil { - return err - } - fmt.Println(txnComment + updateStock + " successful") - - affected, err := result.RowsAffected() - if err != nil { - return err - } - - if affected == 0 { - return fmt.Errorf("stock not enough, rollback") - } - - // insert order - insertOrder := "insert into `orders` (`id`, `book_id`, `user_id`, `quality`) values (?, ?, ?, ?)" - if _, err := txn.Exec(insertOrder, - orderID, bookID, userID, amount); err != nil { - return err - } - fmt.Println(txnComment + insertOrder + " successful") - - // update user - updateUser := "update `users` set `balance` = `balance` - ? where id = ?" - if _, err := txn.Exec(updateUser, - price.Mul(decimal.NewFromInt(int64(amount))), userID); err != nil { - return err - } - fmt.Println(txnComment + updateUser + " successful") - - return nil - }) -} - -func buyOptimistic(db *sql.DB, goroutineID, orderID, bookID, userID, amount int) { - txnComment := fmt.Sprintf("/* txn %d */ ", goroutineID) - if goroutineID != 1 { - txnComment = "\t" + txnComment - } - - fmt.Printf("\nuser %d try to buy %d books(id: %d)\n", userID, amount, bookID) - - runTxn(db, true, retryTimes, func(txn *util.TiDBSqlTx) error { - time.Sleep(time.Second) - - // read the price and stock of book - selectBookForUpdate := "select `price`, `stock` from books where id = ? for update" - bookRows, err := txn.Query(selectBookForUpdate, bookID) - if err != nil { - return err - } - fmt.Println(txnComment + selectBookForUpdate + " successful") - defer bookRows.Close() - - price, stock := decimal.NewFromInt(0), 0 - if bookRows.Next() { - err = bookRows.Scan(&price, &stock) - if err != nil { - return err - } - } else { - return fmt.Errorf("book ID not exist") - } - bookRows.Close() - - if stock < amount { - return fmt.Errorf("book not enough") - } - - // update book - updateStock := "update `books` set stock = stock - ? where id = ? and stock - ? >= 0" - result, err := txn.Exec(updateStock, amount, bookID, amount) - if err != nil { - return err - } - fmt.Println(txnComment + updateStock + " successful") - - affected, err := result.RowsAffected() - if err != nil { - return err - } - - if affected == 0 { - return fmt.Errorf("stock not enough, rollback") - } - - // insert order - insertOrder := "insert into `orders` (`id`, `book_id`, `user_id`, `quality`) values (?, ?, ?, ?)" - if _, err := txn.Exec(insertOrder, - orderID, bookID, userID, amount); err != nil { - return err - } - fmt.Println(txnComment + insertOrder + " successful") - - // update user - updateUser := "update `users` set `balance` = `balance` - ? where id = ?" - if _, err := txn.Exec(updateUser, - price.Mul(decimal.NewFromInt(int64(amount))), userID); err != nil { - return err - } - fmt.Println(txnComment + updateUser + " successful") - - return nil - }) -} - -func createBook(txn *util.TiDBSqlTx, id int, title, bookType string, - publishedAt time.Time, price decimal.Decimal, stock int) error { - _, err := txn.ExecContext(context.Background(), - "INSERT INTO `books` (`id`, `title`, `type`, `published_at`, `price`, `stock`) values (?, ?, ?, ?, ?, ?)", - id, title, bookType, publishedAt, price, stock) - return err -} - -func createUser(txn *util.TiDBSqlTx, id int, nickname string, balance decimal.Decimal) error { - _, err := txn.ExecContext(context.Background(), - "INSERT INTO `users` (`id`, `nickname`, `balance`) VALUES (?, ?, ?)", - id, nickname, balance) - return err -} -``` - -再编写一个包含 `main` 函数的 `txn.go` 来调用 `helper.go`,同时处理传入的命令行参数: - -```go -package main - -import ( - "database/sql" - "flag" - "fmt" - "sync" -) - -func main() { - optimistic, alice, bob := parseParams() - - openDB("mysql", "root:@tcp(127.0.0.1:4000)/bookshop?charset=utf8mb4", func(db *sql.DB) { - prepareData(db, optimistic) - buy(db, optimistic, alice, bob) - }) -} - -func buy(db *sql.DB, optimistic bool, alice, bob int) { - buyFunc := buyOptimistic - if !optimistic { - buyFunc = buyPessimistic - } - - wg := sync.WaitGroup{} - wg.Add(1) - go func() { - defer wg.Done() - buyFunc(db, 1, 1000, 1, 1, bob) - }() - - wg.Add(1) - go func() { - defer wg.Done() - buyFunc(db, 2, 1001, 1, 2, alice) - }() - - wg.Wait() -} - -func openDB(driverName, dataSourceName string, runnable func(db *sql.DB)) { - db, err := sql.Open(driverName, dataSourceName) - if err != nil { - panic(err) - } - defer db.Close() - - runnable(db) -} - -func parseParams() (optimistic bool, alice, bob int) { - flag.BoolVar(&optimistic, "o", false, "transaction is optimistic") - flag.IntVar(&alice, "a", 4, "Alice bought num") - flag.IntVar(&bob, "b", 6, "Bob bought num") - - flag.Parse() - - fmt.Println(optimistic, alice, bob) - - return optimistic, alice, bob -} -``` - -Golang 的例子中,已经包含乐观事务。 - -
- -
- -```python -import time - -import MySQLdb -import os -import datetime -from threading import Thread - -REPEATABLE_ERROR_CODE_SET = { - 9007, # Transactions in TiKV encounter write conflicts. - 8028, # table schema changes - 8002, # "SELECT FOR UPDATE" commit conflict - 8022 # The transaction commit fails and has been rolled back -} - - -def create_connection(): - return MySQLdb.connect( - host="127.0.0.1", - port=4000, - user="root", - password="", - database="bookshop", - autocommit=False - ) - - -def prepare_data() -> None: - connection = create_connection() - with connection: - with connection.cursor() as cursor: - cursor.execute("INSERT INTO `books` (`id`, `title`, `type`, `published_at`, `price`, `stock`) " - "values (%s, %s, %s, %s, %s, %s)", - (1, "Designing Data-Intensive Application", "Science & Technology", - datetime.datetime(2018, 9, 1), 100, 10)) - - cursor.executemany("INSERT INTO `users` (`id`, `nickname`, `balance`) VALUES (%s, %s, %s)", - [(1, "Bob", 10000), (2, "ALICE", 10000)]) - connection.commit() - - -def buy_optimistic(thread_id: int, order_id: int, book_id: int, user_id: int, amount: int, - optimistic_retry_times: int = 5) -> None: - connection = create_connection() - - txn_log_header = f"/* txn {thread_id} */" - if thread_id != 1: - txn_log_header = "\t" + txn_log_header - - with connection: - with connection.cursor() as cursor: - cursor.execute("BEGIN OPTIMISTIC") - print(f'{txn_log_header} BEGIN OPTIMISTIC') - time.sleep(1) - - try: - # read the price of book - select_book_for_update = "SELECT `price`, `stock` FROM books WHERE id = %s FOR UPDATE" - cursor.execute(select_book_for_update, (book_id,)) - book = cursor.fetchone() - if book is None: - raise Exception("book_id not exist") - price, stock = book - print(f'{txn_log_header} {select_book_for_update} successful') - - if stock < amount: - raise Exception("book not enough, rollback") - - # update book - update_stock = "update `books` set stock = stock - %s where id = %s and stock - %s >= 0" - rows_affected = cursor.execute(update_stock, (amount, book_id, amount)) - print(f'{txn_log_header} {update_stock} successful') - - if rows_affected == 0: - raise Exception("stock not enough, rollback") - - # insert order - insert_order = "insert into `orders` (`id`, `book_id`, `user_id`, `quality`) values (%s, %s, %s, %s)" - cursor.execute(insert_order, (order_id, book_id, user_id, amount)) - print(f'{txn_log_header} {insert_order} successful') - - # update user - update_user = "update `users` set `balance` = `balance` - %s where id = %s" - cursor.execute(update_user, (amount * price, user_id)) - print(f'{txn_log_header} {update_user} successful') - - except Exception as err: - connection.rollback() - - print(f'something went wrong: {err}') - else: - # important here! you need deal the Exception from the TiDB - try: - connection.commit() - except MySQLdb.MySQLError as db_err: - code, desc = db_err.args - if code in REPEATABLE_ERROR_CODE_SET and optimistic_retry_times > 0: - print(f'retry, rest {optimistic_retry_times - 1} times, for {code} {desc}') - buy_optimistic(thread_id, order_id, book_id, user_id, amount, optimistic_retry_times - 1) - - -def buy_pessimistic(thread_id: int, order_id: int, book_id: int, user_id: int, amount: int) -> None: - connection = create_connection() - - txn_log_header = f"/* txn {thread_id} */" - if thread_id != 1: - txn_log_header = "\t" + txn_log_header - - with connection: - with connection.cursor() as cursor: - cursor.execute("BEGIN PESSIMISTIC") - print(f'{txn_log_header} BEGIN PESSIMISTIC') - time.sleep(1) - - try: - # read the price of book - select_book_for_update = "SELECT `price` FROM books WHERE id = %s FOR UPDATE" - cursor.execute(select_book_for_update, (book_id,)) - book = cursor.fetchone() - if book is None: - raise Exception("book_id not exist") - price = book[0] - print(f'{txn_log_header} {select_book_for_update} successful') - - # update book - update_stock = "update `books` set stock = stock - %s where id = %s and stock - %s >= 0" - rows_affected = cursor.execute(update_stock, (amount, book_id, amount)) - print(f'{txn_log_header} {update_stock} successful') - - if rows_affected == 0: - raise Exception("stock not enough, rollback") - - # insert order - insert_order = "insert into `orders` (`id`, `book_id`, `user_id`, `quality`) values (%s, %s, %s, %s)" - cursor.execute(insert_order, (order_id, book_id, user_id, amount)) - print(f'{txn_log_header} {insert_order} successful') - - # update user - update_user = "update `users` set `balance` = `balance` - %s where id = %s" - cursor.execute(update_user, (amount * price, user_id)) - print(f'{txn_log_header} {update_user} successful') - - except Exception as err: - connection.rollback() - print(f'something went wrong: {err}') - else: - connection.commit() - - -optimistic = os.environ.get('OPTIMISTIC') -alice = os.environ.get('ALICE') -bob = os.environ.get('BOB') - -if not (optimistic and alice and bob): - raise Exception("please use \"OPTIMISTIC= ALICE= " - "BOB= python3 txn_example.py\" to start this script") - -prepare_data() - -if bool(optimistic) is True: - buy_func = buy_optimistic -else: - buy_func = buy_pessimistic - -bob_thread = Thread(target=buy_func, kwargs={ - "thread_id": 1, "order_id": 1000, "book_id": 1, "user_id": 1, "amount": int(bob)}) -alice_thread = Thread(target=buy_func, kwargs={ - "thread_id": 2, "order_id": 1001, "book_id": 1, "user_id": 2, "amount": int(alice)}) - -bob_thread.start() -alice_thread.start() -bob_thread.join(timeout=10) -alice_thread.join(timeout=10) -``` - -Python 的例子中,已经包含乐观事务。 - -
- -
- -### 2. 运行不涉及超卖的例子 - -运行示例程序: - - - -
- -在 Java 中运行示例程序: - -```shell -mvn clean package -java -jar target/plain-java-txn-0.0.1-jar-with-dependencies.jar ALICE_NUM=4 BOB_NUM=6 -``` - -
- -
- -在 Golang 中运行示例程序: - -```shell -go build -o bin/txn -./bin/txn -a 4 -b 6 -``` - -
- -
- -在 Python 中运行示例程序: - -```shell -OPTIMISTIC=False ALICE=4 BOB=6 python3 txn_example.py -``` - -
- -
- -SQL 日志: - -```sql -/* txn 1 */ BEGIN PESSIMISTIC - /* txn 2 */ BEGIN PESSIMISTIC - /* txn 2 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE - /* txn 2 */ UPDATE `books` SET `stock` = `stock` - 4 WHERE `id` = 1 AND `stock` - 4 >= 0 - /* txn 2 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) VALUES (1001, 1, 1, 4) - /* txn 2 */ UPDATE `users` SET `balance` = `balance` - 400.0 WHERE `id` = 2 - /* txn 2 */ COMMIT -/* txn 1 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE -/* txn 1 */ UPDATE `books` SET `stock` = `stock` - 6 WHERE `id` = 1 AND `stock` - 6 >= 0 -/* txn 1 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) VALUES (1000, 1, 1, 6) -/* txn 1 */ UPDATE `users` SET `balance` = `balance` - 600.0 WHERE `id` = 1 -/* txn 1 */ COMMIT -``` - -最后,检验一下订单创建、用户余额扣减、图书库存扣减情况,都符合预期。 - -```sql -mysql> SELECT * FROM `books`; -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| id | title | type | published_at | stock | price | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| 1 | Designing Data-Intensive Application | Science & Technology | 2018-09-01 00:00:00 | 0 | 100.00 | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -1 row in set (0.00 sec) - -mysql> SELECT * FROM orders; -+------+---------+---------+---------+---------------------+ -| id | book_id | user_id | quality | ordered_at | -+------+---------+---------+---------+---------------------+ -| 1000 | 1 | 1 | 6 | 2022-04-19 10:58:12 | -| 1001 | 1 | 1 | 4 | 2022-04-19 10:58:11 | -+------+---------+---------+---------+---------------------+ -2 rows in set (0.01 sec) - -mysql> SELECT * FROM users; -+----+---------+----------+ -| id | balance | nickname | -+----+---------+----------+ -| 1 | 9400.00 | Bob | -| 2 | 9600.00 | Alice | -+----+---------+----------+ -2 rows in set (0.00 sec) -``` - -### 3. 运行防止超卖的例子 - -可以再把难度加大,如果图书的库存剩余 10 本,Bob 购买 7 本,Alice 购买 4 本,两人几乎同时下单,结果会是怎样?继续复用上个例子里的代码来解决这个需求,只不过把 Bob 购买数量从 6 改成 7: - -运行示例程序: - - - -
- -在 Java 中运行示例程序: - -```shell -mvn clean package -java -jar target/plain-java-txn-0.0.1-jar-with-dependencies.jar ALICE_NUM=4 BOB_NUM=7 -``` - -
- -
- -在 Golang 中运行示例程序: - -```shell -go build -o bin/txn -./bin/txn -a 4 -b 7 -``` - -
- -
- -在 Python 中运行示例程序: - -```shell -OPTIMISTIC=False ALICE=4 BOB=7 python3 txn_example.py -``` - -
- -
- -```sql -/* txn 1 */ BEGIN PESSIMISTIC - /* txn 2 */ BEGIN PESSIMISTIC - /* txn 2 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE - /* txn 2 */ UPDATE `books` SET `stock` = `stock` - 4 WHERE `id` = 1 AND `stock` - 4 >= 0 - /* txn 2 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) values (1001, 1, 1, 4) - /* txn 2 */ UPDATE `users` SET `balance` = `balance` - 400.0 WHERE `id` = 2 - /* txn 2 */ COMMIT -/* txn 1 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE -/* txn 1 */ UPDATE `books` SET `stock` = `stock` - 7 WHERE `id` = 1 AND `stock` - 7 >= 0 -/* txn 1 */ ROLLBACK -``` - -由于 `txn 2` 抢先获得锁资源,更新了 stock,`txn 1` 里面 `affected_rows` 返回值为 0,进入了 `rollback` 流程。 - -再检验一下订单创建、用户余额扣减、图书库存扣减情况。Alice 下单 4 本书成功,Bob 下单 7 本书失败,库存剩余 6 本符合预期。 - -```sql -mysql> SELECT * FROM books; -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| id | title | type | published_at | stock | price | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| 1 | Designing Data-Intensive Application | Science & Technology | 2018-09-01 00:00:00 | 6 | 100.00 | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -1 row in set (0.00 sec) - -mysql> SELECT * FROM orders; -+------+---------+---------+---------+---------------------+ -| id | book_id | user_id | quality | ordered_at | -+------+---------+---------+---------+---------------------+ -| 1001 | 1 | 1 | 4 | 2022-04-19 11:03:03 | -+------+---------+---------+---------+---------------------+ -1 row in set (0.00 sec) - -mysql> SELECT * FROM users; -+----+----------+----------+ -| id | balance | nickname | -+----+----------+----------+ -| 1 | 10000.00 | Bob | -| 2 | 9600.00 | Alice | -+----+----------+----------+ -2 rows in set (0.01 sec) -``` - -## 乐观事务 - -下面代码以乐观事务的方式,用两个线程模拟了两个用户并发买同一本书的过程,和悲观事务的示例一样。书店剩余 10 本,Bob 购买了 6 本,Alice 购买了 4 本。两个人几乎同一时间完成订单,最终,这本书的剩余库存为零。 - -### 1. 编写乐观事务示例 - - - -
- -使用 Java 编写乐观事务示例: - -**代码编写** - -```java -package com.pingcap.txn.optimistic; - -import com.zaxxer.hikari.HikariDataSource; - -import java.math.BigDecimal; -import java.sql.*; -import java.util.Arrays; -import java.util.concurrent.*; - -public class TxnExample { - public static void main(String[] args) throws SQLException, InterruptedException { - System.out.println(Arrays.toString(args)); - int aliceQuantity = 0; - int bobQuantity = 0; - - for (String arg: args) { - if (arg.startsWith("ALICE_NUM")) { - aliceQuantity = Integer.parseInt(arg.replace("ALICE_NUM=", "")); - } - - if (arg.startsWith("BOB_NUM")) { - bobQuantity = Integer.parseInt(arg.replace("BOB_NUM=", "")); - } - } - - HikariDataSource ds = new HikariDataSource(); - ds.setJdbcUrl("jdbc:mysql://localhost:4000/bookshop?useServerPrepStmts=true&cachePrepStmts=true"); - ds.setUsername("root"); - ds.setPassword(""); - - // prepare data - Connection connection = ds.getConnection(); - createBook(connection, 1L, "Designing Data-Intensive Application", "Science & Technology", - Timestamp.valueOf("2018-09-01 00:00:00"), new BigDecimal(100), 10); - createUser(connection, 1L, "Bob", new BigDecimal(10000)); - createUser(connection, 2L, "Alice", new BigDecimal(10000)); - - CountDownLatch countDownLatch = new CountDownLatch(2); - ExecutorService threadPool = Executors.newFixedThreadPool(2); - - final int finalBobQuantity = bobQuantity; - threadPool.execute(() -> { - buy(ds, 1, 1000L, 1L, 1L, finalBobQuantity, 5); - countDownLatch.countDown(); - }); - final int finalAliceQuantity = aliceQuantity; - threadPool.execute(() -> { - buy(ds, 2, 1001L, 1L, 2L, finalAliceQuantity, 5); - countDownLatch.countDown(); - }); - - countDownLatch.await(5, TimeUnit.SECONDS); - } - - public static void createUser(Connection connection, Long id, String nickname, BigDecimal balance) throws SQLException { - PreparedStatement insert = connection.prepareStatement( - "INSERT INTO `users` (`id`, `nickname`, `balance`) VALUES (?, ?, ?)"); - insert.setLong(1, id); - insert.setString(2, nickname); - insert.setBigDecimal(3, balance); - insert.executeUpdate(); - } - - public static void createBook(Connection connection, Long id, String title, String type, Timestamp publishedAt, BigDecimal price, Integer stock) throws SQLException { - PreparedStatement insert = connection.prepareStatement( - "INSERT INTO `books` (`id`, `title`, `type`, `published_at`, `price`, `stock`) values (?, ?, ?, ?, ?, ?)"); - insert.setLong(1, id); - insert.setString(2, title); - insert.setString(3, type); - insert.setTimestamp(4, publishedAt); - insert.setBigDecimal(5, price); - insert.setInt(6, stock); - - insert.executeUpdate(); - } - - public static void buy (HikariDataSource ds, Integer threadID, Long orderID, Long bookID, - Long userID, Integer quantity, Integer retryTimes) { - String txnComment = "/* txn " + threadID + " */ "; - - try (Connection connection = ds.getConnection()) { - try { - - connection.setAutoCommit(false); - connection.createStatement().executeUpdate(txnComment + "begin optimistic"); - - // waiting for other thread ran the 'begin optimistic' statement - TimeUnit.SECONDS.sleep(1); - - BigDecimal price = null; - - // read price of book - PreparedStatement selectBook = connection.prepareStatement(txnComment + "SELECT * FROM books where id = ? for update"); - selectBook.setLong(1, bookID); - ResultSet res = selectBook.executeQuery(); - if (!res.next()) { - throw new RuntimeException("book not exist"); - } else { - price = res.getBigDecimal("price"); - int stock = res.getInt("stock"); - if (stock < quantity) { - throw new RuntimeException("book not enough"); - } - } - - // update book - String updateBookSQL = "update `books` set stock = stock - ? where id = ? and stock - ? >= 0"; - PreparedStatement updateBook = connection.prepareStatement(txnComment + updateBookSQL); - updateBook.setInt(1, quantity); - updateBook.setLong(2, bookID); - updateBook.setInt(3, quantity); - updateBook.executeUpdate(); - - // insert order - String insertOrderSQL = "insert into `orders` (`id`, `book_id`, `user_id`, `quality`) values (?, ?, ?, ?)"; - PreparedStatement insertOrder = connection.prepareStatement(txnComment + insertOrderSQL); - insertOrder.setLong(1, orderID); - insertOrder.setLong(2, bookID); - insertOrder.setLong(3, userID); - insertOrder.setInt(4, quantity); - insertOrder.executeUpdate(); - - // update user - String updateUserSQL = "update `users` set `balance` = `balance` - ? where id = ?"; - PreparedStatement updateUser = connection.prepareStatement(txnComment + updateUserSQL); - updateUser.setBigDecimal(1, price.multiply(new BigDecimal(quantity))); - updateUser.setLong(2, userID); - updateUser.executeUpdate(); - - connection.createStatement().executeUpdate(txnComment + "commit"); - } catch (Exception e) { - connection.createStatement().executeUpdate(txnComment + "rollback"); - System.out.println("error occurred: " + e.getMessage()); - - if (e instanceof SQLException sqlException) { - switch (sqlException.getErrorCode()) { - // You can get all error codes at https://docs.pingcap.com/tidb/stable/error-codes - case 9007: // Transactions in TiKV encounter write conflicts. - case 8028: // table schema changes - case 8002: // "SELECT FOR UPDATE" commit conflict - case 8022: // The transaction commit fails and has been rolled back - if (retryTimes != 0) { - System.out.println("rest " + retryTimes + " times. retry for " + e.getMessage()); - buy(ds, threadID, orderID, bookID, userID, quantity, retryTimes - 1); - } - } - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} -``` - -**配置更改** - -此处,需将 `pom.xml` 中启动类: - -```xml -com.pingcap.txn.TxnExample -``` - -更改为: - -```xml -com.pingcap.txn.optimistic.TxnExample -``` - -来指向乐观事务的例子。 - -
- -
- -Golang 在[编写悲观事务示例](#1-编写悲观事务示例)章节中的例子已经支持了乐观事务,无需更改,可直接使用。 - -
- -
- -Python 在[编写悲观事务示例](#1-编写悲观事务示例)章节中的例子已经支持了乐观事务,无需更改,可直接使用。 +为了确保线程安全,你可以使用 mysqlclient 驱动程序打开多个不在线程之间共享的连接。
-### 2. 运行不涉及超卖的例子 - -运行示例程序: - - - -
- -在 Java 中运行示例程序: - -```shell -mvn clean package -java -jar target/plain-java-txn-0.0.1-jar-with-dependencies.jar ALICE_NUM=4 BOB_NUM=6 -``` - -
- -
- -在 Golang 中运行示例程序: - -```shell -go build -o bin/txn -./bin/txn -a 4 -b 6 -o true -``` - -
- -
- -在 Python 中运行示例程序: - -```shell -OPTIMISTIC=True ALICE=4 BOB=6 python3 txn_example.py -``` - -
- -
- -SQL 语句执行过程: - -```sql - /* txn 2 */ BEGIN OPTIMISTIC -/* txn 1 */ BEGIN OPTIMISTIC - /* txn 2 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE - /* txn 2 */ UPDATE `books` SET `stock` = `stock` - 4 WHERE `id` = 1 AND `stock` - 4 >= 0 - /* txn 2 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) VALUES (1001, 1, 1, 4) - /* txn 2 */ UPDATE `users` SET `balance` = `balance` - 400.0 WHERE `id` = 2 - /* txn 2 */ COMMIT -/* txn 1 */ SELECT * FROM `books` WHERE `id` = 1 for UPDATE -/* txn 1 */ UPDATE `books` SET `stock` = `stock` - 6 WHERE `id` = 1 AND `stock` - 6 >= 0 -/* txn 1 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) VALUES (1000, 1, 1, 6) -/* txn 1 */ UPDATE `users` SET `balance` = `balance` - 600.0 WHERE `id` = 1 -retry 1 times for 9007 Write conflict, txnStartTS=432618733006225412, conflictStartTS=432618733006225411, conflictCommitTS=432618733006225414, key={tableID=126, handle=1} primary={tableID=114, indexID=1, indexValues={1, 1000, }} [try again later] -/* txn 1 */ BEGIN OPTIMISTIC -/* txn 1 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE -/* txn 1 */ UPDATE `books` SET `stock` = `stock` - 6 WHERE `id` = 1 AND `stock` - 6 >= 0 -/* txn 1 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) VALUES (1000, 1, 1, 6) -/* txn 1 */ UPDATE `users` SET `balance` = `balance` - 600.0 WHERE `id` = 1 -/* txn 1 */ COMMIT -``` - -在乐观事务模式下,由于中间状态不一定正确,不能像悲观事务模式一样,通过 `affected_rows` 来判断某个语句是否执行成功。需要把事务看做一个整体,通过最终的 COMMIT 语句是否返回异常来判断当前事务是否发生写冲突。 - -从上面 SQL 日志可以看出,由于两个事务并发执行,并且对同一条记录做了修改,`txn 1` COMMIT 之后抛出了 `9007 Write conflict` 异常。对于乐观事务写冲突,在应用端可以进行安全的重试,重试一次之后提交成功,最终执行结果符合预期: - -```sql -mysql> SELECT * FROM books; -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| id | title | type | published_at | stock | price | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| 1 | Designing Data-Intensive Application | Science & Technology | 2018-09-01 00:00:00 | 0 | 100.00 | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -1 row in set (0.01 sec) - -mysql> SELECT * FROM orders; -+------+---------+---------+---------+---------------------+ -| id | book_id | user_id | quality | ordered_at | -+------+---------+---------+---------+---------------------+ -| 1000 | 1 | 1 | 6 | 2022-04-19 03:18:19 | -| 1001 | 1 | 1 | 4 | 2022-04-19 03:18:17 | -+------+---------+---------+---------+---------------------+ -2 rows in set (0.01 sec) - -mysql> SELECT * FROM users; -+----+---------+----------+ -| id | balance | nickname | -+----+---------+----------+ -| 1 | 9400.00 | Bob | -| 2 | 9600.00 | Alice | -+----+---------+----------+ -2 rows in set (0.00 sec) -``` - -### 3. 运行防止超卖的例子 - -再来看一下用乐观事务防止超卖的例子,如果图书的库存剩余 10 本,Bob 购买 7 本,Alice 购买 4 本,两人几乎同时下单,结果会是怎样?继续复用乐观事务例子里的代码来解决这个需求,只不过把 Bob 购买数量从 6 改成 7: - -运行示例程序: - - - -
- -在 Java 中运行示例程序: - -```shell -mvn clean package -java -jar target/plain-java-txn-0.0.1-jar-with-dependencies.jar ALICE_NUM=4 BOB_NUM=7 -``` - -
- -
- -在 Golang 中运行示例程序: - -```shell -go build -o bin/txn -./bin/txn -a 4 -b 7 -o true -``` - -
- -
- -在 Python 中运行示例程序: - -```shell -OPTIMISTIC=True ALICE=4 BOB=7 python3 txn_example.py -``` - -
- -
- -```sql -/* txn 1 */ BEGIN OPTIMISTIC - /* txn 2 */ BEGIN OPTIMISTIC - /* txn 2 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE - /* txn 2 */ UPDATE `books` SET `stock` = `stock` - 4 WHERE `id` = 1 AND `stock` - 4 >= 0 - /* txn 2 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) VALUES (1001, 1, 1, 4) - /* txn 2 */ UPDATE `users` SET `balance` = `balance` - 400.0 WHERE `id` = 2 - /* txn 2 */ COMMIT -/* txn 1 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE -/* txn 1 */ UPDATE `books` SET `stock` = `stock` - 7 WHERE `id` = 1 AND `stock` - 7 >= 0 -/* txn 1 */ INSERT INTO `orders` (`id`, `book_id`, `user_id`, `quality`) VALUES (1000, 1, 1, 7) -/* txn 1 */ UPDATE `users` SET `balance` = `balance` - 700.0 WHERE `id` = 1 -retry 1 times for 9007 Write conflict, txnStartTS=432619094333980675, conflictStartTS=432619094333980676, conflictCommitTS=432619094333980678, key={tableID=126, handle=1} primary={tableID=114, indexID=1, indexValues={1, 1000, }} [try again later] -/* txn 1 */ BEGIN OPTIMISTIC -/* txn 1 */ SELECT * FROM `books` WHERE `id` = 1 FOR UPDATE -Fail -> out of stock -/* txn 1 */ ROLLBACK -``` - -从上面的 SQL 日志可以看出,第一次执行由于写冲突,`txn 1` 在应用端进行了重试,从获取到的最新快照对比发现,剩余库存不够,应用端抛出 `out of stock` 异常结束。 - -```sql -mysql> SELECT * FROM books; -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| id | title | type | published_at | stock | price | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -| 1 | Designing Data-Intensive Application | Science & Technology | 2018-09-01 00:00:00 | 6 | 100.00 | -+----+--------------------------------------+----------------------+---------------------+-------+--------+ -1 row in set (0.00 sec) - -mysql> SELECT * FROM orders; -+------+---------+---------+---------+---------------------+ -| id | book_id | user_id | quality | ordered_at | -+------+---------+---------+---------+---------------------+ -| 1001 | 1 | 1 | 4 | 2022-04-19 03:41:16 | -+------+---------+---------+---------+---------------------+ -1 row in set (0.00 sec) - -mysql> SELECT * FROM users; -+----+----------+----------+ -| id | balance | nickname | -+----+----------+----------+ -| 1 | 10000.00 | Bob | -| 2 | 9600.00 | Alice | -+----+----------+----------+ -2 rows in set (0.00 sec) -``` +### 编写悲观事务示例 diff --git a/develop/dev-guide-optimize-sql-best-practices.md b/develop/dev-guide-optimize-sql-best-practices.md index 0b2c2f7d8075..ef5cf1d15b0f 100644 --- a/develop/dev-guide-optimize-sql-best-practices.md +++ b/develop/dev-guide-optimize-sql-best-practices.md @@ -1,19 +1,19 @@ --- title: 性能调优最佳实践 -summary: 介绍使用 TiDB 的性能调优最佳实践。 +summary: 介绍 TiDB 性能调优的最佳实践。 --- # 性能调优最佳实践 -本章将介绍在使用 TiDB 数据库的一些最佳实践。 +本文介绍使用 TiDB 数据库的一些最佳实践。 ## DML 最佳实践 -以下将介绍使用 TiDB 的 DML 时所涉及到的最佳实践。 +本节介绍在使用 TiDB 的 DML 时涉及的最佳实践。 -### 使用单个语句多行数据操作 +### 使用多行语句 -当需要修改多行数据时,推荐使用单个 SQL 多行数据的语句: +当你需要修改表的多行数据时,建议使用多行语句: ```sql INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c'); @@ -21,7 +21,7 @@ INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c'); DELETE FROM t WHERE id IN (1, 2, 3); ``` -不推荐使用多个 SQL 单行数据的语句: +不建议使用多个单行语句: ```sql INSERT INTO t VALUES (1, 'a'); @@ -33,29 +33,27 @@ DELETE FROM t WHERE id = 2; DELETE FROM t WHERE id = 3; ``` -### 使用 PREPARE +### 使用 `PREPARE` -当需要多次执行某个 SQL 语句时,推荐使用 `PREPARE` 语句,可以避免重复解析 SQL 语法的开销。 +当你需要多次执行同一个 SQL 语句时,建议使用 `PREPARE` 语句以避免重复解析 SQL 语法的开销。
-在 Golang 中使用 `PREPARE` 语句: - ```go func BatchInsert(db *sql.DB) error { - stmt, err := db.Prepare("INSERT INTO t (id) VALUES (?), (?), (?), (?), (?)") - if err != nil { - return err - } - for i := 0; i < 1000; i += 5 { - values := []interface{}{i, i + 1, i + 2, i + 3, i + 4} - _, err = stmt.Exec(values...) + stmt, err := db.Prepare("INSERT INTO t (id) VALUES (?), (?), (?), (?), (?)") if err != nil { - return err + return err + } + for i := 0; i < 1000; i += 5 { + values := []interface{}{i, i + 1, i + 2, i + 3, i + 4} + _, err = stmt.Exec(values...) + if err != nil { + return err + } } - } - return nil + return nil } ``` @@ -63,42 +61,34 @@ func BatchInsert(db *sql.DB) error {
-在 Java 中使用 `PREPARE` 语句: - ```java public void batchInsert(Connection connection) throws SQLException { - PreparedStatement statement = connection.prepareStatement( - "INSERT INTO `t` (`id`) VALUES (?), (?), (?), (?), (?)"); - for (int i = 0; i < 1000; i ++) { - statement.setInt(i % 5 + 1, i); - - if (i % 5 == 4) { - statement.executeUpdate(); + PreparedStatement statement = connection.prepareStatement( + "INSERT INTO `t` (`id`) VALUES (?), (?), (?), (?), (?)"); + for (int i = 0; i < 1000; i ++) { + statement.setInt(i % 5 + 1, i); + + if (i % 5 == 4) { + statement.executeUpdate(); + } } - } } ``` -
- -
- -在 Python 中使用 `PREPARE` 语句时,并不需要显式指定。在你使用参数化查询时,mysqlclient 等 Driver 将自动转用执行计划。 -
-注意不要重复执行 `PREPARE` 语句,否则并不能提高执行效率。 +不要重复执行 `PREPARE` 语句。否则,执行效率无法得到提升。 -### 避免查询不必要的信息 +### 只查询需要的列 -如非必要,不要总是用 `SELECT *` 返回所以列的数据,下面查询是低效的: +如果你不需要所有列的数据,不要使用 `SELECT *` 返回所有列数据。以下查询效率不高: ```sql SELECT * FROM books WHERE title = 'Marian Yost'; ``` -应该仅查询需要的列信息,例如: +你应该只查询需要的列。例如: ```sql SELECT title, price FROM books WHERE title = 'Marian Yost'; @@ -106,21 +96,21 @@ SELECT title, price FROM books WHERE title = 'Marian Yost'; ### 使用批量删除 -当需要删除大量的数据,推荐使用批量删除,见[批量删除](/develop/dev-guide-delete-data.md#批量删除) +当你删除大量数据时,建议使用[批量删除](/develop/dev-guide-delete-data.md#bulk-delete)。 ### 使用批量更新 -当需要更新大量的数据时,推荐使用批量更新,见[批量更新](/develop/dev-guide-update-data.md#批量更新) +当你更新大量数据时,建议使用[批量更新](/develop/dev-guide-update-data.md#bulk-update)。 -### 使用 TRUNCATE 语句代替 DELETE 全表数据 +### 使用 `TRUNCATE` 而不是 `DELETE` 删除全表数据 -当需要删除一个表的所有数据时,推荐使用 `TRUNCATE` 语句: +当你需要删除表中的所有数据时,建议使用 `TRUNCATE` 语句: ```sql TRUNCATE TABLE t; ``` -不推荐使用 `DELETE` 全表数据: +不建议使用 `DELETE` 删除全表数据: ```sql DELETE FROM t; @@ -128,31 +118,31 @@ DELETE FROM t; ## DDL 最佳实践 -以下将介绍使用 TiDB 的 DDL 时所涉及到的最佳实践。 +本节介绍使用 TiDB 的 DDL 时涉及的最佳实践。 -### 主键选择的最佳实践 +### 主键最佳实践 -见[选择主键时应遵守的规则](/develop/dev-guide-create-table.md#选择主键时应遵守的规则)。 +请参阅[选择主键时需要遵循的规则](/develop/dev-guide-create-table.md#guidelines-to-follow-when-selecting-primary-key)。 -## 索引的最佳实践 +## 索引最佳实践 -见[索引的最佳实践](/develop/dev-guide-index-best-practice.md)。 +请参阅[索引的最佳实践](/develop/dev-guide-index-best-practice.md)。 -### 添加索引性能最佳实践 +### 添加索引最佳实践 -TiDB 支持在线添加索引操作,可通过 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 或 [`CREATE INDEX`](/sql-statements/sql-statement-create-index.md) 完成索引添加操作。添加索引不会阻塞表中的数据读写。可以通过修改下面的系统变量来调整 DDL 操作 `re-organize` 阶段的并行度与回填索引的单批数量大小: +TiDB 支持在线添加索引操作。你可以使用 [ADD INDEX](/sql-statements/sql-statement-add-index.md) 或 [CREATE INDEX](/sql-statements/sql-statement-create-index.md) 语句添加索引。这不会阻塞表中的数据读写。你可以通过修改以下系统变量来调整索引添加操作的 `re-organize` 阶段的并发度和批量大小: -- [tidb_ddl_reorg_worker_cnt](/system-variables.md#tidb_ddl_reorg_worker_cnt) -- [tidb_ddl_reorg_batch_size](/system-variables.md#tidb_ddl_reorg_batch_size) +* [`tidb_ddl_reorg_worker_cnt`](/system-variables.md#tidb_ddl_reorg_worker_cnt) +* [`tidb_ddl_reorg_batch_size`](/system-variables.md#tidb_ddl_reorg_batch_size) -为了减少对在线业务的影响,添加索引的默认速度会比较保守。当添加索引的目标列仅涉及查询负载,或者与线上负载不直接相关时,可以适当调大上述变量来加速添加索引: +为了减少对在线应用的影响,添加索引操作的默认速度较慢。当添加索引操作的目标列只涉及读取负载或与在线工作负载没有直接关系时,你可以适当增加上述变量的值来加快添加索引操作: ```sql SET @@global.tidb_ddl_reorg_worker_cnt = 16; SET @@global.tidb_ddl_reorg_batch_size = 4096; ``` -当添加索引操作的目标列被频繁更新(包含 `UPDATE`、`INSERT` 和 `DELETE`)时,调大上述配置会造成较为频繁的写冲突,使得在线负载较大;同时添加索引操作也可能由于不断地重试,需要很长的时间才能完成。此时建议调小上述配置来避免和在线业务的写冲突: +当添加索引操作的目标列经常被更新(包括 `UPDATE`、`INSERT` 和 `DELETE`)时,增加上述变量会导致更多的写入冲突,这会影响在线工作负载。相应地,由于不断重试,添加索引操作可能需要很长时间才能完成。在这种情况下,建议减小上述变量的值以避免与在线应用发生写入冲突: ```sql SET @@global.tidb_ddl_reorg_worker_cnt = 4; @@ -161,12 +151,56 @@ SET @@global.tidb_ddl_reorg_batch_size = 128; ## 事务冲突 -关于如何定位和解决事务冲突,请参考[TiDB 锁冲突问题处理](/troubleshoot-lock-conflicts.md)。 + + +关于如何定位和解决事务冲突,请参阅[故障诊断:锁冲突](/troubleshoot-lock-conflicts.md)。 + + + + + +关于如何定位和解决事务冲突,请参阅[故障诊断:锁冲突](https://docs.pingcap.com/tidb/stable/troubleshoot-lock-conflicts)。 + + + +## 使用 TiDB 开发 Java 应用程序的最佳实践 + + + +请参阅[使用 TiDB 开发 Java 应用程序的最佳实践](/best-practices/java-app-best-practices.md)。 + + + + + +请参阅[使用 TiDB 开发 Java 应用程序的最佳实践](https://docs.pingcap.com/tidb/stable/java-app-best-practices)。 + + + +### 另请参阅 + + + +- [高并发写入最佳实践](/best-practices/high-concurrency-best-practices.md) + + + + + +- [高并发写入最佳实践](https://docs.pingcap.com/tidb/stable/high-concurrency-best-practices) + + + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 -## Java 数据库应用开发最佳实践 + -[TiDB 最佳实践系列(五)Java 数据库应用开发指南](https://pingcap.com/zh/blog/best-practice-java)。 + -### 推荐阅读 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -- [TiDB 最佳实践系列(一)高并发写入常见热点问题及规避方法](https://pingcap.com/zh/blog/tidb-in-high-concurrency-scenarios)。 + diff --git a/develop/dev-guide-optimize-sql-overview.md b/develop/dev-guide-optimize-sql-overview.md index b177893246c7..b79657df58d4 100644 --- a/develop/dev-guide-optimize-sql-overview.md +++ b/develop/dev-guide-optimize-sql-overview.md @@ -1,31 +1,66 @@ --- -title: 概览 -summary: 介绍 TiDB 的 SQL 性能调优概览。 +title: SQL 性能优化概述 +summary: 为 TiDB 应用程序开发人员提供 SQL 性能调优的概述。 --- -# 概览 +# SQL 性能优化概述 -本章内容描述了如何在 TiDB 中优化 SQL 语句的性能。为了获得更好的性能,你可以从以下方面入手: +本文介绍如何在 TiDB 中优化 SQL 语句的性能。要获得良好的性能,您可以从以下方面入手: -- SQL 性能调优。 -- Schema 设计:根据你的业务负载类型,为了避免事务冲突或者是热点,你可能需要对表的 Schema 做出一些调整。 +* SQL 性能调优 +* 模式设计:根据您的应用程序工作负载模式,您可能需要更改表模式以避免事务冲突或热点。 ## SQL 性能调优 -为了让 SQL 语句的性能更好,可以遵循以下原则: +要获得良好的 SQL 语句性能,您可以遵循以下准则: -- 扫描的数据越少越好,最好能只扫描需要的数据,避免扫描多余的数据。 -- 使用合适的索引,对于 SQL 中的 `WHERE` 子句中的 Column,需要保证有相应索引,否则这将是一个全表扫的语句,性能会很差。 -- 使用合适的 Join 类型。根据查询中各个表的大小和关联性,选择合适的 Join 类型也会非常重要。一般情况下,TiDB 的 cost-based 优化器会自动选择最优的 Join 类型。但在少数情况下,用户手动指定 Join 类型可能会更好。 -- 使用合适的存储引擎。对于 OLTP 和 OLAP 混合类型的负载,推荐使用 TiFlash 查询引擎,具体可以参考 [HTAP 查询](/develop/dev-guide-hybrid-oltp-and-olap-queries.md)。 +* 扫描尽可能少的行。建议只扫描您需要的数据,避免扫描多余的数据。 +* 使用正确的索引。确保 SQL 中 `WHERE` 子句中的列有相应的索引。如果没有,语句会进行全表扫描,从而导致性能不佳。 +* 使用正确的连接类型。根据查询中涉及的表的相对大小选择正确的连接类型很重要。通常,TiDB 的基于成本的优化器会选择性能最佳的连接类型。但是,在少数情况下,您可能需要手动指定更好的连接类型。 +* 使用正确的存储引擎。对于混合 OLTP 和 OLAP 工作负载,建议使用 TiFlash 引擎。详情请参见 [HTAP 查询](/develop/dev-guide-hybrid-oltp-and-olap-queries.md)。 -## Schema 设计 +## 模式设计 -如果根据[SQL 性能调优](#sql-性能调优)调优后任然无法获得较好的性能,你可能需要检查你的 Schema 设计和数据读取模型,来确保避免以下问题: +在[调优 SQL 性能](#sql-性能调优)之后,如果您的应用程序仍然无法获得良好的性能,您可能需要检查您的模式设计和数据访问模式,以避免以下问题: -- 事务冲突。关于如何定位和解决事务冲突,请参考[TiDB 锁冲突问题处理](/troubleshoot-lock-conflicts.md)。 -- 热点。关于如何定位和解决热点,请参考[TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md)。 + -## 推荐阅读 +* 事务冲突。有关如何诊断和解决事务冲突,请参见[排查锁冲突问题](/troubleshoot-lock-conflicts.md)。 +* 热点。有关如何诊断和解决热点问题,请参见[排查热点问题](/troubleshoot-hot-spot-issues.md)。 -- [SQL 性能调优](/sql-tuning-overview.md)。 + + + + +* 事务冲突。有关如何诊断和解决事务冲突,请参见[排查锁冲突问题](https://docs.pingcap.com/tidb/stable/troubleshoot-lock-conflicts)。 +* 热点。有关如何诊断和解决热点问题,请参见[排查热点问题](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues)。 + + + +### 另请参阅 + + + +* [SQL 性能调优](/sql-tuning-overview.md) + + + + + +* [SQL 性能调优](/tidb-cloud/tidb-cloud-sql-tuning-overview.md) + + + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-optimize-sql.md b/develop/dev-guide-optimize-sql.md index 49e0f1cb2401..6f2a3fd15762 100644 --- a/develop/dev-guide-optimize-sql.md +++ b/develop/dev-guide-optimize-sql.md @@ -1,27 +1,27 @@ --- title: SQL 性能调优 -summary: 介绍 TiDB 的 SQL 性能调优方案和分析办法。 +summary: 介绍 TiDB 的 SQL 性能调优方案和分析方法。 --- # SQL 性能调优 -本章介绍常见的 SQL 性能调优,你将会了解导致 SQL 执行慢的常见的原因。 +本文介绍一些常见的 SQL 语句慢的原因以及 SQL 性能调优的技巧。 -## 准备工作 +## 开始之前 -在开始之前,你可以[通过 `tiup demo` 命令导入](/develop/dev-guide-bookshop-schema-design.md#方法一通过-tiup-demo-命令行)示例数据: +你可以使用 [`tiup demo` 导入](/develop/dev-guide-bookshop-schema-design.md#method-1-via-tiup-demo)准备数据: ```shell -tiup demo bookshop prepare --books 1000000 --host 127.0.0.1 --port 4000 +tiup demo bookshop prepare --host 127.0.0.1 --port 4000 --books 1000000 ``` -或[使用 TiDB Cloud 的 Import 功能导入](/develop/dev-guide-bookshop-schema-design.md#方法二通过-tidb-cloud-import-功能)预先准备好的示例数据。 +或者[使用 TiDB Cloud 的导入功能](/develop/dev-guide-bookshop-schema-design.md#method-2-via-tidb-cloud-import)导入预先准备的示例数据。 ## 问题:全表扫描 -慢查询最常见的原因就是 `SELECT` 语句执行是全表扫描,或者是用了不合适的索引。 +SQL 查询慢最常见的原因是 `SELECT` 语句执行全表扫描或使用了错误的索引。 -当基于不在主键或任何二级索引中的列从大表中检索少量行时,通常会获得较差的性能: +当 TiDB 从一个大表中基于非主键列或不在二级索引中的列检索少量行时,性能通常较差: ```sql SELECT * FROM books WHERE title = 'Marian Yost'; @@ -41,7 +41,7 @@ SELECT * FROM books WHERE title = 'Marian Yost'; Time: 0.582s ``` -可以使用 `EXPLAIN` 来查看这个查询的执行计划,看看为什么查询这么慢: +要了解为什么这个查询很慢,你可以使用 `EXPLAIN` 查看执行计划: ```sql EXPLAIN SELECT * FROM books WHERE title = 'Marian Yost'; @@ -57,19 +57,19 @@ EXPLAIN SELECT * FROM books WHERE title = 'Marian Yost'; +---------------------+------------+-----------+---------------+-----------------------------------------+ ``` -从执行计划中的 **TableFullScan_5** 可以看出,TiDB 将会对表 `books` 进行全表扫描,然后对每一行都判断 `title` 是否满足条件。**TableFullScan_5** 的 `estRows` 值为 `1000000.00`,说明优化器估计这个全表扫描会扫描 `1000000.00` 行数据。 +从执行计划中的 `TableFullScan_5` 可以看出,TiDB 对 `books` 表执行全表扫描,并检查每一行的 `title` 是否满足条件。`TableFullScan_5` 的 `estRows` 值为 `1000000.00`,这意味着优化器估计这次全表扫描需要扫描 `1000000.00` 行数据。 -更多关于 `EXPLAIN` 的使用介绍,可以阅读[使用 EXPLAIN 解读执行计划](/explain-walkthrough.md)。 +关于 `EXPLAIN` 的使用方法,请参见 [`EXPLAIN` 详解](/explain-walkthrough.md)。 -### 解决方案:使用索引过滤数据 +### 解决方案:使用二级索引 -为了加速上面的查询,可以在 `books.title` 列创建一个索引: +要加快上述查询,可以在 `books.title` 列上添加二级索引: ```sql CREATE INDEX title_idx ON books (title); ``` -现在再执行这个查询将会快很多: +查询执行速度快了很多: ```sql SELECT * FROM books WHERE title = 'Marian Yost'; @@ -89,7 +89,7 @@ SELECT * FROM books WHERE title = 'Marian Yost'; Time: 0.007s ``` -可以使用 `EXPLAIN` 来查看这个查询的执行计划,看看为什么查询变快了: +要了解为什么性能得到改善,使用 `EXPLAIN` 查看新的执行计划: ```sql EXPLAIN SELECT * FROM books WHERE title = 'Marian Yost'; @@ -105,17 +105,17 @@ EXPLAIN SELECT * FROM books WHERE title = 'Marian Yost'; +---------------------------+---------+-----------+-------------------------------------+-------------------------------------------------------+ ``` -从执行计划中的 **IndexLookUp_10** 可以看出,TiDB 将会通过索引 `title_idx` 来查询数据,其 `estRows` 值为 `1.27`,说明优化器估计只会扫描 `1.27` 行数据,远远小于之前全表扫的 `1000000.00` 行数据。 +从执行计划中的 `IndexLookup_10` 可以看出,TiDB 通过 `title_idx` 索引查询数据。其 `estRows` 值为 `1.27`,这意味着优化器估计只需要扫描 `1.27` 行。估计扫描的行数远少于全表扫描的 `1000000.00` 行数据。 -**IndexLookUp_10** 执行计划的执行流程是先用 **IndexRangeScan_8** 算子通过 `title_idx` 索引获取符合条件的索引数据,然后 **TableRowIDScan_9** 再更据索引数据里面的 Row ID 回表查询相应的行数据。 +`IndexLookup_10` 执行计划是先使用 `IndexRangeScan_8` 算子通过 `title_idx` 索引读取满足条件的索引数据,然后使用 `TableLookup_9` 算子根据索引数据中存储的 Row ID 查询对应的行。 -更多关于 TiDB 执行计划的内容,可以阅读[TiDB 执行计划概览](/explain-overview.md)。 +关于 TiDB 执行计划的更多信息,请参见 [TiDB 执行计划概览](/explain-overview.md)。 -### 解决方案:使用索引查询数据 +### 解决方案:使用覆盖索引 -上述解决方案中,需要先读取索引信息,再回表查询对应的行数据。但如果索引数据中包含了 SQL 查询所需的所有信息,就可以省去回表查询这个步骤。 +如果索引是覆盖索引,包含了 SQL 语句查询的所有列,那么扫描索引数据就足够完成查询。 -例如下面查询中,仅需要根据 `title` 查询对应的 `price`: +例如,在以下查询中,你只需要根据 `title` 查询对应的 `price`: ```sql SELECT title, price FROM books WHERE title = 'Marian Yost'; @@ -135,7 +135,7 @@ SELECT title, price FROM books WHERE title = 'Marian Yost'; Time: 0.007s ``` -由于索引 `title_idx` 仅包含 `title` 列的信息,所以 TiDB 还是需要扫描索引数据,然后回表查询 `price` 数据: +因为 `title_idx` 索引只包含 `title` 列的数据,TiDB 仍然需要先扫描索引数据,然后从表中查询 `price` 列。 ```sql EXPLAIN SELECT title, price FROM books WHERE title = 'Marian Yost'; @@ -151,7 +151,7 @@ EXPLAIN SELECT title, price FROM books WHERE title = 'Marian Yost'; +---------------------------+---------+-----------+-------------------------------------+-------------------------------------------------------+ ``` -删除 `title_idx` 索引,并新建一个 `title_price_idx` 索引: +要优化性能,删除 `title_idx` 索引并创建新的覆盖索引 `title_price_idx`: ```sql ALTER TABLE books DROP INDEX title_idx; @@ -161,7 +161,7 @@ ALTER TABLE books DROP INDEX title_idx; CREATE INDEX title_price_idx ON books (title, price); ``` -现在,`price` 数据已经存储在索引 `title_price_idx` 中了,所以下面查询仅需扫描索引数据,无需回表查询了。这种索引通常被叫做覆盖索引: +因为 `price` 数据存储在 `title_price_idx` 索引中,以下查询只需要扫描索引数据: ```sql EXPLAIN SELECT title, price FROM books WHERE title = 'Marian Yost'; @@ -176,7 +176,7 @@ EXPLAIN SELECT title, price FROM books WHERE title = 'Marian Yost'; +--------------------+---------+-----------+--------------------------------------------------+-------------------------------------------------------+ ``` -现在这条查询的速度将会更快: +现在这个查询运行得更快: ```sql SELECT title, price FROM books WHERE title = 'Marian Yost'; @@ -196,15 +196,15 @@ SELECT title, price FROM books WHERE title = 'Marian Yost'; Time: 0.004s ``` -由于后面的示例还会用到这个库,删除 `title_price_idx` 索引。 +由于 `books` 表将在后面的示例中使用,删除 `title_price_idx` 索引: ```sql ALTER TABLE books DROP INDEX title_price_idx; ``` -### 解决方案:使用主键查询数据 +### 解决方案:使用主键索引 -如果查询中使用主键过滤数据,这条查询的执行速度会非常快,例如表 `books` 的主键是列 `id`,使用列 `id` 来查询数据: +如果查询使用主键过滤数据,查询运行速度很快。例如,`books` 表的主键是 `id` 列,所以你可以使用 `id` 列查询数据: ```sql SELECT * FROM books WHERE id = 896; @@ -220,7 +220,7 @@ SELECT * FROM books WHERE id = 896; Time: 0.004s ``` -使用 `EXPLAIN` 查看执行计划: +使用 `EXPLAIN` 查看执行计划: ```sql EXPLAIN SELECT * FROM books WHERE id = 896; @@ -234,13 +234,27 @@ EXPLAIN SELECT * FROM books WHERE id = 896; +-------------+---------+------+---------------+---------------+ ``` -**Point_Get**,又名 “点查”,它的执行速度也非常快。 +`Point_Get` 是一个非常快的执行计划。 -## 选择合适的 Join 执行计划 +## 使用正确的连接类型 -见 [JOIN 查询的执行计划](/explain-joins.md)。 +请参见[连接的执行计划](/explain-joins.md)。 -## 推荐阅读 +### 另请参阅 -- [使用 EXPLAIN 解读执行计划](/explain-walkthrough.md)。 -- [用 EXPLAIN 查看索引查询的执行计划](/explain-indexes.md)。 +* [EXPLAIN 详解](/explain-walkthrough.md) +* [使用索引的执行计划](/explain-indexes.md) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-overview.md b/develop/dev-guide-overview.md index 0cc72ac21562..c8eea541bcbc 100644 --- a/develop/dev-guide-overview.md +++ b/develop/dev-guide-overview.md @@ -1,48 +1,231 @@ --- -title: 开发者手册概览 -summary: 整体叙述了开发者手册,罗列了开发者手册的大致脉络。 +title: 开发者指南概览 +summary: 介绍 TiDB Cloud 和 TiDB Self-Managed 的开发者指南概览。 --- -# 开发者手册概览 +# 开发者指南概览 -本文是为应用程序开发者所编写的,如果你对 TiDB 的内部原理感兴趣,或希望参与到 TiDB 的开发中来,那么可前往阅读 [TiDB Kernel Development Guide](https://pingcap.github.io/tidb-dev-guide/) 来获取更多 TiDB 的相关信息。 + -本手册将展示如何使用 TiDB 来快速构建一个应用,并且阐述使用 TiDB 期间可能出现的场景以及可能会遇到的问题。因此,在阅读此页面之前,建议你先行阅读 [TiDB 数据库快速上手指南](/quick-start-with-tidb.md)。 + + + -此外,你还可以通过视频的形式学习免费的 [TiDB SQL 开发在线课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)。 +## 按语言和框架分类的指南 -## TiDB 基础 +按照带有示例代码的指南,使用您熟悉的语言构建应用程序。 -在你开始使用 TiDB 之前,你需要了解一些关于 TiDB 数据库的一些重要工作机制: + + -- 阅读 [TiDB 事务概览](/transaction-overview.md)来了解 TiDB 的事务运作方式或查看[为应用开发程序员准备的事务说明](/develop/dev-guide-transaction-overview.md)查看应用开发程序员需要了解的事务部分。 -- 学习免费在线课程 [TiDB 架构与特点](https://learn.pingcap.com/learner/course/600003/?utm_source=docs-cn-dev-guide),了解构建 TiDB 分布式数据库集群的核心组件及其概念。 +在 Edge Function 中通过 HTTPS 连接到 TiDB Cloud。 + + + + +使用 mysql2 将 Next.js 连接到 TiDB Cloud。 + + + + +使用 Prisma ORM 连接到 TiDB Cloud。 + + + + +使用 TypeORM 连接到 TiDB Cloud。 + + + + +使用 Sequelize ORM 连接到 TiDB Cloud。 + + + + +使用 mysql.js 模块将 Node.js 连接到 TiDB Cloud。 + + + + +使用 node-mysql2 模块将 Node.js 连接到 TiDB Cloud。 + + + + +使用 mysql2 将 AWS Lambda 函数连接到 TiDB Cloud。 + + + + + + + +使用 django-tidb 将 Django 应用程序连接到 TiDB Cloud。 + + + + +使用 MySQL 官方包连接到 TiDB Cloud。 + + + + +使用 PyMySQL 包连接到 TiDB Cloud。 + + + + +使用 mysqlclient 包连接到 TiDB Cloud。 + + + + +使用 SQLAlchemy ORM 连接到 TiDB Cloud。 + + + + +使用 Peewee ORM 连接到 TiDB Cloud。 + + + + + + + +使用 JDBC(MySQL Connector/J)连接到 TiDB Cloud。 + + + + +使用 MyBatis ORM 连接到 TiDB Cloud。 + + + + +使用 Hibernate ORM 连接到 TiDB Cloud。 + + + + +使用 Spring Data JPA 将基于 Spring 的应用程序连接到 TiDB Cloud。 + + + + + + + +使用 Go 的 MySQL 驱动程序连接到 TiDB Cloud。 + + + + +使用 GORM 连接到 TiDB Cloud。 + + + + + + + +使用 Active Record ORM 将 Ruby on Rails 应用程序连接到 TiDB Cloud。 + + + + +使用 mysql2 驱动程序连接到 TiDB Cloud。 + + + + +除了这些指南外,PingCAP 还与社区合作[支持第三方 MySQL 驱动程序、ORM 和工具](/develop/dev-guide-third-party-support.md)。 + +## 使用 MySQL 客户端软件 + +由于 TiDB 是一个兼容 MySQL 的数据库,您可以使用许多客户端工具连接到 TiDB Cloud 并像以前一样管理数据库。或者,使用我们的命令行工具连接和管理您的数据库。 + + + + +使用 MySQL Workbench 连接和管理 TiDB Cloud 数据库。 + + + + +使用 VSCode 中的 SQLTools 扩展连接和管理 TiDB Cloud 数据库。 + + + + +使用 DBeaver 连接和管理 TiDB Cloud 数据库。 + + + + +使用 JetBrains 的 DataGrip 连接和管理 TiDB Cloud 数据库。 + + + + +## 其他资源 + +了解使用 TiDB Cloud 开发的其他主题。 + +- 使用 TiDB Cloud CLI 开发、管理和部署您的应用程序。 +- 探索 TiDB Cloud 与流行服务的集成。 +- 使用 [TiDB 数据库开发参考](/develop/dev-guide-schema-design-overview.md)来设计、交互、优化和排查数据和模式问题。 +- 学习免费在线课程 [TiDB 入门](https://eng.edu.pingcap.com/catalog/info/id:203/?utm_source=docs-dev-guide)。 + + + + + +本指南是为应用程序开发人员编写的,但如果您对 TiDB 的内部工作原理感兴趣或想参与 TiDB 开发,请阅读 [TiDB 内核开发指南](https://pingcap.github.io/tidb-dev-guide/)以获取更多信息。 + +本教程展示了如何使用 TiDB 快速构建应用程序、TiDB 的可能用例以及如何处理常见问题。 + +在阅读本页之前,建议您阅读 [TiDB 数据库平台快速入门指南](/quick-start-with-tidb.md)。 + +## TiDB 基础知识 + +在开始使用 TiDB 之前,您需要了解 TiDB 工作原理的一些重要机制: + +- 阅读 [TiDB 事务概述](/transaction-overview.md)以了解 TiDB 中事务的工作原理,或查看[应用程序开发人员的事务说明](/develop/dev-guide-transaction-overview.md)以了解应用程序开发所需的事务知识。 - 了解[应用程序与 TiDB 交互的方式](#应用程序与-tidb-交互的方式)。 +- 要了解构建分布式数据库 TiDB 和 TiDB Cloud 的核心组件和概念,请参考免费在线课程 [TiDB 入门](https://eng.edu.pingcap.com/catalog/info/id:203/?utm_source=docs-dev-guide)。 ## TiDB 事务机制 -TiDB 支持分布式事务,而且提供[乐观事务](/optimistic-transaction.md)与[悲观事务](/pessimistic-transaction.md)两种事务模式。TiDB 当前版本中默认采用 **悲观事务** 模式,这让你在 TiDB 事务时可以像使用传统的单体数据库 (如: MySQL) 事务一样。 +TiDB 支持分布式事务,并提供[乐观事务](/optimistic-transaction.md)和[悲观事务](/pessimistic-transaction.md)模式。当前版本的 TiDB 默认使用**悲观事务**模式,这使您可以像使用传统单体数据库(例如 MySQL)一样与 TiDB 进行事务操作。 -你可以使用 [BEGIN](/sql-statements/sql-statement-begin.md) 开启一个事务,或者使用 `BEGIN PESSIMISTIC` 显式的指定开启一个**悲观事务**,使用 `BEGIN OPTIMISTIC` 显式的指定开启一个**乐观事务**。随后,使用 [COMMIT](/sql-statements/sql-statement-commit.md) 提交事务,或使用 [ROLLBACK](/sql-statements/sql-statement-rollback.md) 回滚事务。 +您可以使用 [`BEGIN`](/sql-statements/sql-statement-begin.md) 开始事务,使用 `BEGIN PESSIMISTIC` 显式指定**悲观事务**,或使用 `BEGIN OPTIMISTIC` 显式指定**乐观事务**。之后,您可以提交([`COMMIT`](/sql-statements/sql-statement-commit.md))或回滚([`ROLLBACK`](/sql-statements/sql-statement-rollback.md))事务。 -TiDB 会为你保证 `BEGIN` 开始到 `COMMIT` 或 `ROLLBACK` 结束间的所有语句的原子性,即在这期间的所有语句全部成功,或者全部失败。用以保证你在应用开发时所需的数据一致性。 +TiDB 保证 `BEGIN` 开始到 `COMMIT` 或 `ROLLBACK` 结束期间所有语句的原子性,即在此期间执行的所有语句要么全部成功,要么全部失败。这用于确保应用程序开发所需的数据一致性。 -若你不清楚**乐观事务**是什么,请暂时不要使用它。因为使用**乐观事务**的前提是需要应用程序可以正确的处理 `COMMIT` 语句所返回的[所有错误](/error-codes.md)。如果不确定应用程序如何处理,请直接使用**悲观事务**。 +如果您不确定什么是**乐观事务**,请**_不要_**使用它。因为**乐观事务**要求应用程序能够正确处理 `COMMIT` 语句返回的[所有错误](/error-codes.md)。如果您不确定您的应用程序如何处理这些错误,请改用**悲观事务**。 ## 应用程序与 TiDB 交互的方式 -TiDB 高度兼容 MySQL 协议,TiDB 支持[大多数 MySQL 的语法及特性](/mysql-compatibility.md),因此大部分的 MySQL 的连接库都与 TiDB 兼容。如果你的应用程序框架或语言无 PingCAP 的官方适配,那么建议你使用 MySQL 的客户端库。同时,也有越来越多的三方数据库主动支持 TiDB 的差异特性。 +TiDB 高度兼容 MySQL 协议并支持[大多数 MySQL 语法和功能](/mysql-compatibility.md),因此大多数 MySQL 连接库都与 TiDB 兼容。如果您的应用程序框架或语言没有来自 PingCAP 的官方适配,建议您使用 MySQL 的客户端库。越来越多的第三方库正在积极支持 TiDB 的不同功能。 -因为 TiDB 兼容 MySQL 协议,且兼容 MySQL 语法,因此大多数支持 MySQL 的 ORM 也兼容 TiDB。 +由于 TiDB 兼容 MySQL 协议和 MySQL 语法,大多数支持 MySQL 的 ORM 也与 TiDB 兼容。 -## 扩展阅读 +## 阅读更多 -- [快速开始](/develop/dev-guide-build-cluster-in-cloud.md) -- [选择驱动或 ORM 框架](/develop/dev-guide-choose-driver-or-orm.md) +- [快速入门](/develop/dev-guide-build-cluster-in-cloud.md) +- [选择驱动程序或 ORM](/develop/dev-guide-choose-driver-or-orm.md) - [连接到 TiDB](/develop/dev-guide-connect-to-tidb.md) - [数据库模式设计](/develop/dev-guide-schema-design-overview.md) -- [数据写入](/develop/dev-guide-insert-data.md) -- [数据读取](/develop/dev-guide-get-data-from-single-table.md) +- [写入数据](/develop/dev-guide-insert-data.md) +- [读取数据](/develop/dev-guide-get-data-from-single-table.md) - [事务](/develop/dev-guide-transaction-overview.md) -- [优化 SQL 性能](/develop/dev-guide-optimize-sql-overview.md) -- [示例程序](/develop/dev-guide-sample-application-java-spring-boot.md) +- [优化](/develop/dev-guide-optimize-sql-overview.md) +- [示例应用程序](/develop/dev-guide-sample-application-java-spring-boot.md) + +## 需要帮助? + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + diff --git a/develop/dev-guide-paginate-results.md b/develop/dev-guide-paginate-results.md index 9a8c291e1a17..7c4ff85519d1 100644 --- a/develop/dev-guide-paginate-results.md +++ b/develop/dev-guide-paginate-results.md @@ -1,28 +1,28 @@ --- -title: 分页查询 -summary: 介绍 TiDB 的分页查询功能。 +title: 分页结果 +summary: 介绍 TiDB 中的分页结果功能。 --- -# 分页查询 +# 分页结果 -当查询结果数据量较大时,往往希望以“分页”的方式返回所需要的部分。 +要对大型查询结果进行分页,您可以以"分页"方式获取所需的部分。 -## 对查询结果进行分页 +## 分页查询结果 -在 TiDB 当中,可以利用 `LIMIT` 语句来实现分页功能,常规的分页语句写法如下所示: +在 TiDB 中,您可以使用 `LIMIT` 语句对查询结果进行分页。例如: ```sql SELECT * FROM table_a t ORDER BY gmt_modified DESC LIMIT offset, row_count; ``` -`offset` 表示起始记录数,`row_count` 表示每页记录数。除此之外,TiDB 也支持 `LIMIT row_count OFFSET offset` 语法。 +`offset` 表示记录的起始编号,`row_count` 表示每页的记录数。TiDB 也支持 `LIMIT row_count OFFSET offset` 语法。 -除非明确要求不要使用任何排序来随机展示数据,使用分页查询语句时都应该通过 `ORDER BY` 语句指定查询结果的排序方式。 +使用分页时,建议使用 `ORDER BY` 语句对查询结果进行排序,除非需要随机显示数据。
-例如,在 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用当中,希望将最新书籍列表以分页的形式返回给用户。通过 `LIMIT 0, 10` 语句,便可以得到列表第 1 页的书籍信息,每页中最多有 10 条记录。获取第 2 页信息,则改成可以改成 `LIMIT 10, 10`,如此类推。 +例如,要让 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序的用户以分页方式查看最新发布的书籍,您可以使用 `LIMIT 0, 10` 语句,该语句返回结果列表的第一页,每页最多 10 条记录。要获取第二页,您可以将语句改为 `LIMIT 10, 10`。 ```sql SELECT * @@ -34,7 +34,7 @@ LIMIT 0, 10;
-在使用 Java 开发应用程序时,后端程序从前端接收到的参数页码 `page_number` 和每页的数据条数 `page_size`,而不是起始记录数 `offset`,因此在进行数据库查询前需要对其进行一些转换。 +在应用程序开发中,后端程序从前端接收 `page_number` 参数(表示请求的页码)和 `page_size` 参数(控制每页显示多少条记录),而不是 `offset` 参数。因此,在查询之前需要进行一些转换。 ```java public List getLatestBooksPage(Long pageNumber, Long pageSize) throws SQLException { @@ -70,16 +70,14 @@ public List getLatestBooksPage(Long pageNumber, Long pageSize) throws SQLE ## 单字段主键表的分页批处理 -常规的分页更新 SQL 一般使用主键或者唯一索引进行排序,再配合 LIMIT 语法中的 `offset`,按固定行数拆分页面。然后把页面包装进独立的事务中,从而实现灵活的分页更新。但是,劣势也很明显:由于需要对主键或者唯一索引进行排序,越靠后的页面参与排序的行数就会越多,尤其当批量处理涉及的数据体量较大时,可能会占用过多计算资源。 +通常,您可以使用主键或唯一索引对结果进行排序,并在 `LIMIT` 子句中使用 `offset` 关键字按指定行数分页来编写分页 SQL 语句。然后将这些页面包装到独立的事务中,以实现灵活的分页更新。但是,缺点也很明显。由于需要对主键或唯一索引进行排序,较大的偏移量会消耗更多的计算资源,特别是在数据量较大的情况下。 -下面将介绍一种更为高效的分页批处理方案: +以下介绍一种更高效的分页批处理方法:
-使用 SQL 实现分页批处理,可以按照如下步骤进行: - -首先将数据按照主键排序,然后调用窗口函数 `row_number()` 为每一行数据生成行号,接着调用聚合函数按照设置好的页面大小对行号进行分组,最终计算出每页的最小值和最大值。 +首先,按主键排序并调用窗口函数 `row_number()` 为每一行生成行号。然后,调用聚合函数按指定的页面大小对行号进行分组,并计算每页的最小值和最大值。 ```sql SELECT @@ -95,7 +93,7 @@ GROUP BY page_num ORDER BY page_num; ``` -查询结果如下: +结果如下: ``` +----------+------------+------------+-----------+ @@ -112,9 +110,9 @@ ORDER BY page_num; 20 rows in set (0.01 sec) ``` -接下来,只需要使用 `WHERE id BETWEEN start_key AND end_key` 语句查询每个分片的数据即可。修改数据时,也可以借助上面计算好的分片信息,实现高效的数据更新。 +接下来,使用 `WHERE id BETWEEN start_key AND end_key` 语句查询每个分片的数据。为了更高效地更新数据,您可以在修改数据时使用上述分片信息。 -例如,假如想要删除第 1 页上的所有书籍的基本信息,可以将上表第 1 页所对应的 `start_key` 和 `end_key` 填入 SQL 语句当中。 +要删除第 1 页的所有图书基本信息,请将上述结果中第 1 页的 `start_key` 和 `end_key` 替换: ```sql DELETE FROM books @@ -126,7 +124,7 @@ ORDER BY id;
-在 Java 语言当中,可以定义一个 `PageMeta` 类来存储分页元信息。 +在 Java 中,定义一个 `PageMeta` 类来存储页面元信息。 ```java public class PageMeta { @@ -135,12 +133,12 @@ public class PageMeta { private K endKey; private Long pageSize; - // Skip the getters and setters. + // 跳过 getter 和 setter。 } ``` -定义一个 `getPageMetaList()` 方法获取到分页元信息列表,然后定义一个可以根据页面元信息批量删除数据的方法 `deleteBooksByPageMeta()`。 +定义一个 `getPageMetaList()` 方法来获取页面元信息列表,然后定义一个 `deleteBooksByPageMeta()` 方法根据页面元信息批量删除数据。 ```java public class BookDAO { @@ -184,7 +182,7 @@ public class BookDAO { } ``` -如果想要删除第 1 页的数据,可以这样写: +以下语句用于删除第 1 页的数据: ```java List> pageMetaList = bookDAO.getPageMetaList(); @@ -193,7 +191,7 @@ if (pageMetaList.size() > 0) { } ``` -如果希望通过分页分批地删除所有书籍数据,可以这样写: +以下语句用于按分页批量删除所有图书数据: ```java List> pageMetaList = bookDAO.getPageMetaList(); @@ -209,17 +207,17 @@ pageMetaList.forEach((pageMeta) -> {
-改进方案由于规避了频繁的数据排序操作造成的性能损耗,显著改善了批量处理的效率。 +这种方法通过避免频繁数据排序操作造成的计算资源浪费,显著提高了批处理效率。 ## 复合主键表的分页批处理 ### 非聚簇索引表 -对于非聚簇索引表(又被称为“非索引组织表”)而言,可以使用隐藏字段 `_tidb_rowid` 作为分页的 key,分页的方法与单列主键表中所介绍的方法相同。 +对于非聚簇索引表(也称为"非索引组织表"),可以使用内部字段 `_tidb_rowid` 作为分页键,分页方法与单字段主键表相同。 -> **建议:** +> **提示:** > -> 你可以通过 `SHOW CREATE TABLE users;` 语句查看表主键是否使用了[聚簇索引](/clustered-indexes.md)。 +> 您可以使用 `SHOW CREATE TABLE users;` 语句检查表主键是否使用[聚簇索引](/clustered-indexes.md)。 例如: @@ -230,14 +228,14 @@ SELECT max(t._tidb_rowid) AS end_key, count(*) AS page_size FROM ( - SELECT _tidb_rowid, row_number() OVER (ORDER BY _tidb_rowid) AS row_num + SELECT _tidb_rowid, row_number () OVER (ORDER BY _tidb_rowid) AS row_num FROM users ) t GROUP BY page_num ORDER BY page_num; ``` -查询结果如下: +结果如下: ``` +----------+-----------+---------+-----------+ @@ -259,13 +257,13 @@ ORDER BY page_num; ### 聚簇索引表 -对于聚簇索引表(又被称为“索引组织表”),可以利用 `concat` 函数将多个列的值连接起来作为一个 key,然后使用窗口函数获取分页信息。 +对于聚簇索引表(也称为"索引组织表"),您可以使用 `concat` 函数将多个列的值连接为一个键,然后使用窗口函数查询分页信息。 -需要注意的是,这时候 key 是一个字符串,你必须确保这个字符串长度总是相等的,才能够通过 `min` 和 `max` 聚合函数得到分页内正确的 `start_key` 和 `end_key`。如果进行字符串连接的字段长度不固定,你可以通过 `LPAD` 函数进行补全。 +需要注意的是,此时键是一个字符串,必须确保字符串的长度始终相同,以通过 `min` 和 `max` 聚合函数在分片中获得正确的 `start_key` 和 `end_key`。如果用于字符串连接的字段长度不固定,可以使用 `LPAD` 函数进行填充。 -例如,想要对 `ratings` 表里的数据进行分页批处理。 +例如,您可以按以下方式对 `ratings` 表中的数据进行分页批处理: -先可以通过下面的 SQL 语句来在制造元信息表。因为组成 key 的 `book_id` 列和 `user_id` 列都是 `bigint` 类型,转换为字符串是并不是等宽的,因此需要根据 `bigint` 类型的最大位数 19,使用 `LPAD` 函数在长度不够时用 `0` 补齐。 +使用以下语句创建元信息表。由于 `book_id` 和 `user_id` 是 `bigint` 类型,它们连接成的键无法转换为相同的长度,因此使用 `LPAD` 函数根据 `bigint` 的最大位数 19 用 `0` 填充长度。 ```sql SELECT @@ -285,9 +283,9 @@ ORDER BY page_num; > **注意:** > -> 该 SQL 会以全表扫描 (TableFullScan) 方式执行,当数据量较大时,查询速度会变慢,此时可以[使用 TiFlash](/tiflash/tiflash-overview.md#使用-tiflash) 进行加速。 +> 上述 SQL 语句执行为 `TableFullScan`。当数据量较大时,查询会很慢,您可以[使用 TiFlash](/tiflash/tiflash-overview.md#使用-tiflash) 加速。 -查询结果如下: +结果如下: ``` +----------+-------------------------------------------+-------------------------------------------+-----------+ @@ -305,7 +303,7 @@ ORDER BY page_num; 30 rows in set (0.28 sec) ``` -假如想要删除第 1 页上的所有评分记录,可以将上表第 1 页所对应的 `start_key` 和 `end_key` 填入 SQL 语句当中。 +要删除第 1 页的所有评分记录,请将上述结果中第 1 页的 `start_key` 和 `end_key` 替换: ```sql SELECT * @@ -335,3 +333,17 @@ WHERE ( ) ORDER BY book_id, user_id; ``` + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-playground-gitpod.md b/develop/dev-guide-playground-gitpod.md index e6ed35e5bd73..da74f71f9220 100644 --- a/develop/dev-guide-playground-gitpod.md +++ b/develop/dev-guide-playground-gitpod.md @@ -1,51 +1,51 @@ --- title: Gitpod -summary: Gitpod 是一个开源 Kubernetes 应用程序,可在浏览器中获得完整的开发环境,并立即编写代码。它能够为云中的每个任务提供全新的自动化开发环境,无需本地配置。Gitpod 提供了完整的、自动化的、预配置的云原生开发环境,让你可以直接在浏览器中开发、运行、测试代码。 +summary: Gitpod 提供了一个完整的、自动化的、预配置的云原生开发环境。你可以直接在浏览器中开发、运行和测试代码,无需任何本地配置。 --- # Gitpod -使用 [Gitpod](https://www.gitpod.io/),只需单击一个按钮或链接即可在浏览器中获得完整的开发环境,并且可以立即编写代码。 +通过 [Gitpod](https://www.gitpod.io/),你只需点击一个按钮或链接,就可以在浏览器中获得一个完整的开发环境,并立即开始编写代码。 -Gitpod 是一个开源 Kubernetes 应用程序(GitHub 仓库地址 ),适用于可直接编写代码的开发环境,可为云中的每个任务提供全新的自动化开发环境,非常迅速。此外,Gitpod 能够将你的开发环境描述为代码,并直接从你的浏览器或桌面 IDE 启动即时、远程和基于云的开发环境。 +Gitpod 是一个用于直接编码开发环境的开源 Kubernetes 应用程序(GitHub 仓库地址:),它可以在几秒钟内在云端为每个任务启动全新的、自动化的开发环境。它使你能够将开发环境描述为代码,并直接从浏览器或桌面 IDE 启动即时、远程和基于云的开发环境。 ## 快速开始 -1. Fork 出 TiDB 应用开发的示例代码仓库 [pingcap-inc/tidb-example-java](https://github.com/pingcap-inc/tidb-example-java)。 +1. Fork TiDB 应用程序开发的示例代码仓库 [pingcap-inc/tidb-example-java](https://github.com/pingcap-inc/tidb-example-java)。 -2. 通过浏览器的地址栏,在示例代码仓库的 URL 前加上 `https://gitpod.io/#` 来启动你的 gitpod 工作区。 +2. 在浏览器的地址栏中,在示例代码仓库的 URL 前加上 `https://gitpod.io/#` 来启动你的 Gitpod 工作区。 - - 例如,`https://gitpod.io/#https://github.com/pingcap-inc/tidb-example-java`。 + - 例如,`https://gitpod.io/#https://github.com/pingcap-inc/tidb-example-java`。 - - 支持在 URL 中配置环境变量。例如,`https://gitpod.io/#targetFile=spring-jpa-hibernate_Makefile,targetMode=spring-jpa-hibernate/https://github.com/pingcap-inc/tidb-example-java`。 + - 你可以在 URL 中配置环境变量。例如,`https://gitpod.io/#targetFile=spring-jpa-hibernate_Makefile,targetMode=spring-jpa-hibernate/https://github.com/pingcap-inc/tidb-example-java`。 -3. 使用列出的提供商之一登录并启动工作区,例如,`Github`。 +3. 使用列出的提供商之一登录并启动工作区。例如,`Github`。 ## 使用默认的 Gitpod 配置和环境 -完成[快速开始](#快速开始) 的步骤之后,Gitpod 会需要一段时间来设置你的工作区。 +完成[快速开始](#快速开始)步骤后,Gitpod 需要一段时间来设置你的工作区。 -以 [Spring Boot Web](/develop/dev-guide-sample-application-java-spring-boot.md) 应用程序为例,通过 URL `https://gitpod.io/#targetFile=spring-jpa-hibernate_Makefile,targetMode=spring-jpa-hibernate/https://github.com/pingcap-inc/tidb-example-java` 可以创建一个新工作区。 +以 [Spring Boot Web](/develop/dev-guide-sample-application-java-spring-boot.md) 应用程序为例。你可以通过 `https://gitpod.io/#targetFile=spring-jpa-hibernate_Makefile,targetMode=spring-jpa-hibernate/https://github.com/pingcap-inc/tidb-example-java` URL 创建一个新的工作区。 -完成后,你将看到如下所示的页面。 +之后,你将看到类似以下的页面: ![playground gitpod workspace init](/media/develop/playground-gitpod-workspace-init.png) -页面中的这个场景使用了 [TiUP](https://docs.pingcap.com/zh/tidb/stable/tiup-overview) 来搭建一个 TiDB Playground。你可以在终端的左侧查看进度。 +页面中的这个场景使用 [TiUP](https://docs.pingcap.com/tidb/stable/tiup-overview) 来构建 TiDB Playground。你可以在终端区域的左侧查看进度。 -一旦 TiDB Playground 准备就绪,另一个 `Spring JPA Hibernate` 任务将运行。 你可以在终端的右侧查看进度。 +当 TiDB Playground 准备就绪后,另一个 `Spring JPA Hibernate` 任务将运行。你可以在终端区域的右侧查看进度。 -完成所有任务后,你可以看到如下所示的页面,并在左侧导航栏的 `REMOTE EXPLORER` 中找到你的端口 `8080` URL(Gitpod 支持基于 URL 的端口转发)。 +所有这些任务完成后,你将看到类似以下的页面。在此页面上,查看左侧导航栏中的 `REMOTE EXPLORER` 区域(Gitpod 支持基于 URL 的端口转发)并找到你的端口 `8080` 的 URL。 ![playground gitpod workspace ready](/media/develop/playground-gitpod-workspace-ready.png) -## 使用自定义的 Gitpod 配置和 Docker 镜像 +## 使用自定义 Gitpod 配置和 Docker 镜像 ### 自定义 Gitpod 配置 -在项目的根目录中,参考[示例 .gitpod.yml](https://github.com/pingcap-inc/tidb-example-java/blob/main/.gitpod.yml),创建一个 `.gitpod.yml` 文件用于配置 Gitpod 工作空间。 +参考 [example.gitpod.yml](https://github.com/pingcap-inc/tidb-example-java/blob/main/.gitpod.yml),在项目的根目录下创建一个 `.gitpod.yml` 文件来配置 Gitpod 工作区。 ```yml # This configuration file was automatically generated by Gitpod. @@ -93,11 +93,11 @@ ports: ### 自定义 Gitpod Docker 镜像 -默认情况下,Gitpod 使用名为 Workspace-Full 的标准 Docker 镜像作为工作空间的基础。 基于此默认镜像启动的工作区预装了 Docker、Go、Java、Node.js、C/C++、Python、Ruby、Rust、PHP 以及 Homebrew、Tailscale、Nginx 等工具。 +默认情况下,Gitpod 使用名为 Workspace-Full 的标准 Docker 镜像作为工作区的基础。从此默认镜像启动的工作区预装了 Docker、Go、Java、Node.js、C/C++、Python、Ruby、Rust、PHP 以及 Homebrew、Tailscale 和 Nginx 等工具。 -你可以提供公共 Docker 镜像或 Dockerfile。 并为你的项目安装所需的任何依赖项。 +你可以使用公共 Docker 镜像或 Dockerfile,并安装项目所需的任何依赖项。 -这是一个 Dockerfile 示例:[示例 .gitpod.Dockerfile](https://github.com/pingcap-inc/tidb-example-java/blob/main/.gitpod.Dockerfile) +例如,你可以使用 Dockerfile(另请参见[示例 `.gitpod.Dockerfile`](https://github.com/pingcap-inc/tidb-example-java/blob/main/.gitpod.Dockerfile))如下: ```dockerfile FROM gitpod/workspace-java-17 @@ -106,7 +106,7 @@ RUN sudo apt install mysql-client -y RUN curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh ``` -然后需要更新`.gitpod.yml`: +然后,你需要更新 `.gitpod.yml`: ```yml # This configuration file was automatically generated by Gitpod. @@ -114,7 +114,7 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/instal # and commit this file to your remote git repository to share the goodness with others. image: - # 在这里导入你的 Dockerfile + # Import your Dockerfile here. file: .gitpod.Dockerfile tasks: @@ -155,14 +155,28 @@ ports: ### 应用更改 -完成对 `.gitpod.yml` 文件配置后,请保证最新的代码已在你对应的 GitHub 代码仓库中可用。 +完成 `.gitpod.yml` 文件的配置后,确保最新代码在你相应的 GitHub 仓库中可用。 -访问 `https://gitpod.io/#` 以建立新的 Gitpod 工作区,新工作区会应用最新的代码。 +访问 `https://gitpod.io/#` 以使用应用了最新代码的新 Gitpod 工作区。 -访问 `https://gitpod.io/workspaces` 以获取所有建立的工作区。 +访问 `https://gitpod.io/workspaces` 查看所有已建立的工作区。 ## 总结 -Gitpod 提供了完整的、自动化的、预配置的云原生开发环境。无需本地配置,你可以直接在浏览器中开发、运行、测试代码。 +Gitpod 提供了一个完整的、自动化的、预配置的云原生开发环境。你可以直接在浏览器中开发、运行和测试代码,无需任何本地配置。 ![playground gitpod summary](/media/develop/playground-gitpod-summary.png) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-prepared-statement.md b/develop/dev-guide-prepared-statement.md index 592bd32c3eec..73a22a61600e 100644 --- a/develop/dev-guide-prepared-statement.md +++ b/develop/dev-guide-prepared-statement.md @@ -1,20 +1,20 @@ --- title: 预处理语句 -summary: 介绍 TiDB 的预处理语句功能。 +summary: 了解如何使用 TiDB 预处理语句。 --- # 预处理语句 -[预处理语句](/sql-statements/sql-statement-prepare.md)是一种将多个仅有参数不同的 SQL 语句进行模板化的语句,它让 SQL 语句与参数进行了分离。可以用它提升 SQL 语句的: +[预处理语句](/sql-statements/sql-statement-prepare.md)将多个只有参数不同的 SQL 语句模板化。它将 SQL 语句与参数分离。你可以使用它来改进 SQL 语句的以下方面: -- 安全性:因为参数和语句已经分离,所以避免了 [SQL 注入攻击](https://en.wikipedia.org/wiki/SQL_injection)的风险。 -- 性能:因为语句在 TiDB 端被预先解析,后续执行只需要传递参数,节省了完整 SQL 解析、拼接 SQL 语句字符串以及网络传输的代价。 +- **安全性**:由于参数和语句是分离的,避免了 [SQL 注入](https://en.wikipedia.org/wiki/SQL_injection)攻击的风险。 +- **性能**:由于语句在 TiDB 服务器上预先解析,后续执行时只传递参数,节省了解析整个 SQL 语句、拼接 SQL 语句字符串和网络传输的成本。 -在大部分的应用程序中,SQL 语句是可以被枚举的,可以使用有限个 SQL 语句来完成整个应用程序的数据查询,所以使用预处理语句是最佳实践之一。 +在大多数应用程序中,SQL 语句是可枚举的。你可以使用有限数量的 SQL 语句来完成整个应用程序的数据查询。因此使用预处理语句是一种最佳实践。 ## SQL 语法 -本节将介绍创建、使用及删除预处理语句的 SQL 语法。 +本节描述创建、运行和删除预处理语句的 SQL 语法。 ### 创建预处理语句 @@ -22,29 +22,29 @@ summary: 介绍 TiDB 的预处理语句功能。 PREPARE {prepared_statement_name} FROM '{prepared_statement_sql}'; ``` -| 参数 | 描述 | +| 参数名称 | 描述 | | :-------------------------: | :------------------------------------: | -| `{prepared_statement_name}` | 预处理语句名称 | -| `{prepared_statement_sql}` | 预处理语句 SQL,以英文半角问号做占位符 | +| `{prepared_statement_name}` | 预处理语句的名称 | +| `{prepared_statement_sql}` | 使用问号作为占位符的预处理语句 SQL | -你可查看 [PREPARE 语句](/sql-statements/sql-statement-prepare.md) 获得更多信息。 +更多信息请参见 [PREPARE 语句](/sql-statements/sql-statement-prepare.md)。 ### 使用预处理语句 -预处理语句仅可使用用户变量作为参数,因此,需先使用 [SET 语句](/sql-statements/sql-statement-set-variable.md) 设置变量后,供 [EXECUTE 语句](/sql-statements/sql-statement-execute.md) 调用预处理语句。 +预处理语句只能使用**用户变量**作为参数,因此在使用 [`EXECUTE` 语句](/sql-statements/sql-statement-execute.md)调用预处理语句之前,需要使用 [`SET` 语句](/sql-statements/sql-statement-set-variable.md)设置变量。 ```sql SET @{parameter_name} = {parameter_value}; EXECUTE {prepared_statement_name} USING @{parameter_name}; ``` -| 参数 | 描述 | +| 参数名称 | 描述 | | :-------------------------: | :-------------------------------------------------------------------: | -| `{parameter_name}` | 用户参数名 | -| `{parameter_value}` | 用户参数值 | -| `{prepared_statement_name}` | 预处理语句名称,需和[创建预处理语句](#创建预处理语句)中定义的名称一致 | +| `{parameter_name}` | 用户变量名称 | +| `{parameter_value}` | 用户变量值 | +| `{prepared_statement_name}` | 预处理语句的名称,必须与[创建预处理语句](#创建预处理语句)中定义的名称相同 | -你可查看 [EXECUTE 语句](/sql-statements/sql-statement-execute.md) 获得更多信息。 +更多信息请参见 [`EXECUTE` 语句](/sql-statements/sql-statement-execute.md)。 ### 删除预处理语句 @@ -52,31 +52,29 @@ EXECUTE {prepared_statement_name} USING @{parameter_name}; DEALLOCATE PREPARE {prepared_statement_name}; ``` -| 参数 | 描述 | +| 参数名称 | 描述 | | :-------------------------: | :-------------------------------------------------------------------: | -| `{prepared_statement_name}` | 预处理语句名称,需和[创建预处理语句](#创建预处理语句)中定义的名称一致 | +| `{prepared_statement_name}` | 预处理语句的名称,必须与[创建预处理语句](#创建预处理语句)中定义的名称相同 | -你可查看 [DEALLOCATE 语句](/sql-statements/sql-statement-deallocate.md) 获得更多信息。 +更多信息请参见 [`DEALLOCATE` 语句](/sql-statements/sql-statement-deallocate.md)。 -## 例子 +## 示例 -本节以使用预处理语句,完成查询数据和插入数据两个场景的示例。 +本节描述预处理语句的两个示例:`SELECT` 数据和 `INSERT` 数据。 -### 查询示例 +### `SELECT` 示例 -例如,需要查询 [Bookshop 应用](/develop/dev-guide-bookshop-schema-design.md#books-表) 中,`id` 为 1 的书籍信息。 +例如,你需要在 [`bookshop` 应用程序](/develop/dev-guide-bookshop-schema-design.md#books-table)中查询 `id = 1` 的图书。
-使用 SQL 查询示例: - ```sql PREPARE `books_query` FROM 'SELECT * FROM `books` WHERE `id` = ?'; ``` -运行结果为: +运行结果: ``` Query OK, 0 rows affected (0.01 sec) @@ -86,7 +84,7 @@ Query OK, 0 rows affected (0.01 sec) SET @id = 1; ``` -运行结果为: +运行结果: ``` Query OK, 0 rows affected (0.04 sec) @@ -96,7 +94,7 @@ Query OK, 0 rows affected (0.04 sec) EXECUTE `books_query` USING @id; ``` -运行结果为: +运行结果: ``` +---------+---------------------------------+--------+---------------------+-------+--------+ @@ -111,10 +109,8 @@ EXECUTE `books_query` USING @id;
-使用 Java 查询示例: - ```java -// ds is an entity of com.mysql.cj.jdbc.MysqlDataSource +// ds 是 com.mysql.cj.jdbc.MysqlDataSource 的实例 try (Connection connection = ds.getConnection()) { PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `books` WHERE `id` = ?"); preparedStatement.setLong(1, 1); @@ -123,7 +119,7 @@ try (Connection connection = ds.getConnection()) { if(!res.next()) { System.out.println("No books in the table with id 1"); } else { - // got book's info, which id is 1 + // 获取 id 为 1 的图书信息 System.out.println(res.getLong("id")); System.out.println(res.getString("title")); System.out.println(res.getString("type")); @@ -137,21 +133,19 @@ try (Connection connection = ds.getConnection()) { -### 插入示例 +### `INSERT` 示例 -还是使用 [books 表](/develop/dev-guide-bookshop-schema-design.md#books-表) 为例,需要插入一个 `title` 为 `TiDB Developer Guide`, `type` 为 `Science & Technology`, `stock` 为 `100`, `price` 为 `0.0`, `published_at` 为 `插入的当前时间` 的书籍信息。需要注意的是,`books` 表的主键包含 `AUTO_RANDOM` 属性,无需指定它。如果你对插入数据还不了解,可以在[插入数据](/develop/dev-guide-insert-data.md)一节了解更多数据插入的相关信息。 +以 [`books` 表](/develop/dev-guide-bookshop-schema-design.md#books-table)为例,你需要插入一本 `title = TiDB Developer Guide`、`type = Science & Technology`、`stock = 100`、`price = 0.0` 和 `published_at = NOW()`(插入时的当前时间)的图书。注意,你不需要在 `books` 表的**主键**中指定 `AUTO_RANDOM` 属性。有关插入数据的更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。
-使用 SQL 插入数据示例如下: - ```sql PREPARE `books_insert` FROM 'INSERT INTO `books` (`title`, `type`, `stock`, `price`, `published_at`) VALUES (?, ?, ?, ?, ?);'; ``` -运行结果为: +运行结果: ``` Query OK, 0 rows affected (0.03 sec) @@ -165,7 +159,7 @@ SET @price = 0.0; SET @published_at = NOW(); ``` -运行结果为: +运行结果: ``` Query OK, 0 rows affected (0.04 sec) @@ -175,7 +169,7 @@ Query OK, 0 rows affected (0.04 sec) EXECUTE `books_insert` USING @title, @type, @stock, @price, @published_at; ``` -运行结果为: +运行结果: ``` Query OK, 1 row affected (0.03 sec) @@ -185,8 +179,6 @@ Query OK, 1 row affected (0.03 sec)
-使用 Java 插入数据示例如下: - ```java try (Connection connection = ds.getConnection()) { String sql = "INSERT INTO `books` (`title`, `type`, `stock`, `price`, `published_at`) VALUES (?, ?, ?, ?, ?);"; @@ -204,29 +196,45 @@ try (Connection connection = ds.getConnection()) { } ``` -可以看到,JDBC 帮你管控了预处理语句的生命周期,而无需你在应用程序里手动使用预处理语句的创建、使用、删除等。但值得注意的是,因为 TiDB 兼容 MySQL 协议,在客户端使用 MySQL JDBC Driver 的过程中,其默认配置并非开启 **_服务端_** 的预处理语句选项,而是使用客户端的预处理语句。你需要关注以下配置项,来获得在 JDBC 下 TiDB 服务端预处理语句的支持,及在你的使用场景下的最佳配置: +如你所见,JDBC 帮助你控制预处理语句的生命周期,你不需要在应用程序中手动创建、使用或删除预处理语句。但是请注意,由于 TiDB 兼容 MySQL,在客户端使用 MySQL JDBC Driver 的默认配置是不启用**_服务器端_**预处理语句选项,而是使用客户端预处理语句。 + +以下配置可帮助你在 JDBC 下使用 TiDB 服务器端预处理语句: -| 参数 | 作用 | 推荐场景 | 推荐配置 | -| :---------------------: | :-----------------------------------: | :--------------------------: | :----------------------: | -| `useServerPrepStmts` | 是否使用服务端开启预处理语句支持 | 在需要多次使用预处理语句时 | `true` | -| `cachePrepStmts` | 客户端是否缓存预处理语句 | `useServerPrepStmts=true` 时 | `true` | -| `prepStmtCacheSqlLimit` | 预处理语句最大大小(默认 256 字符) | 预处理语句大于 256 字符时 | 按实际预处理语句大小配置 | -| `prepStmtCacheSize` | 预处理语句最大缓存数量 (默认 25 条) | 预处理语句数量大于 25 条时 | 按实际预处理语句数量配置 | +| 参数 | 含义 | 推荐场景 | 推荐配置 | +| :------------------------: | :-----------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------: | +| `useServerPrepStmts` | 是否使用服务器端启用预处理语句 | 当你需要多次使用预处理语句时 | `true` | +| `cachePrepStmts` | 客户端是否缓存预处理语句 | `useServerPrepStmts=true` | `true` | +| `prepStmtCacheSqlLimit` | 预处理语句的最大大小(默认 256 字符) | 当预处理语句大于 256 字符时 | 根据预处理语句的实际大小配置 | +| `prepStmtCacheSize` | 预处理语句的最大数量(默认 25 个) | 当预处理语句数量大于 25 个时 | 根据预处理语句的实际数量配置 | -在此处给出一个较为的通用场景的 JDBC 连接字符串配置,以 Host: `127.0.0.1`,Port: `4000`,用户: `root`,密码: 空,默认数据库: `test`为例: +以下是 JDBC 连接字符串配置的典型场景。主机:`127.0.0.1`,端口:`4000`,用户名:`root`,密码:null,默认数据库:`test`: ``` jdbc:mysql://127.0.0.1:4000/test?user=root&useConfigs=maxPerformance&useServerPrepStmts=true&prepStmtCacheSqlLimit=2048&prepStmtCacheSize=256&rewriteBatchedStatements=true&allowMultiQueries=true ``` -你也可以查看[插入行](/develop/dev-guide-insert-data.md#插入行)一章,来查看是否需要在插入数据场景下更改其他 JDBC 的参数。 +如果你在插入数据时需要更改其他 JDBC 参数,也可以参见[插入行](/develop/dev-guide-insert-data.md#插入行)章节。 -有关 Java 的完整示例,可参阅: +有关 Java 的完整示例,请参见: -- [TiDB 和 JDBC 的简单 CRUD 应用程序](/develop/dev-guide-sample-application-java-jdbc.md) -- [TiDB 和 Hibernate 的简单 CRUD 应用程序](/develop/dev-guide-sample-application-java-hibernate.md) -- [使用 Spring Boot 构建 TiDB 应用程序](/develop/dev-guide-sample-application-java-spring-boot.md) +- [使用 JDBC 连接到 TiDB](/develop/dev-guide-sample-application-java-jdbc.md) +- [使用 Hibernate 连接到 TiDB](/develop/dev-guide-sample-application-java-hibernate.md) +- [使用 Spring Boot 连接到 TiDB](/develop/dev-guide-sample-application-java-spring-boot.md)
+ +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-proxysql-integration.md b/develop/dev-guide-proxysql-integration.md index 93f1b9d63cbe..2605320cc882 100644 --- a/develop/dev-guide-proxysql-integration.md +++ b/develop/dev-guide-proxysql-integration.md @@ -1,13 +1,13 @@ --- -title: ProxySQL 集成指南 -summary: 了解如何将本地部署的 TiDB 或 TiDB Cloud 集群与 ProxySQL 集成。 +title: 将 TiDB 与 ProxySQL 集成 +summary: 了解如何将 ProxySQL 与 TiDB 集成。 --- -# ProxySQL 集成指南 +# 将 TiDB 与 ProxySQL 集成 -本文简要介绍 ProxySQL,描述如何在[开发环境](#开发环境)和[生产环境](#生产环境)中将 ProxySQL 与 TiDB 集成,并通过[查询规则的场景](#典型场景)展示集成的主要优势。 +本文提供了对 ProxySQL 的高级介绍,描述了如何在[开发环境](#开发环境)和[生产环境](#生产环境)中将 ProxySQL 与 TiDB 集成,并通过[查询路由场景](#典型场景)演示了关键的集成优势。 -关于 TiDB 和 ProxySQL 的更多信息,请参考以下文档: +如果您想了解更多关于 TiDB 和 ProxySQL 的信息,可以参考以下有用的链接: - [TiDB Cloud](https://docs.pingcap.com/tidbcloud) - [TiDB 开发者指南](/develop/dev-guide-overview.md) @@ -15,36 +15,36 @@ summary: 了解如何将本地部署的 TiDB 或 TiDB Cloud 集群与 ProxySQL ## 什么是 ProxySQL? -[ProxySQL](https://proxysql.com/) 是一个高性能的开源 SQL 代理。它具有灵活的架构,可以通过多种方式部署,适合各类使用场景。例如,ProxySQL 可以通过缓存频繁访问的数据来提高性能。 +[ProxySQL](https://proxysql.com/) 是一个高性能的开源 SQL 代理。它具有灵活的架构,可以以多种不同方式部署,非常适合各种用例。例如,ProxySQL 可以通过缓存频繁访问的数据来提高性能。 -ProxySQL 的设计目标是快速、高效且易于使用。它完全兼容 MySQL,并支持高质量 SQL 代理的所有功能。此外,ProxySQL 还提供了许多独特功能,使其成为各种应用程序的理想选择。 +ProxySQL 从一开始就被设计为快速、高效和易于使用。它完全兼容 MySQL,并支持您期望从高质量 SQL 代理获得的所有功能。此外,ProxySQL 还具有许多独特的功能,使其成为广泛应用的理想选择。 -## 为什么集成 ProxySQL? +## 为什么要集成 ProxySQL? -- ProxySQL 可以通过降低与 TiDB 交互的延迟来提升应用程序性能。无论你构建什么,无论是使用 Lambda 等无服务器函数的可扩展应用程序(其工作负载不确定并且可能激增),还是构建执行大量数据查询的应用程序,都可以利用 ProxySQL 的强大功能(例如[连接池](https://proxysql.com/documentation/detailed-answers-on-faq/)和[缓存常用查询](https://proxysql.com/documentation/query-cache/))。 -- ProxySQL 可以作为应用程序安全防护的附加层,使用[查询规则](#查询规则)防止 SQL 漏洞(例如 SQL 注入)。 -- 由于 [ProxySQL](https://github.com/sysown/proxysql) 和 [TiDB](https://github.com/pingcap/tidb) 都是开源项目,你可以享受到零供应商锁定的好处。 +- ProxySQL 可以通过减少与 TiDB 交互时的延迟来帮助提升应用程序性能。无论您是使用 Lambda 等无服务器函数构建可扩展应用程序(其中工作负载是不确定的并且可能出现峰值),还是构建执行加载大量数据的查询的应用程序。通过利用 ProxySQL 的强大功能,如[连接池](https://proxysql.com/documentation/detailed-answers-on-faq/)和[频繁使用的查询缓存](https://proxysql.com/documentation/query-cache/),应用程序可以立即获得好处。 +- ProxySQL 可以通过[查询规则](#查询规则)(ProxySQL 中一个易于配置的功能)充当应用程序安全保护的额外层,防止 SQL 注入等 SQL 漏洞。 +- 由于 [ProxySQL](https://github.com/sysown/proxysql) 和 [TiDB](https://github.com/pingcap/tidb) 都是开源项目,您可以获得零供应商锁定的好处。 ## 部署架构 -将 ProxySQL 与 TiDB 集成的最直接方式是在应用层和 TiDB 之间添加 ProxySQL 作为独立中介。但是,这种方式无法保证可扩展性和容错性,而且可能因为网络跳转而增加延迟。为避免这些问题,一种替代部署架构是将 ProxySQL 作为附属容器部署,如下图所示: +将 ProxySQL 与 TiDB 集成最明显的方式是将 ProxySQL 作为应用层和 TiDB 之间的独立中介。但是,这种方式无法保证可扩展性和故障容忍性,而且由于网络跳转也会增加额外的延迟。为了避免这些问题,一种替代的部署架构是将 ProxySQL 作为边车部署,如下所示: ![proxysql-client-side-tidb-cloud](/media/develop/proxysql-client-side-tidb-cloud.png) > **注意:** > -> 上图仅供参考,你需要根据实际的部署架构进行调整。 +> 上述图示仅供参考。您必须根据实际部署架构进行调整。 ## 开发环境 -本节介绍如何在开发环境中将 TiDB 与 ProxySQL 集成。在满足[前提条件](#前提条件)的情况下,你可以根据 TiDB 集群类型选择以下选项之一开始集成 ProxySQL: +本节描述如何在开发环境中将 TiDB 与 ProxySQL 集成。要开始 ProxySQL 集成,在准备好所有[前提条件](#前提条件)后,您可以根据 TiDB 集群类型选择以下任一选项。 -- 选项 1:[集成 TiDB Cloud 与 ProxySQL](#选项-1-集成-tidb-cloud-与-proxysql) -- 选项 2:[集成本地部署的 TiDB 与 ProxySQL](#选项-2-集成本地部署的-tidb-与-proxysql) +- 选项 1:[将 TiDB Cloud 与 ProxySQL 集成](#选项-1-将-tidb-cloud-与-proxysql-集成) +- 选项 2:[将 TiDB(自托管)与 ProxySQL 集成](#选项-2-将-tidb-自托管与-proxysql-集成) ### 前提条件 -根据选择的方案,你可能需要以下依赖: +根据您选择的选项,您可能需要以下软件包: - [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) - [Docker](https://docs.docker.com/get-docker/) @@ -52,13 +52,13 @@ ProxySQL 的设计目标是快速、高效且易于使用。它完全兼容 MySQ - [Docker Compose](https://docs.docker.com/compose/install/linux/) - [MySQL Client](https://dev.mysql.com/doc/refman/8.0/en/mysql.html) -你可以按照下面的说明进行安装: +您可以按照以下说明进行安装:
-1. [下载](https://docs.docker.com/get-docker/)并启动 Docker,其中 Docker Desktop 已包含 Docker Compose。 +1. [下载](https://docs.docker.com/get-docker/)并启动 Docker(Docker Desktop 已包含 Docker Compose)。 2. 运行以下命令安装 Python 和 `mysql-client`: ```bash @@ -82,15 +82,15 @@ systemctl start docker - 下载并安装 Git。 - 1. 从 [Download for Windows](https://git-scm.com/download/win) 页面下载 **64-bit Git for Windows Setup** 安装程序。 - 2. 按照安装向导提示安装 Git。你可以多次点击 **Next** 使用默认的安装设置。 + 1. 从 [Git Windows 下载](https://git-scm.com/download/win)页面下载 **64-bit Git for Windows Setup** 包。 + 2. 按照安装向导安装 Git 包。您可以点击**下一步**几次使用默认安装设置。 ![proxysql-windows-git-install](/media/develop/proxysql-windows-git-install.png) - 下载并安装 MySQL Shell。 - 1. 从 [MySQL Community Server Download](https://dev.mysql.com/downloads/mysql/) 页面下载 MySQL Installer 的 ZIP 文件。 - 2. 解压文件,并在 `bin` 文件夹中找到 `mysql.exe`。你需要将该 `bin` 文件夹的路径添加到系统变量中,并在 Git Bash 中将其设置到 `PATH` 变量中。 + 1. 从 [MySQL Community Server 下载](https://dev.mysql.com/downloads/mysql/)页面下载 MySQL 安装程序的 ZIP 文件。 + 2. 解压文件,找到 `bin` 文件夹中的 `mysql.exe`。您需要将 `bin` 文件夹的路径添加到系统变量中,并在 Git Bash 中设置到 `PATH` 变量: ```bash echo 'export PATH="(your bin folder)":$PATH' >>~/.bash_profile @@ -106,32 +106,32 @@ systemctl start docker - 下载并安装 Docker。 - 1. 从 [Docker Download](https://www.docker.com/products/docker-desktop/) 页面下载 Docker Desktop 安装程序。 - 2. 双击安装程序运行。安装完成后,会提示你重新启动。 + 1. 从 [Docker 下载](https://www.docker.com/products/docker-desktop/)页面下载 Docker Desktop 安装程序。 + 2. 双击安装程序运行。安装完成后,系统会提示重启。 ![proxysql-windows-docker-install](/media/develop/proxysql-windows-docker-install.png) -- 从 [Python Download](https://www.python.org/downloads/) 页面下载最新版的 Python 3 安装程序并运行。 +- 从 [Python 下载](https://www.python.org/downloads/)页面下载最新的 Python 3 安装程序并运行。
-### 选项 1: 集成 TiDB Cloud 与 ProxySQL +### 选项 1. 将 TiDB Cloud 与 ProxySQL 集成 -在这个集成中,你将使用 [ProxySQL Docker 镜像](https://hub.docker.com/r/proxysql/proxysql)以及 TiDB Cloud Serverless 集群。下面的步骤将在端口 `16033` 上设置 ProxySQL,请确保此端口可用。 +对于此集成,您将使用 [ProxySQL Docker 镜像](https://hub.docker.com/r/proxysql/proxysql)和 TiDB Cloud Serverless 集群。以下步骤将在端口 `16033` 上设置 ProxySQL,因此请确保此端口可用。 -#### 步骤 1. 创建一个 TiDB Cloud Serverless 集群 +#### 步骤 1. 创建 TiDB Cloud Serverless 集群 -1. 参考[创建一个 TiDB Cloud Serverless 集群](https://docs.pingcap.com/tidbcloud/tidb-cloud-quickstart#step-1-create-a-tidb-cluster)文档。记住为集群设置的 root 密码。 -2. 获取集群的 `hostname`、`port` 及 `username` 供后续使用。 +1. [创建一个免费的 TiDB Cloud Serverless 集群](https://docs.pingcap.com/tidbcloud/tidb-cloud-quickstart#step-1-create-a-tidb-cluster)。记住您为集群设置的 root 密码。 +2. 获取集群主机名、端口和用户名以供后续使用。 - 1. 在 [Clusters](https://tidbcloud.com/console/clusters) 页面,点击你的集群名称,进入集群概览页面。 - 2. 在集群概览页面的 **Connection** 面板中,复制 `Endpoint`、`Port` 与 `User` 字段,其中 `Endpoint` 是集群的 `hostname`。 + 1. 在[集群](https://tidbcloud.com/project/clusters)页面上,点击集群名称进入集群概览页面。 + 2. 在集群概览页面上,找到**连接**窗格,然后复制 `Endpoint`、`Port` 和 `User` 字段,其中 `Endpoint` 是您的集群主机名。 #### 步骤 2. 生成 ProxySQL 配置文件 -1. 克隆 TiDB 和 ProxySQL 的集成示例代码仓库 [`tidb-proxysql-integration`](https://github.com/pingcap-inc/tidb-proxysql-integration): +1. 克隆 TiDB 和 ProxySQL 的[集成示例代码仓库](https://github.com/pingcap-inc/tidb-proxysql-integration): @@ -161,7 +161,7 @@ systemctl start docker -2. 进入 `tidb-cloud-connect` 目录: +2. 切换到 `tidb-cloud-connect` 文件夹: @@ -221,9 +221,9 @@ systemctl start docker - 当出现提示时,输入集群的 `Endpoint` 作为 `Serverless Tier Host`,然后输入集群的 `Port` 与 `User`。 + 当出现提示时,输入集群的 `Serverless Tier Host` 端点,然后输入集群的用户名和密码。 - 下面是一个输出示例。可以看到,在当前的 `tidb-cloud-connect` 目录下生成了三个配置文件。 + 以下是示例输出。您将看到在当前 `tidb-cloud-connect` 文件夹下生成了三个配置文件。 ``` [Begin] generating configuration files.. @@ -235,13 +235,13 @@ systemctl start docker #### 步骤 3. 配置 ProxySQL -1. 启动 Docker。如果 Docker 已经启动,请跳过此步骤: +1. 启动 Docker。如果 Docker 已经启动,跳过此步骤:
- 双击已安装的 Docker 的图标来启动它。 + 双击已安装的 Docker 图标启动它。
@@ -255,13 +255,13 @@ systemctl start docker
- 双击已安装的 Docker 的图标来启动它。 + 双击已安装的 Docker 图标启动它。
-2. 拉取 ProxySQL 镜像,并在后台启动一个 ProxySQL 容器: +2. 拉取 ProxySQL 镜像并在后台启动 ProxySQL 容器: @@ -291,7 +291,7 @@ systemctl start docker -3. 运行以下命令集成 ProxySQL,该命令会在 **ProxySQL Admin Interface** 内执行 `proxysql-prepare.sql`: +3. 通过运行以下命令与 ProxySQL 集成,该命令在 **ProxySQL Admin Interface** 中执行 `proxysql-prepare.sql`: @@ -325,14 +325,14 @@ systemctl start docker > > `proxysql-prepare.sql` 脚本执行以下操作: > - > 1. 使用集群的用户名和密码添加一个 ProxySQL 用户。 - > 2. 将该用户分配给监控账户。 - > 3. 将你的 TiDB Cloud Serverless 集群添加到主机列表中。 - > 4. 在 ProxySQL 和 TiDB Cloud Serverless 集群之间启用安全连接。 + > 1. 使用集群的用户名和密码添加用户。 + > 2. 将用户分配给监控账户。 + > 3. 将您的 TiDB Cloud Serverless 集群添加到主机列表中。 + > 4. 启用 ProxySQL 和 TiDB Cloud Serverless 集群之间的安全连接。 > - > 为了更好地理解此处的配置流程,强烈建议查看 `proxysql-prepare.sql` 文件。关于 ProxySQL 配置的更多信息,参考 [ProxySQL 文档](https://proxysql.com/documentation/proxysql-configuration/)。 + > 强烈建议您查看 `proxysql-prepare.sql` 文件以更好地理解。要了解更多关于 ProxySQL 配置的信息,请参见 [ProxySQL 文档](https://proxysql.com/documentation/proxysql-configuration/)。 - 下面是一个输出示例。输出中显示集群的主机名,这意味着 ProxySQL 和 TiDB Cloud Serverless 集群之间的连接建立成功。 + 以下是示例输出。如果您看到集群的主机名显示在输出中,这意味着 ProxySQL 和 TiDB Cloud Serverless 集群之间的连接已建立。 ``` *************************** 1. row *************************** @@ -352,7 +352,7 @@ systemctl start docker #### 步骤 4. 通过 ProxySQL 连接到 TiDB 集群 -1. 运行 `proxysql-connect.py` 连接到你的 TiDB 集群。该脚本将自动启动 MySQL 客户端并使用你在[步骤 2](#步骤-2-生成-proxysql-配置文件) 中指定的用户名和密码进行连接。 +1. 要连接到 TiDB 集群,运行 `proxysql-connect.py`。该脚本将自动启动 MySQL 客户端,并使用您在[步骤 2](#步骤-2-生成-proxysql-配置文件)中指定的用户名和密码进行连接。 @@ -382,19 +382,19 @@ systemctl start docker -2. 连接 TiDB 集群后,可以使用以下 SQL 语句验证连接: +2. 连接到 TiDB 集群后,您可以使用以下 SQL 语句验证连接: ```sql SELECT VERSION(); ``` - 如果输出了 TiDB 的版本信息,则表示你已经成功通过 ProxySQL 连接到 TiDB Cloud Serverless 集群。如需退出 MySQL 客户端,输入 `quit` 并按下 Enter 键。 + 如果显示了 TiDB 版本,说明您已成功通过 ProxySQL 连接到 TiDB Cloud Serverless 集群。要随时退出 MySQL 客户端,输入 `quit` 并按 enter。 > **注意:** > - > **调试提示:** 如果无法连接到集群,请检查 `tidb-cloud-connect.cnf`、`proxysql-prepare.sql` 和 `proxysql-connect.py` 文件,确保你提供的服务器信息可用且正确。 + > ***调试提示:*** 如果无法连接到集群,请检查文件 `tidb-cloud-connect.cnf`、`proxysql-prepare.sql` 和 `proxysql-connect.py`。确保您提供的服务器信息可用且正确。 -3. 要停止和删除容器,并返回上一个目录,运行以下命令: +3. 要停止并删除容器,并返回上一个目录,运行以下命令: @@ -427,19 +427,19 @@ systemctl start docker -### 选项 2: 集成本地部署的 TiDB 与 ProxySQL +### 选项 2. 将 TiDB(自托管)与 ProxySQL 集成 -在这个集成中,你将使用 [TiDB](https://hub.docker.com/r/pingcap/tidb) 和 [ProxySQL](https://hub.docker.com/r/proxysql/proxysql) 的 Docker 镜像设置环境。你也可以尝试[其他方式安装 TiDB](/quick-start-with-tidb.md)。 +对于此集成,您将使用 [TiDB](https://hub.docker.com/r/pingcap/tidb) 和 [ProxySQL](https://hub.docker.com/r/proxysql/proxysql) 的 Docker 镜像设置环境。我们鼓励您尝试[其他安装 TiDB(自托管)的方式](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb)。 -下面的步骤将在端口 `6033` 和 `4000` 上分别设置 ProxySQL 和 TiDB,请确保这些端口可用。 +以下步骤将在端口 `6033` 和 `4000` 上分别设置 ProxySQL 和 TiDB,因此请确保这些端口可用。 -1. 启动 Docker。如果 Docker 已经启动,请跳过此步骤: +1. 启动 Docker。如果 Docker 已经启动,跳过此步骤:
- 双击已安装的 Docker 的图标来启动它。 + 双击已安装的 Docker 图标启动它。
@@ -453,13 +453,13 @@ systemctl start docker
- 双击已安装的 Docker 的图标来启动它。 + 双击已安装的 Docker 图标启动它。
-2. 克隆 TiDB 和 ProxySQL 的集成示例代码仓库 [`pingcap-inc/tidb-proxysql-integration`](https://github.com/pingcap-inc/tidb-proxysql-integration): +2. 克隆 TiDB 和 ProxySQL 的[集成示例代码仓库](https://github.com/pingcap-inc/tidb-proxysql-integration): @@ -489,7 +489,7 @@ systemctl start docker -3. 拉取 ProxySQL 和 TiDB 的最新镜像: +3. 拉取最新的 ProxySQL 和 TiDB 镜像: @@ -519,7 +519,7 @@ systemctl start docker -4. 使用 TiDB 和 ProxySQL 容器启动一个集成环境: +4. 使用 TiDB 和 ProxySQL 作为容器启动集成环境: @@ -549,7 +549,7 @@ systemctl start docker - 你可以使用 `root` 用户名及空密码登录到 ProxySQL 的 `6033` 端口。 + 要登录到 ProxySQL 的 `6033` 端口,您可以使用 `root` 用户名和空密码。 5. 通过 ProxySQL 连接到 TiDB: @@ -581,15 +581,15 @@ systemctl start docker
-6. 连接 TiDB 集群后,可以使用以下 SQL 语句验证连接: +6. 连接到 TiDB 集群后,您可以使用以下 SQL 语句验证连接: ```sql SELECT VERSION(); ``` - 如果输出了 TiDB 的版本信息,则表示你已经成功通过 ProxySQL 连接到 TiDB 集群。 + 如果显示了 TiDB 版本,说明您已成功通过 ProxySQL 连接到 TiDB 容器。 -7. 要停止和删除容器,并返回上一个目录,运行以下命令: +7. 要停止并删除容器,并返回上一个目录,运行以下命令: @@ -624,21 +624,21 @@ systemctl start docker ## 生产环境 -对于生产环境,建议直接使用 [TiDB Cloud Dedicated](https://www.pingcap.com/tidb-dedicated/) 以获得完全托管的体验。 +对于生产环境,建议您直接使用 [TiDB Cloud Dedicated](https://www.pingcap.com/tidb-cloud-dedicated/) 以获得完全托管的体验。 ### 前提条件 -下载并安装一个 MySQL 客户端。例如,[MySQL Shell](https://dev.mysql.com/downloads/shell/)。 +下载并安装 MySQL 客户端。例如,[MySQL Shell](https://dev.mysql.com/downloads/shell/)。 -### 基于 CentOS 集成 TiDB Cloud 与 ProxySQL +### 在 CentOS 上将 TiDB Cloud 与 ProxySQL 集成 -你可以在不同的平台上安装 ProxySQL,下面以 CentOS 为例进行说明。 +ProxySQL 可以安装在多个不同的平台上。以下以 CentOS 为例。 -关于 ProxySQL 支持的平台和版本要求的完整列表,见 [ProxySQL 文档](https://proxysql.com/documentation/installing-proxysql/)。 +有关支持的平台和相应版本要求的完整列表,请参见 [ProxySQL 文档](https://proxysql.com/documentation/installing-proxysql/)。 -#### 步骤 1. 创建一个 TiDB Cloud Dedicated 集群 +#### 步骤 1. 创建 TiDB Cloud Dedicated 集群 -具体步骤请参考[创建一个 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster)。 +有关详细步骤,请参见[创建 TiDB 集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster)。 #### 步骤 2. 安装 ProxySQL @@ -666,463 +666,13 @@ systemctl start docker systemctl start proxysql ``` -要了解更多关于 ProxySQL 支持的平台及其安装方法,参考 [ProxySQL README](https://github.com/sysown/proxysql#installation) 或 [ProxySQL 安装文档](https://proxysql.com/documentation/installing-proxysql/)。 +要了解更多关于 ProxySQL 支持的平台及其安装的信息,请参考 [ProxySQL README](https://github.com/sysown/proxysql#installation) 或 [ProxySQL 安装文档](https://proxysql.com/documentation/installing-proxysql/)。 #### 步骤 3. 配置 ProxySQL -为了使用 ProxySQL 作为 TiDB 的代理,你需要配置 ProxySQL。你可以[在 ProxySQL Admin Interface 中执行 SQL 语句](#选项-1-使用-admin-interface-配置-proxysql)(推荐)或[使用配置文件](#选项-2-使用配置文件配置-proxysql)进行配置。 +要将 ProxySQL 用作 TiDB 的代理,您需要配置 ProxySQL。为此,您可以选择[在 ProxySQL Admin Interface 中执行 SQL 语句](#选项-1-使用管理界面配置-proxysql)(推荐)或使用[配置文件](#选项-2-使用配置文件配置-proxysql)。 > **注意:** > -> 以下章节仅列出 ProxySQL 的必要配置项。 -> -> 完整的配置信息,可参考 [ProxySQL 文档](https://proxysql.com/documentation/proxysql-configuration/)。 - -##### 选项 1: 使用 Admin Interface 配置 ProxySQL - -1. 使用标准的 ProxySQL Admin Interface 更新 ProxySQL 的配置。你可以通过任何 MySQL 命令行客户端访问(默认端口为 `6032`)。 - - ```bash - mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt 'ProxySQL Admin> ' - ``` - - 执行以上命令后,系统将显示 `'ProxySQL Admin'` 提示。 - -2. 你可以在当前 MySQL 命令行客户端中向 ProxySQL 添加一个或多个 TiDB 集群。例如,下面的语句将添加一个 TiDB Cloud Dedicated 集群。你需要用集群的 `Endpoint` 和 `Port` 替换 `` 和 ``(默认端口为 `4000`)。 - - ```sql - INSERT INTO mysql_servers(hostgroup_id, hostname, port) - VALUES - ( - 0, - '', - - ); - LOAD mysql servers TO runtime; - SAVE mysql servers TO DISK; - ``` - - > **注意:** - > - > - `hostgroup_id`:指定一个 **hostgroup** 的 ID。ProxySQL 使用 **hostgroup** 管理集群。如果需要将 SQL 流量均匀地分配给这些集群,你可以将需要负载均衡的几个 TiDB 集群配置到同一个 **hostgroup** 中。另一方面,为了区分不同的集群,例如为了实现读写分离,你可以将它们配置为不同的 **hostgroup** ID。 - > - `hostname`:TiDB 集群的 `Endpoint`。 - > - `port`:TiDB 集群的 `Port`。 - -3. 为配置 ProxySQL 的登录用户,你需要确保用户在 TiDB 集群上有适当的权限。在下面的语句中,你需要把 `` 和 `` 替换为集群的实际用户名和密码。 - - ```sql - INSERT INTO mysql_users( - username, password, active, default_hostgroup, - transaction_persistent - ) - VALUES - ( - '', - '', - 1, 0, 1 - ); - LOAD mysql users TO runtime; - SAVE mysql users TO DISK; - ``` - - > **注意:** - > - > - `username`:TiDB 用户名。 - > - `password`:TiDB 密码。 - > - `active`:指定用户是否处于激活状态。`1` 表示该用户是**激活的**,可以用于登录,`0` 表示该用户是非激活的。 - > - `default_hostgroup`:用户使用的默认 `hostgroup`,除非特定的查询规则覆盖了 `hostgroup`,否则 SQL 将会默认路由到 `default_hostgroup`。 - > - `transaction_persistent`:值为 `1` 表示使用持久性事务。即当用户在一个连接中启动一个事务时,所有的查询语句都被路由到同一个 `hostgroup`,直到事务被提交或回滚。 - -##### 选项 2: 使用配置文件配置 ProxySQL - -这个选项只能作为配置 ProxySQL 的备用方案。更多信息,可参考[使用配置文件配置 ProxySQL](https://github.com/sysown/proxysql#configuring-proxysql-through-the-config-file)。 - -1. 删除现有的 SQLite 数据库,即 ProxySQL 存储配置的位置。 - - ```bash - rm /var/lib/proxysql/proxysql.db - ``` - - > **警告:** - > - > 删除 SQLite 数据库后,通过 ProxySQL Admin Interface 所做的任何配置更改都会丢失。 - -2. 根据你的需要修改配置文件 `/etc/proxysql.cnf`。例如: - - ``` - mysql_servers: - ( - { - address="" - port= - hostgroup=0 - max_connections=2000 - } - ) - - mysql_users: - ( - { - username = "" - password = "" - default_hostgroup = 0 - max_connections = 1000 - default_schema = "test" - active = 1 - transaction_persistent = 1 - } - ) - ``` - - 在上面的例子中: - - - `address` 和 `port` 用于指定你的 TiDB Cloud 集群的 `Endpoint` 和 `Port`。 - - `username` 和 `password` 用于指定你的 TiDB Cloud 集群的用户名和密码。 - -3. 重启 ProxySQL: - - ```bash - systemctl restart proxysql - ``` - - 重新启动后,ProxySQL 将自动创建 SQLite 数据库。 - -> **警告:** -> -> 在生产环境中,不要使用默认的管理员用户运行 ProxySQL。在启动 `proxysql` 服务之前,你可以通过修改 [`admin_credentials`](https://proxysql.com/documentation/global-variables/admin-variables/#admin-admin_credentials) 变量更改 `/etc/proxysql.cnf` 文件中的默认值。 - -## 典型场景 - -本节以查询规则为例,介绍集成 TiDB 与 ProxySQL 能带来的一些优势。 - -### 查询规则 - -数据库可能会因为高流量、错误代码或恶意攻击而过载。因此,审核 SQL 是必要的。使用 ProxySQL 的查询规则,你可以有效地应对这些问题,例如通过重路由、改写 SQL 或者拒绝查询等方式。 - -![proxysql-client-side-rules](/media/develop/proxysql-client-side-rules.png) - -> **注意:** -> -> 以下步骤使用 TiDB 和 ProxySQL 的容器镜像配置查询规则。如果你还没有拉取这些镜像,请参考[集成本地部署的 TiDB 与 ProxySQL](#选项-2-集成本地部署的-tidb-与-proxysql) 部分的详细步骤。 - -1. 克隆 TiDB 和 ProxySQL 的集成示例代码仓库 [`pingcap-inc/tidb-proxysql-integration`](https://github.com/pingcap-inc/tidb-proxysql-integration)。如果你已经在前面的步骤中克隆了它,请跳过这一步。 - - - -
- - ```bash - git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git - ``` - -
- -
- - ```bash - git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git - ``` - -
- -
- - ```bash - git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git - ``` - -
- -
- -2. 进入 ProxySQL 查询规则的示例目录: - - - -
- - ```bash - cd tidb-proxysql-integration/example/proxy-rule-admin-interface - ``` - -
- -
- - ```bash - cd tidb-proxysql-integration/example/proxy-rule-admin-interface - ``` - -
- -
- - ```bash - cd tidb-proxysql-integration/example/proxy-rule-admin-interface - ``` - -
- -
- -3. 运行下面的命令启动两个 TiDB 容器和一个 ProxySQL 容器: - - - -
- - ```bash - docker compose up -d - ``` - -
- -
- - ```bash - docker compose up -d - ``` - -
- -
- - ```bash - docker compose up -d - ``` - -
- -
- - 如果运行成功,以下容器将被启动: - - - 两个 Docker 容器的 TiDB 集群,端口分别为 `4001` 和 `4002` - - 一个 Docker 容器的 ProxySQL,端口为 `6034` - -4. 在两个 TiDB 容器中,使用 `mysql` 创建一个具有相同 schema 的表,然后插入不同的数据 (`'tidb-server01-port-4001'`, `'tidb-server02-port-4002'`) 以区分这两个容器。 - - - -
- - ```bash - mysql -u root -h 127.0.0.1 -P 4001 << EOF - DROP TABLE IF EXISTS test.tidb_server; - CREATE TABLE test.tidb_server (server_name VARCHAR(255)); - INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server01-port-4001'); - EOF - - mysql -u root -h 127.0.0.1 -P 4002 << EOF - DROP TABLE IF EXISTS test.tidb_server; - CREATE TABLE test.tidb_server (server_name VARCHAR(255)); - INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server02-port-4002'); - EOF - ``` - -
- -
- - ```bash - mysql -u root -h 127.0.0.1 -P 4001 << EOF - DROP TABLE IF EXISTS test.tidb_server; - CREATE TABLE test.tidb_server (server_name VARCHAR(255)); - INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server01-port-4001'); - EOF - - mysql -u root -h 127.0.0.1 -P 4002 << EOF - DROP TABLE IF EXISTS test.tidb_server; - CREATE TABLE test.tidb_server (server_name VARCHAR(255)); - INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server02-port-4002'); - EOF - ``` - -
- -
- - ```bash - mysql -u root -h 127.0.0.1 -P 4001 << EOF - DROP TABLE IF EXISTS test.tidb_server; - CREATE TABLE test.tidb_server (server_name VARCHAR(255)); - INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server01-port-4001'); - EOF - - mysql -u root -h 127.0.0.1 -P 4002 << EOF - DROP TABLE IF EXISTS test.tidb_server; - CREATE TABLE test.tidb_server (server_name VARCHAR(255)); - INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server02-port-4002'); - EOF - ``` - -
- -
- -5. 运行下面的命令配置 ProxySQL,该命令会在 ProxySQL Admin Interface 中执行 `proxysql-prepare.sql`,从而在 TiDB 容器和 ProxySQL 之间建立一个代理连接。 - - - -
- - ```bash - docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql" - ``` - -
- -
- - ```bash - docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql" - ``` - -
- -
- - ```bash - docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql" - ``` - -
- -
- - > **注意:** - > - > `proxysql-prepare.sql` 脚本完成以下操作: - > - > - 在 ProxySQL 中添加 TiDB 集群,`hostgroup_id` 分别为 `0` 和 `1`。 - > - 添加一个用户 `root`,密码为空,并设置 `default_hostgroup` 为 `0`。 - > - 添加规则 `^SELECT.*FOR UPDATE$`,`rule_id` 为 `1`,`destination_hostgroup` 为 `0`。这代表如果一个 SQL 语句与此规则相匹配,该请求将被转发到 `hostgroup` 为 `0` 的 TiDB 集群。 - > - 添加规则 `^SELECT`,`rule_id` 为 `2`,`destination_hostgroup` 为 `1`。这代表如果一个 SQL 语句与此规则相匹配,该请求将被转发到 `hostgroup` 为 `1` 的 TiDB 集群。 - > - > 为了更好地理解此处的配置流程,强烈建议查看 `proxysql-prepare.sql` 文件。关于 ProxySQL 配置的更多信息,参考 [ProxySQL 文档](https://proxysql.com/documentation/proxysql-configuration/)。 - - 下面是关于 ProxySQL 匹配 SQL 查询的规则的一些补充信息: - - - ProxySQL 尝试按照 `rule_id` 的升序逐一匹配规则。 - - 规则中的 `^` 符号用于匹配 SQL 语句的开头,`$` 符号用于匹配语句的结尾。 - - 关于 ProxySQL 正则表达式和模式匹配的更多信息,参考 ProxySQL 文档 [`mysql-query_processor_regex`](https://proxysql.com/documentation/global-variables/mysql-variables/#mysql-query_processor_regex)。 - - 关于完整的参数列表,参考 ProxySQL 文档 [`mysql_query_rules`](https://proxysql.com/documentation/main-runtime/#mysql_query_rules)。 - -6. 验证配置并检查查询规则是否有效。 - - 1. 使用 `root` 用户登录 ProxySQL MySQL Interface: - - - -
- - ```bash - mysql -u root -h 127.0.0.1 -P 6034 - ``` - -
- -
- - ```bash - mysql -u root -h 127.0.0.1 -P 6034 - ``` - -
- -
- - ```bash - mysql -u root -h 127.0.0.1 -P 6034 - ``` - -
- -
- - 2. 执行以下 SQL 语句: - - - 执行一个 `SELECT` 语句: - - ```sql - SELECT * FROM test.tidb_server; - ``` - - 这个语句将匹配 `rule_id` 为 `2` 的规则,因此将转发语句到 `hostgroup` 为 `1` 上的 TiDB 集群中。 - - - 执行一个 `SELECT ... FOR UPDATE` 语句: - - ```sql - SELECT * FROM test.tidb_server FOR UPDATE; - ``` - - 这个语句将匹配 `rule_id` 为 `1` 的规则,因此将转发语句到 `hostgroup` 为 `0` 上的 TiDB 集群中。 - - - 启动一个事务: - - ```sql - BEGIN; - INSERT INTO test.tidb_server (server_name) VALUES ('insert this and rollback later'); - SELECT * FROM test.tidb_server; - ROLLBACK; - ``` - - 在这个事务中,`BEGIN` 语句将不会匹配任何规则。因此,它将使用默认的 `hostgroup`(在这个例子中为 `hostgroup 0`)。因为 ProxySQL 默认启用了用户 transaction_persistent,它将在同一事务中,将所有语句都转发至相同的 `hostgroup`,所以 `INSERT` 和 `SELECT * FROM test.tidb_server;` 语句也将被转发到 `hostgroup` 为 `0` 的 TiDB 集群。 - - 下面是一个输出示例。如果你得到类似的输出,表示你已经成功配置了 ProxySQL 的查询规则。 - - ```sql - +-------------------------+ - | server_name | - +-------------------------+ - | tidb-server02-port-4002 | - +-------------------------+ - +-------------------------+ - | server_name | - +-------------------------+ - | tidb-server01-port-4001 | - +-------------------------+ - +--------------------------------+ - | server_name | - +--------------------------------+ - | tidb-server01-port-4001 | - | insert this and rollback later | - +--------------------------------+ - ``` - - 3. 如需退出 MySQL 客户端,输入 `quit` 并按下 Enter 键。 - -7. 要停止和删除容器,并返回上一个目录,运行以下命令: - - - -
- - ```bash - docker compose down - cd - - ``` - -
- -
- - ```bash - docker compose down - cd - - ``` - -
- -
- - ```bash - docker compose down - cd - - ``` - -
- -
\ No newline at end of file +> 以下部分仅列出了 ProxySQL 的必需配置项。 +> 有关配置的完整列表,请参见 [ProxySQL 文档](https://proxysql.com/documentation/proxysql-configuration/)。 diff --git a/develop/dev-guide-sample-application-aws-lambda.md b/develop/dev-guide-sample-application-aws-lambda.md index 4916d71c6134..ac6f3aa447fe 100644 --- a/develop/dev-guide-sample-application-aws-lambda.md +++ b/develop/dev-guide-sample-application-aws-lambda.md @@ -1,96 +1,108 @@ --- -title: 在 AWS Lambda 函数中使用 mysql2 连接到 TiDB -summary: 本文介绍如何在 AWS Lambda 函数中使用 TiDB 和 mysql2 构建一个 CRUD 应用程序,并给出了简单示例代码片段。 +title: 在 AWS Lambda 函数中使用 mysql2 连接 TiDB +summary: 本文介绍如何在 AWS Lambda 函数中使用 TiDB 和 mysql2 构建 CRUD 应用程序,并提供简单的示例代码片段。 --- -# 在 AWS Lambda 函数中使用 mysql2 连接到 TiDB +# 在 AWS Lambda 函数中使用 mysql2 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[AWS Lambda 函数](https://aws.amazon.com/lambda/)是一个计算服务,[mysql2](https://github.com/sidorares/node-mysql2) 是当前流行的开源 Node.js Driver 之一。 +TiDB 是一个兼容 MySQL 的数据库,[AWS Lambda 函数](https://aws.amazon.com/lambda/)是一个计算服务,而 [mysql2](https://github.com/sidorares/node-mysql2) 是一个流行的 Node.js 开源驱动程序。 -本文档将展示如何在 AWS Lambda 函数中使用 TiDB 和 mysql2 来完成以下任务: +在本教程中,您可以学习如何在 AWS Lambda 函数中使用 TiDB 和 mysql2 完成以下任务: -- 配置你的环境。 -- 使用 mysql2 驱动连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 -- 部署你的 AWS Lambda 函数。 +- 设置环境。 +- 使用 mysql2 连接到 TiDB 集群。 +- 构建并运行应用程序。您也可以查看[示例代码片段](#示例代码片段),了解基本的 CRUD 操作。 +- 部署 AWS Lambda 函数。 -> **Note** +> **注意** > -> 本文档适用于 TiDB Cloud Serverless 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本教程,你需要提前: +要完成本教程,您需要: -- 在你的机器上安装 [Node.js](https://nodejs.org/en) 18.x 或以上版本。 -- 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 -- 准备一个具有管理员权限的 [AWS IAM 用户](https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_users.html)。 -- 在你的机器上安装 [AWS CLI](https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/getting-started-install.html)。 -- 在你的机器上安装 [AWS SAM CLI](https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/install-sam-cli.html)。 +- [Node.js **18**](https://nodejs.org/en/download/) 或更高版本。 +- [Git](https://git-scm.com/downloads)。 +- 一个 TiDB 集群。 +- 一个具有管理员权限的 [AWS 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html)。 +- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) +- [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) -如果你还没有 TiDB 集群,可以按照以下方式创建: + -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -如果你还没有 AWS 账户或用户,可以按照 [Lambda 入门](https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/getting-started.html)文档中的步骤来创建它们。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 -## 运行代码并连接到 TiDB + + -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -> **Note** +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 + + + +如果您没有 AWS 账号或用户,可以按照 [Lambda 入门](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html)指南中的步骤创建。 + +## 运行示例程序连接 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +> **注意** > -> 完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-aws-lambda-quickstart](https://github.com/tidb-samples/tidb-aws-lambda-quickstart)。 +> 有关完整的代码片段和运行说明,请参考 [tidb-samples/tidb-aws-lambda-quickstart](https://github.com/tidb-samples/tidb-aws-lambda-quickstart) GitHub 仓库。 -### 第 1 步:克隆示例代码仓库到本地 +### 步骤 1:克隆示例程序仓库 -运行以下命令,将示例代码仓库克隆到本地: +在终端窗口中运行以下命令来克隆示例代码仓库: ```bash git clone git@github.com:tidb-samples/tidb-aws-lambda-quickstart.git cd tidb-aws-lambda-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 mysql2): +运行以下命令安装示例应用程序所需的包(包括 `mysql2`): ```bash npm install ``` -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到 TiDB 集群。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的选项配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为运行示例代码所在的操作系统。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Note** + > **注意** > - > 在 Node.js 应用程序中,你无需提供 SSL CA 证书,因为在建立 TLS (SSL) 连接时,默认情况下 Node.js 使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates)。 + > 在 Node.js 应用程序中,您不必提供 SSL CA 证书,因为 Node.js 在建立 TLS (SSL) 连接时默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates)。 -4. 如果你还没有设置密码,点击 **Generate Password** 按钮生成一个随机的密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip** + > **提示** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经生成了密码,可以使用原始密码或点击**重置密码**生成新密码。 -5. 编辑 `env.json` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +5. 将相应的连接字符串复制并粘贴到 `env.json` 中。示例如下: ```json { @@ -103,11 +115,13 @@ npm install } ``` + 将 `{}` 中的占位符替换为连接对话框中获得的值。 +
-
+
-编辑 `env.json` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为你的 TiDB 集群的连接参数值: +将相应的连接字符串复制并粘贴到 `env.json` 中。示例如下: ```json { @@ -120,15 +134,17 @@ npm install } ``` +将 `{}` 中的占位符替换为**连接**窗口中获得的值。 +
-### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -1. (前置需求)安装 [AWS SAM CLI](https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/install-sam-cli.html)。 +1. (前提条件)安装 [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)。 -2. 构建应用程序包: +2. 构建打包: ```bash npm run build @@ -140,29 +156,29 @@ npm install sam local invoke --env-vars env.json -e events/event.json "tidbHelloWorldFunction" ``` -4. 检查终端中的输出。如果输出类似于以下内容,则表示连接成功: +4. 检查终端中的输出。如果输出类似于以下内容,则连接成功: ```bash {"statusCode":200,"body":"{\"results\":[{\"Hello World\":\"Hello World\"}]}"} ``` -确认连接成功后,你可以按照[部署 AWS Lambda 函数](#部署-aws-lambda-函数)中的步骤进行部署。 +确认连接成功后,您可以按照[下一节](#部署-aws-lambda-函数)部署 AWS Lambda 函数。 ## 部署 AWS Lambda 函数 -你可以通过 [SAM CLI](#通过-sam-cli-部署推荐) 或 [AWS Lambda 控制台](#通过网页控制台部署)部署 AWS Lambda 函数。 +您可以使用 [SAM CLI](#sam-cli-部署推荐) 或 [AWS Lambda 控制台](#web-控制台部署)部署 AWS Lambda 函数。 -### 通过 SAM CLI 部署(推荐) +### SAM CLI 部署(推荐) -1. ([前置需求](#前置需求))安装 [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)。 +1. ([前提条件](#前提条件))安装 [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)。 -2. 构建应用程序包: +2. 构建打包: ```bash npm run build ``` -3. 更新 [`template.yml`](https://github.com/tidb-samples/tidb-aws-lambda-quickstart/blob/main/template.yml) 文件中的环境变量: +3. 更新 [`template.yml`](https://github.com/tidb-samples/tidb-aws-lambda-quickstart/blob/main/template.yml) 中的环境变量: ```yaml Environment: @@ -173,7 +189,7 @@ npm install TIDB_PASSWORD: {password} ``` -4. 参考[使用短期凭证进行身份验证](https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/cli-authentication-short-term.html)文档,设置 AWS 环境变量: +4. 设置 AWS 环境变量(参考[短期凭证](https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-short-term.html)): ```bash export AWS_ACCESS_KEY_ID={your_access_key_id} @@ -186,7 +202,7 @@ npm install ```bash sam deploy --guided - # Example: + # 示例: # Configuring SAM deploy # ====================== @@ -216,9 +232,9 @@ npm install # Successfully created! ``` -### 通过网页控制台部署 +### Web 控制台部署 -1. 构建应用程序包: +1. 构建打包: ```bash npm run build @@ -230,31 +246,30 @@ npm install 2. 访问 [AWS Lambda 控制台](https://console.aws.amazon.com/lambda/home#/functions)。 -3. 按照[使用 Node.js 构建 Lambda 函数](https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/lambda-nodejs.html)中的步骤创建一个 Node.js Lambda 函数。 +3. 按照[创建 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html)中的步骤创建一个 Node.js Lambda 函数。 -4. 按照 [Lambda 部署程序包](https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/gettingstarted-package.html#gettingstarted-package-zip)中的步骤,上传 `dist/index.zip` 文件。 +4. 按照 [Lambda 部署包](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html#gettingstarted-package-zip)中的步骤上传 `dist/index.zip` 文件。 -5. 在 Lambda 函数中[复制并配置相应的连接字符串](https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/configuration-envvars.html)。 - - 1. 在 Lambda 控制台的[**函数**](https://console.aws.amazon.com/lambda/home#/functions)页面中,选择**配置** > **环境变量**。 - 2. 点击**编辑**。 - 3. 按照以下步骤添加数据库访问凭证: +5. [复制并配置相应的连接字符串](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html)到 Lambda 函数中。 + 1. 在 Lambda 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面中,选择**配置**标签,然后选择**环境变量**。 + 2. 选择**编辑**。 + 3. 要添加数据库访问凭证,请执行以下操作: - 选择**添加环境变量**,然后在**键**中输入 `TIDB_HOST`,在**值**中输入主机名。 - - 选择**添加环境变量**,然后在**键**中输入 `TIDB_PORT`,在**值**中输入端口号(默认 `4000`)。 + - 选择**添加环境变量**,然后在**键**中输入 `TIDB_PORT`,在**值**中输入端口(默认为 4000)。 - 选择**添加环境变量**,然后在**键**中输入 `TIDB_USER`,在**值**中输入用户名。 - - 选择**添加环境变量**,然后在**键**中输入 `TIDB_PASSWORD`,在**值**中输入数据库的密码。 - - 点击**保存**。 + - 选择**添加环境变量**,然后在**键**中输入 `TIDB_PASSWORD`,在**值**中输入创建数据库时选择的密码。 + - 选择**保存**。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-aws-lambda-quickstart](https://github.com/tidb-samples/tidb-aws-lambda-quickstart)。 +有关完整的示例代码和运行方法,请查看 [tidb-samples/tidb-aws-lambda-quickstart](https://github.com/tidb-samples/tidb-aws-lambda-quickstart) 仓库。 ### 连接到 TiDB -下面的代码使用环境变量中定义的连接选项来建立与 TiDB 集群的连接。 +以下代码使用环境变量中定义的选项建立与 TiDB 的连接: ```typescript // lib/tidb.ts @@ -264,17 +279,17 @@ let pool: mysql.Pool | null = null; function connect() { return mysql.createPool({ - host: process.env.TIDB_HOST, // TiDB host, for example: {gateway-region}.aws.tidbcloud.com - port: process.env.TIDB_PORT ? Number(process.env.TIDB_PORT) : 4000, // TiDB port, default: 4000 - user: process.env.TIDB_USER, // TiDB user, for example: {prefix}.root - password: process.env.TIDB_PASSWORD, // TiDB password - database: process.env.TIDB_DATABASE || 'test', // TiDB database name, default: test + host: process.env.TIDB_HOST, // TiDB 主机,例如:{gateway-region}.aws.tidbcloud.com + port: process.env.TIDB_PORT ? Number(process.env.TIDB_PORT) : 4000, // TiDB 端口,默认:4000 + user: process.env.TIDB_USER, // TiDB 用户,例如:{prefix}.root + password: process.env.TIDB_PASSWORD, // TiDB 密码 + database: process.env.TIDB_DATABASE || 'test', // TiDB 数据库名称,默认:test ssl: { minVersion: 'TLSv1.2', rejectUnauthorized: true, }, - connectionLimit: 1, // Setting connectionLimit to "1" in a serverless function environment optimizes resource usage, reduces costs, ensures connection stability, and enables seamless scalability. - maxIdle: 1, // max idle connections, the default value is the same as `connectionLimit` + connectionLimit: 1, // 在无服务器函数环境中将 connectionLimit 设置为 "1" 可以优化资源使用,降低成本,确保连接稳定性,并实现无缝扩展。 + maxIdle: 1, // 最大空闲连接数,默认值与 `connectionLimit` 相同 enableKeepAlive: true, }); } @@ -289,29 +304,29 @@ export function getPool(): mysql.Pool { ### 插入数据 -下面的查询会创建一条单独的 `Player` 记录,并返回一个 `ResultSetHeader` 对象: +以下查询创建一个 `Player` 记录并返回一个 `ResultSetHeader` 对象: ```typescript const [rsh] = await pool.query('INSERT INTO players (coins, goods) VALUES (?, ?);', [100, 100]); console.log(rsh.insertId); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -下面的查询会返回一条 `Player` 记录,其 ID 为 `1`: +以下查询返回 ID 为 `1` 的单个 `Player` 记录: ```typescript const [rows] = await pool.query('SELECT id, coins, goods FROM players WHERE id = ?;', [1]); console.log(rows[0]); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -下面的查询会将 ID 为 `1` 的 `Player` 记录的 `coins` 和 `goods` 字段的值分别增加 `50`: +以下查询为 ID 为 `1` 的 `Player` 添加 `50` 个金币和 `50` 个物品: ```typescript const [rsh] = await pool.query( @@ -321,35 +336,45 @@ const [rsh] = await pool.query( console.log(rsh.affectedRows); ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -下面的查询会删除一条 `Player` 记录,其 ID 为 `1`: +以下查询删除 ID 为 `1` 的 `Player` 记录: ```typescript const [rsh] = await pool.query('DELETE FROM players WHERE id = ?;', [1]); console.log(rsh.affectedRows); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 -- 推荐使用[连接池](https://github.com/sidorares/node-mysql2#using-connection-pools)来管理数据库连接,以减少频繁建立和销毁连接所带来的性能开销。 -- 为了避免 SQL 注入的风险,推荐使用[预处理语句](https://github.com/sidorares/node-mysql2#using-prepared-statements)执行 SQL。 -- 在不涉及大量复杂 SQL 语句的场景下,推荐使用 ORM 框架(例如:[Sequelize](https://sequelize.org/)、[TypeORM](https://typeorm.io/) 或 [Prisma](https://www.prisma.io/))来提升你的开发效率。 -- 如需为你的应用程序构建一个 RESTful API,建议[将 AWS Lambda 与 Amazon API Gateway 结合使用](https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/services-apigateway.html)。 -- 关于使用 TiDB Cloud Serverless 和 AWS Lambda 设计高性能应用程序的更多信息,可以参考[这篇博客](https://aws.amazon.com/blogs/apn/designing-high-performance-applications-using-serverless-tidb-cloud-and-aws-lambda/)。 +- 使用[连接池](https://github.com/sidorares/node-mysql2#using-connection-pools)管理数据库连接可以减少频繁建立和销毁连接带来的性能开销。 +- 为了避免 SQL 注入,建议使用[预处理语句](https://github.com/sidorares/node-mysql2#using-prepared-statements)。 +- 在不涉及太多复杂 SQL 语句的场景中,使用 [Sequelize](https://sequelize.org/)、[TypeORM](https://typeorm.io/) 或 [Prisma](https://www.prisma.io/) 等 ORM 框架可以大大提高开发效率。 +- 要为应用程序构建 RESTful API,建议[将 AWS Lambda 与 API Gateway 结合使用](https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html)。 +- 有关使用 TiDB Cloud Serverless 和 AWS Lambda 设计高性能应用程序,请参考[此博客](https://aws.amazon.com/blogs/apn/designing-high-performance-applications-using-serverless-tidb-cloud-and-aws-lambda/)。 ## 下一步 -- 关于在 AWS Lambda 函数中使用 TiDB 的更多细节,可以参考 [`TiDB-Lambda-integration/aws-lambda-bookstore` 示例程序](https://github.com/pingcap/TiDB-Lambda-integration/blob/main/aws-lambda-bookstore/README.md)。你也可以使用 AWS API Gateway 为你的应用程序构建 RESTful API。 -- 关于 mysql2 的更多使用方法,可以参考 [mysql2 的官方文档](https://sidorares.github.io/node-mysql2/zh-CN/docs)。 -- 关于 AWS Lambda 的更多使用方法,可以参考 [AWS Lambda 开发者指南](https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/welcome.html)。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 有关如何在 AWS Lambda 函数中使用 TiDB 的更多详细信息,请参见我们的 [TiDB-Lambda-integration/aws-lambda-bookstore Demo](https://github.com/pingcap/TiDB-Lambda-integration/blob/main/aws-lambda-bookstore/README.md)。您还可以使用 AWS API Gateway 为您的应用程序构建 RESTful API。 +- 从 [`mysql2` 文档](https://sidorares.github.io/node-mysql2/docs/documentation)了解更多 `mysql2` 的用法。 +- 从 [`Lambda` 的 AWS 开发者指南](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html)了解更多 AWS Lambda 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,或从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。 + diff --git a/develop/dev-guide-sample-application-golang-gorm.md b/develop/dev-guide-sample-application-golang-gorm.md index 76220ef177ca..37db70b17e7b 100644 --- a/develop/dev-guide-sample-application-golang-gorm.md +++ b/develop/dev-guide-sample-application-golang-gorm.md @@ -1,141 +1,155 @@ --- -title: 使用 GORM 连接到 TiDB -summary: 了解如何使用 GORM 连接到 TiDB。本文提供了使用 GORM 与 TiDB 交互的 Golang 示例代码片段。 +title: 使用 GORM 连接 TiDB +summary: 了解如何使用 GORM 连接 TiDB。本教程提供使用 GORM 操作 TiDB 的 Golang 示例代码片段。 --- -# 使用 GORM 连接到 TiDB +# 使用 GORM 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[GORM](https://gorm.io/index.html) 是当前比较流行的开源 Golang ORM 框架并且适配了 TiDB 的 `AUTO_RANDOM` 等特性。同时,TiDB 为 [GORM 的默认支持数据库](https://gorm.io/zh_CN/docs/connecting_to_the_database.html#TiDB)。 +TiDB 是一个兼容 MySQL 的数据库,而 [GORM](https://gorm.io/index.html) 是一个流行的 Golang ORM 框架。GORM 适配了 TiDB 的特性,如 `AUTO_RANDOM`,并[将 TiDB 作为默认数据库选项支持](https://gorm.io/docs/connecting_to_the_database.html#TiDB)。 -本文档将展示如何使用 TiDB 和 GORM 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 GORM 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 GORM 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看[示例代码片段](#示例代码片段),了解基本的 CRUD 操作。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -- 推荐 [Go](https://go.dev/) **1.20** 及以上版本。 +要完成本教程,您需要: + +- [Go](https://go.dev/) **1.20** 或更高版本。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -## 运行代码并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + -### 第 1 步:克隆示例代码仓库到本地 +## 运行示例程序连接 TiDB -运行以下命令,将示例代码仓库克隆到本地: +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: ```shell git clone https://github.com/tidb-samples/tidb-golang-gorm-quickstart.git cd tidb-golang-gorm-quickstart ``` -### 第 2 步:配置连接信息 +### 步骤 2:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经创建了密码,可以使用原始密码或点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. gateway01.ap-northeast-1.prod.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 xxxxxx.root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' USE_SSL='true' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 - TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此 `USE_SSL` 的值应为 `true`。 + TiDB Cloud Serverless 需要安全连接。因此,您需要将 `USE_SSL` 的值设置为 `true`。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. tidb.xxxx.clusters.tidb-cloud.com + TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. root + TIDB_USER='{user}' # 例如 root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv TIDB_HOST='{host}' @@ -146,29 +160,28 @@ cd tidb-golang-gorm-quickstart USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并设置 `USE_SSL` 为 `false`。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并将 `USE_SSL` 设置为 `false`。如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 3 步:运行代码并查看结果 +### 步骤 3:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: ```shell make ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-golang-gorm-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-golang-gorm-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-golang-gorm-quickstart](https://github.com/tidb-samples/tidb-golang-gorm-quickstart)。 +有关完整的示例代码和运行方法,请查看 [tidb-samples/tidb-golang-gorm-quickstart](https://github.com/tidb-samples/tidb-golang-gorm-quickstart) 仓库。 ### 连接到 TiDB @@ -188,7 +201,7 @@ func createDB() *gorm.DB { } ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 等替换为你的 TiDB 集群的实际值。因为 TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此在连接到 TiDB Cloud Serverless 时 `${use_ssl}` 的值应为 `true`。 +使用此函数时,您需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}` 和 `${tidb_db_name}` 替换为 TiDB 集群的实际值。TiDB Cloud Serverless 需要安全连接。因此,您需要将 `${use_ssl}` 的值设置为 `true`。 ### 插入数据 @@ -196,7 +209,7 @@ func createDB() *gorm.DB { db.Create(&Player{ID: "id", Coins: 1, Goods: 1}) ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 @@ -205,16 +218,15 @@ var queryPlayer Player db.Find(&queryPlayer, "id = ?", "id") ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 ```golang - db.Save(&Player{ID: "id", Coins: 100, Goods: 1}) ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 @@ -222,14 +234,24 @@ db.Save(&Player{ID: "id", Coins: 100, Goods: 1}) db.Delete(&Player{ID: "id"}) ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于 GORM 的更多使用方法,可以参考 [GORM 官方文档](https://gorm.io/zh_CN/docs/index.html) 及 GORM 官方文档中的 [TiDB 章节](https://gorm.io/zh_CN/docs/connecting_to_the_database.html#TiDB)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [GORM 文档](https://gorm.io/docs/index.html)和 [GORM 文档中的 TiDB 部分](https://gorm.io/docs/connecting_to_the_database.html#TiDB)了解更多 GORM 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-golang-sql-driver.md b/develop/dev-guide-sample-application-golang-sql-driver.md index 87ede014be58..d8da69c5a998 100644 --- a/develop/dev-guide-sample-application-golang-sql-driver.md +++ b/develop/dev-guide-sample-application-golang-sql-driver.md @@ -1,141 +1,155 @@ --- -title: 使用 Go-MySQL-Driver 连接到 TiDB -summary: 了解如何使用 Go-MySQL-Driver 连接到 TiDB。本文提供了使用 Go-MySQL-Driver 与 TiDB 交互的 Golang 示例代码片段。 +title: 使用 Go-MySQL-Driver 连接 TiDB +summary: 了解如何使用 Go-MySQL-Driver 连接 TiDB。本教程提供使用 Go-MySQL-Driver 操作 TiDB 的 Golang 示例代码片段。 --- -# 使用 Go-MySQL-Driver 连接到 TiDB +# 使用 Go-MySQL-Driver 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[Go-MySQL-Driver](https://github.com/go-sql-driver/mysql) 是 [database/sql](https://pkg.go.dev/database/sql) 接口的 MySQL 实现。 +TiDB 是一个兼容 MySQL 的数据库,而 [Go-MySQL-Driver](https://github.com/go-sql-driver/mysql) 是 [database/sql](https://pkg.go.dev/database/sql) 接口的 MySQL 实现。 -本文档将展示如何使用 TiDB 和 Go-MySQL-Driver 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 Go-MySQL-Driver 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 Go-MySQL-Driver 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看基本 CRUD 操作的[示例代码片段](#示例代码片段)。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -- 推荐 [Go](https://go.dev/) **1.20** 及以上版本。 +要完成本教程,您需要: + +- [Go](https://go.dev/) **1.20** 或更高版本。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -## 运行代码并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + -### 第 1 步:克隆示例代码仓库到本地 +## 运行示例应用程序连接到 TiDB -运行以下命令,将示例代码仓库克隆到本地: +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: ```shell git clone https://github.com/tidb-samples/tidb-golang-sql-driver-quickstart.git cd tidb-golang-sql-driver-quickstart ``` -### 第 2 步:配置连接信息 +### 步骤 2:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接工具**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip:** - > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码或点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. gateway01.ap-northeast-1.prod.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 xxxxxx.root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' USE_SSL='true' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 - TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此 `USE_SSL` 的值应为 `true`。 + TiDB Cloud Serverless 需要安全连接。因此,您需要将 `USE_SSL` 的值设置为 `true`。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. tidb.xxxx.clusters.tidb-cloud.com + TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. root + TIDB_USER='{user}' # 例如 root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv TIDB_HOST='{host}' @@ -146,29 +160,28 @@ cd tidb-golang-sql-driver-quickstart USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并设置 `USE_SSL` 为 `false`。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并将 `USE_SSL` 设置为 `false`。如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 3 步:运行代码并查看结果 +### 步骤 3:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: ```shell make ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-golang-sql-driver-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-golang-sql-driver-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-golang-sql-driver-quickstart](https://github.com/tidb-samples/tidb-golang-sql-driver-quickstart)。 +有关完整的示例代码和如何运行它,请查看 [tidb-samples/tidb-golang-sql-driver-quickstart](https://github.com/tidb-samples/tidb-golang-sql-driver-quickstart) 仓库。 ### 连接到 TiDB @@ -186,13 +199,13 @@ func openDB(driverName string, runnable func(db *sql.DB)) { } ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 等替换为你的 TiDB 集群的实际值。因为 TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此在连接到 TiDB Cloud Serverless 时 `${use_ssl}` 的值应为 `true`。 +使用此函数时,您需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}` 和 `${tidb_db_name}` 替换为您的 TiDB 集群的实际值。TiDB Cloud Serverless 需要安全连接。因此,您需要将 `${use_ssl}` 的值设置为 `true`。 ### 插入数据 ```golang openDB("mysql", func(db *sql.DB) { - insertSQL := "INSERT INTO player (id, coins, goods) VALUES (?, ?, ?)" + insertSQL = "INSERT INTO player (id, coins, goods) VALUES (?, ?, ?)" _, err := db.Exec(insertSQL, "id", 1, 1) if err != nil { @@ -201,19 +214,19 @@ openDB("mysql", func(db *sql.DB) { }) ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 ```golang openDB("mysql", func(db *sql.DB) { - selectSQL := "SELECT id, coins, goods FROM player WHERE id = ?" + selectSQL = "SELECT id, coins, goods FROM player WHERE id = ?" rows, err := db.Query(selectSQL, "id") if err != nil { panic(err) } - // This line is extremely important! + // 这行非常重要! defer rows.Close() id, coins, goods := "", 0, 0 @@ -226,13 +239,13 @@ openDB("mysql", func(db *sql.DB) { }) ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 ```golang openDB("mysql", func(db *sql.DB) { - updateSQL := "UPDATE player set goods = goods + ?, coins = coins + ? WHERE id = ?" + updateSQL = "UPDATE player set goods = goods + ?, coins = coins + ? WHERE id = ?" _, err := db.Exec(updateSQL, 1, -1, "id") if err != nil { @@ -241,13 +254,13 @@ openDB("mysql", func(db *sql.DB) { }) ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 ```golang openDB("mysql", func(db *sql.DB) { - deleteSQL := "DELETE FROM player WHERE id=?" + deleteSQL = "DELETE FROM player WHERE id=?" _, err := db.Exec(deleteSQL, "id") if err != nil { @@ -256,29 +269,39 @@ openDB("mysql", func(db *sql.DB) { }) ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 ### 使用驱动程序还是 ORM 框架? -Golang 驱动程序提供对数据库的底层访问,但要求开发者: +Golang 驱动程序提供对数据库的低级访问,但它要求开发人员: -- 手动建立和释放数据库连接 -- 手动管理数据库事务 -- 手动将数据行映射为数据对象 +- 手动建立和释放数据库连接。 +- 手动管理数据库事务。 +- 手动将数据行映射到数据对象。 -建议仅在需要编写复杂的 SQL 语句时使用驱动程序。其他情况下,建议使用 [ORM](https://zh.wikipedia.org/wiki/对象关系映射) 框架进行开发,例如 [GORM](/develop/dev-guide-sample-application-golang-gorm.md)。ORM 可以帮助你: +除非您需要编写复杂的 SQL 语句,否则建议使用 [ORM](https://en.wikipedia.org/w/index.php?title=Object-relational_mapping) 框架进行开发,例如 [GORM](/develop/dev-guide-sample-application-golang-gorm.md)。它可以帮助您: -- 减少管理连接和事务的[模板代码](https://en.wikipedia.org/wiki/Boilerplate_code) -- 使用数据对象代替大量 SQL 语句来操作数据 +- 减少管理连接和事务的[样板代码](https://en.wikipedia.org/wiki/Boilerplate_code)。 +- 使用数据对象而不是大量 SQL 语句来操作数据。 ## 下一步 -- 关于 Go-MySQL-Driver 的更多使用方法,可以参考 [Go-MySQL-Driver 官方文档](https://github.com/go-sql-driver/mysql/blob/master/README.md)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [Go-MySQL-Driver 文档](https://github.com/go-sql-driver/mysql/blob/master/README.md)了解更多 Go-MySQL-Driver 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-java-hibernate.md b/develop/dev-guide-sample-application-java-hibernate.md index 2be8e1145baf..a3cd11bd5c6d 100644 --- a/develop/dev-guide-sample-application-java-hibernate.md +++ b/develop/dev-guide-sample-application-java-hibernate.md @@ -1,142 +1,156 @@ --- -title: 使用 Hibernate 连接到 TiDB -summary: 了解如何使用 Hibernate 连接到 TiDB。本文提供了使用 Hibernate 与 TiDB 交互的 Java 示例代码片段。 +title: 使用 Hibernate 连接 TiDB +summary: 了解如何使用 Hibernate 连接 TiDB。本教程提供使用 Hibernate 操作 TiDB 的 Java 示例代码片段。 --- -# 使用 Hibernate 连接到 TiDB +# 使用 Hibernate 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[Hibernate](https://hibernate.org/orm/) 是当前比较流行的开源 Java 应用持久层框架,且 Hibernate 在版本 `6.0.0.Beta2` 及以上支持了 TiDB 方言,完美适配了 TiDB 的特性。 +TiDB 是一个兼容 MySQL 的数据库,而 [Hibernate](https://hibernate.org/orm/) 是一个流行的开源 Java ORM。从 `6.0.0.Beta2` 版本开始,Hibernate 支持 TiDB 方言,能很好地适配 TiDB 特性。 -本文档将展示如何使用 TiDB 和 Hibernate 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 Hibernate 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 Hibernate 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看[示例代码片段](#示例代码片段),了解基本的 CRUD 操作。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -- 推荐 **Java Development Kit** (JDK) **17** 及以上版本。你可以根据公司及个人需求,自行选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 -- [Maven](https://maven.apache.org/install.html) **3.8** 及以上版本。 +要完成本教程,您需要: + +- **Java Development Kit (JDK) 17** 或更高版本。您可以根据业务和个人需求选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 +- [Maven](https://maven.apache.org/install.html) **3.8** 或更高版本。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + -## 运行代码并连接到 TiDB +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -### 第 1 步:克隆示例代码仓库到本地 + -运行以下命令,将示例代码仓库克隆到本地: +## 运行示例程序连接 TiDB -```bash +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-java-hibernate-quickstart.git cd tidb-java-hibernate-quickstart ``` -### 第 2 步:配置连接信息 +### 步骤 2:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经创建了密码,可以使用原始密码或点击**重置密码**生成新密码。 -5. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +5. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -6. 复制并粘贴对应连接字符串至 `env.sh` 中。需更改部分示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. gateway01.ap-northeast-1.prod.aws.tidbcloud.com + export TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. xxxxxx.root + export TIDB_USER='{user}' # 例如 xxxxxx.root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='true' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 - TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此 `USE_SSL` 的值应为 `true`。 + TiDB Cloud Serverless 需要安全连接。因此,您需要将 `USE_SSL` 的值设置为 `true`。 7. 保存 `env.sh` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +4. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -5. 复制并粘贴对应的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. tidb.xxxx.clusters.tidb-cloud.com + export TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. root + export TIDB_USER='{user}' # 例如 root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 6. 保存 `env.sh` 文件。
+
-
- -1. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +1. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell export TIDB_HOST='{host}' @@ -147,33 +161,32 @@ cd tidb-java-hibernate-quickstart export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并设置 `USE_SSL` 为 `false`。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并将 `USE_SSL` 设置为 `false`。如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `env.sh` 文件。
- -### 第 3 步:运行代码并查看结果 +### 步骤 3:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: ```shell make ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-java-hibernate-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-java-hibernate-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-java-hibernate-quickstart](https://github.com/tidb-samples/tidb-java-hibernate-quickstart/blob/main/README-zh.md)。 +有关完整的示例代码和运行方法,请查看 [tidb-samples/tidb-java-hibernate-quickstart](https://github.com/tidb-samples/tidb-java-hibernate-quickstart) 仓库。 ### 连接到 TiDB -编写配置文件 `hibernate.cfg.xml`: +编辑 Hibernate 配置文件 `hibernate.cfg.xml`: ```xml @@ -183,7 +196,7 @@ cd tidb-java-hibernate-quickstart - + com.mysql.cj.jdbc.Driver org.hibernate.dialect.TiDBDialect ${tidb_jdbc_url} @@ -191,17 +204,17 @@ cd tidb-java-hibernate-quickstart ${tidb_password} false - + create-drop - + true true ``` -请将 `${tidb_jdbc_url}`、`${tidb_user}`、`${tidb_password}` 等替换为你的 TiDB 集群的实际值。随后编写以下函数: +请确保将 `${tidb_jdbc_url}`、`${tidb_user}` 和 `${tidb_password}` 替换为 TiDB 集群的实际值。然后,定义以下函数: ```java public SessionFactory getSessionFactory() { @@ -212,7 +225,7 @@ public SessionFactory getSessionFactory() { } ``` -在使用该函数时,你需要替换 `${your_entity_class}` 为自己的数据实体类。如果你有多个实体类,需要添加多个 `.addAnnotatedClass(${your_entity_class})` 语句。此外,这仅是 Hibernate 的其中一种配置方式。在配置中遇到任何问题,或想了解更多关于 Hibernate 的信息,你可参考 [Hibernate 官方文档](https://hibernate.org/orm/documentation)。 +使用此函数时,您需要将 `${your_entity_class}` 替换为您自己的数据实体类。对于多个实体类,您需要为每个类添加一个 `.addAnnotatedClass(${your_entity_class})` 语句。上述函数只是配置 Hibernate 的一种方式。如果您在配置过程中遇到任何问题或想了解更多关于 Hibernate 的信息,请参考 [Hibernate 官方文档](https://hibernate.org/orm/documentation)。 ### 插入或更新数据 @@ -222,7 +235,7 @@ try (Session session = sessionFactory.openSession()) { } ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)和[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)和[更新数据](/develop/dev-guide-update-data.md)。 ### 查询数据 @@ -233,7 +246,7 @@ try (Session session = sessionFactory.openSession()) { } ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 删除数据 @@ -243,15 +256,25 @@ try (Session session = sessionFactory.openSession()) { } ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于 Hibernate 的更多使用方法,可以参考 [Hibernate 官方文档](https://hibernate.org/orm/documentation)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 -- 我们还额外提供针对 Java 开发者的课程:[使用 Connector/J - TiDB v6](https://learn.pingcap.com/learner/course/840002/?utm_source=docs-cn-dev-guide) 及[在 TiDB 上开发应用的最佳实践 - TiDB v6](https://learn.pingcap.com/learner/course/780002/?utm_source=docs-cn-dev-guide)。 +- 从 [Hibernate 文档](https://hibernate.org/orm/documentation)了解更多 Hibernate 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 +- 通过 Java 开发者课程学习:[使用 Java 操作 TiDB](https://eng.edu.pingcap.com/catalog/info/id:212)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-java-jdbc.md b/develop/dev-guide-sample-application-java-jdbc.md index 458fc1b901af..9f727a7999ff 100644 --- a/develop/dev-guide-sample-application-java-jdbc.md +++ b/develop/dev-guide-sample-application-java-jdbc.md @@ -1,143 +1,174 @@ --- -title: 使用 JDBC 连接到 TiDB -summary: 了解如何使用 JDBC 连接到 TiDB。本文提供了使用 JDBC 与 TiDB 交互的 Java 示例代码片段。 +title: 使用 JDBC 连接 TiDB +summary: 学习如何使用 JDBC 连接 TiDB。本教程提供使用 JDBC 操作 TiDB 的 Java 示例代码片段。 --- -# 使用 JDBC 连接到 TiDB +# 使用 JDBC 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。JDBC 是 Java 的数据访问 API。[MySQL Connector/J](https://dev.mysql.com/downloads/connector/j/) 是 MySQL 对 JDBC 的实现。 +TiDB 是一个兼容 MySQL 的数据库,而 JDBC(Java Database Connectivity)是 Java 的数据访问 API。[MySQL Connector/J](https://dev.mysql.com/downloads/connector/j/) 是 MySQL 的 JDBC 实现。 -本文档将展示如何使用 TiDB 和 JDBC 来完成以下任务: +在本教程中,你可以学习如何使用 TiDB 和 JDBC 完成以下任务: -- 配置你的环境。 -- 使用 JDBC 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置你的环境。 +- 使用 JDBC 连接到你的 TiDB 集群。 +- 构建并运行你的应用程序。你也可以查看基本 CRUD 操作的[示例代码片段](#示例代码片段)。 -> **注意** + + +> **注意:** > -> - 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 -> - 从 TiDB v7.4 起,如果 JDBC URL 中未配置 `connectionCollation`,且 `characterEncoding` 未配置或配置为 `UTF-8`,JDBC 连接所使用的排序规则取决于 JDBC 驱动版本。详情请参考 [JDBC 连接所使用的排序规则](/faq/sql-faq.md#jdbc-连接所使用的排序规则)。 +> - 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 +> - 从 TiDB v7.4 开始,如果在 JDBC URL 中未配置 `connectionCollation`,且 `characterEncoding` 未配置或设置为 `UTF-8`,JDBC 连接中使用的排序规则取决于 JDBC 驱动程序版本。更多信息,请参见 [JDBC 连接中使用的排序规则](/faq/sql-faq.md#collation-used-in-jdbc-connections)。 + + + + + +> **注意:** +> +> - 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 +> - 从 TiDB v7.4 开始,如果在 JDBC URL 中未配置 `connectionCollation`,且 `characterEncoding` 未配置或设置为 `UTF-8`,JDBC 连接中使用的排序规则取决于 JDBC 驱动程序版本。更多信息,请参见 [JDBC 连接中使用的排序规则](https://docs.pingcap.com/tidb/stable/sql-faq#collation-used-in-jdbc-connections)。 + + + +## 前提条件 -## 前置需求 +要完成本教程,你需要: -- 推荐 **Java Development Kit** (JDK) **17** 及以上版本。你可以根据公司及个人需求,自行选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 -- [Maven](https://maven.apache.org/install.html) **3.8** 及以上版本。 +- **Java Development Kit (JDK) 17** 或更高版本。你可以根据你的业务和个人需求选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 +- [Maven](https://maven.apache.org/install.html) **3.8** 或更高版本。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果你还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + + +> **注意:** +> +> 出于安全考虑,建议你在通过互联网连接到 TiDB 集群时使用 `VERIFY_IDENTITY` 建立 TLS 连接。TiDB Cloud Serverless 和 TiDB Cloud Dedicated 都使用主体备用名称(SAN)证书,这要求 MySQL Connector/J 版本大于或等于 [8.0.22](https://dev.mysql.com/doc/relnotes/connector-j/en/news-8-0-22.html)。 + +**如果你还没有 TiDB 集群,可以按照以下方式创建:** -## 运行代码并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + -### 第 1 步:克隆示例代码仓库到本地 +## 运行示例应用程序连接 TiDB -运行以下命令,将示例代码仓库克隆到本地: +本节演示如何运行示例应用程序代码并连接到 TiDB。 -```bash +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-java-jdbc-quickstart.git cd tidb-java-jdbc-quickstart ``` -### 第 2 步:配置连接信息 +### 步骤 2:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据你选择的 TiDB 部署选项连接到你的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示一个连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与你的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接工具**设置为 `General` + - **操作系统**与你的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建一个随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果你之前已经创建了密码,你可以使用原始密码,也可以点击**重置密码**生成一个新密码。 -5. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +5. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -6. 复制并粘贴对应连接字符串至 `env.sh` 中。需更改部分示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. gateway01.ap-northeast-1.prod.aws.tidbcloud.com + export TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. xxxxxx.root + export TIDB_USER='{user}' # 例如 xxxxxx.root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='true' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 - TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此 `USE_SSL` 的值应为 `true`。 + TiDB Cloud Serverless 需要安全连接。因此,你需要将 `USE_SSL` 的值设置为 `true`。 7. 保存 `env.sh` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示一个连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA cert** 下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果你还没有配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。更多信息,请参见[连接到你的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +4. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -5. 复制并粘贴对应的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. tidb.xxxx.clusters.tidb-cloud.com + export TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. root + export TIDB_USER='{user}' # 例如 root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 6. 保存 `env.sh` 文件。
+
-
- -1. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +1. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell export TIDB_HOST='{host}' @@ -148,29 +179,28 @@ cd tidb-java-jdbc-quickstart export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并设置 `USE_SSL` 为 `false`。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并将 `USE_SSL` 设置为 `false`。如果你在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `env.sh` 文件。
- -### 第 3 步:运行代码并查看结果 +### 步骤 3:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: ```shell make ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-java-jdbc-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-java-jdbc-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +你可以参考以下示例代码片段来完成你自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-java-jdbc-quickstart](https://github.com/tidb-samples/tidb-java-jdbc-quickstart/blob/main/README-zh.md)。 +有关完整的示例代码及其运行方法,请查看 [tidb-samples/tidb-java-jdbc-quickstart](https://github.com/tidb-samples/tidb-java-jdbc-quickstart) 仓库。 ### 连接到 TiDB @@ -192,7 +222,7 @@ public MysqlDataSource getMysqlDataSource() throws SQLException { } ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 等替换为你的 TiDB 集群的实际值。 +使用此函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}` 和 `${tidb_db_name}` 替换为你的 TiDB 集群的实际值。 ### 插入数据 @@ -210,7 +240,7 @@ public void createPlayer(PlayerBean player) throws SQLException { } ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 @@ -231,7 +261,7 @@ public void getPlayer(String id) throws SQLException { } ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 @@ -248,7 +278,7 @@ public void updatePlayer(String id, int amount, int price) throws SQLException { } ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 @@ -263,30 +293,40 @@ public void deletePlayer(String id) throws SQLException { } ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 ### 使用驱动程序还是 ORM 框架? -Java 驱动程序提供对数据库的底层访问,但要求开发者: +Java 驱动程序提供对数据库的低级访问,但它要求开发人员: -- 手动建立和释放数据库连接 -- 手动管理数据库事务 -- 手动将数据行映射为数据对象 +- 手动建立和释放数据库连接。 +- 手动管理数据库事务。 +- 手动将数据行映射到数据对象。 -建议仅在需要编写复杂的 SQL 语句时使用驱动程序。其他情况下,建议使用 [ORM](https://zh.wikipedia.org/wiki/对象关系映射) 框架进行开发,例如 [Hibernate](/develop/dev-guide-sample-application-java-hibernate.md)、[MyBatis](/develop/dev-guide-sample-application-java-mybatis.md) 或 [Spring Data JPA](/develop/dev-guide-sample-application-java-spring-boot.md)。ORM 可以帮助你: +除非你需要编写复杂的 SQL 语句,否则建议使用 [ORM](https://en.wikipedia.org/w/index.php?title=Object-relational_mapping) 框架进行开发,如 [Hibernate](/develop/dev-guide-sample-application-java-hibernate.md)、[MyBatis](/develop/dev-guide-sample-application-java-mybatis.md) 或 [Spring Data JPA](/develop/dev-guide-sample-application-java-spring-boot.md)。它可以帮助你: -- 减少管理连接和事务的[模板代码](https://en.wikipedia.org/wiki/Boilerplate_code) -- 使用数据对象代替大量 SQL 语句来操作数据 +- 减少管理连接和事务的[样板代码](https://en.wikipedia.org/wiki/Boilerplate_code)。 +- 使用数据对象而不是大量 SQL 语句来操作数据。 ## 下一步 -- 关于 MySQL Connector/J 的更多使用方法,可以参考 [MySQL Connector/J 官方文档](https://dev.mysql.com/doc/connector-j/en/)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 -- 我们还额外提供针对 Java 开发者的课程:[使用 Connector/J - TiDB v6](https://learn.pingcap.com/learner/course/840002/?utm_source=docs-cn-dev-guide) 及[在 TiDB 上开发应用的最佳实践 - TiDB v6](https://learn.pingcap.com/learner/course/780002/?utm_source=docs-cn-dev-guide)。 +- 从 [MySQL Connector/J 的文档](https://dev.mysql.com/doc/connector-j/en/)中了解更多用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 +- 通过面向 Java 开发者的课程学习:[使用 Java 操作 TiDB](https://eng.edu.pingcap.com/catalog/info/id:212)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-java-mybatis.md b/develop/dev-guide-sample-application-java-mybatis.md index 7257bfdcc871..1c69a4b9b9c0 100644 --- a/develop/dev-guide-sample-application-java-mybatis.md +++ b/develop/dev-guide-sample-application-java-mybatis.md @@ -1,179 +1,192 @@ --- -title: 使用 MyBatis 连接到 TiDB -summary: 了解如何使用 MyBatis 连接到 TiDB。本文提供了使用 MyBatis 与 TiDB 交互的 Java 示例代码片段。 +title: 使用 MyBatis 连接 TiDB +summary: 了解如何使用 MyBatis 连接 TiDB。本教程提供使用 MyBatis 操作 TiDB 的 Java 示例代码片段。 --- -# 使用 MyBatis 连接到 TiDB +# 使用 MyBatis 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[MyBatis](https://mybatis.org/mybatis-3/index.html) 是当前比较流行的开源 Java 应用持久层框架。 +TiDB 是一个兼容 MySQL 的数据库,而 [MyBatis](https://mybatis.org/mybatis-3/index.html) 是一个流行的开源 Java ORM。 -本文档将展示如何使用 TiDB 和 MyBatis 来完成以下任务: +在本教程中,您将学习如何使用 TiDB 和 MyBatis 完成以下任务: -- 配置你的环境。 -- 使用 MyBatis 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置环境。 +- 使用 MyBatis 连接到您的 TiDB 集群。 +- 构建并运行您的应用程序。您也可以查看[示例代码片段](#示例代码片段)以了解基本的 CRUD 操作。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -- 推荐 **Java Development Kit** (JDK) **17** 及以上版本。你可以根据公司及个人需求,自行选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 -- [Maven](https://maven.apache.org/install.html) **3.8** 及以上版本。 +要完成本教程,您需要: + +- **Java Development Kit (JDK) 17** 或更高版本。您可以根据您的业务和个人需求选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 +- [Maven](https://maven.apache.org/install.html) **3.8** 或更高版本。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + -## 运行代码并连接到 TiDB +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 -### 第 1 步:克隆示例代码仓库到本地 + -运行以下命令,将示例代码仓库克隆到本地: +## 运行示例应用程序连接 TiDB -```bash +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-java-mybatis-quickstart.git cd tidb-java-mybatis-quickstart ``` -### 第 2 步:配置连接信息 +### 步骤 2:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境相匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建一个随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经创建了密码,您可以使用原始密码,也可以点击**重置密码**生成一个新密码。 -5. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +5. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -6. 复制并粘贴对应连接字符串至 `env.sh` 中。需更改部分示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + export TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. xxxxxx.root + export TIDB_USER='{user}' # 例如 xxxxxx.root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='true' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 - TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此 `USE_SSL` 的值应为 `true`。 + TiDB Cloud Serverless 需要安全连接。因此,您需要将 `USE_SSL` 的值设置为 `true`。 7. 保存 `env.sh` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +4. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -5. 复制并粘贴对应的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + export TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. xxxxxx.root + export TIDB_USER='{user}' # 例如 root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 6. 保存 `env.sh` 文件。
+
-
- -1. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +1. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + export TIDB_HOST='{host}' export TIDB_PORT='4000' - export TIDB_USER='root' # e.g. xxxxxx.root + export TIDB_USER='root' export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并设置 `USE_SSL` 为 `false`。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并将 `USE_SSL` 设置为 `false`。如果您在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `env.sh` 文件。
- -### 第 3 步:运行代码并查看结果 +### 步骤 3:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: ```shell make ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-java-mybatis-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-java-mybatis-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成您自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-java-mybatis-quickstart](https://github.com/tidb-samples/tidb-java-mybatis-quickstart/blob/main/README-zh.md)。 +有关完整的示例代码及其运行方法,请查看 [tidb-samples/tidb-java-mybatis-quickstart](https://github.com/tidb-samples/tidb-java-mybatis-quickstart) 仓库。 ### 连接到 TiDB -编写配置文件 `mybatis-config.xml`: +编辑 MyBatis 配置文件 `mybatis-config.xml`: ```xml @@ -190,24 +203,24 @@ cd tidb-java-mybatis-quickstart - + - + - - - + + + - + ``` -请将 `${TIDB_JDBC_URL}`、`${TIDB_USER}`、`${TIDB_PASSWORD}` 等替换为你的 TiDB 集群的实际值。并替换 `${MAPPER_LOCATION}` 的值为你的 mapper XML 配置文件的位置。如果你有多个 mapper XML 配置文件,需要添加多个 `` 标签。随后编写以下函数: +请确保将 `${tidb_jdbc_url}`、`${tidb_user}` 和 `${tidb_password}` 替换为您的 TiDB 集群的实际值。同时,将 `${mapper_location}` 替换为您的映射器 XML 配置文件的路径。对于多个映射器 XML 配置文件,您需要为每个文件添加一个 `` 标签。然后,定义以下函数: ```java public SqlSessionFactory getSessionFactory() { @@ -218,24 +231,24 @@ public SqlSessionFactory getSessionFactory() { ### 插入数据 -在 mapper XML 中添加节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加同名函数: +在映射器 XML 中添加一个节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加一个同名函数: ```xml - INSERT INTO player (id, coins, goods) - VALUES (#{id, jdbcType=VARCHAR}, #{coins, jdbcType=INTEGER}, #{goods, jdbcType=INTEGER}) + insert into player (id, coins, goods) + values (#{id,jdbcType=VARCHAR}, #{coins,jdbcType=INTEGER}, #{goods,jdbcType=INTEGER}) ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -在 mapper XML 中添加节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加同名函数。特别地,如果你在 MyBatis 的查询函数中使用 `resultMap` 作为返回类型,需要额外注意配置文件的 `` 节点配置是否正确。 +在映射器 XML 中添加一个节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加一个同名函数。具体来说,如果您使用 `resultMap` 作为 MyBatis 查询函数的返回类型,请确保正确配置 `` 节点。 ```xml @@ -250,58 +263,68 @@ public SqlSessionFactory getSessionFactory() { ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -在 mapper XML 中添加节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加同名函数: +在映射器 XML 中添加一个节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加一个同名函数: ```xml - UPDATE player - SET coins = #{coins, jdbcType=INTEGER}, - goods = #{goods, jdbcType=INTEGER} - WHERE id = #{id, jdbcType=VARCHAR} + update player + set coins = #{coins,jdbcType=INTEGER}, + goods = #{goods,jdbcType=INTEGER} + where id = #{id,jdbcType=VARCHAR} ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -在 mapper XML 中添加节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加同名函数: +在映射器 XML 中添加一个节点,并在 XML 配置文件的 `mapper.namespace` 属性中配置的接口类中添加一个同名函数: ```xml - DELETE FROM player - WHERE id = #{id, jdbcType=VARCHAR} + delete from player + where id = #{id,jdbcType=VARCHAR} ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于 MyBatis 的更多使用方法,可以参考 [MyBatis 官方文档](http://www.mybatis.org/mybatis-3/)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 -- 我们还额外提供针对 Java 开发者的课程:[使用 Connector/J - TiDB v6](https://learn.pingcap.com/learner/course/840002/?utm_source=docs-cn-dev-guide) 及[在 TiDB 上开发应用的最佳实践 - TiDB v6](https://learn.pingcap.com/learner/course/780002/?utm_source=docs-cn-dev-guide)。 +- 从 [MyBatis 的文档](http://www.mybatis.org/mybatis-3/)了解更多 MyBatis 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 +- 学习 Java 开发者课程:[使用 Java 操作 TiDB](https://eng.edu.pingcap.com/catalog/info/id:212)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-java-spring-boot.md b/develop/dev-guide-sample-application-java-spring-boot.md index da03806f367d..c4fc010d9820 100644 --- a/develop/dev-guide-sample-application-java-spring-boot.md +++ b/develop/dev-guide-sample-application-java-spring-boot.md @@ -1,185 +1,198 @@ --- -title: 使用 Spring Boot 连接到 TiDB -summary: 了解如何使用 Spring Boot 连接到 TiDB。本文提供了使用 Spring Boot 与 TiDB 交互的 Java 示例代码片段。 +title: 使用 Spring Boot 连接 TiDB +summary: 了解如何使用 Spring Boot 连接 TiDB。本教程提供使用 Spring Boot 操作 TiDB 的 Java 示例代码片段。 --- -# 使用 Spring Boot 连接到 TiDB +# 使用 Spring Boot 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[Spring](https://spring.io/) 是当前比较流行的开源 Java 容器框架,本文选择 [Spring Boot](https://spring.io/projects/spring-boot) 作为使用 Spring 的方式。 +TiDB 是一个兼容 MySQL 的数据库,而 [Spring](https://spring.io/) 是一个流行的开源 Java 容器框架。本文档使用 [Spring Boot](https://spring.io/projects/spring-boot) 作为使用 Spring 的方式。 -本文档将展示如何使用 TiDB 和 [Spring Data JPA](https://spring.io/projects/spring-data-jpa) 及 [Hibernate](https://hibernate.org/orm/) 作为 JPA 提供者来完成以下任务: +在本教程中,您将学习如何使用 TiDB 以及 [Spring Data JPA](https://spring.io/projects/spring-data-jpa) 和作为 JPA 提供者的 [Hibernate](https://hibernate.org/orm/) 来完成以下任务: -- 配置你的环境。 -- 使用 Spring Data JPA 与 Hibernate 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置环境。 +- 使用 Hibernate 和 Spring Data JPA 连接到您的 TiDB 集群。 +- 构建并运行您的应用程序。您也可以查看[示例代码片段](#示例代码片段)以了解基本的 CRUD 操作。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -- 推荐 **Java Development Kit** (JDK) **17** 及以上版本。你可以根据公司及个人需求,自行选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 -- [Maven](https://maven.apache.org/install.html) **3.8** 及以上版本。 +要完成本教程,您需要: + +- **Java Development Kit (JDK) 17** 或更高版本。您可以根据您的业务和个人需求选择 [OpenJDK](https://openjdk.org/) 或 [Oracle JDK](https://www.oracle.com/hk/java/technologies/downloads/)。 +- [Maven](https://maven.apache.org/install.html) **3.8** 或更高版本。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 -## 运行代码并连接到 TiDB + -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +## 运行示例应用程序连接 TiDB -### 第 1 步:克隆示例代码仓库到本地 +本节演示如何运行示例应用程序代码并连接到 TiDB。 -运行以下命令,将示例代码仓库克隆到本地: +### 步骤 1:克隆示例应用程序仓库 -```bash +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-java-springboot-jpa-quickstart.git cd tidb-java-springboot-jpa-quickstart ``` -### 第 2 步:配置连接信息 +### 步骤 2:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境相匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建一个随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经创建了密码,您可以使用原始密码,也可以点击**重置密码**生成一个新密码。 -5. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +5. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -6. 复制并粘贴对应连接字符串至 `env.sh` 中。需更改部分示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + export TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. xxxxxx.root + export TIDB_USER='{user}' # 例如 xxxxxx.root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='true' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 - TiDB Cloud Serverless 要求使用 TLS (SSL) connection,因此 `USE_SSL` 的值应为 `true`。 + TiDB Cloud Serverless 需要安全连接。因此,您需要将 `USE_SSL` 的值设置为 `true`。 7. 保存 `env.sh` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +4. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -5. 复制并粘贴对应的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + export TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com export TIDB_PORT='4000' - export TIDB_USER='{user}' # e.g. xxxxxx.root + export TIDB_USER='{user}' # 例如 root export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 6. 保存 `env.sh` 文件。
+
-
- -1. 运行以下命令,将 `env.sh.example` 复制并重命名为 `env.sh`: +1. 运行以下命令复制 `env.sh.example` 并将其重命名为 `env.sh`: - ```bash + ```shell cp env.sh.example env.sh ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `env.sh` 中。需更改部分示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `env.sh` 文件中。示例结果如下: ```shell - export TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + export TIDB_HOST='{host}' export TIDB_PORT='4000' - export TIDB_USER='root' # e.g. xxxxxx.root + export TIDB_USER='root' export TIDB_PASSWORD='{password}' export TIDB_DB_NAME='test' export USE_SSL='false' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并设置 `USE_SSL` 为 `false`。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并将 `USE_SSL` 设置为 `false`。如果您在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `env.sh` 文件。
- -### 第 3 步:运行代码并查看结果 +### 步骤 3:运行代码并检查结果 -1. 运行下述命令,启动示例代码编写的服务: +1. 执行以下命令运行示例代码: ```shell make ``` -2. 打开另一个终端,开启请求脚本: +2. 在另一个终端会话中运行请求脚本: ```shell make request ``` -3. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-java-springboot-jpa-quickstart/blob/main/Expected-Output.txt),并与你的服务程序输出进行比较。结果近似即为连接成功。 +3. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-java-springboot-jpa-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成您自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-java-springboot-jpa-quickstart](https://github.com/tidb-samples/tidb-java-springboot-jpa-quickstart/blob/main/README-zh.md)。 +有关完整的示例代码及其运行方法,请查看 [tidb-samples/tidb-java-springboot-jpa-quickstart](https://github.com/tidb-samples/tidb-java-springboot-jpa-quickstart) 仓库。 ### 连接到 TiDB -编写配置文件 `application.yml`: +编辑配置文件 `application.yml`: ```yaml spring: @@ -195,24 +208,15 @@ spring: ddl-auto: create-drop ``` -请在配置后将环境变量 `TIDB_JDBC_URL`、`TIDB_USER` 和 `TIDB_PASSWORD` 设置为你的 TiDB 集群的实际值。此配置文件带有环境变量默认配置,即在不配置环境变量时,变量的值为: - -- `TIDB_JDBC_URL`: `"jdbc:mysql://localhost:4000/test"` -- `TIDB_USER`: `"root"` -- `TIDB_PASSWORD`: `""` - -### 数据管理 +配置完成后,将环境变量 `TIDB_JDBC_URL`、`TIDB_USER` 和 `TIDB_PASSWORD` 设置为您的 TiDB 集群的实际值。配置文件为这些环境变量提供了默认设置。如果您不配置环境变量,默认值如下: -Spring Data JPA 通过 `@Entity` 注册数据实体,并绑定数据库的表。 +- `TIDB_JDBC_URL`:`"jdbc:mysql://localhost:4000/test"` +- `TIDB_USER`:`"root"` +- `TIDB_PASSWORD`:`""` -```java -@Entity -@Table(name = "player_jpa") -public class PlayerBean { -} -``` +### 数据管理:`@Repository` -`PlayerRepository` 通过继承 `JpaRepository` 接口,由 `JpaRepositoryFactoryBean` 为其自动注册对应的 Repository Bean。同时,`JpaRepository` 接口的默认实现类 `SimpleJpaRepository` 提供了增删改查函数的具体实现。 +Spring Data JPA 通过 `@Repository` 接口管理数据。要使用 `JpaRepository` 提供的 CRUD 操作,您需要扩展 `JpaRepository` 接口: ```java @Repository @@ -220,7 +224,7 @@ public interface PlayerRepository extends JpaRepository { } ``` -随后,在需要使用 `PlayerRepository` 的类中,你可以通过 `@Autowired` 自动装配,这样就可以直接使用增删改查函数了。示例代码如下: +然后,您可以在任何需要 `PlayerRepository` 的类中使用 `@Autowired` 进行自动依赖注入。这使您可以直接使用 CRUD 函数。示例如下: ```java @Autowired @@ -233,7 +237,7 @@ private PlayerRepository playerRepository; playerRepository.save(player); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)和[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)和[更新数据](/develop/dev-guide-update-data.md)。 ### 查询数据 @@ -241,7 +245,7 @@ playerRepository.save(player); PlayerBean player = playerRepository.findById(id).orElse(null); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 删除数据 @@ -249,20 +253,31 @@ PlayerBean player = playerRepository.findById(id).orElse(null); playerRepository.deleteById(id); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于本文使用到的第三方库及框架,可以参考各自官方文档: +- 要了解本文档中使用的第三方库和框架的更多用法,请参考它们的官方文档: + + - [Spring Framework 的文档](https://spring.io/projects/spring-framework) + - [Spring Boot 的文档](https://spring.io/projects/spring-boot) + - [Spring Data JPA 的文档](https://spring.io/projects/spring-data-jpa) + - [Hibernate 的文档](https://hibernate.org/orm/documentation) + +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 +- 学习 Java 开发者课程:[使用 Java 操作 TiDB](https://eng.edu.pingcap.com/catalog/info/id:212)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + - - [Spring Framework 官方文档](https://spring.io/projects/spring-framework) - - [Spring Boot 官方文档](https://spring.io/projects/spring-boot) - - [Spring Data JPA 官方文档](https://spring.io/projects/spring-data-jpa) - - [Hibernate 官方文档](https://hibernate.org/orm/documentation) -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 -- 我们还额外提供针对 Java 开发者的课程:[使用 Connector/J - TiDB v6](https://learn.pingcap.com/learner/course/840002/?utm_source=docs-cn-dev-guide) 及[在 TiDB 上开发应用的最佳实践 - TiDB v6](https://learn.pingcap.com/learner/course/780002/?utm_source=docs-cn-dev-guide)。 + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-nextjs.md b/develop/dev-guide-sample-application-nextjs.md index efd888218fd1..8fd16edf3c44 100644 --- a/develop/dev-guide-sample-application-nextjs.md +++ b/develop/dev-guide-sample-application-nextjs.md @@ -1,90 +1,102 @@ --- -title: 在 Next.js 中使用 mysql2 连接到 TiDB -summary: 本文介绍了如何在 Next.js 中使用 TiDB 和 mysql2 构建一个 CRUD 应用程序,并给出了简单示例代码片段。 +title: 在 Next.js 中使用 mysql2 连接 TiDB +summary: 本文介绍如何在 Next.js 中使用 TiDB 和 mysql2 构建 CRUD 应用程序,并提供简单的示例代码。 --- -# 在 Next.js 中使用 mysql2 连接到 TiDB +# 在 Next.js 中使用 mysql2 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库,[mysql2](https://github.com/sidorares/node-mysql2) 是当前流行的开源 Node.js Driver 之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [mysql2](https://github.com/sidorares/node-mysql2) 是一个流行的 Node.js 驱动程序。 -本文档将展示如何在 Next.js 中使用 TiDB 和 mysql2 来完成以下任务: +在本教程中,你将学习如何在 Next.js 中使用 TiDB 和 mysql2 完成以下任务: -- 配置你的环境。 -- 使用 mysql2 驱动连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置环境 +- 使用 mysql2 连接到 TiDB 集群 +- 构建并运行应用程序。你还可以找到基本 CRUD 操作的[示例代码片段](#示例代码片段) -> **Note** +> **注意** > -> 本文档适用于 TiDB Cloud Serverless 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless 和自托管的 TiDB。 -## 前置需求 +## 前提条件 -为了能够顺利完成本教程,你需要提前: +完成本教程需要: -- 在你的机器上安装 [Node.js](https://nodejs.org/en) 18.x 或以上版本。 -- 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- [Node.js **18**](https://nodejs.org/en/download/) 或更高版本 +- [Git](https://git-scm.com/downloads) +- TiDB 集群 -如果你还没有 TiDB 集群,可以按照以下方式创建: + -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +**如果你还没有 TiDB 集群,可以按照以下方式创建:** -## 运行代码并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + + -> **Note** +**如果你还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 + + + +## 运行示例应用程序连接 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +> **注意** > -> 完整代码及其运行方式,见代码仓库 [tidb-nextjs-vercel-quickstart](https://github.com/tidb-samples/tidb-nextjs-vercel-quickstart)。 +> 完整的代码片段和运行说明,请参考 [tidb-nextjs-vercel-quickstart](https://github.com/tidb-samples/tidb-nextjs-vercel-quickstart) GitHub 仓库。 -### 第 1 步:克隆示例代码仓库到本地 +### 步骤 1:克隆示例应用程序仓库 -运行以下命令,将示例代码仓库克隆到本地: +在终端窗口中运行以下命令来克隆示例代码仓库: ```bash git clone git@github.com:tidb-samples/tidb-nextjs-vercel-quickstart.git cd tidb-nextjs-vercel-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 mysql2 和 Next.js): +运行以下命令安装示例应用程序所需的包(包括 `mysql2`): ```bash npm install ``` -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据你选择的 TiDB 部署选项连接到 TiDB 集群。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**页面](https://tidbcloud.com/project/clusters),然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的选项配置和你的运行环境一致。 +3. 确保连接对话框中的配置与你的操作环境相匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为运行示例代码所在的操作系统。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与你的环境匹配 - > **Note** + > **注意** > - > 在 Node.js 应用程序中,你无需提供 SSL CA 证书,因为在建立 TLS (SSL) 连接时,默认情况下 Node.js 使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates)。 + > 在 Node.js 应用程序中,你不需要提供 SSL CA 证书,因为 Node.js 在建立 TLS (SSL) 连接时默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates)。 -4. 如果你还没有设置密码,点击 **Generate Password** 按钮生成一个随机的密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip** + > **提示** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果你之前已经创建过密码,可以使用原密码或点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: ```bash # Linux @@ -96,7 +108,7 @@ npm install Copy-Item ".env.example" -Destination ".env" ``` -6. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```bash TIDB_HOST='{gateway-region}.aws.tidbcloud.com' @@ -106,13 +118,15 @@ npm install TIDB_DB_NAME='test' ``` + 将 `{}` 中的占位符替换为连接对话框中获得的值。 + 7. 保存 `.env` 文件。
-
+
-1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: ```bash # Linux @@ -124,7 +138,7 @@ npm install Copy-Item ".env.example" -Destination ".env" ``` -2. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为你的 TiDB 集群的连接参数值: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```bash TIDB_HOST='{tidb_server_host}' @@ -134,7 +148,7 @@ npm install TIDB_DB_NAME='test' ``` - 如果你在本地运行 TiDB 集群,默认的主机地址是 `127.0.0.1`,密码为空。 + 将 `{}` 中的占位符替换为**连接**窗口中获得的值。如果你在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。 @@ -142,39 +156,39 @@ npm install -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -1. 运行示例应用程序: +1. 启动应用程序: - ```bash - npm run dev - ``` + ```bash + npm run dev + ``` -2. 打开浏览器,在地址栏输入 `http://localhost:3000`,访问示例应用程序。请查看你的终端以获取实际的端口号,默认为 `3000`。 +2. 打开浏览器并访问 `http://localhost:3000`。(检查终端中的实际端口号,默认为 `3000`) 3. 点击 **RUN SQL** 执行示例代码。 -4. 在终端中检查输出。如果输出类似于以下内容,则连接成功: +4. 检查终端中的输出。如果输出类似于以下内容,则连接成功: - ```json - { - "results": [ - { - "Hello World": "Hello World" - } - ] - } - ``` + ```json + { + "results": [ + { + "Hello World": "Hello World" + } + ] + } + ``` ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-nextjs-vercel-quickstart](https://github.com/tidb-samples/tidb-nextjs-vercel-quickstart)。 +完整的示例代码和运行方法,请查看 [tidb-nextjs-vercel-quickstart](https://github.com/tidb-samples/tidb-nextjs-vercel-quickstart) 仓库。 ### 连接到 TiDB -下面的代码使用环境变量中定义的连接选项来建立与 TiDB 集群的连接。 +以下代码使用环境变量中定义的选项建立与 TiDB 的连接: ```javascript // src/lib/tidb.js @@ -184,17 +198,17 @@ let pool = null; export function connect() { return mysql.createPool({ - host: process.env.TIDB_HOST, // TiDB host, for example: {gateway-region}.aws.tidbcloud.com - port: process.env.TIDB_PORT || 4000, // TiDB port, default: 4000 - user: process.env.TIDB_USER, // TiDB user, for example: {prefix}.root - password: process.env.TIDB_PASSWORD, // The password of TiDB user. - database: process.env.TIDB_DATABASE || 'test', // TiDB database name, default: test + host: process.env.TIDB_HOST, // TiDB 主机,例如:{gateway-region}.aws.tidbcloud.com + port: process.env.TIDB_PORT || 4000, // TiDB 端口,默认:4000 + user: process.env.TIDB_USER, // TiDB 用户,例如:{prefix}.root + password: process.env.TIDB_PASSWORD, // TiDB 用户的密码 + database: process.env.TIDB_DATABASE || 'test', // TiDB 数据库名称,默认:test ssl: { minVersion: 'TLSv1.2', rejectUnauthorized: true, }, - connectionLimit: 1, // Setting connectionLimit to "1" in a serverless function environment optimizes resource usage, reduces costs, ensures connection stability, and enables seamless scalability. - maxIdle: 1, // max idle connections, the default value is the same as `connectionLimit` + connectionLimit: 1, // 在 serverless 函数环境中将 connectionLimit 设置为 "1" 可以优化资源使用,降低成本,确保连接稳定性,并实现无缝扩展。 + maxIdle: 1, // 最大空闲连接数,默认值与 `connectionLimit` 相同 enableKeepAlive: true, }); } @@ -209,29 +223,29 @@ export function getPool() { ### 插入数据 -下面的查询会创建一条单独的 `Player` 记录,并返回一个 `ResultSetHeader` 对象: +以下查询创建一个 `Player` 记录并返回一个 `ResultSetHeader` 对象: ```javascript const [rsh] = await pool.query('INSERT INTO players (coins, goods) VALUES (?, ?);', [100, 100]); console.log(rsh.insertId); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -下面的查询会返回一条 `Player` 记录,其 ID 为 `1`: +以下查询通过 ID `1` 返回一个 `Player` 记录: ```javascript const [rows] = await pool.query('SELECT id, coins, goods FROM players WHERE id = ?;', [1]); console.log(rows[0]); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -下面的查询会将 ID 为 `1` 的 `Player` 记录的 `coins` 和 `goods` 字段的值分别增加 `50`: +以下查询为 ID 为 `1` 的 `Player` 增加 `50` 个金币和 `50` 个物品: ```javascript const [rsh] = await pool.query( @@ -241,32 +255,42 @@ const [rsh] = await pool.query( console.log(rsh.affectedRows); ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -下面的查询会删除一条 `Player` 记录,其 ID 为 `1`: +以下查询删除 ID 为 `1` 的 `Player` 记录: ```javascript const [rsh] = await pool.query('DELETE FROM players WHERE id = ?;', [1]); console.log(rsh.affectedRows); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用注意事项 -- 推荐使用[连接池](https://github.com/sidorares/node-mysql2#using-connection-pools)来管理数据库连接,以减少频繁建立和销毁连接所带来的性能开销。 -- 为了避免 SQL 注入的风险,推荐使用[预处理语句](https://github.com/sidorares/node-mysql2#using-prepared-statements)执行 SQL。 -- 在不涉及大量复杂 SQL 语句的场景下,推荐使用 ORM 框架(例如:[Sequelize](https://sequelize.org/)、[TypeORM](https://typeorm.io/) 或 [Prisma](https://www.prisma.io/))来提升你的开发效率。 +- 使用[连接池](https://github.com/sidorares/node-mysql2#using-connection-pools)管理数据库连接可以减少频繁建立和销毁连接带来的性能开销。 +- 为了避免 SQL 注入,建议使用[预处理语句](https://github.com/sidorares/node-mysql2#using-prepared-statements)。 +- 在不涉及太多复杂 SQL 语句的场景下,使用 [Sequelize](https://sequelize.org/)、[TypeORM](https://typeorm.io/) 或 [Prisma](https://www.prisma.io/) 等 ORM 框架可以大大提高开发效率。 ## 下一步 -- 关于使用 ORM 框架和 Next.js 构建复杂应用程序的更多细节,可以参考 [tidb-prisma-vercel-demo](https://github.com/pingcap/tidb-prisma-vercel-demo)。 -- 关于 mysql2 的更多使用方法,可以参考 [mysql2 的官方文档](https://sidorares.github.io/node-mysql2/zh-CN/docs)。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 要了解如何使用 ORM 和 Next.js 构建复杂应用程序的更多详细信息,请参阅[我们的书店演示](https://github.com/pingcap/tidb-prisma-vercel-demo)。 +- 从 [node-mysql2 文档](https://sidorares.github.io/node-mysql2/docs/documentation)了解更多 node-mysql2 驱动程序的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,或从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。 + diff --git a/develop/dev-guide-sample-application-nodejs-mysql2.md b/develop/dev-guide-sample-application-nodejs-mysql2.md index c51958bd5e54..7c8ad2654b5e 100644 --- a/develop/dev-guide-sample-application-nodejs-mysql2.md +++ b/develop/dev-guide-sample-application-nodejs-mysql2.md @@ -1,185 +1,194 @@ --- -title: 使用 node-mysql2 连接到 TiDB -summary: 本文描述了 TiDB 和 node-mysql2 的连接步骤,并给出了简单示例代码片段。 +title: 使用 node-mysql2 连接 TiDB +summary: 了解如何使用 node-mysql2 连接 TiDB。本教程提供使用 node-mysql2 操作 TiDB 的 Node.js 示例代码片段。 --- -# 使用 node-mysql2 连接到 TiDB +# 使用 node-mysql2 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[node-mysql2](https://github.com/sidorares/node-mysql2) 是一个与 [mysqljs/mysql](https://github.com/mysqljs/mysql) 兼容的面向 Node.js 的 MySQL 驱动。 +TiDB 是一个兼容 MySQL 的数据库,而 [node-mysql2](https://github.com/sidorares/node-mysql2) 是一个快速的、兼容 [mysqljs/mysql](https://github.com/mysqljs/mysql) 的 Node.js MySQL 驱动程序。 -本文档将展示如何使用 TiDB 和 node-mysql2 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 node-mysql2 完成以下任务: -- 配置你的环境。 -- 使用 node-mysql2 驱动连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置环境。 +- 使用 node-mysql2 连接到 TiDB 集群。 +- 构建并运行应用程序。您也可以查看基本 CRUD 操作的[示例代码片段](#示例代码片段)。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 + +## 前提条件 + +要完成本教程,您需要: + +- 在您的机器上安装 [Node.js](https://nodejs.org/en) >= 16.x。 +- 在您的机器上安装 [Git](https://git-scm.com/downloads)。 +- 一个正在运行的 TiDB 集群。 -## 前置需求 +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -为了能够顺利完成本教程,你需要提前: + -- 在你的机器上安装 [Node.js](https://nodejs.org/en) 16.x 或以上版本。 -- 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 -如果你还没有 TiDB 集群,可以按照以下方式创建: + + -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -## 运行代码并连接到 TiDB + -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +## 运行示例应用程序连接到 TiDB -### 第 1 步:克隆示例代码仓库到本地 +本节演示如何运行示例应用程序代码并连接到 TiDB。 -运行以下命令,将示例代码仓库克隆到本地: +### 步骤 1:克隆示例应用程序仓库 -```bash +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-nodejs-mysql2-quickstart.git cd tidb-nodejs-mysql2-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖 (包括 `mysql2` 和 `dotenv` 依赖包): +运行以下命令安装示例应用程序所需的包(包括 `mysql2` 和 `dotenv`): -```bash +```shell npm install ``` -在你现有的项目当中,你可以通过以下命令安装 `mysql2` 和 `dotenv` 依赖包(`dotenv` 用于从 `.env` 文件中读取环境变量): +
+为现有项目安装依赖 + +对于您的现有项目,运行以下命令安装包: -```bash +```shell npm install mysql2 dotenv --save ``` -### 第 3 步:配置连接信息 +
-根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +### 步骤 3:配置连接信息 - +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 +
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的选项配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为运行示例代码所在的操作系统。 + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接工具**设置为 `General`。 + - **操作系统**与您运行应用程序的操作系统匹配。 - > **Note** - > - > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 - -4. 如果你还没有设置密码,点击 **Generate Password** 按钮生成一个随机的密码。 +4. 如果您还没有设置密码,点击**生成密码**生成随机密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +6. 编辑 `.env` 文件,按如下设置环境变量,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv - TIDB_HOST='{host}' - TIDB_PORT='4000' - TIDB_USER='{user}' - TIDB_PASSWORD='{password}' - TIDB_DATABASE='test' - TIDB_ENABLE_SSL='true' + TIDB_HOST={host} + TIDB_PORT=4000 + TIDB_USER={user} + TIDB_PASSWORD={password} + TIDB_DATABASE=test + TIDB_ENABLE_SSL=true ``` - > **Note** - > - > 当你使用 Public Endpoint 连接 TiDB Cloud Serverless 集群时,**必须**启用 TLS 连接,请将 `TIDB_ENABLE_SSL` 修改为 `true`。 + > **注意** + > + > 对于 TiDB Cloud Serverless,使用公共端点时**必须**通过 `TIDB_ENABLE_SSL` 启用 TLS 连接。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 +2. 点击右上角的**连接**。将显示连接对话框。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - ```bash + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: + + ```shell cp .env.example .env ``` -5. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +5. 编辑 `.env` 文件,按如下设置环境变量,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv - TIDB_HOST='{host}' - TIDB_PORT='4000' - TIDB_USER='{user}' - TIDB_PASSWORD='{password}' - TIDB_DATABASE='test' - TIDB_ENABLE_SSL='true' - TIDB_CA_PATH='{downloaded_ssl_ca_path}' + TIDB_HOST={host} + TIDB_PORT=4000 + TIDB_USER={user} + TIDB_PASSWORD={password} + TIDB_DATABASE=test + TIDB_ENABLE_SSL=true + TIDB_CA_PATH={downloaded_ssl_ca_path} ``` - > **Note** + > **注意** > - > 推荐在使用 Public Endpoint 连接 TiDB Cloud Dedicated 集群时,启用 TLS 连接。 + > 使用公共端点连接到 TiDB Cloud Dedicated 时,建议启用 TLS 连接。 > - > 为了启用 TLS (SSL) 连接,将 `TIDB_ENABLE_SSL` 修改为 `true`,并使用 `TIDB_CA_PATH` 指定从连接对话框中下载的 CA 证书的文件路径。 + > 要启用 TLS 连接,将 `TIDB_ENABLE_SSL` 修改为 `true`,并使用 `TIDB_CA_PATH` 指定从连接对话框下载的 CA 证书的文件路径。 6. 保存 `.env` 文件。
+
-
+1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: - - ```bash + ```shell cp .env.example .env ``` -2. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为你的 TiDB 集群的连接参数值: +2. 编辑 `.env` 文件,按如下设置环境变量,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv - TIDB_HOST='{host}' - TIDB_PORT='4000' - TIDB_USER='root' - TIDB_PASSWORD='{password}' - TIDB_DATABASE='test' + TIDB_HOST={host} + TIDB_PORT=4000 + TIDB_USER=root + TIDB_PASSWORD={password} + TIDB_DATABASE=test ``` + 如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 + 3. 保存 `.env` 文件。
- -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -运行下述命令,执行示例代码: +运行以下命令执行示例代码: -```bash -npm run start +```shell +npm start ``` -**预期输出结果:** - -如果连接成功,你的终端将会输出所连接集群的版本信息: +如果连接成功,控制台将输出 TiDB 集群的版本,如下所示: ``` 🔌 Connected to TiDB cluster! (TiDB version: 8.0.11-TiDB-v8.1.2) @@ -194,69 +203,77 @@ npm run start ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-nodejs-mysql2-quickstart](https://github.com/tidb-samples/tidb-nodejs-mysql2-quickstart)。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -### 连接到 TiDB +有关完整的示例代码和如何运行它,请查看 [tidb-samples/tidb-nodejs-mysql2-quickstart](https://github.com/tidb-samples/tidb-nodejs-mysql2-quickstart) 仓库。 -下面的代码使用环境变量中定义的连接选项来建立与 TiDB 集群的连接。 +### 使用连接选项连接 + +以下代码使用环境变量中定义的选项建立与 TiDB 的连接: ```javascript -// 步骤 1. 导入 'mysql2' 和 'dotenv' 依赖包。 +// 步骤 1. 导入 'mysql' 和 'dotenv' 包。 import { createConnection } from "mysql2/promise"; import dotenv from "dotenv"; import * as fs from "fs"; -// 步骤 2. 将连接参数从 .env 文件中读取到 process.env 中。 +// 步骤 2. 从 .env 文件加载环境变量到 process.env。 dotenv.config(); async function main() { - // 步骤 3. 创建与 TiDB 集群的连接。 - const options = { - host: process.env.TIDB_HOST || '127.0.0.1', - port: process.env.TIDB_PORT || 4000, - user: process.env.TIDB_USER || 'root', - password: process.env.TIDB_PASSWORD || '', - database: process.env.TIDB_DATABASE || 'test', - ssl: process.env.TIDB_ENABLE_SSL === 'true' ? { - minVersion: 'TLSv1.2', - ca: process.env.TIDB_CA_PATH ? fs.readFileSync(process.env.TIDB_CA_PATH) : undefined - } : null, - } - const conn = await createConnection(options); - - // 步骤 4. 执行 SQL 语句。 - - // 步骤 5. 关闭连接。 - await conn.end(); + // 步骤 3. 创建到 TiDB 集群的连接。 + const options = { + host: process.env.TIDB_HOST || '127.0.0.1', + port: process.env.TIDB_PORT || 4000, + user: process.env.TIDB_USER || 'root', + password: process.env.TIDB_PASSWORD || '', + database: process.env.TIDB_DATABASE || 'test', + ssl: process.env.TIDB_ENABLE_SSL === 'true' ? { + minVersion: 'TLSv1.2', + ca: process.env.TIDB_CA_PATH ? fs.readFileSync(process.env.TIDB_CA_PATH) : undefined + } : null, + } + const conn = await createConnection(options); + + // 步骤 4. 执行一些 SQL 操作... + + // 步骤 5. 关闭连接。 + await conn.end(); } void main(); ``` -> **Note** +> **注意** > -> 使用 Public Endpoint 连接 TiDB Cloud Serverless 时,**必须**启用 TLS 连接,请将 `TIDB_ENABLE_SSL` 修改为 `true`。但是你**不需要**通过 `TIDB_CA_PATH` 指定 SSL CA 证书,因为 Node.js 默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates),该证书已被 TiDB Cloud Serverless 信任。 +> 对于 TiDB Cloud Serverless,使用公共端点时,您**必须**通过 `TIDB_ENABLE_SSL` 启用 TLS 连接。但是,您**不需要**通过 `TIDB_CA_PATH` 指定 SSL CA 证书,因为 Node.js 默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates),该证书受 TiDB Cloud Serverless 信任。 ### 插入数据 +以下查询创建一个 `Player` 记录并返回一个 `ResultSetHeader` 对象: + ```javascript const [rsh] = await conn.query('INSERT INTO players (coins, goods) VALUES (?, ?);', [100, 100]); console.log(rsh.insertId); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 +以下查询通过 ID `1` 返回一个 `Player` 记录: + ```javascript const [rows] = await conn.query('SELECT id, coins, goods FROM players WHERE id = ?;', [1]); console.log(rows[0]); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 +以下查询为 ID 为 `1` 的 `Player` 增加 `50` 个硬币和 `50` 个物品: + ```javascript const [rsh] = await conn.query( 'UPDATE players SET coins = coins + ?, goods = goods + ? WHERE id = ?;', @@ -265,27 +282,43 @@ const [rsh] = await conn.query( console.log(rsh.affectedRows); ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 +以下查询删除 ID 为 `1` 的 `Player` 记录: + ```javascript const [rsh] = await conn.query('DELETE FROM players WHERE id = ?;', [1]); console.log(rsh.affectedRows); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 -- 推荐使用[连接池](https://sidorares.github.io/node-mysql2/docs#using-connection-pools)来管理数据库连接,以减少频繁建立和销毁连接所带来的性能开销。 -- 为了避免 SQL 注入的风险,推荐使用[预处理语句](https://sidorares.github.io/node-mysql2/docs#using-prepared-statements)执行 SQL。 -- 在不涉及大量复杂 SQL 语句的场景下,推荐使用 ORM 框架 (例如:[Sequelize](https://sequelize.org/)、[TypeORM](https://typeorm.io/) 或 [Prisma](https://www.prisma.io/)) 来提升你的开发效率。 -- 当你在数据表中使用到 `BIGINT` 和 `DECIMAL` 类型列时,需要开启 Driver 的 `supportBigNumbers: true` 选项。 -- 为了避免由于网络原因出现的 `read ECONNRESET` Socket 错误,可以在 Driver 上开启 `enableKeepAlive: true` 选项。(相关 Issue: [sidorares/node-mysql2#683](https://github.com/sidorares/node-mysql2/issues/683)) +- 使用[连接池](https://github.com/sidorares/node-mysql2#using-connection-pools)管理数据库连接可以减少频繁建立和销毁连接带来的性能开销。 +- 为了避免 SQL 注入,建议使用[预处理语句](https://github.com/sidorares/node-mysql2#using-prepared-statements)。 +- 在不涉及太多复杂 SQL 语句的场景中,使用 [Sequelize](https://sequelize.org/)、[TypeORM](https://typeorm.io/) 或 [Prisma](https://www.prisma.io/) 等 ORM 框架可以大大提高开发效率。 +- 在处理数据库中的大数字(`BIGINT` 和 `DECIMAL` 列)时,建议启用 `supportBigNumbers: true` 选项。 +- 建议启用 `enableKeepAlive: true` 选项,以避免因网络问题导致的套接字错误 `read ECONNRESET`。(相关问题:[sidorares/node-mysql2#683](https://github.com/sidorares/node-mysql2/issues/683)) ## 下一步 -- 关于 node-mysql2 的更多使用方法,可以参考 [node-mysql2 的 GitHub 仓库](https://github.com/sidorares/node-mysql2)。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供了专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [node-mysql2 文档](https://github.com/sidorares/node-mysql2#readme)了解更多 node-mysql2 驱动程序的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[查询数据](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-sample-application-nodejs-mysqljs.md b/develop/dev-guide-sample-application-nodejs-mysqljs.md index cbaaad0d8ff8..0aefdfd59f5f 100644 --- a/develop/dev-guide-sample-application-nodejs-mysqljs.md +++ b/develop/dev-guide-sample-application-nodejs-mysqljs.md @@ -1,185 +1,194 @@ --- -title: 使用 mysql.js 连接到 TiDB -summary: 本文描述了 TiDB 和 mysql.js 的连接步骤,并给出了简单示例代码片段。 +title: 使用 mysql.js 连接 TiDB +summary: 学习如何使用 mysql.js 连接 TiDB。本教程提供使用 mysql.js 操作 TiDB 的 Node.js 示例代码片段。 --- -# 使用 mysql.js 连接到 TiDB +# 使用 mysql.js 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[mysql.js](https://github.com/mysqljs/mysql) 是一个纯 Node.js 代码编写的实现了 MySQL 协议的 JavaScript 客户端。 +TiDB 是一个兼容 MySQL 的数据库,而 [mysql.js](https://github.com/mysqljs/mysql) 驱动是一个纯 Node.js JavaScript 客户端,实现了 MySQL 协议。 -本文档将展示如何使用 TiDB 和 mysql.js 来构造一个简单的 CRUD 应用程序。 +在本教程中,你可以学习如何使用 TiDB 和 mysql.js 驱动完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 mysql.js 驱动连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。你也可以查看基本 CRUD 操作的[示例代码片段](#示例代码片段)。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本教程,你需要提前: +要完成本教程,你需要: -- 在你的机器上安装 [Node.js](https://nodejs.org/en) 16.x 或以上版本。 +- 在你的机器上安装 [Node.js](https://nodejs.org/zh-cn) >= 16.x。 - 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- 一个正在运行的 TiDB 集群。 + +**如果你还没有 TiDB 集群,可以按照以下方式创建:** + + + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + -如果你还没有 TiDB 集群,可以按照以下方式创建: +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#部署本地测试集群)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 + -## 运行代码并连接到 TiDB +## 运行示例程序连接 TiDB -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +本节演示如何运行示例应用程序代码并连接到 TiDB。 -### 第 1 步:克隆示例代码仓库到本地 +### 步骤 1:克隆示例程序仓库 -运行以下命令,将示例代码仓库克隆到本地: +在终端窗口中运行以下命令来克隆示例代码仓库: -```bash +```shell git clone https://github.com/tidb-samples/tidb-nodejs-mysqljs-quickstart.git cd tidb-nodejs-mysqljs-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖 (包括 `mysql` 和 `dotenv` 依赖包): +运行以下命令安装示例程序所需的包(包括 `mysql` 和 `dotenv`): -```bash +```shell npm install ``` -在你现有的项目当中,你可以通过以下命令安装 `mysql` 和 `dotenv` 依赖包(`dotenv` 用于从 `.env` 文件中读取环境变量): +
+为现有项目安装依赖 -```bash +对于你的现有项目,运行以下命令安装包: + +```shell npm install mysql dotenv --save ``` -### 第 3 步:配置连接信息 +
-根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +### 步骤 3:配置连接信息 - +根据你选择的 TiDB 部署方式连接到 TiDB 集群。 +
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群名称进入集群概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**,将显示连接对话框。 -3. 确认对话框中的选项配置和你的运行环境一致。 +3. 确保连接对话框中的配置与你的运行环境相匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为运行示例代码所在的操作系统。 + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接方式**设置为 `General`。 + - **操作系统**与运行应用程序的操作系统匹配。 - > **Note** - > - > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 +4. 如果你还没有设置密码,点击**生成密码**生成随机密码。 -4. 如果你还没有设置密码,点击 **Generate Password** 按钮生成一个随机的密码。 +5. 运行以下命令复制 `.env.example` 并重命名为 `.env`: -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: - - ```bash + ```shell cp .env.example .env ``` -6. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +6. 编辑 `.env` 文件,按如下方式设置环境变量,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv - TIDB_HOST='{host}' - TIDB_PORT='4000' - TIDB_USER='{user}' - TIDB_PASSWORD='{password}' - TIDB_DATABASE='test' - TIDB_ENABLE_SSL='true' + TIDB_HOST={host} + TIDB_PORT=4000 + TIDB_USER={user} + TIDB_PASSWORD={password} + TIDB_DATABASE=test + TIDB_ENABLE_SSL=true ``` - > **Note** + > **注意** > - > 当你使用 Public Endpoint 连接 TiDB Cloud Serverless 集群时,**必须**启用 TLS 连接,请将 `TIDB_ENABLE_SSL` 修改为 `true`。 + > 对于 TiDB Cloud Serverless,使用公共端点时**必须**通过 `TIDB_ENABLE_SSL` 启用 TLS 连接。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群名称进入集群概览页面。 + +2. 点击右上角的**连接**,将显示连接对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果你还没有配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**专用端点**和 **VPC 对等连接**连接类型。更多信息,请参阅[连接到 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +5. 编辑 `.env` 文件,按如下方式设置环境变量,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv - TIDB_HOST='{host}' - TIDB_PORT='4000' - TIDB_USER='{user}' - TIDB_PASSWORD='{password}' - TIDB_DATABASE='test' - TIDB_ENABLE_SSL='true' - TIDB_CA_PATH='{downloaded_ssl_ca_path}' + TIDB_HOST={host} + TIDB_PORT=4000 + TIDB_USER={user} + TIDB_PASSWORD={password} + TIDB_DATABASE=test + TIDB_ENABLE_SSL=true + TIDB_CA_PATH={downloaded_ssl_ca_path} ``` - > **Note** + > **注意** > - > 推荐在使用 Public Endpoint 连接 TiDB Cloud Dedicated 集群时,启用 TLS 连接。 - > - > 为了启用 TLS (SSL) 连接,将 `TIDB_ENABLE_SSL` 修改为 `true`,并使用 `TIDB_CA_PATH` 指定从连接对话框中下载的 CA 证书的文件路径。 + > 使用公共端点连接到 TiDB Cloud Dedicated 时,建议启用 TLS 连接。 + > + > 要启用 TLS 连接,请将 `TIDB_ENABLE_SSL` 修改为 `true`,并使用 `TIDB_CA_PATH` 指定从连接对话框下载的 CA 证书文件路径。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为你的 TiDB 集群的连接参数值: +2. 编辑 `.env` 文件,将相应的占位符 `{}` 替换为集群的连接参数。示例配置如下: ```dotenv - TIDB_HOST='{host}' - TIDB_PORT='4000' - TIDB_USER='root' - TIDB_PASSWORD='{password}' - TIDB_DATABASE='test' + TIDB_HOST={host} + TIDB_PORT=4000 + TIDB_USER=root + TIDB_PASSWORD={password} + TIDB_DATABASE=test ``` + 如果你在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 + 3. 保存 `.env` 文件。
- -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -运行下述命令,执行示例代码: +运行以下命令执行示例代码: -```bash -npm run start +```shell +npm start ``` -**预期输出结果:** - -如果连接成功,你的终端将会输出所连接集群的版本信息: +如果连接成功,控制台将输出 TiDB 集群的版本,如下所示: ``` 🔌 Connected to TiDB cluster! (TiDB version: 8.0.11-TiDB-v8.1.2) @@ -194,64 +203,66 @@ npm run start ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-nodejs-mysqljs-quickstart](https://github.com/tidb-samples/tidb-nodejs-mysqljs-quickstart)。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 + +有关完整的示例代码和如何运行它,请查看 [tidb-samples/tidb-nodejs-mysqljs-quickstart](https://github.com/tidb-samples/tidb-nodejs-mysqljs-quickstart) 仓库。 -### 连接到 TiDB +### 使用连接选项连接 -下面的代码使用环境变量中定义的连接选项来建立与 TiDB 集群的连接。 +以下代码使用环境变量中定义的选项建立与 TiDB 的连接: ```javascript -// 步骤 1. 导入 'mysql' 和 'dotenv' 依赖包。 +// 步骤 1. 导入 'mysql' 和 'dotenv' 包。 import { createConnection } from "mysql"; import dotenv from "dotenv"; import * as fs from "fs"; -// 步骤 2. 将连接参数从 .env 文件中读取到 process.env 中。 +// 步骤 2. 从 .env 文件加载环境变量到 process.env。 dotenv.config(); -// 步骤 3. 创建与 TiDB 集群的连接。 +// 步骤 3. 创建到 TiDB 集群的连接。 const options = { - host: process.env.TIDB_HOST || '127.0.0.1', - port: process.env.TIDB_PORT || 4000, - user: process.env.TIDB_USER || 'root', - password: process.env.TIDB_PASSWORD || '', - database: process.env.TIDB_DATABASE || 'test', - ssl: process.env.TIDB_ENABLE_SSL === 'true' ? { - minVersion: 'TLSv1.2', - ca: process.env.TIDB_CA_PATH ? fs.readFileSync(process.env.TIDB_CA_PATH) : undefined - } : null, + host: process.env.TIDB_HOST || '127.0.0.1', + port: process.env.TIDB_PORT || 4000, + user: process.env.TIDB_USER || 'root', + password: process.env.TIDB_PASSWORD || '', + database: process.env.TIDB_DATABASE || 'test', + ssl: process.env.TIDB_ENABLE_SSL === 'true' ? { + minVersion: 'TLSv1.2', + ca: process.env.TIDB_CA_PATH ? fs.readFileSync(process.env.TIDB_CA_PATH) : undefined + } : null, } const conn = createConnection(options); -// 步骤 4. 执行 SQL 语句。 +// 步骤 4. 执行一些 SQL 操作... // 步骤 5. 关闭连接。 conn.end(); ``` -> **Note** -> -> 使用 Public Endpoint 连接 TiDB Cloud Serverless 时,**必须**启用 TLS 连接,请将 `TIDB_ENABLE_SSL` 修改为 `true`。但是你**不需要**通过 `TIDB_CA_PATH` 指定 SSL CA 证书,因为 Node.js 默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates),该证书已被 TiDB Cloud Serverless 信任。 +> **注意** +> +> 对于 TiDB Cloud Serverless,使用公共端点时,你**必须**通过 `TIDB_ENABLE_SSL` 启用 TLS 连接。但是,你**不需要**通过 `TIDB_CA_PATH` 指定 SSL CA 证书,因为 Node.js 默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates),该证书受 TiDB Cloud Serverless 信任。 ### 插入数据 -下面的代码创建了一条 `Player` 记录,并返回了该记录的 ID。 +以下查询创建一条 `Player` 记录并返回新创建记录的 ID: ```javascript -conn.query('INSERT INTO players (coins, goods) VALUES (?, ?);', [coins, goods], (err, ok) => { +conn.query('INSERT INTO players (coins, goods) VALUES (?, ?);', [100, 100], (err, ok) => { if (err) { - console.error(err); + console.error(err); } else { - console.log(ok.insertId); + console.log(ok.insertId); } }); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参阅[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -下面的查询返回了 ID 为 1 的 `Player` 记录。 +以下查询通过 ID `1` 返回一条 `Player` 记录: ```javascript conn.query('SELECT id, coins, goods FROM players WHERE id = ?;', [1], (err, rows) => { @@ -263,11 +274,11 @@ conn.query('SELECT id, coins, goods FROM players WHERE id = ?;', [1], (err, rows }); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参阅[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -下面的查询为 ID 为 1 的 `Player` 记录增加了 50 个金币和 50 个物品。 +以下查询为 ID 为 `1` 的 `Player` 增加 `50` 个金币和 `50` 个商品: ```javascript conn.query( @@ -277,46 +288,60 @@ conn.query( if (err) { console.error(err); } else { - console.log(ok.affectedRows); + console.log(ok.affectedRows); } } ); ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参阅[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -下面的查询删除了 ID 为 1 的 `Player` 记录。 +以下查询删除 ID 为 `1` 的 `Player` 记录: ```javascript conn.query('DELETE FROM players WHERE id = ?;', [1], (err, ok) => { - if (err) { - reject(err); - } else { - resolve(ok.affectedRows); - } + if (err) { + reject(err); + } else { + resolve(ok.affectedRows); + } }); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参阅[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 使用提示 -- 推荐使用[连接池](https://github.com/mysqljs/mysql#pooling-connections)来管理数据库连接,以减少频繁建立和销毁连接所带来的性能开销。 -- 为了避免 SQL 注入的风险,请在执行 SQL 语句前[传递到 SQL 中的值进行转义](https://github.com/mysqljs/mysql#escaping-query-values)。 +- 使用[连接池](https://github.com/mysqljs/mysql#pooling-connections)管理数据库连接可以减少频繁建立和销毁连接带来的性能开销。 +- 为了避免 SQL 注入攻击,建议在执行 SQL 之前使用[转义查询值](https://github.com/mysqljs/mysql#escaping-query-values)。 - > **Note** - > - > `mysqljs/mysql` 包目前还不支持预处理语句,它只在客户端对值进行转义 (相关 issue: [mysqljs/mysql#274](https://github.com/mysqljs/mysql/issues/274))。 - > - > 如果你希望使用预处理语句来避免 SQL 注入或提升批量插入/更新的效率,推荐使用 [mysql2](https://github.com/sidorares/node-mysql2) 包。 + > **注意** + > + > `mysqljs/mysql` 包尚不支持预处理语句,它只在客户端转义值(相关问题:[mysqljs/mysql#274](https://github.com/mysqljs/mysql/issues/274))。 + > + > 如果你想使用此功能来避免 SQL 注入或提高批量插入/更新的效率,建议使用 [mysql2](https://github.com/sidorares/node-mysql2) 包。 -- 在不涉及大量复杂 SQL 语句的场景下, 推荐使用 ORM 框架 (例如:[Sequelize](https://sequelize.org/), [TypeORM](https://typeorm.io/), 或 [Prisma](https://www.prisma.io/)) 来提升你的开发效率. -- 当你在数据表中使用到 `BIGINT` 和 `DECIMAL` 类型列时,需要开启 Driver 的 `supportBigNumbers: true` 选项. +- 在没有大量复杂 SQL 语句的场景下,使用 ORM 框架可以提高开发效率,例如:[Sequelize](https://sequelize.org/)、[TypeORM](https://typeorm.io/) 和 [Prisma](/develop/dev-guide-sample-application-nodejs-prisma.md)。 +- 在处理数据库中的大数字(`BIGINT` 和 `DECIMAL` 列)时,建议启用 `supportBigNumbers: true` 选项。 ## 下一步 -- 关于 mysql.js 驱动的更多使用方法,可以参考 [mysql.js 的 GitHub 仓库](https://github.com/mysqljs/mysql)。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供了专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [mysql.js 文档](https://github.com/mysqljs/mysql#readme)了解更多 mysql.js 驱动的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[查询数据](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区寻求帮助,或者[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区寻求帮助,或者[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-sample-application-nodejs-prisma.md b/develop/dev-guide-sample-application-nodejs-prisma.md index c7f2461481a4..0c63d854f2f4 100644 --- a/develop/dev-guide-sample-application-nodejs-prisma.md +++ b/develop/dev-guide-sample-application-nodejs-prisma.md @@ -1,105 +1,115 @@ --- -title: 使用 Prisma 连接到 TiDB -summary: 本文描述了 TiDB 和 Prisma 的连接步骤,并给出了简单示例代码片段。 +title: 使用 Prisma 连接 TiDB +summary: 了解如何使用 Prisma 连接 TiDB。本教程提供使用 Prisma 操作 TiDB 的 Node.js 示例代码片段。 --- -# 使用 Prisma 连接到 TiDB +# 使用 Prisma 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[Prisma](https://www.prisma.io/) 是当前流行的 Node.js ORM 框架之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [Prisma](https://github.com/prisma/prisma) 是一个流行的开源 Node.js ORM 框架。 -本文档将展示如何使用 TiDB 和 Prisma 来构造一个简单的 CRUD 应用程序。 +在本教程中,您可以学习如何使用 TiDB 和 Prisma 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 Prisma 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看基本 CRUD 操作的[示例代码片段](#示例代码片段)。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本教程,你需要提前: +要完成本教程,您需要: -- 在你的机器上安装 [Node.js](https://nodejs.org/en) 16.x 或以上版本。 -- 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- 在您的机器上安装 [Node.js](https://nodejs.org/en) >= 16.x。 +- 在您的机器上安装 [Git](https://git-scm.com/downloads)。 +- 一个正在运行的 TiDB 集群。 -如果你还没有 TiDB 集群,可以按照以下方式创建: +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 + -## 运行代码并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + + -### 第 1 步:克隆示例代码仓库到本地 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -运行以下命令,将示例代码仓库克隆到本地: + -```bash +## 运行示例应用程序连接到 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-nodejs-prisma-quickstart.git cd tidb-nodejs-prisma-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖 (包括 `prisma` 依赖包): +运行以下命令安装示例应用程序所需的包(包括 `prisma`): -```bash +```shell npm install ``` -在你现有的项目当中,你可以通过以下命令安装所需要的依赖包: +
+为现有项目安装依赖 + +对于您的现有项目,运行以下命令安装包: -```bash +```shell npm install prisma typescript ts-node @types/node --save-dev ``` -### 第 3 步:配置连接信息 +
-根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +### 步骤 3:提供连接参数 - +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 +
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的选项配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `Prisma`。 - - **Operating System** 为运行示例代码所在的操作系统。 + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接工具**设置为 `Prisma`。 + - **操作系统**与您运行应用程序的操作系统匹配。 - > **Note** - > - > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 - -4. 如果你还没有设置密码,点击 **Generate Password** 按钮生成一个随机的密码。 +4. 如果您还没有设置密码,点击**生成密码**生成随机密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 编辑 `.env` 文件,按照如下格式设置环境变量 `DATABASE_URL`,将占位符 `{}` 替换为从连接对话框中复制的连接字符串: +6. 编辑 `.env` 文件,按如下设置环境变量 `DATABASE_URL`,并将相应的占位符 `{}` 替换为连接对话框中的连接字符串: ```dotenv DATABASE_URL='{connection_string}' ``` - > **Note** + > **注意** > - > 在使用 Public Endpoint 连接 TiDB Cloud Serverless 集群时,**必须**启用 TLS 连接,请将 `sslaccept` 参数设置为 `strict`。 + > 对于 TiDB Cloud Serverless,使用公共端点时,您**必须**通过设置 `sslaccept=strict` 启用 TLS 连接。 7. 保存 `.env` 文件。 -8. 在 `prisma/schema.prisma` 文件中,将 `provider` 修改为 `mysql`,并将 `url` 修改为 `env("DATABASE_URL")`: +8. 在 `prisma/schema.prisma` 中,设置 `mysql` 作为连接提供程序,并将 `env("DATABASE_URL")` 作为连接 URL: ```prisma datasource db { @@ -109,37 +119,36 @@ npm install prisma typescript ts-node @types/node --save-dev ```
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示连接对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 编辑 `.env` 文件,按照如下格式设置环境变量 `DATABASE_URL`,将占位符 `{}` 替换为从连接对话框中复制的参数值: +5. 编辑 `.env` 文件,按如下设置环境变量 `DATABASE_URL`,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv DATABASE_URL='mysql://{user}:{password}@{host}:4000/test?sslaccept=strict&sslcert={downloaded_ssl_ca_path}' ``` - > **Note** - > - > 推荐在使用 Public Endpoint 连接 TiDB Cloud Dedicated 集群时,启用 TLS 连接。 - > - > 为了启用 TLS (SSL) 连接,将 `DATABASE_URL` 末尾添加 `sslaccept=strict` 参数,并使用 `sslcert=/path/to/ca.pem` 参数指定从连接对话框中下载的 CA 证书的文件路径。 + > **注意** + > + > 对于 TiDB Cloud Serverless,使用公共端点时,**建议**通过设置 `sslaccept=strict` 启用 TLS 连接。当您设置 `sslaccept=strict` 启用 TLS 连接时,您**必须**通过 `sslcert=/path/to/ca.pem` 指定从连接对话框下载的 CA 证书的文件路径。 6. 保存 `.env` 文件。 -7. 在 `prisma/schema.prisma` 文件中,将 `provider` 修改为 `mysql`,并将 `url` 修改为 `env("DATABASE_URL")`: +7. 在 `prisma/schema.prisma` 中,设置 `mysql` 作为连接提供程序,并将 `env("DATABASE_URL")` 作为连接 URL: ```prisma datasource db { @@ -149,25 +158,25 @@ npm install prisma typescript ts-node @types/node --save-dev ```
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为你的 TiDB 集群的连接参数值: +2. 编辑 `.env` 文件,按如下设置环境变量 `DATABASE_URL`,将相应的占位符 `{}` 替换为您的 TiDB 集群的连接参数: ```dotenv DATABASE_URL='mysql://{user}:{password}@{host}:4000/test' ``` - 如果你在本地运行 TiDB 集群,默认的 Host 是 `127.0.0.1`, 默认用户名为 `root`, 密码为空。 + 如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。 -4. 在 `prisma/schema.prisma` 文件中,将 `provider` 修改为 `mysql`,并将 `url` 修改为 `env("DATABASE_URL")`: + +4. 在 `prisma/schema.prisma` 中,设置 `mysql` 作为连接提供程序,并将 `env("DATABASE_URL")` 作为连接 URL: ```prisma datasource db { @@ -177,21 +186,20 @@ npm install prisma typescript ts-node @types/node --save-dev ```
- -### 第 4 步:初始化表结构 +### 步骤 4:初始化数据库模式 -运行以下命令,使用 [Prisma Migrate](https://www.prisma.io/docs/concepts/components/prisma-migrate) 根据 `prisma/schema.prisma` 文件中的数据模型定义来初始化数据库表结构: +运行以下命令调用 [Prisma Migrate](https://www.prisma.io/docs/concepts/components/prisma-migrate) 使用 `prisma/prisma.schema` 中定义的数据模型初始化数据库。 ```shell npx prisma migrate dev ``` -**`prisma.schema` 文件中的模型定义:** +**`prisma.schema` 中定义的数据模型:** ```prisma -// 定义一个 Player 模型,表示 `players` 表。 +// 定义 Player 模型,表示 `players` 表。 model Player { id Int @id @default(autoincrement()) name String @unique(map: "uk_player_on_name") @db.VarChar(50) @@ -203,21 +211,21 @@ model Player { @@map("players") } -// 定义一个 Profile 模型,表示 `profiles` 表。 +// 定义 Profile 模型,表示 `profiles` 表。 model Profile { playerId Int @id @map("player_id") biography String @db.Text - // 定义 `Player` 和 `Profile` 模型之间的 1:1 关系,并使用外键约束。 + // 使用外键定义 `Player` 和 `Profile` 模型之间的 1:1 关系。 player Player @relation(fields: [playerId], references: [id], onDelete: Cascade, map: "fk_profile_on_player_id") @@map("profiles") } ``` -你可以通过查阅 Prisma 的 [Data model](https://www.prisma.io/docs/concepts/components/prisma-schema/data-model) 文档来了解如何在 `prisma.schema` 文件里定义数据模型。 +要了解如何在 Prisma 中定义数据模型,请查看[数据模型](https://www.prisma.io/docs/concepts/components/prisma-schema/data-model)文档。 -**预期执行结果:** +**预期执行输出:** ``` Your database is now in sync with your schema. @@ -225,20 +233,20 @@ Your database is now in sync with your schema. ✔ Generated Prisma Client (5.1.1 | library) to ./node_modules/@prisma/client in 54ms ``` -这个命令同时会根据 `prisma/schema.prisma` 文件中的模型定义,生成用于与数据库交互的 [Prisma Client](https://www.prisma.io/docs/concepts/components/prisma-client) 的代码。 +此命令还将根据 `prisma/prisma.schema` 生成用于访问 TiDB 数据库的 [Prisma Client](https://www.prisma.io/docs/concepts/components/prisma-client)。 -### 第 5 步:运行代码并查看结果 +### 步骤 5:运行代码 -运行下述命令,执行示例代码: +运行以下命令执行示例代码: -```bash +```shell npm start ``` **示例代码中的主要逻辑:** ```typescript -// 步骤 1. 导入自动生成的 `@prisma/client` 依赖包。 +// 步骤 1. 导入自动生成的 `@prisma/client` 包。 import {Player, PrismaClient} from '@prisma/client'; async function main(): Promise { @@ -246,10 +254,10 @@ async function main(): Promise { const prisma = new PrismaClient(); try { - // 步骤 3. 使用 Prisma Client 执行一些 CRUD 操作。 + // 步骤 3. 使用 Prisma Client 执行一些 CRUD 操作... } finally { - // 步骤 4. 断开 Prisma Client 的连接。 + // 步骤 4. 断开 Prisma Client 连接。 await prisma.$disconnect(); } } @@ -257,9 +265,9 @@ async function main(): Promise { void main(); ``` -**预期输出结果:** +**预期执行输出:** -如果连接成功,在你的终端上会输出所连接集群的版本信息。 +如果连接成功,终端将输出 TiDB 集群的版本,如下所示: ``` 🔌 Connected to TiDB cluster! (TiDB version: 8.0.11-TiDB-v8.1.2) @@ -271,94 +279,107 @@ void main(); ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-nodejs-prisma-quickstart](https://github.com/tidb-samples/tidb-nodejs-prisma-quickstart)。 +有关完整的示例代码和如何运行它,请查看 [tidb-samples/tidb-nodejs-prisma-quickstart](https://github.com/tidb-samples/tidb-nodejs-prisma-quickstart) 仓库。 ### 插入数据 -下面的查询会创建一条新的 `Player` 记录,并返回一个包含自增 ID 的 `Player` 对象: +以下查询创建一个 `Player` 记录,并返回创建的 `Player` 对象,其中包含由 TiDB 生成的 `id` 字段: -```typescript +```javascript const player: Player = await prisma.player.create({ - data: { - name: 'Alice', - coins: 100, - goods: 200, - createdAt: new Date(), - } + data: { + name: 'Alice', + coins: 100, + goods: 200, + createdAt: new Date(), + } }); -console.log(player.id); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -下面的查询会返回 ID 为 `101` 的 `Player` 记录,如果没有找到对应的记录,会返回 `null`: +以下查询返回 ID 为 `101` 的 `Player` 对象,如果未找到记录则返回 `null`: ```javascript const player: Player | null = prisma.player.findUnique({ - where: { - id: 101, - } + where: { + id: 101, + } }); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -下面的查询会将 ID 为 `101` 的 `Player` 记录的 `coins` 和 `goods` 字段的值分别增加 50: +以下查询为 ID 为 `101` 的 `Player` 增加 `50` 个硬币和 `50` 个物品: -```typescript +```javascript await prisma.player.update({ - where: { - id: 101, - }, - data: { - coins: { - increment: 50, - }, - goods: { - increment: 50, - }, - } + where: { + id: 101, + }, + data: { + coins: { + increment: 50, + }, + goods: { + increment: 50, + }, + } }); ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -下面的查询会删除 ID 为 `101` 的 `Player` 记录: +以下查询删除 ID 为 `101` 的 `Player`: -```typescript +```javascript await prisma.player.delete({ - where: { - id: 101, - } + where: { + id: 101, + } }); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 -### 外键约束与 Prisma Relation Mode +### 外键约束与 Prisma 关系模式 -你可以使用外键约束或 Prisma Relation Mode 来检查[参照完整性](https://zh.wikipedia.org/wiki/%E5%8F%82%E7%85%A7%E5%AE%8C%E6%95%B4%E6%80%A7): +要检查[引用完整性](https://en.wikipedia.org/wiki/Referential_integrity?useskin=vector),您可以使用外键约束或 Prisma 关系模式: -- [外键](/foreign-key.md)是 TiDB 从 v6.6.0 开始支持的实验特性,外键允许跨表交叉引用相关数据,外键约束则可以保证相关数据的一致性。 +- [外键](https://docs.pingcap.com/tidb/stable/foreign-key)是从 TiDB v6.6.0 开始支持的实验性功能,它允许跨表引用相关数据,并使用外键约束维护数据一致性。 > **警告:** > - > 外键功能通常适用于为**中小规模**的数据提供完整性和一致性约束校验,但是在大数据量和分布式数据库系统下,使用外键可能会导致严重的性能问题,并对系统产生不可预知的影响。如果计划使用外键,请进行充分验证后谨慎使用。 + > **外键适用于小型和中型数据量场景。**在大数据量场景中使用外键可能会导致严重的性能问题,并可能对系统产生不可预测的影响。如果您计划使用外键,请先进行彻底的验证,并谨慎使用。 -- [Prisma Relation Mode](https://www.prisma.io/docs/concepts/components/prisma-schema/relations/relation-mode) 是 Prisma Client 端对外键约束的模拟。该特性会对应用程序的性能产生一些影响,因为它需要额外的数据库查询来维护参照完整性。 +- [Prisma 关系模式](https://www.prisma.io/docs/concepts/components/prisma-schema/relations/relation-mode)是在 Prisma Client 端模拟引用完整性。但是,应该注意的是,这会带来性能影响,因为它需要额外的数据库查询来维护引用完整性。 ## 下一步 -- 关于 Prisma 的更多使用方法,可以参考 [Prisma 的官方文档](https://www.prisma.io/docs)。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [Prisma 文档](https://www.prisma.io/docs)了解更多 ORM 框架 Prisma 驱动程序的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[查询数据](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-sample-application-nodejs-sequelize.md b/develop/dev-guide-sample-application-nodejs-sequelize.md index adf9a732969d..fff735ed204d 100644 --- a/develop/dev-guide-sample-application-nodejs-sequelize.md +++ b/develop/dev-guide-sample-application-nodejs-sequelize.md @@ -1,96 +1,108 @@ --- -title: 使用 Sequelize 连接到 TiDB -summary: 本文描述了 TiDB 和 Sequelize 的连接步骤,并给出了简单示例代码片段。 +title: 使用 Sequelize 连接 TiDB +summary: 了解如何使用 Sequelize 连接 TiDB。本教程提供使用 Sequelize 操作 TiDB 的 Node.js 示例代码片段。 --- -# 使用 Sequelize 连接到 TiDB +# 使用 Sequelize 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[Sequelize](https://sequelize.org/) 是当前流行的 Node.js ORM 框架之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [Sequelize](https://sequelize.org/) 是一个流行的 Node.js ORM 框架。 -本文档将展示如何使用 TiDB 和 Sequelize 来构造一个简单的 CRUD 应用程序。 +在本教程中,您将学习如何使用 TiDB 和 Sequelize 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 Sequelize 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看基本 CRUD 操作的[示例代码片段](#示例代码片段)。 -> **Note** +> **注意** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本教程,你需要提前: +要完成本教程,您需要: -- 在你的机器上安装 [Node.js](https://nodejs.org/en) 18.x 或以上版本。 -- 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- [Node.js **18**](https://nodejs.org/en/download/) 或更高版本。 +- [Git](https://git-scm.com/downloads)。 +- 一个 TiDB 集群。 -如果你还没有 TiDB 集群,可以按照以下方式创建: + -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -## 运行代码并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + + -> **Note** +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 + + + +## 运行示例程序连接 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +> **注意** > -> 完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-nodejs-sequelize-quickstart](https://github.com/tidb-samples/tidb-nodejs-sequelize-quickstart)。 +> 有关完整的代码片段和运行说明,请参阅 [tidb-samples/tidb-nodejs-sequelize-quickstart](https://github.com/tidb-samples/tidb-nodejs-sequelize-quickstart) GitHub 仓库。 -### 第 1 步:克隆示例代码仓库到本地 +### 步骤 1:克隆示例程序仓库 -运行以下命令,将示例代码仓库克隆到本地: +在终端窗口中运行以下命令来克隆示例代码仓库: ```bash git clone git@github.com:tidb-samples/tidb-nodejs-sequelize-quickstart.git cd tidb-nodejs-sequelize-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 sequelize): +运行以下命令为示例程序安装所需的包(包括 `sequelize`): ```bash npm install ``` -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到 TiDB 集群。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的选项配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为运行示例代码所在的操作系统。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Note** + > **注意** > - > 在 Node.js 应用程序中,你无需提供 SSL CA 证书,因为在建立 TLS (SSL) 连接时,默认情况下 Node.js 使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates)。 + > 在 Node.js 应用程序中,您不必提供 SSL CA 证书,因为 Node.js 在建立 TLS (SSL) 连接时默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates)。 -4. 如果你还没有设置密码,点击 **Generate Password** 按钮生成一个随机的密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip** + > **提示** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经生成过密码,可以使用原密码,也可以点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +6. 编辑 `.env` 文件,按如下方式设置环境变量,用连接对话框中的连接参数替换相应的占位符 `{}`: ```dotenv TIDB_HOST='{host}' @@ -107,21 +119,23 @@ npm install
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示连接对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共端点**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共端点**连接类型外,TiDB Cloud Dedicated 还支持**专用端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +5. 编辑 `.env` 文件,按如下方式设置环境变量,用连接对话框中的连接参数替换相应的占位符 `{}`: ```shell TIDB_HOST='{host}' @@ -137,15 +151,15 @@ npm install
-
+
-1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为你的 TiDB 集群的连接参数值: +2. 编辑 `.env` 文件,按如下方式设置环境变量,用连接对话框中的连接参数替换相应的占位符 `{}`: ```shell TIDB_HOST='{host}' @@ -155,7 +169,7 @@ npm install TIDB_DB_NAME='test' ``` - 如果你在本地运行 TiDB 集群,默认的主机地址是 `127.0.0.1`,密码为空。 + 如果您在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。 @@ -163,16 +177,16 @@ npm install -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行示例程序 -运行以下命令,执行示例代码: +运行以下命令执行示例代码: ```shell npm start ```
-预期输出结果(部分): +**预期输出(部分):** ```shell INFO (app/10117): Getting sequelize instance... @@ -190,13 +204,13 @@ Executing (default): DELETE FROM `players` WHERE `id` = 6 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-nodejs-sequelize-quickstart](https://github.com/tidb-samples/tidb-nodejs-sequelize-quickstart)。 +有关完整的示例代码和运行方法,请查看 [tidb-samples/tidb-nodejs-sequelize-quickstart](https://github.com/tidb-samples/tidb-nodejs-sequelize-quickstart) 仓库。 ### 连接到 TiDB -下面的代码使用环境变量中定义的连接选项来建立与 TiDB 集群的连接。 +以下代码使用环境变量中定义的选项建立与 TiDB 的连接: ```typescript // src/lib/tidb.ts @@ -205,18 +219,18 @@ import { Sequelize } from 'sequelize'; export function initSequelize() { return new Sequelize({ dialect: 'mysql', - host: process.env.TIDB_HOST || 'localhost', // TiDB host, for example: {gateway-region}.aws.tidbcloud.com - port: Number(process.env.TIDB_PORT) || 4000, // TiDB port, default: 4000 - username: process.env.TIDB_USER || 'root', // TiDB user, for example: {prefix}.root - password: process.env.TIDB_PASSWORD || 'root', // TiDB password - database: process.env.TIDB_DB_NAME || 'test', // TiDB database name, default: test + host: process.env.TIDB_HOST || 'localhost', // TiDB 主机,例如:{gateway-region}.aws.tidbcloud.com + port: Number(process.env.TIDB_PORT) || 4000, // TiDB 端口,默认:4000 + username: process.env.TIDB_USER || 'root', // TiDB 用户,例如:{prefix}.root + password: process.env.TIDB_PASSWORD || 'root', // TiDB 密码 + database: process.env.TIDB_DB_NAME || 'test', // TiDB 数据库名称,默认:test dialectOptions: { ssl: - process.env?.TIDB_ENABLE_SSL === 'true' // (Optional) Enable SSL + process.env?.TIDB_ENABLE_SSL === 'true' // (可选)启用 SSL ? { minVersion: 'TLSv1.2', rejectUnauthorized: true, - ca: process.env.TIDB_CA_PATH // (Optional) Path to the custom CA certificate + ca: process.env.TIDB_CA_PATH // (可选)自定义 CA 证书的路径 ? readFileSync(process.env.TIDB_CA_PATH) : undefined, } @@ -242,7 +256,7 @@ export async function getSequelize() { ### 插入数据 -下面的查询会创建一条单独的 `Players` 记录,并返回一个 `Players` 对象: +以下查询创建一个 `Players` 记录并返回一个 `Players` 对象: ```typescript logger.info('Creating a new player...'); @@ -255,11 +269,11 @@ logger.info('Created a new player.'); logger.info(newPlayer.toJSON()); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -下面的查询会返回一条 `Players` 记录,其金币数量大于 `300`: +以下查询返回一个金币数量大于 `300` 的 `Players` 记录: ```typescript logger.info('Reading all players with coins > 300...'); @@ -274,11 +288,11 @@ logger.info('Read all players with coins > 300.'); logger.info(allPlayersWithCoinsGreaterThan300.map((p) => p.toJSON())); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -下面的查询会将 ID 为 `6` 的 `Player` 的金币数量和物品数量设置为 `700`,这个记录是在[插入数据](#插入数据)部分创建的: +以下查询将在[插入数据](#插入数据)部分创建的 ID 为 `6` 的 `Players` 的金币和物品数量设置为 `700`: ```typescript logger.info('Updating the new player...'); @@ -287,11 +301,11 @@ logger.info('Updated the new player.'); logger.info(newPlayer.toJSON()); ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -下面的查询会删除在[插入数据](#插入数据)部分创建的 `Player` 记录,其 ID 为 `6`: +以下查询删除在[插入数据](#插入数据)部分创建的 ID 为 `6` 的 `Player` 记录: ```typescript logger.info('Deleting the new player...'); @@ -301,14 +315,24 @@ logger.info('Deleted the new player.'); logger.info(deletedNewPlayer?.toJSON()); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于 Sequelize 的更多使用方法,可以参考 [Sequelize 的官方文档](https://sequelize.org/)。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [Sequelize 文档](https://sequelize.org/)中了解更多 ORM 框架 Sequelize 驱动程序的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区咨询,或者[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区咨询,或者[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,或从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。 + diff --git a/develop/dev-guide-sample-application-nodejs-typeorm.md b/develop/dev-guide-sample-application-nodejs-typeorm.md index 5f7cc338f0a2..fc35100b90bf 100644 --- a/develop/dev-guide-sample-application-nodejs-typeorm.md +++ b/develop/dev-guide-sample-application-nodejs-typeorm.md @@ -1,67 +1,77 @@ --- -title: 使用 TypeORM 连接到 TiDB -summary: 本文描述了 TiDB 和 TypeORM 的连接步骤,并给出了简单示例代码片段。 +title: 使用 TypeORM 连接 TiDB +summary: 学习如何使用 TypeORM 连接 TiDB。本教程提供使用 TypeORM 操作 TiDB 的 Node.js 示例代码片段。 --- -# 使用 TypeORM 连接到 TiDB +# 使用 TypeORM 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[TypeORM](https://typeorm.io/) 是当前流行的 Node.js ORM 框架之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [TypeORM](https://github.com/TypeORM/TypeORM) 是一个流行的 Node.js 开源 ORM 框架。 -本文档将展示如何使用 TiDB 和 TypeORM 来完成以下任务: +在本教程中,你可以学习如何使用 TiDB 和 TypeORM 完成以下任务: -- 配置你的环境。 -- 使用 TypeORM 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置你的环境。 +- 使用 TypeORM 连接到你的 TiDB 集群。 +- 构建并运行你的应用程序。你也可以找到基本 CRUD 操作的[示例代码片段](#示例代码片段)。 > **注意** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本教程,你需要提前: +要完成本教程,你需要: -- 在你的机器上安装 [Node.js](https://nodejs.org/en) 16.x 或以上版本。 +- 在你的机器上安装 [Node.js](https://nodejs.org/en) >= 16.x。 - 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- 一个正在运行的 TiDB 集群。 -如果你还没有 TiDB 集群,可以按照以下方式创建: +**如果你还没有 TiDB 集群,可以按照以下方式创建:** -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 + -## 运行代码并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)来创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + + -### 第 1 步:克隆示例代码仓库到本地 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)来创建本地集群。 -运行以下命令,将示例代码仓库克隆到本地: + -```bash +## 运行示例程序连接 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 第 1 步:克隆示例程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-nodejs-typeorm-quickstart.git cd tidb-nodejs-typeorm-quickstart ``` ### 第 2 步:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 `typeorm` 和 `mysql2` 依赖包): +运行以下命令来安装示例程序所需的包(包括 `typeorm` 和 `mysql2`): -```bash +```shell npm install ```
-在现有的项目中安装依赖 +为现有项目安装依赖 -在你现有的项目当中,你可以通过以下命令安装所需要的依赖包: +对于你的现有项目,运行以下命令来安装这些包: -- `typeorm`:面向 Node.js 应用的 ORM 框架。 -- `mysql2`:面向 Node.js 的 MySQL Driver 包。你也可以使用 `mysql`。 -- `dotenv`:用于从 `.env` 文件中读取环境变量。 -- `typescript`:TypeScript 编译器。 -- `ts-node`:用于在不编译的情况下直接执行 TypeScript 代码。 -- `@types/node`:用于提供 Node.js 的 TypeScript 类型定义。 +- `typeorm`:Node.js 的 ORM 框架。 +- `mysql2`:Node.js 的 MySQL 驱动程序。你也可以使用 `mysql` 驱动程序。 +- `dotenv`:从 `.env` 文件加载环境变量。 +- `typescript`:将 TypeScript 代码编译为 JavaScript。 +- `ts-node`:直接运行 TypeScript 代码而无需编译。 +- `@types/node`:为 Node.js 提供 TypeScript 类型定义。 ```shell npm install typeorm mysql2 dotenv --save @@ -72,36 +82,31 @@ npm install @types/node ts-node typescript --save-dev ### 第 3 步:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据你选择的 TiDB 部署选项连接到你的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 确认对话框中的选项配置和你的运行环境一致。 +3. 确保连接对话框中的配置与你的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为运行示例代码所在的操作系统。 + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接方式**设置为 `General`。 + - **操作系统**与运行应用程序的操作系统匹配。 - > **Note** - > - > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 +4. 如果你还没有设置密码,点击**生成密码**来生成随机密码。 -4. 如果你还没有设置密码,点击 **Generate Password** 按钮生成一个随机的密码。 +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: - - ```bash + ```shell cp .env.example .env ``` -6. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +6. 编辑 `.env` 文件,按如下方式设置环境变量,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv TIDB_HOST={host} @@ -112,31 +117,32 @@ npm install @types/node ts-node typescript --save-dev TIDB_ENABLE_SSL=true ``` - > **Note** + > **注意** > - > 当你使用 Public Endpoint 连接 TiDB Cloud Serverless 集群时,**必须**启用 TLS 连接,请将 `TIDB_ENABLE_SSL` 修改为 `true`。 + > 对于 TiDB Cloud Serverless,在使用公共端点时,你**必须**通过 `TIDB_ENABLE_SSL` 启用 TLS 连接。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA cert** 下载 CA 证书。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: + 如果你还没有配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - ```bash + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。更多信息,请参阅[连接到你的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: + + ```shell cp .env.example .env ``` -5. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为从连接对话框中复制的参数值: +5. 编辑 `.env` 文件,按如下方式设置环境变量,将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv TIDB_HOST={host} @@ -148,23 +154,22 @@ npm install @types/node ts-node typescript --save-dev TIDB_CA_PATH={downloaded_ssl_ca_path} ``` - > **Note** + > **注意** > - > 推荐在使用 Public Endpoint 连接 TiDB Cloud Dedicated 集群时,启用 TLS 连接。为了启用 TLS (SSL) 连接,将 `TIDB_ENABLE_SSL` 修改为 `true`,并使用 `TIDB_CA_PATH` 指定从连接对话框中下载的 CA 证书的文件路径。 + > 对于 TiDB Cloud Dedicated,在使用公共端点时**建议**通过 `TIDB_ENABLE_SSL` 启用 TLS 连接。当你设置 `TIDB_ENABLE_SSL=true` 时,你**必须**通过 `TIDB_CA_PATH=/path/to/ca.pem` 指定从连接对话框下载的 CA 证书路径。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 编辑 `.env` 文件,按照如下格式设置连接信息,将占位符 `{}` 替换为你的 TiDB 集群的连接参数值: +2. 编辑 `.env` 文件,按如下方式设置环境变量,将相应的占位符 `{}` 替换为你的 TiDB 集群的连接参数: ```dotenv TIDB_HOST={host} @@ -174,26 +179,25 @@ npm install @types/node ts-node typescript --save-dev TIDB_DATABASE=test ``` - 如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 如果你在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 4 步:初始化表结构 +### 第 4 步:初始化数据库架构 -运行以下命令,使用 TypeORM CLI 初始化数据库。TypeORM CLI 会根据 `src/migrations` 文件夹中的迁移文件生成 SQL 语句并执行。 +运行以下命令调用 TypeORM CLI 来使用 `src/migrations` 文件夹中迁移文件中编写的 SQL 语句初始化数据库: ```shell npm run migration:run ```
-预期的执行输出 +预期执行输出 -下面的 SQL 语句创建了 `players` 表和 `profiles` 表,并通过外键关联了两个表。 +以下 SQL 语句创建一个 `players` 表和一个 `profiles` 表,这两个表通过外键关联。 ```sql query: SELECT VERSION() AS `version` @@ -214,19 +218,19 @@ query: COMMIT
-迁移文件是根据 `src/entities` 文件夹中定义的实体生成的。要了解如何在 TypeORM 中定义实体,请参考 [TypeORM: Entities](https://typeorm.io/entities)。 +迁移文件是从 `src/entities` 文件夹中定义的实体生成的。要了解如何在 TypeORM 中定义实体,请参考 [TypeORM:实体](https://typeorm.io/entities)。 -### 第 5 步:运行代码并查看结果 +### 第 5 步:运行代码并检查结果 -运行以下命令,执行示例代码: +运行以下命令执行示例代码: ```shell npm start ``` -**预期输出结果:** +**预期执行输出:** -如果连接成功,你的终端将会输出所连接集群的版本信息: +如果连接成功,终端将输出 TiDB 集群的版本,如下所示: ``` 🔌 Connected to TiDB cluster! (TiDB version: 8.0.11-TiDB-v8.1.2) @@ -238,18 +242,18 @@ npm start ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-nodejs-typeorm-quickstart](https://github.com/tidb-samples/tidb-nodejs-typeorm-quickstart)。 +要查看完整的示例代码及其运行方法,请查看 [tidb-samples/tidb-nodejs-typeorm-quickstart](https://github.com/tidb-samples/tidb-nodejs-typeorm-quickstart) 仓库。 -### 连接到 TiDB +### 使用连接选项连接 -下面的代码使用环境变量中定义的连接选项来建立与 TiDB 集群的连接。 +以下代码使用环境变量中定义的选项建立与 TiDB 的连接: ```typescript // src/dataSource.ts -// 加载 .env 文件中的环境变量到 process.env。 +// Load environment variables from .env file to process.env. require('dotenv').config(); export const AppDataSource = new DataSource({ @@ -270,26 +274,26 @@ export const AppDataSource = new DataSource({ }); ``` -> **Note** +> **注意** > -> 使用 Public Endpoint 连接 TiDB Cloud Serverless 时,**必须**启用 TLS 连接,请将 `TIDB_ENABLE_SSL` 修改为 `true`。 +> 对于 TiDB Cloud Serverless,在使用公共端点时,你必须启用 TLS 连接。在此示例代码中,请在 `.env` 文件中将环境变量 `TIDB_ENABLE_SSL` 设置为 `true`。 > -> 但是你**不需要**通过 `TIDB_CA_PATH` 指定 SSL CA 证书,因为 Node.js 默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates),该证书已被 TiDB Cloud Serverless 信任。 +> 但是,你**不需要**通过 `TIDB_CA_PATH` 指定 SSL CA 证书,因为 Node.js 默认使用内置的 [Mozilla CA 证书](https://wiki.mozilla.org/CA/Included_Certificates),该证书受 TiDB Cloud Serverless 信任。 ### 插入数据 -下面的代码创建了一条 `Player` 记录,并返回该记录的 `id` 字段,该字段由 TiDB 自动生成: +以下查询创建一条 `Player` 记录,并返回创建的 `Player` 对象,其中包含由 TiDB 生成的 `id` 字段: ```typescript const player = new Player('Alice', 100, 100); await this.dataSource.manager.save(player); ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -下面的代码查询 ID 为 101 的 `Player` 记录,如果没有找到则返回 `null`: +以下查询返回 ID 为 101 的单个 `Player` 对象,如果未找到记录则返回 `null`: ```typescript const player: Player | null = await this.dataSource.manager.findOneBy(Player, { @@ -297,11 +301,11 @@ const player: Player | null = await this.dataSource.manager.findOneBy(Player, { }); ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -下面的代码将 `Player` 记录的 `goods` 字段增加 `50`: +以下查询为 ID 为 `101` 的 `Player` 添加 `50` 个物品: ```typescript const player = await this.dataSource.manager.findOneBy(Player, { @@ -311,11 +315,11 @@ player.goods += 50; await this.dataSource.manager.save(player); ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -下面的代码删除 ID 为 `101` 的 `Player` 记录: +以下查询删除 ID 为 `101` 的 `Player`: ```typescript await this.dataSource.manager.delete(Player, { @@ -323,26 +327,26 @@ await this.dataSource.manager.delete(Player, { }); ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 -### 执行原生 SQL 查询 +### 执行原始 SQL 查询 -下面的代码执行原生 SQL 语句 (`SELECT VERSION() AS tidb_version;`) 并返回 TiDB 集群的版本信息: +以下查询执行原始 SQL 语句(`SELECT VERSION() AS tidb_version;`)并返回 TiDB 集群的版本: ```typescript const rows = await dataSource.query('SELECT VERSION() AS tidb_version;'); console.log(rows[0]['tidb_version']); ``` -更多信息参考 [TypeORM: DataSource API](https://typeorm.io/data-source-api)。 +更多信息,请参考 [TypeORM:DataSource API](https://typeorm.io/data-source-api)。 -## 注意事项 +## 实用说明 ### 外键约束 -使用[外键约束](/foreign-key.md)(实验特性)可以通过在数据库层面添加检查来确保数据的[引用完整性](https://zh.wikipedia.org/wiki/参照完整性)。但是,在大数据量的场景下,这可能会导致严重的性能问题。 +使用[外键约束](https://docs.pingcap.com/tidb/stable/foreign-key)(实验性功能)通过在数据库端添加检查来确保数据的[参照完整性](https://en.wikipedia.org/wiki/Referential_integrity)。但是,这可能会在大数据量场景下导致严重的性能问题。 -你可以通过使用 `createForeignKeyConstraints` 选项来控制在构建实体之间的关系时是否创建外键约束(默认值为 `true`)。 +你可以使用 `createForeignKeyConstraints` 选项(默认值为 `true`)来控制在构建实体之间的关系时是否创建外键约束。 ```typescript @Entity() @@ -357,14 +361,24 @@ export class ActionLog { } ``` -更多信息,请参考 [TypeORM FAQ](https://typeorm.io/relations-faq#avoid-foreign-key-constraint-creation) 和 [TiDB 外键约束](/foreign-key.md)。 +更多信息,请参考 [TypeORM FAQ](https://typeorm.io/relations-faq#avoid-foreign-key-constraint-creation) 和[外键约束](https://docs.pingcap.com/tidbcloud/foreign-key#foreign-key-constraints)。 ## 下一步 -- 关于 TypeORM 的更多使用方法,可以参考 [TypeORM 的官方文档](https://typeorm.io)。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [TypeORM 的文档](https://typeorm.io/)了解更多 TypeORM 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[查询数据](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-python-django.md b/develop/dev-guide-sample-application-python-django.md index 5ba89864c9c2..0bbbb440aadc 100644 --- a/develop/dev-guide-sample-application-python-django.md +++ b/develop/dev-guide-sample-application-python-django.md @@ -1,256 +1,246 @@ --- -title: 使用 Django 连接到 TiDB -summary: 了解如何使用 Django 连接到 TiDB。本文提供了使用 Django 与 TiDB 交互的 Python 示例代码片段。 +title: 使用 Django 连接 TiDB +summary: 了解如何使用 Django 连接 TiDB。本教程提供使用 Django 操作 TiDB 的 Python 示例代码片段。 --- -# 使用 Django 连接到 TiDB +# 使用 Django 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[Django](https://www.djangoproject.com/) 为当前流行的 Python Web 框架之一,它内部实现了一个强大的 ORM (Object Relational Mapper) 系统。 +TiDB 是一个兼容 MySQL 的数据库,而 [Django](https://www.djangoproject.com) 是一个流行的 Python Web 框架,它包含一个强大的对象关系映射(ORM)库。 -本文档将展示如何使用 TiDB 和 Django 来完成以下任务: +在本教程中,您将学习如何使用 TiDB 和 Django 完成以下任务: -- 配置你的环境。 -- 使用 Django 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置环境。 +- 使用 Django 连接到您的 TiDB 集群。 +- 构建并运行您的应用程序。您也可以查看基本 CRUD 操作的示例代码片段。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed 集群。 -## 前置需求 +## 前提条件 -- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 +要完成本教程,您需要: + +- [Python 3.8 或更高版本](https://www.python.org/downloads/)。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 -## 运行代码并连接到 TiDB + -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +## 运行示例应用程序连接 TiDB -### 第 1 步:克隆示例代码仓库到本地 +本节演示如何运行示例应用程序代码并连接到 TiDB。 -运行以下命令,将示例代码仓库克隆到本地: +### 步骤 1:克隆示例应用程序仓库 -```bash +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-python-django-quickstart.git cd tidb-python-django-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 Django、django-tidb 和 mysqlclient): +运行以下命令安装示例应用程序所需的包(包括 Django、django-tidb 和 mysqlclient): -```bash +```shell pip install -r requirements.txt ``` -如果你在安装 mysqlclient 时遇到问题,请参考 [mysqlclient 官方文档](https://github.com/PyMySQL/mysqlclient#install)。 +如果您在安装 mysqlclient 时遇到问题,请参考 [mysqlclient 官方文档](https://github.com/PyMySQL/mysqlclient#install)。 -#### `django-tidb` 是什么? +#### 什么是 `django-tidb`? -`django-tidb` 是一个为 Django 提供的 TiDB 适配器,它解决了 TiDB 与 Django 之间的兼容性问题。 +`django-tidb` 是一个用于 Django 的 TiDB 方言,它解决了 TiDB 和 Django 之间的兼容性问题。 -安装 `django-tidb` 时,请选择与你的 Django 版本匹配的版本。例如,如果你使用的是 `django==4.2.*`,则应安装 `django-tidb>=4.2.0,<4.3.0`,其中 minor 版本号不需要完全相同。建议使用最新的 minor 版本。 +安装 `django-tidb` 时,请选择与您的 Django 版本匹配的版本。例如,如果您使用的是 `django==4.2.*`,请安装 `django-tidb==4.2.*`。次要版本号不需要相同。建议使用最新的次要版本。 更多信息,请参考 [django-tidb 仓库](https://github.com/pingcap/django-tidb)。 -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境相匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建一个随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经创建了密码,您可以使用原始密码,也可以点击**重置密码**生成一个新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 xxxxxx.root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' - CA_PATH='{ssl_ca}' # e.g. /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) + CA_PATH='{ssl_ca}' # 例如 /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 + + TiDB Cloud Serverless 需要安全连接。由于 mysqlclient 的 `ssl_mode` 默认为 `PREFERRED`,您不需要手动指定 `CA_PATH`。只需将其留空即可。但如果您有特殊原因需要手动指定 `CA_PATH`,可以参考 [TiDB Cloud Serverless 的 TLS 连接](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters)获取不同操作系统的证书路径。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' CA_PATH='{your-downloaded-ca-path}' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值,并配置前面步骤中下载好的证书路径。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数,并将 `CA_PATH` 配置为在上一步中下载的证书路径。 6. 保存 `.env` 文件。
+
-
+1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: - - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' + TIDB_HOST='{tidb_server_host}' TIDB_PORT='4000' TIDB_USER='root' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并删除 `CA_PATH` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并删除 `CA_PATH` 行。如果您在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 4 步:初始化数据库 +### 步骤 4:初始化数据库 -在示例项目根目录执行以下命令,初始化数据库: +在项目的根目录中,运行以下命令初始化数据库: ```shell python manage.py migrate ``` -```shell -Operations to perform: - Apply all migrations: admin, auth, contenttypes, sample_project, sessions -Running migrations: - Applying contenttypes.0001_initial... OK - Applying auth.0001_initial... OK - Applying admin.0001_initial... OK - Applying admin.0002_logentry_remove_auto_add... OK - Applying admin.0003_logentry_add_action_flag_choices... OK - Applying contenttypes.0002_remove_content_type_name... OK - Applying auth.0002_alter_permission_name_max_length... OK - Applying auth.0003_alter_user_email_max_length... OK - Applying auth.0004_alter_user_username_opts... OK - Applying auth.0005_alter_user_last_login_null... OK - Applying auth.0006_require_contenttypes_0002... OK - Applying auth.0007_alter_validators_add_error_messages... OK - Applying auth.0008_alter_user_username_max_length... OK - Applying auth.0009_alter_user_last_name_max_length... OK - Applying auth.0010_alter_group_name_max_length... OK - Applying auth.0011_update_proxy_permissions... OK - Applying auth.0012_alter_user_first_name_max_length... OK - Applying sample_project.0001_initial... OK - Applying sessions.0001_initial... OK -``` +### 步骤 5:运行示例应用程序 -### 第 5 步:运行示例应用程序 - -1. 在开发模式下运行示例应用程序: +1. 在开发模式下运行应用程序: ```shell python manage.py runserver ``` - 应用程序默认在 `8000` 端口上运行。如果你想要使用其他端口号,可以在命令后添加端口号,例如: + 应用程序默认在端口 `8000` 上运行。要使用不同的端口,您可以在命令后附加端口号。示例如下: ```shell python manage.py runserver 8080 ``` -2. 打开浏览器,在地址栏输入 `http://localhost:8000/`,访问示例应用程序,你可以进行以下操作: +2. 要访问应用程序,请打开浏览器并访问 `http://localhost:8000/`。在示例应用程序中,您可以: - - 创建一个新的 Player - - 批量创建 Player - - 查看所有的 Player - - 更新 Player - - 删除 Player - - 在两个 Player 之间交易物品 + - 创建新玩家。 + - 批量创建玩家。 + - 查看所有玩家。 + - 更新玩家信息。 + - 删除玩家。 + - 在两个玩家之间交易物品。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成您自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-python-django-quickstart](https://github.com/tidb-samples/tidb-python-django-quickstart)。 +有关完整的示例代码及其运行方法,请查看 [tidb-samples/tidb-python-django-quickstart](https://github.com/tidb-samples/tidb-python-django-quickstart) 仓库。 -### 配置数据库连接 +### 连接到 TiDB -打开 `sample_project/settings.py` 文件,添加以下配置: +在文件 `sample_project/settings.py` 中,添加以下配置: ```python DATABASES = { "default": { "ENGINE": "django_tidb", - "HOST": '${tidb_host}', - "PORT": '${tidb_port}', - "USER": '${tidb_user}', - "PASSWORD": '${tidb_password}', - "NAME": '${tidb_db_name}', + "HOST": ${tidb_host}, + "PORT": ${tidb_port}, + "USER": ${tidb_user}, + "PASSWORD": ${tidb_password}, + "NAME": ${tidb_db_name}, "OPTIONS": { "charset": "utf8mb4", }, } } -TIDB_CA_PATH = '${ca_path}' +TIDB_CA_PATH = ${ca_path} if TIDB_CA_PATH: DATABASES["default"]["OPTIONS"]["ssl_mode"] = "VERIFY_IDENTITY" DATABASES["default"]["OPTIONS"]["ssl"] = { @@ -258,9 +248,9 @@ if TIDB_CA_PATH: } ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 以及 `${ca_path}` 替换为你的 TiDB 集群的实际值。 +您需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 和 `${ca_path}` 替换为您的 TiDB 集群的实际值。 -### 声明数据对象 +### 定义数据模型 ```python from django.db import models @@ -273,7 +263,7 @@ class Player(models.Model): updated_at = models.DateTimeField(auto_now=True) ``` -更多信息参考 [Django 模型](https://docs.djangoproject.com/en/dev/topics/db/models/)。 +更多信息,请参见 [Django 模型](https://docs.djangoproject.com/en/dev/topics/db/models/)。 ### 插入数据 @@ -289,22 +279,22 @@ Player.objects.bulk_create([ ]) ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 ```python -# 查询单个对象 +# 获取单个对象 player = Player.objects.get(name="player1") -# 查询多个对象 +# 获取多个对象 filtered_players = Player.objects.filter(name="player1") -# 查询所有对象 +# 获取所有对象 all_players = Player.objects.all() ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 @@ -314,11 +304,11 @@ player = Player.objects.get(name="player1") player.coins = 200 player.save() -# 批量更新多个对象 +# 更新多个对象 Player.objects.filter(coins=100).update(coins=200) ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 @@ -327,18 +317,28 @@ Player.objects.filter(coins=100).update(coins=200) player = Player.objects.get(name="player1") player.delete() -# 批量删除多个对象 +# 删除多个对象 Player.objects.filter(coins=100).delete() ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于 Django 的更多使用方法,可以参考 [Django 官方文档](https://www.djangoproject.com/)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [Django 的文档](https://www.djangoproject.com/)了解更多 Django 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 \ No newline at end of file + diff --git a/develop/dev-guide-sample-application-python-mysql-connector.md b/develop/dev-guide-sample-application-python-mysql-connector.md index f60ed8a41a1b..337d6916f9d3 100644 --- a/develop/dev-guide-sample-application-python-mysql-connector.md +++ b/develop/dev-guide-sample-application-python-mysql-connector.md @@ -1,213 +1,227 @@ --- -title: 使用 MySQL Connector/Python 连接到 TiDB -summary: 了解如何使用 MySQL Connector/Python 连接到 TiDB。本文提供了使用 MySQL Connector/Python 与 TiDB 交互的 Python 示例代码片段。 +title: 使用 MySQL Connector/Python 连接 TiDB +summary: 了解如何使用 MySQL Connector/Python 连接 TiDB。本教程提供使用 MySQL Connector/Python 操作 TiDB 的 Python 示例代码片段。 --- -# 使用 MySQL Connector/Python 连接到 TiDB +# 使用 MySQL Connector/Python 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[MySQL Connector/Python](https://dev.mysql.com/doc/connector-python/en/) 是由 MySQL 开发的 Python Driver。 +TiDB 是一个兼容 MySQL 的数据库,而 [MySQL Connector/Python](https://dev.mysql.com/doc/connector-python/en/) 是 Python 的官方 MySQL 驱动程序。 -本文档将展示如何使用 TiDB 和 MySQL Connector/Python 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 MySQL Connector/Python 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 MySQL Connector/Python 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看基本 CRUD 操作的示例代码片段。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed 集群。 -## 前置需求 +## 前提条件 -- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 +要完成本教程,您需要: + +- [Python 3.8 或更高版本](https://www.python.org/downloads/)。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + -## 运行代码并连接到 TiDB +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -### 第 1 步:克隆示例代码仓库到本地 + -运行以下命令,将示例代码仓库克隆到本地: +## 运行示例应用程序连接到 TiDB -```bash +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-python-mysqlconnector-quickstart.git cd tidb-python-mysqlconnector-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 mysql-connector-python): +运行以下命令安装示例应用程序所需的包(包括 mysql-connector-python): -```bash +```shell pip install -r requirements.txt ``` -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接工具**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip:** - > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码或点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 xxxxxx.root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' - CA_PATH='{ssl_ca}' # e.g. /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) + CA_PATH='{ssl_ca}' # 例如 /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' CA_PATH='{your-downloaded-ca-path}' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值,并配置前面步骤中下载好的证书路径。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数,并将 `CA_PATH` 配置为之前下载的证书路径。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' + TIDB_HOST='{tidb_server_host}' TIDB_PORT='4000' TIDB_USER='root' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并删除 `CA_PATH` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并删除 `CA_PATH` 行。如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: - ```bash + ```shell python mysql_connector_example.py ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-python-mysqlconnector-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-python-mysqlconnector-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-python-mysqlconnector-quickstart](https://github.com/tidb-samples/tidb-python-mysqlconnector-quickstart)。 +有关完整的示例代码和如何运行它,请查看 [tidb-samples/tidb-python-mysqlconnector-quickstart](https://github.com/tidb-samples/tidb-python-mysqlconnector-quickstart) 仓库。 ### 连接到 TiDB ```python def get_connection(autocommit: bool = True) -> MySQLConnection: + config = Config() db_conf = { - "host": '${tidb_host}', - "port": '${tidb_port}', - "user": '${tidb_user}', - "password": '${tidb_password}', - "database": '${tidb_db_name}', + "host": ${tidb_host}, + "port": ${tidb_port}, + "user": ${tidb_user}, + "password": ${tidb_password}, + "database": ${tidb_db_name}, "autocommit": autocommit, "use_pure": True, } - if '${ca_path}': + if ${ca_path}: db_conf["ssl_verify_cert"] = True db_conf["ssl_verify_identity"] = True - db_conf["ssl_ca"] = '${ca_path}' + db_conf["ssl_ca"] = ${ca_path} return mysql.connector.connect(**db_conf) ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 以及 `${ca_path}` 替换为你的 TiDB 集群的实际值。 +使用此函数时,您需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 和 `${ca_path}` 替换为您的 TiDB 集群的实际值。 ### 插入数据 ```python with get_connection(autocommit=True) as conn: with conn.cursor() as cur: - player = ("test", 1, 1) + player = ("1", 1, 1) cursor.execute("INSERT INTO players (id, coins, goods) VALUES (%s, %s, %s)", player) ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 @@ -218,54 +232,64 @@ with get_connection(autocommit=True) as conn: print(cur.fetchone()[0]) ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 ```python with get_connection(autocommit=True) as conn: with conn.cursor() as cur: - player_id, amount, price="test", 10, 500 - cur.execute( + player_id, amount, price="1", 10, 500 + cursor.execute( "UPDATE players SET goods = goods + %s, coins = coins + %s WHERE id = %s", (-amount, price, player_id), ) ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 ```python with get_connection(autocommit=True) as conn: with conn.cursor() as cur: - player_id = "test" - cur.execute("DELETE FROM players WHERE id = %s", (player_id,)) + player_id = "1" + cursor.execute("DELETE FROM players WHERE id = %s", (player_id,)) ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 ### 使用驱动程序还是 ORM 框架? -Python 驱动程序提供对数据库的底层访问,但要求开发者: +Python 驱动程序提供对数据库的低级访问,但它要求开发人员: -- 手动建立和释放数据库连接 -- 手动管理数据库事务 -- 手动将数据行(在 `mysql-connector-python` 中表示为元组 (Tuple) 或者字典 (Dictionary))映射为数据对象 +- 手动建立和释放数据库连接。 +- 手动管理数据库事务。 +- 手动将数据行(在 `mysql-connector-python` 中表示为元组或字典)映射到数据对象。 -建议仅在需要编写复杂的 SQL 语句时使用驱动程序。其他情况下,建议使用 [ORM](https://zh.wikipedia.org/wiki/对象关系映射) 框架进行开发,例如 [SQLAlchemy](/develop/dev-guide-sample-application-python-sqlalchemy.md)、[Peewee](/develop/dev-guide-sample-application-python-peewee.md) 和 [Django](/develop/dev-guide-sample-application-python-django.md)。ORM 可以帮助你: +除非您需要编写复杂的 SQL 语句,否则建议使用 [ORM](https://en.wikipedia.org/w/index.php?title=Object-relational_mapping) 框架进行开发,例如 [SQLAlchemy](/develop/dev-guide-sample-application-python-sqlalchemy.md)、[Peewee](/develop/dev-guide-sample-application-python-peewee.md) 和 Django ORM。它可以帮助您: -- 减少管理连接和事务的[模板代码](https://en.wikipedia.org/wiki/Boilerplate_code) -- 使用数据对象代替大量 SQL 语句来操作数据 +- 减少管理连接和事务的[样板代码](https://en.wikipedia.org/wiki/Boilerplate_code)。 +- 使用数据对象而不是大量 SQL 语句来操作数据。 ## 下一步 -- 关于 mysql-connector-python 的更多使用方法,可以参考 [MySQL Connector/Python 官方文档](https://dev.mysql.com/doc/connector-python/en/)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [MySQL Connector/Python 文档](https://dev.mysql.com/doc/connector-python/en/)了解更多 mysql-connector-python 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 \ No newline at end of file + diff --git a/develop/dev-guide-sample-application-python-mysqlclient.md b/develop/dev-guide-sample-application-python-mysqlclient.md index 14b1f3fc613e..847ed2cd1144 100644 --- a/develop/dev-guide-sample-application-python-mysqlclient.md +++ b/develop/dev-guide-sample-application-python-mysqlclient.md @@ -1,216 +1,229 @@ --- -title: 使用 mysqlclient 连接到 TiDB -summary: 了解如何使用 mysqlclient 连接到 TiDB。本文提供了使用 mysqlclient 与 TiDB 交互的 Python 示例代码片段。 +title: 使用 mysqlclient 连接 TiDB +summary: 学习如何使用 mysqlclient 连接 TiDB。本教程提供使用 mysqlclient 操作 TiDB 的 Python 示例代码片段。 --- -# 使用 mysqlclient 连接到 TiDB +# 使用 mysqlclient 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[mysqlclient](https://github.com/PyMySQL/mysqlclient) 为当前流行的开源 Python Driver 之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [mysqlclient](https://github.com/PyMySQL/mysqlclient) 是一个流行的 Python 开源驱动程序。 -本文档将展示如何使用 TiDB 和 mysqlclient 来完成以下任务: +在本教程中,你可以学习如何使用 TiDB 和 mysqlclient 完成以下任务: -- 配置你的环境。 -- 使用 mysqlclient 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置你的环境。 +- 使用 mysqlclient 连接到你的 TiDB 集群。 +- 构建并运行你的应用程序。你也可以查看基本 CRUD 操作的示例代码片段。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 +要完成本教程,你需要: + +- [Python **3.10** 或更高版本](https://www.python.org/downloads/)。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果你还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 + + + -## 运行代码并连接到 TiDB +**如果你还没有 TiDB 集群,可以按照以下方式创建:** -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 -### 第 1 步:克隆示例代码仓库到本地 + -运行以下命令,将示例代码仓库克隆到本地: +## 运行示例应用程序连接 TiDB -```bash +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-python-mysqlclient-quickstart.git -cd tidb-python-mysqlclient-quickstart +cd tidb-python-mysqlclient-quickstart; ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 mysqlclient): +运行以下命令安装示例应用程序所需的包(包括 `mysqlclient`): -```bash +```shell pip install -r requirements.txt ``` 如果遇到安装问题,请参考 [mysqlclient 官方文档](https://github.com/PyMySQL/mysqlclient#install)。 -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据你选择的 TiDB 部署选项连接到你的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示一个连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与你的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接工具**设置为 `General` + - **操作系统**与你的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建一个随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果你之前已经创建了密码,你可以使用原始密码,也可以点击**重置密码**生成一个新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{gateway-region}.aws.tidbcloud.com' TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{prefix}.root' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' CA_PATH='' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 - TiDB Cloud Serverless 要求使用 TLS (SSL) connection,由于 mysqlclient 的 `ssl_mode` 默认为 `PREFERRED`,所以不需要你手动指定 `CA_PATH`,设置为空即可。但如果你有特殊原因需要手动指定 `CA_PATH`,可以参考 [TiDB Cloud 文档](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters#root-certificate-default-path)获取不同操作系统下证书的路径。 + TiDB Cloud Serverless 需要安全连接。由于 mysqlclient 的 `ssl_mode` 默认为 `PREFERRED`,你不需要手动指定 `CA_PATH`。只需将其留空即可。但如果你有特殊原因需要手动指定 `CA_PATH`,可以参考 [TiDB Cloud Serverless 的 TLS 连接](https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters)获取不同操作系统的证书路径。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示一个连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA cert** 下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果你还没有配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。更多信息,请参见[连接到你的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{host}.clusters.tidb-cloud.com' TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{username}' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' CA_PATH='{your-downloaded-ca-path}' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值,并配置前面步骤中下载好的证书路径。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数,并将 `CA_PATH` 配置为之前步骤中下载的证书路径。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' + TIDB_HOST='{tidb_server_host}' TIDB_PORT='4000' TIDB_USER='root' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并删除 `CA_PATH` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并删除 `CA_PATH` 行。如果你在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: - ```bash + ```shell python mysqlclient_example.py ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-python-mysqlclient-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-python-mysqlclient-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +你可以参考以下示例代码片段来完成你自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-python-mysqlclient-quickstart](https://github.com/tidb-samples/tidb-python-mysqlclient-quickstart)。 +有关完整的示例代码及其运行方法,请查看 [tidb-samples/tidb-python-mysqlclient-quickstart](https://github.com/tidb-samples/tidb-python-mysqlclient-quickstart) 仓库。 ### 连接到 TiDB ```python def get_mysqlclient_connection(autocommit:bool=True) -> MySQLdb.Connection: db_conf = { - "host": '${tidb_host}', - "port": '${tidb_port}', - "user": '${tidb_user}', - "password": '${tidb_password}', - "database": '${tidb_db_name}', + "host": ${tidb_host}, + "port": ${tidb_port}, + "user": ${tidb_user}, + "password": ${tidb_password}, + "database": ${tidb_db_name}, "autocommit": autocommit } - if '${ca_path}': + if ${ca_path}: db_conf["ssl_mode"] = "VERIFY_IDENTITY" - db_conf["ssl"] = {"ca": '${ca_path}'} + db_conf["ssl"] = {"ca": ${ca_path}} return MySQLdb.connect(**db_conf) ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}`、`${ca_path}` 等替换为你的 TiDB 集群的实际值。 +使用此函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 和 `${ca_path}` 替换为你的 TiDB 集群的实际值。 ### 插入数据 ```python with get_mysqlclient_connection(autocommit=True) as conn: with conn.cursor() as cur: - player = ("test", 1, 1) + player = ("1", 1, 1) cursor.execute("INSERT INTO players (id, coins, goods) VALUES (%s, %s, %s)", player) ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 @@ -221,54 +234,64 @@ with get_mysqlclient_connection(autocommit=True) as conn: print(cur.fetchone()[0]) ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 ```python with get_mysqlclient_connection(autocommit=True) as conn: with conn.cursor() as cur: - player_id, amount, price="test", 10, 500 - cur.execute( + player_id, amount, price="1", 10, 500 + cursor.execute( "UPDATE players SET goods = goods + %s, coins = coins + %s WHERE id = %s", (-amount, price, player_id), ) ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 ```python with get_mysqlclient_connection(autocommit=True) as conn: with conn.cursor() as cur: - player_id = "test" - cur.execute("DELETE FROM players WHERE id = %s", (player_id,)) + player_id = "1" + cursor.execute("DELETE FROM players WHERE id = %s", (player_id,)) ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 ### 使用驱动程序还是 ORM 框架? -Python 驱动程序提供对数据库的底层访问,但要求开发者: +Python 驱动程序提供对数据库的低级访问,但它要求开发人员: -- 手动建立和释放数据库连接 -- 手动管理数据库事务 -- 手动将数据行(在 mysqlclient 中表示为元组 (tuple))映射为数据对象 +- 手动建立和释放数据库连接。 +- 手动管理数据库事务。 +- 手动将数据行(在 `mysqlclient` 中表示为元组)映射到数据对象。 -建议仅在需要编写复杂的 SQL 语句时使用驱动程序。其他情况下,建议使用 [ORM](https://zh.wikipedia.org/wiki/对象关系映射) 框架进行开发,例如 [SQLAlchemy](/develop/dev-guide-sample-application-python-sqlalchemy.md)、[Peewee](/develop/dev-guide-sample-application-python-peewee.md) 和 [Django](/develop/dev-guide-sample-application-python-django.md)。ORM 可以帮助你: +除非你需要编写复杂的 SQL 语句,否则建议使用 [ORM](https://en.wikipedia.org/w/index.php?title=Object-relational_mapping) 框架进行开发,如 [SQLAlchemy](/develop/dev-guide-sample-application-python-sqlalchemy.md)、[Peewee](/develop/dev-guide-sample-application-python-peewee.md) 和 Django ORM。它可以帮助你: -- 减少管理连接和事务的[模板代码](https://en.wikipedia.org/wiki/Boilerplate_code) -- 使用数据对象代替大量 SQL 语句来操作数据 +- 减少管理连接和事务的[样板代码](https://en.wikipedia.org/wiki/Boilerplate_code)。 +- 使用数据对象而不是大量 SQL 语句来操作数据。 ## 下一步 -- 关于 mysqlclient 的更多使用方法,可以参考 [mysqlclient 官方文档](https://mysqlclient.readthedocs.io/)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [mysqlclient 的文档](https://mysqlclient.readthedocs.io/)中了解更多用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-python-peewee.md b/develop/dev-guide-sample-application-python-peewee.md index 50624c4ae959..2e6595febafc 100644 --- a/develop/dev-guide-sample-application-python-peewee.md +++ b/develop/dev-guide-sample-application-python-peewee.md @@ -1,183 +1,196 @@ --- -title: 使用 peewee 连接到 TiDB -summary: 了解如何使用 peewee 连接到 TiDB。本文提供了使用 peewee 与 TiDB 交互的 Python 示例代码片段。 +title: 使用 peewee 连接 TiDB +summary: 了解如何使用 peewee 连接 TiDB。本教程提供使用 peewee 操作 TiDB 的 Python 示例代码片段。 --- -# 使用 peewee 连接到 TiDB +# 使用 peewee 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[peewee](https://github.com/coleifer/peewee) 为当前流行的开源 Python ORM (Object Relational Mapper) 之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [peewee](https://docs.peewee-orm.com/) 是一个流行的 Python 对象关系映射器(ORM)。 -本文档将展示如何使用 TiDB 和 peewee 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 peewee 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 peewee 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看基本 CRUD 操作的示例代码片段。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed 集群。 -## 前置需求 +## 前提条件 -- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 +要完成本教程,您需要: + +- [Python 3.8 或更高版本](https://www.python.org/downloads/)。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + -## 运行代码并连接到 TiDB +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -### 第 1 步:克隆示例代码仓库到本地 + -运行以下命令,将示例代码仓库克隆到本地: +## 运行示例应用程序连接到 TiDB -```bash +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-python-peewee-quickstart.git cd tidb-python-peewee-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 peewee 和 PyMySQL): +运行以下命令安装示例应用程序所需的包(包括 peewee 和 PyMySQL): -```bash +```shell pip install -r requirements.txt ``` -#### 为什么安装 PyMySQL? +#### 为什么使用 PyMySQL? -peewee 是一个支持多种数据库的 ORM 库。它是对数据库的高层抽象,可以帮助开发者以更面向对象的方式编写 SQL 语句。但 peewee 并不提供数据库驱动,因此需要单独安装用于连接 TiDB 的驱动。本示例项目使用 [PyMySQL](/develop/dev-guide-sample-application-python-pymysql.md) 作为数据库驱动。PyMySQL 是一个与 TiDB 兼容的纯 Python 实现的 MySQL 客户端库,并可以在所有平台上安装。更多信息,参考 [peewee 官方文档](https://docs.peewee-orm.com/en/latest/peewee/database.html?highlight=mysql#using-mysql)。 +peewee 是一个可以与多个数据库一起工作的 ORM 库。它提供了数据库的高级抽象,帮助开发人员以更面向对象的方式编写 SQL 语句。但是,peewee 不包含数据库驱动程序。要连接到数据库,您需要安装数据库驱动程序。本示例应用程序使用 PyMySQL 作为数据库驱动程序,它是一个纯 Python MySQL 客户端库,与 TiDB 兼容,并且可以在所有平台上安装。更多信息,请参考 [peewee 官方文档](https://docs.peewee-orm.com/en/latest/peewee/database.html?highlight=mysql#using-mysql)。 -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接工具**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip:** - > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码或点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 xxxxxx.root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' - CA_PATH='{ssl_ca}' # e.g. /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) + CA_PATH='{ssl_ca}' # 例如 /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. xxxxxx.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' CA_PATH='{your-downloaded-ca-path}' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值,并配置前面步骤中下载好的证书路径。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数,并将 `CA_PATH` 配置为之前下载的证书路径。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' + TIDB_HOST='{tidb_server_host}' TIDB_PORT='4000' TIDB_USER='root' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并删除 `CA_PATH` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并删除 `CA_PATH` 行。如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: - ```bash + ```shell python peewee_example.py ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-python-peewee-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-python-peewee-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-python-peewee-quickstart](https://github.com/tidb-samples/tidb-python-peewee-quickstart)。 +有关完整的示例代码和如何运行它,请查看 [tidb-samples/tidb-python-peewee-quickstart](https://github.com/tidb-samples/tidb-python-peewee-quickstart) 仓库。 ### 连接到 TiDB @@ -185,26 +198,27 @@ peewee 是一个支持多种数据库的 ORM 库。它是对数据库的高层 from peewee import MySQLDatabase def get_db_engine(): + config = Config() connect_params = {} - if '${ca_path}': + if ${ca_path}: connect_params = { "ssl_verify_cert": True, "ssl_verify_identity": True, - "ssl_ca": '${ca_path}', + "ssl_ca": ${ca_path}, } return MySQLDatabase( - '${tidb_db_name}', - host='${tidb_host}', - port='${tidb_port}', - user='${tidb_user}', - password='${tidb_password}', + ${tidb_db_name}, + host=${tidb_host}, + port=${tidb_port}, + user=${tidb_user}, + password=${tidb_password}, **connect_params, ) ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 以及 `${ca_path}` 替换为你的 TiDB 集群的实际值。 +使用此函数时,您需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 和 `${ca_path}` 替换为您的 TiDB 集群的实际值。 -### 声明数据对象 +### 定义表 ```python from peewee import Model, CharField, IntegerField @@ -222,77 +236,85 @@ class Player(BaseModel): class Meta: table_name = "players" - - def __str__(self): - return f"Player(name={self.name}, coins={self.coins}, goods={self.goods})" ``` -更多信息参考 [peewee 模型与字段](https://docs.peewee-orm.com/en/latest/peewee/models.html)。 +更多信息,请参见 [peewee 文档:模型和字段](https://docs.peewee-orm.com/en/latest/peewee/models.html)。 ### 插入数据 ```python -# 插入单个对象 +# 插入单条记录 Player.create(name="test", coins=100, goods=100) -# 插入多个对象 -data = [ +# 插入多条记录 +Player.insert_many( + [ {"name": "test1", "coins": 100, "goods": 100}, {"name": "test2", "coins": 100, "goods": 100}, -] -Player.insert_many(data).execute() + ] +).execute() ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 ```python -# 查询所有对象 +# 查询所有记录 players = Player.select() -# 查询单个对象 +# 查询单条记录 player = Player.get(Player.name == "test") -# 查询多个对象 +# 查询多条记录 players = Player.select().where(Player.coins == 100) ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 ```python -# 更新单个对象 +# 更新单条记录 player = Player.get(Player.name == "test") player.coins = 200 player.save() -# 批量更新多个对象 +# 更新多条记录 Player.update(coins=200).where(Player.coins == 100).execute() ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 ```python -# 删除单个对象 +# 删除单条记录 player = Player.get(Player.name == "test") player.delete_instance() -# 批量删除多个对象 +# 删除多条记录 Player.delete().where(Player.coins == 100).execute() ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于 peewee 的更多使用方法,可以参考 [peewee 官方文档](https://docs.peewee-orm.com/)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [peewee 文档](https://docs.peewee-orm.com/)了解更多 peewee 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 \ No newline at end of file + diff --git a/develop/dev-guide-sample-application-python-pymysql.md b/develop/dev-guide-sample-application-python-pymysql.md index e6f684ff5a22..ad1782ccda80 100644 --- a/develop/dev-guide-sample-application-python-pymysql.md +++ b/develop/dev-guide-sample-application-python-pymysql.md @@ -1,179 +1,192 @@ --- -title: 使用 PyMySQL 连接到 TiDB -summary: 了解如何使用 PyMySQL 连接到 TiDB。本文提供了使用 PyMySQL 与 TiDB 交互的 Python 示例代码片段。 +title: 使用 PyMySQL 连接 TiDB +summary: 了解如何使用 PyMySQL 连接 TiDB。本教程提供使用 PyMySQL 操作 TiDB 的 Python 示例代码片段。 --- -# 使用 PyMySQL 连接到 TiDB +# 使用 PyMySQL 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[PyMySQL](https://github.com/PyMySQL/PyMySQL) 为当前流行的开源 Python Driver 之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [PyMySQL](https://github.com/PyMySQL/PyMySQL) 是一个流行的 Python 开源驱动程序。 -本文档将展示如何使用 TiDB 和 PyMySQL 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 PyMySQL 完成以下任务: -- 配置你的环境。 +- 设置环境。 - 使用 PyMySQL 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 构建并运行应用程序。您也可以查看示例代码片段,了解基本的 CRUD 操作。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed 集群。 -## 前置需求 +## 前提条件 -- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 +要完成本教程,您需要: + +- [Python 3.8 或更高版本](https://www.python.org/downloads/)。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果您还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 + + + -## 运行代码并连接到 TiDB +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -### 第 1 步:克隆示例代码仓库到本地 + -运行以下命令,将示例代码仓库克隆到本地: +## 运行示例程序连接 TiDB -```bash +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-python-pymysql-quickstart.git cd tidb-python-pymysql-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 `pymysql`): +运行以下命令安装示例应用程序所需的包(包括 PyMySQL): -```bash +```shell pip install -r requirements.txt ``` -### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到 TiDB 集群。 -
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与您的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**创建随机密码。 - > **Tip:** + > **提示:** > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > 如果您之前已经创建了密码,可以使用原始密码或点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. gateway01.ap-northeast-1.prod.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 xxxxxx.root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' - CA_PATH='{ssl_ca}' # e.g. /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) + CA_PATH='{ssl_ca}' # 例如 /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**连接类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. tidb.xxxx.clusters.tidb-cloud.com + TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. root + TIDB_USER='{user}' # 例如 root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' CA_PATH='{your-downloaded-ca-path}' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值,并配置前面步骤中下载好的证书路径。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数,并将 `CA_PATH` 配置为之前下载的证书路径。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' + TIDB_HOST='{tidb_server_host}' TIDB_PORT='4000' TIDB_USER='root' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并删除 `CA_PATH` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并删除 `CA_PATH` 行。如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: - ```bash + ```shell python pymysql_example.py ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-python-pymysql-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-python-pymysql-quickstart/blob/main/Expected-Output.txt) 以检查输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-python-pymysql-quickstart](https://github.com/tidb-samples/tidb-python-pymysql-quickstart)。 +有关完整的示例代码和运行方法,请查看 [tidb-samples/tidb-python-pymysql-quickstart](https://github.com/tidb-samples/tidb-python-pymysql-quickstart) 仓库。 ### 连接到 TiDB @@ -181,6 +194,7 @@ pip install -r requirements.txt from pymysql import Connection from pymysql.cursors import DictCursor + def get_connection(autocommit: bool = True) -> Connection: config = Config() db_conf = { @@ -201,7 +215,7 @@ def get_connection(autocommit: bool = True) -> Connection: return pymysql.connect(**db_conf) ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 以及 `${ca_path}` 替换为你的 TiDB 集群的实际值。 +使用此函数时,您需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 和 `${ca_path}` 替换为 TiDB 集群的实际值。 ### 插入数据 @@ -209,10 +223,10 @@ def get_connection(autocommit: bool = True) -> Connection: with get_connection(autocommit=True) as conn: with conn.cursor() as cur: player = ("1", 1, 1) - cur.execute("INSERT INTO players (id, coins, goods) VALUES (%s, %s, %s)", player) + cursor.execute("INSERT INTO players (id, coins, goods) VALUES (%s, %s, %s)", player) ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 @@ -223,21 +237,21 @@ with get_connection(autocommit=True) as conn: print(cursor.fetchone()["count(*)"]) ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 ```python with get_connection(autocommit=True) as conn: with conn.cursor() as cur: - player_id, amount, price = "1", 1, 50 - cur.execute( + player_id, amount, price="1", 10, 500 + cursor.execute( "UPDATE players SET goods = goods + %s, coins = coins + %s WHERE id = %s", (-amount, price, player_id), ) ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 @@ -245,32 +259,42 @@ with get_connection(autocommit=True) as conn: with get_connection(autocommit=True) as conn: with conn.cursor() as cur: player_id = "1" - cur.execute("DELETE FROM players WHERE id = %s", player_id) + cursor.execute("DELETE FROM players WHERE id = %s", (player_id,)) ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 -## 注意事项 +## 实用说明 ### 使用驱动程序还是 ORM 框架? -Python 驱动程序提供对数据库的底层访问,但要求开发者: +Python 驱动程序提供对数据库的低级访问,但它要求开发人员: -- 手动建立和释放数据库连接 -- 手动管理数据库事务 -- 手动将数据行(在 pymysql 中表示为元组 (tuple) 或者字典 (dict))映射为数据对象 +- 手动建立和释放数据库连接。 +- 手动管理数据库事务。 +- 手动将数据行(在 `pymysql` 中表示为元组或字典)映射到数据对象。 -建议仅在需要编写复杂的 SQL 语句时使用驱动程序。其他情况下,建议使用 [ORM](https://zh.wikipedia.org/wiki/对象关系映射) 框架进行开发,例如 [SQLAlchemy](/develop/dev-guide-sample-application-python-sqlalchemy.md)、[Peewee](/develop/dev-guide-sample-application-python-peewee.md) 和 [Django](/develop/dev-guide-sample-application-python-django.md)。ORM 可以帮助你: +除非您需要编写复杂的 SQL 语句,否则建议使用 [ORM](https://en.wikipedia.org/w/index.php?title=Object-relational_mapping) 框架进行开发,例如 [SQLAlchemy](/develop/dev-guide-sample-application-python-sqlalchemy.md)、[Peewee](/develop/dev-guide-sample-application-python-peewee.md) 和 Django ORM。它可以帮助您: -- 减少管理连接和事务的[模板代码](https://en.wikipedia.org/wiki/Boilerplate_code) -- 使用数据对象代替大量 SQL 语句来操作数据 +- 减少管理连接和事务的[样板代码](https://en.wikipedia.org/wiki/Boilerplate_code)。 +- 使用数据对象而不是大量 SQL 语句来操作数据。 ## 下一步 -- 关于 PyMySQL 的更多使用方法,可以参考 [PyMySQL 官方文档](https://pymysql.readthedocs.io)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [PyMySQL 文档](https://pymysql.readthedocs.io)了解更多 PyMySQL 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 \ No newline at end of file + diff --git a/develop/dev-guide-sample-application-python-sqlalchemy.md b/develop/dev-guide-sample-application-python-sqlalchemy.md index 610c02821b30..913e4b57b432 100644 --- a/develop/dev-guide-sample-application-python-sqlalchemy.md +++ b/develop/dev-guide-sample-application-python-sqlalchemy.md @@ -1,189 +1,202 @@ --- -title: 使用 SQLAlchemy 连接到 TiDB -summary: 了解如何使用 SQLAlchemy 连接到 TiDB。本文提供了使用 SQLAlchemy 与 TiDB 交互的 Python 示例代码片段。 +title: 使用 SQLAlchemy 连接 TiDB +summary: 学习如何使用 SQLAlchemy 连接 TiDB。本教程提供使用 SQLAlchemy 操作 TiDB 的 Python 示例代码片段。 --- -# 使用 SQLAlchemy 连接到 TiDB +# 使用 SQLAlchemy 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[SQLAlchemy](https://www.sqlalchemy.org/) 为当前流行的开源 Python ORM (Object Relational Mapper) 之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [SQLAlchemy](https://www.sqlalchemy.org/) 是一个流行的 Python SQL 工具包和对象关系映射器(ORM)。 -本文档将展示如何使用 TiDB 和 SQLAlchemy 来完成以下任务: +在本教程中,你可以学习如何使用 TiDB 和 SQLAlchemy 完成以下任务: -- 配置你的环境。 -- 使用 SQLAlchemy 连接到 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置你的环境。 +- 使用 SQLAlchemy 连接到你的 TiDB 集群。 +- 构建并运行你的应用程序。你也可以找到基本 CRUD 操作的示例代码片段。 -> **注意** +> **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed 集群。 + +## 前提条件 -## 前置需求 +要完成本教程,你需要: -- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 +- [Python 3.8 或更高版本](https://www.python.org/downloads/)。 - [Git](https://git-scm.com/downloads)。 -- TiDB 集群。如果你还没有 TiDB 集群,可以按照以下方式创建: - - (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 - - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 一个 TiDB 集群。 + + + +**如果你还没有 TiDB 集群,可以按照以下方式创建:** + +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)来创建本地集群。 -## 运行代码并连接到 TiDB + + -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 +**如果你还没有 TiDB 集群,可以按照以下方式创建:** -### 第 1 步:克隆示例代码仓库到本地 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)来创建本地集群。 -运行以下命令,将示例代码仓库克隆到本地: + -```bash +## 运行示例程序连接 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 第 1 步:克隆示例程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell git clone https://github.com/tidb-samples/tidb-python-sqlalchemy-quickstart.git cd tidb-python-sqlalchemy-quickstart ``` ### 第 2 步:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 SQLAlchemy 和 PyMySQL): +运行以下命令来安装示例程序所需的包(包括 SQLAlchemy 和 PyMySQL): -```bash +```shell pip install -r requirements.txt ``` -#### 为什么安装 PyMySQL? +#### 为什么使用 PyMySQL? -SQLAlchemy 是一个支持多种数据库的 ORM 库。它是对数据库的高层抽象,可以帮助开发者以更面向对象的方式编写 SQL 语句。但 SQLAlchemy 并不提供数据库驱动,因此需要单独安装用于连接 TiDB 的驱动。本示例项目使用 PyMySQL 作为数据库驱动。PyMySQL 是一个与 TiDB 兼容的纯 Python 实现的 MySQL 客户端库,并可以在所有平台上安装。 +SQLAlchemy 是一个可以与多个数据库一起工作的 ORM 库。它提供了数据库的高级抽象,帮助开发人员以更面向对象的方式编写 SQL 语句。但是,SQLAlchemy 不包含数据库驱动程序。要连接到数据库,你需要安装一个数据库驱动程序。本示例应用程序使用 PyMySQL 作为数据库驱动程序,它是一个纯 Python MySQL 客户端库,与 TiDB 兼容,并且可以在所有平台上安装。 -你也可以使用其他数据库驱动,例如 [mysqlclient](https://github.com/PyMySQL/mysqlclient) 以及 [mysql-connector-python](https://dev.mysql.com/doc/connector-python/en/)。但是它们不是纯 Python 库,需要安装对应的 C/C++ 编译器和 MySQL 客户端库进行编译。更多信息,参考 [SQLAlchemy 官方文档](https://docs.sqlalchemy.org/en/20/core/engines.html#mysql)。 +你也可以使用其他数据库驱动程序,如 [mysqlclient](https://github.com/PyMySQL/mysqlclient) 和 [mysql-connector-python](https://dev.mysql.com/doc/connector-python/en/)。但它们不是纯 Python 库,需要相应的 C/C++ 编译器和 MySQL 客户端来编译。更多信息,请参考 [SQLAlchemy 官方文档](https://docs.sqlalchemy.org/en/20/core/engines.html#mysql)。 ### 第 3 步:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据你选择的 TiDB 部署选项连接到你的 TiDB 集群。 -
> **注意:** > -> TiDB Cloud Serverless 集群目前存在一个限制:如果 5 分钟内没有活跃连接,集群将会自动关闭,这会导致所有连接中断。因此,当使用 SQLAlchemy 连接到 TiDB Cloud Serverless 集群时,从连接池中获取的连接可能会遇到 `OperationalError` 报错,例如 `Lost connection to MySQL server during query` 或 `MySQL Connection not available`。为了避免该错误,可将 `pool_recycle` 参数设置为 `300`。更多信息,请参阅 SQLAlchemy 文档 [Dealing with Disconnects](https://docs.sqlalchemy.org/en/20/core/pooling.html#dealing-with-disconnects)。 +> 目前,TiDB Cloud Serverless 集群有一个限制:如果 5 分钟内没有活动连接,它们将关闭,这会关闭所有连接。因此,在将 SQLAlchemy 与 TiDB Cloud Serverless 集群一起使用时,池化连接可能会遇到 `OperationalError`,如 `Lost connection to MySQL server during query` 或 `MySQL Connection not available`。要避免此错误,你可以将 `pool_recycle` 参数设置为 `300`。更多信息,请参阅 SQLAlchemy 文档中的[处理断开连接](https://docs.sqlalchemy.org/en/20/core/pooling.html#dealing-with-disconnects)。 -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Serverless 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 确保连接对话框中的配置与你的操作环境匹配。 - - **Connection Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `General`。 - - **Operating System** 为你的运行环境。 + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与你的环境匹配。 - > **Tip:** + > **提示:** > - > 如果你在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 点击**生成密码**来创建随机密码。 - > **Tip:** - > - > 如果你之前已经生成过密码,可以直接使用原密码,或点击 **Reset Password** 重新生成密码。 + > **提示:** + > + > 如果你之前已经创建了密码,你可以使用原始密码,也可以点击**重置密码**生成新密码。 -5. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -6. 复制并粘贴对应连接字符串至 `.env` 中。示例结果如下: +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. gateway01.ap-northeast-1.prod.aws.tidbcloud.com + TIDB_HOST='{host}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. xxxxxx.root + TIDB_USER='{user}' # 例如 xxxxxx.root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' - CA_PATH='{ssl_ca}' # e.g. /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) + CA_PATH='{ssl_ca}' # 例如 /etc/ssl/certs/ca-certificates.crt (Debian / Ubuntu / Arch) ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。 7. 保存 `.env` 文件。
-
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,选择你的 TiDB Cloud Dedicated 集群,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会出现连接对话框。 +2. 点击右上角的**连接**。此时会显示一个连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择 **Public**,然后点击 **CA cert** 下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果你还没有配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤在首次连接之前进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。更多信息,请参阅[连接到你的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 -4. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -5. 复制并粘贴对应的连接字符串至 `.env` 中。示例结果如下: +5. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' # e.g. tidb.xxxx.clusters.tidb-cloud.com + TIDB_HOST='{host}' # 例如 tidb.xxxx.clusters.tidb-cloud.com TIDB_PORT='4000' - TIDB_USER='{user}' # e.g. root + TIDB_USER='{user}' # 例如 root TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' CA_PATH='{your-downloaded-ca-path}' ``` - 注意替换 `{}` 中的占位符为连接对话框中获得的值,并配置前面步骤中下载好的证书路径。 + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数,并将 `CA_PATH` 配置为上一步下载的证书路径。 6. 保存 `.env` 文件。
+
-
- -1. 运行以下命令,将 `.env.example` 复制并重命名为 `.env`: +1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: - ```bash + ```shell cp .env.example .env ``` -2. 复制并粘贴对应 TiDB 的连接字符串至 `.env` 中。示例结果如下: +2. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: ```dotenv - TIDB_HOST='{host}' + TIDB_HOST='{tidb_server_host}' TIDB_PORT='4000' TIDB_USER='root' TIDB_PASSWORD='{password}' TIDB_DB_NAME='test' ``` - 注意替换 `{}` 中的占位符为你的 TiDB 对应的值,并删除 `CA_PATH` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 请确保将占位符 `{}` 替换为连接参数,并删除 `CA_PATH` 行。如果你在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
- -### 第 4 步:运行代码并查看结果 +### 第 4 步:运行代码并检查结果 -1. 运行下述命令,执行示例代码: +1. 执行以下命令运行示例代码: - ```bash + ```shell python sqlalchemy_example.py ``` -2. 查看 [`Expected-Output.txt`](https://github.com/tidb-samples/tidb-python-sqlalchemy-quickstart/blob/main/Expected-Output.txt),并与你的程序输出进行比较。结果近似即为连接成功。 +2. 查看 [Expected-Output.txt](https://github.com/tidb-samples/tidb-python-sqlalchemy-quickstart/blob/main/Expected-Output.txt) 以确认输出是否匹配。 ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-python-sqlalchemy-quickstart](https://github.com/tidb-samples/tidb-python-sqlalchemy-quickstart)。 +要查看完整的示例代码及其运行方法,请查看 [tidb-samples/tidb-python-sqlalchemy-quickstart](https://github.com/tidb-samples/tidb-python-sqlalchemy-quickstart) 仓库。 ### 连接到 TiDB @@ -215,9 +228,9 @@ engine = get_db_engine() Session = sessionmaker(bind=engine) ``` -在使用该函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 以及 `${ca_path}` 替换为你的 TiDB 集群的实际值。 +使用此函数时,你需要将 `${tidb_host}`、`${tidb_port}`、`${tidb_user}`、`${tidb_password}`、`${tidb_db_name}` 和 `${ca_path}` 替换为你的 TiDB 集群的实际值。 -### 声明数据对象 +### 定义表 ```python from sqlalchemy import Column, Integer, String @@ -234,7 +247,7 @@ class Player(Base): __tablename__ = "players" ``` -更多信息参考 [SQLAlchemy 声明式映射表](https://docs.sqlalchemy.org/en/20/orm/declarative_mapping.html)。 +更多信息,请参考 [SQLAlchemy 文档:使用声明式映射类](https://docs.sqlalchemy.org/en/20/orm/declarative_mapping.html)。 ### 插入数据 @@ -245,7 +258,7 @@ with Session() as session: session.commit() ``` -更多信息参考[插入数据](/develop/dev-guide-insert-data.md)以及 [SQLAlchemy Query](https://docs.sqlalchemy.org/en/20/orm/queryguide/index.html)。 +更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 @@ -255,7 +268,7 @@ with Session() as session: print(player) ``` -更多信息参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)以及 [SQLAlchemy Query](https://docs.sqlalchemy.org/en/20/orm/queryguide/index.html)。 +更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 @@ -266,7 +279,7 @@ with Session() as session: session.commit() ``` -更多信息参考[更新数据](/develop/dev-guide-update-data.md)以及 [SQLAlchemy Query](https://docs.sqlalchemy.org/en/20/orm/queryguide/index.html)。 +更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 @@ -277,14 +290,24 @@ with Session() as session: session.commit() ``` -更多信息参考[删除数据](/develop/dev-guide-delete-data.md)以及 [SQLAlchemy Query](https://docs.sqlalchemy.org/en/20/orm/queryguide/index.html)。 +更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 ## 下一步 -- 关于 SQLAlchemy 的更多使用方法,可以参考 [SQLAlchemy 官方文档](https://www.sqlalchemy.org/)。 -- 你可以继续阅读开发者文档,以获取更多关于 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)、[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [SQLAlchemy 的文档](https://www.sqlalchemy.org/)了解更多 SQLAlchemy 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 需要帮助? +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 + diff --git a/develop/dev-guide-sample-application-ruby-mysql2.md b/develop/dev-guide-sample-application-ruby-mysql2.md index 9ed8030840bf..f83806ac5b5b 100644 --- a/develop/dev-guide-sample-application-ruby-mysql2.md +++ b/develop/dev-guide-sample-application-ruby-mysql2.md @@ -1,52 +1,62 @@ --- title: 使用 mysql2 连接 TiDB -summary: 本文描述了 TiDB 和 mysql2 的连接步骤,并给出了使用 mysql2 gem 连接 TiDB 的简单示例代码片段。 +summary: 了解如何使用 Ruby mysql2 连接 TiDB。本教程提供使用 mysql2 gem 操作 TiDB 的 Ruby 示例代码片段。 --- # 使用 mysql2 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库。[mysql2](https://github.com/brianmario/mysql2) 是 Ruby 中最受欢迎的 MySQL 驱动之一。 +TiDB 是一个兼容 MySQL 的数据库,而 [mysql2](https://github.com/brianmario/mysql2) 是 Ruby 最流行的 MySQL 驱动程序之一。 -本文档将展示如何使用 TiDB 和 mysql2 来完成以下任务: +在本教程中,您可以学习如何使用 TiDB 和 mysql2 完成以下任务: -- 设置你的环境。 -- 使用 mysql2 连接你的 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置环境。 +- 使用 mysql2 连接到 TiDB 集群。 +- 构建并运行应用程序。您也可以查看基本 CRUD 操作的[示例代码片段](#示例代码片段)。 > **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 以及本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本文中的操作,你需要提前: +要完成本教程,您需要: -- 在你的机器上安装 [Ruby](https://www.ruby-lang.org/en/) 3.0 或以上版本。 -- 在你的机器上安装 [Bundler](https://bundler.io/)。 -- 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- 在您的机器上安装 [Ruby](https://www.ruby-lang.org/en/) >= 3.0 +- 在您的机器上安装 [Bundler](https://bundler.io/) +- 在您的机器上安装 [Git](https://git-scm.com/downloads) +- 一个正在运行的 TiDB 集群 -如果你还没有 TiDB 集群,可以按照以下方式创建: +**如果您还没有 TiDB 集群,可以按照以下方式创建:** -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 + -## 运行示例应用程序并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + + -### 第 1 步:克隆示例代码仓库到本地 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)创建本地集群。 -在你的终端窗口中运行以下命令,将示例代码仓库克隆到本地: + + +## 运行示例应用程序连接到 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: ```shell git clone https://github.com/tidb-samples/tidb-ruby-mysql2-quickstart.git cd tidb-ruby-mysql2-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 `mysql2` 和 `dotenv` 依赖包): +运行以下命令安装示例应用程序所需的包(包括 `mysql2` 和 `dotenv`): ```shell bundle install @@ -55,7 +65,7 @@ bundle install
为现有项目安装依赖 -对于你的现有项目,运行以下命令安装这些包: +对于您的现有项目,运行以下命令安装包: ```shell bundle add mysql2 dotenv @@ -63,25 +73,25 @@ bundle add mysql2 dotenv
-### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据您选择的 TiDB 部署选项连接到您的 TiDB 集群。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你的目标集群的名称,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 确保连接对话框中的配置与你的操作环境匹配。 +3. 确保连接对话框中的配置与您的操作环境匹配。 - - **Connection Type** 设置为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 设置为 `General`。 - - **Operating System** 与你运行应用程序的操作系统相匹配。 + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接工具**设置为 `General`。 + - **操作系统**与您运行应用程序的操作系统匹配。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 如果您还没有设置密码,点击**生成密码**生成随机密码。 5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: @@ -89,7 +99,7 @@ bundle add mysql2 dotenv cp .env.example .env ``` -6. 编辑 `.env` 文件,按照以下方式设置环境变量,并将占位符 `{}`替换为连接对话框中相应的连接参数: +6. 编辑 `.env` 文件,按如下设置环境变量,并将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv DATABASE_HOST={host} @@ -100,24 +110,24 @@ bundle add mysql2 dotenv DATABASE_ENABLE_SSL=true ``` - > **注意:** + > **注意** > - > 对于 TiDB Cloud Serverless,当使用 Public Endpoint 时,**必须**通过 `DATABASE_ENABLE_SSL` 启用 TLS 连接。 + > 对于 TiDB Cloud Serverless,使用公共端点时**必须**通过 `DATABASE_ENABLE_SSL` 启用 TLS 连接。 7. 保存 `.env` 文件。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你的目标集群的名称,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果您尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**私有端点**和 **VPC 对等连接**类型。更多信息,请参见[连接到您的 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: @@ -125,7 +135,7 @@ bundle add mysql2 dotenv cp .env.example .env ``` -5. 编辑 `.env` 文件,按照以下方式设置环境变量,并将占位符 `{}`替换为连接对话框中相应的连接参数: +5. 编辑 `.env` 文件,按如下设置环境变量,并将相应的占位符 `{}` 替换为连接对话框中的连接参数: ```dotenv DATABASE_HOST={host} @@ -137,16 +147,16 @@ bundle add mysql2 dotenv DATABASE_SSL_CA={downloaded_ssl_ca_path} ``` - > **注意:** + > **注意** > - > 当使用 Public Endpoint 连接到 TiDB Cloud Dedicated 集群时,建议启用 TLS 连接。 + > 使用公共端点连接到 TiDB Cloud Dedicated 集群时,建议启用 TLS 连接。 > - > 要启用 TLS 连接,请将 `DATABASE_ENABLE_SSL` 修改为 `true`,并使用 `DATABASE_SSL_CA` 的值设置为从连接对话框下载的 CA 证书的文件路径。 + > 要启用 TLS 连接,将 `DATABASE_ENABLE_SSL` 修改为 `true`,并使用 `DATABASE_SSL_CA` 指定从连接对话框下载的 CA 证书的文件路径。 6. 保存 `.env` 文件。
-
+
1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: @@ -154,7 +164,7 @@ bundle add mysql2 dotenv cp .env.example .env ``` -2. 编辑 `.env` 文件,按照以下方式设置环境变量,并将占位符 `{}`替换为你的 TiDB 集群的连接参数: +2. 编辑 `.env` 文件,按如下设置环境变量,并将相应的占位符 `{}` 替换为您自己的 TiDB 连接信息: ```dotenv DATABASE_HOST={host} @@ -164,22 +174,22 @@ bundle add mysql2 dotenv DATABASE_NAME=test ``` - 如果你在本地运行 TiDB,那么默认的主机地址是 `127.0.0.1`,密码为空。 + 如果您在本地运行 TiDB,默认主机地址为 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
-### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 -运行以下命令来执行示例代码: +运行以下命令执行示例代码: ```shell ruby app.rb ``` -如果连接成功,你的终端将会输出所连接集群的版本信息: +如果连接成功,控制台将输出 TiDB 集群的版本,如下所示: ``` 🔌 Connected to TiDB cluster! (TiDB version: 8.0.11-TiDB-v8.1.2) @@ -194,18 +204,18 @@ ruby app.rb ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +您可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-ruby-mysql2-quickstart](https://github.com/tidb-samples/tidb-ruby-mysql2-quickstart)。 +有关完整的示例代码和如何运行它,请查看 [tidb-samples/tidb-ruby-mysql2-quickstart](https://github.com/tidb-samples/tidb-ruby-mysql2-quickstart) 仓库。 -### 连接到 TiDB +### 使用连接选项连接到 TiDB -下面的代码使用环境变量中定义的连接选项来建立与 TiDB 集群的连接。 +以下代码使用环境变量中定义的选项建立与 TiDB 的连接: ```ruby require 'dotenv/load' require 'mysql2' -Dotenv.load # 从 .env 文件中加载环境变量 +Dotenv.load # 从 .env 文件加载环境变量 options = { host: ENV['DATABASE_HOST'] || '127.0.0.1', @@ -219,13 +229,13 @@ options.merge(sslca: ENV['DATABASE_SSL_CA']) if ENV['DATABASE_SSL_CA'] client = Mysql2::Client.new(options) ``` -> **注意:** +> **注意** > -> 对于 TiDB Cloud Serverless,当使用 Public Endpoint 时,**必须**通过 `DATABASE_ENABLE_SSL` 启用 TLS 连接,但是你**不需要**通过 `DATABASE_SSL_CA` 指定 SSL CA 证书,因为 mysql2 gem 会按照特定的顺序搜索现有的 CA 证书,直到找到相应的文件。 +> 对于 TiDB Cloud Serverless,使用公共端点时,您**必须**通过 `DATABASE_ENABLE_SSL` 启用 TLS 连接,但您**不需要**通过 `DATABASE_SSL_CA` 指定 SSL CA 证书,因为 mysql2 gem 会按特定顺序搜索现有的 CA 证书,直到找到一个文件。 ### 插入数据 -以下查询创建一个具有两个字段的 player,并返回 `last_insert_id`: +以下查询创建一个具有两个字段的玩家,并返回 `last_insert_id`: ```ruby def create_player(client, coins, goods) @@ -236,11 +246,11 @@ def create_player(client, coins, goods) end ``` -更多信息,请参考[插入数据](/develop/dev-guide-insert-data.md)。 +更多信息,请参见[插入数据](/develop/dev-guide-insert-data.md)。 ### 查询数据 -以下查询通过 ID 返回特定 player 的记录: +以下查询通过 ID 返回特定玩家的记录: ```ruby def get_player_by_id(client, id) @@ -251,11 +261,11 @@ def get_player_by_id(client, id) end ``` -更多信息,请参考[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 +更多信息,请参见[查询数据](/develop/dev-guide-get-data-from-single-table.md)。 ### 更新数据 -以下查询通过 ID 更新特定 player 的记录: +以下查询通过 ID 更新特定玩家的记录: ```ruby def update_player(client, player_id, inc_coins, inc_goods) @@ -266,11 +276,11 @@ def update_player(client, player_id, inc_coins, inc_goods) end ``` -更多信息,请参考[更新数据](/develop/dev-guide-update-data.md)。 +更多信息,请参见[更新数据](/develop/dev-guide-update-data.md)。 ### 删除数据 -以下查询删除特定 player 的记录: +以下查询删除特定玩家的记录: ```ruby def delete_player_by_id(client, id) @@ -281,25 +291,35 @@ def delete_player_by_id(client, id) end ``` -更多信息,请参考[删除数据](/develop/dev-guide-delete-data.md)。 +更多信息,请参见[删除数据](/develop/dev-guide-delete-data.md)。 ## 最佳实践 -默认情况下,mysql2 gem 可以按照特定的顺序搜索现有的 CA 证书,直到找到相应的文件。 +默认情况下,mysql2 gem 可以按特定顺序搜索现有的 CA 证书,直到找到一个文件。 -1. 对于 Debian、Ubuntu、Gentoo、Arch 或 Slackware,证书的默认存储路径为 `/etc/ssl/certs/ca-certificates.crt`。 -2. 对于 RedHat、Fedora、CentOS、Mageia、Vercel 或 Netlify,证书的默认存储路径为 `/etc/pki/tls/certs/ca-bundle.crt`。 -3. 对于 OpenSUSE,证书的默认存储路径为 `/etc/ssl/ca-bundle.pem`。 -4. 对于 macOS 或 Alpine(docker 容器),证书的默认存储路径为 `/etc/ssl/cert.pem`。 +1. `/etc/ssl/certs/ca-certificates.crt` 用于 Debian、Ubuntu、Gentoo、Arch 或 Slackware +2. `/etc/pki/tls/certs/ca-bundle.crt` 用于 RedHat、Fedora、CentOS、Mageia、Vercel 或 Netlify +3. `/etc/ssl/ca-bundle.pem` 用于 OpenSUSE +4. `/etc/ssl/cert.pem` 用于 macOS 或 Alpine(docker 容器) -尽管可以手动指定 CA 证书路径,但在多环境部署场景中这可能会引起不必要的麻烦,因为不同的机器和环境可能存储 CA 证书的位置不同。因此,建议将 `sslca` 设置为 `nil`,方便在不同环境中灵活且方便地部署。 +虽然可以手动指定 CA 证书路径,但在多环境部署场景中这样做可能会带来很大的不便,因为不同的机器和环境可能会将 CA 证书存储在不同的位置。因此,建议将 `sslca` 设置为 `nil`,以便在不同环境中灵活且易于部署。 ## 下一步 -- 从 [mysql2 的文档](https://github.com/brianmario/mysql2#readme)中了解更多关于 mysql2 驱动的使用情况。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [mysql2 文档](https://github.com/brianmario/mysql2#readme)了解更多 mysql2 驱动程序的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节学习 TiDB 应用程序开发的最佳实践,如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[查询数据](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 学习专业的 [TiDB 开发者课程](https://www.pingcap.com/education/),通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 ## 需要帮助? -在 [AskTUG](https://asktug.com/) 论坛上提问。 \ No newline at end of file + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-sample-application-ruby-rails.md b/develop/dev-guide-sample-application-ruby-rails.md index 343dd4342ce0..247076b23d46 100644 --- a/develop/dev-guide-sample-application-ruby-rails.md +++ b/develop/dev-guide-sample-application-ruby-rails.md @@ -1,52 +1,62 @@ --- title: 使用 Rails 框架和 ActiveRecord ORM 连接 TiDB -summary: 本文描述了 TiDB 和 Rails 框架的连接步骤,并给出了使用 Rails 框架和 ActiveRecord ORM 连接 TiDB 的简单示例代码片段。 +summary: 学习如何使用 Rails 框架连接 TiDB。本教程提供使用 Rails 框架和 ActiveRecord ORM 操作 TiDB 的 Ruby 示例代码片段。 --- # 使用 Rails 框架和 ActiveRecord ORM 连接 TiDB -TiDB 是一个兼容 MySQL 的数据库,[Rails](https://github.com/rails/rails) 是用 Ruby 编写的流行的 Web 框架,而 [ActiveRecord ORM](https://github.com/rails/rails/tree/main/activerecord) 是 Rails 中的对象关系映工具。 +TiDB 是一个兼容 MySQL 的数据库,[Rails](https://github.com/rails/rails) 是一个用 Ruby 编写的流行 Web 应用框架,[ActiveRecord ORM](https://github.com/rails/rails/tree/main/activerecord) 是 Rails 中的对象关系映射工具。 -本文档将展示如何使用 TiDB 和 Rails 来完成以下任务: +在本教程中,你将学习如何使用 TiDB 和 Rails 完成以下任务: -- 设置你的环境。 -- 使用 Rails 连接你的 TiDB 集群。 -- 构建并运行你的应用程序。你也可以参考[示例代码片段](#示例代码片段),完成基本的 CRUD 操作。 +- 设置开发环境 +- 使用 Rails 连接到 TiDB 集群 +- 构建并运行应用程序。你还可以找到使用 ActiveRecord ORM 进行基本 CRUD 操作的[示例代码片段](#sample-code-snippets) > **注意:** > -> 本文档适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 以及本地部署的 TiDB。 +> 本教程适用于 TiDB Cloud Serverless、TiDB Cloud Dedicated 和 TiDB Self-Managed。 -## 前置需求 +## 前提条件 -为了能够顺利完成本文中的操作,你需要提前: +完成本教程需要: -- 在你的机器上安装 [Ruby](https://www.ruby-lang.org/en/) 3.0 或以上版本。 -- 在你的机器上安装 [Bundler](https://bundler.io/)。 -- 在你的机器上安装 [Git](https://git-scm.com/downloads)。 -- 准备一个 TiDB 集群。 +- 在你的机器上安装 [Ruby](https://www.ruby-lang.org/en/) >= 3.0 +- 在你的机器上安装 [Bundler](https://bundler.io/) +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 一个正在运行的 TiDB 集群 -如果你还没有 TiDB 集群,可以按照以下方式创建: +**如果你还没有 TiDB 集群,可以按照以下方式创建:** -- (推荐方式)参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建你自己的 TiDB Cloud 集群。 -- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 + -## 运行示例应用程序并连接到 TiDB +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](/production-deployment-using-tiup.md)的说明创建本地集群。 -本小节演示如何运行示例应用程序的代码,并连接到 TiDB。 + + -### 第 1 步:克隆示例代码仓库到本地 +- (推荐)按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建你自己的 TiDB Cloud 集群。 +- 按照[部署本地测试 TiDB 集群](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb#deploy-a-local-test-cluster)或[部署生产 TiDB 集群](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup)的说明创建本地集群。 -在你的终端窗口中运行以下命令,将示例代码仓库克隆到本地: + + +## 运行示例应用程序连接 TiDB + +本节演示如何运行示例应用程序代码并连接到 TiDB。 + +### 步骤 1:克隆示例应用程序仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: ```shell git clone https://github.com/tidb-samples/tidb-ruby-rails-quickstart.git cd tidb-ruby-rails-quickstart ``` -### 第 2 步:安装依赖 +### 步骤 2:安装依赖 -运行以下命令,安装示例代码所需要的依赖(包括 `mysql2` 和 `dotenv` 依赖包): +运行以下命令安装示例应用程序所需的包(包括 `mysql2` 和 `dotenv`): ```shell bundle install @@ -55,7 +65,7 @@ bundle install
为现有项目安装依赖 -对于你的现有项目,运行以下命令以安装这些包: +对于你的现有项目,运行以下命令安装包: ```shell bundle add mysql2 dotenv @@ -63,20 +73,20 @@ bundle add mysql2 dotenv
-### 第 3 步:配置连接信息 +### 步骤 3:配置连接信息 -根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 +根据你选择的 TiDB 部署方式连接到 TiDB 集群。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你的目标集群的名称,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群名称进入集群概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**按钮。将显示连接对话框。 -3. 在连接对话框中,从 **Connect With** 下拉列表中选择 `Rails`,并保持 **Connection Type** 的默认设置为 `Public`。 +3. 在连接对话框中,从**连接方式**下拉列表中选择 `Rails`,并保持**连接类型**的默认设置为`公共`。 -4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 +4. 如果你还没有设置密码,点击**生成密码**生成随机密码。 5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: @@ -84,30 +94,30 @@ bundle add mysql2 dotenv cp .env.example .env ``` -6. 编辑 `.env` 文件,按照以下方式设置 `DATABASE_URL` 环境变量,并将占位符 `{}` 替换为连接对话框中相应的连接参数: +6. 编辑 `.env` 文件,设置 `DATABASE_URL` 环境变量如下,并从连接对话框中复制连接字符串作为变量值: ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database_name}?ssl_mode=verify_identity + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database_name}?ssl_mode=verify_identity' ``` > **注意** > - > 对于 TiDB Cloud Serverless,当使用 Public Endpoint 时,必须使用 `ssl_mode=verify_identity` 查询参数启用 TLS 连接。 + > 对于 TiDB Cloud Serverless,使用公共端点时**必须**通过 `ssl_mode=verify_identity` 查询参数启用 TLS 连接。 7. 保存 `.env` 文件。
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面中,点击你的目标集群的名称,进入集群的 **Overview** 页面。 +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群名称进入集群概览页面。 -2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 +2. 点击右上角的**连接**按钮。将显示连接对话框。 -3. 在连接对话框中,从 **Connection Type** 下拉列表中选择 **Public**,并点击 **CA cert** 下载 CA 文件。 +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,然后点击 **CA 证书**下载 CA 证书。 - 如果你尚未配置 IP 访问列表,请在首次连接前点击 **Configure IP Access List** 或按照[配置 IP 访问列表(英文)](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 + 如果你还没有配置 IP 访问列表,在首次连接之前,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置。 - 除 **Public** 连接类型外,TiDB Cloud Dedicated 还支持 **Private Endpoint** 和 **VPC Peering** 连接类型。详情请参阅[连接 TiDB Cloud Dedicated 集群(英文)](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 + 除了**公共**连接类型外,TiDB Cloud Dedicated 还支持**专用端点**和 **VPC 对等连接**连接类型。更多信息,请参阅[连接到 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/connect-to-tidb-cluster)。 4. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: @@ -115,22 +125,22 @@ bundle add mysql2 dotenv cp .env.example .env ``` -5. 编辑 `.env` 文件,按照以下方式设置 `DATABASE_URL` 环境变量,将占位符 `{}` 替换为连接对话框中相应的连接参数,并将 `sslca` 查询参数设置为从连接对话框下载的 CA 证书的文件路径: +5. 编辑 `.env` 文件,设置 `DATABASE_URL` 环境变量如下,从连接对话框中复制连接字符串作为变量值,并将 `sslca` 查询参数设置为从连接对话框下载的 CA 证书的文件路径: ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database}?ssl_mode=verify_identity&sslca=/path/to/ca.pem + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database}?ssl_mode=verify_identity&sslca=/path/to/ca.pem' ``` > **注意** > - > 当使用 Public Endpoint 连接到 TiDB Cloud Dedicated 集群时,建议启用 TLS 连接。 + > 使用公共端点连接到 TiDB Cloud Dedicated 时,建议启用 TLS 连接。 > - > 要启用 TLS 连接,请将 `ssl_mode` 查询参数的值修改为 `verify_identity`,并将 `sslca` 的值设置为从连接对话框下载的 CA 证书的文件路径。 + > 要启用 TLS 连接,请将 `ssl_mode` 查询参数的值修改为 `verify_identity`,并将 `sslca` 的值修改为从连接对话框下载的 CA 证书的文件路径。 6. 保存 `.env` 文件。
-
+
1. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: @@ -138,20 +148,20 @@ bundle add mysql2 dotenv cp .env.example .env ``` -2. 编辑 `.env` 文件,按照以下方式设置 `DATABASE_URL` 环境变量,并将 `{user}`、`{password}`、`{host}`、`{port}` 和 `{database}` 替换为你自己的 TiDB 连接信息: +2. 编辑 `.env` 文件,设置 `DATABASE_URL` 环境变量如下,并将 `{user}`、`{password}`、`{host}`、`{port}` 和 `{database}` 替换为你自己的 TiDB 连接信息: ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database} + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database}' ``` - 如果你在本地运行 TiDB,那么默认的主机地址是 `127.0.0.1`,密码为空。 + 如果你在本地运行 TiDB,默认主机地址是 `127.0.0.1`,密码为空。 3. 保存 `.env` 文件。
-### 第 4 步:运行代码并查看结果 +### 步骤 4:运行代码并检查结果 1. 创建数据库和表: @@ -172,7 +182,7 @@ bundle add mysql2 dotenv bundle exec rails runner ./quickstart.rb ``` -如果连接成功,你的终端将会输出所连接集群的版本信息: +如果连接成功,控制台将输出 TiDB 集群的版本信息如下: ``` 🔌 Connected to TiDB cluster! (TiDB version: 8.0.11-TiDB-v8.1.2) @@ -187,13 +197,13 @@ bundle add mysql2 dotenv ## 示例代码片段 -你可参考以下关键代码片段,完成自己的应用开发。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 -完整代码及其运行方式,见代码仓库 [tidb-samples/tidb-ruby-rails-quickstart](https://github.com/tidb-samples/tidb-ruby-rails-quickstart)。 +完整的示例代码和运行方法,请查看 [tidb-samples/tidb-ruby-rails-quickstart](https://github.com/tidb-samples/tidb-ruby-rails-quickstart) 仓库。 -### 连接到 TiDB +### 使用连接选项连接到 TiDB -`config/database.yml` 中的以下代码使用 `DATABASE_URL` 系统变量的配置连接到 TiDB: +以下 `config/database.yml` 中的代码使用环境变量中定义的选项建立与 TiDB 的连接: ```yml default: &default @@ -215,11 +225,11 @@ production: > **注意** > -> 对于 TiDB Cloud Serverless,当使用 Public Endpoint 时,**必须**通过在 `DATABASE_URL` 中设置 `ssl_mode` 查询参数为 `verify_identity` 来启用 TLS 连接,但是你**不需要**通过 `DATABASE_URL` 指定 SSL CA 证书,因为 mysql2 gem 会按照特定的顺序搜索现有的 CA 证书,直到找到相应的文件。 +> 对于 TiDB Cloud Serverless,使用公共端点时**必须**通过在 `DATABASE_URL` 中设置 `ssl_mode` 查询参数为 `verify_identity` 来启用 TLS 连接,但你**不需要**通过 `DATABASE_URL` 指定 SSL CA 证书,因为 mysql2 gem 会按特定顺序搜索现有的 CA 证书,直到找到一个文件。 ### 插入数据 -以下查询创建了一个具有两个字段的 Player,并返回创建的 `Player` 对象: +以下查询创建一个具有两个字段的 Player 并返回创建的 `Player` 对象: ```ruby new_player = Player.create!(coins: 100, goods: 100) @@ -229,7 +239,7 @@ new_player = Player.create!(coins: 100, goods: 100) ### 查询数据 -以下通过 ID 查询返回特定 `Player` 的记录: +以下查询通过 ID 返回特定玩家的记录: ```ruby player = Player.find_by(id: new_player.id) @@ -239,7 +249,7 @@ player = Player.find_by(id: new_player.id) ### 更新数据 -以下查询更新特定 `Player` 对象: +以下查询更新一个 `Player` 对象: ```ruby player.update(coins: 50, goods: 50) @@ -249,7 +259,7 @@ player.update(coins: 50, goods: 50) ### 删除数据 -以下查询删除特定 `Player` 对象: +以下查询删除一个 `Player` 对象: ```ruby player.destroy @@ -259,21 +269,31 @@ player.destroy ## 最佳实践 -默认情况下,mysql2 gem 可以按照特定的顺序搜索现有的 CA 证书,直到找到相应的文件。 +默认情况下,mysql2 gem(由 ActiveRecord ORM 用于连接 TiDB)会按特定顺序搜索现有的 CA 证书,直到找到一个文件。 -1. 对于 Debian、Ubuntu、Gentoo、Arch 或 Slackware,证书的默认存储路径为 `/etc/ssl/certs/ca-certificates.crt`。 -2. 对于 RedHat、Fedora、CentOS、Mageia、Vercel 或 Netlify,证书的默认存储路径为 `/etc/pki/tls/certs/ca-bundle.crt`。 -3. 对于 OpenSUSE,证书的默认存储路径为 `/etc/ssl/ca-bundle.pem`。 -4. 对于 macOS 或 Alpine(docker 容器),证书的默认存储路径为 `/etc/ssl/cert.pem`。 +1. /etc/ssl/certs/ca-certificates.crt # Debian / Ubuntu / Gentoo / Arch / Slackware +2. /etc/pki/tls/certs/ca-bundle.crt # RedHat / Fedora / CentOS / Mageia / Vercel / Netlify +3. /etc/ssl/ca-bundle.pem # OpenSUSE +4. /etc/ssl/cert.pem # MacOS / Alpine (docker container) -尽管可以手动指定 CA 证书路径,但在多环境部署场景中这可能会引起不必要的麻烦,因为不同的机器和环境可能存储 CA 证书的位置不同。因此,建议将 `sslca` 设置为 `nil`,方便在不同环境中灵活且方便地部署。 +虽然可以手动指定 CA 证书路径,但这种方法可能会在多环境部署场景中造成很大的不便,因为不同的机器和环境可能会将 CA 证书存储在不同的位置。因此,建议将 `sslca` 设置为 `nil`,以便在不同环境中灵活部署。 ## 下一步 -- 从 [ActiveRecord 文档](https://guides.rubyonrails.org/active_record_basics.html)中了解更多关于 ActiveRecord ORM 的用法。 -- 你可以继续阅读开发者文档的其它章节来获取更多 TiDB 应用开发的最佳实践。例如:[插入数据](/develop/dev-guide-insert-data.md),[更新数据](/develop/dev-guide-update-data.md),[删除数据](/develop/dev-guide-delete-data.md),[单表读取](/develop/dev-guide-get-data-from-single-table.md),[事务](/develop/dev-guide-transaction-overview.md),[SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)等。 -- 如果你更倾向于参与课程进行学习,我们也提供专业的 [TiDB 开发者课程](https://cn.pingcap.com/courses-catalog/category/back-end-developer/?utm_source=docs-cn-dev-guide)支持,并在考试后提供相应的[资格认证](https://learn.pingcap.com/learner/certification-center)。 +- 从 [ActiveRecord 文档](https://guides.rubyonrails.org/active_record_basics.html)中了解更多 ActiveRecord ORM 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如:[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[查询数据](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 ## 需要帮助? -在 [AskTUG](https://asktug.com/) 论坛上提问。 \ No newline at end of file + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-schema-design-overview.md b/develop/dev-guide-schema-design-overview.md index 61c8d5c7cd10..5d59cabcff1e 100644 --- a/develop/dev-guide-schema-design-overview.md +++ b/develop/dev-guide-schema-design-overview.md @@ -1,67 +1,104 @@ --- -title: 概述 -summary: TiDB 数据库模式设计的概述。 +title: TiDB 数据库架构设计概述 +summary: 了解 TiDB 数据库架构设计的基础知识。 --- -# 概述 +# TiDB 数据库架构设计概述 -本页概述了 TiDB 中的数据库模式。将从本页开始围绕 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 这个应用程序来对 TiDB 的设计数据库部分展开介绍。并使用此数据库做后续数据的写入、读取示例。 +本文档提供了 TiDB 数据库架构设计的基础知识,包括 TiDB 中的对象、访问控制、数据库架构变更和对象限制。 -## 术语歧义 +在后续文档中,将以[书店](/develop/dev-guide-bookshop-schema-design.md)为例,向你展示如何设计数据库并在数据库中执行数据读写操作。 -此处术语会有歧义,为消除歧义,在此作出数据库模式设计文档部分中的术语简要约定: +## TiDB 中的对象 -为避免和通用术语[数据库 (Database)](https://en.wikipedia.org/wiki/Database) 混淆,因此将逻辑对象称为**数据库 (Database)**,TiDB 仍使用原名称,并将 TiDB 的部署实例称为**集群 (Cluster)**。 +为了区分一些通用术语,以下是 TiDB 中使用的术语约定: -因为 TiDB 使用与 MySQL 兼容的语法,在此语法下,**模式 (Schema)** 仅代表[通用术语定义](https://en.wiktionary.org/wiki/schema),并无逻辑对象定义,可参考此[官方文档](https://dev.mysql.com/doc/refman/8.0/en/create-database.html)。若你从其他拥有 **Schema** 逻辑对象的数据库(如:[PostgreSQL](https://www.postgresql.org/docs/current/ddl-schemas.html)、[Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/tdddg/creating-managing-schema-objects.html)、[Microsoft SQL Server](https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-schema?view=sql-server-ver15) 等)迁移而来,请注意此区别。 +- 为避免与通用术语[数据库](https://en.wikipedia.org/wiki/Database)混淆,本文档中的**数据库**指的是一个逻辑对象,**TiDB** 指的是 TiDB 本身,而**集群**指的是已部署的 TiDB 实例。 -## 数据库 Database +- TiDB 使用与 MySQL 兼容的语法,其中 **schema** 表示通用术语 [schema](https://en.wiktionary.org/wiki/schema),而不是数据库中的逻辑对象。更多信息,请参见 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/create-database.html)。如果你要从将 schema 作为逻辑对象的数据库(例如 [PostgreSQL](https://www.postgresql.org/docs/current/ddl-schemas.html)、[Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/tdddg/creating-managing-schema-objects.html) 和 [Microsoft SQL Server](https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-schema?view=sql-server-ver15))迁移,请注意这一区别。 -TiDB 语境中的 Database 或者说数据库,可以认为是表和索引等对象的集合。 +### 数据库 -TiDB 集群包含一个名为 `test` 的数据库。但建议你自行创建数据库,而不是使用 `test` 数据库。 +TiDB 中的数据库是表和索引等对象的集合。 -## 表 Table +TiDB 自带一个名为 `test` 的默认数据库。但是,建议你创建自己的数据库,而不是使用 `test` 数据库。 -TiDB 语境中的 Table 或者说表,从属于某个[数据库](#数据库-database)。 +### 表 -表包含数据**行**。每行数据中的每个值都属于一个特定的**列**。每列都只允许单一数据类型的数据值。列可添加[约束](/constraints.md)来进一步限定。你还可以添加[生成列](/generated-columns.md)用于计算。 +表是[数据库](#数据库)中相关数据的集合。 -## 索引 Index +每个表由**行**和**列**组成。行中的每个值都属于特定的**列**。每列只允许单一数据类型。为了进一步限定列,你可以添加一些[约束](/constraints.md)。为了加速计算,你可以添加[生成列](/generated-columns.md)。 -索引是单个表中行的副本,按列或列集排序。TiDB 查询使用索引来更有效的查找表内的数据,同时可以给出特定列的值。每个索引都是从属于某个[表](#表-table)的。 +### 索引 -索引有两种常见的类型,分别为: +索引是表中选定列的副本。你可以使用[表](#表)的一列或多列创建索引。通过索引,TiDB 可以快速定位数据,而无需每次都搜索表中的每一行,这大大提高了查询性能。 -- **Primary Key**: 即主键索引,即标识在主键列上的索引。 -- **Secondary Index**: 即二级索引,即在非主键上标识的索引。 +有两种常见的索引类型: + +- **主键**:主键列上的索引。 +- **二级索引**:非主键列上的索引。 > **注意:** > -> TiDB 中,关于 **Primary Key** 的默认定义与 MySQL 常用存储引擎 [InnoDB](https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html) 不一致。**InnoDB** 中,**Primary Key** 的语义为:唯一,不为空,**且为聚簇索引**。 +> 在 TiDB 中,**主键**的默认定义与 [InnoDB](https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html)(MySQL 的常用存储引擎)中的定义不同。 > -> 而在 TiDB 中,**Primary Key** 的定义为:唯一,不为空。但主键不保证为**聚簇索引**。而是由另一组关键字 `CLUSTERED`、`NONCLUSTERED` 额外控制 **Primary Key** 是否为聚簇索引,若不指定,则由系统变量 `@@global.tidb_enable_clustered_index` 影响,具体说明请看[聚簇索引](/clustered-indexes.md)。 +> - 在 InnoDB 中,**主键**的定义是唯一的、非空的,并且是**聚簇索引**。 +> - 在 TiDB 中,**主键**的定义是唯一的和非空的。但主键不一定是**聚簇索引**。要指定主键是否为聚簇索引,你可以在 `CREATE TABLE` 语句中的 `PRIMARY KEY` 后添加非保留关键字 `CLUSTERED` 或 `NONCLUSTERED`。如果语句没有明确指定这些关键字,默认行为由系统变量 `@@global.tidb_enable_clustered_index` 控制。更多信息,请参见[聚簇索引](/clustered-indexes.md)。 + +#### 专用索引 + + + +为了提高各种用户场景的查询性能,TiDB 为你提供了一些专用类型的索引。有关每种类型的详细信息,请参见[索引和约束](/basic-features.md#索引和约束)。 + + -### 专用索引 + -TiDB 支持一些特殊场景专用的索引,用以提高特定用例中的查询性能。具体请参考[索引和约束](/basic-features.md#索引和约束)。 +为了提高各种用户场景的查询性能,TiDB 为你提供了一些专用类型的索引。有关每种类型的详细信息,请参见[索引和约束](https://docs.pingcap.com/tidb/stable/basic-features#indexing-and-constraints)。 -## 其他对象 + -TiDB 支持一些和**表**同级的对象: +### 其他支持的逻辑对象 -- [视图](/views.md): 视图是一张虚拟表,该虚拟表的结构由创建视图时的 `SELECT` 语句定义,TiDB 目前不支持物化视图。 -- [序列](/sql-statements/sql-statement-create-sequence.md): 创建和存储顺序数据。 -- [临时表](/temporary-tables.md): 临时表是数据不持久化的表。 +TiDB 支持以下与**表**处于同一级别的逻辑对象: + +- [视图](/views.md):视图充当虚拟表,其架构由创建视图的 `SELECT` 语句定义。 +- [序列](/sql-statements/sql-statement-create-sequence.md):序列用于生成和存储顺序数据。 +- [临时表](/temporary-tables.md):数据不持久的表。 ## 访问控制 -TiDB 支持基于用户或角色的访问控制。你可以通过[角色](/role-based-access-control.md)或直接指向[用户](/user-account-management.md),从而授予**用户**查看、修改或删除数据对象和数据模式的[权限](/privilege-management.md)。 + + +TiDB 支持基于用户和基于角色的访问控制。要允许用户查看、修改或删除数据对象和数据架构,你可以直接向[用户](/user-account-management.md)授予[权限](/privilege-management.md),或通过[角色](/role-based-access-control.md)向用户授予[权限](/privilege-management.md)。 + + + + + +TiDB 支持基于用户和基于角色的访问控制。要允许用户查看、修改或删除数据对象和数据架构,你可以直接向[用户](https://docs.pingcap.com/tidb/stable/user-account-management)授予[权限](https://docs.pingcap.com/tidb/stable/privilege-management),或通过[角色](https://docs.pingcap.com/tidb/stable/role-based-access-control)向用户授予[权限](https://docs.pingcap.com/tidb/stable/privilege-management)。 + + + +## 数据库架构变更 + +作为最佳实践,建议你使用 [MySQL 客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)或 GUI 客户端而不是驱动程序或 ORM 来执行数据库架构变更。 + +## 对象限制 + +更多信息,请参见 [TiDB 限制](/tidb-limitations.md)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 -## 执行数据库模式更改 + -不推荐使用客户端的 Driver 或 ORM 来执行数据库模式的更改。以经验来看,作为最佳实践,建议使用 [MySQL 客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)或使用任意你喜欢的 GUI 客户端来进行数据库模式的更改。本文档中,将在大多数场景下,使用 **MySQL 客户端** 传入 SQL 文件来执行数据库模式的更改。 + -## 对象大小限制 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -具体限制请参考 [TiDB 使用限制](/tidb-limitations.md)。 + diff --git a/develop/dev-guide-sql-development-specification.md b/develop/dev-guide-sql-development-specification.md index c7f5ad663ea3..16dd207da7dd 100644 --- a/develop/dev-guide-sql-development-specification.md +++ b/develop/dev-guide-sql-development-specification.md @@ -1,28 +1,28 @@ --- title: SQL 开发规范 -summary: TiDB 的 SQL 开发规范。 +summary: 了解 TiDB 的 SQL 开发规范。 --- # SQL 开发规范 -本章将介绍一些使用 SQL 的一般化开发规范。 +本文介绍使用 SQL 时的一些通用开发规范。 -## 建表删表规范 +## 创建和删除表 -- 基本原则:表的建立在遵循表命名规范前提下,建议业务应用内部封装建表删表语句增加判断逻辑,防止业务流程异常中断。 -- 详细说明:`create table if not exists table_name` 或者 `drop table if exists table_name` 语句建议增加 if 判断,避免应用侧由于 SQL 命令运行异常造成的异常中断。 +- 基本原则:在遵循表命名规范的前提下,建议应用程序内部封装表的创建和删除语句,并添加判断逻辑,以防止业务流程异常中断。 +- 详细说明:建议使用 `create table if not exists table_name` 或 `drop table if exists table_name` 语句添加 `if` 判断,以避免应用程序端 SQL 命令运行异常导致的中断。 -## SELECT \* 使用规范 +## `SELECT *` 的使用 -- 基本原则:避免使用 SELECT \* 进行查询。 -- 详细说明:按需求选择合适的字段列,避免盲目地 SELECT \* 读取全部字段,因为其会消耗网络带宽。考虑将被查询的字段也加入到索引中,以有效利用覆盖索引功能。 +- 基本原则:避免使用 `SELECT *` 进行查询。 +- 详细说明:根据需要选择适当的列,避免使用 `SELECT *` 读取所有字段,因为这样的操作会消耗网络带宽。考虑将查询的字段添加到索引中,以有效利用覆盖索引。 -## 字段上使用函数规范 +## 在字段上使用函数 -- 基本原则:在取出字段上可以使用相关函数,但是在 Where 条件中的过滤条件字段上避免使用任何函数,包括数据类型转换函数,以避免索引失效。或者可以考虑使用表达式索引功能。 +- 基本原则:可以在查询的字段上使用相关函数。为避免索引失效,不要在 `WHERE` 子句的过滤字段上使用任何函数,包括数据类型转换函数。你可以考虑使用表达式索引。 - 详细说明: - 不推荐的写法: + 不推荐: {{< copyable "sql" >}} @@ -32,23 +32,37 @@ summary: TiDB 的 SQL 开发规范。 WHERE DATE_FORMAT(gmt_create, '%Y%m%d %H:%i:%s') = '20090101 00:00:00' ``` - 推荐的写法: + 推荐: {{< copyable "sql" >}} ```sql - SELECT DATE_FORMAT(gmt_create,'%Y%m%d %H:%i:%s') + SELECT DATE_FORMAT(gmt_create, '%Y%m%d %H:%i:%s') FROM ... WHERE gmt_create = str_to_date('20090101 00:00:00', '%Y%m%d %H:%i:%s') ``` ## 其他规范 -- WHERE 条件中不要在索引列上进行数学运算或函数运算。 -- 用 in/union 替换 or,并注意 in 的个数小于 300。 -- 避免使用 %前缀进行模糊前缀查询。 -- 如应用使用 Multi Statements 执行 SQL,即将多个 SQL 使用分号连接,一次性地发给客户端执行,TiDB 只会返回第一个 SQL 的执行结果。 -- 当使用表达式时,检查其是否支持计算下推到存储层的功能 (TiKV、TiFlash),否则应有预期在 TiDB 层需要消耗更多内存、甚至 OOM。计算下推到存储层的功能列表如下: - - [TiFlash 支持的计算下推清单](/tiflash/tiflash-supported-pushdown-calculations.md)。 - - [下推到 TiKV 的表达式列表](/functions-and-operators/expressions-pushed-down.md#下推到-tikv-的表达式列表)。 - - [谓词下推](/predicate-push-down.md#谓词下推)。 +- 不要在 `WHERE` 条件中对索引列进行数学运算或函数运算。 +- 用 `IN` 或 `UNION` 替代 `OR`。`IN` 的数量必须小于 `300`。 +- 避免使用 `%` 前缀进行模糊前缀查询。 +- 如果应用程序使用 **Multi Statements** 执行 SQL,即多个 SQL 用分号连接并一次性发送到客户端执行,TiDB 只返回第一个 SQL 的执行结果。 +- 使用表达式时,检查表达式是否支持计算下推到存储层(TiKV 或 TiFlash)。如果不支持,你应该预期 TiDB 层会有更多的内存消耗,甚至可能出现 OOM。可以下推到存储层的计算包括: + - [TiFlash 支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md)。 + - [TiKV - 下推表达式列表](/functions-and-operators/expressions-pushed-down.md)。 + - [谓词下推](/predicate-push-down.md)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-third-party-support.md b/develop/dev-guide-third-party-support.md index 0915e57364e0..fdcdec5aed7c 100644 --- a/develop/dev-guide-third-party-support.md +++ b/develop/dev-guide-third-party-support.md @@ -1,38 +1,38 @@ --- title: TiDB 支持的第三方工具 -summary: TiDB 支持的第三方工具主要包括驱动、ORM 框架和 GUI。支持等级分为 Full 和 Compatible,其中 Full 表示绝大多数功能兼容性已得到支持,Compatible 表示大部分功能可使用但未经完整验证。对于支持的 Driver 或 ORM 框架并不包括应用端事务重试和错误处理。如果在使用工具连接 TiDB 时出现问题,可在 GitHub 上提交包含详细信息的 issue 以获得进展。 +summary: 了解 TiDB 支持的第三方工具。 --- # TiDB 支持的第三方工具 > **注意:** > -> 本文档仅列举了常见的 TiDB 支持的[第三方工具](https://en.wikipedia.org/wiki/Third-party_source),未被列入其中的第三方工具并非代表不支持,但 PingCAP 无法了解其是否使用到 TiDB 不支持的特性,从而无法保证兼容性。 +> 本文档仅列出 TiDB 支持的常见[第三方工具](https://en.wikipedia.org/wiki/Third-party_source)。一些其他第三方工具未被列出,这并不是因为它们不受支持,而是因为 PingCAP 不确定它们是否使用了与 TiDB 不兼容的功能。 -TiDB [高度兼容 MySQL 协议](/mysql-compatibility.md),使得大部分适配 MySQL 的 Driver、ORM 及其他工具与 TiDB 兼容。本文主要介绍这些工具和它们的支持等级。 +TiDB [高度兼容 MySQL 协议](/mysql-compatibility.md),因此大多数适配 MySQL 的驱动程序、ORM 框架和其他工具都与 TiDB 兼容。本文档重点介绍这些工具及其对 TiDB 的支持级别。 -## 支持等级 +## 支持级别 -PingCAP 与开源社区合作,通过三方工具提供以下支持: +PingCAP 与社区合作,为第三方工具提供以下支持级别: -- Full:表明 PingCAP 已经支持该工具的绝大多数功能兼容性,并且在新版本中对其保持兼容,将定期地对下表中记录的新版本进行兼容性测试。 -- Compatible:表明由于该工具已适配 MySQL,而 TiDB 高度兼容 MySQL 协议,因此可以使用此工具的大部分功能。但 PingCAP 并未对该工具作出完整的兼容性验证,有可能出现一些意外的行为。 +- **_完全_**:表示 TiDB 已经与相应第三方工具的大多数功能兼容,并保持与其新版本的兼容性。PingCAP 会定期对该工具的最新版本进行兼容性测试。 +- **_兼容_**:表示由于相应的第三方工具适配了 MySQL,而 TiDB 高度兼容 MySQL 协议,因此 TiDB 可以使用该工具的大多数功能。但是,PingCAP 尚未对该工具的所有功能进行完整测试,这可能会导致一些意外行为。 > **注意:** > -> 除非明确说明,否则对于支持的 Driver 或者 ORM 框架并不包括[应用端事务重试和错误处理](/develop/dev-guide-transaction-troubleshoot.md#应用端重试和错误处理)。 +> 除非特别说明,**驱动程序**或 **ORM 框架**不包括对[应用程序重试和错误处理](/develop/dev-guide-transaction-troubleshoot.md#application-retry-and-error-handling)的支持。 -如果在使用本文列出的工具连接 TiDB 时出现问题,请在 GitHub 上提交包含详细信息的 [issue](https://github.com/pingcap/tidb/issues/new?assignees=&labels=type%2Fquestion&template=general-question.md),以帮助在此工具的支持上得到进展。 +如果你在使用本文档列出的工具连接 TiDB 时遇到问题,请在 GitHub 上提交[问题](https://github.com/pingcap/tidb/issues/new?assignees=&labels=type%2Fquestion&template=general-question.md)并提供详细信息,以促进对该工具的支持。 -## Driver +## 驱动程序 - - - - + + + + @@ -42,22 +42,22 @@ PingCAP 与开源社区合作,通过三方工具提供以下支持: - + - + - + - +
编程语言驱动最新已测试版本支持等级语言驱动程序最新测试版本支持级别 TiDB 适配器 教程
Go Go-MySQL-Driver v1.6.0Full完全 N/A使用 Go-MySQL-Driver 连接到 TiDB使用 Go-MySQL-Driver 连接 TiDB
Java JDBC 8.0Full完全 使用 JDBC 连接到 TiDB使用 JDBC 连接 TiDB
@@ -67,10 +67,10 @@ PingCAP 与开源社区合作,通过三方工具提供以下支持: - + - - + + @@ -80,28 +80,28 @@ PingCAP 与开源社区合作,通过三方工具提供以下支持: - + - + - + - + - + @@ -109,28 +109,28 @@ PingCAP 与开源社区合作,通过三方工具提供以下支持: - + - + - + - + - + - + - - + + @@ -138,54 +138,69 @@ PingCAP 与开源社区合作,通过三方工具提供以下支持: - + - + - - + + - + - + - + - + - + - + - + - +
编程语言语言 ORM 框架最新已测试版本支持等级最新测试版本支持级别 TiDB 适配器 教程
Go gorm v1.23.5Full完全 N/A使用 GORM 连接到 TiDB使用 GORM 连接 TiDB
beego v2.0.3Full完全 N/A N/A
upper/db v4.5.2Full完全 N/A N/A
xorm v1.3.1Full完全 N/A N/A
Java Hibernate 6.1.0.FinalFull完全 N/A使用 Hibernate 连接到 TiDB使用 Hibernate 连接 TiDB
MyBatis v3.5.10Full完全 N/A使用 MyBatis 连接到 TiDB使用 MyBatis 连接 TiDB
Spring Data JPA 2.7.2Full完全 N/A使用 Spring Boot 连接到 TiDB使用 Spring Boot 连接 TiDB
jOOQv3.16.7 (Open Source)Fullv3.16.7(开源版)完全 N/A N/A
Ruby Active Record v7.0Full完全 N/A使用 Rails 框架和 ActiveRecord ORM 连接到 TiDB使用 Rails 框架和 ActiveRecord ORM 连接 TiDB
JavaScript / TypeScript Sequelize v6.20.1FullN/A完全 N/A使用 Sequelize 连接 TiDB
Prisma 4.16.2Full完全 N/A使用 Prisma 连接到 TiDB使用 Prisma 连接 TiDB
TypeORM v0.3.17Full完全 N/A使用 TypeORM 连接到 TiDB使用 TypeORM 连接 TiDB
Python Django v4.2Full完全 django-tidb使用 Django 连接到 TiDB使用 Django 连接 TiDB
SQLAlchemy v1.4.37Full完全 N/A使用 SQLAlchemy 连接到 TiDB使用 SQLAlchemy 连接 TiDB
## GUI -| GUI | 最新已测试版本 | 支持等级 | 教程 | -|-----------------------------------------------------------|-----------------------|---------------|-----| -| [JetBrains DataGrip](https://www.jetbrains.com/datagrip/) | 2023.2.1 | Full | N/A | -| [DBeaver](https://dbeaver.io/) | 23.0.3 | Full | N/A | -| [Visual Studio Code](https://code.visualstudio.com/) | 1.72.0 | Full | N/A | \ No newline at end of file +| GUI | 最新测试版本 | 支持级别 | 教程 | +|-----------------------------------------------------------|-----------------------|---------------|--------------------------------------------------------------------------------------| +| [Beekeeper Studio](https://www.beekeeperstudio.io/) | 4.3.0 | 完全 | N/A | +| [JetBrains DataGrip](https://www.jetbrains.com/datagrip/) | 2023.2.1 | 完全 | [使用 JetBrains DataGrip 连接 TiDB](/develop/dev-guide-gui-datagrip.md) | +| [DBeaver](https://dbeaver.io/) | 23.0.3 | 完全 | [使用 DBeaver 连接 TiDB](/develop/dev-guide-gui-dbeaver.md) | +| [Visual Studio Code](https://code.visualstudio.com/) | 1.72.0 | 完全 | [使用 Visual Studio Code 连接 TiDB](/develop/dev-guide-gui-vscode-sqltools.md) | + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-third-party-tools-compatibility.md b/develop/dev-guide-third-party-tools-compatibility.md index fa9713bcd716..8bfe68326eb1 100644 --- a/develop/dev-guide-third-party-tools-compatibility.md +++ b/develop/dev-guide-third-party-tools-compatibility.md @@ -1,56 +1,76 @@ --- -title: 已知的第三方工具兼容问题 -summary: 介绍在测试中发现的 TiDB 与第三方工具的兼容性问题。 +title: 第三方工具的已知兼容性问题 +summary: 描述在测试中发现的 TiDB 与第三方工具的兼容性问题。 --- -# 已知的第三方工具兼容问题 +# 第三方工具的已知兼容性问题 > **注意:** > -> TiDB 已列举[不支持的功能特性](/mysql-compatibility.md#不支持的功能特性),典型的不支持特性有: +> [不支持的特性](/mysql-compatibility.md#unsupported-features) 部分列出了 TiDB 中不支持的特性,包括: > -> - 存储过程与函数 +> - 存储过程和函数 > - 触发器 > - 事件 -> - 自定义函数 -> - 空间类型的函数、数据类型和索引 +> - 用户自定义函数 +> - `SPATIAL` 函数、数据类型和索引 > - `XA` 语法 > -> 这些不支持的功能不兼容将被视为预期行为,不再重复叙述。关于更多 TiDB 与 MySQL 的兼容性对比,你可以查看[与 MySQL 兼容性对比](/mysql-compatibility.md)。 +> 上述不支持的特性是预期行为,本文档中不再列出。更多详情,请参阅 [MySQL 兼容性](/mysql-compatibility.md)。 -本文列举的兼容性问题是在一些 [TiDB 支持的第三方工具](/develop/dev-guide-third-party-support.md)中发现的。 +本文档列出了在一些 [TiDB 支持的第三方工具](/develop/dev-guide-third-party-tools-compatibility.md) 中发现的兼容性问题。 -## 通用 +## 一般兼容性问题 -### TiDB 中 `SELECT CONNECTION_ID()` 返回结果类型为 64 位整型 +### `SELECT CONNECTION_ID()` 在 TiDB 中返回 64 位整数 **描述** -TiDB 中 `SELECT CONNECTION_ID()` 的返回值为 64 位,如 `2199023260887`。而 MySQL 中返回值为 32 位,如 `391650`。 +`SELECT CONNECTION_ID()` 函数在 TiDB 中返回 64 位整数,如 `2199023260887`,而在 MySQL 中返回 32 位整数,如 `391650`。 **规避方法** -在 TiDB 应用程序中,请注意使用各语言的 64 位整型类型(或字符串类型)存储 `SELECT CONNECTION_ID()` 的结果,防止溢出。如 Java 应使用 `Long` 或 `String` 进行接收,JavaScript/TypeScript 应使用 `string` 类型进行接收。 +在 TiDB 应用程序中,为避免数据溢出,应使用 64 位整数或字符串类型来存储 `SELECT CONNECTION_ID()` 的结果。例如,在 Java 中可以使用 `Long` 或 `String`,在 JavaScript 或 TypeScript 中使用 `string`。 -### TiDB 未设置 `Com_*` 计数器 +### TiDB 不维护 `Com_*` 计数器 **描述** -MySQL 维护了一系列 [`Com_` 开头的服务端变量](https://dev.mysql.com/doc/refman/8.0/en/server-status-variables.html#statvar_Com_xxx)来记录你对数据库的操作总数,如 `Com_select` 记录了 MySQL 数据库从上次启动开始,总共发起的 `SELECT` 语句数(即使语句并未成功执行)。而 TiDB 并未维护此变量。你可以使用语句 [SHOW GLOBAL STATUS LIKE 'Com_%'](/sql-statements/sql-statement-show-status.md) 观察 TiDB 与 MySQL 的差异。 +MySQL 维护一系列以 `Com_` 开头的[服务器状态变量](https://dev.mysql.com/doc/refman/8.0/en/server-status-variables.html#statvar_Com_xxx),用于跟踪自上次启动以来对数据库执行的操作总数。例如,`Com_select` 记录了 MySQL 自启动以来发起的 `SELECT` 语句总数(即使语句未成功查询)。TiDB 不维护这些变量。你可以使用语句 [SHOW GLOBAL STATUS LIKE 'Com_%'](/sql-statements/sql-statement-show-status.md) 查看 TiDB 和 MySQL 之间的差异。 **规避方法** -请勿使用这样的变量。在 MySQL 中 `Com_*` 常见的使用场景之一是监控。TiDB 的可观测性较为完善,无需从服务端变量进行查询。如需定制监控工具,可阅读 [TiDB 监控框架概述](/tidb-monitoring-framework.md)来获得更多信息。 + -### TiDB 错误日志区分 `TIMESTAMP` 与 `DATETIME` 类型 +不要使用这些变量。一个常见场景是监控。TiDB 具有良好的可观察性,不需要从服务器状态变量中查询。对于自定义监控工具,请参考 [TiDB 监控框架概述](/tidb-monitoring-framework.md)。 + + + + + +不要使用这些变量。一个常见场景是监控。TiDB Cloud 具有良好的可观察性,不需要从服务器状态变量中查询。有关 TiDB Cloud 监控服务的更多信息,请参考[监控 TiDB 集群](/tidb-cloud/monitor-tidb-cluster.md)。 + + + +### TiDB 在错误消息中区分 `TIMESTAMP` 和 `DATETIME` **描述** -TiDB 错误日志区分 `TIMESTAMP` 与 `DATETIME`,而 MySQL 不区分,全部返回为 `DATETIME`。即 MySQL 会将 `TIMESTAMP` 类型的报错信息错误地写为 `DATETIME` 类型。 +TiDB 错误消息区分 `TIMESTAMP` 和 `DATETIME`,而 MySQL 不区分,都返回为 `DATETIME`。也就是说,MySQL 错误地将 `TIMESTAMP` 类型的错误消息转换为 `DATETIME` 类型。 **规避方法** -请勿使用错误日志进行字符串匹配,要使用[错误码](/error-codes.md)进行故障诊断。 + + +不要使用错误消息进行字符串匹配。相反,使用[错误码](/error-codes.md)进行故障排除。 + + + + + +不要使用错误消息进行字符串匹配。相反,使用[错误码](https://docs.pingcap.com/tidb/stable/error-codes)进行故障排除。 + + ### TiDB 不支持 `CHECK TABLE` 语句 @@ -60,9 +80,9 @@ TiDB 不支持 `CHECK TABLE` 语句。 **规避方法** -在 TiDB 中使用 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 语句进行表中数据和对应索引的一致性校验。 +要检查数据和相应索引的一致性,可以在 TiDB 中使用 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 语句。 -## 与 MySQL JDBC 的兼容性 +## MySQL JDBC 兼容性 测试版本为 MySQL Connector/J 8.0.29。 @@ -70,11 +90,11 @@ TiDB 不支持 `CHECK TABLE` 语句。 **描述** -MySQL Connector/J 的排序规则保存在客户端内,通过获取的服务端版本进行判别。 +MySQL Connector/J 的排序规则存储在客户端,并根据服务器版本进行区分。 -下表列出了已知的客户端与服务端排序规则不一致的字符集: +下表列出了已知的客户端和服务器端字符集排序规则不一致: -| 字符集 | 客户端默认排序规则 | 服务端默认排序规则 | +| 字符集 | 客户端默认排序规则 | 服务器端默认排序规则 | | --------- | -------------------- | ------------- | | `ascii` | `ascii_general_ci` | `ascii_bin` | | `latin1` | `latin1_swedish_ci` | `latin1_bin` | @@ -82,91 +102,93 @@ MySQL Connector/J 的排序规则保存在客户端内,通过获取的服务 **规避方法** -在 TiDB 中手动设置排序规则,不要依赖客户端默认排序规则。客户端默认排序规则由 MySQL Connector/J 配置文件保存。 +手动设置排序规则,不要依赖客户端默认排序规则。客户端默认排序规则由 MySQL Connector/J 配置文件存储。 -### 参数 `NO_BACKSLASH_ESCAPES` 不生效 +### `NO_BACKSLASH_ESCAPES` 参数不生效 **描述** -TiDB 中无法使用 `NO_BACKSLASH_ESCAPES` 参数从而不进行 `\` 字符的转义。已提 [issue](https://github.com/pingcap/tidb/issues/35302)。 +在 TiDB 中,如果不转义 `\` 字符,则无法使用 `NO_BACKSLASH_ESCAPES` 参数。更多详情,请跟踪此 [issue](https://github.com/pingcap/tidb/issues/35302)。 **规避方法** -在 TiDB 中不搭配使用 `NO_BACKSLASH_ESCAPES` 与 `\`,而是使用 `\\` 编写 SQL 语句。 +在 TiDB 中不要将 `NO_BACKSLASH_ESCAPES` 与 `\` 一起使用,而是在 SQL 语句中使用 `\\`。 -### 未设置索引使用情况参数 +### 不支持 `INDEX_USED` 相关参数 **描述** -TiDB 在通讯协议中未设置 `SERVER_QUERY_NO_GOOD_INDEX_USED` 与 `SERVER_QUERY_NO_INDEX_USED` 参数。这将导致以下参数返回与实际不一致: +TiDB 不在协议中设置 `SERVER_QUERY_NO_GOOD_INDEX_USED` 和 `SERVER_QUERY_NO_INDEX_USED` 参数。这将导致以下参数返回的结果与实际情况不一致: - `com.mysql.cj.protocol.ServerSession.noIndexUsed()` - `com.mysql.cj.protocol.ServerSession.noGoodIndexUsed()` **规避方法** -不使用 `noIndexUsed()` 与 `noGoodIndexUsed()` 函数。 +在 TiDB 中不要使用 `noIndexUsed()` 和 `noGoodIndexUsed()` 函数。 ### 不支持 `enablePacketDebug` 参数 **描述** -TiDB 不支持 [enablePacketDebug](https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-debugging-profiling.html) 参数,这是一个 MySQL Connector/J 用于调试的参数,将保留数据包的 Buffer。这将导致连接的**意外关闭**,**请勿**打开。 +TiDB 不支持 [enablePacketDebug](https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-debugging-profiling.html) 参数。这是一个用于调试的 MySQL Connector/J 参数,它会保留数据包的缓冲区。这可能导致连接意外关闭。**不要**启用它。 **规避方法** -不设置 `enablePacketDebug` 参数。 +在 TiDB 中不要设置 `enablePacketDebug` 参数。 ### 不支持 UpdatableResultSet **描述** -TiDB 暂不支持 `UpdatableResultSet`,即请勿指定 `ResultSet.CONCUR_UPDATABLE` 参数,也不要在 `ResultSet` 内部进行数据更新。 +TiDB 不支持 `UpdatableResultSet`。**不要**指定 `ResultSet.CONCUR_UPDATABLE` 参数,**不要**在 `ResultSet` 内更新数据。 **规避方法** -使用 `UPDATE` 语句进行数据更新,可使用事务保证数据一致性。 +要通过事务确保数据一致性,可以使用 `UPDATE` 语句更新数据。 -## MySQL JDBC Bug +## MySQL JDBC 错误 -### `useLocalTransactionState` 和 `rewriteBatchedStatements` 同时开启将导致事务无法提交或回滚 +### `useLocalTransactionState` 和 `rewriteBatchedStatements` 同时为 true 会导致事务提交或回滚失败 **描述** -在使用 8.0.32 或以下版本的 MySQL Connector/J 时,同时开启 `useLocalTransactionState` 和 `rewriteBatchedStatements` 参数将导致事务无法提交。你可以使用[代码](https://github.com/Icemap/tidb-java-gitpod/tree/reproduction-local-transaction-state-txn-error)复现。 +使用 MySQL Connector/J 8.0.32 或更早版本时,如果 `useLocalTransactionState` 和 `rewriteBatchedStatements` 参数同时设置为 `true`,事务可能无法提交。你可以使用[此代码](https://github.com/Icemap/tidb-java-gitpod/tree/reproduction-local-transaction-state-txn-error)复现。 **规避方法** > **注意:** > -> `maxPerformance` 配置中包含多个参数,其中包括 `useLocalSessionState` 参数。要查看当前 MySQL Connector/J 中 `maxPerformance` 包含的具体参数,可参考 MySQL Connector/J [8.0 版本](https://github.com/mysql/mysql-connector-j/blob/release/8.0/src/main/resources/com/mysql/cj/configurations/maxPerformance.properties) 或 [5.1 版本](https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/configs/maxPerformance.properties) 的配置文件。在使用 `maxPerformance` 时,请关闭 `useLocalTransactionState`,即 `useConfigs=maxPerformance&useLocalTransactionState=false`。 +> `useConfigs=maxPerformance` 包含一组配置。有关 MySQL Connector/J 8.0 和 MySQL Connector/J 5.1 中的详细配置,请参阅 [mysql-connector-j 8.0](https://github.com/mysql/mysql-connector-j/blob/release/8.0/src/main/resources/com/mysql/cj/configurations/maxPerformance.properties) 和 [mysql-connector-j 5.1](https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/configs/maxPerformance.properties)。使用 `maxPerformance` 时需要禁用 `useLocalTransactionState`。即使用 `useConfigs=maxPerformance&useLocalTransactionState=false`。 -MySQL Connector/J 已在 8.0.33 版本修复此问题。请使用 8.0.33 或更高版本。基于稳定性和性能考量,并结合到 8.0.x 版本已经停止更新,强烈建议升级 MySQL Connector/J 到[最新的 GA 版本](https://dev.mysql.com/downloads/connector/j/)。 +此错误已在 MySQL Connector/J 8.0.33 中修复。考虑到 8.0.x 系列的更新已停止,强烈建议将 MySQL Connector/J 升级到[最新的正式发布(GA)版本](https://dev.mysql.com/downloads/connector/j/)以提高稳定性和性能。 -### Connector 无法兼容 5.7.5 版本以下的服务端 +### 连接器与 5.7.5 之前的服务器版本不兼容 **描述** -8.0.31 及以下版本 MySQL Connector/J,在与 5.7.5 版本以下的 MySQL 服务端,或使用 5.7.5 版本以下 MySQL 服务端协议的数据库(如 TiDB 6.3.0 版本以下)同时使用时,将在某些情况下导致数据库连接的挂起。关于更多细节信息,可查看此 [Bug Report](https://bugs.mysql.com/bug.php?id=106252)。 +使用 MySQL Connector/J 8.0.31 或更早版本时,如果 MySQL 服务器 < 5.7.5 或使用 MySQL 服务器 < 5.7.5 协议的数据库(如 TiDB v6.3.0 之前的版本),数据库连接可能在某些条件下挂起。更多详情,请参阅[错误报告](https://bugs.mysql.com/bug.php?id=106252)。 **规避方法** -MySQL Connector/J 已在 8.0.32 版本修复此问题。请使用 8.0.32 或更高版本。基于稳定性和性能考量,并结合到 8.0.x 版本已经停止更新,强烈建议升级 MySQL Connector/J 到[最新的 GA 版本](https://dev.mysql.com/downloads/connector/j/)。 +此错误已在 MySQL Connector/J 8.0.32 中修复。考虑到 8.0.x 系列的更新已停止,强烈建议将 MySQL Connector/J 升级到[最新的正式发布(GA)版本](https://dev.mysql.com/downloads/connector/j/)以提高稳定性和性能。 + +TiDB 也通过以下方式修复了这个问题: -TiDB 也对其进行了两个维度的修复: +- 客户端:此错误已在 **pingcap/mysql-connector-j** 中修复,你可以使用 [pingcap/mysql-connector-j](https://github.com/pingcap/mysql-connector-j) 替代官方的 MySQL Connector/J。 +- 服务器端:此兼容性问题已在 TiDB v6.3.0 中修复,你可以将服务器升级到 v6.3.0 或更高版本。 -- 客户端方面:**pingcap/mysql-connector-j** 中修复了该 Bug,你可以使用 [pingcap/mysql-connector-j](https://github.com/pingcap/mysql-connector-j) 替换官方的 MySQL Connector/J。 -- 服务端方面:TiDB v6.3.0 修复了此兼容性问题,你可以升级服务端至 v6.3.0 或以上版本。 +## Sequelize 兼容性 -## 与 Sequelize 的兼容性 +本节描述的兼容性信息基于 [Sequelize v6.32.1](https://www.npmjs.com/package/sequelize/v/6.32.1)。 -本小节描述的兼容性信息基于 [Sequelize v6.32.1](https://www.npmjs.com/package/sequelize/v/6.32.1) 测试。 +根据测试结果,TiDB 支持大多数 Sequelize 功能([使用 `MySQL` 作为方言](https://sequelize.org/docs/v6/other-topics/dialect-specific-things/#mysql))。 -根据测试结果,TiDB 支持绝大部分 Sequelize 功能([使用 `MySQL` 作为方言](https://sequelize.org/docs/v6/other-topics/dialect-specific-things/#mysql)),不支持的功能有: +不支持的功能包括: -- [不支持 `GEOMETRY`](https://github.com/pingcap/tidb/issues/6347) 相关。 +- 不支持 [`GEOMETRY`](https://github.com/pingcap/tidb/issues/6347)。 - 不支持修改整数主键。 -- 不支持 `PROCEDURE` 相关。 +- 不支持 `PROCEDURE`。 - 不支持 `READ-UNCOMMITTED` 和 `SERIALIZABLE` [隔离级别](/system-variables.md#transaction_isolation)。 - 默认不允许修改列的 `AUTO_INCREMENT` 属性。 - 不支持 `FULLTEXT`、`HASH` 和 `SPATIAL` 索引。 @@ -178,34 +200,48 @@ TiDB 也对其进行了两个维度的修复: **描述** -不支持修改整数类型的主键,这是由于当主键为整数类型时,TiDB 使用其作为数据组织的索引。你可以在此 [Issue](https://github.com/pingcap/tidb/issues/18090) 或[聚簇索引](/clustered-indexes.md)一节中获取更多信息。 +不支持修改整数主键。如果主键是整数类型,TiDB 使用主键作为数据组织的索引。参考 [Issue #18090](https://github.com/pingcap/tidb/issues/18090) 和[聚簇索引](/clustered-indexes.md)了解更多详情。 ### 不支持 `READ-UNCOMMITTED` 和 `SERIALIZABLE` 隔离级别 **描述** -TiDB 不支持 `READ-UNCOMMITTED` 和 `SERIALIZABLE` 隔离级别。设置事务隔离级别为 `READ-UNCOMMITTED` 或 `SERIALIZABLE` 时将报错。 +TiDB 不支持 `READ-UNCOMMITTED` 和 `SERIALIZABLE` 隔离级别。如果将隔离级别设置为 `READ-UNCOMMITTED` 或 `SERIALIZABLE`,TiDB 会抛出错误。 **规避方法** -仅使用 TiDB 支持的 `REPEATABLE-READ` 或 `READ-COMMITTED` 隔离级别。 +仅使用 TiDB 支持的隔离级别:`REPEATABLE-READ` 或 `READ-COMMITTED`。 -如果你的目的是兼容其他设置 `SERIALIZABLE` 隔离级别的应用,但不依赖于 `SERIALIZABLE`,你可以设置 [`tidb_skip_isolation_level_check`](/system-variables.md#tidb_skip_isolation_level_check) 为 `1`,此后如果对 `tx_isolation`([`transaction_isolation`](/system-variables.md#transaction_isolation) 别名)赋值一个 TiDB 不支持的隔离级别(`READ-UNCOMMITTED` 和 `SERIALIZABLE`),不会报错。 +如果你希望 TiDB 与设置了 `SERIALIZABLE` 隔离级别但不依赖 `SERIALIZABLE` 的其他应用程序兼容,可以将 [`tidb_skip_isolation_level_check`](/system-variables.md#tidb_skip_isolation_level_check) 设置为 `1`。在这种情况下,TiDB 会忽略不支持的隔离级别错误。 ### 默认不允许修改列的 `AUTO_INCREMENT` 属性 **描述** -默认不允许通过 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 来增加或移除某个列的 `AUTO_INCREMENT` 属性。 +默认情况下,不允许通过 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 命令添加或删除列的 `AUTO_INCREMENT` 属性。 **规避方法** -参考 [`AUTO_INCREMENT` 的使用限制](/auto-increment.md#使用限制)。 +参考 [`AUTO_INCREMENT` 的限制](/auto-increment.md#restrictions)。 -设置 `@@tidb_allow_remove_auto_inc` 为 `true`,即可允许移除 `AUTO_INCREMENT` 属性。 +要允许删除 `AUTO_INCREMENT` 属性,请将 `@@tidb_allow_remove_auto_inc` 设置为 `true`。 ### 不支持 `FULLTEXT`、`HASH` 和 `SPATIAL` 索引 **描述** -TiDB 不支持 `FULLTEXT`、`HASH` 和 `SPATIAL` 索引。 +不支持 `FULLTEXT`、`HASH` 和 `SPATIAL` 索引。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-tidb-crud-sql.md b/develop/dev-guide-tidb-crud-sql.md index 2108dd10e104..806f1c89d33f 100644 --- a/develop/dev-guide-tidb-crud-sql.md +++ b/develop/dev-guide-tidb-crud-sql.md @@ -1,60 +1,65 @@ --- -title: 使用 TiDB 的增删改查 SQL -summary: 简单介绍 TiDB 的增删改查 SQL。 +title: TiDB 中的 CRUD SQL +summary: TiDB CRUD SQL 的简要介绍。 --- -# 使用 TiDB 的增删改查 SQL +# TiDB 中的 CRUD SQL -本章将简单介绍 TiDB 的增删改查 SQL 的使用方法。 +本文简要介绍如何使用 TiDB 的 CRUD SQL。 -## 在开始之前 +## 开始之前 -请确保你已经连接到 TiDB 集群,若未连接,请参考[使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群)来创建一个 TiDB Cloud Serverless 集群。 +请确保你已连接到 TiDB 集群。如果没有,请参考[构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#step-1-create-a-tidb-cloud-serverless-cluster)来创建一个 TiDB Cloud Serverless 集群。 -## 基本 SQL 操作 +## 使用 TiDB 探索 SQL > **注意:** > -> 此处文档引用并简化自 TiDB 文档中的 [SQL 基本操作](/basic-sql-operations.md),你可直接前往此文档获取更全面、深入的 SQL 基本操作信息。 +> 本文参考并简化了[使用 TiDB 探索 SQL](/basic-sql-operations.md)。更多详细信息,请参见[使用 TiDB 探索 SQL](/basic-sql-operations.md)。 -成功部署 TiDB 集群之后,便可以在 TiDB 中执行 SQL 语句了。因为 TiDB 兼容 MySQL,你可以使用 MySQL 客户端连接 TiDB,并且[大多数情况下](/mysql-compatibility.md)可以直接执行 MySQL 语句。 +TiDB 与 MySQL 兼容,在大多数情况下你可以直接使用 MySQL 语句。有关不支持的功能,请参见[与 MySQL 的兼容性](/mysql-compatibility.md#unsupported-features)。 -SQL 是一门声明性语言,它是数据库用户与数据库交互的方式。它更像是一种自然语言,好像在用英语与数据库进行对话。本文档介绍基本的 SQL 操作。完整的 SQL 语句列表,参见 [SQL 语句概览](/sql-statements/sql-statement-overview.md)。 +要试验 SQL 并测试 TiDB 与 MySQL 查询的兼容性,你可以尝试使用 [TiDB Playground](https://play.tidbcloud.com/?utm_source=docs&utm_medium=basic-sql-operations)。你也可以先部署一个 TiDB 集群,然后在其中运行 SQL 语句。 + +本页将指导你了解基本的 TiDB SQL 语句,如 DDL、DML 和 CRUD 操作。有关 TiDB 语句的完整列表,请参见 [SQL 语句概览](/sql-statements/sql-statement-overview.md)。 ## 分类 -SQL 语言通常按照功能划分成以下的 4 个部分: +SQL 根据其功能分为以下 4 种类型: + +- **DDL(数据定义语言)**:用于定义数据库对象,包括数据库、表、视图和索引。 + +- **DML(数据操作语言)**:用于操作应用程序相关的记录。 -- **DDL (Data Definition Language)**:数据定义语言,用来定义数据库对象,包括库、表、视图和索引等。 -- **DML (Data Manipulation Language)**:数据操作语言,用来操作和业务相关的记录。 -- **DQL (Data Query Language)**:数据查询语言,用来查询经过条件筛选的记录。 -- **DCL (Data Control Language)**:数据控制语言,用来定义访问权限和安全级别。 +- **DQL(数据查询语言)**:用于在条件过滤后查询记录。 -此文档中,主要介绍 DML 和 DQL,即数据操作语言和数据查询语言。其余部分可查看 [SQL 基本操作](/basic-sql-operations.md)或 [SQL 语句概览](/sql-statements/sql-statement-overview.md)获得更多信息。 +- **DCL(数据控制语言)**:用于定义访问权限和安全级别。 -## DML 数据操作语言 +以下主要介绍 DML 和 DQL。有关 DDL 和 DCL 的更多信息,请参见[使用 TiDB 探索 SQL](/basic-sql-operations.md)或 [SQL 语句概览](/sql-statements/sql-statement-overview.md)。 -数据操作语言可完成数据的增删改。 +## 数据操作语言 -使用 `INSERT` 语句向表内插入表记录。例如: +常见的 DML 功能是添加、修改和删除表记录。对应的命令是 `INSERT`、`UPDATE` 和 `DELETE`。 + +要向表中插入数据,使用 `INSERT` 语句: ```sql INSERT INTO person VALUES(1,'tom','20170912'); ``` -使用 `INSERT` 语句向表内插入包含部分字段数据的表记录。例如: +要向表中插入包含部分字段数据的记录,使用 `INSERT` 语句: ```sql INSERT INTO person(id,name) VALUES('2','bob'); ``` -使用 `UPDATE` 语句向表内修改表记录的部分字段数据。例如: +要更新表中某条记录的部分字段,使用 `UPDATE` 语句: ```sql UPDATE person SET birthday='20180808' WHERE id=2; ``` -使用 `DELETE` 语句向表内删除部分表记录。例如: +要删除表中的数据,使用 `DELETE` 语句: ```sql DELETE FROM person WHERE id=2; @@ -62,25 +67,25 @@ DELETE FROM person WHERE id=2; > **注意:** > -> `UPDATE` 和 `DELETE` 操作如果不带 `WHERE` 过滤条件是对全表进行操作。 +> 没有 `WHERE` 子句作为过滤条件的 `UPDATE` 和 `DELETE` 语句会对整个表进行操作。 -## DQL 数据查询语言 +## 数据查询语言 -数据查询语言是从一个表或多个表中检索出想要的数据行,通常是业务开发的核心内容。 +DQL 用于从一个或多个表中检索所需的数据行。 -使用 `SELECT` 语句检索单表内数据。例如: +要查看表中的数据,使用 `SELECT` 语句: ```sql SELECT * FROM person; ``` -在 `SELECT` 后面加上要查询的列名。例如: +要查询特定列,在 `SELECT` 关键字后添加列名: ```sql SELECT name FROM person; ``` -运行结果为: +结果如下: ``` +------+ @@ -91,8 +96,22 @@ SELECT name FROM person; 1 rows in set (0.00 sec) ``` -使用 `WHERE` 子句,对所有记录进行是否符合条件的筛选后再返回。例如: +使用 `WHERE` 子句过滤所有匹配条件的记录,然后返回结果: ```sql SELECT * FROM person WHERE id < 5; ``` + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-timeouts-in-tidb.md b/develop/dev-guide-timeouts-in-tidb.md index 1babbf916c2b..d0f924b89523 100644 --- a/develop/dev-guide-timeouts-in-tidb.md +++ b/develop/dev-guide-timeouts-in-tidb.md @@ -1,62 +1,104 @@ --- -title: TiDB 中的各种超时 -summary: 简单介绍 TiDB 中的各种超时,为排查错误提供依据。 +title: TiDB 中的超时机制 +summary: 了解 TiDB 中的超时机制,以及解决错误的方案。 --- -# TiDB 中的各种超时 +# TiDB 中的超时机制 -本章将介绍 TiDB 中的各种超时,为排查错误提供依据。 +本文档描述了 TiDB 中的各种超时机制,帮助您排查错误。 ## GC 超时 -TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。TiDB 通过定期 GC 的机制来清理不再需要的旧数据。 +TiDB 的事务实现使用 MVCC(多版本并发控制)机制。当新写入的数据覆盖旧数据时,旧数据不会被替换,而是与新写入的数据一起保留。版本通过时间戳来区分。TiDB 使用定期垃圾回收(GC)机制来清理不再需要的旧数据。 -- TiDB v4.0 之前的版本: +- 对于早于 v4.0 的 TiDB 版本: - 默认情况下,TiDB 可以确保每个 MVCC 版本(一致性快照)保存 10 分钟。读取时间超过 10 分钟的事务,会收到报错 `GC life time is shorter than transaction duration`。 + 默认情况下,每个 MVCC 版本(一致性快照)保留 10 分钟。读取时间超过 10 分钟的事务将收到错误 `GC life time is shorter than transaction duration`。 -- TiDB v4.0 及之后的版本: +- 对于 TiDB v4.0 及更高版本: - 正在运行的事务,如果持续时间不超过 24 小时,在运行期间 GC 会被阻塞,不会出现 `GC life time is shorter than transaction duration` 报错。 + 对于执行时间不超过 24 小时的运行中事务,垃圾回收(GC)在事务执行期间会被阻塞。不会出现错误 `GC life time is shorter than transaction duration`。 -如果你确定在临时特殊场景中需要更长的读取时间,可以通过以下方式调大 MVCC 版本保留时间: +如果在某些情况下临时需要更长的读取时间,您可以增加 MVCC 版本的保留时间: -- TiDB v5.0 之前的版本 :调整 `mysql.tidb` 表中的 `tikv_gc_life_time`。 -- TiDB v5.0 及之后的版本:调整系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入)。 +- 对于早于 v5.0 的 TiDB 版本:在 TiDB 的 `mysql.tidb` 表中调整 `tikv_gc_life_time`。 +- 对于 TiDB v5.0 及更高版本:调整系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-new-in-v50)。 -需要注意的是,此变量的配置是立刻影响全局的,调大它会增加当前所有快照的生命时长,调小它也会立即缩短所有快照的生命时长。过多的 MVCC 版本会影响 TiDB 的集群性能,因此在使用后,需要及时把此变量调整回之前的设置。 +请注意,系统变量配置会立即全局生效。增加其值会增加所有现有快照的生命周期,减少其值会立即缩短所有快照的生命周期。过多的 MVCC 版本会影响 TiDB 集群的性能。因此,您需要及时将此变量改回之前的设置。 -> **Tip:** + + +> **提示:** +> +> 具体来说,当 Dumpling 从 TiDB 导出数据(小于 1 TB)时,如果 TiDB 版本是 v4.0.0 或更高版本,并且 Dumpling 可以访问 TiDB 集群的 PD 地址和 [`INFORMATION_SCHEMA.CLUSTER_INFO`](/information-schema/information-schema-cluster-info.md) 表,Dumpling 会自动调整 GC 安全点以阻止 GC,而不影响原始集群。 > -> 特别地,在 Dumpling 备份时,如果导出的数据量少于 1 TB 且导出的 TiDB 版本为 v4.0.0 或更新版本,并且 Dumpling 可以访问 TiDB 集群的 PD 地址以及 [`INFORMATION_SCHEMA.CLUSTER_INFO`](/information-schema/information-schema-cluster-info.md) 表,Dumpling 会自动调整 GC 的 safe point 从而阻塞 GC 且不会对原集群造成影响。以下场景除外: +> 但是,在以下任一情况下,Dumpling 无法自动调整 GC 时间: > > - 数据量非常大(超过 1 TB)。 -> - Dumpling 无法直接连接到 PD,例如 TiDB 集群运行在 TiDB Cloud 上,或者 TiDB 集群运行在 Kubernetes 上且与 Dumpling 分离。 +> - Dumpling 无法直接连接到 PD,例如,TiDB 集群在 TiDB Cloud 上或在与 Dumpling 分离的 Kubernetes 上。 +> +> 在这种情况下,您必须提前手动延长 GC 时间,以避免在导出过程中因 GC 而导致导出失败。 > -> 在这些场景中,你必须使用 `tikv_gc_life_time` 提前手动调长 GC 时间,以避免因为导出过程中发生 GC 导致导出失败。详见 TiDB 工具 Dumpling 的[手动设置 TiDB GC 时间](/dumpling-overview.md#手动设置-tidb-gc-时间)。 +> 更多详细信息,请参见[手动设置 TiDB GC 时间](/dumpling-overview.md#manually-set-the-tidb-gc-time)。 -更多关于 GC 的信息,请参考 [GC 机制简介](/garbage-collection-overview.md)文档。 + + + + +> **提示:** +> +> 具体来说,当 Dumpling 从 TiDB 导出数据(小于 1 TB)时,如果 TiDB 版本大于或等于 v4.0.0,并且 Dumpling 可以访问 TiDB 集群的 PD 地址,Dumpling 会自动延长 GC 时间,而不影响原始集群。 +> +> 但是,在以下任一情况下,Dumpling 无法自动调整 GC 时间: +> +> - 数据量非常大(超过 1 TB)。 +> - Dumpling 无法直接连接到 PD,例如,TiDB 集群在 TiDB Cloud 上或在与 Dumpling 分离的 Kubernetes 上。 +> +> 在这种情况下,您必须提前手动延长 GC 时间,以避免在导出过程中因 GC 而导致导出失败。 +> +> 更多详细信息,请参见[手动设置 TiDB GC 时间](https://docs.pingcap.com/tidb/stable/dumpling-overview#manually-set-the-tidb-gc-time)。 + + + +有关 GC 的更多信息,请参见 [GC 概述](/garbage-collection-overview.md)。 ## 事务超时 -在事务已启动但未提交或回滚的情况下,你可能需要更细粒度的控制和更短的超时,以避免持有锁的时间过长。此时,你可以使用 TiDB 在 v7.6.0 引入的 [`tidb_idle_transaction_timeout`](/system-variables.md#tidb_idle_transaction_timeout-从-v760-版本开始引入) 控制用户会话中事务的空闲超时。 +在事务已启动但既未提交也未回滚的场景中,您可能需要更细粒度的控制和更短的超时时间,以防止长时间持有锁。在这种情况下,您可以使用 [`tidb_idle_transaction_timeout`](/system-variables.md#tidb_idle_transaction_timeout-new-in-v760)(在 TiDB v7.6.0 中引入)来控制用户会话中事务的空闲超时。 -垃圾回收 (GC) 不会影响到正在执行的事务。但悲观事务的运行仍有上限,有基于事务超时的限制(TiDB 配置文件 [performance] 类别下的 `max-txn-ttl` 修改,默认为 60 分钟)和基于事务使用内存的限制。 +GC 不会影响正在进行的事务。但是,可以运行的悲观事务数量仍有上限,事务超时和事务使用的内存都有限制。您可以通过 TiDB 配置文件中 `[performance]` 类别下的 `max-txn-ttl` 修改事务超时时间,默认为 `60` 分钟。 -形如 `INSERT INTO t10 SELECT * FROM t1` 的 SQL 语句,不会受到 GC 的影响,但超过了 `max-txn-ttl` 的时间后,会由于超时而回滚。 +像 `INSERT INTO t10 SELECT * FROM t1` 这样的 SQL 语句不受 GC 影响,但超过 `max-txn-ttl` 后会因超时而回滚。 -## SQL 执行时间超时 +## SQL 执行超时 -TiDB 还提供了一个系统变量来限制单条 SQL 语句的执行时间,仅对“只读”语句生效:`max_execution_time`,它的默认值为 0,表示无限制。`max_execution_time` 的单位为 ms,但实际精度在 100ms 级别,而非更准确的毫秒级别。 +TiDB 还提供了一个系统变量(`max_execution_time`,默认为 `0`,表示无限制)来限制单个 SQL 语句的执行时间。目前,该系统变量仅对只读 SQL 语句生效。`max_execution_time` 的单位是 `ms`,但实际精度是 `100ms` 级别而不是毫秒级别。 ## JDBC 查询超时 -MySQL jdbc 的查询超时设置 `setQueryTimeout()` 对 TiDB 不起作用。这是因为现实客户端感知超时时,向数据库发送一个 KILL 命令。但是由于 tidb-server 是负载均衡的,为防止在错误的 tidb-server 上终止连接,tidb-server 不会执行这个 KILL。这时就要用 `MAX_EXECUTION_TIME` 实现查询超时的效果。 +MySQL JDBC 的 `setQueryTimeout()` 查询超时设置对 TiDB **_不_**起作用,因为当客户端检测到超时时,会向数据库发送 `KILL` 命令。但是,tidb-server 是负载均衡的,它不会执行这个 `KILL` 命令,以避免在错误的 tidb-server 上终止连接。您需要使用 `MAX_EXECUTION_TIME` 来检查查询超时效果。 + +TiDB 提供以下与 MySQL 兼容的超时控制参数。 + +- **wait_timeout**,控制与 Java 应用程序的非交互式空闲超时。从 TiDB v5.4 开始,`wait_timeout` 的默认值是 `28800` 秒,即 8 小时。对于早于 v5.4 的 TiDB 版本,默认值是 `0`,表示超时时间无限制。 +- **interactive_timeout**,控制与 Java 应用程序的交互式空闲超时。默认值为 `8` 小时。 +- **max_execution_time**,控制连接中 SQL 执行的超时时间,仅对只读 SQL 语句有效。默认值为 `0`,允许连接无限忙碌,即 SQL 语句可以无限长时间执行。 + +但是,在实际生产环境中,空闲连接和无限执行的 SQL 语句对数据库和应用程序都有负面影响。您可以通过在应用程序的连接字符串中配置这两个会话级变量来避免空闲连接和无限执行的 SQL 语句。例如,设置以下内容: + +- `sessionVariables=wait_timeout=3600`(1 小时) +- `sessionVariables=max_execution_time=300000`(5 分钟) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + -TiDB 提供了三个与 MySQL 兼容的超时控制参数: + -- **wait_timeout**,控制与 Java 应用连接的非交互式空闲超时时间。在 TiDB v5.4 及以上版本中,默认值为 `28800` 秒,即空闲超时为 8 小时。在 v5.4 之前,默认值为 `0`,即没有时间限制。 -- **interactive_timeout**,控制与 Java 应用连接的交互式空闲超时时间,默认值为 8 小时。 -- **max_execution_time**,控制连接中 SQL 执行的超时时间,仅对“只读”语句生效,默认值是 0,即允许连接无限忙碌(一个 SQL 语句执行无限的长的时间)。 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -但在实际生产环境中,空闲连接和一直无限执行的 SQL 对数据库和应用都有不好的影响。你可以通过在应用的连接字符串中配置这两个 session 级的变量来避免空闲连接和执行时间过长的 SQL 语句。例如,设置 `sessionVariables=wait_timeout=3600(1 小时)`和 `sessionVariables=max_execution_time=300000(5 分钟)`。 + diff --git a/develop/dev-guide-transaction-overview.md b/develop/dev-guide-transaction-overview.md index 41e6be8091f5..e6ca235f3306 100644 --- a/develop/dev-guide-transaction-overview.md +++ b/develop/dev-guide-transaction-overview.md @@ -1,28 +1,24 @@ --- -title: 事务概览 -summary: 简单介绍 TiDB 中的事务。 +title: 事务概述 +summary: TiDB 事务的简要介绍。 --- -# 事务概览 +# 事务概述 -TiDB 支持完整的分布式事务,提供[乐观事务](/optimistic-transaction.md)与[悲观事务](/pessimistic-transaction.md)(TiDB 3.0 中引入)两种事务模型。本文主要介绍涉及到事务的语句、乐观事务和悲观事务、事务的隔离级别,以及乐观事务应用端重试和错误处理。 +TiDB 支持完整的分布式事务,提供[乐观事务](/optimistic-transaction.md)和[悲观事务](/pessimistic-transaction.md)(在 TiDB 3.0 中引入)。本文主要介绍事务语句、乐观事务和悲观事务、事务隔离级别,以及乐观事务中的应用端重试和错误处理。 -## 拓展学习视频 +## 常用语句 -[TiDB 特有功能与事务控制 - TiDB v6](https://learn.pingcap.com/learner/course/750002/?utm_source=docs-cn-dev-guide):了解可用于应用程序的 TiDB 独特功能,如 `AUTO_RANDOM` 及 `AUTO_INCREMENT` 特别注意事项、全局临时表、如何使用 TiFlash 启用 HTAP 以及放置策略等。 +本章介绍如何在 TiDB 中使用事务。以下示例演示了一个简单事务的过程: -## 通用语句 +Bob 想要转账 $20 给 Alice。这个事务包括两个操作: -本章介绍在 TiDB 中如何使用事务。 将使用下面的示例来演示一个简单事务的控制流程: +- Bob 的账户减少 $20。 +- Alice 的账户增加 $20。 -Bob 要给 Alice 转账 20 元钱,当中至少包括两个操作: +事务可以确保上述两个操作都执行成功或都失败。 -- Bob 账户减少 20 元。 -- Alice 账户增加 20 元。 - -事务可以确保以上两个操作要么都执行成功,要么都执行失败,不会出现钱平白消失或出现的情况。 - -使用 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库中的 `users` 表,在表中插入一些示例数据: +使用 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库中的 `users` 表插入一些示例数据: ```sql INSERT INTO users (id, nickname, balance) @@ -31,7 +27,7 @@ INSERT INTO users (id, nickname, balance) VALUES (1, 'Alice', 100); ``` -现在,运行以下事务并解释每个语句的含义: +运行以下事务并解释每个语句的含义: ```sql BEGIN; @@ -40,7 +36,7 @@ BEGIN; COMMIT; ``` -上述事务成功后,表应如下所示: +上述事务执行成功后,表应该如下所示: ``` +----+--------------+---------+ @@ -52,9 +48,9 @@ COMMIT; ``` -### 开启事务 +### 开始事务 -要显式地开启一个新事务,既可以使用 `BEGIN` 语句,也可以使用 `START TRANSACTION` 语句,两者效果相同。语法: +要显式开始一个新事务,你可以使用 `BEGIN` 或 `START TRANSACTION`。 ```sql BEGIN; @@ -64,39 +60,39 @@ BEGIN; START TRANSACTION; ``` -TiDB 的默认事务模式是悲观事务,你也可以明确指定开启[乐观事务](/develop/dev-guide-optimistic-and-pessimistic-transaction.md): +TiDB 的默认事务模式是悲观事务。你也可以显式指定[乐观事务模式](/develop/dev-guide-optimistic-and-pessimistic-transaction.md): ```sql BEGIN OPTIMISTIC; ``` -开启[悲观事务](/develop/dev-guide-optimistic-and-pessimistic-transaction.md): +启用[悲观事务模式](/develop/dev-guide-optimistic-and-pessimistic-transaction.md): ```sql BEGIN PESSIMISTIC; ``` -如果执行以上语句时,当前 Session 正处于一个事务的中间过程,那么系统会先自动提交当前事务,再开启一个新的事务。 +如果在执行上述语句时当前会话正处于事务中,TiDB 会先提交当前事务,然后开始一个新事务。 ### 提交事务 -`COMMIT` 语句用于提交 TiDB 在当前事务中进行的所有修改。语法: +你可以使用 `COMMIT` 语句提交 TiDB 在当前事务中所做的所有修改。 ```sql COMMIT; ``` -启用乐观事务前,请确保应用程序可正确处理 `COMMIT` 语句可能返回的错误。如果不确定应用程序将会如何处理,建议改为使用悲观事务。 +在启用乐观事务之前,请确保你的应用程序可以正确处理 `COMMIT` 语句可能返回的错误。如果你不确定你的应用程序将如何处理,建议使用悲观事务模式。 ### 回滚事务 -`ROLLBACK` 语句用于回滚并撤销当前事务的所有修改。语法: +你可以使用 `ROLLBACK` 语句回滚当前事务的修改。 ```sql ROLLBACK; ``` -回到之前转账示例,使用 `ROLLBACK` 回滚整个事务之后,Alice 和 Bob 的余额都未发生改变,当前事务的所有修改一起被取消。 +在前面的转账示例中,如果你回滚整个事务,Alice 和 Bob 的余额将保持不变,当前事务的所有修改都被取消。 ```sql TRUNCATE TABLE `users`; @@ -125,22 +121,29 @@ SELECT * FROM `users`; +----+--------------+---------+ ``` -如果客户端连接中止或关闭,也会自动回滚该事务。 +如果客户端连接停止或关闭,事务也会自动回滚。 ## 事务隔离级别 -事务隔离级别是数据库事务处理的基础,**ACID** 中的 **“I”**,即 Isolation,指的就是事务的隔离性。 +事务隔离级别是数据库事务处理的基础。**ACID** 中的 "I"(隔离性)指的是事务的隔离性。 + +SQL-92 标准定义了四个隔离级别: -SQL-92 标准定义了 4 种隔离级别:读未提交 (`READ UNCOMMITTED`)、读已提交 (`READ COMMITTED`)、可重复读 (`REPEATABLE READ`)、串行化 (`SERIALIZABLE`)。详见下表: +- 读未提交(`READ UNCOMMITTED`) +- 读已提交(`READ COMMITTED`) +- 可重复读(`REPEATABLE READ`) +- 可串行化(`SERIALIZABLE`) -| Isolation Level | Dirty Write | Dirty Read | Fuzzy Read | Phantom | +详细信息请参见下表: + +| 隔离级别 | 脏写 | 脏读 | 不可重复读 | 幻读 | | ---------------- | ------------ | ------------ | ------------ | ------------ | -| READ UNCOMMITTED | Not Possible | Possible | Possible | Possible | -| READ COMMITTED | Not Possible | Not possible | Possible | Possible | -| REPEATABLE READ | Not Possible | Not possible | Not possible | Possible | -| SERIALIZABLE | Not Possible | Not possible | Not possible | Not possible | +| READ UNCOMMITTED | 不可能 | 可能 | 可能 | 可能 | +| READ COMMITTED | 不可能 | 不可能 | 可能 | 可能 | +| REPEATABLE READ | 不可能 | 不可能 | 不可能 | 可能 | +| SERIALIZABLE | 不可能 | 不可能 | 不可能 | 不可能 | -TiDB 语法上支持设置 `READ COMMITTED` 和 `REPEATABLE READ` 两种隔离级别: +TiDB 支持以下隔离级别:`READ COMMITTED` 和 `REPEATABLE READ`: ```sql mysql> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; @@ -155,4 +158,18 @@ mysql> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; ERROR 8048 (HY000): The isolation level 'SERIALIZABLE' is not supported. Set tidb_skip_isolation_level_check=1 to skip this error ``` -TiDB 实现了快照隔离 (Snapshot Isolation, SI) 级别的一致性。为与 MySQL 保持一致,又称其为“可重复读”。该隔离级别不同于 [ANSI 可重复读隔离级别](/transaction-isolation-levels.md#与-ansi-可重复读隔离级别的区别) 和 [MySQL 可重复读隔离级别](/transaction-isolation-levels.md#与-mysql-可重复读隔离级别的区别)。更多细节请阅读 [TiDB 事务隔离级别](/transaction-isolation-levels.md)。 +TiDB 实现了快照隔离(SI)级别的一致性,为了与 MySQL 保持一致,也称为"可重复读"。这个隔离级别与 [ANSI 可重复读隔离级别](/transaction-isolation-levels.md#difference-between-tidb-and-ansi-repeatable-read)和 [MySQL 可重复读隔离级别](/transaction-isolation-levels.md#difference-between-tidb-and-mysql-repeatable-read)不同。更多详细信息,请参见 [TiDB 事务隔离级别](/transaction-isolation-levels.md)。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-transaction-restraints.md b/develop/dev-guide-transaction-restraints.md index 745255236686..290cd7baa8a4 100644 --- a/develop/dev-guide-transaction-restraints.md +++ b/develop/dev-guide-transaction-restraints.md @@ -1,42 +1,42 @@ --- -title: 事务限制 -summary: 介绍 TiDB 中的事务限制。 +title: 事务约束 +summary: 了解 TiDB 中的事务约束。 --- -# 事务限制 +# 事务约束 -本章将简单介绍 TiDB 中的事务限制。 +本文档简要介绍 TiDB 中的事务约束。 ## 隔离级别 -TiDB 支持的隔离级别是 RC(Read Committed)与 SI(Snapshot Isolation),其中 SI 与 RR(Repeatable Read)隔离级别基本等价。 +TiDB 支持的隔离级别是 **RC(读已提交)**和 **SI(快照隔离)**,其中 **SI** 基本等同于 **RR(可重复读)**隔离级别。 ![隔离级别](/media/develop/transaction_isolation_level.png) -## SI 可以克服幻读 +## 快照隔离可以避免幻读 -TiDB 的 SI 隔离级别可以克服幻读异常 (Phantom Reads),但 ANSI/ISO SQL 标准中的 RR 不能。 +TiDB 的 `SI` 隔离级别可以避免**幻读**,但 ANSI/ISO SQL 标准中的 `RR` 不能。 -所谓幻读是指:事务 A 首先根据条件查询得到 n 条记录,然后事务 B 改变了这 n 条记录之外的 m 条记录或者增添了 m 条符合事务 A 查询条件的记录,导致事务 A 再次发起请求时发现有 n+m 条符合条件记录,就产生了幻读。 +以下两个示例说明什么是**幻读**。 -例如:系统管理员 A 将数据库中所有学生的成绩从具体分数改为 ABCDE 等级,但是系统管理员 B 就在这个时候插入了一条具体分数的记录,当系统管理员 A 改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。 +- 示例 1:**事务 A** 首先根据查询获得 `n` 行数据,然后 **事务 B** 修改了这 `n` 行以外的 `m` 行数据或添加了 `m` 行符合 **事务 A** 查询条件的数据。当 **事务 A** 再次运行查询时,发现有 `n+m` 行数据符合条件。这就像是出现了幻影,所以称为**幻读**。 -## SI 不能克服写偏斜 +- 示例 2:**管理员 A** 将数据库中所有学生的成绩从具体分数改为 ABCDE 等级,但 **管理员 B** 在此时插入了一条具体分数的记录。当 **管理员 A** 完成修改后,发现还有一条记录(**管理员 B** 插入的那条)没有被修改。这就是一个**幻读**。 -TiDB 的 SI 隔离级别不能克服写偏斜异常(Write Skew),需要使用 Select for update 语法来克服写偏斜异常。 +## SI 不能避免写偏斜 -写偏斜异常是指两个并发的事务读取了不同但相关的记录,接着这两个事务各自更新了自己读到的数据,并最终都提交了事务,如果这些相关的记录之间存在着不能被多个事务并发修改的约束,那么最终结果将是违反约束的。 +TiDB 的 SI 隔离级别不能避免**写偏斜**异常。您可以使用 `SELECT FOR UPDATE` 语法来避免**写偏斜**异常。 -举个例子,假设你正在为医院写一个医生轮班管理程序。医院通常会同时要求几位医生待命,但底线是至少有一位医生在待命。医生可以放弃他们的班次(例如,如果他们自己生病了),只要至少有一个同事在这一班中继续工作。 +当两个并发事务读取不同但相关的记录,然后每个事务都更新它读取的数据并最终提交事务时,就会发生**写偏斜**异常。如果这些相关记录之间存在不能被多个事务同时修改的约束,那么最终结果将违反该约束。 -现在出现这样一种情况,Alice 和 Bob 是两位值班医生。两人都感到不适,所以他们都决定请假。不幸的是,他们恰好在同一时间点击按钮下班。下面用程序来模拟一下这个过程。 +例如,假设您正在编写一个医院的医生值班管理程序。医院通常要求同时有多名医生值班,但最低要求是至少有一名医生值班。医生可以请假(例如,如果他们感到不适),只要在该班次中至少有一名医生值班即可。 + +现在有一种情况,医生 `Alice` 和 `Bob` 都在值班。两人都感到不适,所以决定请病假。他们恰好同时点击了按钮。让我们用以下程序模拟这个过程:
-Java 程序示例如下: - ```java package com.pingcap.txn.write.skew; @@ -57,7 +57,7 @@ public class EffectWriteSkew { ds.setJdbcUrl("jdbc:mysql://localhost:4000/test?useServerPrepStmts=true&cachePrepStmts=true"); ds.setUsername("root"); - // prepare data + // 准备数据 Connection connection = ds.getConnection(); createDoctorTable(connection); createDoctor(connection, 1, "Alice", true, 123); @@ -110,7 +110,7 @@ public class EffectWriteSkew { String comment = txnID == 2 ? " " : "" + "/* txn #{txn_id} */ "; connection.createStatement().executeUpdate(comment + "BEGIN"); - // Txn 1 should be waiting until txn 2 is done. + // 事务 1 应该等待事务 2 完成 if (txnID == 1) { txn1Pass.acquire(); } @@ -126,7 +126,7 @@ public class EffectWriteSkew { } else { int count = res.getInt("count"); if (count >= 2) { - // If current on-call doctor has 2 or more, this doctor can leave + // 如果当前值班医生有 2 个或更多,这个医生可以请假 PreparedStatement insert = connection.prepareStatement( comment + "UPDATE `doctors` SET `on_call` = ? WHERE `id` = ? AND `shift_id` = ?"); insert.setBoolean(1, false); @@ -140,12 +140,12 @@ public class EffectWriteSkew { } } - // Txn 2 is done. Let txn 1 run again. + // 事务 2 完成,让事务 1 继续运行 if (txnID == 2) { txn1Pass.release(); } } catch (Exception e) { - // If got any error, you should roll back, data is priceless + // 如果出现任何错误,您应该回滚,数据是无价的 connection.rollback(); e.printStackTrace(); } @@ -160,7 +160,7 @@ public class EffectWriteSkew {
-在 Golang 中,首先,封装一个用于适配 TiDB 事务的工具包 [util](https://github.com/pingcap-inc/tidb-example-golang/tree/main/util),随后编写以下代码: +要适配 TiDB 事务,请根据以下代码编写一个 [util](https://github.com/pingcap-inc/tidb-example-golang/tree/main/util): ```go package main @@ -232,7 +232,7 @@ func askForLeave(db *sql.DB, waitingChan chan bool, goroutineID, doctorID int) e } fmt.Println(txnComment + "start txn") - // Txn 1 should be waiting until txn 2 is done. + // 事务 1 应该等待直到事务 2 完成 if goroutineID == 1 { <-waitingChan } @@ -276,7 +276,7 @@ func askForLeave(db *sql.DB, waitingChan chan bool, goroutineID, doctorID int) e fmt.Printf("[runTxn] got an error, rollback: %+v\n", err) } - // Txn 2 is done. Let txn 1 run again. + // 事务 2 完成。让事务 1 继续运行。 if goroutineID == 2 { waitingChan <- true } @@ -341,7 +341,7 @@ SQL 日志: /* txn 1 */ COMMIT ``` -执行结果: +运行结果: ```sql mysql> SELECT * FROM doctors; @@ -354,381 +354,8 @@ mysql> SELECT * FROM doctors; +----+-------+---------+----------+ ``` -在两个事务中,应用首先检查是否有两个或以上的医生正在值班;如果是的话,它就假定一名医生可以安全地休班。由于数据库使用快照隔离,两次检查都返回 2,所以两个事务都进入下一个阶段。Alice 更新自己的记录休班了,而 Bob 也做了一样的事情。两个事务都成功提交了,现在没有医生值班了。违反了至少有一名医生在值班的要求。下图(引用自《Designing Data-Intensive Application》)说明了实际发生的情况: - -![Write Skew](/media/develop/write-skew.png) - -现在更改示例程序,使用 `SELECT FOR UPDATE` 来克服写偏斜问题: - - - -
- -Java 中使用 `SELECT FOR UPDATE` 来克服写偏斜问题的示例如下: - -```java -package com.pingcap.txn.write.skew; - -import com.zaxxer.hikari.HikariDataSource; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Semaphore; - -public class EffectWriteSkew { - public static void main(String[] args) throws SQLException, InterruptedException { - HikariDataSource ds = new HikariDataSource(); - ds.setJdbcUrl("jdbc:mysql://localhost:4000/test?useServerPrepStmts=true&cachePrepStmts=true"); - ds.setUsername("root"); - - // prepare data - Connection connection = ds.getConnection(); - createDoctorTable(connection); - createDoctor(connection, 1, "Alice", true, 123); - createDoctor(connection, 2, "Bob", true, 123); - createDoctor(connection, 3, "Carol", false, 123); - - Semaphore txn1Pass = new Semaphore(0); - CountDownLatch countDownLatch = new CountDownLatch(2); - ExecutorService threadPool = Executors.newFixedThreadPool(2); - - threadPool.execute(() -> { - askForLeave(ds, txn1Pass, 1, 1); - countDownLatch.countDown(); - }); - - threadPool.execute(() -> { - askForLeave(ds, txn1Pass, 2, 2); - countDownLatch.countDown(); - }); - - countDownLatch.await(); - } - - public static void createDoctorTable(Connection connection) throws SQLException { - connection.createStatement().executeUpdate("CREATE TABLE `doctors` (" + - " `id` int(11) NOT NULL," + - " `name` varchar(255) DEFAULT NULL," + - " `on_call` tinyint(1) DEFAULT NULL," + - " `shift_id` int(11) DEFAULT NULL," + - " PRIMARY KEY (`id`)," + - " KEY `idx_shift_id` (`shift_id`)" + - " ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"); - } - - public static void createDoctor(Connection connection, Integer id, String name, Boolean onCall, Integer shiftID) throws SQLException { - PreparedStatement insert = connection.prepareStatement( - "INSERT INTO `doctors` (`id`, `name`, `on_call`, `shift_id`) VALUES (?, ?, ?, ?)"); - insert.setInt(1, id); - insert.setString(2, name); - insert.setBoolean(3, onCall); - insert.setInt(4, shiftID); - insert.executeUpdate(); - } - - public static void askForLeave(HikariDataSource ds, Semaphore txn1Pass, Integer txnID, Integer doctorID) { - try(Connection connection = ds.getConnection()) { - try { - connection.setAutoCommit(false); - - String comment = txnID == 2 ? " " : "" + "/* txn #{txn_id} */ "; - connection.createStatement().executeUpdate(comment + "BEGIN"); - - // Txn 1 should be waiting until txn 2 is done. - if (txnID == 1) { - txn1Pass.acquire(); - } - - PreparedStatement currentOnCallQuery = connection.prepareStatement(comment + - "SELECT COUNT(*) AS `count` FROM `doctors` WHERE `on_call` = ? AND `shift_id` = ? FOR UPDATE"); - currentOnCallQuery.setBoolean(1, true); - currentOnCallQuery.setInt(2, 123); - ResultSet res = currentOnCallQuery.executeQuery(); - - if (!res.next()) { - throw new RuntimeException("error query"); - } else { - int count = res.getInt("count"); - if (count >= 2) { - // If current on-call doctor has 2 or more, this doctor can leave - PreparedStatement insert = connection.prepareStatement( comment + - "UPDATE `doctors` SET `on_call` = ? WHERE `id` = ? AND `shift_id` = ?"); - insert.setBoolean(1, false); - insert.setInt(2, doctorID); - insert.setInt(3, 123); - insert.executeUpdate(); - - connection.commit(); - } else { - throw new RuntimeException("At least one doctor is on call"); - } - } - - // Txn 2 is done. Let txn 1 run again. - if (txnID == 2) { - txn1Pass.release(); - } - } catch (Exception e) { - // If got any error, you should roll back, data is priceless - connection.rollback(); - e.printStackTrace(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} -``` - -
- -
- -Golang 中使用 `SELECT FOR UPDATE` 来克服写偏斜问题的示例如下: - -```go -package main - -import ( - "database/sql" - "fmt" - "sync" - - "github.com/pingcap-inc/tidb-example-golang/util" - - _ "github.com/go-sql-driver/mysql" -) - -func main() { - openDB("mysql", "root:@tcp(127.0.0.1:4000)/test", func(db *sql.DB) { - writeSkew(db) - }) -} - -func openDB(driverName, dataSourceName string, runnable func(db *sql.DB)) { - db, err := sql.Open(driverName, dataSourceName) - if err != nil { - panic(err) - } - defer db.Close() - - runnable(db) -} - -func writeSkew(db *sql.DB) { - err := prepareData(db) - if err != nil { - panic(err) - } - - waitingChan, waitGroup := make(chan bool), sync.WaitGroup{} - - waitGroup.Add(1) - go func() { - defer waitGroup.Done() - err = askForLeave(db, waitingChan, 1, 1) - if err != nil { - panic(err) - } - }() - - waitGroup.Add(1) - go func() { - defer waitGroup.Done() - err = askForLeave(db, waitingChan, 2, 2) - if err != nil { - panic(err) - } - }() - - waitGroup.Wait() -} - -func askForLeave(db *sql.DB, waitingChan chan bool, goroutineID, doctorID int) error { - txnComment := fmt.Sprintf("/* txn %d */ ", goroutineID) - if goroutineID != 1 { - txnComment = "\t" + txnComment - } - - txn, err := util.TiDBSqlBegin(db, true) - if err != nil { - return err - } - fmt.Println(txnComment + "start txn") - - // Txn 1 should be waiting until txn 2 is done. - if goroutineID == 1 { - <-waitingChan - } - - txnFunc := func() error { - queryCurrentOnCall := "SELECT COUNT(*) AS `count` FROM `doctors` WHERE `on_call` = ? AND `shift_id` = ?" - rows, err := txn.Query(queryCurrentOnCall, true, 123) - if err != nil { - return err - } - defer rows.Close() - fmt.Println(txnComment + queryCurrentOnCall + " successful") - - count := 0 - if rows.Next() { - err = rows.Scan(&count) - if err != nil { - return err - } - } - rows.Close() - - if count < 2 { - return fmt.Errorf("at least one doctor is on call") - } - - shift := "UPDATE `doctors` SET `on_call` = ? WHERE `id` = ? AND `shift_id` = ?" - _, err = txn.Exec(shift, false, doctorID, 123) - if err == nil { - fmt.Println(txnComment + shift + " successful") - } - return err - } - - err = txnFunc() - if err == nil { - txn.Commit() - fmt.Println("[runTxn] commit success") - } else { - txn.Rollback() - fmt.Printf("[runTxn] got an error, rollback: %+v\n", err) - } - - // Txn 2 is done. Let txn 1 run again. - if goroutineID == 2 { - waitingChan <- true - } - - return nil -} - -func prepareData(db *sql.DB) error { - err := createDoctorTable(db) - if err != nil { - return err - } - - err = createDoctor(db, 1, "Alice", true, 123) - if err != nil { - return err - } - err = createDoctor(db, 2, "Bob", true, 123) - if err != nil { - return err - } - err = createDoctor(db, 3, "Carol", false, 123) - if err != nil { - return err - } - return nil -} - -func createDoctorTable(db *sql.DB) error { - _, err := db.Exec("CREATE TABLE IF NOT EXISTS `doctors` (" + - " `id` int(11) NOT NULL," + - " `name` varchar(255) DEFAULT NULL," + - " `on_call` tinyint(1) DEFAULT NULL," + - " `shift_id` int(11) DEFAULT NULL," + - " PRIMARY KEY (`id`)," + - " KEY `idx_shift_id` (`shift_id`)" + - " ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin") - return err -} - -func createDoctor(db *sql.DB, id int, name string, onCall bool, shiftID int) error { - _, err := db.Exec("INSERT INTO `doctors` (`id`, `name`, `on_call`, `shift_id`) VALUES (?, ?, ?, ?)", - id, name, onCall, shiftID) - return err -} -``` - -
- -
- -SQL 日志: - -```sql -/* txn 1 */ BEGIN - /* txn 2 */ BEGIN - /* txn 2 */ SELECT COUNT(*) AS `count` FROM `doctors` WHERE on_call = 1 AND `shift_id` = 123 FOR UPDATE - /* txn 2 */ UPDATE `doctors` SET on_call = 0 WHERE `id` = 2 AND `shift_id` = 123 - /* txn 2 */ COMMIT -/* txn 1 */ SELECT COUNT(*) AS `count` FROM `doctors` WHERE `on_call` = 1 FOR UPDATE -At least one doctor is on call -/* txn 1 */ ROLLBACK -``` - -执行结果: - -```sql -mysql> SELECT * FROM doctors; -+----+-------+---------+----------+ -| id | name | on_call | shift_id | -+----+-------+---------+----------+ -| 1 | Alice | 1 | 123 | -| 2 | Bob | 0 | 123 | -| 3 | Carol | 0 | 123 | -+----+-------+---------+----------+ -``` - -## 对 savepoint 和嵌套事务的支持 - -> **注意:** -> -> TiDB 从 v6.2.0 版本开始支持 [savepoint](/sql-statements/sql-statement-savepoint.md) 特性。因此低于 v6.2.0 版本的 TiDB 不支持 `PROPAGATION_NESTED` 传播行为。建议升级至 v6.2.0 及之后版本。如无法升级 TiDB 版本,且基于 Java Spring 框架的应用使用了 `PROPAGATION_NESTED` 传播行为,需要在应用端做出调整,将嵌套事务的逻辑移除。 - -Spring 支持的 PROPAGATION_NESTED 传播行为会启动一个嵌套的事务,它是当前事务之上独立启动的一个子事务。嵌套事务开始时会记录一个 savepoint,如果嵌套事务执行失败,事务将会回滚到 savepoint 的状态。嵌套事务是外层事务的一部分,它将会在外层事务提交时一起被提交。下面案例展示了 savepoint 机制: - -```sql -mysql> BEGIN; -mysql> INSERT INTO T2 VALUES(100); -mysql> SAVEPOINT svp1; -mysql> INSERT INTO T2 VALUES(200); -mysql> ROLLBACK TO SAVEPOINT svp1; -mysql> RELEASE SAVEPOINT svp1; -mysql> COMMIT; -mysql> SELECT * FROM T2; -+------+ -| ID | -+------+ -| 100 | -+------+ -``` - -## 大事务限制 - -基本原则是要限制事务的大小。TiDB 对单个事务的大小有限制,这层限制是在 KV 层面。反映在 SQL 层面的话,简单来说一行数据会映射为一个 KV entry,每多一个索引,也会增加一个 KV entry。所以这个限制反映在 SQL 层面是: - -- 最大单行记录容量为 120 MiB。 - - - TiDB v4.0.10 及更高的 v4.0.x 版本、v5.0.0 及更高的版本可通过 tidb-server 配置项 [`performance.txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v4010-和-v500-版本开始引入) 调整,低于 TiDB v4.0.10 的版本支持的单行容量为 6 MiB。 - - 从 v7.6.0 开始,你可以使用 [`tidb_txn_entry_size_limit`](/system-variables.md#tidb_txn_entry_size_limit-从-v760-版本开始引入) 系统变量动态修改该配置项的值。 - -- 支持的最大单个事务容量为 1 TiB。 - - - TiDB v4.0 及更高版本可通过 tidb-server 配置项 [`performance.txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit) 调整,低于 TiDB v4.0 的版本支持的最大单个事务容量为 100 MiB。 - - 在 v6.5.0 及之后的版本中,不再推荐使用配置项 [`performance.txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit)。更多详情请参考 [`performance.txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit)。 - -另外注意,无论是大小限制还是行数限制,还要考虑事务执行过程中,TiDB 做编码以及事务额外 Key 的开销。在使用的时候,为了使性能达到最优,建议每 100 ~ 500 行写入一个事务。 - -## 自动提交的 SELECT FOR UPDATE 语句不会等锁 - -自动提交下的 SELECT FOR UPDATE 目前不会加锁。效果如下图所示: - -![TiDB中的情况](/media/develop/autocommit_selectforupdate_nowaitlock.png) +在两个事务中,应用程序首先检查是否有两个或更多医生值班;如果是,则假定一个医生可以安全地请假。由于数据库使用快照隔离,两次检查都返回 `2`,所以两个事务都进入下一阶段。`Alice` 更新她的记录为不值班,`Bob` 也是如此。两个事务都成功提交。现在没有医生值班,这违反了至少应该有一名医生值班的要求。下图(引自**《设计数据密集型应用》**)说明了实际发生的情况。 -这是已知的与 MySQL 不兼容的地方。 +![写偏斜](/media/develop/write-skew.png) -可以通过使用显式的 `BEGIN;COMMIT;` 解决该问题。 +现在让我们修改示例程序,使用 `SELECT FOR UPDATE` 来避免写偏斜问题: diff --git a/develop/dev-guide-transaction-troubleshoot.md b/develop/dev-guide-transaction-troubleshoot.md index f66a5e58c1e6..3c5220bf25a3 100644 --- a/develop/dev-guide-transaction-troubleshoot.md +++ b/develop/dev-guide-transaction-troubleshoot.md @@ -1,57 +1,59 @@ --- -title: 事务错误处理 -summary: 介绍 TiDB 中的事务错误处理办法。 +title: 处理事务错误 +summary: 了解如何处理事务错误,例如死锁和应用程序重试错误。 --- -# 事务错误处理 +# 处理事务错误 -本章介绍使用事务时可能会遇到的错误和处理办法。 +本文档介绍如何处理事务错误,例如死锁和应用程序重试错误。 ## 死锁 -如果应用程序遇到下面错误时,说明遇到了死锁问题: +应用程序中出现以下错误表示存在死锁问题: ```sql ERROR 1213: Deadlock found when trying to get lock; try restarting transaction ``` -当两个及以上的事务,双方都在等待对方释放已经持有的锁或因为加锁顺序不一致,造成循环等待锁资源,就会出现“死锁”。这里以 [bookshop](/develop/dev-guide-bookshop-schema-design.md) 数据库中的 `books` 表为示例演示死锁: +当两个或多个事务互相等待对方释放已持有的锁,或者不一致的锁顺序导致循环等待锁资源时,就会发生死锁。 -先给 `books` 表中写入 2 条数据: +以下是使用 [`bookshop`](/develop/dev-guide-bookshop-schema-design.md) 数据库中的 `books` 表的死锁示例: + +首先,向 `books` 表中插入 2 行数据: ```sql INSERT INTO books (id, title, stock, published_at) VALUES (1, 'book-1', 10, now()), (2, 'book-2', 10, now()); ``` -在 TiDB 悲观事务模式下,用 2 个客户端分别执行以下语句,就会遇到死锁: +在 TiDB 悲观事务模式下,如果两个客户端分别执行以下语句,将会发生死锁: -| 客户端-A | 客户端-B | -| ---------------------------------------------------------- | ---------------------------------------------------------------- | -| BEGIN; | | -| | BEGIN; | -| UPDATE books SET stock=stock-1 WHERE id=1; | | -| | UPDATE books SET stock=stock-1 WHERE id=2; | -| UPDATE books SET stock=stock-1 WHERE id=2; -- 执行会被阻塞 | | -| | UPDATE books SET stock=stock-1 WHERE id=1; -- 遇到 Deadlock 错误 | +| 客户端 A | 客户端 B | +| --------------------------------------------------------------| --------------------------------------------------------------------| +| BEGIN; | | +| | BEGIN; | +| UPDATE books SET stock=stock-1 WHERE id=1; | | +| | UPDATE books SET stock=stock-1 WHERE id=2; | +| UPDATE books SET stock=stock-1 WHERE id=2; -- 执行将被阻塞 | | +| | UPDATE books SET stock=stock-1 WHERE id=1; -- 发生死锁错误 | -在客户端-B 遇到死锁错误后,TiDB 会自动 `ROLLBACK` 客户端-B 中的事务,然后客户端-A 中购买 `id=2` 的操作就会执行成功,再执行 `COMMIT` 即可完成购买的事务流程。 +当客户端 B 遇到死锁错误时,TiDB 会自动回滚客户端 B 的事务。客户端 A 中更新 `id=2` 的操作将成功执行。然后你可以运行 `COMMIT` 完成事务。 ### 解决方案 1:避免死锁 -为了应用程序有更好的性能,可以通过调整业务逻辑或者 Schema 设计,尽量从应用层面避免死锁。例如上面示例中,如果客户端-B 也和客户端-A 用同样的购买顺序,即都先买 `id=1` 的书,再买 `id=2` 的书,就可以避免死锁了: +为了获得更好的性能,你可以通过调整业务逻辑或架构设计在应用程序层面避免死锁。在上面的示例中,如果客户端 B 也使用与客户端 A 相同的更新顺序,即先更新 `id=1` 的图书,然后更新 `id=2` 的图书,就可以避免死锁: -| 客户端-A | 客户端-B | -| ------------------------------------------ | ------------------------------------------------------------------------------------- | -| BEGIN; | | -| | BEGIN; | -| UPDATE books SET stock=stock-1 WHERE id=1; | | -| | UPDATE books SET stock=stock-1 WHERE id=1; -- 执行会被阻塞,当事务 A 完成后再继续执行 | -| UPDATE books SET stock=stock-1 WHERE id=2; | | -| | UPDATE books SET stock=stock-1 WHERE id=2; | -| COMMIT; | | -| | COMMIT; | +| 客户端 A | 客户端 B | +| ---------------------------------------------------------- | ----------------------------------------------------------------| +| BEGIN; | | +| | BEGIN; | +| UPDATE books SET stock=stock-1 WHERE id=1; | | +| | UPDATE books SET stock=stock-1 WHERE id=1; -- 将被阻塞 | +| UPDATE books SET stock=stock-1 WHERE id=2; | | +| COMMIT; | | +| | UPDATE books SET stock=stock-1 WHERE id=2; | +| | COMMIT; | -或者直接用 1 条 SQL 购买 2 本书,也能避免死锁,而且执行效率更高: +或者,你可以使用 1 条 SQL 语句更新 2 本书,这样也可以避免死锁并且执行效率更高: ```sql UPDATE books SET stock=stock-1 WHERE id IN (1, 2); @@ -59,35 +61,47 @@ UPDATE books SET stock=stock-1 WHERE id IN (1, 2); ### 解决方案 2:减小事务粒度 -如果每次购书都是一个单独的事务,也能避免死锁。但需要权衡的是,事务粒度太小不符合性能上的最佳实践。 +如果你在每个事务中只更新 1 本书,也可以避免死锁。但是,过小的事务粒度可能会影响性能。 ### 解决方案 3:使用乐观事务 -乐观事务模型下,并不会有死锁问题,但应用端需要加上乐观事务在失败后的重试逻辑,具体重试逻辑见[应用端重试和错误处理](#应用端重试和错误处理)。 +在乐观事务模型中不会出现死锁。但是在你的应用程序中,你需要添加乐观事务重试逻辑以防失败。详情请参阅[应用程序重试和错误处理](#应用程序重试和错误处理)。 ### 解决方案 4:重试 -正如错误信息中提示的那样,在应用代码中加入重试逻辑即可。具体重试逻辑见[应用端重试和错误处理](#应用端重试和错误处理)。 +按照错误消息的建议在应用程序中添加重试逻辑。详情请参阅[应用程序重试和错误处理](#应用程序重试和错误处理)。 + +## 应用程序重试和错误处理 + +尽管 TiDB 尽可能与 MySQL 兼容,但其分布式系统的特性导致某些差异。其中之一就是事务模型。 + +开发人员用来连接数据库的适配器和 ORM 是为 MySQL 和 Oracle 等传统数据库量身定制的。在这些数据库中,事务在默认隔离级别下很少提交失败,因此不需要重试机制。当事务提交失败时,这些客户端会因错误而中止,因为这在这些数据库中被视为异常情况。 + +与 MySQL 等传统数据库不同,在 TiDB 中,如果你使用乐观事务模型并希望避免提交失败,你需要在应用程序中添加处理相关异常的机制。 + +以下 Python 伪代码展示了如何实现应用程序级重试。它不需要你的驱动程序或 ORM 实现高级重试逻辑。它可以在任何编程语言或环境中使用。 + +你的重试逻辑必须遵循以下规则: -## 应用端重试和错误处理 +- 如果失败重试次数达到 `max_retries` 限制,则抛出错误。 +- 使用 `try ... catch ...` 捕获 SQL 执行异常。遇到以下错误时重试。遇到其他错误时回滚。 + - `Error 8002: can not retry select for update statement`:SELECT FOR UPDATE 写冲突错误 + - `Error 8022: Error: KV error safe to retry`:事务提交失败错误。 + - `Error 8028: Information schema is changed during the execution of the statement`:表架构已被 DDL 操作更改,导致事务提交出错。 + - `Error 9007: Write conflict`:写冲突错误,通常在使用乐观事务模式时由多个事务修改同一行数据导致。 +- 在 try 块的末尾 `COMMIT` 事务。 -尽管 TiDB 尽可能地与 MySQL 兼容,但其分布式系统的性质导致了某些差异,其中之一就是事务模型。 + -开发者用来与数据库通信的 Adapter 和 ORM 都是为 MySQL 和 Oracle 等传统数据库量身定制的,在这些数据库中,提交很少在默认隔离级别失败,因此不需要重试机制。对于这些客户端,当提交失败时,它们会因错误而中止,因为这在这些数据库中被呈现为罕见的异常。 +有关错误代码的更多信息,请参阅[错误码与故障诊断](/error-codes.md)。 -与 MySQL 等传统数据库不同的是,在 TiDB 中,如果采用乐观事务模型,想要避免提交失败,需要在自己的应用程序的业务逻辑中添加机制来处理相关的异常。 + -下面的类似 Python 的伪代码展示了如何实现应用程序级的重试。 它不要求您的驱动程序或 ORM 来实现高级重试处理逻辑,因此可以在任何编程语言或环境中使用。 + -特别是,您的重试逻辑必须: +有关错误代码的更多信息,请参阅[错误码与故障诊断](https://docs.pingcap.com/tidb/stable/error-codes)。 -- 如果失败重试的次数达到 `max_retries` 限制,则抛出错误 -- 使用 `try ... catch ...` 语句捕获 SQL 执行异常,当遇到下面这些错误时进行失败重试,遇到其它错误则进行回滚。详细信息请参考:[错误码与故障诊断](https://docs.pingcap.com/tidb/stable/error-codes)。 - - `Error 8002: can not retry select for update statement`:SELECT FOR UPDATE 写入冲突报错。 - - `Error 8022: Error: KV error safe to retry`:事务提交失败报错。 - - `Error 8028: Information schema is changed during the execution of the statement`:表的 Schema 结构因为完成了 DDL 变更,导致事务提交时报错。 - - `Error 9007: Write conflict`:写冲突报错,一般是采用乐观事务模式时,多个事务都对同一行数据进行修改时遇到的写冲突报错。 -- 在 try 块结束时使用 COMMIT 提交事务: + ```python while True: @@ -113,10 +127,44 @@ while True: > **注意:** > -> 如果你经常遇到 `Error 9007: Write conflict` 错误,你可能需要进一步评估你的 Schema 设计和数据存取模型,找到冲突的根源并从设计上避免冲突。 -> 关于如何定位和解决事务冲突,请参考[TiDB 锁冲突问题处理](/troubleshoot-lock-conflicts.md)。 +> 如果你经常遇到 `Error 9007: Write conflict`,你可能需要检查你的架构设计和工作负载的数据访问模式,找出冲突的根本原因,并尝试通过更好的设计来避免冲突。 + + + +有关如何排查和解决事务冲突的信息,请参阅[排查锁冲突](/troubleshoot-lock-conflicts.md)。 + + + + + +有关如何排查和解决事务冲突的信息,请参阅[排查锁冲突](https://docs.pingcap.com/tidb/stable/troubleshoot-lock-conflicts)。 + + + +## 另请参阅 + + + +- [排查乐观事务中的写入冲突](/troubleshoot-write-conflicts.md) + + + + + +- [排查乐观事务中的写入冲突](https://docs.pingcap.com/tidb/stable/troubleshoot-write-conflicts) + + + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 推荐阅读 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -- [TiDB 锁冲突问题处理](/troubleshoot-lock-conflicts.md) -- [乐观事务模型下写写冲突问题排查](/troubleshoot-write-conflicts.md) + diff --git a/develop/dev-guide-troubleshoot-overview.md b/develop/dev-guide-troubleshoot-overview.md index 4a76485a3994..338abf4e28ef 100644 --- a/develop/dev-guide-troubleshoot-overview.md +++ b/develop/dev-guide-troubleshoot-overview.md @@ -1,27 +1,58 @@ --- title: SQL 或事务问题 -summary: 学习诊断在应用开发过程中可能产生的 SQL 或事务问题的方法。 +summary: 了解如何排查应用程序开发过程中可能出现的 SQL 或事务问题。 --- # SQL 或事务问题 -本章介绍在开发应用过程中可能遇到的常见问题的诊断处理方法。 +本文介绍应用程序开发过程中可能出现的问题和相关文档。 -## SQL 操作常见问题 +## 排查 SQL 查询问题 -如果你想提高 SQL 的性能,可以阅读 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)来避免一些常见的性能问题。然后如果依然存在性能问题,推荐阅读: +如果您想提高 SQL 查询性能,请按照 [SQL 性能调优](/develop/dev-guide-optimize-sql-overview.md) 中的说明解决全表扫描和缺少索引等性能问题。 + + + +如果您仍然遇到性能问题,请参见以下文档: - [分析慢查询](/analyze-slow-queries.md) -- [使用 Top SQL 定位系统资源消耗过多的查询](/dashboard/top-sql.md) +- [使用 Top SQL 识别高开销查询](/dashboard/top-sql.md) + +如果您对 SQL 操作有疑问,请参见 [SQL 常见问题](/faq/sql-faq.md)。 + + + + + +如果您对 SQL 操作有疑问,请参见 [SQL 常见问题](https://docs.pingcap.com/tidb/stable/sql-faq)。 + + + +## 排查事务问题 + +请参见[处理事务错误](/develop/dev-guide-transaction-troubleshoot.md)。 + +## 另请参阅 + +- [不支持的功能](/mysql-compatibility.md#unsupported-features) + + + +- [集群管理常见问题](/faq/manage-cluster-faq.md) +- [TiDB 常见问题](/faq/tidb-faq.md) + + + +## 需要帮助? + + -如果你遇到了一些关于 SQL 操作的问题,可以阅读 [SQL 操作常见问题](/faq/sql-faq.md)。 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 -## 事务错误处理 + -见[事务错误处理](/develop/dev-guide-transaction-troubleshoot.md)。 + -## 推荐阅读 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -- [不支持的功能特性](/mysql-compatibility.md#不支持的功能特性) -- [集群管理 FAQ](/faq/manage-cluster-faq.md) -- [TiDB 产品 FAQ](/faq/tidb-faq.md) + diff --git a/develop/dev-guide-unique-serial-number-generation.md b/develop/dev-guide-unique-serial-number-generation.md index dbdd83616af6..9addafafee2c 100644 --- a/develop/dev-guide-unique-serial-number-generation.md +++ b/develop/dev-guide-unique-serial-number-generation.md @@ -1,47 +1,65 @@ --- -title: 唯一序列号生成方案 -summary: 唯一序列号生成方案,为自行生成唯一 ID 的开发者提供帮助。 +title: 唯一序列号生成 +summary: 为需要生成自己的唯一 ID 的开发者提供唯一序列号生成方案。 --- -# 唯一序列号生成方案 +# 唯一序列号生成 -本章将介绍唯一序列号生成方案,为自行生成唯一 ID 的开发者提供帮助。 +本文介绍唯一序列号生成方案,帮助需要生成自己的唯一 ID 的开发者。 ## 自增列 -自增(auto_increment)是大多数兼容 MySQL 协议的 RDBMS 上列的一种属性,通过配置该属性来使数据库为该列的值自动赋值,用户不需要为该列赋值,该列的值随着表内记录增加会自动增长,并确保唯一性。在大多数场景中,自增列并未拥有业务属性,仅仅代表了这一行数据,即被作为无业务含义的代理主键使用。自增列的局限性在于:自增列只能采用整型字段,所赋的值也只能为整型。假设业务所需要的序列号由字母、数字及其他字符拼接而成,用户将难以通过自增列来获取序列号中所需的数字自增值。 +`AUTO_INCREMENT` 是许多兼容 MySQL 协议的关系型数据库管理系统的列属性。通过 `AUTO_INCREMENT` 属性,数据库可以在无需用户干预的情况下自动为该列分配值。随着表中记录数量的增加,该列的值会自动递增并保证唯一。在大多数场景中,`AUTO_INCREMENT` 列被用作没有实际意义的代理主键。 -## 序列(Sequence) +`AUTO_INCREMENT` 列的限制是该列必须是整数类型,并且分配给它们的值必须是整数。如果应用程序需要的序列号由字母、数字和其他字符组成,用户很难通过 `AUTO_INCREMENT` 列获取序列号中需要的自增数字。 -序列是一种数据库对象,应用程序通过调用某个序列可以产生递增的序列值,应用程序可以灵活的使用这个序列值为一张表或多张表赋值,也可以使用序列值进行更复杂的加工,来实现文本和数字的组合,来赋予代理键以一定的跟踪和分类的意义。从 TiDB v4.0 版本开始提供序列功能,详情请参考 [CREATE SEQUENCE](/sql-statements/sql-statement-create-sequence.md#create-sequence)。 +## 序列 -## 类 Snowflake 方案 +**序列(Sequence)**是一个数据库对象,应用程序可以调用它来生成递增的序列值。应用程序可以灵活地使用序列值为一个或多个表分配值。应用程序还可以使用序列值进行更复杂的处理,生成文本和数字的组合。这种方法为代理键赋予了一些跟踪和分类的意义。 -Snowflake 是 Twitter 提出的分布式 ID 生成方案。目前有多种实现,较流行的是百度的 uid-generator 和美团的 leaf。下面以 uid-generator 为例展开说明。 +序列功能从 TiDB v4.0 开始提供。详细信息,请参考[序列文档](/sql-statements/sql-statement-create-sequence.md#create-sequence)。 -uid-generator 生成的 64 位 ID 结构如下: +## 雪花算法类解决方案 + +雪花(Snowflake)是 Twitter 提出的分布式 ID 生成解决方案。它有多种实现,比较流行的有百度的 **uid-generator** 和美团的 **leaf**。本节以 `uid-generator` 为例。 + +`uid-generator` 生成的 64 位 ID 结构如下: ``` -| sign | delta seconds | worker node id | sequencs | -|------|---------------|----------------|----------| -| 1bit | 28bits | 22bits | 13bits | +| 符号位 | 相对时间差 | 工作节点 ID | 序列号 | +|------|-----------|------------|--------| +| 1bit | 28bits | 22bits | 13bits | ``` -- sign:长度固定为 1 位。固定为 0,表示生成的 ID 始终为正数。 -- delta seconds:默认 28 位。当前时间,表示为相对于某个预设时间基点 (默认"2016-05-20") 的增量值,单位为秒。28 位最多可支持约 8.7 年。 -- worker node id:默认 22 位。表示机器 id,通常在应用程序进程启动时从一个集中式的 ID 生成器取得。常见的集中式 ID 生成器是数据库自增列或者 Zookeeper。默认分配策略为用后即弃,进程重启时会重新获取一个新的 worker node id,22 位最多可支持约 420 万次启动。 -- sequence:默认 13 位。表示每秒的并发序列,13 位可支持每秒 8192 个并发。 +- 符号位:固定长度为 1 位。固定为 `0`,表示生成的 ID 始终是正数。 +- 相对时间差:默认 28 位。当前时间,表示为相对于预设时间基准(默认为 `2016-05-20`)的秒级增量值。28 位最多可以支持约 8.7 年。 +- 工作节点 ID:默认 22 位。表示机器 ID,通常在应用程序进程启动时从中央 ID 生成器获取。常见的中央 ID 生成器包括自增列和 ZooKeeper。默认分配策略是用完即弃,进程重启时重新获取新的工作节点 ID。22 位最多可以支持约 420 万次启动。 +- 序列号:默认 13 位。每秒内的并发序列。13 位每秒可以支持 8192 个并发序列。 ## 号段分配方案 -号段分配方案可以理解为从数据库批量获取自增 ID。本方案需要一张序列号生成表,每行记录表示一个序列对象。表定义示例如下: +号段分配方案可以理解为从数据库批量获取自增 ID。这个方案需要一个序列号生成表,每一行代表一个序列对象。表定义示例如下: -| 字段名 | 字段类型 | 字段说明 | +| 字段名 | 字段类型 | 字段说明 | | -------- | ------------ | ---------------------------- | -| SEQ_NAME | varchar(128) | 序列名称,用来区分不同业务 | -| MAX_ID | bigint(20) | 当前序列已被分配出去的最大值 | -| STEP | int(11) | 步长,表示每次分配的号段长度 | +| `SEQ_NAME` | varchar(128) | 序列名称,用于区分不同的应用。 | +| `MAX_ID` | bigint(20) | 当前已分配的序列的最大值。 | +| `STEP` | int(11) | 步长,表示每次分配的号段长度。 | + +每次应用程序按照配置的步长获取一段序列号。同时更新数据库以持久化当前已分配的序列的最大值。序列号的处理和分配在应用程序的内存中完成。一段序列号用完后,应用程序获取新的一段序列号,这有效地缓解了数据库写入压力。在实践中,您还可以调整步长来控制数据库更新的频率。 + +最后需要注意的是,上述两种方案生成的 ID 随机性不够,不能直接用作 TiDB 表的**主键**。在实践中,您可以对生成的 ID 进行位反转以获得更随机的新 ID。例如,对 `00000010100101000001111010011100` 进行位反转后变成 `00111001011110000010100101000000`,对 `11111111111111111111111111111101` 进行位反转后变成 `10111111111111111111111111111111`。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -应用程序每次按配置好的步长获取一段序列号,并同时更新数据库以持久化保存当前序列已被分配出去的最大值,然后在应用程序内存中即可完成序列号加工及分配动作。待一段号码耗尽之后,应用程序才会去获取新的号段,这样就有效降低了数据库写入压力。实际使用过程中,还可以适度调节步长以控制数据库记录的更新频度。 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -最后,需要注意的是,上述两种方案生成的 ID 都不够随机,不适合直接作为 TiDB 表的主键。实际使用过程中可以对生成的 ID 进行位反转(bit-reverse)后得到一个较为随机的新 ID。例如,经过位反转后,ID `00000010100101000001111010011100` 变为 `00111001011110000010100101000000`,ID `11111111111111111111111111111101` 变为 `10111111111111111111111111111111`。 + diff --git a/develop/dev-guide-unstable-result-set.md b/develop/dev-guide-unstable-result-set.md index d04bdfababa4..1283eb33144d 100644 --- a/develop/dev-guide-unstable-result-set.md +++ b/develop/dev-guide-unstable-result-set.md @@ -1,20 +1,42 @@ --- -title: 结果集不稳定 -summary: 结果集不稳定错误的处理办法。 +title: 不稳定结果集 +summary: 了解如何处理不稳定结果集错误。 --- -# 结果集不稳定 +# 不稳定结果集 -本章将叙述结果集不稳定错误的处理办法。 +本文档介绍如何解决不稳定结果集错误。 -## group by +## GROUP BY -出于便捷的考量,MySQL “扩展” 了 group by 语法,使 select 子句可以引用未在 group by 子句中声明的非聚集字段,也就是 non-full group by 语法。在其他数据库中,这被认为是一种语法错误,因为这会导致结果集不稳定。 +为了方便使用,MySQL "扩展"了 `GROUP BY` 语法,允许 `SELECT` 子句引用未在 `GROUP BY` 子句中声明的非聚合字段,即 `NON-FULL GROUP BY` 语法。在其他数据库中,这被视为语法**_错误_**,因为它会导致不稳定的结果集。 -在下例的 3 条 SQL 语句中,第一条 SQL 使用了 full group by 语法,所有在 select 子句中引用的字段,都在 group by 子句中有所声明,所以它的结果集是稳定的,可以看到 class 与 stuname 的全部组合共有三种;第二条与第三条是同一个 SQL,但它在两次执行时得到了不同的结果,这条 SQL 的 group by 子句中仅声明了一个 class 字段,因此结果集只会针对 class 进行聚集,class 的唯一值有两个,也就是说结果集中只会包含两行数据,而 class 与 stuname 的全部组合共有三种,班级 2018_CS_03 有两位同学,每次执行时返回哪位同学是没有语义上的限制的,都是符合语义的结果。 +例如,你有两个表: + +- `stu_info` 存储学生信息 +- `stu_score` 存储学生考试成绩 + +然后你可以编写如下 SQL 查询语句: + +```sql +SELECT + `a`.`class`, + `a`.`stuname`, + max( `b`.`courscore` ) +FROM + `stu_info` `a` + JOIN `stu_score` `b` ON `a`.`stuno` = `b`.`stuno` +GROUP BY + `a`.`class`, + `a`.`stuname` +ORDER BY + `a`.`class`, + `a`.`stuname`; +``` + +结果: ```sql -mysql> SELECT a.class, a.stuname, max(b.courscore) from stu_info a join stu_score b on a.stuno=b.stuno group by a.class, a.stuname order by a.class, a.stuname; +------------+--------------+------------------+ | class | stuname | max(b.courscore) | +------------+--------------+------------------+ @@ -23,30 +45,54 @@ mysql> SELECT a.class, a.stuname, max(b.courscore) from stu_info a join stu_scor | 2018_CS_03 | SpongeBob | 95.0 | +------------+--------------+------------------+ 3 rows in set (0.00 sec) +``` -mysql> select a.class, a.stuname, max(b.courscore) from stu_info a join stu_score b on a.stuno=b.stuno group by a.class order by a.class, a.stuname; -+------------+--------------+------------------+ -| class | stuname | max(b.courscore) | -+------------+--------------+------------------+ -| 2018_CS_01 | MonkeyDLuffy | 95.5 | -| 2018_CS_03 | SpongeBob | 99.0 | -+------------+--------------+------------------+ -2 rows in set (0.01 sec) +`a`.`class` 和 `a`.`stuname` 字段在 `GROUP BY` 语句中指定,选择的列是 `a`.`class`、`a`.`stuname` 和 `b`.`courscore`。唯一不在 `GROUP BY` 条件中的列 `b`.`courscore` 也使用 `max()` 函数指定了唯一值。这个 SQL 语句只有**_一个_**满足条件的结果,没有任何歧义,这就是所谓的 `FULL GROUP BY` 语法。 -mysql> select a.class, a.stuname, max(b.courscore) from stu_info a join stu_score b on a.stuno=b.stuno group by a.class order by a.class, a.stuname; +下面是一个 `NON-FULL GROUP BY` 语法的反例。例如,在这两个表中,编写以下 SQL 查询(在 `GROUP BY` 中删除 `a`.`stuname`)。 + +```sql +SELECT + `a`.`class`, + `a`.`stuname`, + max( `b`.`courscore` ) +FROM + `stu_info` `a` + JOIN `stu_score` `b` ON `a`.`stuno` = `b`.`stuno` +GROUP BY + `a`.`class` +ORDER BY + `a`.`class`, + `a`.`stuname`; +``` + +这时会返回两个匹配此 SQL 的值。 + +第一个返回值: + +```sql ++------------+--------------+------------------------+ +| class | stuname | max( `b`.`courscore` ) | ++------------+--------------+------------------------+ +| 2018_CS_01 | MonkeyDLuffy | 95.5 | +| 2018_CS_03 | PatrickStar | 99.0 | ++------------+--------------+------------------------+ +``` + +第二个返回值: + +```sql +------------+--------------+------------------+ | class | stuname | max(b.courscore) | +------------+--------------+------------------+ | 2018_CS_01 | MonkeyDLuffy | 95.5 | -| 2018_CS_03 | PatrickStar | 99.0 | +| 2018_CS_03 | SpongeBob | 99.0 | +------------+--------------+------------------+ -2 rows in set (0.01 sec) - ``` -因此,想保障 group by 语句结果集的稳定,请使用 full group by 语法。 +出现两个结果是因为你在 SQL 中**_没有_**指定如何获取 `a`.`stuname` 字段的值,而这两个结果都满足 SQL 语义。这导致了不稳定的结果集。因此,如果你想保证 `GROUP BY` 语句结果集的稳定性,请使用 `FULL GROUP BY` 语法。 -MySQL 提供了一个 SQL_MODE 开关 ONLY_FULL_GROUP_BY 来控制是否进行 full group by 语法的检查,TiDB 也兼容了这个 SQL_MODE 开关: +MySQL 提供了 `sql_mode` 开关 `ONLY_FULL_GROUP_BY` 来控制是否检查 `FULL GROUP BY` 语法。TiDB 也兼容这个 `sql_mode` 开关。 ```sql mysql> select a.class, a.stuname, max(b.courscore) from stu_info a join stu_score b on a.stuno=b.stuno group by a.class order by a.class, a.stuname; @@ -65,13 +111,15 @@ mysql> select a.class, a.stuname, max(b.courscore) from stu_info a join stu_scor ERROR 1055 (42000): Expression #2 of ORDER BY is not in GROUP BY clause and contains nonaggregated column '' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by ``` -**运行结果简述**:上例为 sql_mode 设置了 ONLY_FULL_GROUP_BY 的效果。 +**运行结果**:上面的例子展示了设置 `sql_mode` 为 `ONLY_FULL_GROUP_BY` 时的效果。 + +## ORDER BY -## order by +在 SQL 语义中,只有使用 `ORDER BY` 语法才能保证结果集按顺序输出。对于单实例数据库,由于数据存储在一台服务器上,在没有数据重组的情况下,多次执行的结果通常是稳定的。某些数据库(特别是 MySQL InnoDB 存储引擎)甚至可以按主键或索引顺序输出结果集。 -在 SQL 的语义中,只有使用了 order by 语法才会保障结果集的顺序输出。而单机数据库由于数据都存储在一台服务器上,在不进行数据重组时,多次执行的结果往往是稳定的,有些数据库(尤其是 MySQL InnoDB 存储引擎)还会按照主键或索引的顺序进行结果集的输出。TiDB 是分布式数据库,数据被存储在多台服务器上,另外 TiDB 层不缓存数据页,因此不含 order by 的 SQL 语句的结果集展现顺序容易被感知到不稳定。想要按顺序输出的结果集,需明确地把要排序的字段添加到 order by 子句中,这符合 SQL 的语义。 +作为分布式数据库,TiDB 将数据存储在多个服务器上。此外,TiDB 层不缓存数据页,因此没有 `ORDER BY` 的 SQL 语句的结果集顺序容易被感知为不稳定。要输出有序的结果集,需要在 `ORDER BY` 子句中明确添加排序字段,这符合 SQL 语义。 -在下面的案例中,用户只在 order by 子句中添加了一个字段,TiDB 只会按照这一个字段进行排序。 +在下面的例子中,只在 `ORDER BY` 子句中添加了一个字段,TiDB 只按该字段对结果进行排序。 ```sql mysql> select a.class, a.stuname, b.course, b.courscore from stu_info a join stu_score b on a.stuno=b.stuno order by a.class; @@ -119,15 +167,15 @@ mysql> select a.class, a.stuname, b.course, b.courscore from stu_info a join stu ``` -当 order by 值相同时,结果会不稳定。为了减少随机性,order by 值应该是唯一的。如果不能保证唯一性,则需要添加更多的 order by 字段,直到 order by 字段的组合是唯一的,这样结果才会稳定。 +当 `ORDER BY` 值相同时,结果是不稳定的。为了减少随机性,`ORDER BY` 值应该是唯一的。如果无法保证唯一性,则需要添加更多的 `ORDER BY` 字段,直到 `ORDER BY` 中的 `ORDER BY` 字段组合是唯一的,这样结果才会稳定。 -## 由于 group_concat() 中没有使用 order by 导致结果集不稳定 +## GROUP_CONCAT() 中未使用 ORDER BY 导致结果集不稳定 -结果集不稳定是因为 TiDB 是并行地从存储层读取数据,所以 `group_concat()` 在不加 order by 的情况下得到的结果集展现顺序容易被感知到不稳定。 +由于 TiDB 从存储层并行读取数据,因此没有 `ORDER BY` 的 `GROUP_CONCAT()` 返回的结果集顺序容易被感知为不稳定。 -`group_concat()` 要获取到按顺序输出的结果集,需要把用于排序的字段添加到 order by 子句中,这样才符合 SQL 的语义。在下面的案例中,使用 `group_concat()` 不加 order by 的情况下拼接 customer_id,造成结果集不稳定: +要让 `GROUP_CONCAT()` 按顺序获取结果集输出,需要在 `ORDER BY` 子句中添加排序字段,这符合 SQL 语义。在下面的例子中,没有 `ORDER BY` 的拼接 `customer_id` 的 `GROUP_CONCAT()` 导致了不稳定的结果集。 -1. 不加 order by +1. 不包含 `ORDER BY` 第一次查询: @@ -155,7 +203,7 @@ mysql> select a.class, a.stuname, b.course, b.courscore from stu_info a join stu +-------------------------------------------------------------------------+ ``` -2. 加 order by +2. 包含 `ORDER BY` 第一次查询: @@ -183,6 +231,20 @@ mysql> select a.class, a.stuname, b.course, b.courscore from stu_info a join stu +-------------------------------------------------------------------------+ ``` -## select \* from t limit n 的结果不稳定 +## SELECT * FROM T LIMIT N 的不稳定结果 + +返回的结果与存储节点(TiKV)上的数据分布有关。如果执行多次查询,存储节点(TiKV)的不同存储单元(Region)返回结果的速度不同,这可能导致不稳定的结果。 + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上向社区提问,或[提交支持工单](https://tidb.support.pingcap.com/)。 -返回结果与数据在存储节点 (TiKV) 上的分布有关。如果进行了多次查询,存储节点 (TiKV) 不同存储单元 (Region) 返回结果的速度不同,会造成结果不稳定。 + diff --git a/develop/dev-guide-update-data.md b/develop/dev-guide-update-data.md index be795f94fa5a..23ae754f6436 100644 --- a/develop/dev-guide-update-data.md +++ b/develop/dev-guide-update-data.md @@ -1,66 +1,75 @@ --- title: 更新数据 -summary: 更新数据、批量更新数据的方法、最佳实践及例子。 +summary: 了解如何更新数据和批量更新数据。 --- # 更新数据 -此页面将展示以下 SQL 语句,配合各种编程语言 TiDB 中的数据进行更新: +本文档介绍如何使用以下 SQL 语句和各种编程语言在 TiDB 中更新数据: -- [UPDATE](/sql-statements/sql-statement-update.md): 用于修改指定表中的数据。 -- [INSERT ON DUPLICATE KEY UPDATE](/sql-statements/sql-statement-insert.md): 用于插入数据,在有主键或唯一键冲突时,更新此数据。注意,**_不建议_**在有多个唯一键(包含主键)的情况下使用此语句。这是因为此语句在检测到任何唯一键(包括主键) 冲突时,将更新数据。在不止匹配到一行冲突时,将只会更新一行数据。 +- [UPDATE](/sql-statements/sql-statement-update.md):用于修改指定表中的数据。 +- [INSERT ON DUPLICATE KEY UPDATE](/sql-statements/sql-statement-insert.md):用于插入数据,如果存在主键或唯一键冲突,则更新该数据。如果存在多个唯一键(包括主键),**不建议**使用此语句。这是因为此语句在检测到任何唯一键(包括主键)冲突时都会更新数据。当存在多行冲突时,它只会更新一行。 -## 在开始之前 +## 开始之前 -在阅读本页面之前,你需要准备以下事项: +在阅读本文档之前,您需要准备以下内容: -- [使用 TiDB Cloud Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md) -- 阅读[数据库模式概览](/develop/dev-guide-schema-design-overview.md),并[创建数据库](/develop/dev-guide-create-database.md)、[创建表](/develop/dev-guide-create-table.md)、[创建二级索引](/develop/dev-guide-create-secondary-indexes.md) -- 若需使用 `UPDATE` 语句更新数据,需先[插入数据](/develop/dev-guide-insert-data.md) +- [构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 +- 阅读[架构设计概述](/develop/dev-guide-schema-design-overview.md)、[创建数据库](/develop/dev-guide-create-database.md)、[创建表](/develop/dev-guide-create-table.md)和[创建二级索引](/develop/dev-guide-create-secondary-indexes.md)。 +- 如果您想要 `UPDATE` 数据,需要先[插入数据](/develop/dev-guide-insert-data.md)。 ## 使用 `UPDATE` -需更新表中的现有行,需要使用带有 WHERE 子句的 [UPDATE 语句](/sql-statements/sql-statement-update.md),即需要过滤列进行更新。 +要更新表中的现有行,您需要使用带有 `WHERE` 子句的 [`UPDATE` 语句](/sql-statements/sql-statement-update.md)来过滤要更新的列。 > **注意:** > -> 如果您需要更新大量的行,比如数万甚至更多行,那么建议不要一次性进行完整的更新,而是每次迭代更新一部分,直到所有行全部更新。您可以编写脚本或程序,使用循环完成此操作。 -> 您可参考[批量更新](#批量更新)获得指引。 +> 如果您需要更新大量行,例如超过一万行,建议**_不要_**一次性完全更新,而是每次更新一部分,直到所有行都更新完成。您可以编写脚本或程序来循环执行此操作。 +> 详情请参见[批量更新](#批量更新)。 -### SQL 语法 +### `UPDATE` SQL 语法 -在 SQL 中,`UPDATE` 语句一般为以下形式: +在 SQL 中,`UPDATE` 语句通常采用以下形式: ```sql UPDATE {table} SET {update_column} = {update_value} WHERE {filter_column} = {filter_value} ``` -| 参数 | 描述 | +| 参数名 | 描述 | | :---------------: | :------------------: | | `{table}` | 表名 | -| `{update_column}` | 需更新的列名 | -| `{update_value}` | 需更新的此列的值 | -| `{filter_column}` | 匹配条件过滤器的列名 | -| `{filter_value}` | 匹配条件过滤器的列值 | +| `{update_column}` | 要更新的列名 | +| `{update_value}` | 要更新的列值 | +| `{filter_column}` | 匹配过滤条件的列名 | +| `{filter_value}` | 匹配过滤条件的列值 | -此处仅展示 `UPDATE` 的简单用法,详细文档可参考 TiDB 的 [UPDATE 语法页](/sql-statements/sql-statement-update.md)。 +详细信息,请参见 [UPDATE 语法](/sql-statements/sql-statement-update.md)。 ### `UPDATE` 最佳实践 -以下是更新行时需要遵循的一些最佳实践: +以下是一些更新数据的最佳实践: -- 始终在更新语句中指定 `WHERE` 子句。如果 `UPDATE` 没有 `WHERE` 子句,TiDB 将更新这个表内的**_所有行_**。 -- 需要更新大量行(数万或更多)的时候,使用[批量更新](#批量更新),这是因为 TiDB 单个事务大小限制为 [txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit)(默认为 100MB),且一次性过多的数据更新,将导致持有锁时间过长([悲观事务](/pessimistic-transaction.md)),或产生大量冲突([乐观事务](/optimistic-transaction.md))。 +- 始终在 `UPDATE` 语句中指定 `WHERE` 子句。如果 `UPDATE` 语句没有 `WHERE` 子句,TiDB 将更新表中的**_所有行_**。 -### `UPDATE` 例子 + -假设某位作者改名为 Helen Haruki,需要更改 [authors](/develop/dev-guide-bookshop-schema-design.md#authors-表) 表。假设他的唯一标识 `id` 为 1,即过滤器应为:`id = 1`。 +- 当需要更新大量行(例如超过一万行)时,使用[批量更新](#批量更新)。因为 TiDB 限制单个事务的大小([txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit),默认为 100 MB),一次性更新太多数据会导致锁定时间过长([悲观事务](/pessimistic-transaction.md))或引起冲突([乐观事务](/optimistic-transaction.md))。 + + + + + +- 当需要更新大量行(例如超过一万行)时,使用[批量更新](#批量更新)。因为 TiDB 默认限制单个事务的大小为 100 MB,一次性更新太多数据会导致锁定时间过长([悲观事务](/pessimistic-transaction.md))或引起冲突([乐观事务](/optimistic-transaction.md))。 + + + +### `UPDATE` 示例 + +假设一位作者将她的名字改为 **Helen Haruki**。您需要更改 [authors](/develop/dev-guide-bookshop-schema-design.md#authors-table) 表。假设她的唯一 `id` 是 **1**,过滤条件应为:`id = 1`。
-在 SQL 中更改作者姓名的示例为: - ```sql UPDATE `authors` SET `name` = "Helen Haruki" WHERE `id` = 1; ``` @@ -69,10 +78,8 @@ UPDATE `authors` SET `name` = "Helen Haruki" WHERE `id` = 1;
-在 Java 中更改作者姓名的示例为: - ```java -// ds is an entity of com.mysql.cj.jdbc.MysqlDataSource +// ds 是 com.mysql.cj.jdbc.MysqlDataSource 的实例 try (Connection connection = ds.getConnection()) { PreparedStatement pstmt = connection.prepareStatement("UPDATE `authors` SET `name` = ? WHERE `id` = ?"); pstmt.setString(1, "Helen Haruki"); @@ -88,41 +95,39 @@ try (Connection connection = ds.getConnection()) { ## 使用 `INSERT ON DUPLICATE KEY UPDATE` -如果你需要将新数据插入表中,但如果有任何唯一键(主键也是一种唯一键)发生冲突,则会更新第一条冲突数据,可使用 `INSERT ... ON DUPLICATE KEY UPDATE ...` 语句进行插入或更新。 +如果您需要向表中插入新数据,但如果存在唯一键(主键也是唯一键)冲突,则会更新第一个冲突的记录。您可以使用 `INSERT ... ON DUPLICATE KEY UPDATE ...` 语句来插入或更新。 -### SQL 语法 +### `INSERT ON DUPLICATE KEY UPDATE` SQL 语法 -在 SQL 中,`INSERT ... ON DUPLICATE KEY UPDATE ...` 语句一般为以下形式: +在 SQL 中,`INSERT ... ON DUPLICATE KEY UPDATE ...` 语句通常采用以下形式: ```sql INSERT INTO {table} ({columns}) VALUES ({values}) ON DUPLICATE KEY UPDATE {update_column} = {update_value}; ``` -| 参数 | 描述 | +| 参数名 | 描述 | | :---------------: | :--------------: | | `{table}` | 表名 | -| `{columns}` | 需插入的列名 | -| `{values}` | 需插入的此列的值 | -| `{update_column}` | 需更新的列名 | -| `{update_value}` | 需更新的此列的值 | +| `{columns}` | 要插入的列名 | +| `{values}` | 要插入的列值 | +| `{update_column}` | 要更新的列名 | +| `{update_value}` | 要更新的列值 | ### `INSERT ON DUPLICATE KEY UPDATE` 最佳实践 -- 在仅有一个唯一键的表上使用 `INSERT ON DUPLICATE KEY UPDATE`。此语句在检测到任何 **_唯一键_** (包括主键) 冲突时,将更新数据。在不止匹配到一行冲突时,将只会更新一行数据。因此,除非能保证仅有一行冲突,否则不建议在有多个唯一键的表中使用 `INSERT ON DUPLICATE KEY UPDATE` 语句。 -- 在创建或更新的场景中使用此语句。 +- 仅对具有一个唯一键的表使用 `INSERT ON DUPLICATE KEY UPDATE`。此语句在检测到任何**_唯一键_**(包括主键)冲突时都会更新数据。如果存在多行冲突,只会更新一行。因此,除非您能保证只有一行冲突,否则不建议在具有多个唯一键的表中使用 `INSERT ON DUPLICATE KEY UPDATE` 语句。 +- 在创建数据或更新数据时使用此语句。 -### `INSERT ON DUPLICATE KEY UPDATE` 例子 +### `INSERT ON DUPLICATE KEY UPDATE` 示例 -例如,需要更新 [ratings](/develop/dev-guide-bookshop-schema-design.md#ratings-表) 表来写入用户对书籍的评价,如果用户还未评价此书籍,将新建一条评价,如果用户已经评价过,那么将会更新他之前的评价。 +例如,您需要更新 [ratings](/develop/dev-guide-bookshop-schema-design.md#ratings-table) 表以包含用户对图书的评分。如果用户尚未对图书进行评分,将创建新的评分。如果用户已经评分,将更新他之前的评分。 -此处主键为 `book_id` 和 `user_id` 的联合主键。`user_id` 为 1 的用户,给 `book_id` 为 1000 的书籍,打出的 5 分的评价。 +在以下示例中,主键是 `book_id` 和 `user_id` 的联合主键。用户 `user_id = 1` 给图书 `book_id = 1000` 评分为 `5`。
-在 SQL 中更新书籍评价的示例为: - ```sql INSERT INTO `ratings` (`book_id`, `user_id`, `score`, `rated_at`) @@ -135,10 +140,8 @@ ON DUPLICATE KEY UPDATE `score` = 5, `rated_at` = NOW();
-在 Java 中更新书籍评价的示例为: - ```java -// ds is an entity of com.mysql.cj.jdbc.MysqlDataSource +// ds 是 com.mysql.cj.jdbc.MysqlDataSource 的实例 try (Connection connection = ds.getConnection()) { PreparedStatement p = connection.prepareStatement("INSERT INTO `ratings` (`book_id`, `user_id`, `score`, `rated_at`) @@ -158,23 +161,33 @@ VALUES (?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE `score` = ?, `rated_at` = NOW()" ## 批量更新 -需要更新表中多行的数据,可选择[使用 `UPDATE`](#使用-update),并使用 `WHERE` 子句过滤需要更新的数据。 +当您需要更新表中的多行数据时,可以使用带有 `WHERE` 子句的 [`INSERT ON DUPLICATE KEY UPDATE`](#使用-insert-on-duplicate-key-update) 来过滤需要更新的数据。 + + -但如果你需要更新大量行(数万或更多)的时候,建议使用一个迭代,每次都只更新一部分数据,直到更新全部完成。这是因为 TiDB 单个事务大小限制为 [txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit)(默认为 100MB),且一次性过多的数据更新,将导致持有锁时间过长([悲观事务](/pessimistic-transaction.md)),或产生大量冲突([乐观事务](/optimistic-transaction.md))。你可以在程序或脚本中使用循环来完成操作。 +但是,如果您需要更新大量行(例如超过一万行),建议您迭代更新数据,即每次只更新一部分数据,直到更新完成。这是因为 TiDB 限制单个事务的大小([txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit),默认为 100 MB)。一次性更新太多数据会导致锁定时间过长([悲观事务](/pessimistic-transaction.md))或引起冲突([乐观事务](/optimistic-transaction.md))。您可以在程序或脚本中使用循环来完成操作。 -本页提供了编写脚本来处理循环更新的示例,该示例演示了应如何进行 `SELECT` 和 `UPDATE` 的组合,完成循环更新。 + + + + +但是,如果您需要更新大量行(例如超过一万行),建议您迭代更新数据,即每次只更新一部分数据,直到更新完成。这是因为 TiDB 默认限制单个事务的大小为 100 MB。一次性更新太多数据会导致锁定时间过长([悲观事务](/pessimistic-transaction.md))或引起冲突([乐观事务](/optimistic-transaction.md))。您可以在程序或脚本中使用循环来完成操作。 + + + +本节提供编写脚本处理迭代更新的示例。此示例展示了如何组合使用 `SELECT` 和 `UPDATE` 来完成批量更新。 ### 编写批量更新循环 -首先,你应在你的应用或脚本的循环中,编写一个 `SELECT` 查询。这个查询的返回值可以作为需要更新的行的主键。需要注意的是,定义这个 `SELECT` 查询时,需要注意使用 `WHERE` 子句过滤需要更新的行。 +首先,您应该在应用程序或脚本的循环中编写一个 `SELECT` 查询。此查询的返回值可以用作需要更新的行的主键。请注意,在定义此 `SELECT` 查询时,需要使用 `WHERE` 子句来过滤需要更新的行。 -### 例子 +### 示例 -假设在过去的一年里,用户在 `bookshop` 网站进行了大量的书籍打分,但是原本设计为 5 分制的评分导致书籍评分的区分度不够,大量书籍评分集中在 3 分附近,因此,决定将 5 分制改为 10 分制。用来增大书籍评分的区分度。 +假设在过去一年中,您的 `bookshop` 网站收到了大量用户对图书的评分,但原来的 5 分制设计导致图书评分缺乏区分度。大多数图书的评分都是 `3` 分。您决定从 5 分制改为 10 分制,以区分评分。 -这时需要对 `ratings` 表内之前 5 分制的数据进行乘 2 操作,同时需向 `ratings` 表内添加一个新列,以指示行是否已经被更新了。使用此列,可以在 `SELECT` 中过滤掉已经更新的行,这将防止脚本崩溃时对行进行多次更新,导致不合理的数据出现。 +您需要将 `ratings` 表中之前 5 分制的数据乘以 `2`,并在评分表中添加一个新列来指示行是否已更新。使用此列,您可以在 `SELECT` 中过滤出已更新的行,这将防止脚本崩溃并多次更新行,导致数据不合理。 -例如,你可以创建一个名为 `ten_point`,数据类型为 [BOOL](/data-type-numeric.md#boolean-类型) 的列作为是否为 10 分制的标识: +例如,您创建一个名为 `ten_point` 的列,数据类型为 [BOOL](/data-type-numeric.md#boolean-type),作为是否为 10 分制的标识符: ```sql ALTER TABLE `bookshop`.`ratings` ADD COLUMN `ten_point` BOOL NOT NULL DEFAULT FALSE; @@ -182,12 +195,12 @@ ALTER TABLE `bookshop`.`ratings` ADD COLUMN `ten_point` BOOL NOT NULL DEFAULT FA > **注意:** > -> 此批量更新程序将使用 **DDL** 语句将进行数据表的模式更改。TiDB 的所有 DDL 变更操作全部都是在线进行的,可查看此处,了解此处使用的 [ADD COLUMN](/sql-statements/sql-statement-add-column.md) 语句。 +> 此批量更新应用程序使用 **DDL** 语句对数据表进行架构更改。TiDB 的所有 DDL 更改操作都是在线执行的。更多信息,请参见 [ADD COLUMN](/sql-statements/sql-statement-add-column.md)。
-在 Golang 中,批量更新程序类似于以下内容: +在 Golang 中,批量更新应用程序类似于以下内容: ```go package main @@ -216,9 +229,9 @@ func main() { } } -// updateBatch select at most 1000 lines data to update score +// updateBatch 选择最多 1000 行数据来更新分数 func updateBatch(db *sql.DB, firstTime bool, lastBookID, lastUserID int64) (bookID, userID int64) { - // select at most 1000 primary keys in five-point scale data + // 选择最多 1000 个五分制数据的主键 var err error var rows *sql.Rows @@ -235,7 +248,7 @@ func updateBatch(db *sql.DB, firstTime bool, lastBookID, lastUserID int64) (book panic(fmt.Errorf("error occurred or rows nil: %+v", err)) } - // joint all id with a list + // 将所有 id 连接成一个列表 var idList []interface{} for rows.Next() { var tempBookID, tempUserID int64 @@ -253,7 +266,7 @@ func updateBatch(db *sql.DB, firstTime bool, lastBookID, lastUserID int64) (book return bookID, userID } -// placeHolder format SQL place holder +// placeHolder 格式化 SQL 占位符 func placeHolder(n int) string { holderList := make([]string, n/2, n/2) for i := range holderList { @@ -263,15 +276,15 @@ func placeHolder(n int) string { } ``` -每次迭代中,`SELECT` 按主键顺序进行查询,最多选择 1000 行未更新到 10 分制(`ten_point` 为 `false`)数据的主键值。每次 `SELECT` 都会选择比上一次 `SELECT` 结果的最大主键还要大的数据,防止重复。然后,使用批量更新的方式,对其 `score` 列乘 2,并且将 `ten_point` 设为 `true`,更新 `ten_point` 的意义是在于防止更新程序崩溃重启后,反复更新同一行数据,导致数据损坏。每次循环中的 `time.Sleep(time.Second)` 将使得更新程序暂停 1 秒,防止批量更新程序占用过多的硬件资源。 +在每次迭代中,`SELECT` 按主键顺序查询。它选择最多 `1000` 行尚未更新为 10 分制(`ten_point` 为 `false`)的主键值。每个 `SELECT` 语句选择大于前一个 `SELECT` 结果中最大值的主键,以防止重复。然后,它使用批量更新,将其 `score` 列乘以 `2`,并将 `ten_point` 设置为 `true`。更新 `ten_point` 的目的是防止更新应用程序在崩溃后重启时重复更新同一行,这可能会导致数据损坏。每个循环中的 `time.Sleep(time.Second)` 使更新应用程序暂停 1 秒,以防止更新应用程序消耗过多的硬件资源。
-
+
-在 Java (JDBC) 中,批量更新程序类似于以下内容: +在 Java (JDBC) 中,批量更新应用程序可能类似于以下内容: -**Java 代码部分:** +**代码:** ```java package com.pingcap.bulkUpdate; @@ -316,12 +329,12 @@ public class BatchUpdateExample { } public static void main(String[] args) throws InterruptedException { - // Configure the example database connection. + // 配置示例数据库连接 - // Create a mysql data source instance. + // 创建 mysql 数据源实例 MysqlDataSource mysqlDataSource = new MysqlDataSource(); - // Set server name, port, database name, username and password. + // 设置服务器名称、端口、数据库名称、用户名和密码 mysqlDataSource.setServerName("localhost"); mysqlDataSource.setPortNumber(4000); mysqlDataSource.setDatabaseName("bookshop"); @@ -403,7 +416,7 @@ public class BatchUpdateExample { } ``` -**`hibernate.cfg.xml` 配置部分:** +- `hibernate.cfg.xml` 配置: ```xml @@ -413,7 +426,7 @@ public class BatchUpdateExample { - + com.mysql.cj.jdbc.Driver org.hibernate.dialect.TiDBDialect jdbc:mysql://localhost:4000/movie @@ -422,15 +435,29 @@ public class BatchUpdateExample { false 20 - + true true ``` -每次迭代中,`SELECT` 按主键顺序进行查询,最多选择 1000 行未更新到 10 分制(`ten_point` 为 `false`)数据的主键值。每次 `SELECT` 都会选择比上一次 `SELECT` 结果的最大主键还要大的数据,防止重复。然后,使用批量更新的方式,对其 `score` 列乘 2,并且将 `ten_point` 设为 `true`,更新 `ten_point` 的意义是在于防止更新程序崩溃重启后,反复更新同一行数据,导致数据损坏。每次循环中的 `TimeUnit.SECONDS.sleep(1);` 将使得更新程序暂停 1 秒,防止批量更新程序占用过多的硬件资源。 +在每次迭代中,`SELECT` 按主键顺序查询。它选择最多 `1000` 行尚未更新为 10 分制(`ten_point` 为 `false`)的主键值。每个 `SELECT` 语句选择大于前一个 `SELECT` 结果中最大值的主键,以防止重复。然后,它使用批量更新,将其 `score` 列乘以 `2`,并将 `ten_point` 设置为 `true`。更新 `ten_point` 的目的是防止更新应用程序在崩溃后重启时重复更新同一行,这可能会导致数据损坏。每个循环中的 `TimeUnit.SECONDS.sleep(1);` 使更新应用程序暂停 1 秒,以防止更新应用程序消耗过多的硬件资源。
+ +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-use-common-table-expression.md b/develop/dev-guide-use-common-table-expression.md index 82d3df9f3f93..33fb2ee86f74 100644 --- a/develop/dev-guide-use-common-table-expression.md +++ b/develop/dev-guide-use-common-table-expression.md @@ -1,27 +1,27 @@ --- -title: 公共表表达式 (CTE) -summary: 介绍 TiDB 公共表表达式能力,用以简化 SQL。 +title: 公共表表达式 +summary: 了解 TiDB 的 CTE 功能,它可以帮助你更高效地编写 SQL 语句。 --- -# 公共表表达式 (CTE) +# 公共表表达式 -由于业务的客观复杂性,有时候会写出长达 2000 行的单条 SQL 语句,其中包含大量的聚合和多层子查询嵌套,维护此类 SQL 堪称开发人员的噩梦。 +在某些事务场景中,由于应用程序的复杂性,你可能需要编写长达 2,000 行的单个 SQL 语句。该语句可能包含大量聚合和多层子查询嵌套。维护这样一个长 SQL 语句可能会成为开发人员的噩梦。 -在前面的小节当中已经介绍了如何使用[视图](/develop/dev-guide-use-views.md)简化查询,也介绍了如何使用[临时表](/develop/dev-guide-use-temporary-tables.md)来缓存中间查询结果。 +为了避免这样的长 SQL 语句,你可以使用[视图](/develop/dev-guide-use-views.md)来简化查询,或使用[临时表](/develop/dev-guide-use-temporary-tables.md)来缓存中间查询结果。 -在这一小节当中,将介绍 TiDB 当中的公共表表达式(CTE)语法,它是一种更加便捷的复用查询结果的方法。 +本文介绍 TiDB 中的公共表表达式(Common Table Expression,CTE)语法,这是重用查询结果的一种更便捷的方式。 -TiDB 从 5.1 版本开始支持 ANSI SQL 99 标准的 CTE 及其递归的写法,极大提升开发人员和 DBA 编写复杂业务逻辑 SQL 的效率,增强代码的可维护性。 +自 TiDB v5.1 起,TiDB 支持 ANSI SQL99 标准的 CTE 和递归。使用 CTE,你可以更高效地编写复杂应用逻辑的 SQL 语句,并且更容易维护代码。 -## 基本使用 +## 基本用法 -公共表表达式 (CTE) 是一个临时的中间结果集,能够在 SQL 语句中引用多次,提高 SQL 语句的可读性与执行效率。在 TiDB 中可以通过 [`WITH`](/sql-statements/sql-statement-with.md) 语句使用公共表表达式。 +公共表表达式(CTE)是一个临时结果集,可以在 SQL 语句中多次引用,以提高语句的可读性和执行效率。你可以使用 [`WITH`](/sql-statements/sql-statement-with.md) 语句来使用 CTE。 -公共表表达式可以分为非递归和递归两种类型。 +公共表表达式可以分为两种类型:非递归 CTE 和递归 CTE。 -### 非递归的 CTE +### 非递归 CTE -非递归的 CTE 使用如下语法进行定义: +非递归 CTE 可以使用以下语法定义: ```sql WITH AS ( @@ -30,12 +30,12 @@ WITH AS ( SELECT ... FROM ; ``` -例如,假设还想知道最年长的 50 位作家分别编写过多少书籍。 +例如,如果你想知道 50 位最年长的作者各自写了多少本书,请按照以下步骤操作: - -
+ +
-在 SQL 中,可以将[临时表](/develop/dev-guide-use-temporary-tables.md)小节当中的例子改为以下 SQL 语句: +将[临时表](/develop/dev-guide-use-temporary-tables.md)中的语句更改为以下内容: ```sql WITH top_50_eldest_authors_cte AS ( @@ -54,7 +54,7 @@ LEFT JOIN book_authors ba ON ta.id = ba.author_id GROUP BY ta.id; ``` -查询结果如下: +结果如下: ``` +------------+------------+---------------------+-------+ @@ -70,9 +70,7 @@ GROUP BY ta.id; ```
-
- -在 Java 中的示例如下: +
```java public List getTop50EldestAuthorInfoByCTE() throws SQLException { @@ -111,7 +109,7 @@ public List getTop50EldestAuthorInfoByCTE() throws SQLException {
-这时,可以发现名为 “Ray Macejkovic” 的作者写了 4 本书,继续通过 CTE 查询来了解这 4 本书的销量和评分: +可以发现作者 "Ray Macejkovic" 写了 4 本书。通过 CTE 查询,你可以进一步获取这 4 本书的订单和评分信息,如下所示: ```sql WITH books_authored_by_rm AS ( @@ -146,7 +144,7 @@ FROM ; ``` -查询结果如下: +结果如下: ``` +------------+-------------------------+----------------+--------+ @@ -160,19 +158,19 @@ FROM 4 rows in set (0.06 sec) ``` -在这个 SQL 语句,定义了三个 CTE 块,CTE 块之间使用 `,` 进行分隔。 +这个 SQL 语句中定义了三个 CTE 块,它们用 `,` 分隔。 -先在 CTE 块 `books_authored_by_rm` 当中将该作者(作者 ID 为 `2299112019`)所编写的书查出来,然后在 `books_with_average_ratings` 和 `books_with_orders` 中分别查出这些书的平均评分和订单数,最后通过 `JOIN` 语句进行汇总。 +首先,在 CTE 块 `books_authored_by_rm` 中查找该作者(ID 为 `2299112019`)写的书。然后在 `books_with_average_ratings` 和 `books_with_orders` 中分别找到这些书的平均评分和订单。最后,通过 `JOIN` 语句聚合结果。 -值得注意的是,`books_authored_by_rm` 中的查询只会执行一次,TiDB 会开辟一块临时空间对查询的结果进行缓存,当 `books_with_average_ratings` 和 `books_with_orders` 引用时会直接从该临时空间当中获取数据。 +注意,`books_authored_by_rm` 中的查询只执行一次,然后 TiDB 创建一个临时空间来缓存其结果。当 `books_with_average_ratings` 和 `books_with_orders` 中的查询引用 `books_authored_by_rm` 时,TiDB 直接从这个临时空间获取其结果。 -> **建议:** +> **提示:** > -> 当默认的 CTE 查询执行效率不高时,你可以使用 [`MERGE()`](/optimizer-hints.md#merge) hint,将 CTE 子查询拓展到外部查询,以此提高执行效率。 +> 如果默认 CTE 查询的效率不好,你可以使用 [`MERGE()`](/optimizer-hints.md#merge) 提示将 CTE 子查询展开到外部查询中以提高效率。 -### 递归的 CTE +### 递归 CTE -递归的公共表表达式可以使用如下语法进行定义: +递归 CTE 可以使用以下语法定义: ```sql WITH RECURSIVE AS ( @@ -181,7 +179,7 @@ WITH RECURSIVE AS ( SELECT ... FROM ; ``` -比较经典的例子是通过递归的 CTE 生成一组[斐波那契数](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0): +一个经典的例子是使用递归 CTE 生成一组[斐波那契数](https://en.wikipedia.org/wiki/Fibonacci_number): ```sql WITH RECURSIVE fibonacci (n, fib_n, next_fib_n) AS @@ -193,7 +191,7 @@ WITH RECURSIVE fibonacci (n, fib_n, next_fib_n) AS SELECT * FROM fibonacci; ``` -查询结果如下: +结果如下: ``` +------+-------+------------+ @@ -213,6 +211,20 @@ SELECT * FROM fibonacci; 10 rows in set (0.00 sec) ``` -## 扩展阅读 +## 阅读更多 - [WITH](/sql-statements/sql-statement-with.md) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-use-follower-read.md b/develop/dev-guide-use-follower-read.md index 52f934c88f7b..56f2cfb3018f 100644 --- a/develop/dev-guide-use-follower-read.md +++ b/develop/dev-guide-use-follower-read.md @@ -1,49 +1,61 @@ --- title: Follower Read -summary: 使用 Follower Read 在特定情况下加速查询。 +summary: 了解如何使用 Follower Read 优化查询性能。 --- # Follower Read -本章将介绍使用 Follower Read 在特定情况下加速查询的方法。 +本文档介绍如何使用 Follower Read 优化查询性能。 ## 简介 -在 TiDB 当中,数据是以 [Region](/tidb-storage.md#region) 为单位,分散在集群中所有的节点上进行存储的。一个 Region 可以存在多个副本,副本又分为一个 leader 和多个 follower。当 leader 上的数据发生变化时,TiDB 会将数据同步更新到 follower。 +TiDB 使用 [Region](/tidb-storage.md#region) 作为基本单位将数据分布到集群中的所有节点。一个 Region 可以有多个副本,这些副本分为一个 leader 和多个 follower。当 leader 上的数据发生变化时,TiDB 会同步更新数据到 follower。 -默认情况下,TiDB 只会在同一个 Region 的 leader 上读写数据。当系统中存在读取热点 Region 导致 leader 资源紧张成为整个系统读取瓶颈时,启用 Follower Read 功能可明显降低 leader 的负担,并且通过在多个 follower 之间均衡负载,显著地提升整体系统的吞吐能力。 +默认情况下,TiDB 只在同一个 Region 的 leader 上读写数据。当 Region 出现读热点时,Region leader 可能成为整个系统的读取瓶颈。在这种情况下,启用 Follower Read 功能可以通过在多个 follower 之间平衡负载来显著减少 leader 的负载并提高整个系统的吞吐量。 -## 何时使用 +## 使用场景 -### 优化读热点 +### 减少读热点 -你可以在 [TiDB Dashboard 流量可视化页面](/dashboard/dashboard-key-visualizer.md)当中通过可视化的方法分析你的应用程序是否存在热点 Region。你可以通过将「指标选择框」选择到 `Read (bytes)` 或 `Read (keys)` 查看是否存在读取热点 Region。 + -如果发现确实存在热点问题,你可以通过阅读 [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md)章节进行逐一排查,以便从应用程序层面上避免热点的产生。 +你可以在 [TiDB Dashboard 的 Key Visualizer 页面](/dashboard/dashboard-key-visualizer.md)上直观地分析你的应用程序是否存在热点 Region。你可以通过选择"指标选择框"为 `Read (bytes)` 或 `Read (keys)` 来检查是否出现读热点。 -如果读取热点的确无法避免或者改动的成本很大,你可以尝试通过 Follower Read 功能将读取请求更好的负载均衡到 follower region。 +有关处理热点的更多信息,请参阅 [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md)。 -### 优化跨数据中心部署的延迟 + -如果 TiDB 集群是跨地区或跨数据中心部署的,一个 Region 的不同副本分布在不同的地区或数据中心,此时可以通过配置 Follower Read 为 `closest-adaptive` 或 `closest-replicas` 让 TiDB 优先从当前的数据中心执行读操作,这样可以大幅降低读操作的延迟和流量开销。具体原理可参考 [Follower Read](/follower-read.md)。 + -## 开启 Follower Read +你可以在 [TiDB Cloud 的 Key Visualizer 页面](/tidb-cloud/tune-performance.md#key-visualizer)上直观地分析你的应用程序是否存在热点 Region。你可以通过选择"指标选择框"为 `Read (bytes)` 或 `Read (keys)` 来检查是否出现读热点。 - -
+有关处理热点的更多信息,请参阅 [TiDB 热点问题处理](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues)。 -在 SQL 中,你可以将变量 `tidb_replica_read` 的值(默认为 `leader`)设置为 `follower`、`leader-and-follower`、`prefer-leader`、`closest-replicas` 或 `closest-adaptive` 开启 TiDB 的 Follower Read 功能: + + +如果读热点不可避免或更改成本很高,你可以尝试使用 Follower Read 功能,将读取请求更好地负载均衡到 follower Region。 + +### 减少地理分布部署的延迟 + +如果你的 TiDB 集群跨区域或数据中心部署,Region 的不同副本分布在不同的区域或数据中心。在这种情况下,你可以将 Follower Read 配置为 `closest-adaptive` 或 `closest-replicas`,允许 TiDB 优先从当前数据中心读取,这可以显著减少读取操作的延迟和流量开销。有关实现细节,请参阅 [Follower Read](/follower-read.md)。 + +## 启用 Follower Read + + +
+ +要启用 Follower Read,将变量 `tidb_replica_read`(默认值为 `leader`)设置为 `follower`、`leader-and-follower`、`prefer-leader`、`closest-replicas` 或 `closest-adaptive`: ```sql SET [GLOBAL] tidb_replica_read = 'follower'; ``` -你可以通过 [Follower Read 使用方式](/follower-read.md#使用方式) 了解该变量的更多细节。 +有关此变量的更多详细信息,请参阅 [Follower Read 使用方法](/follower-read.md#usage)。
-
+
-在 Java 语言当中,可以定义一个 `FollowerReadHelper` 类用于开启 Follower Read 功能: +在 Java 中,要启用 Follower Read,定义一个 `FollowerReadHelper` 类。 ```java public enum FollowReadMode { @@ -88,19 +100,19 @@ public class FollowerReadHelper { } ``` -在需要使用从 Follower 节点读取数据时,通过 `setSessionReplicaRead(conn, FollowReadMode.LEADER_AND_FOLLOWER)` 方法在当前 Session 开启能够在 Leader 节点和 Follower 节点进行负载均衡的 Follower Read 功能,当连接断开时,会恢复到原来的模式。 +从 Follower 节点读取数据时,使用 `setSessionReplicaRead(conn, FollowReadMode.LEADER_AND_FOLLOWER)` 方法启用 Follower Read 功能,可以在当前会话中平衡 Leader 节点和 Follower 节点之间的负载。当连接断开时,它将恢复到原始模式。 ```java public static class AuthorDAO { - // Omit initialization of instance variables... + // 省略实例变量的初始化... public void getAuthorsByFollowerRead() throws SQLException { try (Connection conn = ds.getConnection()) { - // Enable the follower read feature. + // 启用 follower read 功能。 FollowerReadHelper.setSessionReplicaRead(conn, FollowReadMode.LEADER_AND_FOLLOWER); - // Read the authors list for 100000 times. + // 读取作者列表 100000 次。 Random random = new Random(); for (int i = 0; i < 100000; i++) { Integer birthYear = 1920 + random.nextInt(100); @@ -131,8 +143,34 @@ public static class AuthorDAO {
-## 扩展阅读 +## 阅读更多 - [Follower Read](/follower-read.md) -- [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md) -- [TiDB Dashboard 流量可视化页面](/dashboard/dashboard-key-visualizer.md) + + + +- [热点问题处理](/troubleshoot-hot-spot-issues.md) +- [TiDB Dashboard - Key Visualizer 页面](/dashboard/dashboard-key-visualizer.md) + + + + + +- [热点问题处理](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues) +- [TiDB Cloud Key Visualizer 页面](/tidb-cloud/tune-performance.md#key-visualizer) + + + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-use-stale-read.md b/develop/dev-guide-use-stale-read.md index 1e771ad65c68..ab38ac2b0ea2 100644 --- a/develop/dev-guide-use-stale-read.md +++ b/develop/dev-guide-use-stale-read.md @@ -1,25 +1,25 @@ --- -title: Stale Read -summary: 使用 Stale Read 在特定情况下加速查询。 +title: 历史读取 +summary: 了解如何在特定条件下使用历史读取来加速查询。 --- -# Stale Read +# 历史读取 -Stale Read 是一种读取历史数据版本的机制,通过 Stale Read 功能,你能从指定时间点或时间范围内读取对应的历史数据,从而在数据强一致需求没那么高的场景降低读取数据的延迟。当使用 Stale Read 时,TiDB 默认会随机选择一个副本来读取数据,因此能利用所有保存有副本的节点的处理能力。 +历史读取(Stale Read)是 TiDB 用于读取存储在 TiDB 中的历史版本数据的机制。使用此机制,您可以读取特定时间或指定时间范围内的相应历史数据,从而节省存储节点之间数据复制造成的延迟。当您使用历史读取时,TiDB 会随机选择一个副本进行数据读取,这意味着所有副本都可用于数据读取。 -在实际的使用当中,请根据具体的[场景](/stale-read.md#场景描述)判断是否适合在 TiDB 当中开启 Stale Read 功能。如果你的应用程序不能容忍读到非实时的数据,请勿使用 Stale Read,否则读到的数据可能不是最新成功写入的数据。 +在实践中,请根据[使用场景](/stale-read.md#usage-scenarios-of-stale-read)仔细考虑是否适合在 TiDB 中启用历史读取。如果您的应用程序不能容忍读取非实时数据,请不要启用历史读取。 -TiDB 提供了语句级别、事务级别、会话级别三种级别的 Stale Read 功能,接下来将逐一进行介绍: +TiDB 提供了三个级别的历史读取:语句级别、事务级别和会话级别。 -## 引入 +## 简介 -在 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序当中,你可以通过下面的 SQL 语句查询出最新出版的书籍以及它们的价格: +在 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序中,您可以通过以下 SQL 语句查询最新发布的图书及其价格: ```sql SELECT id, title, type, price FROM books ORDER BY published_at DESC LIMIT 5; ``` -运行结果为: +结果如下: ``` +------------+------------------------------+-----------------------+--------+ @@ -34,22 +34,22 @@ SELECT id, title, type, price FROM books ORDER BY published_at DESC LIMIT 5; 5 rows in set (0.02 sec) ``` -看到此时(2022-04-20 15:20:00)的列表中,**The Story of Droolius Caesar** 这本小说的价格为 100.0 元。 +在此时(2022-04-20 15:20:00),《The Story of Droolius Caesar》的价格是 100.0。 -于此同时,卖家发现这本书很受欢迎,于是他通过下面的 SQL 语句将这本书的价格高到了 150.0 元。 +同时,卖家发现这本书很受欢迎,通过以下 SQL 语句将书的价格提高到 150.0: ```sql UPDATE books SET price = 150 WHERE id = 3181093216; ``` -运行结果为: +结果如下: ``` Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 ``` -当再次查询最新书籍列表时,发现这本书确实涨价了。 +通过查询最新的图书列表,您可以看到这本书的价格已经上涨。 ``` +------------+------------------------------+-----------------------+--------+ @@ -64,22 +64,22 @@ Rows matched: 1 Changed: 1 Warnings: 0 5 rows in set (0.01 sec) ``` -如果不要求必须使用最新的数据,可以让 TiDB 通过 Stale Read 功能直接返回可能已经过期的历史数据,避免使用强一致性读时数据同步带来的延迟。 +如果不需要使用最新数据,您可以使用历史读取进行查询,这可能会返回过期数据,以避免强一致性读取期间数据复制造成的延迟。 -假设在 Bookshop 应用程序当中,在用户浏览书籍列表页时,不对书籍价格的实时性进行要求,只有用户在点击查看书籍详情页或下单时才去获取实时的价格信息,可以借助 Stale Read 能力来进一步提升应用的吞吐量。 +假设在 Bookshop 应用程序中,图书列表页面不需要实时价格,只在图书详情和订单页面需要实时价格。这时可以使用历史读取来提高应用程序的吞吐量。 ## 语句级别
-在 SQL 中,你可以在上述价格的查询语句当中添加上 `AS OF TIMESTAMP ` 语句查看到固定时间点之前这本书的价格。 +要查询特定时间之前的图书价格,在上述查询语句中添加 `AS OF TIMESTAMP ` 子句。 ```sql SELECT id, title, type, price FROM books AS OF TIMESTAMP '2022-04-20 15:20:00' ORDER BY published_at DESC LIMIT 5; ``` -运行结果为: +结果如下: ``` +------------+------------------------------+-----------------------+--------+ @@ -94,21 +94,21 @@ SELECT id, title, type, price FROM books AS OF TIMESTAMP '2022-04-20 15:20:00' O 5 rows in set (0.01 sec) ``` -除了指定精确的时间点外,你还可以通过: +除了指定确切时间外,您还可以指定以下内容: -- `AS OF TIMESTAMP NOW() - INTERVAL 10 SECOND` 表示读取 10 秒前最新的数据。 -- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS('2016-10-08 16:45:26', '2016-10-08 16:45:29')` 表示读取在 2016 年 10 月 8 日 16 点 45 分 26 秒到 29 秒的时间范围内尽可能新的数据。 -- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS(NOW() - INTERVAL 20 SECOND, NOW())` 表示读取 20 秒前到现在的时间范围内尽可能新的数据。 +- `AS OF TIMESTAMP NOW() - INTERVAL 10 SECOND` 查询 10 秒前的最新数据。 +- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS('2016-10-08 16:45:26', '2016-10-08 16:45:29')` 查询 `2016-10-08 16:45:26` 和 `2016-10-08 16:45:29` 之间的最新数据。 +- `AS OF TIMESTAMP TIDB_BOUNDED_STALENESS(NOW() -INTERVAL 20 SECOND, NOW())` 查询 20 秒内的最新数据。 -需要注意的是,设定的时间戳或时间戳的范围不能过早或晚于当前时间。此外 `NOW()` 默认精确到秒,当精度要求较高时,需要添加参数,例如 `NOW(3)` 精确到毫秒。详情请参考 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_now)。 +请注意,指定的时间戳或间隔不能太早或晚于当前时间。此外,`NOW()` 默认为秒精度。要实现更高精度,您可以添加参数,例如使用 `NOW(3)` 获取毫秒精度。更多信息,请参见 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_now)。 -过期的数据在 TiDB 当中会由[垃圾回收器](/garbage-collection-overview.md)进行回收,数据在被清除之前会被保留一小段时间,这段时间被称为 [GC Life Time (默认 10 分钟)](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入)。每次进行 GC 时,将以当前时间减去该时间周期的值作为 **GC Safe Point**。如果尝试读取 GC Safe Point 之前数据,TiDB 会报如下错误: +过期数据将被 TiDB 中的[垃圾回收](/garbage-collection-overview.md)回收,数据在被清除前会保留一段时间。这段时间称为 [GC Life Time(默认 10 分钟)](/system-variables.md#tidb_gc_life_time-new-in-v50)。当 GC 启动时,当前时间减去这段时间将被用作 **GC Safe Point**。如果您尝试读取 GC Safe Point 之前的数据,TiDB 将报告以下错误: ``` ERROR 9006 (HY000): GC life time is shorter than transaction duration... ``` -如果给出的时间戳是一个未来的时间节点,TiDB 会报如下错误: +如果给定的时间戳是未来时间,TiDB 将报告以下错误: ``` ERROR 9006 (HY000): cannot set read timestamp to a future time. @@ -117,12 +117,10 @@ ERROR 9006 (HY000): cannot set read timestamp to a future time.
-在 Java 中的示例如下: - ```java public class BookDAO { - // Omit some code... + // 省略部分代码... public List getTop5LatestBooks() throws SQLException { List books = new ArrayList<>(); @@ -199,19 +197,19 @@ if (top5LatestBooks.size() > 0) { top5LatestBooks = bookDAO.getTop5LatestBooks(); System.out.println("The latest book price (after update): " + top5LatestBooks.get(0).getPrice()); - // Use the stale read. + // 使用历史读取 top5LatestBooks = bookDAO.getTop5LatestBooksWithStaleRead(5); System.out.println("The latest book price (maybe stale): " + top5LatestBooks.get(0).getPrice()); - // Try to stale read the data at the future time. + // 尝试读取未来时间的数据 bookDAO.getTop5LatestBooksWithStaleRead(-5); - // Try to stale read the data before 20 minutes. + // 尝试读取 20 分钟前的数据 bookDAO.getTop5LatestBooksWithStaleRead(20 * 60); } ``` -通过结果可以看到通过 Stale Read 读取到了更新之前的价格 100.00 元。 +以下结果显示历史读取返回的价格是 100.00,这是更新前的值。 ``` The latest book price (before update): 100.00 @@ -226,24 +224,24 @@ WARN: GC life time is shorter than transaction duration. ## 事务级别 -通过 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 语句,你可以开启一个基于历史时间的只读事务,该事务基于所提供的历史时间来读取历史数据。 +使用 `START TRANSACTION READ ONLY AS OF TIMESTAMP` 语句,您可以基于历史时间启动一个只读事务,该事务从指定的历史时间戳读取历史数据。
-在 SQL 中的示例如下: +例如: ```sql START TRANSACTION READ ONLY AS OF TIMESTAMP NOW() - INTERVAL 5 SECOND; ``` -尝试通过 SQL 查询最新书籍的价格,发现 **The Story of Droolius Caesar** 这本书的价格还是更新之前的价格 100.0 元。 +通过查询图书的最新价格,您可以看到《The Story of Droolius Caesar》的价格仍然是 100.0,这是更新前的值。 ```sql SELECT id, title, type, price FROM books ORDER BY published_at DESC LIMIT 5; ``` -运行结果为: +结果如下: ``` +------------+------------------------------+-----------------------+--------+ @@ -258,7 +256,7 @@ SELECT id, title, type, price FROM books ORDER BY published_at DESC LIMIT 5; 5 rows in set (0.01 sec) ``` -随后通过 `COMMIT;` 语句提交事务,当事务结束后,又可以重新读取到最新数据: +在使用 `COMMIT;` 语句提交事务后,您可以读取最新数据。 ``` +------------+------------------------------+-----------------------+--------+ @@ -276,7 +274,7 @@ SELECT id, title, type, price FROM books ORDER BY published_at DESC LIMIT 5;
-在 Java 中,可以先定义一个事务的工具类,将开启事务级别 Stale Read 的命令封装成工具方法。 +您可以定义一个事务的辅助类,该类将在事务级别启用历史读取的命令封装为辅助方法。 ```java public static class StaleReadHelper { @@ -293,17 +291,17 @@ public static class StaleReadHelper { } ``` -然后在 `BookDAO` 类当中定义一个通过事务开启 Stale Read 功能的方法,在方法内查询最新的书籍列表,但是不再在查询语句中添加 `AS OF TIMESTAMP`。 +然后在 `BookDAO` 类中定义一个方法,通过事务启用历史读取功能。使用该方法进行查询,而不是在查询语句中添加 `AS OF TIMESTAMP`。 ```java public class BookDAO { - // Omit some code... + // 省略部分代码... public List getTop5LatestBooksWithTxnStaleRead(Integer seconds) throws SQLException { List books = new ArrayList<>(); try (Connection conn = ds.getConnection()) { - // Start a read only transaction. + // 启动只读事务 TxnHelper.startTxnWithStaleRead(conn, seconds); Statement stmt = conn.createStatement(); @@ -319,7 +317,7 @@ public class BookDAO { books.add(book); } - // Commit transaction. + // 提交事务 conn.commit(); } catch (SQLException e) { if ("HY000".equals(e.getSQLState()) && e.getErrorCode() == 1105) { @@ -347,17 +345,17 @@ if (top5LatestBooks.size() > 0) { top5LatestBooks = bookDAO.getTop5LatestBooks(); System.out.println("The latest book price (after update): " + top5LatestBooks.get(0).getPrice()); - // Use the stale read. + // 使用历史读取 top5LatestBooks = bookDAO.getTop5LatestBooksWithTxnStaleRead(5); System.out.println("The latest book price (maybe stale): " + top5LatestBooks.get(0).getPrice()); - // After the stale read transaction is committed. + // 在历史读取事务提交后 top5LatestBooks = bookDAO.getTop5LatestBooks(); System.out.println("The latest book price (after the transaction commit): " + top5LatestBooks.get(0).getPrice()); } ``` -输出结果: +结果如下: ``` The latest book price (before update): 100.00 @@ -369,12 +367,12 @@ The latest book price (after the transaction commit): 150
-通过 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 语句,你可以将当前事务或下一个事务设置为基于指定历史时间的只读事务。该事务将会基于所提供的历史时间来读取历史数据。 +使用 `SET TRANSACTION READ ONLY AS OF TIMESTAMP` 语句,您可以将已打开的事务或下一个事务设置为基于指定历史时间的只读事务。该事务将基于提供的历史时间读取历史数据。
-例如,可以通过下面这个 SQL 将已开启的事务切换到只读模式,通过 `AS OF TIMESTAMP` 语句开启能够读取 5 秒前的历史数据 Stale Read 功能。 +例如,您可以使用以下 `AS OF TIMESTAMP` 语句将正在进行的事务切换到只读模式,并读取 5 秒前的历史数据。 ```sql SET TRANSACTION READ ONLY AS OF TIMESTAMP NOW() - INTERVAL 5 SECOND; @@ -383,7 +381,7 @@ SET TRANSACTION READ ONLY AS OF TIMESTAMP NOW() - INTERVAL 5 SECOND;
-可以先定义一个事务的工具类,将开启事务级别 Stale Read 的命令封装成工具方法。 +您可以定义一个事务的辅助类,该类将在事务级别启用历史读取的命令封装为辅助方法。 ```java public static class TxnHelper { @@ -399,20 +397,21 @@ public static class TxnHelper { } ``` -然后在 `BookDAO` 类当中定义一个通过事务开启 Stale Read 功能的方法,在方法内查询最新的书籍列表,但是不再在查询语句中添加 `AS OF TIMESTAMP`。 +然后在 `BookDAO` 类中定义一个方法,通过事务启用历史读取功能。使用该方法进行查询,而不是在查询语句中添加 `AS OF TIMESTAMP`。 ```java public class BookDAO { - // Omit some code... + // 省略部分代码... public List getTop5LatestBooksWithTxnStaleRead2(Integer seconds) throws SQLException { List books = new ArrayList<>(); try (Connection conn = ds.getConnection()) { - // Start a read only transaction. - conn.setAutoCommit(false); StaleReadHelper.setTxnWithStaleRead(conn, seconds); + // 启动只读事务 + conn.setAutoCommit(false); + Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(""" SELECT id, title, type, price FROM books ORDER BY published_at DESC LIMIT 5; @@ -426,7 +425,7 @@ public class BookDAO { books.add(book); } - // Commit transaction. + // 提交事务 conn.commit(); } catch (SQLException e) { if ("HY000".equals(e.getSQLState()) && e.getErrorCode() == 1105) { @@ -447,20 +446,20 @@ public class BookDAO { ## 会话级别 -为支持读取历史版本数据,TiDB 从 5.4 版本起引入了一个新的系统变量 `tidb_read_staleness`。系统变量 `tidb_read_staleness` 用于设置当前会话允许读取的历史数据范围,其数据类型为 int,作用域为 SESSION。 +为了支持读取历史数据,TiDB 从 v5.4 开始引入了一个新的系统变量 `tidb_read_staleness`。您可以使用它来设置当前会话允许读取的历史数据范围。其数据类型为 `int`,作用域为 `SESSION`。
-在会话中开启 Stale Read: +在会话中启用历史读取: ```sql SET @@tidb_read_staleness="-5"; ``` -比如,如果该变量的值设置为 -5,TiDB 会在 5 秒时间范围内,保证 TiKV 或者 TiFlash 拥有对应历史版本数据的情况下,选择尽可能新的一个时间戳。 +例如,如果值设置为 `-5`,并且 TiKV 或 TiFlash 有相应的历史数据,TiDB 会在 5 秒时间范围内选择一个尽可能新的时间戳。 -关闭会话当中的 Stale Read: +在会话中禁用历史读取: ```sql set @@tidb_read_staleness=""; @@ -469,8 +468,6 @@ set @@tidb_read_staleness="";
-在 Java 中示例如下: - ```java public static class StaleReadHelper{ @@ -495,8 +492,22 @@ public static class StaleReadHelper{
-## 扩展阅读 +## 阅读更多 + +- [历史读取的使用场景](/stale-read.md) +- [使用 `AS OF TIMESTAMP` 子句读取历史数据](/as-of-timestamp.md) +- [使用 `tidb_read_staleness` 系统变量读取历史数据](/tidb-read-staleness.md) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -- [Stale Read 功能的使用场景](/stale-read.md) -- [使用 AS OF TIMESTAMP 语法读取历史数据](/as-of-timestamp.md#语法方式) -- [通过系统变量 tidb_read_staleness 读取历史数据](/tidb-read-staleness.md) + diff --git a/develop/dev-guide-use-subqueries.md b/develop/dev-guide-use-subqueries.md index 005eb3cb3794..068baf952118 100644 --- a/develop/dev-guide-use-subqueries.md +++ b/develop/dev-guide-use-subqueries.md @@ -1,39 +1,39 @@ --- title: 子查询 -summary: 介绍 TiDB 子查询功能。 +summary: 了解如何在 TiDB 中使用子查询。 --- # 子查询 -本章将介绍 TiDB 中的子查询功能。 +本文档介绍 TiDB 中的子查询语句和类别。 ## 概述 -子查询是嵌套在另一个查询中的 SQL 表达式,借助子查询,可以在一个查询当中使用另外一个查询的查询结果。 +子查询是在另一个 SQL 查询中的查询。通过子查询,查询结果可以在另一个查询中使用。 -下面将以 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用为例对子查询展开介绍: +以下以 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序为例介绍子查询。 ## 子查询语句 -通常情况下,子查询语句分为如下几种形式: +在大多数情况下,有五种类型的子查询: -- 标量子查询(Scalar Subquery),如 `SELECT (SELECT s1 FROM t2) FROM t1`。 -- 派生表(Derived Tables),如 `SELECT t1.s1 FROM (SELECT s1 FROM t2) t1`。 -- 存在性测试(Existential Test),如 `WHERE NOT EXISTS(SELECT ... FROM t2)`,`WHERE t1.a IN (SELECT ... FROM t2)`。 -- 集合比较(Quantified Comparison),如 `WHERE t1.a = ANY(SELECT ... FROM t2)`。 -- 作为比较运算符操作数的子查询,如 `WHERE t1.a > (SELECT ... FROM t2)`。 +- 标量子查询,例如 `SELECT (SELECT s1 FROM t2) FROM t1`。 +- 派生表,例如 `SELECT t1.s1 FROM (SELECT s1 FROM t2) t1`。 +- 存在性测试,例如 `WHERE NOT EXISTS(SELECT ... FROM t2)`,`WHERE t1.a IN (SELECT ... FROM t2)`。 +- 量化比较,例如 `WHERE t1.a = ANY(SELECT ... FROM t2)`,`WHERE t1.a = ANY(SELECT ... FROM t2)`。 +- 作为比较运算符操作数的子查询,例如 `WHERE t1.a > (SELECT ... FROM t2)`。 -## 子查询的分类 +## 子查询类别 -一般来说,可以将子查询分为关联子查询([Correlated Subquery](https://en.wikipedia.org/wiki/Correlated_subquery))和无关联子查询 (Self-contained Subquery) 两大类,TiDB 对于这两类子查询的处理方式是不一样的。 +子查询可以分为[相关子查询](https://en.wikipedia.org/wiki/Correlated_subquery)和独立子查询。TiDB 对这两种类型的处理方式不同。 -判断是否为关联子查询的依据在于子查询当中是否引用了外层查询的列。 +子查询是相关的还是独立的取决于它是否引用了外部查询中使用的列。 -### 无关联子查询 +### 独立子查询 -对于将子查询作为比较运算符 (`>` / `>=`/ `<` / `<=` / `=` / `!=`) 操作数的这类无关联子查询而言,内层子查询只需要进行一次查询,TiDB 在生成执行计划阶段会将内层子查询改写为常量。 +对于使用子查询作为比较运算符(`>`、`>=`、`<`、`<=`、`=` 或 `!=`)操作数的独立子查询,内部子查询只查询一次,TiDB 在执行计划阶段将其重写为常量。 -例如,想要查找 `authors` 表当中年龄大于总体平均年龄的作家,可以通过将子查询作为比较操作符的操作数来实现: +例如,要查询 `authors` 表中年龄大于平均年龄的作者,你可以使用子查询作为比较运算符的操作数。 ```sql SELECT * FROM authors a1 WHERE (IFNULL(a1.death_year, YEAR(NOW())) - a1.birth_year) > ( @@ -44,20 +44,20 @@ SELECT * FROM authors a1 WHERE (IFNULL(a1.death_year, YEAR(NOW())) - a1.birth_ye ) ``` -在 TiDB 执行上述查询的时候会先执行一次内层子查询: +在 TiDB 执行上述查询之前,内部子查询会先执行: ```sql SELECT AVG(IFNULL(a2.death_year, YEAR(NOW())) - a2.birth_year) AS average_age FROM authors a2; ``` -假设查询得到的结果为 34,即总体平均年龄为 34,34 将作为常量替换掉原来的子查询。 +假设查询结果为 34,即平均年龄为 34,34 将作为常量替换原始子查询。 ```sql SELECT * FROM authors a1 WHERE (IFNULL(a1.death_year, YEAR(NOW())) - a1.birth_year) > 34; ``` -运行结果为: +结果如下: ``` +--------+-------------------+--------+------------+------------+ @@ -79,15 +79,15 @@ WHERE (IFNULL(a1.death_year, YEAR(NOW())) - a1.birth_year) > 34; ... ``` -对于存在性测试和集合比较两种情况下的无关联列子查询,TiDB 会将其进行改写和等价替换以获得更好的执行性能,你可以通过阅读[子查询相关的优化](/subquery-optimization.md)章节来了解更多的实现细节。 +对于存在性测试和量化比较等独立子查询,TiDB 会将其重写并替换为等效查询以获得更好的性能。更多信息,请参阅[子查询相关优化](/subquery-optimization.md)。 -## 关联子查询 +### 相关子查询 -对于关联子查询而言,由于内层的子查询引用外层查询的列,子查询需要对外层查询得到的每一行都执行一遍,也就是说假设外层查询得到一千万的结果,那么子查询也会被执行一千万次,这会导致查询需要消耗更多的时间和资源。 +对于相关子查询,由于内部子查询引用了外部查询的列,每个子查询都会为外部查询的每一行执行一次。也就是说,假设外部查询得到 1000 万个结果,子查询也会执行 1000 万次,这将消耗更多的时间和资源。 -因此在处理过程中,TiDB 会尝试对[关联子查询去关联](/correlated-subquery-optimization.md),以从执行计划层面上提高查询效率。 +因此,在处理过程中,TiDB 会尝试在执行计划层面[去关联化相关子查询](/correlated-subquery-optimization.md)以提高查询效率。 -例如,假设想要查找那些大于其它相同性别作家的平均年龄的的作家,SQL 语句可以这样写: +以下语句用于查询年龄大于同性别其他作者平均年龄的作者。 ```sql SELECT * FROM authors a1 WHERE (IFNULL(a1.death_year, YEAR(NOW())) - a1.birth_year) > ( @@ -101,7 +101,7 @@ SELECT * FROM authors a1 WHERE (IFNULL(a1.death_year, YEAR(NOW())) - a1.birth_ye ); ``` -TiDB 在处理该 SQL 语句是会将其改写为等价的 Join 查询: +TiDB 将其重写为等效的 `join` 查询: ```sql SELECT * @@ -121,10 +121,24 @@ WHERE AND (IFNULL(a1.death_year, YEAR(NOW())) - a1.birth_year) > a2.average_age; ``` -作为最佳实践,在实际开发当中,建议在明确知道有更好的等价写法时,尽量避免通过关联子查询来进行查询。 +作为最佳实践,在实际开发中,如果可以使用另一个具有更好性能的等效查询,建议避免通过相关子查询进行查询。 -## 扩展阅读 +## 阅读更多 -- [子查询相关的优化](/subquery-optimization.md) -- [关联子查询去关联](/correlated-subquery-optimization.md) -- [TiDB 中的子查询优化技术](https://pingcap.com/zh/blog/tidb-optimization-for-subquery) +- [子查询相关优化](/subquery-optimization.md) +- [相关子查询的去关联化](/correlated-subquery-optimization.md) +- [TiDB 中的子查询优化](https://www.pingcap.com/blog/subquery-optimization-in-tidb/) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/develop/dev-guide-use-temporary-tables.md b/develop/dev-guide-use-temporary-tables.md index 4d449aa53a38..0c927f75e5f9 100644 --- a/develop/dev-guide-use-temporary-tables.md +++ b/develop/dev-guide-use-temporary-tables.md @@ -1,13 +1,15 @@ --- title: 临时表 -summary: 介绍 TiDB 临时表创建、删除、限制。 +summary: 了解如何创建、查看、查询和删除临时表。 --- # 临时表 -临时表可以被认为是一种复用查询结果的技术。 +临时表可以被视为重用查询结果的一种技术。 -假设希望知道 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用当中最年长的作家们的一些情况,可能需要编写多个查询,而这些查询都需要使用到这个最年长作家列表。可以通过下面的 SQL 语句从 `authors` 表当中找出最年长的前 50 位作家作为研究对象。 +如果您想了解 [Bookshop](/develop/dev-guide-bookshop-schema-design.md) 应用程序中年龄最大的作者的相关信息,您可能会编写多个使用年龄最大作者列表的查询。 + +例如,您可以使用以下语句从 `authors` 表中获取年龄最大的前 50 位作者: ```sql SELECT a.id, a.name, (IFNULL(a.death_year, YEAR(NOW())) - a.birth_year) AS age @@ -16,7 +18,7 @@ ORDER BY age DESC LIMIT 50; ``` -查询结果如下: +结果如下: ``` +------------+---------------------+------+ @@ -35,27 +37,27 @@ LIMIT 50; 50 rows in set (0.01 sec) ``` -在找到这 50 位最年长的作家后,希望缓存这个查询结果,以便后续的查询能够方便地使用到这组数据。如果使用一般的数据库表进行存储的话,在创建这些表时,需要考虑如何避免不同会话之间的表重名问题,而且可能在一批查询结束之后就不再需要这些表了,还需要及时地对这些中间结果表进行清理。 +为了便于后续查询,您需要缓存此查询的结果。当使用普通表进行存储时,您应该注意如何避免不同会话之间的表名重复问题,以及需要及时清理中间结果,因为这些表在批量查询后可能不会再被使用。 ## 创建临时表 -为了满足这类缓存中间结果的需求,TiDB 在 v5.3.0 版本中引入了临时表功能,对于临时表当中的本地临时表而言,TiDB 将会在会话结束的一段时间后自动清理这些已经没用的临时表,用户无需担心中间结果表的增多会带来管理上的麻烦。 +为了缓存中间结果,TiDB v5.3.0 引入了临时表功能。TiDB 会在会话结束后自动删除本地临时表,这使您不必担心中间结果增加带来的管理麻烦。 -### 临时表类型 +### 临时表的类型 -TiDB 的临时表分为本地临时表和全局临时表: +TiDB 中的临时表分为两种类型:本地临时表和全局临时表。 -- 本地临时表的表定义和表内数据只对当前会话可见,适用于暂存会话内的中间数据。 -- 全局临时表的表定义对整个 TiDB 集群可见,表内数据只对当前事务可见,适用于暂存事务内的中间数据。 +- 对于本地临时表,表定义和表中的数据仅对当前会话可见。这种类型适合临时存储会话中的中间数据。 +- 对于全局临时表,表定义对整个 TiDB 集群可见,而表中的数据仅对当前事务可见。这种类型适合临时存储事务中的中间数据。 ### 创建本地临时表 -在创建本地临时表前,你需要给当前数据库用户添加上 `CREATE TEMPORARY TABLES` 权限。 +在创建本地临时表之前,您需要为当前数据库用户添加 `CREATE TEMPORARY TABLES` 权限。
-在 SQL 中,通过 `CREATE TEMPORARY TABLE ` 语句创建临时表,默认临时表的类型为本地临时表,它只能被当前会话所访问。 +您可以使用 `CREATE TEMPORARY TABLE ` 语句创建临时表。默认类型是本地临时表,仅对当前会话可见。 ```sql CREATE TEMPORARY TABLE top_50_eldest_authors ( @@ -66,7 +68,7 @@ CREATE TEMPORARY TABLE top_50_eldest_authors ( ); ``` -在创建完临时表后,你可以通过 `INSERT INTO table_name SELECT ...` 语句,将上述查询得到的结果导入到刚刚创建的临时表当中。 +创建临时表后,您可以使用 `INSERT INTO table_name SELECT ...` 语句将上述查询的结果插入到刚刚创建的临时表中。 ```sql INSERT INTO top_50_eldest_authors @@ -76,7 +78,7 @@ ORDER BY age DESC LIMIT 50; ``` -运行结果为: +结果如下: ``` Query OK, 50 rows affected (0.03 sec) @@ -86,8 +88,6 @@ Records: 50 Duplicates: 0 Warnings: 0
-在 Java 中创建本地临时表的示例如下: - ```java public List getTop50EldestAuthorInfo() throws SQLException { List authors = new ArrayList<>(); @@ -133,7 +133,7 @@ public List getTop50EldestAuthorInfo() throws SQLException {
-在 SQL 中,你可以通过加上 `GLOBAL` 关键字来声明你所创建的是全局临时表。创建全局临时表时必须在末尾 `ON COMMIT DELETE ROWS` 修饰,这表明该全局数据表的所有数据行将在事务结束后被删除。 +要创建全局临时表,您可以添加 `GLOBAL` 关键字并以 `ON COMMIT DELETE ROWS` 结尾,这表示表将在当前事务结束后被删除。 ```sql CREATE GLOBAL TEMPORARY TABLE IF NOT EXISTS top_50_eldest_authors_global ( @@ -144,12 +144,12 @@ CREATE GLOBAL TEMPORARY TABLE IF NOT EXISTS top_50_eldest_authors_global ( ) ON COMMIT DELETE ROWS; ``` -在对全局临时表导入数据时,你需要特别注意,你必须通过 `BEGIN` 显式声明事务的开始。否则导入的数据在 `INSERT INTO` 语句执行后就清除掉,因为 Auto Commit 模式下,`INSERT INTO` 语句的执行结束,事务会自动被提交,事务结束,全局临时表的数据便被清空了。 +向全局临时表插入数据时,必须通过 `BEGIN` 显式声明事务的开始。否则,数据将在 `INSERT INTO` 语句执行后被清除。因为在自动提交模式下,事务会在 `INSERT INTO` 语句执行后自动提交,而全局临时表会在事务结束时被清除。
-在 Java 中使用全局临时表时,你需要将 Auto Commit 模式先关闭。在 Java 语言当中,你可以通过 `conn.setAutoCommit(false);` 语句来实现,当你使用完成后,可以通过 `conn.commit();` 显式地提交事务。事务在提交或取消后,在事务过程中对全局临时表添加的数据将会被清除。 +使用全局临时表时,您需要先关闭自动提交模式。在 Java 中,您可以使用 `conn.setAutoCommit(false);` 语句来实现,并可以使用 `conn.commit();` 显式提交事务。事务期间添加到全局临时表的数据将在事务提交或取消后被清除。 ```java public List getTop50EldestAuthorInfo() throws SQLException { @@ -194,11 +194,11 @@ public List getTop50EldestAuthorInfo() throws SQLException {
-## 查看临时表信息 +## 查看临时表 -通过 `SHOW [FULL] TABLES` 语句可以查看到已经创建的全局临时表,但是无法看到本地临时表的信息,TiDB 暂时也没有类似的 `information_schema.INNODB_TEMP_TABLE_INFO` 系统表存放临时表的信息。 +使用 `SHOW [FULL] TABLES` 语句,您可以查看现有的全局临时表列表,但在列表中看不到任何本地临时表。目前,TiDB 没有类似 `information_schema.INNODB_TEMP_TABLE_INFO` 的系统表来存储临时表信息。 -例如,你可以在 table 列表当中查看到全局临时表 `top_50_eldest_authors_global`,但是无法查看到 `top_50_eldest_authors` 表。 +例如,您可以在表列表中看到全局临时表 `top_50_eldest_authors_global`,但看不到 `top_50_eldest_authors` 表。 ``` +-------------------------------+------------+ @@ -217,13 +217,13 @@ public List getTop50EldestAuthorInfo() throws SQLException { ## 查询临时表 -在临时表准备就绪之后,你便可以像对一般数据表一样对临时表进行查询: +临时表准备就绪后,您可以像查询普通数据表一样查询它: ```sql SELECT * FROM top_50_eldest_authors; ``` -你可以通过[表连接](/develop/dev-guide-join-tables.md)将临时表中的数据引用到你的查询当中: +您可以通过[多表联接查询](/develop/dev-guide-join-tables.md)在查询中引用临时表中的数据: ```sql EXPLAIN SELECT ANY_VALUE(ta.id) AS author_id, ANY_VALUE(ta.age), ANY_VALUE(ta.name), COUNT(*) AS books @@ -232,19 +232,19 @@ LEFT JOIN book_authors ba ON ta.id = ba.author_id GROUP BY ta.id; ``` -与[视图](/develop/dev-guide-use-views.md)有所不同,在对临时表进行查询时,不会再执行导入数据时所使用的原始查询,而是直接从临时表中获取数据。在一些情况下,这会帮助你提高查询的效率。 +与[视图](/develop/dev-guide-use-views.md)不同,查询临时表时直接从临时表获取数据,而不是执行用于数据插入的原始查询。在某些情况下,这可以提高查询性能。 ## 删除临时表 -本地临时表会在**会话**结束后连同数据和表结构都进行自动清理。全局临时表在**事务**结束后会自动清除数据,但是表结构依然保留,需要手动删除。 +会话中的本地临时表在**会话**结束后会自动删除,包括数据和表结构。事务中的全局临时表在**事务**结束时会自动清除数据,但表结构保留,需要手动删除。 -你可以通过 `DROP TABLE` 或 `DROP TEMPORARY TABLE` 语句手动删除**本地临时表**。例如: +要手动删除本地临时表,请使用 `DROP TABLE` 或 `DROP TEMPORARY TABLE` 语法。例如: ```sql DROP TEMPORARY TABLE top_50_eldest_authors; ``` -你还可以通过 `DROP TABLE` 或 `DROP GLOBAL TEMPORARY TABLE` 语句手动删除**全局临时表**。例如: +要手动删除全局临时表,请使用 `DROP TABLE` 或 `DROP GLOBAL TEMPORARY TABLE` 语法。例如: ```sql DROP GLOBAL TEMPORARY TABLE top_50_eldest_authors_global; @@ -252,8 +252,22 @@ DROP GLOBAL TEMPORARY TABLE top_50_eldest_authors_global; ## 限制 -关于 TiDB 在临时表功能上的一些限制,你可以通过阅读参考文档中的[临时表与其他 TiDB 功能的兼容性限制](/temporary-tables.md#与其他-tidb-功能的兼容性限制)小节进行了解。 +有关 TiDB 中临时表的限制,请参见[与其他 TiDB 功能的兼容性限制](/temporary-tables.md#compatibility-restrictions-with-other-tidb-features)。 + +## 阅读更多 + +- [临时表](/temporary-tables.md) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + -## 扩展阅读 +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 -- [临时表](/temporary-tables.md) \ No newline at end of file + diff --git a/develop/dev-guide-use-views.md b/develop/dev-guide-use-views.md index f7fd5ddcfac7..eaf44d64a5b4 100644 --- a/develop/dev-guide-use-views.md +++ b/develop/dev-guide-use-views.md @@ -1,30 +1,32 @@ --- title: 视图 -summary: 介绍 TiDB 中的视图功能。 +summary: 了解如何在 TiDB 中使用视图。 --- # 视图 -本章将介绍 TiDB 中的视图功能。 +本文档介绍如何在 TiDB 中使用视图。 ## 概述 -TiDB 支持视图,视图是一张虚拟表,该虚拟表的结构由创建视图时的 `SELECT` 语句定义。 +TiDB 支持视图。视图充当虚拟表,其架构由创建视图的 `SELECT` 语句定义。 -- 通过视图可以对用户只暴露安全的字段及数据,进而保证底层表的敏感字段及数据的安全。 -- 将频繁出现的复杂查询定义为视图,可以使复杂查询更加简单便捷。 +- 你可以创建视图来仅向用户公开安全的字段和数据,这确保了底层表中敏感字段和数据的安全性。 +- 你可以为经常使用的复杂查询创建视图,使复杂查询更简单和方便。 ## 创建视图 -在 TiDB 当中,可以通过 `CREATE VIEW` 语句来将某个较为复杂的查询定义为视图,其语法如下: +在 TiDB 中,可以使用 `CREATE VIEW` 语句将复杂查询定义为视图。语法如下: ```sql CREATE VIEW view_name AS query; ``` -请注意,创建的视图名称不能与已有的视图或表重名。 +注意,你不能创建与现有视图或表同名的视图。 -例如,在[多表连接查询](/develop/dev-guide-join-tables.md) 章节当中,通过 `JOIN` 语句连接 `books` 表和 `ratings` 表查询到了带有平均评分的书籍列表。为了方便后续查询,可以将该查询语句定义为一个视图,SQL 语句如下所示: +例如,[多表联接查询](/develop/dev-guide-join-tables.md)通过 `JOIN` 语句联接 `books` 表和 `ratings` 表,获取带有平均评分的书籍列表。 + +为了便于后续查询,你可以使用以下语句将查询定义为视图: ```sql CREATE VIEW book_with_ratings AS @@ -36,20 +38,20 @@ GROUP BY b.id; ## 查询视图 -视图创建完成后,便可以使用 `SELECT` 语句像查询一般数据表一样查询视图。 +创建视图后,你可以像查询普通表一样使用 `SELECT` 语句查询视图。 ```sql SELECT * FROM book_with_ratings LIMIT 10; ``` -TiDB 在执行查询视图语句时,会将视图展开成创建视图时定义的 `SELECT` 语句,进而执行展开后的查询语句。 +当 TiDB 查询视图时,它会查询与该视图关联的 `SELECT` 语句。 ## 更新视图 -目前 TiDB 中的视图不支持 `ALTER VIEW view_name AS query;` 语法,你可以通过以下两种方式实现视图的 “更新”: +目前,TiDB 中的视图不支持 `ALTER VIEW view_name AS query;`,你可以通过以下两种方式"更新"视图: -- 先 `DROP VIEW view_name;` 语句删除旧视图,再通过 `CREATE VIEW view_name AS query;` 语句创建新视图的方式来更新视图。 -- 使用 `CREATE OR REPLACE VIEW view_name AS query;` 语句覆盖已存在的同名视图。 +- 使用 `DROP VIEW view_name;` 语句删除旧视图,然后使用 `CREATE VIEW view_name AS query;` 语句创建新视图来更新视图。 +- 使用 `CREATE OR REPLACE VIEW view_name AS query;` 语句覆盖同名的现有视图。 ```sql CREATE OR REPLACE VIEW book_with_ratings AS @@ -67,7 +69,7 @@ GROUP BY b.id; SHOW CREATE VIEW book_with_ratings\G ``` -运行结果为: +结果如下: ``` *************************** 1. row *************************** @@ -84,7 +86,7 @@ collation_connection: utf8mb4_general_ci SELECT * FROM information_schema.views WHERE TABLE_NAME = 'book_with_ratings'\G ``` -运行结果为: +结果如下: ``` *************************** 1. row *************************** @@ -103,20 +105,34 @@ COLLATION_CONNECTION: utf8mb4_general_ci ## 删除视图 -通过 `DROP VIEW view_name;` 语句可以删除已经创建的视图。 +使用 `DROP VIEW view_name;` 语句删除视图。 ```sql DROP VIEW book_with_ratings; ``` -## 局限性 +## 限制 -关于局限性,你可以通过阅读参考文档当中的[视图](/views.md#局限性)章节进行了解。 +有关 TiDB 中视图的限制,请参见[视图的限制](/views.md#limitations)。 -## 扩展阅读 +## 阅读更多 - [视图](/views.md) - [CREATE VIEW 语句](/sql-statements/sql-statement-create-view.md) - [DROP VIEW 语句](/sql-statements/sql-statement-drop-view.md) -- [用 EXPLAIN 查看带视图的 SQL 执行计划](/explain-views.md) -- [TiFlink: 使用 TiKV 和 Flink 实现强一致的物化视图](https://github.com/tiflink/tiflink) +- [使用视图的 EXPLAIN 语句](/explain-views.md) +- [TiFlink:使用 TiKV 和 Flink 的强一致性物化视图](https://github.com/tiflink/tiflink) + +## 需要帮助? + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](/support.md)。 + + + + + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 + + diff --git a/explain-aggregation.md b/explain-aggregation.md index 41e49472b97c..f1800347214b 100644 --- a/explain-aggregation.md +++ b/explain-aggregation.md @@ -1,18 +1,11 @@ --- -title: 用 EXPLAIN 查看聚合查询的执行计划 -summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划信息。 +title: 使用聚合的 EXPLAIN 语句 +summary: 了解 TiDB 中 `EXPLAIN` 语句返回的执行计划信息。 --- -# 用 EXPLAIN 查看聚合查询执行计划 +# 使用聚合的 EXPLAIN 语句 -SQL 查询中可能会使用聚合计算,可以通过 `EXPLAIN` 语句来查看聚合查询的执行计划。本文提供多个示例,以帮助用户理解聚合查询是如何执行的。 - -SQL 优化器会选择以下任一算子实现数据聚合: - -- Hash Aggregation -- Stream Aggregation - -为了提高查询效率,数据聚合在 Coprocessor 层和 TiDB 层均会执行。现有示例如下: +在进行数据聚合时,SQL 优化器会选择使用 Hash 聚合或者流式聚合操作符。为了提高查询效率,聚合操作会同时在 coprocessor 和 TiDB 层进行。考虑以下示例: {{< copyable "sql" >}} @@ -38,7 +31,7 @@ SELECT SLEEP(1); ANALYZE TABLE t1; ``` -以上示例创建表格 `t1` 并插入数据后,再执行 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) 语句。从以下 `SHOW TABLE REGIONS` 的执行结果可知,表 `t1` 被切分为多个 Region: +从 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) 的输出可以看到,该表被分割成多个 Region: {{< copyable "sql" >}} @@ -58,7 +51,7 @@ SHOW TABLE t1 REGIONS; 4 rows in set (0.00 sec) ``` -使用 `EXPLAIN` 查看以下聚合语句的执行计划。可以看到 `└─StreamAgg_8` 算子先执行在 TiKV 内每个 Region 上,然后 TiKV 的每个 Region 会返回一行数据给 TiDB,TiDB 在 `StreamAgg_16` 算子上对每个 Region 返回的数据进行聚合: +使用 `EXPLAIN` 查看以下聚合语句,可以看到 `└─StreamAgg_8` 首先在 TiKV 的每个 Region 内执行。然后每个 TiKV Region 会向 TiDB 返回一行数据,TiDB 在 `StreamAgg_16` 中聚合来自每个 Region 的数据: {{< copyable "sql" >}} @@ -78,7 +71,7 @@ EXPLAIN SELECT COUNT(*) FROM t1; 4 rows in set (0.00 sec) ``` -同样,通过执行 `EXPLAIN ANALYZE` 语句可知,`actRows` 与 `SHOW TABLE REGIONS` 返回结果中的 Region 数匹配,这是因为执行使用了 `TableFullScan` 全表扫并且没有二级索引: +这在 `EXPLAIN ANALYZE` 中最容易观察到,其中 `actRows` 与 `SHOW TABLE REGIONS` 中的 Region 数量匹配,因为使用了 `TableFullScan` 且没有二级索引: ```sql EXPLAIN ANALYZE SELECT COUNT(*) FROM t1; @@ -96,11 +89,11 @@ EXPLAIN ANALYZE SELECT COUNT(*) FROM t1; 4 rows in set (0.01 sec) ``` -## Hash Aggregation +## Hash 聚合 -Hash Aggregation 算法在执行聚合时使用 Hash 表存储中间结果。此算法采用多线程并发优化,执行速度快,但与 Stream Aggregation 算法相比会消耗较多内存。 +Hash 聚合算法使用哈希表来存储执行聚合时的中间结果。它使用多个线程并行执行,但比流式聚合消耗更多内存。 -下面是一个使用 Hash Aggregation(即 `HashAgg` 算子)的例子: +以下是 `HashAgg` 操作符的示例: {{< copyable "sql" >}} @@ -120,13 +113,13 @@ EXPLAIN SELECT /*+ HASH_AGG() */ count(*) FROM t1; 4 rows in set (0.00 sec) ``` -`operator info` 列显示,用于聚合数据的 Hash 函数为 `funcs:count(1)->Column#6`。 +`operator info` 显示用于聚合数据的哈希函数是 `funcs:count(1)->Column#6`。 -## Stream Aggregation +## 流式聚合 -Stream Aggregation 算法通常会比 Hash Aggregation 算法占用更少的内存。但是此算法要求数据按顺序发送,以便对依次到达的值实现流式数据聚合。 +流式聚合算法通常比 Hash 聚合消耗更少的内存。但是,这个操作符要求数据是有序发送的,这样它才能在数据到达时进行流式处理并应用聚合。 -下面是一个使用 Stream Aggregation 的例子: +考虑以下示例: {{< copyable "sql" >}} @@ -154,7 +147,7 @@ Records: 5 Duplicates: 0 Warnings: 0 5 rows in set (0.00 sec) ``` -以上示例中,可以在 `col1` 上添加索引来消除 `└─Sort_13` 算子。添加索引后,TiDB 就可以按顺序读取数据并消除 `└─Sort_13` 算子。 +在这个示例中,通过在 `col1` 上添加索引可以消除 `└─Sort_13` 操作符。一旦添加了索引,数据就可以按顺序读取,`└─Sort_13` 操作符就被消除了: {{< copyable "sql" >}} @@ -178,15 +171,15 @@ Query OK, 0 rows affected (0.28 sec) 5 rows in set (0.00 sec) ``` -## 多维度数据聚合 ROLLUP +## 使用 ROLLUP 进行多维数据聚合 -自 v7.4.0 起,TiDB 的 `GROUP BY` 子句支持 `WITH ROLLUP` 修饰符。 +从 v7.4.0 版本开始,TiDB 的 `GROUP BY` 子句支持 `WITH ROLLUP` 修饰符。 -你可以在 `GROUP BY` 子句中指定一个或多个列,形成一个分组列表,然后添加 `WITH ROLLUP` 修饰符。TiDB 将会按照分组列表中的列进行多维度的递减分组,并在输出中为你提供各个分组数据的汇总结果。 +在 `GROUP BY` 子句中,你可以指定一个或多个列作为分组列表,并在列表后添加 `WITH ROLLUP` 修饰符。然后,TiDB 将基于分组列表中的列进行多维度降序分组,并在输出中为你提供每个分组的汇总结果。 -> **注意** +> **注意:** > -> TiDB 暂不支持 Cube 语法; TiDB 目前仅在 MPP 模式下支持为 `WITH ROLLUP` 语法生成有效的执行计划。 +> 目前,TiDB 不支持 Cube 语法,并且 TiDB 仅在 TiFlash MPP 模式下支持为 `WITH ROLLUP` 语法生成有效的执行计划。 ```sql explain SELECT year, month, grouping(year), grouping(month), SUM(profit) AS profit FROM bank GROUP BY year, month WITH ROLLUP; @@ -207,16 +200,6 @@ explain SELECT year, month, grouping(year), grouping(month), SUM(profit) AS prof 10 rows in set (0.05 sec) ``` -该语句的 SQL 聚合可以按照 `GROUP BY year, month WITH ROLLUP` 语法在 {year, month}、{year}、{} 这 3 个分组中分别计算并连接结果。 - -更多信息,请参考 [GROUP BY 修饰符](/functions-and-operators/group-by-modifier.md)。 - -## 其他类型查询的执行计划 +根据上述语句中的 `GROUP BY year, month WITH ROLLUP` 语法,该 SQL 语句的聚合结果可以按照 `{year, month}`、`{year}` 和 `{}` 三个分组分别计算并连接。 -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [索引查询的执行计划](/explain-indexes.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [视图查询的执行计划](/explain-views.md) -+ [分区查询的执行计划](/explain-partitions.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) +更多信息,请参见 [GROUP BY 修饰符](/functions-and-operators/group-by-modifier.md)。 diff --git a/explain-index-merge.md b/explain-index-merge.md index 6359e1d9e5d8..b3c2be69e07e 100644 --- a/explain-index-merge.md +++ b/explain-index-merge.md @@ -1,19 +1,17 @@ --- -title: 用 EXPLAIN 查看索引合并的 SQL 执行计划 -summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划信息。 +title: 使用索引合并的 EXPLAIN 语句 +summary: 了解 TiDB 中 `EXPLAIN` 语句返回的执行计划信息。 --- -# 用 EXPLAIN 查看索引合并的 SQL 执行计划 +# 使用索引合并的 EXPLAIN 语句 -索引合并是从 TiDB v4.0 起引入的一种新的表访问方式。在这种访问方式下,TiDB 优化器可以选择对一张表使用多个索引,并将每个索引的返回结果进行合并。在某些场景下,这种访问方式能够减少大量不必要的数据扫描,提升查询的执行效率。 +索引合并是 TiDB v4.0 引入的一种表访问方法。使用此方法时,TiDB 优化器可以在每个表上使用多个索引,并合并每个索引返回的结果。在某些场景下,这种方法通过避免全表扫描使查询更加高效。 -TiDB 中的索引合并分为交集型和并集型两种类型,分别适用于由 `AND` 连接的表达式和由 `OR` 连接的表达式。其中,并集型索引合并在 TiDB v4.0 作为实验功能引入,在 v5.4.0 成为正式功能 (GA)。交集型索引合并从 TiDB v6.5.0 起引入,且必须使用 [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) Hint 指定才能使用。 +TiDB 中的索引合并有两种类型:交集类型和并集类型。前者适用于 `AND` 表达式,而后者适用于 `OR` 表达式。并集类型的索引合并在 TiDB v4.0 中作为实验特性引入,并在 v5.4.0 中正式发布(GA)。交集类型在 TiDB v6.5.0 中引入,只有在指定 [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) 提示时才能使用。 -## 开启索引合并 +## 启用索引合并 -在 v5.4.0 及以上版本的新建集群中,索引合并默认开启。在其他情况下如果未开启,可将 `tidb_enable_index_merge` 的值设为 `ON` 来开启索引合并功能。 - -{{< copyable "sql" >}} +在 TiDB v5.4.0 或更高版本中,索引合并默认启用。在其他情况下,如果索引合并未启用,你需要将变量 [`tidb_enable_index_merge`](/system-variables.md#tidb_enable_index_merge-new-in-v40) 设置为 `ON` 来启用此功能。 ```sql SET session tidb_enable_index_merge = ON; @@ -27,6 +25,7 @@ CREATE TABLE t(a int, b int, c int, d int, INDEX idx_a(a), INDEX idx_b(b), INDEX ```sql EXPLAIN SELECT /*+ NO_INDEX_MERGE() */ * FROM t WHERE a = 1 OR b = 1; + +-------------------------+----------+-----------+---------------+--------------------------------------+ | id | estRows | task | access object | operator info | +-------------------------+----------+-----------+---------------+--------------------------------------+ @@ -45,11 +44,13 @@ EXPLAIN SELECT /*+ USE_INDEX_MERGE(t) */ * FROM t WHERE a > 1 OR b > 1; +-------------------------------+---------+-----------+-------------------------+------------------------------------------------+ ``` -例如,在上述示例中,过滤条件是使用 `OR` 连接的 `WHERE` 子句。在启用索引合并前,每个表只能使用一个索引,不能将 `a = 1` 下推到索引 `a`,也不能将 `b = 1` 下推到索引 `b`。当 `t` 中存在大量数据时,全表扫描的效率会很低。 +在上述查询中,过滤条件是使用 `OR` 作为连接符的 `WHERE` 子句。在没有索引合并的情况下,每个表只能使用一个索引。`a = 1` 不能下推到索引 `a`,`b = 1` 也不能下推到索引 `b`。当表 `t` 中存在大量数据时,全表扫描效率很低。为了处理这种情况,TiDB 引入了索引合并来访问表。 -对于以上查询语句,优化器选择了并集型索引合并的方式访问表。在这种访问方式下,优化器可以选择对一张表使用多个索引,并将每个索引的返回结果进行合并,生成以上两个示例中的后一个执行计划。此时的 `IndexMerge_8` 算子的 `operator info` 中的 `type: union` 表示该算子是一个并集型索引合并算子。它有三个子节点,其中 `IndexRangeScan_5` 和 `IndexRangeScan_6` 根据范围扫描得到符合条件的所有 `RowID`,再由 `TableRowIDScan_7` 算子根据这些 `RowID` 精确地读取所有满足条件的数据。 +对于上述查询,优化器选择使用并集类型的索引合并来访问表。索引合并允许优化器在每个表上使用多个索引,合并每个索引返回的结果,并生成上述输出中的后一个执行计划。 -其中对于 `IndexRangeScan`/`TableRangeScan` 一类按范围进行的扫表操作,`EXPLAIN` 表中 `operator info` 列相比于其他扫表操作,多了被扫描数据的范围这一信息。比如上面的例子中,`IndexRangeScan_5` 算子中的 `range:(1,+inf]` 这一信息表示该算子扫描了从 1 到正无穷这个范围的数据。 +在输出中,`IndexMerge_8` 算子的 `operator info` 中的 `type: union` 信息表明这个算子是并集类型的索引合并。它有三个子节点。`IndexRangeScan_5` 和 `IndexRangeScan_6` 根据范围扫描满足条件的 `RowID`,然后 `TableRowIDScan_7` 算子根据这些 `RowID` 准确读取所有满足条件的数据。 + +对于在特定数据范围内执行的扫描操作,如 `IndexRangeScan`/`TableRangeScan`,结果中的 `operator info` 列与其他扫描操作(如 `IndexFullScan`/`TableFullScan`)相比,有关于扫描范围的额外信息。在上面的例子中,`IndexRangeScan_5` 算子中的 `range:(1,+inf]` 表示该算子扫描从 1 到正无穷的数据。 ```sql EXPLAIN SELECT /*+ NO_INDEX_MERGE() */ * FROM t WHERE a > 1 AND b > 1 AND c = 1; -- 不使用索引合并 @@ -64,7 +65,6 @@ EXPLAIN SELECT /*+ NO_INDEX_MERGE() */ * FROM t WHERE a > 1 AND b > 1 AND c = 1; +--------------------------------+---------+-----------+-------------------------+---------------------------------------------+ EXPLAIN SELECT /*+ USE_INDEX_MERGE(t, idx_a, idx_b, idx_c) */ * FROM t WHERE a > 1 AND b > 1 AND c = 1; -- 使用索引合并 - +-------------------------------+---------+-----------+-------------------------+------------------------------------------------+ | id | estRows | task | access object | operator info | +-------------------------------+---------+-----------+-------------------------+------------------------------------------------+ @@ -76,30 +76,24 @@ EXPLAIN SELECT /*+ USE_INDEX_MERGE(t, idx_a, idx_b, idx_c) */ * FROM t WHERE a > +-------------------------------+---------+-----------+-------------------------+------------------------------------------------+ ``` -在如上示例中,过滤条件是使用 `AND` 连接的 `WHERE` 子句。在启用索引合并前,只能选择使用 `idx_a`、`idx_b` 或 `idx_c` 三个索引中的一个。 +从上面的例子可以看出,过滤条件是使用 `AND` 作为连接符的 `WHERE` 子句。在启用索引合并之前,优化器只能选择三个索引(`idx_a`、`idx_b` 或 `idx_c`)中的一个。 -如果三个过滤条件中的其中一个的过滤性非常好,直接选择对应的索引即可达到理想的执行效率。但如果数据分布同时满足以下三种情形,可以考虑使用交集型索引合并: +如果其中一个过滤条件的选择性较低,优化器会直接选择相应的索引来实现理想的执行效率。但是,如果数据分布满足以下三个条件,你可以考虑使用交集类型的索引合并: -- 全表的数据量相当大,导致直接读全表的执行效率非常低下 -- 每个过滤条件单独的过滤性都不够好,导致 `IndexLookUp` 使用单个索引的执行效率也不够理想 -- 三个过滤条件整体的过滤性非常好 +- 整个表的数据量很大,直接读取整个表效率不高。 +- 对于三个过滤条件中的每一个,各自的选择性都很高,所以使用单个索引的 `IndexLookUp` 的执行效率不理想。 +- 三个过滤条件的整体选择性较低。 -在交集型索引合并访问方式下,优化器可以选择对一张表使用多个索引,并将每个索引的返回结果取交集,生成以上两个示例中的后一个执行计划。此时的 `IndexMerge_9` 算子的 `operator info` 中的 `type: intersection` 表示该算子是一个交集型索引合并算子。该执行计划的其它部分和上述并集型索引合并示例类似。 +在使用交集类型的索引合并访问表时,优化器可以选择在一个表上使用多个索引,并合并每个索引返回的结果,生成上述示例输出中后一个 `IndexMerge` 的执行计划。`IndexMerge_9` 算子的 `operator info` 中的 `type: intersection` 信息表明这个算子是交集类型的索引合并。执行计划的其他部分与前面的并集类型索引合并示例类似。 > **注意:** > -> - TiDB 的索引合并特性在 v5.4.0 及之后的版本默认开启,即 [`tidb_enable_index_merge`](/system-variables.md#tidb_enable_index_merge-从-v40-版本开始引入) 为 `ON`。 -> - 如果查询中使用了 SQL 优化器 Hint [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-),无论 `tidb_enable_index_merge` 开关是否开启,都会强制使用索引合并特性。当过滤条件中有无法下推的表达式时,必须使用 Hint [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) 才能开启索引合并。 -> - 如果查询有除了全表扫描以外的单索引扫描方式可以选择,优化器不会自动选择索引合并,只能通过 Hint 指定使用索引合并。从 v8.1.0 开始,这个限制可以通过 [Optimizer Fix Control 52869](/optimizer-fix-controls.md#52869-从-v810-版本开始引入) 解除。解除此限制能让优化器在更多查询中自动选择索引合并,但也有可能忽略其他更好的执行计划,因此建议在解除此限制前针对实际场景进行充分测试,确保不会带来性能回退。 -> - 索引合并目前无法在临时表上使用。 -> - 交集型索引合并目前不会被优化器自动选择,必须使用 [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) Hint 指定**表名和索引名**时才会被选择。 - -## 其他类型查询的执行计划 - -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [索引查询的执行计划](/explain-indexes.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [视图查询的执行计划](/explain-views.md) -+ [分区查询的执行计划](/explain-partitions.md) +> - 从 v5.4.0 开始,索引合并功能默认启用。也就是说,[`tidb_enable_index_merge`](/system-variables.md#tidb_enable_index_merge-new-in-v40) 为 `ON`。 +> +> - 你可以使用 SQL 提示 [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) 强制优化器应用索引合并,而不考虑 `tidb_enable_index_merge` 的设置。当过滤条件包含无法下推的表达式时,你必须使用 SQL 提示 [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-)。 +> +> - 如果优化器可以为查询计划选择单索引扫描方法(而不是全表扫描),优化器将不会自动使用索引合并。要使优化器使用索引合并,你需要使用优化器提示。从 v8.1.0 开始,你可以通过设置[优化器修复控制 52869](/optimizer-fix-controls.md#52869-new-in-v810) 来移除这个限制。移除这个限制可以让优化器在更多查询中自动选择索引合并,但可能会导致优化器忽略最优执行计划。因此,建议在移除这个限制之前,对实际使用场景进行充分测试,以确保不会导致性能下降。 +> +> - 目前[临时表](/temporary-tables.md)不支持索引合并。 +> +> - 交集类型的索引合并不会被优化器自动选择。你必须使用 [`USE_INDEX_MERGE`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) 提示指定**表名和索引名**才能选择它。 diff --git a/explain-indexes.md b/explain-indexes.md index 62f2177f7798..29dfc4ebccfe 100644 --- a/explain-indexes.md +++ b/explain-indexes.md @@ -1,20 +1,18 @@ --- -title: 用 EXPLAIN 查看索引查询的执行计划 +title: 解释使用索引的语句 summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划信息。 --- -# 用 EXPLAIN 查看索引查询的执行计划 +# 解释使用索引的语句 -SQL 查询可能会使用索引,可以通过 `EXPLAIN` 语句来查看索引查询的执行计划。本文提供多个示例,以帮助用户理解索引查询是如何执行的。 - -TiDB 支持以下使用索引的算子来提升查询速度: +TiDB 支持几种使用索引来加速查询执行的算子: + [`IndexLookup`](#indexlookup) + [`IndexReader`](#indexreader) + [`Point_Get` 和 `Batch_Point_Get`](#point_get-和-batch_point_get) + [`IndexFullScan`](#indexfullscan) -本文档中的示例都基于以下数据: +本文档中的示例基于以下示例数据: {{< copyable "sql" >}} @@ -34,7 +32,7 @@ INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1024), RANDOM_BYTES(1024) FROM t1 a JOI ## IndexLookup -TiDB 从二级索引检索数据时会使用 `IndexLookup` 算子。例如,以下所有查询均会在 `intkey` 列的索引上使用 `IndexLookup` 算子: +TiDB 在从二级索引检索数据时使用 `IndexLookup` 算子。在这种情况下,以下查询都将在 `intkey` 索引上使用 `IndexLookup` 算子: {{< copyable "sql" >}} @@ -93,12 +91,12 @@ EXPLAIN SELECT * FROM t1 WHERE intkey >= 99 AND intkey <= 103; 3 rows in set (0.00 sec) ``` -`IndexLookup` 算子有以下两个子节点: +`IndexLookup` 算子有两个子节点: -* `├─IndexRangeScan_8(Build)` 算子节点对 `intkey` 列的索引执行范围扫描,并检索内部的 `RowID` 值(对此表而言,即为主键)。 -* `└─TableRowIDScan_9(Probe)` 算子节点随后从表数据中检索整行。 +* `├─IndexRangeScan_8(Build)` 算子在 `intkey` 索引上执行范围扫描,并检索内部 `RowID`(对于此表,即主键)的值。 +* `└─TableRowIDScan_9(Probe)` 算子然后从表数据中检索完整的行。 -`IndexLookup` 任务分以上两步执行。如果满足条件的行较多,SQL 优化器可能会根据[常规统计信息](/statistics.md)选择使用 `TableFullScan` 算子。在以下示例中,很多行都满足 `intkey > 100` 这一条件,因此优化器选择了 `TableFullScan`: +因为 `IndexLookup` 任务需要两个步骤,在匹配大量行的场景中,SQL 优化器可能会根据[统计信息](/statistics.md)选择 `TableFullScan` 算子。在以下示例中,大量行匹配条件 `intkey > 100`,因此选择了 `TableFullScan`: {{< copyable "sql" >}} @@ -117,7 +115,7 @@ EXPLAIN SELECT * FROM t1 WHERE intkey > 100; 3 rows in set (0.00 sec) ``` -`IndexLookup` 算子能在带索引的列上有效优化 `LIMIT`: +`IndexLookup` 算子还可以用于有效地优化索引列上的 `LIMIT`: {{< copyable "sql" >}} @@ -135,13 +133,14 @@ EXPLAIN SELECT * FROM t1 ORDER BY intkey DESC LIMIT 10; | └─TableRowIDScan_19(Probe) | 10.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +--------------------------------+---------+-----------+--------------------------------+------------------------------------+ 4 rows in set (0.00 sec) + ``` -以上示例中,TiDB 从 `intkey` 索引读取最后 10 行,然后从表数据中检索这些行的 `RowID` 值。 +在上面的示例中,从索引 `intkey` 中读取最后 10 行。然后从表数据中检索这些 `RowID` 值。 ## IndexReader -TiDB 支持覆盖索引优化 (covering index optimization)。如果 TiDB 能从索引中检索出所有行,就会跳过 `IndexLookup` 任务中通常所需的第二步(即从表数据中检索整行)。示例如下: +TiDB 支持_覆盖索引优化_。如果所有行都可以从索引中检索,TiDB 将跳过 `IndexLookup` 中通常需要的第二个步骤。考虑以下两个示例: {{< copyable "sql" >}} @@ -170,11 +169,11 @@ EXPLAIN SELECT id FROM t1 WHERE intkey = 123; 3 rows in set (0.00 sec) ``` -以上结果中,`id` 也是内部的 `RowID` 值,因此 `id` 也存储在 `intkey` 索引中。部分 `└─IndexRangeScan_5` 任务使用 `intkey` 索引后,可直接返回 `RowID` 值。 +因为 `id` 也是内部 `RowID`,所以它存储在 `intkey` 索引中。在使用 `intkey` 索引作为 `└─IndexRangeScan_5` 的一部分后,可以直接返回 `RowID` 的值。 ## Point_Get 和 Batch_Point_Get -TiDB 直接从主键或唯一键检索数据时会使用 `Point_Get` 或 `Batch_Point_Get` 算子。这两个算子比 `IndexLookup` 更有效率。示例如下: +TiDB 在直接从主键或唯一键检索数据时使用 `Point_Get` 或 `Batch_Point_Get` 算子。这些算子比 `IndexLookup` 更高效。例如: {{< copyable "sql" >}} @@ -229,7 +228,7 @@ Query OK, 0 rows affected (0.37 sec) ## IndexFullScan -索引是有序的,所以优化器可以使用 `IndexFullScan` 算子来优化常见的查询,例如在索引值上使用 `MIN` 或 `MAX` 函数: +因为索引是有序的,所以 `IndexFullScan` 算子可以用来优化常见查询,例如索引值的 `MIN` 或 `MAX` 值: {{< copyable "sql" >}} @@ -262,9 +261,9 @@ EXPLAIN SELECT MAX(intkey) FROM t1; 5 rows in set (0.00 sec) ``` -以上语句的执行过程中,TiDB 在每一个 TiKV Region 上执行 `IndexFullScan` 操作。虽然算子名为 `FullScan` 即全扫描,TiDB 只读取第一行 (`└─Limit_28`)。每个 TiKV Region 返回各自的 `MIN` 或 `MAX` 值给 TiDB,TiDB 再执行流聚合运算来过滤出一行数据。即使表为空,带 `MAX` 或 `MIN` 函数的流聚合运算也能保证返回 `NULL` 值。 +在上述语句中,在每个 TiKV Region 上执行 `IndexFullScan` 任务。尽管名称为 `FullScan`,但只需要读取第一行(`└─Limit_28`)。每个 TiKV Region 将其 `MIN` 或 `MAX` 值返回给 TiDB,然后 TiDB 执行流式聚合以过滤出单行。带有聚合函数 `MAX` 或 `MIN` 的流式聚合还确保在表为空时返回 `NULL`。 -相反,在没有索引的值上执行 `MIN` 函数会在每一个 TiKV Region 上执行 `TableFullScan` 操作。该查询会要求在 TiKV 中扫描所有行,但 `TopN` 计算可保证每个 TiKV Region 只返回一行数据给 TiDB。尽管 `TopN` 能减少 TiDB 和 TiKV 之间的多余数据传输,但该查询的效率仍远不及以上示例(`MIN` 能够使用索引)。 +相比之下,在未索引值上执行 `MIN` 函数将导致 `TableFullScan`。查询将需要扫描 TiKV 中的所有行,但执行 `TopN` 计算以确保每个 TiKV Region 只向 TiDB 返回一行。虽然 `TopN` 防止了 TiKV 和 TiDB 之间传输过多的行,但与上面的示例相比,这个语句仍然被认为效率低得多,因为 `MIN` 能够利用索引。 {{< copyable "sql" >}} @@ -286,7 +285,7 @@ EXPLAIN SELECT MIN(pad1) FROM t1; 6 rows in set (0.00 sec) ``` -执行以下语句时,TiDB 将使用 `IndexFullScan` 算子扫描索引中的每一行: +以下语句将使用 `IndexFullScan` 算子扫描索引中的每一行: {{< copyable "sql" >}} @@ -317,9 +316,9 @@ EXPLAIN SELECT AVG(intkey) FROM t1; 4 rows in set (0.00 sec) ``` -以上示例中,`IndexFullScan` 比 `TableFullScan` 更有效率,因为 `(intkey + RowID)` 索引中值的长度小于整行的长度。 +在上面的示例中,`IndexFullScan` 比 `TableFullScan` 更高效,因为 `(intkey + RowID)` 索引中的值宽度小于完整行的宽度。 -以下语句不支持使用 `IndexFullScan` 算子,因为涉及该表中的其他列: +以下语句不支持使用 `IndexFullScan` 算子,因为需要从表中获取额外的列: {{< copyable "sql" >}} @@ -339,13 +338,3 @@ EXPLAIN SELECT AVG(intkey), ANY_VALUE(pad1) FROM t1; +------------------------------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------------------------------+ 5 rows in set (0.00 sec) ``` - -## 其他类型查询的执行计划 - -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [视图查询的执行计划](/explain-views.md) -+ [分区查询的执行计划](/explain-partitions.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) diff --git a/explain-joins.md b/explain-joins.md index cc12cd0ccc6a..b001371540a1 100644 --- a/explain-joins.md +++ b/explain-joins.md @@ -1,15 +1,11 @@ --- -title: 用 EXPLAIN 查看 JOIN 查询的执行计划 +title: 解释使用连接的语句 summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划信息。 --- -# 用 EXPLAIN 查看 JOIN 查询的执行计划 +# 解释使用连接的语句 -SQL 查询中可能会使用 JOIN 进行表连接,可以通过 `EXPLAIN` 语句来查看 JOIN 查询的执行计划。本文提供多个示例,以帮助用户理解表连接查询是如何执行的。 - -在 TiDB 中,SQL 优化器需要确定数据表的连接顺序,且要判断对于某条特定的 SQL 语句,哪一种 Join 算法最为高效。 - -本文档使用的示例数据如下: +在 TiDB 中,SQL 优化器需要决定表的连接顺序以及针对特定 SQL 语句的最有效连接算法。本文档中的示例基于以下示例数据: {{< copyable "sql" >}} @@ -41,13 +37,13 @@ SELECT SLEEP(1); ANALYZE TABLE t1, t2; ``` -## Index Join +## 索引连接 -如果预计需要连接的行数较少(一般小于 1 万行),推荐使用 Index Join 算法。这个算法与 MySQL 主要使用的 Join 算法类似。在下表的示例中,`TableReader_29(Build)` 算子首先读取表 `t1`,然后根据在 `t1` 中匹配到的每行数据,依次探查表 `t2` 中的数据: +如果需要连接的估计行数较小(通常少于 10000 行),优先使用索引连接方法。这种连接方法的工作原理类似于 MySQL 中使用的主要连接方法。在下面的示例中,操作符 `├─TableReader_29(Build)` 首先读取表 `t1`。对于每个匹配的行,TiDB 将探测表 `t2`: > **注意:** > -> 在执行计划返回结果中,自 v6.4.0 版本起,特定算子(即 `IndexJoin` 和 `Apply` 算子的 Probe 端所有子节点)的 `estRows` 字段意义与 v6.4.0 版本之前的有所不同。细节请参考 [TiDB 执行计划概览](/explain-overview.md#解读-explain-的返回结果)。 +> 在返回的执行计划中,对于 `IndexJoin` 和 `Apply` 操作符的所有探测端子节点,从 v6.4.0 开始 `estRows` 的含义与 v6.4.0 之前不同。更多详情,请参见[TiDB 执行计划概览](/explain-overview.md#understand-explain-output)。 {{< copyable "sql" >}} @@ -68,20 +64,19 @@ EXPLAIN SELECT /*+ INL_JOIN(t1, t2) */ * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_ +---------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ ``` -Index Join 算法对内存消耗较小,但如果需要执行大量探查操作,运行速度可能会慢于其他 Join 算法。以下面这条查询语句为例: +索引连接在内存使用方面很高效,但当需要大量探测操作时,执行速度可能比其他连接方法慢。考虑以下查询: ```sql SELECT * FROM t1 INNER JOIN t2 ON t1.id=t2.t1_id WHERE t1.pad1 = 'value' and t2.pad1='value'; ``` -在 Inner Join 操作中,TiDB 会先执行 Join Reorder 算法,所以不能确定会先读取 `t1` 还是 `t2`。假设 TiDB 先读取了 `t1` 来构建 Build 端,那么 TiDB 会在探查 `t2` 前先根据谓词 `t1.pad1 = 'value'` 筛选数据,但接下来每次探查 `t2` 时都要应用谓词 `t2.pad1='value'`。所以对于这条语句,Index Join 算法可能不如其他 Join 算法高效。 - -但如果 Build 端的数据量比 Probe 端小,且 Probe 端的数据已预先建立了索引,那么这种情况下 Index Join 算法效率更高。在下面这段查询语句中,因为 Index Join 比 Hash Join 效率低,所以 SQL 优化器选择了 Hash Join 算法: +在内连接操作中,TiDB 实现了连接重排序,可以首先访问 `t1` 或 `t2`。假设 TiDB 选择 `t1` 作为第一个表来应用 `build` 步骤,然后 TiDB 能够在探测表 `t2` 之前过滤谓词 `t1.pad1 = 'value'`。谓词 `t2.pad1='value'` 的过滤器将在每次探测表 `t2` 时应用,这可能比其他连接方法效率低。 +当构建端较小且探测端已预先建立索引且较大时,索引连接是有效的。考虑以下查询,其中索引连接的性能比哈希连接差,且未被 SQL 优化器选择: {{< copyable "sql" >}} ```sql --- 删除已有索引 +-- 删除之前添加的索引 ALTER TABLE t2 DROP INDEX t1_id; EXPLAIN ANALYZE SELECT /*+ INL_JOIN(t1, t2) */ * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_col = 1; @@ -90,41 +85,41 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ ``` ```sql -+-----------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+-----------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ -| IndexJoin_14 | 90000.00 | 0 | root | | time:330.2ms, loops:1, inner:{total:72.2ms, concurrency:5, task:12, construct:58.6ms, fetch:13.5ms, build:2.12µs}, probe:26.1ms | inner join, inner:TableReader_10, outer key:test.t2.t1_id, inner key:test.t1.id, equal cond:eq(test.t2.t1_id, test.t1.id) | 88.5 MB | N/A | ++-----------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++-----------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ +| IndexJoin_14 | 90000.00 | 0 | root | | time:330.2ms, loops:1, inner:{total:72.2ms, concurrency:5, task:12, construct:58.6ms, fetch:13.5ms, build:2.12µs}, probe:26.1ms | inner join, inner:TableReader_10, outer key:test.t2.t1_id, inner key:test.t1.id, equal cond:eq(test.t2.t1_id, test.t1.id) | 88.5 MB | N/A | | ├─TableReader_20(Build) | 90000.00 | 90000 | root | | time:307.2ms, loops:96, cop_task: {num: 24, max: 130.6ms, min: 170.9µs, avg: 33.5ms, p95: 105ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 472ms, rpc_num: 24, rpc_time: 802.4ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_19 | 58.6 MB | N/A | | │ └─TableFullScan_19 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:34ms, min:0s, avg: 15.3ms, p80:24ms, p95:30ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 69753, get_snapshot_time: 701.6µs, rocksdb: {delete_skipped_count: 97368, key_skipped_count: 236847, block: {cache_hit_count: 3509}}} | keep order:false | N/A | N/A | | └─TableReader_10(Probe) | 12617.92 | 0 | root | | time:11.9ms, loops:12, cop_task: {num: 42, max: 848.8µs, min: 199µs, avg: 451.8µs, p95: 846.2µs, max_proc_keys: 7, p95_proc_keys: 5, rpc_num: 42, rpc_time: 18.3ms, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15} | data:Selection_9 | N/A | N/A | | └─Selection_9 | 12617.92 | 0 | cop[tikv] | | tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:42, tasks:42}, scan_detail: {total_process_keys: 56, total_process_keys_size: 174608, total_keys: 77, get_snapshot_time: 727.7µs, rocksdb: {block: {cache_hit_count: 154}}} | eq(test.t1.int_col, 1) | N/A | N/A | -| └─TableRangeScan_8 | 90000.00 | 56 | cop[tikv] | table:t1 | tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:42, tasks:42} | range: decided by [test.t2.t1_id], keep order:false | N/A | N/A | -+-----------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ - -+------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ -| HashJoin_20 | 90000.00 | 0 | root | | time:313.6ms, loops:1, build_hash_table:{total:24.6ms, fetch:21.2ms, build:3.32ms}, probe:{concurrency:5, total:1.57s, max:313.5ms, probe:18.9ms, fetch:1.55s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.0 MB | 0 Bytes | -| ├─TableReader_23(Build) | 9955.54 | 10000 | root | | time:23.6ms, loops:12, cop_task: {num: 11, max: 504.6µs, min: 203.7µs, avg: 377.4µs, p95: 504.6µs, rpc_num: 11, rpc_time: 3.92ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_22 | 14.9 MB | N/A | -| │ └─Selection_22 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 241.4µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | -| │ └─TableFullScan_21 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | -| └─TableReader_25(Probe) | 90000.00 | 90000 | root | | time:293.7ms, loops:91, cop_task: {num: 24, max: 105.7ms, min: 210.9µs, avg: 31.4ms, p95: 103.8ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 407ms, rpc_num: 24, rpc_time: 752.2ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_24 | 58.6 MB | N/A | +| └─TableRangeScan_8 | 90000.00 | 56 | cop[tikv] | table:t1 | tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:42, tasks:42} | range: decided by [test.t2.t1_id], keep order:false | N/A | N/A | ++-----------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ + ++------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| HashJoin_20 | 90000.00 | 0 | root | | time:313.6ms, loops:1, build_hash_table:{total:24.6ms, fetch:21.2ms, build:3.32ms}, probe:{concurrency:5, total:1.57s, max:313.5ms, probe:18.9ms, fetch:1.55s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.0 MB | 0 Bytes | +| ├─TableReader_23(Build) | 9955.54 | 10000 | root | | time:23.6ms, loops:12, cop_task: {num: 11, max: 504.6µs, min: 203.7µs, avg: 377.4µs, p95: 504.6µs, rpc_num: 11, rpc_time: 3.92ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_22 | 14.9 MB | N/A | +| │ └─Selection_22 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 241.4µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| │ └─TableFullScan_21 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | +| └─TableReader_25(Probe) | 90000.00 | 90000 | root | | time:293.7ms, loops:91, cop_task: {num: 24, max: 105.7ms, min: 210.9µs, avg: 31.4ms, p95: 103.8ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 407ms, rpc_num: 24, rpc_time: 752.2ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_24 | 58.6 MB | N/A | | └─TableFullScan_24 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:31ms, min:0s, avg: 13ms, p80:19ms, p95:26ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 69753, get_snapshot_time: 637.2µs, rocksdb: {delete_skipped_count: 97368, key_skipped_count: 236847, block: {cache_hit_count: 3509}}} | keep order:false | N/A | N/A | -+------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ - -+------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ -| HashJoin_21 | 90000.00 | 0 | root | | time:331.7ms, loops:1, build_hash_table:{total:32.7ms, fetch:26ms, build:6.73ms}, probe:{concurrency:5, total:1.66s, max:331.3ms, probe:16ms, fetch:1.64s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.3 MB | 0 Bytes | -| ├─TableReader_26(Build) | 9955.54 | 10000 | root | | time:30.4ms, loops:13, cop_task: {num: 11, max: 1.87ms, min: 844.7µs, avg: 1.29ms, p95: 1.87ms, rpc_num: 11, rpc_time: 13.5ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_25 | 12.2 MB | N/A | -| │ └─Selection_25 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 521µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | -| │ └─TableFullScan_24 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | -| └─TableReader_23(Probe) | 90000.00 | 90000 | root | | time:308.6ms, loops:91, cop_task: {num: 24, max: 123.3ms, min: 518.9µs, avg: 32.4ms, p95: 113.4ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 499ms, rpc_num: 24, rpc_time: 776ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_22 | 58.6 MB | N/A | ++------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ + ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| HashJoin_21 | 90000.00 | 0 | root | | time:331.7ms, loops:1, build_hash_table:{total:32.7ms, fetch:26ms, build:6.73ms}, probe:{concurrency:5, total:1.66s, max:331.3ms, probe:16ms, fetch:1.64s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.3 MB | 0 Bytes | +| ├─TableReader_26(Build) | 9955.54 | 10000 | root | | time:30.4ms, loops:13, cop_task: {num: 11, max: 1.87ms, min: 844.7µs, avg: 1.29ms, p95: 1.87ms, rpc_num: 11, rpc_time: 13.5ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_25 | 12.2 MB | N/A | +| │ └─Selection_25 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 521µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| │ └─TableFullScan_24 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | +| └─TableReader_23(Probe) | 90000.00 | 90000 | root | | time:308.6ms, loops:91, cop_task: {num: 24, max: 123.3ms, min: 518.9µs, avg: 32.4ms, p95: 113.4ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 499ms, rpc_num: 24, rpc_time: 776ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_22 | 58.6 MB | N/A | | └─TableFullScan_22 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:44ms, min:0s, avg: 16.8ms, p80:27ms, p95:40ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 69753, get_snapshot_time: 955.4µs, rocksdb: {delete_skipped_count: 97368, key_skipped_count: 236847, block: {cache_hit_count: 3509}}} | keep order:false | N/A | N/A | -+------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ ``` -在上面所示的 Index Join 操作中,`t1.int_col` 一列的索引被删除了。如果加上这个索引,操作执行速度可以从 `0.3 秒` 提高到 `0.06 秒`,如下表所示: +在上面的示例中,索引连接操作缺少 `t1.int_col` 上的索引。一旦添加了这个索引,操作的性能从 `0.3 秒` 提升到 `0.06 秒`,如下所示: ```sql -- 重新添加索引 @@ -173,24 +168,24 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ > **注意:** > -> 在上方示例中,SQL 优化器之所以选择了性能较差的 Hash Join 算法,而不是 Index Join 算法,原因在于查询优化是一个 [NP 完全问题](https://zh.wikipedia.org/wiki/NP%E5%AE%8C%E5%85%A8),可能会选择不太理想的计划。如果需要频繁调用这个查询,建议通过[执行计划管理](/sql-plan-management.md)的方式将 Hint 与 SQL 语句绑定,这样要比在发送给 TiDB 的 SQL 语句中插入 Hint 更容易管理。 +> 在上面的示例中,SQL 优化器选择了性能比索引连接差的哈希连接计划。查询优化是一个 [NP 完全问题](https://en.wikipedia.org/wiki/NP-completeness),可能会选择次优的计划。如果这是一个频繁的查询,建议使用[SQL 计划管理](/sql-plan-management.md)来绑定一个提示到查询,这比在应用程序发送到 TiDB 的查询中插入提示更容易管理。 -### Index Join 相关算法 +### 索引连接的变体 -如果使用 Hint [`INL_JOIN`](/optimizer-hints.md#inl_joint1_name--tl_name-) 进行 Index Join 操作,TiDB 会在连接外表之前创建一个中间结果的 Hash Table。TiDB 同样也支持使用 Hint [`INL_HASH_JOIN`](/optimizer-hints.md#inl_hash_join) 在外表上建 Hash Table。以上所述的 Index Join 相关算法都由 SQL 优化器自动选择。 +使用提示 [`INL_JOIN`](/optimizer-hints.md#inl_joint1_name--tl_name-) 的索引连接操作会在连接外表之前为中间结果创建一个哈希表。TiDB 还支持使用提示 [`INL_HASH_JOIN`](/optimizer-hints.md#inl_hash_join) 在外表上创建哈希表。这些索引连接的变体都会被 SQL 优化器自动选择。 ### 配置 -Index Join 算法的性能受以下系统变量影响: +索引连接的性能受以下系统变量影响: -* [`tidb_index_join_batch_size`](/system-variables.md#tidb_index_join_batch_size)(默认值:`25000`)- `index lookup join` 操作的 batch 大小。 -* [`tidb_index_lookup_join_concurrency`](/system-variables.md#tidb_index_lookup_join_concurrency)(默认值:`4`)- 可以并发执行的 index lookup 任务数。 +- [`tidb_index_join_batch_size`](/system-variables.md#tidb_index_join_batch_size)(默认值:`25000`)- `index lookup join` 操作的批处理大小。 +- [`tidb_index_lookup_join_concurrency`](/system-variables.md#tidb_index_lookup_join_concurrency)(默认值:`4`)- 并发索引查找任务的数量。 -## Hash Join +## 哈希连接 -在 Hash Join 操作中,TiDB 首先读取 Build 端的数据并将其缓存在 Hash Table 中,然后再读取 Probe 端的数据,使用 Probe 端的数据来探查 Hash Table 以获得所需行。与 Index Join 算法相比,Hash Join 要消耗更多内存,但如果需要连接的行数很多,运行速度会比 Index Join 快。TiDB 中的 Hash Join 算子是多线程的,并且可以并发执行。 +在哈希连接操作中,TiDB 读取并缓存连接 `Build` 端的数据到哈希表中,然后读取连接 `Probe` 端的数据,探测哈希表以访问所需的行。哈希连接比索引连接需要更多内存来执行,但当需要连接大量行时执行速度更快。TiDB 中的哈希连接操作符是多线程的,并且可以并行执行。 -下面是一个 Hash Join 示例: +以下是哈希连接的示例: {{< copyable "sql" >}} @@ -211,19 +206,19 @@ EXPLAIN SELECT /*+ HASH_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; 5 rows in set (0.00 sec) ``` -TiDB 会按照以下顺序执行 `HashJoin_27` 算子: +对于 `HashJoin_27` 的执行过程,TiDB 按顺序执行以下操作: -1. 将 Build 端数据缓存在内存中。 -2. 根据缓存数据在 Build 端构造一个 Hash Table。 -3. 读取 Probe 端的数据。 -4. 使用 Probe 端的数据来探查 Hash Table。 -5. 将符合条件的结果返回给用户。 +1. 将 `Build` 端的数据缓存在内存中。 +2. 基于缓存的数据在 `Build` 端构建哈希表。 +3. 读取 `Probe` 端的数据。 +4. 使用 `Probe` 端的数据探测哈希表。 +5. 将符合条件的数据返回给用户。 -`EXPLAIN` 返回结果中的 `operator info` 一列记录了 `HashJoin_27` 的其他信息,包括该查询是 Inner Join 还是 Outer Join 以及 Join 的条件是什么等。在上面给出的示例中,该查询为 Inner Join,Join 条件是 `equal:[eq(test.t1.id, test.t2.id)]`,与查询语句中的 `WHERE t1.id = t2.id` 部分对应。下面例子中其他几个 Join 算子的 operator info 和此处类似。 +`EXPLAIN` 结果表中的 `operator info` 列还记录了关于 `HashJoin_27` 的其他信息,包括查询是内连接还是外连接,以及连接的条件是什么。在上面的示例中,查询是一个内连接,其中连接条件 `equal:[eq(test.t1.id, test.t2.id)]` 部分对应于查询条件 `WHERE t1.id = t2.id`。以下示例中其他连接操作符的操作信息与此类似。 -### 运行数据 +### 运行时统计信息 -如果在执行操作时,内存使用超过了 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 规定的值(默认为 1 GB),且 [`tidb_enable_tmp_storage_on_oom`](/system-variables.md#tidb_enable_tmp_storage_on_oom) 的值为 `ON` (默认为 `ON`),那么 TiDB 会尝试使用临时存储,在磁盘上创建 Hash Join 的 Build 端。`EXPLAIN ANALYZE` 返回结果中的 `execution info` 一栏记录了有关内存使用情况等运行数据。下面的例子展示了 `tidb_mem_quota_query` 的值分别设为 1 GB(默认)及 500 MB 时,`EXPLAIN ANALYZE` 的返回结果(当内存配额设为 500 MB 时,磁盘用作临时存储区): +如果超过 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query)(默认值:1 GB),且 [`tidb_enable_tmp_storage_on_oom`](/system-variables.md#tidb_enable_tmp_storage_on_oom) 的值为 `ON`(默认),TiDB 将尝试使用临时存储,并可能在磁盘上创建 `Build` 操作符(用作哈希连接的一部分)。运行时统计信息(如内存使用情况)记录在 `EXPLAIN ANALYZE` 结果表的 `execution info` 中。以下示例显示了 `tidb_mem_quota_query` 为 1 GB(默认)和 500 MB 时的 `EXPLAIN ANALYZE` 输出。在 500 MB 时,会使用磁盘作为临时存储: ```sql EXPLAIN ANALYZE SELECT /*+ HASH_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -259,21 +254,20 @@ Query OK, 0 rows affected (0.00 sec) ### 配置 -Hash Join 算法的性能受以下系统变量影响: +哈希连接的性能受以下系统变量影响: -* [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query)(默认值:1GB)- 如果某条查询的内存消耗超出了配额,TiDB 会尝试将 Hash Join 的 Build 端移到磁盘上以节省内存。 -* [`tidb_hash_join_concurrency`](/system-variables.md#tidb_hash_join_concurrency)(默认值:`5`)- 可以并发执行的 Hash Join 任务数量。 +- [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query)(默认值:1GB)- 如果超过查询的内存配额,TiDB 将尝试将哈希连接的 `Build` 操作符溢出到磁盘以节省内存。 +- [`tidb_hash_join_concurrency`](/system-variables.md#tidb_hash_join_concurrency)(默认值:`5`)- 并发哈希连接任务的数量。 ### 相关优化 -TiDB 提供了 Runtime Filter 功能,针对 Hash Join 进行性能优化,大幅提升 Hash Join 的执行速度。具体优化使用方式见 [Runtime Filter](/runtime-filter.md)。 +TiDB 提供了运行时过滤器(Runtime Filter)功能,该功能优化了哈希连接的性能,大大提高了其执行速度。有关具体的优化用法,请参见[运行时过滤器](/runtime-filter.md)。 -## Merge Join +## 归并连接 -Merge Join 是一种特殊的 Join 算法。当两个关联表要 Join 的字段需要按排好的顺序读取时,适用 Merge Join 算法。由于 Build 端和 Probe 端的数据都会读取,这种算法的 Join 操作是流式的,类似“拉链式合并”的高效版。Merge Join 占用的内存要远低于 Hash Join,但 Merge Join 不能并发执行。 - -下面是一个使用 Merge Join 的例子: +归并连接是一种特殊的连接方式,适用于连接的两端都以排序顺序读取的情况。它可以被描述为类似于"高效的拉链式合并":当连接的 `Build` 端和 `Probe` 端的数据被读取时,连接操作就像一个流式操作。归并连接比哈希连接需要的内存少得多,但不能并行执行。 +以下是一个示例: {{< copyable "sql" >}} ```sql @@ -293,18 +287,8 @@ EXPLAIN SELECT /*+ MERGE_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; 5 rows in set (0.00 sec) ``` -TiDB 会按照以下顺序执行 Merge Join 算子: - -1. 从 Build 端把一个 Join Group 的数据全部读取到内存中。 -2. 读取 Probe 端的数据。 -3. 将 Probe 端的每行数据与 Build 端的一个完整 Join Group 比较,依次查看是否匹配(除了满足等值条件以外,还有其他非等值条件,这里的“匹配”主要是指查看是否满足非等值条件)。Join Group 指的是所有 Join Key 上值相同的数据。 - -## 其他类型查询的执行计划 +对于归并连接操作符的执行过程,TiDB 执行以下操作: -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [索引查询的执行计划](/explain-indexes.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [视图查询的执行计划](/explain-views.md) -+ [分区查询的执行计划](/explain-partitions.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) +1. 将 `Build` 端一个连接组的所有数据读入内存。 +2. 读取 `Probe` 端的数据。 +3. 比较 `Probe` 端的每一行数据是否与 `Build` 端的一个完整连接组匹配。除了等值条件外,还有非等值条件。这里的"匹配"主要指检查是否满足非等值条件。连接组指的是在所有连接键中具有相同值的数据。 diff --git a/explain-mpp.md b/explain-mpp.md index 502f8b349ada..e060c8e800e1 100644 --- a/explain-mpp.md +++ b/explain-mpp.md @@ -1,13 +1,13 @@ --- -title: 用 EXPLAIN 查看 MPP 模式查询的执行计划 -summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划信息。 +title: MPP 模式下的 EXPLAIN 语句 +summary: 了解 TiDB 中 EXPLAIN 语句返回的 MPP 执行计划信息。 --- -# 用 EXPLAIN 查看 MPP 模式查询的执行计划 +# MPP 模式下的 EXPLAIN 语句 -TiDB 支持使用 [MPP 模式](/tiflash/use-tiflash-mpp-mode.md)来执行查询。在 MPP 执行模式下,SQL 优化器会生成 MPP 的执行计划。注意 MPP 模式仅对有 [TiFlash](/tiflash/tiflash-overview.md) 副本的表生效。 +TiDB 支持使用 [MPP 模式](/tiflash/use-tiflash-mpp-mode.md) 执行查询。在 MPP 模式下,TiDB 优化器会生成 MPP 执行计划。请注意,MPP 模式仅适用于在 [TiFlash](/tiflash/tiflash-overview.md) 上有副本的表。 -本文档使用的示例数据如下: +本文档中的示例基于以下示例数据: {{< copyable "sql" >}} @@ -21,7 +21,7 @@ SET tidb_allow_mpp = 1; ## MPP 查询片段和 MPP 任务 -在 MPP 模式下,一个查询在逻辑上会被切分为多个 MPP 查询片段 (query fragment)。示例如下: +在 MPP 模式下,查询在逻辑上被切分为多个查询片段。以下面的语句为例: {{< copyable "sql" >}} @@ -29,11 +29,13 @@ SET tidb_allow_mpp = 1; EXPLAIN SELECT COUNT(*) FROM t1 GROUP BY id; ``` -这个查询在 MPP 模式下会包含两个查询片段,一个为一阶段聚合,一个为二阶段聚合(最终聚合)。在查询执行的时候每个查询片段都会被实例化为一个或者多个 MPP 任务。 +这个查询在 MPP 模式下被分为两个片段。一个用于第一阶段聚合,另一个用于第二阶段聚合(也是最终聚合)。当执行这个查询时,每个查询片段会被实例化为一个或多个 MPP 任务。 ## Exchange 算子 -MPP 查询的执行计划中有两个 MPP 特有的 Exchange 算子,分别为 ExchangeReceiver 和 ExchangeSender。ExchangeReceiver 表示从下游查询片段读取数据,ExchangeSender 表示下游查询片段向上游查询片段发送数据。在 MPP 执行模式下,每个 MPP 查询片段的根算子均为 ExchangeSender 算子,即每个查询片段以 ExchangeSender 为界进行划分。一个简单的 MPP 计划如下: +`ExchangeReceiver` 和 `ExchangeSender` 是 MPP 执行计划特有的两个 exchange 算子。`ExchangeReceiver` 算子从下游查询片段读取数据,而 `ExchangeSender` 算子将数据从下游查询片段发送到上游查询片段。在 MPP 模式下,每个 MPP 查询片段的根算子都是 `ExchangeSender`,这意味着查询片段是由 `ExchangeSender` 算子划分的。 + +以下是一个简单的 MPP 执行计划: {{< copyable "sql" >}} @@ -56,30 +58,32 @@ EXPLAIN SELECT COUNT(*) FROM t1 GROUP BY id; +------------------------------------+---------+-------------------+---------------+----------------------------------------------------+ ``` -以上执行计划中有两个查询片段: +上述执行计划包含两个查询片段: -* `[TableFullScan_25, HashAgg_9, ExchangeSender_28]` 为第一个查询片段,其主要完成一阶段聚合的计算。 -* `[ExchangeReceiver_29, HashAgg_27, Projection_26, ExchangeSender_30]` 为第二个查询片段,其主要完成二阶段聚合的计算。 +* 第一个是 `[TableFullScan_25, HashAgg_9, ExchangeSender_28]`,主要负责第一阶段聚合。 +* 第二个是 `[ExchangeReceiver_29, HashAgg_27, Projection_26, ExchangeSender_30]`,主要负责第二阶段聚合。 -ExchangeSender 算子的 `operator info` 列输出了 ExchangeType 信息。目前有以下三种 ExchangeType: +`ExchangeSender` 算子的 `operator info` 列显示了 exchange 类型信息。目前有三种 exchange 类型: -* HashPartition:ExchangeSender 把数据按 Hash 值进行分区之后分发给上游的 MPP 任务的 ExchangeReceiver 算子,通常在 Hash Aggregation 以及 Shuffle Hash Join 算法中使用。 -* Broadcast:ExchangeSender 通过广播的方式把数据分发给上游的 MPP 任务,通常在 Broadcast Join 中使用。 -* PassThrough:ExchangeSender 把数据分发给上游的 MPP Task,与 Broadcast 的区别是此时上游有且仅有一个 MPP 任务,通常用于向 TiDB 返回数据。 +* HashPartition:`ExchangeSender` 算子首先根据 Hash 值对数据进行分区,然后将数据分发给上游 MPP 任务的 `ExchangeReceiver` 算子。这种 exchange 类型通常用于 Hash 聚合和 Shuffle Hash Join 算法。 +* Broadcast:`ExchangeSender` 算子通过广播方式将数据分发给上游 MPP 任务。这种 exchange 类型通常用于 Broadcast Join。 +* PassThrough:`ExchangeSender` 算子将数据发送给唯一的上游 MPP 任务,这与 Broadcast 类型不同。这种 exchange 类型通常用于向 TiDB 返回数据。 -上述例子中 ExchangeSender 的 ExchangeType 为 HashPartition 以及 PassThrough,分别对应于 Hash Aggregation 运算以及向 TiDB 返回数据。 +在示例执行计划中,算子 `ExchangeSender_28` 的 exchange 类型是 HashPartition,表示它执行 Hash 聚合算法。算子 `ExchangeSender_30` 的 exchange 类型是 PassThrough,表示它用于向 TiDB 返回数据。 -另外一个典型的 MPP 应用为 join 运算。TiDB MPP 支持两种类型的 join,分别为: +MPP 也经常应用于连接操作。TiDB 中的 MPP 模式支持以下两种连接算法: -* Shuffle Hash Join:join 的 input 通过 HashPartition 的方式 shuffle 数据,上游的 MPP 任务进行分区内的 join。 -* Broadcast Join:join 中的小表以 Broadcast 的方式把数据广播到各个节点,各个节点各自进行 join。 +* Shuffle Hash Join:使用 HashPartition exchange 类型对连接操作的数据输入进行 shuffle。然后,上游 MPP 任务对同一分区内的数据进行连接。 +* Broadcast Join:将连接操作中小表的数据广播到每个节点,然后每个节点分别进行数据连接。 -典型的 Shuffle Hash Join 执行计划如下: +以下是一个典型的 Shuffle Hash Join 执行计划: {{< copyable "sql" >}} ```sql -SET tidb_broadcast_join_threshold_count=0; SET tidb_broadcast_join_threshold_size=0; EXPLAIN SELECT COUNT(*) FROM t1 a JOIN t1 b ON a.id = b.id; +SET tidb_broadcast_join_threshold_count=0; +SET tidb_broadcast_join_threshold_size=0; +EXPLAIN SELECT COUNT(*) FROM t1 a JOIN t1 b ON a.id = b.id; ``` ```sql @@ -102,13 +106,13 @@ SET tidb_broadcast_join_threshold_count=0; SET tidb_broadcast_join_threshold_siz 12 rows in set (0.00 sec) ``` -以上执行计划中, +在上述执行计划中: -* `[TableFullScan_20, Selection_21, ExchangeSender_22]` 完成表 b 的数据读取并通过 HashPartition 的方式把数据 shuffle 给上游 MPP 任务。 -* `[TableFullScan_16, Selection_17, ExchangeSender_18]` 完成表 a 的数据读取并通过 HashPartition 的方式把数据 shuffle 给上游 MPP 任务。 -* `[ExchangeReceiver_19, ExchangeReceiver_23, HashJoin_44, ExchangeSender_47]` 完成 join 并把数据返回给 TiDB。 +* 查询片段 `[TableFullScan_20, Selection_21, ExchangeSender_22]` 从表 b 读取数据并将数据 shuffle 到上游 MPP 任务。 +* 查询片段 `[TableFullScan_16, Selection_17, ExchangeSender_18]` 从表 a 读取数据并将数据 shuffle 到上游 MPP 任务。 +* 查询片段 `[ExchangeReceiver_19, ExchangeReceiver_23, HashJoin_44, ExchangeSender_47]` 连接所有数据并将其返回给 TiDB。 -典型的 Broadcast Join 执行计划如下: +以下是一个典型的 Broadcast Join 执行计划: {{< copyable "sql" >}} @@ -133,14 +137,16 @@ EXPLAIN SELECT COUNT(*) FROM t1 a JOIN t1 b ON a.id = b.id; +----------------------------------------+---------+--------------+---------------+------------------------------------------------+ ``` -以上执行计划中, +在上述执行计划中: + +* 查询片段 `[TableFullScan_17, Selection_18, ExchangeSender_19]` 从小表(表 a)读取数据,并将数据广播到包含大表(表 b)数据的每个节点。 +* 查询片段 `[TableFullScan_21, Selection_22, ExchangeReceiver_20, HashJoin_43, ExchangeSender_46]` 连接所有数据并将其返回给 TiDB。 -* `[TableFullScan_17, Selection_18, ExchangeSender_19]` 从小表(表 a)读数据并广播给大表(表 b)数据所在的各个节点。 -* `[TableFullScan_21, Selection_22, ExchangeReceiver_20, HashJoin_43, ExchangeSender_46]` 完成 join 并将数据返回给 TiDB。 +## MPP 模式下的 `EXPLAIN ANALYZE` 语句 -## 对 MPP 模式的查询使用 `EXPLAIN ANALYZE` +`EXPLAIN ANALYZE` 语句与 `EXPLAIN` 类似,但它还会输出一些运行时信息。 -`EXPLAIN ANALYZE` 语句与 `EXPLAIN` 类似,但还会输出一些运行时的信息。一个简单的 `EXPLAIN ANALYZE` 输出信息如下: +以下是一个简单的 `EXPLAIN ANALYZE` 示例输出: {{< copyable "sql" >}} @@ -163,14 +169,16 @@ EXPLAIN ANALYZE SELECT COUNT(*) FROM t1 GROUP BY id; +------------------------------------+---------+---------+-------------------+---------------+---------------------------------------------------------------------------------------------------+----------------------------------------------------------------+--------+------+ ``` -与 `EXPLAIN` 相比,ExchangeSender 的 `operator info` 中多了 `task id` 的输出,其记录了该查询片段实例化成的 MPP 任务的任务 ID。此外 MPP 算子中都会有 `threads` 这一列,这列记录了 MPP 在执行该算子时使用的并发数(如果集群由多个节点组成,该并发数是所有节点并发数相加的结果)。 +与 `EXPLAIN` 的输出相比,`ExchangeSender` 算子的 `operator info` 列还显示了 `tasks`,它记录了查询片段实例化成的 MPP 任务的 id。此外,每个 MPP 算子在 `execution info` 列中都有一个 `threads` 字段,它记录了 TiDB 执行此算子时的并发度。如果集群由多个节点组成,这个并发度是所有节点并发度的总和。 -## MPP Version 和 Exchange 数据压缩 +## MPP 版本和数据交换压缩 -从 v6.6.0 开始,MPP 执行计划新增字段 `MppVersion` 和 `Compression`。 +从 v6.6.0 开始,MPP 执行计划中新增了 `MPPVersion` 和 `Compression` 字段。 -- `MppVersion`:MPP 执行计划的版本号,可通过系统变量 [`mpp_version`](/system-variables.md#mpp_version-从-v660-版本开始引入) 设置。 -- `Compression`:`Exchange` 算子的数据压缩模式,可通过系统变量 [`mpp_exchange_compression_mode`](/system-variables.md#mpp_exchange_compression_mode-从-v660-版本开始引入) 设置。如果未启用数据压缩,则执行计划中不显示该字段。 +- `MppVersion`:MPP 执行计划的版本号,可以通过系统变量 [`mpp_version`](/system-variables.md#mpp_version-new-in-v660) 设置。 +- `Compression`:`Exchange` 算子的数据压缩模式,可以通过系统变量 [`mpp_exchange_compression_mode`](/system-variables.md#mpp_exchange_compression_mode-new-in-v660) 设置。如果未启用数据压缩,执行计划中不会显示此字段。 + +请看以下示例: ```sql mysql > EXPLAIN SELECT COUNT(*) AS count_order FROM lineitem GROUP BY l_returnflag, l_linestatus ORDER BY l_returnflag, l_linestatus; @@ -191,14 +199,4 @@ mysql > EXPLAIN SELECT COUNT(*) AS count_order FROM lineitem GROUP BY l_returnfl +----------------------------------------+--------------+--------------+----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ``` -例如上面的执行计划结果中,TiDB 使用了版本为 `1` 的 MPP 执行计划来构建 `TableReader`。其中类型为 `HashPartition` 的 ExchangeSender 算子使用 `FAST` 数据压缩模式,类型为 `PassThrough` 的 ExchangeSender 算子未启用数据压缩。 - -## 其他类型查询的执行计划 - -+ [索引查询的执行计划](/explain-indexes.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [视图查询的执行计划](/explain-views.md) -+ [分区查询的执行计划](/explain-partitions.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) +在上述执行计划结果中,TiDB 使用版本为 `1` 的 MPP 执行计划来构建 `TableReader`。`HashPartition` 类型的 `ExchangeSender` 算子使用 `FAST` 数据压缩模式。`PassThrough` 类型的 `ExchangeSender` 算子未启用数据压缩。 diff --git a/explain-overview.md b/explain-overview.md index 0c1c6d806027..68646f0081cb 100644 --- a/explain-overview.md +++ b/explain-overview.md @@ -1,17 +1,19 @@ --- -title: TiDB 执行计划概览 -summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划。 +title: TiDB 查询执行计划概览 +summary: 了解 TiDB 中 `EXPLAIN` 语句返回的执行计划信息。 --- -# TiDB 执行计划概览 +# TiDB 查询执行计划概览 > **注意:** > -> 使用 MySQL 客户端连接到 TiDB 时,为避免输出结果在终端中换行,可先执行 `pager less -S` 命令。执行命令后,新的 `EXPLAIN` 的输出结果不再换行,可按右箭头 键水平滚动阅读输出结果。 +> 当您使用 MySQL 客户端连接 TiDB 时,为了以更清晰的方式阅读输出结果而不换行,您可以使用 `pager less -S` 命令。然后,在 `EXPLAIN` 结果输出后,您可以按键盘上的右箭头键 来水平滚动输出。 -使用 `EXPLAIN` 可查看 TiDB 执行某条语句时选用的执行计划。也就是说,TiDB 在考虑上数百或数千种可能的执行计划后,最终认定该执行计划消耗的资源最少、执行的速度最快。 +SQL 是一种声明式语言。它描述了查询结果应该是什么样子,而**不是**如何获取这些结果的方法。TiDB 会考虑执行查询的所有可能方式,包括使用什么顺序来连接表以及是否可以使用任何潜在的索引。这个_考虑查询执行计划_的过程被称为 SQL 优化。 -`EXPLAIN` 示例如下: +`EXPLAIN` 语句显示给定语句的选定执行计划。也就是说,在考虑了数百或数千种可能的查询执行方式之后,TiDB 认为这个_计划_将消耗最少的资源并在最短的时间内执行: + +{{< copyable "sql" >}} ```sql CREATE TABLE t (id INT NOT NULL PRIMARY KEY auto_increment, a INT NOT NULL, pad1 VARCHAR(255), INDEX(a)); @@ -19,8 +21,6 @@ INSERT INTO t VALUES (1, 1, 'aaa'),(2,2, 'bbb'); EXPLAIN SELECT * FROM t WHERE a = 1; ``` -返回的结果如下: - ```sql Query OK, 0 rows affected (0.96 sec) @@ -37,33 +37,30 @@ Records: 2 Duplicates: 0 Warnings: 0 3 rows in set (0.00 sec) ``` -`EXPLAIN` 实际不会执行查询。[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 可用于实际执行查询并显示执行计划。如果 TiDB 所选的执行计划非最优,可用 `EXPLAIN` 或 `EXPLAIN ANALYZE` 来进行诊断。有关 `EXPLAIN` 用法的详细内容,参阅以下文档: +`EXPLAIN` 不会执行实际的查询。[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 可以用来执行查询并显示 `EXPLAIN` 信息。这在诊断所选执行计划不理想的情况时很有用。有关使用 `EXPLAIN` 的更多示例,请参见以下文档: -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [索引查询的执行计划](/explain-indexes.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [视图查询的执行计划](/explain-views.md) -+ [分区查询的执行计划](/explain-partitions.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) +* [索引](/explain-indexes.md) +* [连接](/explain-joins.md) +* [子查询](/explain-subqueries.md) +* [聚合](/explain-aggregation.md) +* [视图](/explain-views.md) +* [分区](/explain-partitions.md) -## 解读 EXPLAIN 的返回结果 +## 理解 EXPLAIN 输出 -`EXPLAIN` 的返回结果包含以下字段: +以下是对上述 `EXPLAIN` 语句输出的解释: -+ `id` 为算子名,或执行 SQL 语句需要执行的子任务。详见[算子简介](#算子简介)。 -+ `estRows` 为显示 TiDB 预计会处理的行数。该预估数可能基于字典信息(例如访问方法基于主键或唯一键),或基于 `CMSketch` 或直方图等统计信息估算而来。 -+ `task` 显示算子在执行语句时的所在位置。详见 [Task 简介](#task-简介)。 -+ `access-object` 显示被访问的表、分区和索引。显示的索引为部分索引。以上示例中 TiDB 使用了 `a` 列的索引。尤其是在有组合索引的情况下,该字段显示的信息很有参考意义。 -+ `operator info` 显示访问表、分区和索引的其他信息。详见 [`operator info` 结果](#operator-info-结果)。 +* `id` 描述了执行 SQL 语句所需的操作符或子任务的名称。有关更多详细信息,请参见[操作符概览](#操作符概览)。 +* `estRows` 显示 TiDB 预计要处理的行数。这个数字可能基于字典信息(例如当访问方法基于主键或唯一键时),或者可能基于统计信息(如 CMSketch 或直方图)。 +* `task` 显示操作符在哪里执行工作。有关更多详细信息,请参见[任务概览](#任务概览)。 +* `access object` 显示正在访问的表、分区和索引。还显示了索引的组成部分,如上例中使用了索引中的列 `a`。这在您有复合索引的情况下很有用。 +* `operator info` 显示有关访问的其他详细信息。有关更多详细信息,请参见[操作符信息概览](#操作符信息概览)。 > **注意:** > -> 在执行计划返回结果中,自 v6.4.0 版本起,特定算子(即 `IndexJoin` 和 `Apply` 算子的 Probe 端所有子节点)的 `estRows` 字段意义与 v6.4.0 版本之前的有所不同。 -> -> 在 v6.4.0 之前,`estRows` 表示对于 Build 端子节点的每一行,Probe 端预计会处理的行数。自 v6.4.0 起,`estRows` 表示 Probe 端预计会处理的**总行数**。由于 `EXPLAIN ANALYZE` 中展示的实际行数(`actRows` 列)表示的是总行数,v6.4.0 起这些算子 `estRows` 的含义与 `actRows` 列的含义保持一致。 +> 在返回的执行计划中,对于 `IndexJoin` 和 `Apply` 操作符的所有探测端(probe-side)子节点,从 v6.4.0 开始 `estRows` 的含义与 v6.4.0 之前不同。 > +> 在 v6.4.0 之前,`estRows` 表示探测端操作符对构建端(build side)操作符的每一行需要处理的估计行数。从 v6.4.0 开始,`estRows` 表示探测端操作符需要处理的估计行数的**总数**。在 `EXPLAIN ANALYZE` 结果中显示的实际行数(由 `actRows` 列表示)表示总行数,因此从 v6.4.0 开始,`IndexJoin` 和 `Apply` 操作符的探测端子节点的 `estRows` 和 `actRows` 的含义是一致的。 > > 例如: > @@ -101,9 +98,9 @@ Records: 2 Duplicates: 0 Warnings: 0 > | └─IndexRangeScan_19 | 1.00 | cop[tikv] | table:t2, index:ia(a) | range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo | > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ > -> -- 自 v6.4.0 起: +> -- 从 v6.4.0 开始: > -> -- 可以发现 `IndexLookUp_11`、`Selection_10`、`IndexRangeScan_8` 和 `TableRowIDScan_9` 在 `estRows` 列显示的行数与 v6.4.0 以前的不同 +> -- 您可以发现从 v6.4.0 开始,`IndexLookUp_11`、`Selection_10`、`IndexRangeScan_8` 和 `TableRowIDScan_9` 的 `estRows` 列值与 v6.4.0 之前不同。 > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ > | id | estRows | task | access object | operator info | > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ @@ -117,7 +114,7 @@ Records: 2 Duplicates: 0 Warnings: 0 > | └─TableRowIDScan_9(Probe) | 12487.50 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ > -> -- 可以发现 `Limit_17`、`IndexReader_21`、`Limit_20` 和 `IndexRangeScan_19` 在 `estRows` 列显示的行数与 v6.4.0 以前的不同 +> -- 您可以发现从 v6.4.0 开始,`Limit_17`、`IndexReader_21`、`Limit_20` 和 `IndexRangeScan_19` 的 `estRows` 列值与 v6.4.0 之前不同。 > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ > | id | estRows | task | access object | operator info | > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ @@ -132,72 +129,51 @@ Records: 2 Duplicates: 0 Warnings: 0 > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ > ``` -### 算子简介 - -算子是为返回查询结果而执行的特定步骤。真正执行扫表(读盘或者读 TiKV Block Cache)操作的算子有如下几类: +### 操作符概览 -- **TableFullScan**:全表扫描。 -- **TableRangeScan**:带有范围的表数据扫描。 -- **TableRowIDScan**:根据上层传递下来的 RowID 扫描表数据。时常在索引读操作后检索符合条件的行。 -- **IndexFullScan**:另一种“全表扫描”,扫的是索引数据,不是表数据。 -- **IndexRangeScan**:带有范围的索引数据扫描操作。 +操作符是执行查询结果返回过程中的特定步骤。执行表扫描(磁盘或 TiKV Block Cache)的操作符列表如下: -TiDB 会汇聚 TiKV/TiFlash 上扫描的数据或者计算结果,这种“数据汇聚”算子目前有如下几类: +- **TableFullScan**:全表扫描 +- **TableRangeScan**:带指定范围的表扫描 +- **TableRowIDScan**:基于 RowID 的表数据扫描。通常在索引读取操作后执行,用于检索匹配的数据行。 +- **IndexFullScan**:类似于"全表扫描",但扫描的是索引而不是表数据。 +- **IndexRangeScan**:带指定范围的索引扫描。 -- **TableReader**:将 TiKV 上底层扫表算子 TableFullScan 或 TableRangeScan 得到的数据进行汇总。 -- **IndexReader**:将 TiKV 上底层扫表算子 IndexFullScan 或 IndexRangeScan 得到的数据进行汇总。 -- **IndexLookUp**:先汇总 Build 端 TiKV 扫描上来的 RowID,再去 Probe 端上根据这些 `RowID` 精确地读取 TiKV 上的数据。Build 端是 `IndexFullScan` 或 `IndexRangeScan` 类型的算子,Probe 端是 `TableRowIDScan` 类型的算子。 -- **IndexMerge**:和 `IndexLookupReader` 类似,可以看做是它的扩展,可以同时读取多个索引的数据,有多个 Build 端,一个 Probe 端。执行过程也很类似,先汇总所有 Build 端 TiKV 扫描上来的 RowID,再去 Probe 端上根据这些 RowID 精确地读取 TiKV 上的数据。Build 端是 `IndexFullScan` 或 `IndexRangeScan` 类型的算子,Probe 端是 `TableRowIDScan` 类型的算子。 +TiDB 聚合从 TiKV/TiFlash 扫描的数据或计算结果。数据聚合操作符可以分为以下几类: -#### 算子的执行顺序 +- **TableReader**:聚合 TiKV 中 `TableFullScan` 或 `TableRangeScan` 等底层操作符获取的数据。 +- **IndexReader**:聚合 TiKV 中 `IndexFullScan` 或 `IndexRangeScan` 等底层操作符获取的数据。 +- **IndexLookUp**:首先聚合 `Build` 端扫描的 RowID(在 TiKV 中)。然后在 `Probe` 端,基于这些 RowID 从 TiKV 中准确读取数据。在 `Build` 端有 `IndexFullScan` 或 `IndexRangeScan` 等操作符;在 `Probe` 端有 `TableRowIDScan` 操作符。 +- **IndexMerge**:类似于 `IndexLookUp`。`IndexMerge` 可以看作是 `IndexLookupReader` 的扩展。`IndexMerge` 支持同时读取多个索引。有多个 `Build` 和一个 `Probe`。`IndexMerge` 的执行过程与 `IndexLookUp` 相同。 -算子的结构是树状的,但在查询执行过程中,并不严格要求子节点任务在父节点之前完成。TiDB 支持同一查询内的并行处理,即子节点“流入”父节点。父节点、子节点和同级节点可能并行执行查询的一部分。 +虽然结构看起来像一棵树,但执行查询并不严格要求子节点在父节点之前完成。TiDB 支持查询内并行,所以更准确的描述执行方式是子节点_流入_它们的父节点。父节点、子节点和兄弟节点_可能_会并行执行查询的各个部分。 -在以上示例中,`├─IndexRangeScan_8(Build)` 算子为 `a(a)` 索引所匹配的行查找内部 RowID。`└─TableRowIDScan_9(Probe)` 算子随后从表中检索这些行。 - -Build 总是先于 Probe 执行,并且 Build 总是出现在 Probe 前面。即如果一个算子有多个子节点,子节点 ID 后面有 Build 关键字的算子总是先于有 Probe 关键字的算子执行。TiDB 在展现执行计划的时候,Build 端总是第一个出现,接着才是 Probe 端。 +在前面的示例中,`├─IndexRangeScan_8(Build)` 操作符找到匹配 `a(a)` 索引的行的内部 `RowID`。然后 `└─TableRowIDScan_9(Probe)` 操作符从表中检索这些行。 #### 范围查询 -在 `WHERE`/`HAVING`/`ON` 条件中,TiDB 优化器会分析主键或索引键的查询返回。如数字、日期类型的比较符,如大于、小于、等于以及大于等于、小于等于,字符类型的 `LIKE` 符号等。 - -若要使用索引,条件必须是 "Sargable" (Search ARGument ABLE) 的。例如条件 `YEAR(date_column) < 1992` 不能使用索引,但 `date_column < '1992-01-01` 就可以使用索引。 - -推荐使用同一类型的数据以及同一类型的[字符串和排序规则](/character-set-and-collation.md)进行比较,以避免引入额外的 `cast` 操作而导致不能利用索引。 - -可以在范围查询条件中使用 `AND`(求交集)和 `OR`(求并集)进行组合。对于多维组合索引,可以对多个列使用条件。例如对组合索引 `(a, b, c)`: +在 `WHERE`/`HAVING`/`ON` 条件中,TiDB 优化器分析主键查询或索引键查询返回的结果。例如,这些条件可能包括数字和日期类型的比较运算符,如 `>`、`<`、`=`、`>=`、`<=`,以及字符类型如 `LIKE`。 -+ 当 `a` 为等值查询时,可以继续求 `b` 的查询范围。 -+ 当 `b` 也为等值查询时,可以继续求 `c` 的查询范围。 -+ 反之,如果 `a` 为非等值查询,则只能求 `a` 的范围。 - -### Task 简介 - -目前 TiDB 的计算任务分为两种不同的 task:cop task 和 root task。Cop task 是指使用 TiKV 中的 Coprocessor 执行的计算任务,root task 是指在 TiDB 中执行的计算任务。 - -SQL 优化的目标之一是将计算尽可能地下推到 TiKV 中执行。TiKV 中的 Coprocessor 能支持大部分 SQL 内建函数(包括聚合函数和标量函数)、SQL `LIMIT` 操作、索引扫描和表扫描。 - -### `operator info` 结果 - -`EXPLAIN` 返回结果中 `operator info` 列可显示诸如条件下推等信息。本文以上示例中,`operator info` 结果各字段解释如下: +> **注意:** +> +> - 为了使用索引,条件必须是_可查询的_。例如,条件 `YEAR(date_column) < 1992` 不能使用索引,但 `date_column < '1992-01-01'` 可以。 +> - 建议比较相同类型和[字符集和排序规则](/character-set-and-collation.md)的数据。混合类型可能需要额外的 `cast` 操作,或阻止使用索引。 +> - 您也可以使用 `AND`(交集)和 `OR`(并集)来组合一个列的范围查询条件。对于多维复合索引,您可以使用多列中的条件。例如,对于复合索引 `(a, b, c)`: +> - 当 `a` 是等值查询时,继续确定 `b` 的查询范围;当 `b` 也是等值查询时,继续确定 `c` 的查询范围。 +> - 否则,如果 `a` 是非等值查询,则只能确定 `a` 的范围。 -+ `range: [1,1]` 表示查询的 `WHERE` 字句 (`a = 1`) 被下推到了 TiKV,对应的 task 为 `cop[tikv]`。 -+ `keep order:false` 表示该查询的语义不需要 TiKV 按顺序返回结果。如果查询指定了排序(例如 `SELECT * FROM t WHERE a = 1 ORDER BY id`),该字段的返回结果为 `keep order:true`。 -+ `stats:pseudo` 表示 `estRows` 显示的预估数可能不准确。TiDB 定期在后台更新统计信息。也可以通过执行 `ANALYZE TABLE t` 来手动更新统计信息。 +### 任务概览 -`EXPLAIN` 执行后,不同算子返回不同的信息。你可以使用 Optimizer Hints 来控制优化器的行为,以此控制物理算子的选择。例如 `/*+ HASH_JOIN(t1, t2) */` 表示优化器将使用 Hash Join 算法。详细内容见 [Optimizer Hints](/optimizer-hints.md)。 +目前,TiDB 的计算任务可以分为两类:cop 任务和 root 任务。`cop[tikv]` 任务表示操作符在 TiKV 协处理器内执行。`root` 任务表示它将在 TiDB 内完成。 -## 算子相关的系统变量 +SQL 优化的目标之一是尽可能多地将计算下推到 TiKV。TiKV 中的协处理器支持大多数内置 SQL 函数(包括聚合函数和标量函数)、SQL `LIMIT` 操作、索引扫描和表扫描。 -TiDB 在 MySQL 的基础上,定义了一些专用的系统变量和语法用来优化性能。其中一些系统变量和具体的算子相关,比如算子的并发度,算子的内存使用上限,是否允许使用分区表等。这些都可以通过系统变量进行控制,从而影响各个算子执行的效率。 +### 操作符信息概览 -如果读者想要详细了解所有的系统变量及其使用规则,可以参见[系统变量和语法](/system-variables.md)。 +`operator info` 可以显示有用的信息,例如哪些条件可以被下推: -## 另请参阅 +* `range: [1,1]` 显示查询的 where 子句中的谓词(`a = 1`)被直接下推到 TiKV(任务是 `cop[tikv]`)。 +* `keep order:false` 显示此查询的语义不要求 TiKV 按顺序返回结果。如果查询被修改为需要排序(例如 `SELECT * FROM t WHERE a = 1 ORDER BY id`),则此条件将为 `keep order:true`。 +* `stats:pseudo` 显示 `estRows` 中显示的估计可能不准确。TiDB 作为后台操作定期更新统计信息。也可以通过运行 `ANALYZE TABLE t` 手动更新。 -* [`EXPLAIN`](/sql-statements/sql-statement-explain.md) -* [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) -* [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) -* [`TRACE`](/sql-statements/sql-statement-trace.md) -* [`TiDB in Action`](https://book.tidb.io/session3/chapter1/sql-execution-plan.html) -* [系统变量](/system-variables.md) +不同的操作符在执行 `EXPLAIN` 语句后输出不同的信息。您可以使用优化器提示来控制优化器的行为,从而控制物理操作符的选择。例如,`/*+ HASH_JOIN(t1, t2) */` 表示优化器使用 `Hash Join` 算法。有关更多详细信息,请参见[优化器提示](/optimizer-hints.md)。 diff --git a/explain-partitions.md b/explain-partitions.md index 91190e984d27..b7a675e61842 100644 --- a/explain-partitions.md +++ b/explain-partitions.md @@ -1,13 +1,13 @@ --- -title: 用 EXPLAIN 查看分区查询的执行计划 +title: 使用分区的 EXPLAIN 语句 summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划信息。 --- -# 用 EXPLAIN 查看分区查询的执行计划 +# 使用分区的 EXPLAIN 语句 -使用 `EXPLAIN` 语句可以查看 TiDB 在执行查询时需要访问的分区。由于存在[分区裁剪](/partition-pruning.md),所显示的分区通常只是所有分区的一个子集。本文档介绍了常见分区表的一些优化方式,以及如何解读 `EXPLAIN` 语句返回的执行计划信息。 +`EXPLAIN` 语句显示 TiDB 执行查询时需要访问的分区。由于[分区裁剪](/partition-pruning.md)的存在,显示的分区通常只是整体分区的一个子集。本文档描述了常见分区表的一些优化,以及如何解释 `EXPLAIN` 的输出。 -本文档所使用的示例数据如下: +本文档使用的示例数据: {{< copyable "sql" >}} @@ -27,7 +27,7 @@ CREATE TABLE t1 ( PARTITION pmax VALUES LESS THAN MAXVALUE ); -INSERT INTO t1 (d, pad1, pad2, pad3) VALUES +INSERT INTO t1 (d, pad1, pad2, pad3) VALUES ('2016-01-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), ('2016-06-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), ('2016-09-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), @@ -41,7 +41,7 @@ INSERT INTO t1 (d, pad1, pad2, pad3) VALUES ('2019-06-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), ('2019-09-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), ('2020-01-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), - ('2020-06-01', RANDOM_BYTES(102), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), + ('2020-06-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)), ('2020-09-01', RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024)); INSERT INTO t1 SELECT NULL, a.d, RANDOM_BYTES(1024), RANDOM_BYTES(1024), RANDOM_BYTES(1024) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 10000; @@ -53,7 +53,7 @@ SELECT SLEEP(1); ANALYZE TABLE t1; ``` -以下示例解释了基于新建分区表 `t1` 的一条语句: +以下示例展示了对新创建的分区表执行的语句: {{< copyable "sql" >}} @@ -74,14 +74,14 @@ EXPLAIN SELECT COUNT(*) FROM t1 WHERE d = '2017-06-01'; 5 rows in set (0.01 sec) ``` -由上述 `EXPLAIN` 结果可知,从最末尾的 `—TableFullScan_19` 算子开始,再返回到根部的 `StreamAgg_21` 算子的执行过程如下: +从最内层(`└─TableFullScan_19`)算子开始,向上到根算子(`StreamAgg_21`): -* TiDB 成功地识别出只需要访问一个分区 (`p2017`),并将该信息在 `access object` 列中注明。 -* `└─TableFullScan_19` 算子先对整个分区进行扫描,然后执行 `└─Selection_20` 算子筛选起始日期为 `2017-06-01 00:00:00.000000` 的行。 -* 之后,`└─Selection_20` 算子匹配的行在 Coprocessor 中进行流式聚合,Coprocessor 本身就可以理解聚合函数 `count`。 -* 每个 Coprocessor 请求会发送一行数据给 TiDB 的 `└─TableReader_22` 算子,然后将数据在 `StreamAgg_21` 算子下进行流式聚合,再将一行数据返回给客户端。 +* TiDB 成功识别出只需要访问一个分区(`p2017`)。这在 `access object` 下有标注。 +* 在算子 `└─TableFullScan_19` 中扫描分区本身,然后应用 `└─Selection_20` 来过滤出开始日期为 `2017-06-01 00:00:00.000000` 的行。 +* 匹配 `└─Selection_20` 的行然后在协处理器中进行流式聚合,协处理器原生支持 `count` 函数。 +* 每个协处理器请求然后将一行数据发送回 TiDB 内部的 `└─TableReader_22`,然后在 `StreamAgg_21` 下进行流式聚合,最后向客户端返回一行数据。 -以下示例中,分区裁剪不会消除任何分区: +在以下示例中,分区裁剪没有消除任何分区: {{< copyable "sql" >}} @@ -124,19 +124,9 @@ EXPLAIN SELECT COUNT(*) FROM t1 WHERE YEAR(d) = 2017; 27 rows in set (0.00 sec) ``` -由上述 `EXPLAIN` 结果可知: +从上面的输出可以看出: -* TiDB 认为需要访问所有分区 `(p2016..pMax)`。这是因为 TiDB 将谓词 `YEAR(d)= 2017` 视为 [non-sargable](https://en.wikipedia.org/wiki/Sargable)。这个问题并非是 TiDB 特有的。 -* 在扫描每个分区时,`Selection` 算子将筛选出年份不为 2017 的行。 -* 在每个分区上会执行流式聚合,以计算匹配的行数。 -* `└─PartitionUnion_21` 算子会合并访问每个分区后的结果。 - -## 其他类型查询的执行计划 - -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [索引查询的执行计划](/explain-indexes.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [视图查询的执行计划](/explain-views.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) +* TiDB 认为需要访问所有分区(`p2016..pMax`)。这是因为谓词 `YEAR(d) = 2017` 被认为是[非可查询参数化](https://en.wikipedia.org/wiki/Sargable)的。这个问题不是 TiDB 特有的。 +* 在扫描每个分区时,`Selection` 算子过滤掉不匹配 2017 年的行。 +* 在每个分区上执行流式聚合来计算匹配的行数。 +* 算子 `└─PartitionUnion_21` 将访问每个分区的结果进行合并。 diff --git a/explain-subqueries.md b/explain-subqueries.md index 74b1a97f9257..008b7291a162 100644 --- a/explain-subqueries.md +++ b/explain-subqueries.md @@ -1,13 +1,13 @@ --- -title: 用 EXPLAIN 查看子查询的执行计划 +title: 解释使用子查询的语句 summary: 了解 TiDB 中 EXPLAIN 语句返回的执行计划信息。 --- -# 用 EXPLAIN 查看子查询的执行计划 +# 解释使用子查询的语句 -TiDB 会执行多种[子查询相关的优化](/subquery-optimization.md),以提升子查询的执行性能。本文档介绍一些常见子查询的优化方式,以及如何解读 `EXPLAIN` 语句返回的执行计划信息。 +TiDB 执行[多种优化](/subquery-optimization.md)来提高子查询的性能。本文档描述了一些常见子查询的优化方法,以及如何解释 `EXPLAIN` 的输出。 -本文档所使用的示例表数据如下: +本文档中的示例基于以下示例数据: ```sql CREATE TABLE t1 (id BIGINT NOT NULL PRIMARY KEY auto_increment, pad1 BLOB, pad2 BLOB, pad3 BLOB, int_col INT NOT NULL DEFAULT 0); @@ -45,9 +45,9 @@ SELECT SLEEP(1); ANALYZE TABLE t1, t2, t3; ``` -## Inner join(无 `UNIQUE` 约束的子查询) +## 内连接(非唯一子查询) -以下示例中,`IN` 子查询会从表 `t2` 中搜索一列 ID。为保证语义正确性,TiDB 需要保证 `t1_id` 列的值具有唯一性。使用 `EXPLAIN` 可查看到该查询的执行计划去掉重复项并执行 `Inner Join` 内连接操作: +在以下示例中,`IN` 子查询从表 `t2` 中搜索 ID 列表。为了语义正确性,TiDB 需要保证列 `t1_id` 是唯一的。使用 `EXPLAIN`,您可以看到用于删除重复项并执行 `INNER JOIN` 操作的执行计划: ```sql EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2); @@ -65,14 +65,18 @@ EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2); | └─TableReader_12(Probe) | 21.11 | root | | data:TableRangeScan_11 | | └─TableRangeScan_11 | 21.11 | cop[tikv] | table:t1 | range: decided by [test.t2.t1_id], keep order:false | +--------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ - ``` -由上述查询结果可知,TiDB 通过索引连接操作 `IndexJoin_15` 将子查询做了连接转化。该执行计划首先在 TiKV 侧通过索引扫描算子 `└─IndexFullScan_26` 读取 `t2.t1_id` 列的值,然后由 `└─StreamAgg_34` 算子的部分任务在 TiKV 中对 `t1_id` 值进行去重,然后采用 `├─StreamAgg_44(Build)` 算子的部分任务在 TiDB 中对 `t1_id` 值再次进行去重,去重操作由聚合函数 `firstrow(test.t2.t1_id)` 执行;之后将操作结果与 `t1` 表的主键相连接,连接条件是 `eq(test.t1.id, test.t2.t1_id)`。 +从上面的查询结果中,您可以看到 TiDB 使用索引连接操作 `IndexJoin_15` 来连接和转换子查询。在执行计划中,执行过程如下: + +1. TiKV 端的索引扫描算子 `└─IndexFullScan_26` 读取 `t2.t1_id` 列的值。 +2. TiKV 中的 `└─StreamAgg_34` 算子任务对 `t1_id` 的值进行去重。 +3. TiDB 中的 `├─StreamAgg_44(Build)` 算子任务对 `t1_id` 的值进行去重。去重是通过聚合函数 `firstrow(test.t2.t1_id)` 完成的。 +4. 操作结果与 `t1` 表的主键进行连接。连接条件是 `eq(test.t1.id, test.t2.t1_id)`。 -## Inner join(有 `UNIQUE` 约束的子查询) +## 内连接(唯一子查询) -在上述示例中,为了确保 `t1_id` 值在与表 `t1` 连接前具有唯一性,需要执行聚合运算。在以下示例中,由于 `UNIQUE` 约束已能确保 `t3.t1_id` 列值的唯一: +在前面的示例中,在与表 `t1` 连接之前需要聚合以确保 `t1_id` 的值是唯一的。但在以下示例中,由于 `UNIQUE` 约束,`t3.t1_id` 已经保证是唯一的: ```sql EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t3); @@ -88,16 +92,15 @@ EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t3); | └─TableReader_15(Probe) | 999.00 | root | | data:TableRangeScan_14 | | └─TableRangeScan_14 | 999.00 | cop[tikv] | table:t1 | range: decided by [test.t3.t1_id], keep order:false | +-----------------------------+---------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ - ``` -从语义上看,因为约束保证了 `t3.t1_id` 列值的唯一性,TiDB 可以直接执行 `INNER JOIN` 查询。 +从语义上讲,因为 `t3.t1_id` 保证是唯一的,所以它可以直接作为 `INNER JOIN` 执行。 -## Semi Join(关联查询) +## 半连接(相关子查询) -在前两个示例中,通过 `StreamAgg` 聚合操作或通过 `UNIQUE` 约束保证子查询数据的唯一性之后,TiDB 才能够执行 `Inner Join` 操作。这两种连接均使用了 `Index Join`。 +在前面的两个示例中,TiDB 能够在子查询中的数据变得唯一(通过 `StreamAgg`)或保证唯一后执行 `INNER JOIN` 操作。两个连接都使用索引连接执行。 -下面的例子中,TiDB 优化器则选择了一种不同的执行计划: +在这个示例中,TiDB 选择了不同的执行计划: ```sql EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2 WHERE t1_id != t1.int_col); @@ -116,13 +119,13 @@ EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2 WHERE t1_id != t1.int +-----------------------------+----------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------+ ``` -由上述查询结果可知,TiDB 执行了 `Semi Join`。不同于 `Inner Join`,`Semi Join` 仅允许右键 (`t2.t1_id`) 上的第一个值,也就是该操作将去除 `Join` 算子任务中的重复数据。`Join` 算法也包含 `Merge Join`,会按照排序顺序同时从左侧和右侧读取数据,这是一种高效的 `Zipper Merge`。 +从上面的结果中,您可以看到 TiDB 使用了 `Semi Join` 算法。半连接与内连接不同:半连接只允许右键(`t2.t1_id`)上的第一个值,这意味着重复项作为连接算子任务的一部分被消除。连接算法也是归并连接,就像一个高效的拉链合并,因为算子按排序顺序从左右两侧读取数据。 -可以将原语句视为*关联子查询*,因为它引入了子查询外的 `t1.int_col` 列。然而,`EXPLAIN` 语句的返回结果显示的是[关联子查询去关联](/correlated-subquery-optimization.md)后的执行计划。条件 `t1_id != t1.int_col` 会被重写为 `t1.id != t1.int_col`。TiDB 可以从表 `t1` 中读取数据并且在 `└─Selection_21` 中执行此操作,因此这种去关联和重写操作会极大提高执行效率。 +原始语句被认为是一个_相关子查询_,因为子查询引用了子查询外部存在的列(`t1.int_col`)。但是,`EXPLAIN` 的输出显示了应用[子查询去相关优化](/correlated-subquery-optimization.md)后的执行计划。条件 `t1_id != t1.int_col` 被重写为 `t1.id != t1.int_col`。TiDB 可以在读取表 `t1` 的数据时在 `└─Selection_21` 中执行此操作,因此这种去相关和重写使执行效率更高。 -## Anti Semi Join(`NOT IN` 子查询) +## 反半连接(`NOT IN` 子查询) -在以下示例中,*除非*子查询中存在 `t3.t1_id`,否则该查询将(从语义上)返回表 `t3` 中的所有行: +在以下示例中,查询语义上返回表 `t3` 中的所有行,_除非_ `t3.t1_id` 在子查询中: ```sql EXPLAIN SELECT * FROM t3 WHERE t1_id NOT IN (SELECT id FROM t1 WHERE int_col < 100); @@ -141,13 +144,13 @@ EXPLAIN SELECT * FROM t3 WHERE t1_id NOT IN (SELECT id FROM t1 WHERE int_col < 1 +-----------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------+ ``` -上述查询首先读取了表 `t3`,然后根据主键开始探测 (probe) 表 `t1`。连接类型是 _anti semi join_,即反半连接:之所以使用 _anti_,是因为上述示例有不存在匹配值(即 `NOT IN`)的情况;使用 `Semi Join` 则是因为仅需要匹配第一行后就可以停止查询。 +这个查询首先读取表 `t3`,然后根据 `PRIMARY KEY` 探测表 `t1`。连接类型是一个_反半连接_;反是因为这个示例是针对值的不存在(`NOT IN`),半连接是因为只需要第一行匹配就可以拒绝连接。 -## Null-Aware Semi Join(`IN` 和 `= ANY` 子查询) +## 空值感知半连接(`IN` 和 `= ANY` 子查询) -`IN` 和 `= ANY` 的集合运算符号具有特殊的三值属性(`true`、`false` 和 `NULL`)。这意味着在该运算符所转化得到的 Join 类型中需要对 Join key 两侧的 `NULL` 进行特殊的感知和处理。 +`IN` 或 `= ANY` 集合运算符的值是三值的(`true`、`false` 和 `NULL`)。对于从这两个运算符转换而来的连接类型,TiDB 需要感知连接键两侧的 `NULL` 并以特殊方式处理。 -`IN` 和 `= ANY` 算子引导的子查询会分别转为 Semi Join 和 Left Outer Semi Join。在上述 [Semi Join](#semi-join关联查询) 小节中,示例中 Join key 两侧的列 `test.t1.id` 和 `test.t2.t1_id` 都为 `not NULL` 属性,所以 Semi Join 本身不需要 Null-Aware 的性质来辅助运算,即不需要特殊处理 `NULL`。当前 TiDB 对于 Null-Aware Semi Join 没有特定的优化,其实现本质都是基于笛卡尔积加过滤 (filter) 的模式。以下为 Null-Aware Semi Join 的例子: +包含 `IN` 和 `= ANY` 运算符的子查询分别转换为半连接和左外半连接。在前面的[半连接](#半连接相关子查询)示例中,由于连接键两侧的列 `test.t1.id` 和 `test.t2.t1_id` 都是 `not NULL`,因此半连接不需要考虑空值感知(不需要特殊处理 `NULL`)。TiDB 基于笛卡尔积和过滤器处理空值感知半连接,没有特殊优化。以下是一个示例: ```sql CREATE TABLE t(a INT, b INT); @@ -185,33 +188,33 @@ tidb> EXPLAIN SELECT * FROM t WHERE (a,b) IN (SELECT * FROM s); 8 rows in set (0.01 sec) ``` -第一个查询 `EXPLAIN SELECT (a,b) IN (SELECT * FROM s) FROM t;` 中,由于 `t` 表和 `s` 表的 `a`、`b` 列都是 NULLABLE 的,所以 `IN` 子查询所转化的 Left Outer Semi Join 是具有 Null-Aware 性质的。具体实现是先进行笛卡尔积,然后将 `IN` 或 `= ANY` 所连接的列作为普通等值条件放到 other condition 进行过滤(filter)。 +在第一个查询语句 `EXPLAIN SELECT (a,b) IN (SELECT * FROM s) FROM t;` 中,由于表 `t` 和 `s` 的列 `a` 和 `b` 都是 NULLABLE,由 `IN` 子查询转换的左外半连接是空值感知的。具体来说,首先计算笛卡尔积,然后将由 `IN` 或 `= ANY` 连接的列作为普通相等查询放入其他条件中进行过滤。 -第二个查询 `EXPLAIN SELECT * FROM t WHERE (a,b) IN (SELECT * FROM s);` 中,由于 `t` 表和 `s` 表的 `a`、`b` 列都是 NULLABLE 的,`IN` 子查询本应该转为具有 Null-Aware 性质的 Semi Join,但当前 TiDB 进行了优化,直接将 Semi Join 转为了 Inner Join + Aggregate 的方式来实现。这是因为在非 scalar 输出的 `IN` 子查询中,`NULL` 和 `false` 是等效的。下推过滤的 `NULL` 行导致了 `WHERE` 子句的否定语义,因此可以事先忽略这些行。 +在第二个查询语句 `EXPLAIN SELECT * FROM t WHERE (a,b) IN (SELECT * FROM s);` 中,由于表 `t` 和 `s` 的列 `a` 和 `b` 都是 NULLABLE,`IN` 子查询应该转换为空值感知半连接。但是 TiDB 通过将半连接转换为内连接和聚合来优化它。这是因为对于非标量输出,`IN` 子查询中的 `NULL` 和 `false` 是等价的。下推过滤器中的 `NULL` 行导致 `WHERE` 子句的负面语义。因此,可以提前忽略这些行。 > **注意:** > -> `Exists` 操作符也会被转成 Semi Join,但是 `Exists` 操作符号本身不具有集合运算 Null-Aware 的性质。 +> `Exists` 运算符也转换为半连接,但它不是空值感知的。 -## Null-Aware Anti Semi Join(`NOT IN` 和 `!= ALL` 子查询) +## 空值感知反半连接(`NOT IN` 和 `!= ALL` 子查询) -`NOT IN` 和 `!= ALL` 的集合运算运算具有特殊的三值属性(`true`、`false` 和 `NULL`)。这意味着在其所转化得到的 Join 类型中需要对 Join key 两侧的 `NULL` 进行特殊的感知和处理。 +`NOT IN` 或 `!= ALL` 集合运算符的值是三值的(`true`、`false` 和 `NULL`)。对于从这两个运算符转换而来的连接类型,TiDB 需要感知连接键两侧的 `NULL` 并以特殊方式处理。 -`NOT IN` 和 `!= ALL` 算子引导的子查询会对应地转为 Anti Semi Join 和 Anti Left Outer Semi Join。在上述的 [Anti Semi Join](#anti-semi-joinnot-in-子查询) 小节中,由于示例中 Join key 两侧的列 `test.t3.t1_id` 和 `test.t1.id` 都是 `not NULL` 属性的,所以 Anti Semi Join 本身不需要 Null-Aware 的性质来辅助计算,即不需要特殊处理 `NULL`。 +包含 `NOT IN` 和 `!= ALL` 运算符的子查询分别转换为反半连接和反左外半连接。在前面的[反半连接](#反半连接not-in-子查询)示例中,由于连接键两侧的列 `test.t3.t1_id` 和 `test.t1.id` 都是 `not NULL`,因此反半连接不需要考虑空值感知(不需要特殊处理 `NULL`)。 -在 TiDB v6.3.0 版本,TiDB 引入了针对 Null-Aware Anti Join (NAAJ) 的如下特殊优化: +TiDB v6.3.0 对空值感知反连接(NAAJ)进行了以下优化: -- 利用 Null-Aware 的等值条件 (NA-EQ) 构建哈希连接 +- 使用空值感知相等条件(NA-EQ)构建哈希连接 - 由于集合操作符引入的等值需要对等值两侧操作符数的 `NULL` 值做特殊处理,这里称需要 Null-Aware 的等值条件为 NA-EQ 条件。与 v6.3.0 之前版本不同的是,TiDB 不会再将 NA-EQ 条件处理成普通 EQ 条件,而是专门放置于 Join 后置的 other condition 中,匹配笛卡尔积后再判断结果集的合法性。 + 集合运算符引入了相等条件,该条件需要对运算符两侧的 `NULL` 值进行特殊处理。需要空值感知的相等条件称为 NA-EQ。与早期版本不同,TiDB v6.3.0 不再像以前那样处理 NA-EQ,而是将其放在连接后的其他条件中,然后在匹配笛卡尔积后确定结果集的合法性。 - 在 TiDB v6.3.0 版本中,NA-EQ 这种弱化的等值条件依然会被用来构建哈希值 (Hash Join),大大减少了匹配时所需遍历的数据量,加速匹配过程。在 build 表 `DISTINCT` 值比例趋近 1 的时候,加速效果更为显著。 + 从 TiDB v6.3.0 开始,仍然使用 NA-EQ(一个弱化的相等条件)来构建哈希连接。这减少了需要遍历的匹配数据量,加快了匹配过程。当构建表的 `DISTINCT()` 值总百分比接近 100% 时,加速效果更显著。 -- 利用两侧数据源 `NULL` 值的特殊性质加速匹配过程的返回 +- 利用 `NULL` 的特殊属性加快匹配结果的返回 - 由于 Anti Semi Join 自身具有 CNF (Conjunctive normal form) 表达式的属性,其任何一侧出现的 `NULL` 值都会导致确定的结果。利用这个性质可以来加速整个匹配过程。 + 由于反半连接是合取范式(CNF),连接任一侧的 `NULL` 都会导致确定的结果。可以利用这个属性来加快整个匹配过程的返回。 -以下为 Null-Aware Anti Semi Join 的例子: +以下是一个示例: ```sql CREATE TABLE t(a INT, b INT); @@ -246,22 +249,22 @@ tidb> EXPLAIN SELECT * FROM t WHERE (a, b) NOT IN (SELECT * FROM s); 5 rows in set (0.00 sec) ``` -第一个查询 `EXPLAIN SELECT (a, b) NOT IN (SELECT * FROM s) FROM t;` 中,由于 `t` 表和 `s` 表的 `a`、`b` 列都是 NULLABLE 的,所以 `NOT IN` 子查询所转化的 Left Outer Semi Join 是具有 Null-Aware 性质的。不同的是,NAAJ 优化将 NA-EQ 条件也作为了 Hash Join 的连接条件,大大加速了 Join 的计算。 +在第一个查询语句 `EXPLAIN SELECT (a, b) NOT IN (SELECT * FROM s) FROM t;` 中,由于表 `t` 和 `s` 的列 `a` 和 `b` 都是 NULLABLE,由 `NOT IN` 子查询转换的左外半连接是空值感知的。不同之处在于 NAAJ 优化也使用 NA-EQ 作为哈希连接条件,这大大加快了连接计算。 -第二个查询 `EXPLAIN SELECT * FROM t WHERE (a, b) NOT IN (SELECT * FROM s);` 中,由于 `t` 表和 `s` 表的 `a`、`b` 列都是 NULLABLE 的,所以 `NOT IN` 子查询所转化的 Anti Semi Join 是具有 Null-Aware 性质的。不同的是,NAAJ 优化将 NA-EQ 条件也作为了 Hash Join 的连接条件,大大加速了 Join 的计算。 +在第二个查询语句 `EXPLAIN SELECT * FROM t WHERE (a, b) NOT IN (SELECT * FROM s);` 中,由于表 `t` 和 `s` 的列 `a` 和 `b` 都是 NULLABLE,由 `NOT IN` 子查询转换的反半连接是空值感知的。不同之处在于 NAAJ 优化也使用 NA-EQ 作为哈希连接条件,这大大加快了连接计算。 -当前 TiDB 仅针对 Anti Semi Join 和 Anti Left Outer Semi Join 实现了 `NULL` 感知。目前仅支持 Hash Join 类型且其 build 表只能固定为右侧表。 +目前,TiDB 只能对反半连接和反左外半连接进行空值感知。只支持哈希连接类型,并且其构建表应固定为右表。 > **注意:** > -> `Not Exists` 操作符也会被转成 Anti Semi Join,但是 `Not Exists` 符号本身不具有集合运算 Null-Aware 的性质。 +> `Not Exists` 运算符也转换为反半连接,但它不是空值感知的。 -## 其他类型查询的执行计划 +## 解释使用其他类型子查询的语句 -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [索引查询的执行计划](/explain-indexes.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [视图查询的执行计划](/explain-views.md) -+ [分区查询的执行计划](/explain-partitions.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) ++ [解释 MPP 模式下的语句](/explain-mpp.md) ++ [解释使用索引的语句](/explain-indexes.md) ++ [解释使用连接的语句](/explain-joins.md) ++ [解释使用聚合的语句](/explain-aggregation.md) ++ [解释使用视图的语句](/explain-views.md) ++ [解释使用分区的语句](/explain-partitions.md) ++ [解释使用索引合并的语句](/explain-index-merge.md) diff --git a/explain-views.md b/explain-views.md index 61052394cce8..95be7728ed31 100644 --- a/explain-views.md +++ b/explain-views.md @@ -1,13 +1,23 @@ --- -title: 用 EXPLAIN 查看带视图的 SQL 执行计划 -summary: 了解 TiDB 中视图相关语句的执行计划。 +title: EXPLAIN 使用视图的语句 +summary: 了解 TiDB 中 `EXPLAIN` 语句返回的执行计划信息。 --- -# 用 EXPLAIN 查看带视图的 SQL 执行计划 +# EXPLAIN 使用视图的语句 -`EXPLAIN` 语句返回的结果会显示[视图](/views.md)引用的表和索引,而不是视图本身的名称。这是因为视图是一张虚拟表,本身并不存储任何数据。视图的定义会和查询语句的其余部分在 SQL 优化过程中进行合并。 +`EXPLAIN` 显示[视图](/views.md)引用的表和索引,而不是视图本身的名称。这是因为视图只是虚拟表,本身不存储任何数据。视图的定义和语句的其余部分在 SQL 优化期间会合并在一起。 -参考 [bikeshare 数据库示例(英文)](https://docs.pingcap.com/tidb/stable/import-example-data),以下两个示例查询的执行方式类似: + + +从 [bikeshare 示例数据库](/import-example-data.md)中,你可以看到以下两个查询的执行方式类似: + + + + + +从 [bikeshare 示例数据库](/tidb-cloud/import-sample-data.md)中,你可以看到以下两个查询的执行方式类似: + + {{< copyable "sql" >}} @@ -42,7 +52,7 @@ Query OK, 0 rows affected (0.13 sec) 3 rows in set (0.00 sec) ``` -同样,该视图中的谓词被下推至基表: +类似地,视图中的谓词会下推到基表: {{< copyable "sql" >}} @@ -72,9 +82,9 @@ EXPLAIN SELECT * FROM trips WHERE bike_number = 'W00950'; 3 rows in set (0.00 sec) ``` -执行以上第一条语句时使用了索引,满足视图定义,接着在 TiDB 读取行时应用了 `bike_number = 'W00950'` 条件。执行以上第二条语句时,不存在满足该语句的索引,因此使用了 `TableFullScan`。 +在上面的第一个语句中,你可以看到索引用于满足视图定义,然后在 TiDB 读取表行时应用 `bike_number = 'W00950'`。在第二个语句中,没有索引可以满足该语句,因此使用了 `TableFullScan`。 -TiDB 使用的索引可以同时满足视图定义和语句本身,如以下组合索引所示: +TiDB 会使用同时满足视图定义和语句本身的索引。考虑以下复合索引: {{< copyable "sql" >}} @@ -106,14 +116,4 @@ Query OK, 0 rows affected (2 min 31.20 sec) 3 rows in set (0.00 sec) ``` -在第一条语句中,TiDB 能够使用组合索引的两个部分 `(bike_number, duration)`。在第二条语句,TiDB 仅使用了索引 `(bike_number, duration)` 的第一部分 `bike_number`。 - -## 其他类型查询的执行计划 - -+ [MPP 模式查询的执行计划](/explain-mpp.md) -+ [索引查询的执行计划](/explain-indexes.md) -+ [Join 查询的执行计划](/explain-joins.md) -+ [子查询的执行计划](/explain-subqueries.md) -+ [聚合查询的执行计划](/explain-aggregation.md) -+ [分区查询的执行计划](/explain-partitions.md) -+ [索引合并查询的执行计划](/explain-index-merge.md) +在第一个语句中,TiDB 能够使用复合索引 `(bike_number, duration)` 的两个部分。在第二个语句中,只使用了索引 `(bike_number, duration)` 的第一部分 `bike_number`。 diff --git a/explain-walkthrough.md b/explain-walkthrough.md index 0d914ba6edea..af71d07f3e61 100644 --- a/explain-walkthrough.md +++ b/explain-walkthrough.md @@ -1,13 +1,23 @@ --- -title: 使用 EXPLAIN 解读执行计划 -summary: 通过示例了解如何使用 EXPLAIN 分析执行计划。 +title: EXPLAIN 使用教程 +summary: 通过示例语句学习如何使用 EXPLAIN --- -# 使用 `EXPLAIN` 解读执行计划 +# `EXPLAIN` 使用教程 -SQL 是一种声明性语言,因此用户无法根据 SQL 语句直接判断一条查询的执行是否有效率。用户首先要使用 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 语句查看当前的执行计划。 +由于 SQL 是一种声明式语言,你无法自动判断查询是否高效执行。你必须首先使用 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 语句来了解当前的执行计划。 -以 [bikeshare 数据库示例(英文)](https://docs.pingcap.com/tidb/stable/import-example-data) 中的一个 SQL 语句为例,该语句统计了 2017 年 7 月 1 日的行程次数: + + +以下语句来自 [bikeshare 示例数据库](/import-example-data.md),用于统计 2017 年 7 月 1 日发生的行程数量: + + + + + +以下语句来自 [bikeshare 示例数据库](/tidb-cloud/import-sample-data.md),用于统计 2017 年 7 月 1 日发生的行程数量: + + {{< copyable "sql" >}} @@ -28,25 +38,21 @@ EXPLAIN SELECT count(*) FROM trips WHERE start_date BETWEEN '2017-07-01 00:00:00 5 rows in set (0.00 sec) ``` -以上是该查询的执行计划结果。从 `└─TableFullScan_18` 算子开始向上看,查询的执行过程如下(非最佳执行计划): +从子运算符 `└─TableFullScan_18` 开始回溯,你可以看到其执行过程如下,目前这个执行计划并不是最优的: -1. Coprocessor (TiKV) 读取整张 `trips` 表的数据,作为一次 `TableFullScan` 操作,再将读取到的数据传递给 `Selection_19` 算子。`Selection_19` 算子仍在 TiKV 内。 - -2. `Selection_19` 算子根据谓词 `WHERE start_date BETWEEN ..` 进行数据过滤。预计大约有 250 行数据满足该过滤条件(基于统计信息以及算子的执行逻辑估算而来)。`└─TableFullScan_18` 算子显示 `stats:pseudo`,表示该表没有实际统计信息,执行 `ANALYZE TABLE trips` 收集统计信息后,预计的估算的数字会更加准确。 - -3. `COUNT` 函数随后应用于满足过滤条件的行,这一过程也是在 TiKV (`cop[tikv]`) 中的 `StreamAgg_9` 算子内完成的。TiKV coprocessor 能执行一些 MySQL 内置函数,`COUNT` 是其中之一。 - -4. `StreamAgg_9` 算子执行的结果会被传递给 `TableReader_21` 算子(位于 TiDB 进程中,即 `root` 任务)。执行计划中,`TableReader_21` 算子的 `estRows` 为 `1`,表示该算子将从每个访问的 TiKV Region 接收一行数据。这一请求过程的详情,可参阅 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md)。 - -5. `StreamAgg_20` 算子随后对 `└─TableReader_21` 算子传来的每行数据计算 `COUNT` 函数的结果。`StreamAgg_20` 是根算子,会将结果返回给客户端。 +1. 协处理器(TiKV)通过 `TableFullScan` 操作读取整个 `trips` 表。然后将读取的行传递给仍在 TiKV 中的 `Selection_19` 运算符。 +2. `WHERE start_date BETWEEN ..` 谓词在 `Selection_19` 运算符中进行过滤。估计约有 `250` 行满足这个选择条件。注意,这个数字是根据统计信息和运算符的逻辑估算的。`└─TableFullScan_18` 运算符显示 `stats:pseudo`,这表示该表没有实际的统计信息。在运行 `ANALYZE TABLE trips` 收集统计信息后,预计统计数据会更准确。 +3. 对满足选择条件的行应用 `count` 函数。这也在仍在 TiKV 中的 `StreamAgg_9` 运算符内完成(`cop[tikv]`)。TiKV 协处理器可以执行多个 MySQL 内置函数,`count` 就是其中之一。 +4. `StreamAgg_9` 的结果然后发送到现在位于 TiDB 服务器内(任务为 `root`)的 `TableReader_21` 运算符。该运算符的 `estRows` 列值为 `1`,这表示运算符将从每个要访问的 TiKV Region 接收一行。有关这些请求的更多信息,请参见 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md)。 +5. `StreamAgg_20` 运算符然后对来自 `└─TableReader_21` 运算符的每一行应用 `count` 函数,从 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) 可以看到大约有 56 行。由于这是根运算符,它随后将结果返回给客户端。 > **注意:** > -> 要查看 TiDB 中某张表的 Region 信息,可执行 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) 语句。 +> 要查看表包含的 Region 的概览,请执行 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md)。 -## 评估当前的性能 +## 评估当前性能 -`EXPLAIN` 语句只返回查询的执行计划,并不执行该查询。若要获取实际的执行时间,可执行该查询,或使用 `EXPLAIN ANALYZE` 语句: +`EXPLAIN` 只返回查询执行计划但不执行查询。要获取实际执行时间,你可以执行查询或使用 `EXPLAIN ANALYZE`: {{< copyable "sql" >}} @@ -67,11 +73,9 @@ EXPLAIN ANALYZE SELECT count(*) FROM trips WHERE start_date BETWEEN '2017-07-01 5 rows in set (1.03 sec) ``` -执行以上示例查询耗时 `1.03` 秒,说明执行性能较为理想。 - -以上 `EXPLAIN ANALYZE` 的结果中,`actRows` 表明一些 `estRows` 预估数不准确(预估返回 10000 行数据但实际返回 19117643 行)。`└─TableFullScan_18` 算子的 `operator info` 列 (`stats:pseudo`) 信息也表明该算子的预估数不准确。 +上面的示例查询执行需要 `1.03` 秒,这并不是理想的性能。 -如果先执行 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 再执行 `EXPLAIN ANALYZE`,预估数与实际数会更接近: +从上面 `EXPLAIN ANALYZE` 的结果中,`actRows` 表明一些估计值(`estRows`)不准确(预期 1 万行但实际找到 1900 万行),这在 `└─TableFullScan_18` 的 `operator info`(`stats:pseudo`)中已经有所提示。如果你先运行 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 然后再次运行 `EXPLAIN ANALYZE`,你会看到估计值更接近实际值: {{< copyable "sql" >}} @@ -95,9 +99,9 @@ Query OK, 0 rows affected (10.22 sec) 5 rows in set (0.93 sec) ``` -执行 `ANALYZE TABLE` 后,可以看到 `└─TableFullScan_18` 算子的预估行数是准确的,`└─Selection_19` 算子的预估行数也更接近实际行数。以上两个示例中的执行计划(即 TiDB 执行查询所使用的一组算子)未改变,但过时的统计信息常常导致 TiDB 选择到非最优的执行计划。 +执行 `ANALYZE TABLE` 后,你可以看到 `└─TableFullScan_18` 运算符的估计行数是准确的,`└─Selection_19` 的估计值现在也更接近实际值。在上述两种情况下,虽然执行计划(TiDB 用于执行此查询的运算符集)没有改变,但不理想的执行计划通常是由过时的统计信息导致的。 -除 `ANALYZE TABLE` 外,达到 [`tidb_auto_analyze_ratio`](/system-variables.md#tidb_auto_analyze_ratio) 阈值后,TiDB 会自动在后台重新生成统计数据。若要查看 TiDB 有多接近该阈值(即 TiDB 判断统计数据有多健康),可执行 [`SHOW STATS_HEALTHY`](/sql-statements/sql-statement-show-stats-healthy.md) 语句。 +除了 `ANALYZE TABLE`,TiDB 还会在达到 [`tidb_auto_analyze_ratio`](/system-variables.md#tidb_auto_analyze_ratio) 阈值后自动在后台重新生成统计信息。你可以通过执行 [`SHOW STATS_HEALTHY`](/sql-statements/sql-statement-show-stats-healthy.md) 语句来查看 TiDB 距离这个阈值有多近(TiDB 认为统计信息的健康程度): {{< copyable "sql" >}} @@ -114,15 +118,15 @@ SHOW STATS_HEALTHY; 1 row in set (0.00 sec) ``` -## 确定优化方案 +## 识别优化机会 -当前执行计划是有效率的: +当前执行计划在以下方面是高效的: -* 大部分任务是在 TiKV 内处理的,需要通过网络传输给 TiDB 处理的仅有 56 行数据,每行都满足过滤条件,而且都很短。 +* 大部分工作在 TiKV 协处理器内处理。只有 56 行数据需要通过网络发送回 TiDB 进行处理。每一行都很短,只包含匹配选择条件的计数。 -* 在 TiDB (`StreamAgg_20`) 中和在 TiKV (`└─StreamAgg_9`) 中汇总行数都使用了 Stream Aggregate,该算法在内存使用方面很有效率。 +* 在 TiDB (`StreamAgg_20`) 和 TiKV (`└─StreamAgg_9`) 中聚合行数都使用了流式聚合,这在内存使用上非常高效。 -当前执行计划存在的最大问题在于谓词 `start_date BETWEEN '2017-07-01 00:00:00' AND '2017-07-01 23:59:59'` 并未立即生效,先是 `TableFullScan` 算子读取所有行数据,然后才进行过滤选择。可以在 `SHOW CREATE TABLE trips` 的返回结果中找出问题原因: +当前执行计划最大的问题是谓词 `start_date BETWEEN '2017-07-01 00:00:00' AND '2017-07-01 23:59:59'` 没有立即应用。所有行都先通过 `TableFullScan` 运算符读取,然后才应用选择条件。你可以从 `SHOW CREATE TABLE trips` 的输出中找出原因: {{< copyable "sql" >}} @@ -149,7 +153,7 @@ Create Table: CREATE TABLE `trips` ( 1 row in set (0.00 sec) ``` -以上返回结果显示,`start_date` 列**没有**索引。要将该谓词下推到 index reader 算子,还需要一个索引。添加索引如下: +`start_date` 列上**没有**索引。你需要一个索引才能将这个谓词推入索引读取运算符。添加索引的方法如下: {{< copyable "sql" >}} @@ -163,9 +167,9 @@ Query OK, 0 rows affected (2 min 10.23 sec) > **注意:** > -> 你可通过执行 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句来查看 DDL 任务的进度。TiDB 中的默认值的设置较为保守,因此添加索引不会对生产环境下的负载造成太大影响。测试环境下,可以考虑调大 [`tidb_ddl_reorg_batch_size`](/system-variables.md#tidb_ddl_reorg_batch_size) 和 [`tidb_ddl_reorg_worker_cnt`](/system-variables.md#tidb_ddl_reorg_worker_cnt) 的值。在参照系统上,将批处理大小设为 `10240`,将 worker count 并发度设置为 `32`,该系统可获得 10 倍的性能提升(较之使用默认值)。 +> 你可以使用 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 命令监控 DDL 作业的进度。TiDB 的默认设置经过精心选择,以确保添加索引不会对生产工作负载产生太大影响。对于测试环境,考虑增加 [`tidb_ddl_reorg_batch_size`](/system-variables.md#tidb_ddl_reorg_batch_size) 和 [`tidb_ddl_reorg_worker_cnt`](/system-variables.md#tidb_ddl_reorg_worker_cnt) 的值。在参考系统上,批量大小为 `10240` 和工作线程数为 `32` 可以实现比默认值高 10 倍的性能提升。 -添加索引后,可以使用 `EXPLAIN` 重复该查询。在以下返回结果中,可见 TiDB 选择了新的执行计划,而且不再使用 `TableFullScan` 和 `Selection` 算子。 +添加索引后,你可以再次使用 `EXPLAIN` 查询。在下面的输出中,你可以看到选择了一个新的执行计划,`TableFullScan` 和 `Selection` 运算符已被消除: {{< copyable "sql" >}} @@ -185,7 +189,7 @@ EXPLAIN SELECT count(*) FROM trips WHERE start_date BETWEEN '2017-07-01 00:00:00 4 rows in set (0.00 sec) ``` -若要比较实际的执行时间,可再次使用 `EXPLAIN ANALYZE` 语句: +要比较实际执行时间,你可以再次使用 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md): {{< copyable "sql" >}} @@ -205,15 +209,15 @@ EXPLAIN ANALYZE SELECT count(*) FROM trips WHERE start_date BETWEEN '2017-07-01 4 rows in set (0.00 sec) ``` -从以上结果可看出,查询时间已从 1.03 秒减少到 0.0 秒。 +从上面的结果可以看出,查询时间从 1.03 秒减少到了 0.0 秒。 > **注意:** > -> 以上示例另一个可用的优化方案是 [coprocessor cache](/coprocessor-cache.md)。如果你无法添加索引,可考虑开启 coprocessor cache 功能。开启后,只要算子上次执行以来 Region 未作更改,TiKV 将从缓存中返回值。这也有助于减少 `TableFullScan` 和 `Selection` 算子的大部分运算成本。 +> 这里还有另一个优化选项是协处理器缓存。如果你无法添加索引,可以考虑启用[协处理器缓存](/coprocessor-cache.md)。启用后,只要自上次执行运算符以来 Region 没有被修改,TiKV 就会返回缓存中的值。这也将有助于减少昂贵的 `TableFullScan` 和 `Selection` 运算符的大部分开销。 -## 禁止子查询提前执行 +## 禁用子查询的提前执行 -在查询优化过程中,TiDB 会提前执行可以在优化阶段直接计算的子查询。例如: +在查询优化过程中,TiDB 会提前执行可以直接计算的子查询。例如: ```sql CREATE TABLE t1(a int); @@ -233,9 +237,9 @@ EXPLAIN SELECT * FROM t2 WHERE a = (SELECT a FROM t1); 3 rows in set (0.00 sec) ``` -在上述例子中 `a = (SELECT a FROM t1)` 子查询在优化阶段就进行了计算,表达式被改写为 `t2.a=1`。这种执行方式可以在优化阶段进行更多的常量传播和常量折叠优化,但是会影响 `EXPLAIN` 语句的执行时间。当子查询本身耗时较长时,`EXPLAIN` 语句无法执行完成,可能会影响线上问题的排查。 +在上面的例子中,`a = (SELECT a FROM t1)` 子查询在优化过程中被计算并重写为 `t2.a=1`。这允许在优化过程中进行更多优化,如常量传播和折叠。但是,这会影响 `EXPLAIN` 语句的执行时间。当子查询本身需要很长时间执行时,`EXPLAIN` 语句可能无法完成,这可能会影响在线故障排除。 -从 v7.3.0 开始,TiDB 引入 [`tidb_opt_enable_non_eval_scalar_subquery`](/system-variables.md#tidb_opt_enable_non_eval_scalar_subquery-从-v730-版本开始引入) 系统变量,可以控制这类子查询在 `EXPLAIN` 语句中是否禁止提前执行计算展开。该变量默认值为 `OFF`,即提前计算子查询。你可以将该变量设置为 `ON` 来禁止子查询提前执行: +从 v7.3.0 开始,TiDB 引入了 [`tidb_opt_enable_non_eval_scalar_subquery`](/system-variables.md#tidb_opt_enable_non_eval_scalar_subquery-new-in-v730) 系统变量,用于控制是否在 `EXPLAIN` 中禁用此类子查询的提前执行。该变量的默认值为 `OFF`,表示会提前计算子查询。你可以将此变量设置为 `ON` 来禁用子查询的提前执行: ```sql SET @@tidb_opt_enable_non_eval_scalar_subquery = ON; @@ -257,8 +261,8 @@ EXPLAIN SELECT * FROM t2 WHERE a = (SELECT a FROM t1); 7 rows in set (0.00 sec) ``` -可以看到,标量子查询在执行阶段并没有被展开,这样更便于理解该类 SQL 具体的执行过程。 +如你所见,标量子查询在执行过程中没有被展开,这使得更容易理解此类 SQL 的具体执行过程。 > **注意:** > -> [`tidb_opt_enable_non_eval_scalar_subquery`](/system-variables.md#tidb_opt_enable_non_eval_scalar_subquery-从-v730-版本开始引入) 目前仅控制 `EXPLAIN` 语句的行为,`EXPLAIN ANALYZE` 语句仍然会将子查询提前展开。 \ No newline at end of file +> [`tidb_opt_enable_non_eval_scalar_subquery`](/system-variables.md#tidb_opt_enable_non_eval_scalar_subquery-new-in-v730) 只影响 `EXPLAIN` 语句的行为,`EXPLAIN ANALYZE` 语句仍然会提前执行子查询。 diff --git a/expression-syntax.md b/expression-syntax.md index 1e70096a3f58..0ec0c8e461f6 100644 --- a/expression-syntax.md +++ b/expression-syntax.md @@ -1,20 +1,23 @@ --- title: 表达式语法 -summary: 本文列出 TiDB 的表达式语法。 +summary: 了解 TiDB 中的表达式语法。 --- -# 表达式语法 (Expression Syntax) +# 表达式语法 -表达式是一个或多个值、操作符或函数的组合。在 TiDB 中,表达式主要使用在 `SELECT` 语句的各个子句中,包括 Group by 子句、Where 子句、Having 子句、Join 条件以及窗口函数等。此外,部分 DDL 语句也会使用到表达式,例如建表时默认值的设置、生成列的设置,分区规则等。 +表达式是一个或多个值、运算符或函数的组合。在 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 表达式等。 +- 标识符。参考[架构对象名称](/schema-object-names.md)。 -以下规则是表达式的语法,该语法基于 TiDB parser 的 [`parser.y`](https://github.com/pingcap/tidb/blob/release-8.1/pkg/parser/parser.y) 文件中所定义的规则。 +- 谓词、数值、字符串、日期表达式。这些类型的[字面值](/literal-values.md)也是表达式。 + +- 函数调用和窗口函数。参考[函数和操作符概览](/functions-and-operators/functions-and-operators-overview.md)和[窗口函数](/functions-and-operators/window-functions.md)。 + +- 参数标记(`?`)、系统变量、用户变量和 CASE 表达式。 + +以下规则是表达式语法,基于 TiDB 解析器的 [`parser.y`](https://github.com/pingcap/tidb/blob/release-8.1/pkg/parser/parser.y) 规则。 ```ebnf+diagram Expression ::= diff --git a/extended-statistics.md b/extended-statistics.md index 24c633bd0ffb..fe4122e4b9f3 100644 --- a/extended-statistics.md +++ b/extended-statistics.md @@ -1,72 +1,74 @@ --- -title: 扩展统计信息 -summary: 了解如何使用扩展统计信息指导优化器。 +title: 扩展统计信息简介 +summary: 了解如何使用扩展统计信息来指导优化器。 --- -# 扩展统计信息 +# 扩展统计信息简介 -TiDB 可以收集以下两种类型的统计信息,本文主要介绍如何使用扩展统计信息来指导优化器。阅读本文前,建议先阅读[常规统计信息](/statistics.md)。 +TiDB 可以收集以下两种类型的统计信息。本文介绍如何使用扩展统计信息来指导优化器。在阅读本文之前,建议您先阅读[统计信息简介](/statistics.md)。 -- 常规统计信息:主要关注单个列的统计信息,例如直方图和 Count-Min Sketch。这些统计信息对优化器估算查询成本至关重要。详情参见[常规统计信息](/statistics.md)。 -- 扩展统计信息:主要关注指定列之间的数据相关性,指导优化器在查询有相关性的列时更精确地估算查询成本。 +- 基本统计信息:如直方图和 Count-Min Sketch 等统计信息,主要关注单个列。它们对优化器估算查询成本至关重要。详情请参见[统计信息简介](/statistics.md)。 +- 扩展统计信息:关注指定列之间数据相关性的统计信息,当查询的列之间存在相关性时,可以指导优化器更精确地估算查询成本。 -当手动或自动执行 `ANALYZE` 语句时,TiDB 默认只收集常规统计信息,不收集扩展统计信息。这是因为扩展统计信息仅在特定场景下用于优化器估算,而且收集扩展统计信息会增加额外开销。 +当手动或自动执行 `ANALYZE` 语句时,TiDB 默认只收集基本统计信息,不收集扩展统计信息。这是因为扩展统计信息仅在特定场景下用于优化器估算,且收集它们需要额外的开销。 -扩展统计信息默认关闭。如果要收集扩展统计信息,请先启用扩展统计信息,然后逐个创建所需的扩展统计信息对象。创建完之后,下次执行 `ANALYZE` 语句时,TiDB 会同时收集常规统计信息和已创建对象的扩展统计信息。 +扩展统计信息默认是禁用的。要收集扩展统计信息,您需要先启用扩展统计信息,然后逐个创建所需的扩展统计信息对象。创建对象后,下次执行 `ANALYZE` 语句时,TiDB 会同时收集基本统计信息和已创建对象的相应扩展统计信息。 > **警告:** > -> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 此功能是实验性的。不建议在生产环境中使用。此功能可能会在没有预先通知的情况下进行更改或删除。如果您发现 bug,可以在 GitHub 上提交[问题](https://github.com/pingcap/tidb/issues)。 -## 使用限制 +## 限制 -在以下场景下,TiDB 不会收集扩展统计信息: +在以下场景中不会收集扩展统计信息: -- 仅在索引上收集统计信息 -- 使用 `ANALYZE INCREMENTAL` 命令收集统计信息 -- 系统变量 `tidb_enable_fast_analyze` 设置为 `true` 时收集统计信息 +- 仅对索引进行统计信息收集 +- 使用 `ANALYZE INCREMENTAL` 命令进行统计信息收集 +- 系统变量 `tidb_enable_fast_analyze` 的值设置为 `true` 时进行统计信息收集 ## 常用操作 ### 启用扩展统计信息 -要启用扩展统计信息,需要将系统变量 `tidb_enable_extended_stats` 设置为 `ON`: +要启用扩展统计信息,请将系统变量 `tidb_enable_extended_stats` 设置为 `ON`: ```sql SET GLOBAL tidb_enable_extended_stats = ON; ``` -该变量的默认值为 `OFF`。该系统变量的设置对所有扩展统计信息对象生效。 +此变量的默认值为 `OFF`。此系统变量的设置适用于所有扩展统计信息对象。 ### 创建扩展统计信息对象 -创建扩展统计信息对象不是一次性任务,你需要为每个要收集的扩展统计信息分别创建对象。 +创建扩展统计信息对象不是一次性任务。您需要为每个扩展统计信息对象重复创建。 -要创建扩展统计信息对象,使用 SQL 语句 `ALTER TABLE ADD STATS_EXTENDED`。语法如下: +要创建扩展统计信息对象,请使用 SQL 语句 `ALTER TABLE ADD STATS_EXTENDED`。语法如下: ```sql ALTER TABLE table_name ADD STATS_EXTENDED IF NOT EXISTS stats_name stats_type(column_name, column_name...); ``` -你可以在语法中指定要收集扩展统计信息的表名、统计信息名称、统计信息类型和列名。 +在语法中,您可以指定要收集扩展统计信息的表名、统计信息名称、统计信息类型和列名。 -- `table_name`:指定要收集扩展统计信息的表名。 -- `stats_name`:指定统计信息对象的名称,每个表的统计信息对象名称必须唯一。 -- `stats_type`:指定统计信息的类型。目前仅支持相关性 (correlation) 类型。 -- `column_name`:指定列组,可以有多个列。目前只支持指定两个列名。 +- `table_name` 指定从中收集扩展统计信息的表的名称。 +- `stats_name` 指定统计信息对象的名称,对于每个表必须是唯一的。 +- `stats_type` 指定统计信息的类型。目前仅支持相关性类型。 +- `column_name` 指定列组,可能有多个列。目前只能指定两个列名。
-实现原理 +工作原理 -为了提高访问性能,每个 TiDB 节点在系统表 `mysql.stats_extended` 中维护一份缓存,用于记录扩展统计信息。在创建扩展统计信息对象后,下次执行 `ANALYZE` 语句时,如果系统表 `mysql.stats_extended` 中有相应的对象,TiDB 将收集扩展统计信息。 +为了提高访问性能,每个 TiDB 节点在系统表 `mysql.stats_extended` 中维护扩展统计信息的缓存。创建扩展统计信息对象后,下次执行 `ANALYZE` 语句时,如果系统表 `mysql.stats_extended` 有相应的对象,TiDB 将收集扩展统计信息。 -`mysql.stats_extended` 系统表中的每一行都有一个 `version` 列。只要一行数据有更新,`version` 的值就会增加。这样,TiDB 会将表增量加载到内存中,而不是全量加载。 +`mysql.stats_extended` 表中的每一行都有一个 `version` 列。一旦行被更新,`version` 的值就会增加。这样,TiDB 就可以增量加载表,而不是完全加载。 -TiDB 定期加载 `mysql.stats_extended` 系统表,以确保缓存与表中的数据保持一致。 +TiDB 定期加载 `mysql.stats_extended` 以确保缓存与表中的数据保持一致。 > **警告:** > -> 不建议直接操作 `mysql.stats_extended` 系统表,否则不同 TiDB 节点上的缓存会不一致。如果误操作了该系统表,可以在每个 TiDB 节点上执行以下语句,以清除当前缓存,并重新加载 `mysql.stats_extended` 系统表: +> **不建议**直接操作 `mysql.stats_extended` 系统表。否则,不同 TiDB 节点上会出现不一致的缓存。 +> +> 如果您错误地操作了该表,可以在每个 TiDB 节点上执行以下语句。然后当前缓存将被清除,并且 `mysql.stats_extended` 表将被完全重新加载: > > ```sql > ADMIN RELOAD STATS_EXTENDED; @@ -76,20 +78,24 @@ TiDB 定期加载 `mysql.stats_extended` 系统表,以确保缓存与表中的 ### 删除扩展统计信息对象 -要删除扩展统计信息对象,使用以下语句: +要删除扩展统计信息对象,请使用以下语句: ```sql ALTER TABLE table_name DROP STATS_EXTENDED stats_name; ```
-实现原理 +工作原理 + +执行语句后,TiDB 将 `mysql.stats_extended` 中相应对象的 `status` 列的值标记为 `2`,而不是直接删除对象。 -在执行删除扩展统计信息对象的语句后,TiDB 不会直接删除 `mysql.stats_extended` 系统表中的对象,而是将相应对象的 `status` 列的值标记为 `2`。其它 TiDB 节点会读取这个变化,并删除内存缓存中的对象。后台的垃圾回收机制会最终删除该对象。 +其他 TiDB 节点将读取此更改并删除其内存缓存中的对象。后台垃圾收集最终会删除该对象。 > **警告:** > -> 不建议直接操作 `mysql.stats_extended` 系统表,否则不同 TiDB 节点上的缓存会不一致。如果误操作了该系统表,可以在每个 TiDB 节点上执行以下语句,以清除当前缓存,并重新加载 `mysql.stats_extended` 系统表: +> **不建议**直接操作 `mysql.stats_extended` 系统表。否则,不同 TiDB 节点上会出现不一致的缓存。 +> +> 如果您错误地操作了该表,可以在每个 TiDB 节点上使用以下语句。然后当前缓存将被清除,并且 `mysql.stats_extended` 表将被完全重新加载: > > ```sql > ADMIN RELOAD STATS_EXTENDED; @@ -99,13 +105,13 @@ ALTER TABLE table_name DROP STATS_EXTENDED stats_name; ### 导出和导入扩展统计信息 -导出和导入扩展统计信息的方式与导出和导入常规统计信息的方式相同。详情参见[导出和导入常规统计信息](/statistics.md#导出和导入统计信息)。 +导出或导入扩展统计信息的方式与导出或导入基本统计信息相同。详情请参见[统计信息简介 - 导入和导出统计信息](/statistics.md#导入和导出统计信息)。 -## 相关性类型的扩展统计信息使用示例 +## 相关性类型扩展统计信息的使用示例 -目前,TiDB 仅支持相关性类型的扩展统计信息。该类型用于估算范围查询中的行数,并改善索引选择。以下示例展示了如何使用相关性类型的扩展统计信息来估算范围查询中的行数。 +目前,TiDB 仅支持相关性类型的扩展统计信息。此类型用于估算范围查询中的行数并改进索引选择。以下示例展示了如何使用相关性类型的扩展统计信息来估算范围查询中的行数。 -### 第 1 步:定义表 +### 步骤 1. 定义表 定义表 `t` 如下: @@ -113,43 +119,43 @@ ALTER TABLE table_name DROP STATS_EXTENDED stats_name; CREATE TABLE t(col1 INT, col2 INT, KEY(col1), KEY(col2)); ``` -假设表 `t` 的 `col1` 和 `col2` 在行顺序上都遵循单调递增的约束,这意味着 `col1` 和 `col2` 的值在顺序上严格相关,并且相关性系数为 `1`。 +假设表 `t` 的 `col1` 和 `col2` 都遵循行序单调递增约束。这意味着 `col1` 和 `col2` 的值在顺序上严格相关,相关因子为 `1`。 -### 第 2 步:执行不使用扩展统计信息的示例查询 +### 步骤 2. 在不使用扩展统计信息的情况下执行示例查询 -执行以下查询,不使用扩展统计信息: +在不使用扩展统计信息的情况下执行以下查询: ```sql SELECT * FROM t WHERE col1 > 1 ORDER BY col2 LIMIT 1; ``` -对于上述查询的执行,TiDB 优化器会通过以下方式之一来访问表 `t`: +对于上述查询的执行,TiDB 优化器有以下选项来访问表 `t`: - 使用 `col1` 上的索引访问表 `t`,然后按 `col2` 对结果进行排序以计算 `Top-1`。 -- 使用 `col2` 上的索引按顺序扫描表 `t`,直到遇到一条满足 `col1 > 1` 条件的记录后结束扫描。这种访问方式的代价主要取决于 TiDB 按 `col2` 的顺序扫描表时过滤掉了多少行。 +- 使用 `col2` 上的索引来满足第一个满足 `col1 > 1` 的行。此访问方法的成本主要取决于 TiDB 按 `col2` 的顺序扫描表时过滤掉多少行。 -在没有扩展统计信息的情况下,TiDB 优化器只会假设 `col1` 和 `col2` 是独立的,这会**导致显著的估算误差**。 +没有扩展统计信息时,TiDB 优化器只假设 `col1` 和 `col2` 是独立的,这**会导致显著的估算误差**。 -### 第 3 步:启用扩展统计信息 +### 步骤 3. 启用扩展统计信息 -将系统变量 `tidb_enable_extended_stats` 设置为 `ON`,并将 `col1` 和 `col2` 创建为扩展统计信息对象: +将 `tidb_enable_extended_stats` 设置为 `ON`,并为 `col1` 和 `col2` 创建扩展统计信息对象: ```sql ALTER TABLE t ADD STATS_EXTENDED s1 correlation(col1, col2); ``` -创建完统计信息对象后,当执行 `ANALYZE` 语句时,TiDB 会计算表 `t` 的 `col1` 和 `col2` 的[皮尔逊相关系数](https://zh.wikipedia.org/zh-cn/皮尔逊积矩相关系数),并将对象写入 `mysql.stats_extended` 系统表。 +在创建对象后执行 `ANALYZE` 时,TiDB 计算表 `t` 的 `col1` 和 `col2` 的[皮尔逊相关系数](https://en.wikipedia.org/wiki/Pearson_correlation_coefficient),并将对象写入 `mysql.stats_extended` 表。 -### 第 4 步:查看扩展统计信息的效果 +### 步骤 4. 了解扩展统计信息带来的差异 -当 TiDB 有了相关性扩展统计信息后,优化器可以更准确地估算需要扫描的行数。 +在 TiDB 有了相关性的扩展统计信息后,优化器可以更精确地估算要扫描的行数。 -此时,对于上述[第 2 步](#第-2-步执行不使用扩展统计信息的示例查询)中的查询,`col1` 和 `col2` 在顺序上严格相关。如果 TiDB 通过 `col2` 上的索引按顺序扫描表 `t`,直到遇到一条满足 `col1 > 1` 条件的记录后结束扫描,优化器会将行数估算等价转换为以下查询: +此时,对于[步骤 2. 在不使用扩展统计信息的情况下执行示例查询](#步骤-2-在不使用扩展统计信息的情况下执行示例查询)中的查询,`col1` 和 `col2` 在顺序上严格相关。如果 TiDB 通过使用 `col2` 上的索引来访问表 `t` 以满足第一个满足 `col1 > 1` 的行,TiDB 优化器将等效地将行数估算转换为以下查询: ```sql SELECT * FROM t WHERE col1 <= 1 OR col1 IS NULL; ``` -上述查询结果加 1 即为对行数的最终估算值。这样不再使用独立不相关假设,**避免了显著的估算误差**。 +上述查询结果加一将是最终的行数估算。这样,您就不需要使用独立性假设,并且**避免了显著的估算误差**。 -如果相关性系数(本例中为 `1`)小于系统变量 `tidb_opt_correlation_threshold` 的值,优化器会使用独立假设,但会试探性地调大估算值。`tidb_opt_correlation_exp_factor` 的值越大,估算结果越大。相关性系数的绝对值越大,估算结果越大。 +如果相关因子(在本例中为 `1`)小于系统变量 `tidb_opt_correlation_threshold` 的值,优化器将使用独立性假设,但也会启发式地增加估算。`tidb_opt_correlation_exp_factor` 的值越大,估算结果越大。相关因子的绝对值越大,估算结果越大。 diff --git a/external-storage-uri.md b/external-storage-uri.md index af8eb0ce1fa6..bc8e64ece0f5 100644 --- a/external-storage-uri.md +++ b/external-storage-uri.md @@ -1,11 +1,13 @@ --- title: 外部存储服务的 URI 格式 -summary: 介绍了外部存储服务 Amazon S3、GCS、和 Azure Blob Storage 的 URI 格式。 +summary: 了解外部存储服务的存储 URI 格式,包括 Amazon S3、GCS 和 Azure Blob Storage。 --- -# 外部存储服务的 URI 格式 +## 外部存储服务的 URI 格式 -本文介绍 Amazon S3、GCS、和 Azure Blob Storage 存储服务的 URI 格式。基本格式如下: +本文描述外部存储服务的 URI 格式,包括 Amazon S3、GCS 和 Azure Blob Storage。 + +URI 的基本格式如下: ```shell [scheme]://[host]/[path]?[parameters] @@ -13,30 +15,32 @@ summary: 介绍了外部存储服务 Amazon S3、GCS、和 Azure Blob Storage ## Amazon S3 URI 格式 + + - `scheme`:`s3` -- `host`:`bucket name` +- `host`:`bucket name`(存储桶名称) - `parameters`: - - `access-key`:访问密钥 - - `secret-access-key`:秘密访问密钥 - - `session-token`:临时会话令牌(BR v7.6.0 及之后版本支持) - - `use-accelerate-endpoint`:是否在 Amazon S3 上使用加速端点,默认为 `false` - - `endpoint`:Amazon S3 兼容服务自定义端点的 URL,例如 `` - - `force-path-style`:使用路径类型 (path-style),而不是虚拟托管类型 (virtual-hosted-style),默认为 `true` - - `storage-class`:上传对象的存储类别,例如 `STANDARD`、`STANDARD_IA` - - `sse`:加密上传的服务端加密算法,可以设置为空、`AES256` 或 `aws:kms` - - `sse-kms-key-id`:如果 `sse` 设置为 `aws:kms`,则使用该参数指定 KMS ID - - `acl`:上传对象的标准 ACL (Canned ACL),例如 `private`、`authenticated-read` - - `role-arn`:当需要使用特定的 [IAM 角色](https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_roles.html)来访问第三方 Amazon S3 的数据时,使用这个参数来指定 IAM 角色的对应 [Amazon Resource Name (ARN)](https://docs.aws.amazon.com/zh_cn/general/latest/gr/aws-arns-and-namespaces.html)(例如 `arn:aws:iam::888888888888:role/my-role`)。关于使用 IAM 角色访问第三方 Amazon S3 数据的场景,请参考 [AWS 相关文档介绍](https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html)。(BR v7.6.0 及之后版本支持) - - `external-id`:当需要使用特定的 [IAM 角色](https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_roles.html)来访问第三方 Amazon S3 的数据时,可能需要同时提供正确的[外部 ID](https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) 来确保用户有权限代入该 IAM 角色。这个参数用来指定对应的外部 ID,确保成功代入 IAM 角色。外部 ID 可以是任意字符串,并且不是必须的,一般由控制 Amazon S3 数据访问的第三方来指定。如果第三方对于 IAM 角色没有要求指定外部 ID,则可以不需要提供该参数也能顺利代入对应的 IAM 角色,从而访问对应的 Amazon S3 数据。 - -以下是用于 TiDB Lightning 和 BR 的 Amazon S3 URI 示例,需要指定文件夹路径 `testfolder`: + - `access-key`:指定访问密钥。 + - `secret-access-key`:指定秘密访问密钥。 + - `session-token`:指定临时会话令牌。BR 从 v7.6.0 版本开始支持此参数。 + - `use-accelerate-endpoint`:指定是否在 Amazon S3 上使用加速端点(默认为 `false`)。 + - `endpoint`:指定 S3 兼容服务的自定义端点 URL(例如,``)。 + - `force-path-style`:使用路径样式访问而不是虚拟托管样式访问(默认为 `true`)。 + - `storage-class`:指定上传对象的存储类(例如,`STANDARD` 或 `STANDARD_IA`)。 + - `sse`:指定用于加密上传对象的服务器端加密算法(可选值:空、`AES256` 或 `aws:kms`)。 + - `sse-kms-key-id`:如果 `sse` 设置为 `aws:kms`,则指定 KMS ID。 + - `acl`:指定上传对象的预设 ACL(例如,`private` 或 `authenticated-read`)。 + - `role-arn`:当你需要使用指定的 [IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)从第三方访问 Amazon S3 数据时,可以使用 `role-arn` URL 查询参数指定 IAM 角色的 [Amazon 资源名称 (ARN)](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html),例如 `arn:aws:iam::888888888888:role/my-role`。有关使用 IAM 角色从第三方访问 Amazon S3 数据的更多信息,请参见 [AWS 文档](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html)。BR 从 v7.6.0 版本开始支持此参数。 + - `external-id`:当你从第三方访问 Amazon S3 数据时,可能需要指定正确的[外部 ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) 来承担 [IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)。在这种情况下,你可以使用 `external-id` URL 查询参数指定外部 ID,以确保你可以承担该 IAM 角色。外部 ID 是由第三方与 IAM 角色 ARN 一起提供的任意字符串,用于访问 Amazon S3 数据。在承担 IAM 角色时提供外部 ID 是可选的,这意味着如果第三方不要求 IAM 角色提供外部 ID,你可以在不提供此参数的情况下承担 IAM 角色并访问相应的 Amazon S3 数据。 + +以下是 TiDB Lightning 和 BR 的 Amazon S3 URI 示例。在此示例中,你需要指定特定的文件路径 `testfolder`。 ```shell s3://external/testfolder?access-key=${access-key}&secret-access-key=${secret-access-key} ``` -以下是用于 TiCDC `sink-uri` 的 Amazon S3 URI 示例: +以下是 TiCDC `sink-uri` 的 Amazon S3 URI 示例。 ```shell tiup cdc:v7.5.0 cli changefeed create \ @@ -46,29 +50,63 @@ tiup cdc:v7.5.0 cli changefeed create \ --config=cdc_csv.toml ``` -以下是用于 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 的 Amazon S3 URI 示例,需要指定具体的文件名 `test.csv`: + + + + +- `scheme`:`s3` +- `host`:`bucket name`(存储桶名称) +- `parameters`: + + - `access-key`:指定访问密钥。 + - `secret-access-key`:指定秘密访问密钥。 + - `session-token`:指定临时会话令牌。 + - `use-accelerate-endpoint`:指定是否在 Amazon S3 上使用加速端点(默认为 `false`)。 + - `endpoint`:指定 S3 兼容服务的自定义端点 URL(例如,``)。 + - `force-path-style`:使用路径样式访问而不是虚拟托管样式访问(默认为 `true`)。 + - `storage-class`:指定上传对象的存储类(例如,`STANDARD` 或 `STANDARD_IA`)。 + - `sse`:指定用于加密上传对象的服务器端加密算法(可选值:空、`AES256` 或 `aws:kms`)。 + - `sse-kms-key-id`:如果 `sse` 设置为 `aws:kms`,则指定 KMS ID。 + - `acl`:指定上传对象的预设 ACL(例如,`private` 或 `authenticated-read`)。 + - `role-arn`:要允许 TiDB Cloud 使用特定的 [IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)访问 Amazon S3 数据,请在 `role-arn` URL 查询参数中提供该角色的 [Amazon 资源名称 (ARN)](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)。例如:`arn:aws:iam::888888888888:role/my-role`。 + + > **注意:** + > + > - 要自动创建 IAM 角色,请在 [TiDB Cloud 控制台](https://tidbcloud.com/)中导航到集群的**从 Amazon S3 导入数据**页面,填写**文件夹 URI**字段,在**角色 ARN**字段下点击**点击此处使用 AWS CloudFormation 创建新角色**,然后按照**添加新角色 ARN**对话框中的屏幕说明操作。 + > - 如果你在使用 AWS CloudFormation 创建 IAM 角色时遇到任何问题,请在**添加新角色 ARN**对话框中点击**遇到问题?手动创建角色 ARN**以获取 TiDB Cloud 账户 ID 和 TiDB Cloud 外部 ID,然后按照[使用角色 ARN 配置 Amazon S3 访问](https://docs.pingcap.com/tidbcloud/dedicated-external-storage#configure-amazon-s3-access-using-a-role-arn)中的步骤手动创建角色。在配置 IAM 角色时,确保在**账户 ID**字段中输入 TiDB Cloud 账户 ID,并选择**需要外部 ID**以防止[混淆代理攻击](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)。 + > - 为了增强安全性,你可以通过配置较短的**最大会话持续时间**来减少 IAM 角色的有效期。更多信息,请参见 AWS 文档中的[更新角色的最大会话持续时间](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-settings.html#id_roles_update-session-duration)。 + + - `external-id`:指定 TiDB Cloud 外部 ID,这是 TiDB Cloud 访问 Amazon S3 数据所必需的。你可以从 [TiDB Cloud 控制台](https://tidbcloud.com/)的**添加新角色 ARN**对话框中获取此 ID。更多信息,请参见[使用角色 ARN 配置 Amazon S3 访问](https://docs.pingcap.com/tidbcloud/dedicated-external-storage#configure-amazon-s3-access-using-a-role-arn)。 + +以下是 [`BACKUP`](/sql-statements/sql-statement-backup.md) 和 [`RESTORE`](/sql-statements/sql-statement-restore.md) 的 Amazon S3 URI 示例。此示例使用文件路径 `testfolder`。 ```shell -s3://external/test.csv?access-key=${access-key}&secret-access-key=${secret-access-key} +s3://external/testfolder?access-key=${access-key}&secret-access-key=${secret-access-key} ``` + + ## GCS URI 格式 - `scheme`:`gcs` 或 `gs` -- `host`:`bucket name` +- `host`:`bucket name`(存储桶名称) - `parameters`: - - `credentials-file`:迁移工具节点上凭证 JSON 文件的路径 - - `storage-class`:上传对象的存储类别,例如 `STANDARD` 或 `COLDLINE` - - `predefined-acl`:上传对象的预定义 ACL,例如 `private` 或 `project-private` + - `credentials-file`:指定迁移工具节点上的凭证 JSON 文件路径。 + - `storage-class`:指定上传对象的存储类(例如,`STANDARD` 或 `COLDLINE`)。 + - `predefined-acl`:指定上传对象的预设 ACL(例如,`private` 或 `project-private`)。 + + -以下是用于 TiDB Lightning 和 BR 的 GCS URI 示例,需要指定文件夹路径 `testfolder`: +以下是 TiDB Lightning 和 BR 的 GCS URI 示例。在此示例中,你需要指定特定的文件路径 `testfolder`。 ```shell gcs://external/testfolder?credentials-file=${credentials-file-path} ``` -以下是用于 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 的 GCS URI 示例,需要指定具体的文件名 `test.csv`: + + +以下是 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 的 GCS URI 示例。在此示例中,你需要指定特定的文件名 `test.csv`。 ```shell gcs://external/test.csv?credentials-file=${credentials-file-path} @@ -77,17 +115,17 @@ gcs://external/test.csv?credentials-file=${credentials-file-path} ## Azure Blob Storage URI 格式 - `scheme`:`azure` 或 `azblob` -- `host`:`container name` +- `host`:`container name`(容器名称) - `parameters`: - - `account-name`:存储账户名 - - `account-key`:访问密钥 - - `sas-token`:共享访问签名令牌 - - `access-tier`:上传对象的存储类别,例如 `Hot`、`Cool`、`Archive`,默认值为该存储账户的默认访问层。 - - `encryption-scope`:服务端的[加密范围 (Encryption Scope)](https://learn.microsoft.com/zh-cn/azure/storage/blobs/encryption-scope-manage?tabs=powershell#upload-a-blob-with-an-encryption-scope) - - `encryption-key`:服务端使用的[加密密钥 (Encryption Key)](https://learn.microsoft.com/zh-cn/azure/storage/blobs/encryption-customer-provided-keys),采用的加密算法为 AES256 + - `account-name`:指定存储的账户名称。 + - `account-key`:指定访问密钥。 + - `sas-token`:指定共享访问签名(SAS)令牌。 + - `access-tier`:指定上传对象的访问层级,例如 `Hot`、`Cool` 或 `Archive`。默认值是存储账户的默认访问层级。 + - `encryption-scope`:指定用于服务器端加密的[加密范围](https://learn.microsoft.com/en-us/azure/storage/blobs/encryption-scope-manage?tabs=powershell#upload-a-blob-with-an-encryption-scope)。 + - `encryption-key`:指定用于服务器端加密的[加密密钥](https://learn.microsoft.com/en-us/azure/storage/blobs/encryption-customer-provided-keys),使用 AES256 加密算法。 -以下是用于 BR 的 Azure Blob Storage URI 示例,需要指定文件夹路径 `testfolder`: +以下是 BR 的 Azure Blob Storage URI 示例。在此示例中,你需要指定特定的文件路径 `testfolder`。 ```shell azure://external/testfolder?account-name=${account-name}&account-key=${account-key} diff --git a/follower-read.md b/follower-read.md index 6f3846471e10..532cd9a608e2 100644 --- a/follower-read.md +++ b/follower-read.md @@ -1,23 +1,23 @@ --- title: Follower Read -summary: 了解 Follower Read 的使用与实现。 +summary: 本文介绍 Follower Read 的使用和实现机制。 --- # Follower Read -当系统中存在读取热点 Region 导致 leader 资源紧张成为整个系统读取瓶颈时,启用 Follower Read 功能可明显降低 leader 的负担,并且通过在多个 follower 之间均衡负载,显著地提升整体系统的吞吐能力。本文主要介绍 Follower Read 的使用方法与实现机制。 +当 Region 出现读热点时,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 Read 功能是指在保证强一致性读的前提下,使用 Region 的任意 follower 副本来处理读取请求。该功能可以提高 TiDB 集群的吞吐量并减轻 leader 的负载。它包含一系列负载均衡机制,将 TiKV 的读取负载从 Region 的 leader 副本转移到 follower 副本。TiKV 的 Follower Read 实现为用户提供强一致性读取。 > **注意:** > -> 为了获得强一致读取的能力,在当前的实现中,follower 节点需要向 leader 节点询问当前的执行进度(即 `ReadIndex`),这会产生一次额外的网络请求开销,因此目前 Follower Read 的主要优势是将集群中的读请求与写请求隔离开,并提升整体的读吞吐量。 +> 为了实现强一致性读取,follower 节点目前需要向 leader 节点请求当前的执行进度(即 `ReadIndex`),这会导致额外的网络请求开销。因此,Follower Read 的主要优势在于隔离集群中的读写请求,并提高整体读取吞吐量。 -## 使用方式 +## 使用方法 -要开启 TiDB 的 Follower Read 功能,将变量 `tidb_replica_read` 的值设置为对应的目标值即可: +要启用 TiDB 的 Follower Read 功能,请按如下方式修改 `tidb_replica_read` 变量的值: {{< copyable "sql" >}} @@ -29,34 +29,40 @@ set [session | global] tidb_replica_read = '<目标值>'; 默认值:leader -该变量用于设置期待的数据读取方式。 +该变量用于设置期望的数据读取模式。 -- 当设置为默认值 `leader` 或者空字符串时,TiDB 会维持原有行为方式,将所有的读取操作都发送给 leader 副本处理。 -- 当设置为 `follower` 时,TiDB 会选择 Region 的 follower 副本完成所有的数据读取操作。 -- 当设置为 `leader-and-follower` 时,TiDB 可以选择任意副本来执行读取操作,此时读请求会在 leader 和 follower 之间负载均衡。 -- 当设置为 `prefer-leader` 时,TiDB 会优先选择 leader 副本执行读取操作。当 leader 副本的处理速度明显变慢时,例如由于磁盘或网络性能抖动,TiDB 将选择其他可用的 follower 副本来执行读取操作。 -- 当设置为 `closest-replicas` 时,TiDB 会优先选择分布在同一可用区的副本执行读取操作,对应的副本可以是 leader 或 follower。如果同一可用区内没有副本分布,则会从 leader 执行读取。 -- 当设置为 `closest-adaptive` 时: +- 当 `tidb_replica_read` 的值设置为 `leader` 或空字符串时,TiDB 保持其默认行为,将所有读取操作发送给 leader 副本执行。 +- 当 `tidb_replica_read` 的值设置为 `follower` 时,TiDB 选择 Region 的一个 follower 副本来执行所有读取操作。 +- 当 `tidb_replica_read` 的值设置为 `leader-and-follower` 时,TiDB 可以选择任意副本来执行读取操作。在此模式下,读取请求在 leader 和 follower 之间进行负载均衡。 +- 当 `tidb_replica_read` 的值设置为 `prefer-leader` 时,TiDB 优先选择 leader 副本来执行读取操作。如果 leader 副本在处理读取操作时明显变慢(例如由磁盘或网络性能抖动导致),TiDB 将选择其他可用的 follower 副本来执行读取操作。 +- 当 `tidb_replica_read` 的值设置为 `closest-replicas` 时,TiDB 优先选择同一可用区内的副本来执行读取操作,可以是 leader 或 follower。如果同一可用区内没有副本,TiDB 将从 leader 副本读取。 +- 当 `tidb_replica_read` 的值设置为 `closest-adaptive` 时: - - 当一个读请求的预估返回结果大于或等于变量 [`tidb_adaptive_closest_read_threshold`](/system-variables.md#tidb_adaptive_closest_read_threshold-从-v630-版本开始引入) 的值时,TiDB 会优先选择分布在同一可用区的副本执行读取操作。此时,为了避免读流量在各个可用区分布不均衡,TiDB 会动态检测当前在线的所有 TiDB 和 TiKV 的可用区数量分布,在每个可用区中 `closest-adaptive` 配置实际生效的 TiDB 节点数总是与包含 TiDB 节点最少的可用区中的 TiDB 节点数相同,并将其他多出的 TiDB 节点自动切换为读取 leader 副本。例如,如果 TiDB 分布在 3 个可用区,其中 A 和 B 两个可用区各包含 3 个 TiDB 节点,C 可用区只包含 2 个 TiDB 节点,那么每个可用区中 `closest-adaptive` 实际生效的 TiDB 节点数为 2,A 和 B 可用区中各有 1 个节点自动被切换为读取 leader 副本。 - - 当一个读请求的预估返回结果小于变量 [`tidb_adaptive_closest_read_threshold`](/system-variables.md#tidb_adaptive_closest_read_threshold-从-v630-版本开始引入) 的值时,TiDB 会选择 leader 副本执行读取操作。 + - 如果读取请求的预估结果大于或等于 [`tidb_adaptive_closest_read_threshold`](/system-variables.md#tidb_adaptive_closest_read_threshold-new-in-v630) 的值,TiDB 优先选择同一可用区内的副本进行读取操作。为了避免读取流量在可用区之间分布不均衡,TiDB 会动态检测所有在线 TiDB 和 TiKV 节点的可用区分布。在每个可用区中,`closest-adaptive` 配置生效的 TiDB 节点数量是有限制的,始终与拥有最少 TiDB 节点的可用区中的 TiDB 节点数量相同,其他 TiDB 节点自动从 leader 副本读取。例如,如果 TiDB 节点分布在 3 个可用区(A、B 和 C)中,其中 A 和 B 各包含 3 个 TiDB 节点,C 只包含 2 个 TiDB 节点,则每个可用区中 `closest-adaptive` 配置生效的 TiDB 节点数量为 2,A 和 B 可用区中的其他 TiDB 节点自动选择 leader 副本进行读取操作。 + - 如果读取请求的预估结果小于 [`tidb_adaptive_closest_read_threshold`](/system-variables.md#tidb_adaptive_closest_read_threshold-new-in-v630) 的值,TiDB 只能选择 leader 副本进行读取操作。 -- 当设置为 `learner` 时,TiDB 会选择 learner 副本执行读取操作。在读取时,如果当前 Region 没有 learner 副本,TiDB 会报错。 +- 当 `tidb_replica_read` 的值设置为 `learner` 时,TiDB 从 learner 副本读取数据。如果 Region 中没有 learner 副本,TiDB 将返回错误。 + + > **注意:** > -> 当设置为 `closest-replicas` 或 `closest-adaptive` 时,你需要配置集群以确保副本按照指定的设置分布在各个可用区。请参考[通过拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md)为 PD 配置 `location-labels` 并为 TiDB 和 TiKV 设置正确的 `labels`。TiDB 依赖 `zone` 标签匹配位于同一可用区的 TiKV,因此请**务必**在 PD 的 `location-labels` 配置中包含 `zone` 并确保每个 TiDB 和 TiKV 节点的 `labels` 配置中包含 `zone`。如果是使用 TiDB Operator 部署的集群,请参考[数据的高可用](https://docs.pingcap.com/zh/tidb-in-kubernetes/v1.4/configure-a-tidb-cluster#%E6%95%B0%E6%8D%AE%E7%9A%84%E9%AB%98%E5%8F%AF%E7%94%A8)进行配置。 +> 当 `tidb_replica_read` 的值设置为 `closest-replicas` 或 `closest-adaptive` 时,你需要配置集群以确保副本按照指定配置分布在可用区中。要为 PD 配置 `location-labels` 并为 TiDB 和 TiKV 设置正确的 `labels`,请参考[通过拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md)。TiDB 依赖 `zone` 标签来匹配同一可用区内的 TiKV 节点,因此你需要确保 `zone` 标签包含在 PD 的 `location-labels` 中,并且 `zone` 包含在每个 TiDB 和 TiKV 节点的配置中。如果你的集群是使用 TiDB Operator 部署的,请参考[数据的高可用](https://docs.pingcap.com/tidb-in-kubernetes/v1.4/configure-a-tidb-cluster#high-availability-of-data)。 + + ## 实现机制 -在 Follower Read 功能出现之前,TiDB 采用 strong leader 策略将所有的读写操作全部提交到 Region 的 leader 节点上完成。虽然 TiKV 能够很均匀地将 Region 分散到多个物理节点上,但是对于每一个 Region 来说,只有 leader 副本能够对外提供服务,另外的 follower 除了时刻同步数据准备着 failover 时投票切换成为 leader 外,没有办法对 TiDB 的请求提供任何帮助。 +在引入 Follower Read 功能之前,TiDB 采用强 leader 原则,将所有读写请求提交给 Region 的 leader 节点处理。虽然 TiKV 可以在多个物理节点上均匀分布 Region,但对于每个 Region,只有 leader 可以提供外部服务。其他 follower 除了接收来自 leader 复制的数据并准备在故障转移时进行 leader 选举投票外,无法处理读取请求。 -为了允许在 TiKV 的 follower 节点进行数据读取,同时又不破坏线性一致性和 Snapshot Isolation 的事务隔离,Region 的 follower 节点需要使用 Raft `ReadIndex` 协议确保当前读请求可以读到当前 leader 上已经 commit 的最新数据。在 TiDB 层面,Follower Read 只需根据负载均衡策略将某个 Region 的读取请求发送到 follower 节点。 +为了允许在 follower 节点进行数据读取而不违反线性一致性或影响 TiDB 的快照隔离,follower 节点需要使用 Raft 协议的 `ReadIndex` 来确保读取请求可以读取到已在 leader 上提交的最新数据。在 TiDB 层面,Follower Read 功能只需要根据负载均衡策略将 Region 的读取请求发送到 follower 副本即可。 -### Follower 强一致读 +### 强一致性读取 -TiKV follower 节点处理读取请求时,首先使用 Raft `ReadIndex` 协议与 Region 当前的 leader 进行一次交互,来获取当前 Raft group 最新的 commit index。本地 apply 到所获取的 leader 最新 commit index 后,便可以开始正常的读取请求处理流程。 +当 follower 节点处理读取请求时,它首先使用 Raft 协议的 `ReadIndex` 与 Region 的 leader 交互,以获取当前 Raft 组的最新提交索引。在 leader 的最新提交索引在本地应用到 follower 后,才开始处理读取请求。 ### 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 发生故障或者因调度策略发生调整的情况下才会进行切换。如果同一事务内既有点查请求又有 Coprocessor 请求,两种请求都将按照上述调度策略分别进行读取,即使 Coprocessor 和点查出现在同一个 Region 上,TiDB 也会当作独立事件来处理。 +由于 Follower Read 功能不影响 TiDB 的快照隔离事务隔离级别,TiDB 采用轮询策略来选择 follower 副本。目前,对于 coprocessor 请求,Follower Read 负载均衡策略的粒度是在连接级别。对于连接到特定 Region 的 TiDB 客户端,选择的 follower 是固定的,只有在失败或调整调度策略时才会切换。 + +然而,对于非 coprocessor 请求,如点查询,Follower Read 负载均衡策略的粒度是在事务级别。对于特定 Region 上的 TiDB 事务,选择的 follower 是固定的,只有在失败或调度策略调整时才会切换。如果一个事务同时包含点查询和 coprocessor 请求,这两种类型的请求会根据前述调度策略分别进行读取调度。在这种情况下,即使 coprocessor 请求和点查询针对同一个 Region,TiDB 也会将它们作为独立事件处理。 diff --git a/foreign-key.md b/foreign-key.md index 3fda884b5076..5b298f266b41 100644 --- a/foreign-key.md +++ b/foreign-key.md @@ -1,18 +1,18 @@ --- title: 外键约束 -summary: TiDB 数据库中外键约束的使用概况。 +summary: TiDB 数据库中外键约束的使用概述。 --- # 外键约束 -从 v6.6.0 开始,TiDB 支持外键以及外键约束功能,外键允许跨表交叉引用相关数据,外键约束则可以保证相关数据的一致性。 +从 v6.6.0 开始,TiDB 支持外键功能,允许跨表引用相关数据,并通过外键约束维护数据一致性。 > **警告:** > -> - 外键功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 -> - 外键功能通常用于强制执行[参照完整性](https://zh.wikipedia.org/wiki/%E5%8F%82%E7%85%A7%E5%AE%8C%E6%95%B4%E6%80%A7)约束检查。使用该功能可能会导致性能下降,在将其应用于性能敏感的场景前,建议先进行全面测试。 +> - 目前,外键功能处于实验阶段。不建议在生产环境中使用。此功能可能会在没有预先通知的情况下发生变更或移除。如果发现 bug,你可以在 GitHub 上提交[问题](https://github.com/pingcap/tidb/issues)。 +> - 外键功能通常用于强制执行[引用完整性](https://en.wikipedia.org/wiki/Referential_integrity)约束检查。它可能会导致性能下降,因此建议在性能敏感的场景中使用之前进行充分测试。 -外键是在子表中定义的,语法如下: +外键在子表中定义。语法如下: ```ebnf+diagram ForeignKeyDef @@ -34,47 +34,47 @@ ReferenceOption 外键的命名遵循以下规则: -- 如果在 `CONSTRAINT identifier` 语句中指定了名称,则使用该名称。 -- 如果 `CONSTRAINT identifier` 语句未指定名称,但在 `FOREIGN KEY identifier` 语句中指定了名称,则使用 `FOREIGN KEY identifier` 定义的名称。 -- 如果 `CONSTRAINT identifier` 和 `FOREIGN KEY identifier` 语句都没有指定名称,则会自动生成一个名称,例如 `fk_1`、`fk_2`、`fk_3` 等。 -- 外键名称必须在当前表中唯一,否则创建时会报错 `ERROR 1826: Duplicate foreign key constraint name 'fk'`。 +- 如果在 `CONSTRAINT identifier` 中指定了名称,则使用指定的名称。 +- 如果在 `CONSTRAINT identifier` 中未指定名称,但在 `FOREIGN KEY identifier` 中指定了名称,则使用 `FOREIGN KEY identifier` 中指定的名称。 +- 如果 `CONSTRAINT identifier` 和 `FOREIGN KEY identifier` 都未指定名称,则自动生成名称,如 `fk_1`、`fk_2` 和 `fk_3`。 +- 外键名称在当前表中必须唯一。否则,在创建外键时会报错 `ERROR 1826: Duplicate foreign key constraint name 'fk'`。 ## 限制 -创建外键时需要满足以下条件: +创建外键时必须满足以下条件: - 父表和子表都不能是临时表。 -- 用户需要对父表有 `REFERENCES` 权限。 -- 外键中的列和引用的父表中的列必须是相同的数据类型,并具有相同的大小、精度、长度、字符集 (charset) 和排序规则 (collation)。 +- 用户必须对父表具有 `REFERENCES` 权限。 +- 父表和子表中外键引用的列必须具有相同的数据类型和相同的大小、精度、长度、字符集和排序规则。 - 外键中的列不能引用自身。 -- 外键中的列和引用的父表中的列必须有相同的索引,并且索引中的列顺序必须与外键的列顺序一样,这样才能在执行外键约束检查时使用索引来避免全表扫描。 +- 外键中的列和父表中被引用的列必须具有相同的索引,并且索引中列的顺序与外键中的顺序匹配。这是为了在执行外键约束检查时使用索引来避免全表扫描。 - - 如果父表中没有对应的外键索引,则会报错 `ERROR 1822: Failed to add the foreign key constraint. Missing index for constraint 'fk' in the referenced table 't'`。 - - 如果子表中没有对应的外键索引,则会自动创建一个索引,索引名和外键名一样。 + - 如果父表中没有相应的外键索引,会报错 `ERROR 1822: Failed to add the foreign key constraint. Missing index for constraint 'fk' in the referenced table 't'`。 + - 如果子表中没有相应的外键索引,会自动创建一个与外键同名的索引。 -- 不支持在 `BLOB` 和 `TEXT` 类型的列上创建外键。 +- 不支持在 `BLOB` 或 `TEXT` 类型的列上创建外键。 - 不支持在分区表上创建外键。 -- 不支持在虚拟生成列 (`VIRTUAL GENERATED COLUMNS`) 上创建外键。 +- 不支持在虚拟生成列上创建外键。 ## 引用操作 -当 `UPDATE` 或 `DELETE` 操作影响父表中的外键值时,其在子表中相匹配的外键值取决于外键定义中 `ON UPDATE` 和 `ON DELETE` 定义的引用操作,引用操作包括: +如果 `UPDATE` 或 `DELETE` 操作影响父表中的外键值,子表中相应的外键值由外键定义中的 `ON UPDATE` 或 `ON DELETE` 子句定义的引用操作决定。引用操作包括以下几种: -- `CASCADE`:当 `UPDATE` 或 `DELETE` 父表中的行数据时,自动级联更新或删除子表中的匹配行数据。级联操作会用深度优先方式执行。 -- `SET NULL`:当 `UPDATE` 或 `DELETE` 父表中的行数据时,自动将子表中匹配的外键列数据设置为 `NULL`。 -- `RESTRICT`:如果子表中存在外键匹配的行数据,则拒绝 `UPDATE` 或 `DELETE` 父表的操作。 -- `NO ACTION`:行为和 `RESTRICT` 一样。 -- `SET DEFAULT`:行为和 `RESTRICT` 一样。 +- `CASCADE`:当 `UPDATE` 或 `DELETE` 操作影响父表时,自动更新或删除子表中的匹配行。级联操作以深度优先的方式执行。 +- `SET NULL`:当 `UPDATE` 或 `DELETE` 操作影响父表时,自动将子表中匹配的外键列设置为 `NULL`。 +- `RESTRICT`:如果子表中存在匹配的行,则拒绝 `UPDATE` 或 `DELETE` 操作。 +- `NO ACTION`:与 `RESTRICT` 相同。 +- `SET DEFAULT`:与 `RESTRICT` 相同。 -如果父表中没有匹配的外键值,则拒绝 `INSERT` 或 `UPDATE` 子表的操作。 +如果父表中没有匹配的外键值,则拒绝对子表的 `INSERT` 或 `UPDATE` 操作。 -如果外键定义中没有指定 `ON DELETE` 或者 `ON UPDATE`,则默认的行为是 `NO ACTION`。 +如果外键定义中未指定 `ON DELETE` 或 `ON UPDATE`,则默认行为是 `NO ACTION`。 -如果外键是定义在 `STORED GENERATED COLUMN` 上的,则不支持使用 `CASCADE`、`SET NULL` 和 `SET DEFAULT` 引用操作。 +如果外键定义在 `STORED GENERATED COLUMN` 上,则不支持 `CASCADE`、`SET NULL` 和 `SET DEFAULT` 引用。 ## 外键使用示例 -下面的示例通过单列外键关联父表和子表: +以下示例使用单列外键关联父表和子表: ```sql CREATE TABLE parent ( @@ -89,7 +89,7 @@ CREATE TABLE child ( ); ``` -下面是一个更复杂的示例,其中 `product_order` 表有两个外键分别引用其他两个表。一个外键引用 `product` 表中的两列索引。另一个引用 `customer` 表中的单列索引: +以下是一个更复杂的示例,其中 `product_order` 表有两个外键引用其他两个表。一个外键引用 `product` 表上的两个索引,另一个引用 `customer` 表上的单个索引: ```sql CREATE TABLE product ( @@ -122,9 +122,9 @@ CREATE TABLE product_order ( ); ``` -## 新增外键约束 +## 创建外键约束 -可以使用下面 `ALTER TABLE` 语句来新增一个外键约束: +要创建外键约束,你可以使用以下 `ALTER TABLE` 语句: ```sql ALTER TABLE table_name @@ -135,17 +135,17 @@ ALTER TABLE table_name [ON UPDATE reference_option] ``` -外键可以是自引用的,即引用同一个表。使用 `ALTER TABLE` 向表添加外键约束时,请先在外键引用父表的列上创建索引。 +外键可以是自引用的,即引用同一个表。当你使用 `ALTER TABLE` 向表添加外键约束时,需要先在父表的被引用列上创建索引。 ## 删除外键约束 -可以使用下面 `ALTER TABLE` 语句来删除一个外键约束: +要删除外键约束,你可以使用以下 `ALTER TABLE` 语句: ```sql ALTER TABLE table_name DROP FOREIGN KEY fk_identifier; ``` -如果外键约束在创建时定义了名称,则可以引用该名称来删除外键约束。否则,只能引用自动生成的约束名称进行删除。你可以使用 `SHOW CREATE TABLE` 查看外键名称: +如果在创建外键约束时指定了名称,你可以引用该名称来删除外键约束。否则,你必须使用自动生成的约束名称来删除约束。你可以使用 `SHOW CREATE TABLE` 查看外键名称: ```sql mysql> SHOW CREATE TABLE child\G @@ -161,30 +161,30 @@ Create Table: CREATE TABLE `child` ( ## 外键约束检查 -TiDB 支持是否开启外键约束检查,由系统变量 [`foreign_key_checks`](/system-variables.md#foreign_key_checks) 控制,其默认值是 `ON`,即开启外键约束检查,它有 `GLOBAL` 和 `SESSION` 两种作用域。在一般的操作中保持该变量开启可以保证外键引用关系的完整性。 +TiDB 支持外键约束检查,这由系统变量 [`foreign_key_checks`](/system-variables.md#foreign_key_checks) 控制。默认情况下,该变量设置为 `ON`,表示启用外键约束检查。该变量有两个作用域:`GLOBAL` 和 `SESSION`。保持此变量启用可以确保外键引用关系的完整性。 -关闭外键约束检查的作用如下: +禁用外键约束检查的效果如下: -- 当删除一个被外键引用的父表时,只有关闭外键约束检查时才能删除成功。 -- 当给数据库导入数据时,创建表的顺序可能和外键依赖顺序不一样而导致创建表报错,只有关闭外键约束检查时才能创建表成功,另外,导入数据时关闭外键约束检查也能加快导数据的速度。 -- 当给数据库导入数据时,先导入子表的数据会报错,只有关闭外键约束检查,才能确保顺利导入子表数据。 -- 执行有关外键的 `ALTER TABLE` 操作时,关闭外键约束检查才能执行成功。 +- 当你删除被外键引用的父表时,只有在禁用外键约束检查的情况下才能成功删除。 +- 当你导入数据到数据库时,创建表的顺序可能与外键依赖顺序不同,这可能导致表创建失败。只有在禁用外键约束检查的情况下才能成功创建表。此外,禁用外键约束检查可以加快数据导入速度。 +- 当你导入数据到数据库时,如果先导入子表的数据,会报错。只有在禁用外键约束检查的情况下才能成功导入子表的数据。 +- 如果要执行的 `ALTER TABLE` 操作涉及外键的更改,只有在禁用外键约束检查的情况下才能成功执行。 -当关闭关键约束检查时,不会执行外键约束检查以及引用操作,但以下场景除外: +当外键约束检查被禁用时,不会执行外键约束检查和引用操作,但以下情况除外: -- 如果执行 `ALTER TABLE` 会导致外键定义不正确,则依然会执行报错。 -- 删除外键所需的索引时,需要先删除外键,否则删除外键会执行报错。 -- 创建外键时,如果不符合外键的条件或限制,则依然会执行报错。 +- 如果 `ALTER TABLE` 的执行可能导致外键定义错误,在执行过程中仍会报错。 +- 删除外键所需的索引时,应该先删除外键。否则会报错。 +- 当你创建外键但不满足相关条件或限制时,会报错。 -## 锁 +## 锁定 -在 `INSERT` 或者 `UPDATE` 子表时,外键约束会检查父表中是否存在对应的外键值,并对父表中的该行数据上锁,避免该外键值被其他操作删除,导致破坏外键约束。这里的上锁行为等同于对父表中外键值所在行做 `SELECT FOR UPDATE` 操作。 +当对子表执行 `INSERT` 或 `UPDATE` 时,外键约束会检查父表中是否存在相应的外键值,并锁定父表中的行以避免其他操作删除外键值而违反外键约束。锁定行为相当于对父表中外键值所在的行执行 `SELECT FOR UPDATE` 操作。 -因为 TiDB 目前暂不支持 `LOCK IN SHARE MODE`,所以,在并发写入子表场景,如果引用的外键值大部分都一样,可能会有比较严重的锁冲突。建议在大批量写入子表数据时,关闭 [`foreign_key_checks`](/system-variables.md#foreign_key_checks)。 +由于 TiDB 目前不支持 `LOCK IN SHARE MODE`,如果子表接受大量并发写入,且大多数被引用的外键值相同,可能会出现严重的锁定冲突。建议在写入大量子表数据时禁用 [`foreign_key_checks`](/system-variables.md#foreign_key_checks)。 -## 外键的定义和元信息 +## 外键的定义和元数据 -你可以使用 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 语句查看外键的定义: +要查看外键约束的定义,执行 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 语句: ```sql mysql> SHOW CREATE TABLE child\G @@ -198,15 +198,15 @@ Create Table: CREATE TABLE `child` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ``` -你可以使用以下任一系统表获取有关外键的信息: +你也可以使用以下任一系统表获取外键信息: - [`INFORMATION_SCHEMA.KEY_COLUMN_USAGE`](/information-schema/information-schema-key-column-usage.md) - [`INFORMATION_SCHEMA.TABLE_CONSTRAINTS`](/information-schema/information-schema-table-constraints.md) - [`INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS`](/information-schema/information-schema-referential-constraints.md) -下面提供了查询示例: +以下提供示例: -从 `INFORMATION_SCHEMA.KEY_COLUMN_USAGE` 系统表中获取有关的外键信息: +从 `INFORMATION_SCHEMA.KEY_COLUMN_USAGE` 系统表获取外键信息: ```sql mysql> SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA IS NOT NULL; @@ -220,7 +220,7 @@ mysql> SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORM +--------------+---------------+------------------+-----------------+ ``` -从 `INFORMATION_SCHEMA.TABLE_CONSTRAINTS` 系统表中获取有关的外键信息: +从 `INFORMATION_SCHEMA.TABLE_CONSTRAINTS` 系统表获取外键信息: ```sql mysql> SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE='FOREIGN KEY'\G @@ -233,7 +233,7 @@ TABLE_NAME | child CONSTRAINT_TYPE | FOREIGN KEY ``` -从 `INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS` 系统表中获取有关的外键信息: +从 `INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS` 系统表获取外键信息: ```sql mysql> SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS\G @@ -253,7 +253,7 @@ REFERENCED_TABLE_NAME | parent ## 查看带有外键的执行计划 -你可以使用 `EXPLAIN` 语句查看执行计划。`Foreign_Key_Check` 算子是执行 DML 语句时,执行外键约束检查的算子。 +你可以使用 `EXPLAIN` 语句查看执行计划。`Foreign_Key_Check` 算子对执行的 DML 语句执行外键约束检查。 ```sql mysql> explain insert into child values (1,1); @@ -265,7 +265,7 @@ mysql> explain insert into child values (1,1); +-----------------------+---------+------+---------------+-------------------------------+ ``` -你可以使用 `EXPLAIN ANALYZE` 语句查看外键引用行为的执行。`Foreign_Key_Cascade` 算子是执行 DML 语句时,执行外键引用行为的算子。 +你可以使用 `EXPLAIN ANALYZE` 语句查看外键引用行为的执行情况。`Foreign_Key_Cascade` 算子对执行的 DML 语句执行外键引用。 ```sql mysql> explain analyze delete from parent where id = 1; @@ -284,9 +284,9 @@ mysql> explain analyze delete from parent where id = 1; ## 兼容性 -### TiDB 版本间兼容性 +### TiDB 版本之间的兼容性 -TiDB 在 v6.6.0 之前已经支持创建外键的语法,但创建的外键并不生效。如果将之前创建的 TiDB 集群升级到 v6.6.0 及之后的版本,之前创建的外键依然是不生效的,可以先删除不生效的外键后再创建外键使外键约束生效。只有在 v6.6.0 及之后版本中新创建的外键才生效。你可以使用 `SHOW CREATE TABLE` 语句查看外键是否生效,不生效的外键会有一条 `/* FOREIGN KEY INVALID */` 注释。 +在 v6.6.0 之前,TiDB 支持创建外键的语法,但创建的外键是无效的。如果将 v6.6.0 之前创建的 TiDB 集群升级到 v6.6.0 或更高版本,升级前创建的外键仍然是无效的。只有在 v6.6.0 或更高版本中创建的外键才是有效的。你可以删除无效的外键并创建新的外键来使外键约束生效。你可以使用 `SHOW CREATE TABLE` 语句检查外键是否有效。无效的外键有 `/* FOREIGN KEY INVALID */` 注释。 ```sql mysql> SHOW CREATE TABLE child\G @@ -302,19 +302,29 @@ Create Table | CREATE TABLE `child` ( ### 与 TiDB 工具的兼容性 -- [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md) 不支持外键功能。 -- [DM](/dm/dm-overview.md) 不兼容外键功能。DM 在同步数据到下游 TiDB 时,会显式关闭下游 TiDB 的 [`foreign_key_checks`](/system-variables.md#foreign_key_checks),所以由外键产生的级联操作不会从上游同步到下游,这会导致上下游数据不一致。 -- [TiCDC](/ticdc/ticdc-overview.md) v6.6.0 兼容外键功能。旧版本的 TiCDC 在同步带外键的表时,可能会报错,建议使用 v6.6.0 之前版本 TiCDC 时先关闭下游 TiDB 集群的 `foreign_key_checks`。 -- [BR](/br/backup-and-restore-overview.md) v6.6.0 兼容外键功能。之前版本的 BR 在恢复带外键的表到 v6.6.0 及之后版本的集群时,可能会报错,建议先关闭下游 TiDB 集群的 `foreign_key_checks` 后再恢复集群。 -- [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 导入数据到 TiDB 前,如果目标表使用了外键,建议先关闭 TiDB 集群的 `foreign_key_checks`。对于 v6.6.0 之前的版本,关闭该系统变量也不会生效,你需要为下游数据库用户添加 `REFERENCES` 权限,或者提前手动在下游数据库中创建好目标表,以确保顺利导入数据。 -- [Dumpling](/dumpling-overview.md) 兼容外键功能。 -- [sync-diff-inspector](/sync-diff-inspector/sync-diff-inspector-overview.md) 在对比上下游数据时,如果上下游数据库的版本不一样,且下游 TiDB 中存在[不生效的外键](#tidb-版本间兼容性),则 sync-diff-inspector 可能会报上下游表结构不一致的错误。因为 TiDB v6.6.0 会对表结构中不生效的外键添加一条 `/* FOREIGN KEY INVALID */` 注释。 + + +- [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md) 不支持外键。 +- [DM](/dm/dm-overview.md) 不支持外键。DM 在将数据复制到 TiDB 时会禁用下游 TiDB 的 [`foreign_key_checks`](/system-variables.md#foreign_key_checks)。因此,由外键引起的级联操作不会从上游复制到下游,这可能导致数据不一致。 +- [TiCDC](/ticdc/ticdc-overview.md) v6.6.0 兼容外键。早期版本的 TiCDC 在复制带有外键的表时可能会报错。建议在使用早于 v6.6.0 的 TiCDC 版本时禁用下游 TiDB 集群的 `foreign_key_checks`。 +- [BR](/br/backup-and-restore-overview.md) v6.6.0 兼容外键。早期版本的 BR 在将带有外键的表恢复到 v6.6.0 或更高版本的集群时可能会报错。建议在使用早于 v6.6.0 的 BR 版本恢复集群时禁用下游 TiDB 集群的 `foreign_key_checks`。 +- 当你使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 时,如果目标表使用外键,建议在导入数据前禁用下游 TiDB 集群的 `foreign_key_checks`。对于早于 v6.6.0 的版本,禁用此系统变量不会生效,你需要为下游数据库用户授予 `REFERENCES` 权限,或者提前在下游数据库中手动创建目标表,以确保数据导入顺利进行。 + + + +- [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview) 兼容外键。 + + + +- 当你使用 [sync-diff-inspector](/sync-diff-inspector/sync-diff-inspector-overview.md) 比较上下游数据库之间的数据时,如果数据库版本不同,且下游 TiDB 中存在[无效的外键](#tidb-版本之间的兼容性),sync-diff-inspector 可能会报告表结构不一致错误。这是因为 TiDB v6.6.0 为无效的外键添加了 `/* FOREIGN KEY INVALID */` 注释。 + + ### 与 MySQL 的兼容性 -创建外键未指定名称时,TiDB 自动生成的外键名称和 MySQL 不一样。例如 TiDB 生成的外键名称为 `fk_1`、`fk_2`、`fk_3` 等,MySQL 生成的外键名称为 `table_name_ibfk_1`、 `table_name_ibfk_2`、`table_name_ibfk_3` 等。 +当你创建外键而不指定名称时,TiDB 生成的名称与 MySQL 生成的名称不同。例如,TiDB 生成的外键名称是 `fk_1`、`fk_2` 和 `fk_3`,而 MySQL 生成的外键名称是 `table_name_ibfk_1`、`table_name_ibfk_2` 和 `table_name_ibfk_3`。 -MySQL 和 TiDB 均能解析但会忽略以内联 `REFERENCES` 的方式定义的外键。只有当 `REFERENCES` 作为 `FOREIGN KEY` 定义的一部分时,才会进行检查和执行。下面的示例在定义外键约束时只使用了 `REFERENCES`: +MySQL 和 TiDB 都会解析但忽略"内联 `REFERENCES` 规范"。只有作为 `FOREIGN KEY` 定义一部分的 `REFERENCES` 规范才会被检查和强制执行。以下示例使用 `REFERENCES` 子句创建外键约束: ```sql CREATE TABLE parent ( @@ -329,7 +339,7 @@ CREATE TABLE child ( SHOW CREATE TABLE child; ``` -输出结果显示 `child` 表不包含任何外键: +输出显示 `child` 表不包含任何外键: ```sql +-------+-------------------------------------------------------------+ diff --git a/functions-and-operators/aggregate-group-by-functions.md b/functions-and-operators/aggregate-group-by-functions.md index d097a473a7b2..932e9ed4d5c6 100644 --- a/functions-and-operators/aggregate-group-by-functions.md +++ b/functions-and-operators/aggregate-group-by-functions.md @@ -1,46 +1,44 @@ --- -title: GROUP BY 聚合函数 -summary: TiDB支持的聚合函数包括 COUNT、COUNT(DISTINCT)、SUM、AVG、MAX、MIN、GROUP_CONCAT、VARIANCE、VAR_POP、STD、STDDEV、VAR_SAMP、STDDEV_SAMP 和 JSON_OBJECTAGG。除了 GROUP_CONCAT 和 APPROX_PERCENTILE 外,这些聚合函数可以作为窗口函数使用。另外,TiDB 的 GROUP BY 子句支持 WITH ROLLUP 修饰符,还支持 SQL 模式 ONLY_FULL_GROUP_BY。与 MySQL 的区别在于 TiDB 对标准 SQL 有一些扩展,允许在 HAVING 子句中使用别名和非列表达式。 +title: 聚合(GROUP BY)函数 +summary: 了解 TiDB 支持的聚合函数。 --- -# GROUP BY 聚合函数 +# 聚合(GROUP BY)函数 -本文将详细介绍 TiDB 支持的聚合函数。 +本文档详细介绍了 TiDB 支持的聚合函数。 -## TiDB 支持的聚合函数 +## 支持的聚合函数 -TiDB 支持的 MySQL `GROUP BY` 聚合函数如下所示: +本节介绍 TiDB 支持的 MySQL `GROUP BY` 聚合函数。 -| 函数名 | 功能描述 | -|:---------|:--------------------| -| [`COUNT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count) | 返回检索到的行的数目| -| [`COUNT(DISTINCT)`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct) | 返回不同值的数目 | -| [`SUM()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_sum) | 返回和 | -| [`AVG()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_avg) | 返回平均值 | -| [`MAX()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max) | 返回最大值 | -| [`MIN()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min) | 返回最小值 | -| [`GROUP_CONCAT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat) | 返回连接的字符串 | -| [`VARIANCE()`,`VAR_POP()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-pop) | 返回总体标准方差 | -| [`STD()`,`STDDEV()`,`STDDEV_POP`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_std) | 返回总体标准差 | -| [`VAR_SAMP()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-samp) | 返回采样方差 | -| [`STDDEV_SAMP()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-samp) | 返回采样标准方差 | -| [`JSON_ARRAYAGG()`](/functions-and-operators/json-functions/json-functions-aggregate.md#json_arrayagg) | 将结果集返回为单个 JSON 数组 | -| [`JSON_OBJECTAGG()`](/functions-and-operators/json-functions/json-functions-aggregate.md#json_objectagg) | 将结果集返回为单个含 (key, value) 键值对的 JSON 对象 | +| 名称 | 描述 | +|:---------------------------------------------------------------------------------------------------------------|:--------------------------------------------------| +| [`COUNT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count) | 返回返回行数的计数 | +| [`COUNT(DISTINCT)`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct) | 返回不同值的计数 | +| [`SUM()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_sum) | 返回总和 | +| [`AVG()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_avg) | 返回参数的平均值 | +| [`MAX()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max) | 返回最大值 | +| [`MIN()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min) | 返回最小值 | +| [`GROUP_CONCAT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat) | 返回连接后的字符串 | +| [`VARIANCE()`, `VAR_POP()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-pop) | 返回总体标准方差 | +| [`STD()`, `STDDEV()`, `STDDEV_POP`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_std) | 返回总体标准差 | +| [`VAR_SAMP()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-samp) | 返回样本方差 | +| [`STDDEV_SAMP()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-samp) | 返回样本标准差 | +| [`JSON_ARRAYAGG()`](/functions-and-operators/json-functions/json-functions-aggregate.md#json_arrayagg) | 将结果集作为单个 JSON 数组返回 | +| [`JSON_OBJECTAGG()`](/functions-and-operators/json-functions/json-functions-aggregate.md#json_objectagg) | 将结果集作为包含键值对的单个 JSON 对象返回 | -> **注意:** -> -> - 除非另有说明,否则聚合函数默认忽略 `NULL` 值。 -> - 如果在不包含 `GROUP BY` 子句的语句中使用聚合函数,则相当于对所有行进行分组。 +- 除非另有说明,分组函数会忽略 `NULL` 值。 +- 如果在不包含 `GROUP BY` 子句的语句中使用分组函数,则等同于对所有行进行分组。 -另外,TiDB 还支持以下聚合函数: +此外,TiDB 还提供以下聚合函数: + `APPROX_PERCENTILE(expr, constant_integer_expr)` - 该函数用于计算 `expr` 值的百分位数。参数 `constant_integer_expr` 是一个取值为区间 `[1,100]` 内整数的常量表达式,表示百分数。一个百分位数 Pk(`k`为百分数)表示数据集中至少有 `k%` 的数据小于等于 Pk。 + 此函数返回 `expr` 的百分位数。`constant_integer_expr` 参数表示百分比值,是范围在 `[1,100]` 内的常量整数。百分位数 Pk(`k` 表示百分比)表示数据集中至少有 `k%` 的值小于或等于 Pk。 - 该函数中,表达式的返回结果必须为[数值类型](/data-type-numeric.md)或[日期与时间类型](/data-type-date-and-time.md)。函数不支持计算其他类型的返回结果,并直接返回 `NULL`。 + 此函数仅支持 [数值类型](/data-type-numeric.md) 和 [日期时间类型](/data-type-date-and-time.md) 作为 `expr` 的返回类型。对于其他返回类型,`APPROX_PERCENTILE` 仅返回 `NULL`。 - 以下是一个计算第 50 百分位数的例子: + 以下示例展示如何计算 `INT` 列的第五十百分位数: ```sql DROP TABLE IF EXISTS t; @@ -63,9 +61,9 @@ TiDB 支持的 MySQL `GROUP BY` 聚合函数如下所示: + `APPROX_COUNT_DISTINCT(expr, [expr...])` - 该函数的功能与 `COUNT(DISTINCT)` 相似,用于统计不同值的数量,但返回的是一个近似值。它采用 `BJKST` 算法,在处理具有幂律分布特征的大规模数据集时,可以显著降低内存消耗。此外,对于低基数 (low cardinality) 的数据,该函数的结果准确性较高,同时对 CPU 的使用效率也较优。 + 此函数类似于 `COUNT(DISTINCT)`,用于计算不同值的数量,但返回的是近似结果。它使用 `BJKST` 算法,在处理具有幂律分布的大型数据集时显著减少内存消耗。此外,对于低基数数据,该函数在保持高效 CPU 利用率的同时提供高精度。 - 以下是一个使用该函数的示例: + 以下示例展示如何使用此函数: ```sql DROP TABLE IF EXISTS t; @@ -87,27 +85,22 @@ TiDB 支持的 MySQL `GROUP BY` 聚合函数如下所示: 2 rows in set (0.00 sec) ``` -上述聚合函数除 `GROUP_CONCAT()`、 `APPROX_PERCENTILE()` 和 `APPROX_COUNT_DISTINCT` 以外,均可作为[窗口函数](/functions-and-operators/window-functions.md)使用。 +除了 `GROUP_CONCAT()`、`APPROX_PERCENTILE()` 和 `APPROX_COUNT_DISTINCT` 函数外,所有上述函数都可以作为[窗口函数](/functions-and-operators/window-functions.md)使用。 ## GROUP BY 修饰符 -自 v7.4.0 起,TiDB 的 `GROUP BY` 子句支持 `WITH ROLLUP` 修饰符。详情请参阅 [GROUP BY 修饰符](/functions-and-operators/group-by-modifier.md)。 +从 v7.4.0 开始,TiDB 的 `GROUP BY` 子句支持 `WITH ROLLUP` 修饰符。更多信息,请参见 [GROUP BY 修饰符](/functions-and-operators/group-by-modifier.md)。 -## 对 SQL 模式的支持 +## SQL 模式支持 -TiDB 支持 SQL 模式 `ONLY_FULL_GROUP_BY`,当启用该模式时,TiDB 拒绝不明确的非聚合列的查询。例如,以下查询在启用 `ONLY_FULL_GROUP_BY` 时是不合规的,因为 `SELECT` 列表中的非聚合列 "b" 在 `GROUP BY` 语句中不显示: +TiDB 支持 SQL 模式 `ONLY_FULL_GROUP_BY`,启用时 TiDB 将拒绝包含不明确非聚合列的查询。例如,当启用 `ONLY_FULL_GROUP_BY` 时,以下查询是非法的,因为 `SELECT` 列表中的非聚合列 "b" 未出现在 `GROUP BY` 语句中: ```sql drop table if exists t; create table t(a bigint, b bigint, c bigint); insert into t values(1, 2, 3), (2, 2, 3), (3, 2, 3); -``` - -```sql -select a, b, sum(c) from t group by a; -``` -``` +mysql> select a, b, sum(c) from t group by a; +------+------+--------+ | a | b | sum(c) | +------+------+--------+ @@ -116,29 +109,19 @@ select a, b, sum(c) from t group by a; | 3 | 2 | 3 | +------+------+--------+ 3 rows in set (0.01 sec) -``` -```sql -set sql_mode = 'ONLY_FULL_GROUP_BY'; -``` - -``` +mysql> set sql_mode = 'ONLY_FULL_GROUP_BY'; Query OK, 0 rows affected (0.00 sec) -``` -```sql -select a, b, sum(c) from t group by a; -``` - -``` +mysql> 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`](/mysql-compatibility.md#sql-模式)。 +TiDB 目前默认启用 [`ONLY_FULL_GROUP_BY`](/mysql-compatibility.md#default-differences) 模式。 -### 与 MySQL 的区别 +### 与 MySQL 的差异 -TiDB 目前实现的 `ONLY_FULL_GROUP_BY` 没有 MySQL 5.7 严格。例如,假设我们执行以下查询,希望结果按 "c" 排序: +当前 `ONLY_FULL_GROUP_BY` 的实现比 MySQL 5.7 中的实现要宽松。例如,假设我们执行以下查询,期望结果按 "c" 排序: ```sql drop table if exists t; @@ -147,16 +130,16 @@ insert into t values(1, 2, 1), (1, 2, 2), (1, 3, 1), (1, 3, 2); select distinct a, b from t order by c; ``` -要对结果进行排序,必须先清除重复。但选择保留哪一行会影响 `c` 的保留值,也会影响排序,并使其具有任意性。 +要对结果进行排序,必须先消除重复项。但是,我们应该保留哪一行?这个选择会影响保留的 "c" 值,进而影响排序并使其变得任意。 -在 MySQL 中,`ORDER BY` 表达式需至少满足以下条件之一,否则 `DISTINCT` 和 `ORDER BY` 查询将因不合规而被拒绝: +在 MySQL 中,如果任何 `ORDER BY` 表达式不满足以下条件之一,则包含 `DISTINCT` 和 `ORDER BY` 的查询将被拒绝为无效: -- 表达式等同于 `SELECT` 列表中的一个。 -- 表达式引用并属于查询选择表的所有列都是 `SELECT` 列表的元素。 +- 该表达式等于 `SELECT` 列表中的一个表达式 +- 表达式引用的所有列都属于查询的选定表,并且是 `SELECT` 列表的元素 -但是在 TiDB 中,上述查询是合规的,详情参阅 [#4254](https://github.com/pingcap/tidb/issues/4254)。 +但在 TiDB 中,上述查询是合法的,更多信息请参见 [#4254](https://github.com/pingcap/tidb/issues/4254)。 -TiDB 中另一个标准 SQL 的扩展允许 `HAVING` 子句中的引用使用 `SELECT` 列表中的别名表达式。例如:以下查询返回在 `orders` 中只出现一次的 `name` 值 +TiDB 对标准 SQL 的另一个扩展是允许在 `HAVING` 子句中引用 `SELECT` 列表中的别名表达式。例如,以下查询返回表 "orders" 中只出现一次的 "name" 值: ```sql select name, count(name) from orders @@ -164,7 +147,7 @@ group by name having count(name) = 1; ``` -这个 TiDB 扩展允许在聚合列的 `HAVING` 子句中使用别名: +TiDB 扩展允许在 `HAVING` 子句中使用聚合列的别名: ```sql select name, count(name) as c from orders @@ -172,7 +155,7 @@ group by name having c = 1; ``` -标准 SQL 只支持 `GROUP BY` 子句中的列表达式,以下语句不合规,因为 `FLOOR(value/100)` 是一个非列表达式: +标准 SQL 仅允许在 `GROUP BY` 子句中使用列表达式,因此像这样的语句是无效的,因为 "FLOOR(value/100)" 是非列表达式: ```sql select id, floor(value/100) @@ -180,9 +163,9 @@ from tbl_name group by id, floor(value/100); ``` -TiDB 对标准 SQL 的扩展支持 `GROUP BY` 子句中非列表达式,认为上述语句合规。 +TiDB 扩展了标准 SQL,允许在 `GROUP BY` 子句中使用非列表达式,并认为上述语句有效。 -标准 SQL 也不支持 `GROUP BY` 子句中使用别名。TiDB 对标准 SQL 的扩展支持使用别名,查询的另一种写法如下: +标准 SQL 也不允许在 `GROUP BY` 子句中使用别名。TiDB 扩展了标准 SQL 以允许使用别名,因此可以这样编写查询: ```sql select id, floor(value/100) as val @@ -192,4 +175,4 @@ group by id, val; ## 相关系统变量 -[`group_concat_max_len`](/system-variables.md#group_concat_max_len) 变量设置 `GROUP_CONCAT()` 函数缓冲区的最大长度。 +[`group_concat_max_len`](/system-variables.md#group_concat_max_len) 变量设置 `GROUP_CONCAT()` 函数的最大项目数。 diff --git a/functions-and-operators/bit-functions-and-operators.md b/functions-and-operators/bit-functions-and-operators.md index f7725626db66..480360b0d6a9 100644 --- a/functions-and-operators/bit-functions-and-operators.md +++ b/functions-and-operators/bit-functions-and-operators.md @@ -1,27 +1,27 @@ --- -title: 位函数和操作符 -summary: TiDB 支持 MySQL 8.0 中的所有位函数和操作符。 +title: 位函数和运算符 +summary: 了解位函数和运算符。 --- -# 位函数和操作符 +# 位函数和运算符 -TiDB 支持使用 MySQL 8.0 中提供的所有[位函数和操作符](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html)。 +TiDB 支持 MySQL 8.0 中提供的所有[位函数和运算符](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html)。 -**位函数和操作符表** +**位函数和运算符:** -| 函数和操作符名 | 功能描述 | -| -------------- | ------------------------------------- | -| [`BIT_COUNT()`](#bit_count) | 返回参数二进制表示中为 1 的个数 | -| [&](#按位与) | 按位与 | -| [~](#按位取反) | 按位取反 | -| [\|](#按位或) | 按位或 | -| [`^`](#按位异或) | 按位异或 | -| [`<<`](#左移) | 左移 | -| [`>>`](#右移) | 右移 | +| 名称 | 描述 | +| :------| :------------- | +| [`BIT_COUNT()`](#bit_count) | 返回值为 1 的位数 | +| [&](#-bitwise-and) | 按位与 | +| [~](#-bitwise-inversion) | 按位取反 | +| [\|](#-bitwise-or) | 按位或 | +| [`^`](#-bitwise-xor) | 按位异或 | +| [`<<`](#-left-shift) | 左移 | +| [`>>`](#-right-shift) | 右移 | ## [`BIT_COUNT()`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#function_bit-count) -`BIT_COUNT(expr)` 函数返回 `expr` 中为 1 的位数。 +`BIT_COUNT(expr)` 函数返回 `expr` 中值为 1 的位数。 ```sql SELECT BIT_COUNT(b'00101001'); @@ -38,9 +38,9 @@ SELECT BIT_COUNT(b'00101001'); > **注意:** > -> 当输入的 `expr` 参数是一个二进制数时,你需要在这个数之前显式地指定 `b`,比如 `b'00101001'`。否则,该函数会将其视为字符串处理而返回不同的结果。例如,`BIT_COUNT('00101001')` 会返回 `7`,因为它会将字符串 `'00101001'` 转换为十进制数 `101001`,并计算 `101001` 的二进制表示 `11000100001010001` 中 `1` 的位数。 +> 如果参数 `expr` 是二进制数,你需要在数字前明确指定 `b`,例如 `b'00101001'`。否则,此函数会将其视为字符串并返回不同的结果。例如,`BIT_COUNT('00101001')` 返回 `7`,因为它将字符串 `'00101001'` 转换为十进制数 `101001`,并计算其二进制格式 `11000100001010001` 中 `1` 的位数。 -下面的示例与前面的类似,但使用的参数是十六进制数而非二进制数。`CONV()` 函数用于将 `0x29` 从十六进制转换为二进制,可以看到 `0x29` 等价于二进制的 `00101001`。 +以下示例与前面的类似,但使用十六进制字面量而不是位字面量作为参数。`CONV()` 函数将 `0x29` 从十六进制(基数 16)转换为二进制(基数 2),显示其二进制表示为 `00101001`。 ```sql SELECT BIT_COUNT(0x29), CONV(0x29,16,2); @@ -55,7 +55,7 @@ SELECT BIT_COUNT(0x29), CONV(0x29,16,2); 1 row in set (0.01 sec) ``` -`BIT_COUNT(expr)` 函数的一个常见用法是将子网掩码转换为 [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) 表示法。在下面的示例中,子网掩码 `255.255.255.0` 被转换为其 CIDR 表示形式 `24`。 +`BIT_COUNT(expr)` 函数的一个实际用途是将网络掩码转换为 [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) 表示法。在以下示例中,网络掩码 `255.255.255.0` 被转换为其 CIDR 表示 `24`。 ```sql SELECT BIT_COUNT(INET_ATON('255.255.255.0')); @@ -72,9 +72,9 @@ SELECT BIT_COUNT(INET_ATON('255.255.255.0')); ## [`&`(按位与)](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-and) -`&` 操作符用于执行按位与 (bitwise AND) 操作。它会比较两个数中的对应位,如果两个对应位都是 1,则结果中的对应位为 1,否则为 0。 +`&` 运算符执行按位与运算。它比较两个数字的对应位:如果两个对应位都为 1,则结果的对应位为 1;否则为 0。 -例如,对 `1010` 和 `1100` 进行按位与操作会返回 `1000`,因为在这两个数中只有最左边的第一位都是 1。 +例如,`1010` 和 `1100` 之间的按位与运算返回 `1000`,因为只有最左边的位在两个数字中都设置为 1。 ``` 1010 @@ -83,7 +83,7 @@ SELECT BIT_COUNT(INET_ATON('255.255.255.0')); 1000 ``` -在 SQL 中,可以这样使用 `&` 操作符: +在 SQL 中,你可以如下使用 `&` 运算符: ```sql SELECT CONV(b'1010' & b'1000',10,2); @@ -98,9 +98,9 @@ SELECT CONV(b'1010' & b'1000',10,2); 1 row in set (0.00 sec) ``` -你可以将 `&` 操作符与 `INET_NTOA()` 和 `INET_ATON()` 函数结合在一起使用,对 IP 地址和网络掩码进行按位与操作,以获取网络地址。这对于判断多个 IP 地址是否属于同一网络非常有用。 +你可以将 `&` 运算符与 `INET_NTOA()` 和 `INET_ATON()` 函数一起使用,对 IP 地址和网络掩码执行按位与运算以获取网络地址。这对于确定多个 IP 地址是否属于同一网络非常有用。 -在以下示例中,使用掩码 `255.255.255.0` 时,IP 地址 `192.168.1.1` 和 `192.168.1.2` 都属于同一网络 `192.168.1.0/24`。 +在以下两个示例中,IP 地址 `192.168.1.1` 和 `192.168.1.2` 在与 `255.255.255.0` 掩码后都属于同一网络 `192.168.1.0/24`。 ```sql SELECT INET_NTOA(INET_ATON('192.168.1.1') & INET_ATON('255.255.255.0')); @@ -130,18 +130,18 @@ SELECT INET_NTOA(INET_ATON('192.168.1.2') & INET_ATON('255.255.255.0')); ## [`~`(按位取反)](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-invert) -`~` 操作符用于对给定的值进行按位取反(bitwise NOT)操作。它会对给定值中的每一位进行取反:0 的位变为 1,1 的位变为 0。 +`~` 运算符对给定值执行按位取反(或按位非)运算。它对给定值的每一位进行取反:0 变为 1,1 变为 0。 -在进行取反操作之前,它会先将给定的值扩展到 64 位。 +在运算之前,该值会被扩展为 64 位。 -以二进制数 `1111000011110000` 为例。当扩展到 64 位并进行取反后,其结果如下: +以二进制数 `1111000011110000` 为例。当扩展到 64 位并取反时,它看起来是这样的: ``` -Original (16 bits): 1111000011110000 -Expanded and inverted (64 bits): 1111111111111111111111111111111111111111111111110000111100001111 +原始(16 位): 1111000011110000 +扩展并取反(64 位): 1111111111111111111111111111111111111111111111110000111100001111 ``` -在 SQL 中,可以这样使用 `~` 操作符: +在 SQL 中,你可以如下使用 `~` 运算符: ```sql SELECT CONV(~ b'1111000011110000',10,2); @@ -153,7 +153,7 @@ SELECT CONV(~ b'1111000011110000',10,2); 1 row in set (0.00 sec) ``` -如果需要对取反后的结果再次取反,可以再次应用 `~` 操作符。 +你可以通过对结果再次应用 `~` 运算符来反转取反操作: ```sql SELECT CONV(~ b'1111111111111111111111111111111111111111111111110000111100001111',10,2); @@ -170,9 +170,9 @@ SELECT CONV(~ b'1111111111111111111111111111111111111111111111110000111100001111 ## [`|`(按位或)](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-or) -`|` 操作符用于执行按位或 (bitwise OR) 操作。它会比较两个数中的对应位,如果至少有一个对应位为 1,则结果中的对应位为 1。 +`|` 运算符执行按位或运算。它比较两个数字的对应位:如果至少一个对应位为 1,则结果中的对应位为 1。 -例如,对 `1010` 和 `1100` 进行按位或操作会返回 `1110`,因为在这两个数的前三位中,至少有一个数的对应位为 1。 +例如,`1010` 和 `1100` 之间的按位或运算返回 `1110`,因为在两个数字的前三位中,至少有一个对应位设置为 1。 ``` 1010 @@ -181,7 +181,7 @@ SELECT CONV(~ b'1111111111111111111111111111111111111111111111110000111100001111 1110 ``` -在 SQL 中,可以这样使用 `|` 操作符: +在 SQL 中,你可以如下使用 `|` 运算符: ```sql SELECT CONV(b'1010' | b'1100',10,2); @@ -198,9 +198,9 @@ SELECT CONV(b'1010' | b'1100',10,2); ## [`^`(按位异或)](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-xor) -`^` 操作符用于执行按位异或 (bitwise XOR) 操作。它会比较两个数中的对应位,如果对应位不同,则结果中的对应位为 1。 +`^` 运算符执行按位异或(XOR)运算。它比较两个数字的对应位:如果对应位不同,则结果中的对应位为 1。 -例如,对 `1010` 和 `1100` 进行按位异或操作会返回 `0110`,因为这两个数中的第二位和第三位都不同。 +例如,`1010` 和 `1100` 之间的按位异或运算返回 `0110`,因为两个数字的第二位和第三位是不同的。 ``` 1010 @@ -209,7 +209,7 @@ SELECT CONV(b'1010' | b'1100',10,2); 0110 ``` -在 SQL 中,可以这样使用 `^` 操作符: +在 SQL 中,你可以如下使用 `^` 运算符: ```sql SELECT CONV(b'1010' ^ b'1100',10,2); @@ -224,13 +224,13 @@ SELECT CONV(b'1010' ^ b'1100',10,2); 1 row in set (0.00 sec) ``` -需要注意的是,由于省略了前导零,结果会显示为 `110` 而不是 `0110`。 +注意结果显示为 `110` 而不是 `0110`,因为前导零被删除了。 ## [`<<`(左移)](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_left-shift) -`<<` 操作符用于执行左移操作。它会将一个数中的所有位向左移动指定的位数,并用零填充右侧空出的位。 +`<<` 运算符执行左移运算,将数字的位向左移动指定的位数,在右侧用零填充空出的位。 -例如,下面的语句使用了 `1<>`(右移)](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_right-shift) -`>>` 操作符用于执行右移操作。它会将数中的所有位向右移动指定的位数,并用零填充左侧空出的位。 +`>>` 运算符执行右移运算,将数字的位向右移动指定的位数,在左侧用零填充空出的位。 -例如,下面的语句使用了 `1024>>n` 将数字 `1024`(二进制为 `10000000000`)向右移动了 `n` 位: +例如,以下语句使用 `1024>>n` 将值 `1024`(二进制为 `10000000000`)向右移动 `n` 个位置: ```sql WITH RECURSIVE cte(n) AS ( @@ -295,15 +295,15 @@ SELECT n,1024>>n,LPAD(CONV(1024>>n,10,2),11,0) FROM cte; 12 rows in set (0.00 sec) ``` -`>>` 操作符还可以用于提取一个大数中的特定部分,例如从 TiDB [TSO](/tso.md) 时间戳中提取 UNIX 时间戳。 +`>>` 运算符还可用于从较大的数字中提取特定部分,例如从 TiDB [TSO](/tso.md) 时间戳中提取 UNIX 时间戳。 ## MySQL 兼容性 -在处理位函数和操作符时,MySQL 8.0 与之前版本的 MySQL 之间存在一些差异。TiDB 旨在遵循 MySQL 8.0 的行为。 +MySQL 8.0 和早期版本的 MySQL 在处理位函数和运算符方面存在一些差异。TiDB 旨在遵循 MySQL 8.0 的行为。 ## 已知问题 -在以下情况中,TiDB 中的查询结果与 MySQL 5.7 相同,但与 MySQL 8.0 不同。 +在以下情况下,TiDB 中的查询结果与 MySQL 5.7 相同,但与 MySQL 8.0 不同。 -- 二进制参数的位操作。更多信息,请参考 [#30637](https://github.com/pingcap/tidb/issues/30637)。 -- `BIT_COUNT()` 函数的结果。更多信息,请参考 [#44621](https://github.com/pingcap/tidb/issues/44621)。 \ No newline at end of file +- 带有二进制参数的位运算。更多信息,请参见 [#30637](https://github.com/pingcap/tidb/issues/30637)。 +- `BIT_COUNT()` 函数的结果。更多信息,请参见 [#44621](https://github.com/pingcap/tidb/issues/44621)。 diff --git a/functions-and-operators/cast-functions-and-operators.md b/functions-and-operators/cast-functions-and-operators.md index f87330a1c4db..e9443e68f055 100644 --- a/functions-and-operators/cast-functions-and-operators.md +++ b/functions-and-operators/cast-functions-and-operators.md @@ -1,55 +1,53 @@ --- -title: Cast 函数和操作符 -summary: Cast 函数和操作符用于将某种数据类型的值转换为另一种数据类型。TiDB 支持使用 MySQL 8.0 中提供的所有 Cast 函数和操作符。 +title: 类型转换函数和运算符 +summary: 了解类型转换函数和运算符。 --- -# Cast 函数和操作符 +# 类型转换函数和运算符 -Cast 函数和操作符用于将某种数据类型的值转换为另一种数据类型。TiDB 支持使用 MySQL 8.0 中提供的所有 [Cast 函数和操作符](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html)。 +类型转换函数和运算符允许将值从一种数据类型转换为另一种数据类型。TiDB 支持 MySQL 8.0 中提供的所有[类型转换函数和运算符](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html)。 -## Cast 函数和操作符表 - -| 函数和操作符名 | 功能描述 | -| --------------- | ----------------------------------- | -| [`BINARY`](#binary) | 将一个字符串转换成一个二进制字符串 | -| [`CAST()`](#cast) | 将一个值转换成一个确定类型 | -| [`CONVERT()`](#convert) | 将一个值转换成一个确定类型 | +| 名称 | 描述 | +| ---------------------------------------- | -------------------------------- | +| [`BINARY`](#binary) | 将字符串转换为二进制字符串 | +| [`CAST()`](#cast) | 将值转换为指定类型 | +| [`CONVERT()`](#convert) | 将值转换为指定类型 | > **注意:** > -> TiDB 和 MySQL 对于 `SELECT CAST(MeN AS CHAR)`(或者等价的 `SELECT CONVERT(MeM, CHAR)`)的结果显示不一致,其中 `MeN` 是用科学计数法表示的双精度浮点数。MySQL 在 `-15 <= N <= 14` 时显示完整数值,在 `N < -15` 或 `N > 14` 时显示科学计数法。而 TiDB 始终显示完整数值。例如,MySQL 对于 `SELECT CAST(3.1415e15 AS CHAR)` 的显示结果为 `3.1415e15`,而 TiDB 的显示结果为 `3141500000000000`。 +> TiDB 和 MySQL 对于 `SELECT CAST(MeN AS CHAR)`(或其等效形式 `SELECT CONVERT(MeM, CHAR)`)显示不一致的结果,其中 `MeN` 表示科学记数法中的双精度浮点数。当 `-15 <= N <= 14` 时,MySQL 显示完整的数值,当 `N < -15` 或 `N > 14` 时显示科学记数法。但是,TiDB 始终显示完整的数值。例如,MySQL 显示 `SELECT CAST(3.1415e15 AS CHAR)` 的结果为 `3.1415e15`,而 TiDB 显示结果为 `3141500000000000`。 ## BINARY -[`BINARY`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#operator_binary) 运算符从 MySQL 8.0.27 版本起已被废弃。建议在 TiDB 和 MySQL 中都改用 `CAST(... AS BINARY)`。 +[`BINARY`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#operator_binary) 运算符自 MySQL 8.0.27 起已被弃用。建议在 TiDB 和 MySQL 中都使用 `CAST(... AS BINARY)` 代替。 ## CAST -[`CAST( AS [ARRAY])`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast) 函数用于将一个表达式的值转换为指定的数据类型。 +[`CAST( AS [ARRAY])`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast) 函数用于将表达式转换为指定类型。 -此外,你还可以将该函数用于创建[多值索引](/sql-statements/sql-statement-create-index.md#多值索引)。 +此函数也用于创建[多值索引](/sql-statements/sql-statement-create-index.md#multi-valued-indexes)。 -支持的数据类型包括: +支持以下类型: -| 类型 | 描述 | 是否可用于多值索引 | -|----------------------|------------------|------------------------------------------------| -| `BINARY(n)` | 二进制字符串 | 否 | -| `CHAR(n)` | 字符串 | 是,但仅当指定了长度时才有效 | -| `DATE` | 日期 | 是 | -| `DATETIME(fsp)` | 日期/时间,其中 `fsp` 是可选的 | 是 | -| `DECIMAL(n, m)` | 十进制数,其中 `n` 和 `m` 是可选的,如果未指定,则默认为 `10` 和 `0` | 否 | -| `DOUBLE` | 双精度浮点数 | 否 | -| `FLOAT(n)` | 浮点数,其中 `n` 是可选的,应介于 `0` 和 `53` 之间 | 否 | -| `JSON` | JSON | 否 | -| `REAL` | 浮点数 | 是 | -| `SIGNED [INTEGER]` | 有符号整数 | 是 | -| `TIME(fsp)` | 时间 | 是 | -| `UNSIGNED [INTEGER]` | 无符号整数 | 是 | -| `YEAR` | 年 | 否 | +| 类型 | 描述 | 是否可用于多值索引 | +|----------------------|------------------|------------------------------------------------------------| +| `BINARY(n)` | 二进制字符串 | 否 | +| `CHAR(n)` | 字符串 | 是,但仅当指定长度时 | +| `DATE` | 日期 | 是 | +| `DATETIME(fsp)` | 日期/时间,其中 `fsp` 是可选的 | 是 | +| `DECIMAL(n, m)` | 十进制数,其中 `n` 和 `m` 是可选的,如果未指定则分别为 `10` 和 `0` | 否 | +| `DOUBLE` | 双精度浮点数 | 否 | +| `FLOAT(n)` | 浮点数,其中 `n` 是可选的,应在 `0` 到 `53` 之间 | 否 | +| `JSON` | JSON | 否 | +| `REAL` | 浮点数 | 是 | +| `SIGNED [INTEGER]` | 有符号整数 | 是 | +| `TIME(fsp)` | 时间 | 是 | +| `UNSIGNED [INTEGER]` | 无符号整数 | 是 | +| `YEAR` | 年份 | 否 | 示例: -以下语句将二进制字符串从十六进制文字转换为 `CHAR`。 +以下语句将十六进制字面量的二进制字符串转换为 `CHAR`。 ```sql SELECT CAST(0x54694442 AS CHAR); @@ -64,7 +62,7 @@ SELECT CAST(0x54694442 AS CHAR); 1 row in set (0.0002 sec) ``` -以下语句将从 JSON 列中提取的 `a` 属性的值转换为无符号数组。需要注意的是,该函数只有作为多值索引定义的一部分时,才支持将数据转换为数组。 +以下语句将从 JSON 列中提取的 `a` 属性的值转换为无符号数组。注意,转换为数组仅支持作为多值索引定义的一部分。 ```sql CREATE TABLE t ( @@ -122,6 +120,6 @@ SELECT CONVERT(0x616263 USING utf8mb4); ## MySQL 兼容性 -- TiDB 不支持对空间类型 (`SPATIAL`) 进行转换操作。更多信息,请参考 [#6347](https://github.com/pingcap/tidb/issues/6347)。 -- TiDB 不支持在 `CAST()` 中使用 `AT TIME ZONE`。更多信息,请参考 [#51742](https://github.com/pingcap/tidb/issues/51742)。 -- `CAST(24 AS YEAR)` 在 TiDB 中返回的结果为两位数字,而在 MySQL 中返回的结果为四位数字。更多信息,请参考 [#29629](https://github.com/pingcap/tidb/issues/29629)。 \ No newline at end of file +- TiDB 不支持对 `SPATIAL` 类型进行类型转换操作。更多信息,请参见 [#6347](https://github.com/pingcap/tidb/issues/6347)。 +- TiDB 不支持 `CAST()` 的 `AT TIME ZONE`。更多信息,请参见 [#51742](https://github.com/pingcap/tidb/issues/51742)。 +- `CAST(24 AS YEAR)` 在 TiDB 中返回 2 位数字,在 MySQL 中返回 4 位数字。更多信息,请参见 [#29629](https://github.com/pingcap/tidb/issues/29629)。 diff --git a/functions-and-operators/control-flow-functions.md b/functions-and-operators/control-flow-functions.md index e75c232a5201..89c0228919c2 100644 --- a/functions-and-operators/control-flow-functions.md +++ b/functions-and-operators/control-flow-functions.md @@ -1,22 +1,22 @@ --- -title: 控制流程函数 -summary: TiDB 支持 MySQL 8.0 中的控制流程函数,包括 CASE、IF()、IFNULL() 和 NULLIF()。这些函数可以用于构建 if/else 语句和处理 NULL 值。 +title: 流程控制函数 +summary: 了解流程控制函数。 --- -# 控制流程函数 +# 流程控制函数 -TiDB 支持使用 MySQL 8.0 中提供的所有[控制流程函数](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html)。 +TiDB 支持 MySQL 8.0 中提供的所有[流程控制函数](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html)。 -| 函数名 | 功能描述 | -|:----------------------|:------------------------------| -| [`CASE`](#case) | Case 操作符 | -| [`IF()`](#if) | 构建 if/else | -| [`IFNULL()`](#ifnull) | 构建 Null if/else | -| [`NULLIF()`](#nullif) | 如果 expr1 = expr2,返回 `NULL` | +| 名称 | 描述 | +|:--------------------------------------------------------------------------------------------------|:----------------------------------| +| [`CASE`](#case) | Case 运算符 | +| [`IF()`](#if) | If/else 结构 | +| [`IFNULL()`](#ifnull) | Null if/else 结构 | +| [`NULLIF()`](#nullif) | 如果 expr1 = expr2,则返回 `NULL` | ## CASE -[`CASE`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) 操作符可以根据指定的条件进行条件逻辑判断并自定义查询结果。 +[`CASE`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) 运算符使你能够执行条件逻辑并根据指定条件自定义查询结果。 语法: @@ -56,7 +56,7 @@ SELECT n, CASE WHEN n MOD 2 THEN "odd" ELSE "even" END FROM d; ## IF() -[`IF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if) 函数可以根据值或表达式是否为真执行不同的操作。 +[`IF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if) 函数使你能够根据值或表达式是否为真来执行不同的操作。 语法: @@ -91,7 +91,7 @@ SELECT n, IF(n MOD 2, "odd", "even") FROM d; ## IFNULL() -[`IFNULL(expr1,expr2)`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) 函数用于处理查询中的 NULL 值。如果 `expr1` 不为 `NULL`,该函数返回 `expr1`;否则返回 `expr2`。 +[`IFNULL(expr1,expr2)`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) 函数用于处理查询中的 NULL 值。如果 `expr1` 不为 `NULL`,则返回 `expr1`;否则返回 `expr2`。 示例: @@ -112,7 +112,7 @@ SELECT x, IFNULL(x,'x has no value') FROM data; ## NULLIF() -[`NULLIF(expr1,expr2)`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_nullif) 函数用于在两个参数相同或第一个参数为 `NULL` 时返回 `NULL`。否则,返回第一个参数。 +[`NULLIF(expr1,expr2)`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_nullif) 函数在两个参数相同或第一个参数为 `NULL` 时返回 `NULL`。否则,返回第一个参数。 示例: @@ -139,4 +139,4 @@ SELECT n, NULLIF(n+n, n+2) FROM d; 10 rows in set (0.00 sec) ``` -在该示例中,当 `n` 等于 `2` 时,`n+n` 和 `n+2` 都等于 `4`,两个参数值相同,因此函数返回 `NULL`。 \ No newline at end of file +在此示例中,当 `n` 等于 `2` 时,`n+n` 和 `n+2` 都等于 `4`,使两个参数相同,导致函数返回 `NULL`。 diff --git a/functions-and-operators/date-and-time-functions.md b/functions-and-operators/date-and-time-functions.md index 44738f858326..6bb8c31e5057 100644 --- a/functions-and-operators/date-and-time-functions.md +++ b/functions-and-operators/date-and-time-functions.md @@ -1,100 +1,102 @@ --- title: 日期和时间函数 -summary: TiDB 支持 MySQL 8.0 中的所有日期和时间函数。 +summary: 了解如何使用日期和时间函数。 --- # 日期和时间函数 -TiDB 支持使用 MySQL 8.0 中提供的所有[日期和时间函数](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html)。 +TiDB 支持 MySQL 8.0 中提供的所有[日期和时间函数](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html)。 > **注意:** > -> - MySQL 常常会接受格式不正确的日期和时间值。例如,`'2020-01-01\n\t01:01:01'` 和 `'2020-01_01\n\t01:01'` 被视为有效的日期和时间值。 -> - TiDB 会尽量与 MySQL 的行为保持一致,但可能无法在所有情况下完全匹配。建议使用正确的格式化日期,TiDB 文档中未记录将如何处理格式不正确的值。 +> - MySQL 通常会接受格式不正确的日期和时间值。例如,`'2020-01-01\n\t01:01:01'` 和 `'2020-01_01\n\t01:01'` 会被视为有效的日期和时间值。 +> - TiDB 尽最大努力匹配 MySQL 的行为,但可能并非在所有情况下都能完全匹配。建议正确格式化日期,因为对于格式不正确的值的预期行为没有文档说明,而且通常是不一致的。 -## 日期时间函数表 +**日期/时间函数:** -| 函数名 | 功能描述 | -| ------ | ---------------------------------------- | -| [`ADDDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_adddate) | 将时间间隔添加到日期上 | -| [`ADDTIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_addtime) | 时间数值相加 | -| [`CONVERT_TZ()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_convert-tz) | 转换时区 | +| 名称 | 描述 | +| ---------------------------------------- | ---------------------------------------- | +| [`ADDDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_adddate) | 将时间值(间隔)添加到日期值 | +| [`ADDTIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_addtime) | 添加时间 | +| [`CONVERT_TZ()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_convert-tz) | 从一个时区转换到另一个时区 | | [`CURDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_curdate) | 返回当前日期 | -| [`CURRENT_DATE()`, `CURRENT_DATE`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_current-date) | 与 CURDATE() 同义 | -| [`CURRENT_TIME()`, `CURRENT_TIME`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_current-time) | 与 CURTIME() 同义 | -| [`CURRENT_TIMESTAMP()`, `CURRENT_TIMESTAMP`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_current-timestamp) | 与 NOW() 同义 | +| [`CURRENT_DATE()`, `CURRENT_DATE`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_current-date) | CURDATE() 的同义词 | +| [`CURRENT_TIME()`, `CURRENT_TIME`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_current-time) | CURTIME() 的同义词 | +| [`CURRENT_TIMESTAMP()`, `CURRENT_TIMESTAMP`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_current-timestamp) | NOW() 的同义词 | | [`CURTIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_curtime) | 返回当前时间 | -| [`DATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date) | 从日期或日期/时间表达式中提取日期部分| -| [`DATE_ADD()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-add) | 将时间间隔添加到日期上| -| [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format) | 返回满足指定格式的日期/时间 | -| [`DATE_SUB()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-sub) | 从日期减去指定的时间间隔 | -| [`DATEDIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_datediff) | 返回两个日期间隔的天数| -| [`DAY()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_day) | 与 DAYOFMONTH() 同义| -| [`DAYNAME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayname) | 返回星期名称 | -| [`DAYOFMONTH()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofmonth) | 返回参数对应的天数部分(1-31)| -| [`DAYOFWEEK()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofweek) | 返回参数对应的星期下标| -| [`DAYOFYEAR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofyear) | 返回参数代表一年的哪一天 (1-366) | -| [`EXTRACT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_extract) | 提取日期/时间中的单独部分| -| [`FROM_DAYS()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_from-days) | 将天数转化为日期 | +| [`DATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date) | 从日期或日期时间表达式中提取日期部分 | +| [`DATE_ADD()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-add) | 将时间值(间隔)添加到日期值 | +| [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format) | 按指定格式格式化日期 | +| [`DATE_SUB()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-sub) | 从日期中减去时间值(间隔) | +| [`DATEDIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_datediff) | 计算两个日期之差 | +| [`DAY()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_day) | DAYOFMONTH() 的同义词 | +| [`DAYNAME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayname) | 返回星期几的名称 | +| [`DAYOFMONTH()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofmonth) | 返回月份中的日期(0-31) | +| [`DAYOFWEEK()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofweek) | 返回参数的星期索引 | +| [`DAYOFYEAR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofyear) | 返回一年中的第几天(1-366) | +| [`EXTRACT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_extract) | 提取日期的部分内容 | +| [`FROM_DAYS()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_from-days) | 将天数转换为日期 | | [`FROM_UNIXTIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_from-unixtime) | 将 Unix 时间戳格式化为日期 | -| [`GET_FORMAT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_get-format) | 返回满足日期格式的字符串 | -| [`HOUR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour) | 提取日期/时间表达式中的小时部分 | -| [`LAST_DAY`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_last-day) | 返回参数中月份的最后一天 | -| [`LOCALTIME()`, `LOCALTIME`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_localtime) | 与 NOW() 同义 | -| [`LOCALTIMESTAMP`, `LOCALTIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_localtimestamp) | 与 NOW() 同义 | -| [`MAKEDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_makedate) | 根据给定的年份和一年中的天数生成一个日期 | -| [`MAKETIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_maketime) | 根据给定的时、分、秒生成一个时间 | -| [`MICROSECOND()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_microsecond) | 返回参数的微秒部分| -| [`MINUTE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_minute) | 返回参数的分钟部分| -| [`MONTH()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_month) | 返回参数的月份部分| -| [`MONTHNAME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_monthname) | 返回参数的月份名称| -| [`NOW()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_now) | 返回当前日期和时间| -| [`PERIOD_ADD()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-add) | 在年-月表达式上添加一段时间(数个月)| -| [`PERIOD_DIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-diff) | 返回间隔的月数| -| [`QUARTER()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_quarter) | 返回参数对应的季度(1-4) | -| [`SEC_TO_TIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sec-to-time) | 将秒数转化为 'HH:MM:SS' 的格式| -| [`SECOND()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_second) | 返回秒数(0-59) | -| [`STR_TO_DATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_str-to-date) | 将字符串转化为日期| -| [`SUBDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_subdate) | 当传入三个参数时作为 DATE_SUB() 的同义| -| [`SUBTIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_subtime) | 从一个时间中减去一段时间 | -| [`SYSDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sysdate) | 返回该方法执行时的时间| -| [`TIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time) | 返回参数的时间表达式部分 | -| [`TIME_FORMAT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time-format) | 格式化时间| -| [`TIME_TO_SEC()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time-to-sec) | 返回参数对应的秒数| -| [`TIMEDIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timediff) | 返回时间间隔 | -| [`TIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timestamp) | 传入一个参数时候,该方法返回日期或日期/时间表达式,传入两个参数时候,返回参数的和 | -| [`TIMESTAMPADD()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timestampadd) | 在日期/时间表达式上增加一段时间间隔 | -| [`TIMESTAMPDIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timestampdiff) | 从日期/时间表达式中减去一段时间间隔 | -| [`TO_DAYS()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_to-days) | 将参数转化对应的天数(从第 0 年开始) | -| [`TO_SECONDS()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_to-seconds) | 将日期或日期/时间参数转化为秒数(从第 0 年开始) | -| [`UNIX_TIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_unix-timestamp) | 返回一个 Unix 时间戳| -| [`UTC_DATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_utc-date) | 返回当前的 UTC 日期 | -| [`UTC_TIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_utc-time) | 返回当前的 UTC 时间 | -| [`UTC_TIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_utc-timestamp) | 返回当前的 UTC 日期和时间| -| [`WEEK()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_week) | 返回参数所在的一年中的星期数 | -| [`WEEKDAY()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekday) | 返回星期下标 | -| [`WEEKOFYEAR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekofyear) | 返回参数在日历中对应的一年中的星期数 | -| [`YEAR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_year) | 返回参数对应的年数| -| [`YEARWEEK()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_yearweek) | 返回年数和星期数 | +| [`GET_FORMAT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_get-format) | 返回日期格式字符串 | +| [`HOUR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour) | 提取小时 | +| [`LAST_DAY`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_last-day) | 返回参数的月份最后一天 | +| [`LOCALTIME()`, `LOCALTIME`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_localtime) | NOW() 的同义词 | +| [`LOCALTIMESTAMP`, `LOCALTIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_localtimestamp) | NOW() 的同义词 | +| [`MAKEDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_makedate) | 从年份和一年中的天数创建日期 | +| [`MAKETIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_maketime) | 从小时、分钟、秒创建时间 | +| [`MICROSECOND()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_microsecond) | 返回参数中的微秒 | +| [`MINUTE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_minute) | 返回参数中的分钟 | +| [`MONTH()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_month) | 返回传入日期的月份 | +| [`MONTHNAME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_monthname) | 返回月份名称 | +| [`NOW()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_now) | 返回当前日期和时间 | +| [`PERIOD_ADD()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-add) | 将周期添加到年月 | +| [`PERIOD_DIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-diff) | 返回两个周期之间的月数 | +| [`QUARTER()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_quarter) | 返回日期参数的季度 | +| [`SEC_TO_TIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sec-to-time) | 将秒转换为 'HH:MM:SS' 格式 | +| [`SECOND()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_second) | 返回秒数(0-59) | +| [`STR_TO_DATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_str-to-date) | 将字符串转换为日期 | +| [`SUBDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_subdate) | 当使用三个参数调用时,是 DATE_SUB() 的同义词 | +| [`SUBTIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_subtime) | 减去时间 | +| [`SYSDATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sysdate) | 返回函数执行时的时间 | +| [`TIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time) | 提取传入表达式的时间部分 | +| [`TIME_FORMAT()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time-format) | 格式化为时间 | +| [`TIME_TO_SEC()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time-to-sec) | 返回转换为秒的参数 | +| [`TIMEDIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timediff) | 计算时间差 | +| [`TIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timestamp) | 使用单个参数时,此函数返回日期或日期时间表达式;使用两个参数时,返回参数之和 | +| [`TIMESTAMPADD()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timestampadd) | 向日期时间表达式添加间隔 | +| [`TIMESTAMPDIFF()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timestampdiff) | 从日期时间表达式中减去间隔 | +| [`TO_DAYS()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_to-days) | 返回转换为天数的日期参数 | +| [`TO_SECONDS()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_to-seconds) | 返回转换为从公元 0 年开始的秒数的日期或日期时间参数 | +| [`UNIX_TIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_unix-timestamp) | 返回 Unix 时间戳 | +| [`UTC_DATE()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_utc-date) | 返回当前 UTC 日期 | +| [`UTC_TIME()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_utc-time) | 返回当前 UTC 时间 | +| [`UTC_TIMESTAMP()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_utc-timestamp) | 返回当前 UTC 日期和时间 | +| [`WEEK()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_week) | 返回周数 | +| [`WEEKDAY()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekday) | 返回星期索引 | +| [`WEEKOFYEAR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekofyear) | 返回日期的日历周(1-53) | +| [`YEAR()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_year) | 返回年份 | +| [`YEARWEEK()`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_yearweek) | 返回年份和周 | + +详情请参见[日期和时间函数](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html)。 ## MySQL 兼容性 -TiDB 支持 `STR_TO_DATE()` 函数,但是无法解析所有的日期和时间值。此外,TiDB 不支持以下日期和时间格式化选项: +TiDB 支持 `STR_TO_DATE()` 函数,但无法解析所有日期和时间值。此外,以下日期和时间格式选项**尚未实现**: -| 格式 | 说明 | +| 格式 | 描述 | |--------|---------------------------------------------------------------------------------------| -| "%a" | 星期名的缩写(例如 Sun..Sat) | -| "%D" | 带英文后缀的月份日期(例如 0th,1st,2nd,3rd) | -| "%U" | 星期 (00..53),星期日是每周的第一天;WEEK() mode 0 | -| "%u" | 星期 (00..53),星期一是每周的第一天;WEEK() mode 1 | -| "%V" | 星期 (01..53),星期日是每周的第一天;WEEK() mode 2;和 "%X" 一起使用 | -| "%v" | 星期 (01..53),星期一是每周的第一天;WEEK() mode 3;和 "%x" 一起使用 | -| "%W" | 星期名(例如 Sunday..Saturday) | -| "%w" | 一周中的天名 (0=Sunday..6=Saturday) | -| "%X" | 星期天是每周第一天的年份,数字类型,四位数字 | -| "%x" | 星期一是每周第一天的年份,数字类型,四位数字 | +| "%a" | 缩写的星期名称(Sun..Sat) | +| "%D" | 带有英文后缀的月份中的日期(0th, 1st, 2nd, 3rd) | +| "%U" | 周(00..53),其中星期日是一周的第一天;WEEK() 模式 0 | +| "%u" | 周(00..53),其中星期一是一周的第一天;WEEK() 模式 1 | +| "%V" | 周(01..53),其中星期日是一周的第一天;WEEK() 模式 2;与 %X 一起使用 | +| "%v" | 周(01..53),其中星期一是一周的第一天;WEEK() 模式 3;与 %x 一起使用 | +| "%W" | 星期名称(Sunday..Saturday) | +| "%w" | 一周中的第几天(0=Sunday..6=Saturday) | +| "%X" | 星期日作为一周第一天的周所在的年份,数字,四位。 | +| "%x" | 星期一作为一周第一天的周所在的年份,数字,四位。 | -更多信息,参见 [GitHub Issue #30082](https://github.com/pingcap/tidb/issues/30082)。 +更多详情请参见 [issue #30082](https://github.com/pingcap/tidb/issues/30082)。 ## 相关系统变量 diff --git a/functions-and-operators/encryption-and-compression-functions.md b/functions-and-operators/encryption-and-compression-functions.md index 2b55a9dc243e..a1fd75b27f50 100644 --- a/functions-and-operators/encryption-and-compression-functions.md +++ b/functions-and-operators/encryption-and-compression-functions.md @@ -1,37 +1,37 @@ --- title: 加密和压缩函数 -summary: TiDB 支持 MySQL 8.0 中提供的大部分加密和压缩函数。 +summary: 了解加密和压缩函数。 --- # 加密和压缩函数 -TiDB 支持使用 MySQL 8.0 中提供的大部分[加密和压缩函数](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html)。 +TiDB 支持 MySQL 8.0 中提供的大多数[加密和压缩函数](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html)。 ## 支持的函数 -| 函数名 | 功能描述 | -|:--------------------------------------------------------------|:------------------| -| [`AES_DECRYPT()`](#aes_decrypt) | 使用 AES 解密 | -| [`AES_ENCRYPT()`](#aes_encrypt) | 使用 AES 加密 | -| [`COMPRESS()`](#compress) | 返回压缩后的二进制字符串 | -| [`MD5()`](#md5) | 计算字符串的 MD5 校验和 | -| [`PASSWORD()`](#password) | 计算并返回密码字符串 | -| [`RANDOM_BYTES()`](#random_bytes) | 返回随机字节向量 | -| [`SHA()`](#sha) | 计算 SHA-1 160 位校验和 | -| [`SHA1()`](#sha1) | 计算 SHA-1 160 位校验和 | -| [`SHA2()`](#sha2) | 计算 SHA-2 校验和 | -| [`SM3()`](#sm3) | 计算 SM3 校验和 | -| [`UNCOMPRESS()`](#uncompress) | 解压缩字符串 | -| [`UNCOMPRESSED_LENGTH()`](#uncompressed_length) | 返回字符串压缩前的长度 | -| [`VALIDATE_PASSWORD_STRENGTH()`](#validate_password_strength) | 计算密码强度 | +| 名称 | 描述 | +|:--------------------------------------------------------------|:--------------------------------------------------| +| [`AES_DECRYPT()`](#aes_decrypt) | 使用 AES 解密 | +| [`AES_ENCRYPT()`](#aes_encrypt) | 使用 AES 加密 | +| [`COMPRESS()`](#compress) | 压缩并以二进制字符串形式返回结果 | +| [`MD5()`](#md5) | 计算 MD5 校验和 | +| [`PASSWORD()`](#password) | 计算并返回密码字符串 | +| [`RANDOM_BYTES()`](#random_bytes) | 返回随机字节向量 | +| [`SHA()`](#sha) | 计算 SHA-1 160 位校验和 | +| [`SHA1()`](#sha1) | 计算 SHA-1 160 位校验和 | +| [`SHA2()`](#sha2) | 计算 SHA-2 校验和 | +| [`SM3()`](#sm3) | 计算 SM3 校验和 | +| [`UNCOMPRESS()`](#uncompress) | 解压缩压缩的字符串 | +| [`UNCOMPRESSED_LENGTH()`](#uncompressed_length) | 返回压缩前字符串的长度 | +| [`VALIDATE_PASSWORD_STRENGTH()`](#validate_password_strength) | 验证密码强度 | ### [`AES_DECRYPT()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-decrypt) -`AES_DECRYPT(data, key [,iv])` 函数使用相同的 `key` 解密之前由 [`AES_ENCRYPT()`](#aes_encrypt) 函数加密的 `data`。 +`AES_DECRYPT(data, key [,iv])` 函数使用与 [`AES_ENCRYPT()`](#aes_encrypt) 函数相同的 `key` 解密之前加密的 `data`。 -你可以使用系统变量 [`block_encryption_mode`](/system-variables.md#block_encryption_mode) 选择[高级加密标准 (AES)](https://zh.wikipedia.org/wiki/高级加密标准) 加密模式。 +你可以使用 [`block_encryption_mode`](/system-variables.md#block_encryption_mode) 系统变量来选择 [高级加密标准 (AES)](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) 加密模式。 -对于需要初始化向量的加密模式,使用 `iv` 参数设置。默认值为 `NULL`。 +对于需要初始化向量的加密模式,可以使用 `iv` 参数设置。默认值为 `NULL`。 ```sql SELECT AES_DECRYPT(0x28409970815CD536428876175F1A4923, 'secret'); @@ -48,11 +48,11 @@ SELECT AES_DECRYPT(0x28409970815CD536428876175F1A4923, 'secret'); ### [`AES_ENCRYPT()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-encrypt) -`AES_ENCRYPT(data, key [,iv])` 函数使用[高级加密标准 (AES)](https://zh.wikipedia.org/wiki/高级加密标准) 算法和 `key` 加密 `data`。 +`AES_ENCRYPT(data, key [,iv])` 函数使用 [高级加密标准 (AES)](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) 算法用 `key` 加密 `data`。 -你可以使用系统变量 [`block_encryption_mode`](/system-variables.md#block_encryption_mode) 选择 AES 加密模式。 +你可以使用 [`block_encryption_mode`](/system-variables.md#block_encryption_mode) 系统变量来选择 AES 加密模式。 -对于需要初始化向量的加密模式,使用 `iv` 参数设置。默认值为 `NULL`。 +对于需要初始化向量的加密模式,可以使用 `iv` 参数设置。默认值为 `NULL`。 ```sql SELECT AES_ENCRYPT(0x616263,'secret'); @@ -69,15 +69,15 @@ SELECT AES_ENCRYPT(0x616263,'secret'); ### [`COMPRESS()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_compress) -`COMPRESS(expr)` 函数返回输入参数 `expr` 的压缩版本。 +`COMPRESS(expr)` 函数返回输入数据 `expr` 的压缩版本。 -- 如果输入参数为 `NULL`,该函数返回 `NULL`。 -- 如果输入参数为空字符串,该函数返回零长度值。 +- 如果参数为 `NULL`,函数返回 `NULL`。 +- 如果参数为空字符串,函数返回零长度值。 -对于非零长度输入参数,函数返回具有以下结构的二进制字符串: +对于非零长度参数,函数返回具有以下结构的二进制字符串: -- 字节 0 到 3:未压缩长度 -- 字节 4 到结尾:zlib 压缩数据 +- 字节 0 到 3:未压缩的长度 +- 字节 4 到结尾:zlib 压缩的数据 ```sql SELECT COMPRESS(0x414243); @@ -92,7 +92,7 @@ SELECT COMPRESS(0x414243); 1 row in set (0.00 sec) ``` -在此输出中,`0x03000000` 表示未压缩长度 (3),`0x789C72747206040000FFFF018D00C7` 是 zlib 压缩数据。 +在此输出中,`0x03000000` 表示未压缩的长度(3),`0x789C72747206040000FFFF018D00C7` 是 zlib 压缩的数据。 使用 Python 在 TiDB 外部解码的示例: @@ -105,7 +105,7 @@ print(int.from_bytes(data[:4], byteorder='little')) # 3 print(zlib.decompress(data[4:])) # b'ABC' ``` -对于短字符串,`COMPRESS()` 可能返回比输入更多的字节。以下示例显示 100 个 `a` 字符的字符串压缩为 19 字节。 +对于短字符串,`COMPRESS()` 可能返回比输入更多的字节。以下示例显示 100 个 `a` 字符的字符串压缩为 19 个字节。 ```sql WITH x AS (SELECT REPEAT('a',100) 'a') @@ -123,7 +123,7 @@ SELECT LENGTH(a),LENGTH(COMPRESS(a)) FROM x; ### [`MD5()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_md5) -`MD5(expr)` 函数为给定参数 `expr` 计算 128 位 [MD5](https://zh.wikipedia.org/wiki/MD5) 哈希值。 +`MD5(expr)` 函数为给定参数 `expr` 计算 128 位 [MD5](https://en.wikipedia.org/wiki/MD5) 哈希值。 ```sql SELECT MD5('abc'); @@ -142,7 +142,7 @@ SELECT MD5('abc'); > **警告:** > -> `PASSWORD()` 函数在 MySQL 5.7 中已弃用,在 MySQL 8.0 中已删除,在 TiDB 中也已弃用。不建议使用此函数。 +> 此函数在 MySQL 5.7 中已弃用,在 MySQL 8.0 中已移除。在 TiDB 中已弃用。不建议使用此函数。 `PASSWORD(str)` 函数计算可用于 `mysql_native_password` 认证方法的密码哈希。 @@ -184,7 +184,7 @@ SELECT RANDOM_BYTES(3); ### [`SHA1()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_sha1) -`SHA1(expr)` 函数为给定参数 `expr` 计算 160 位 [SHA-1](https://zh.wikipedia.org/wiki/SHA-1) 哈希值。 +`SHA1(expr)` 函数为给定参数 `expr` 计算 160 位 [SHA-1](https://en.wikipedia.org/wiki/SHA-1) 哈希值。 ```sql SELECT SHA1('abc'); @@ -201,17 +201,17 @@ SELECT SHA1('abc'); ### [`SHA2()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_sha2) -`SHA2(str, n)` 函数使用 [SHA-2](https://zh.wikipedia.org/wiki/SHA-2) 系列中的算法计算哈希值。参数 `n` 用于选择算法。如果任一参数为 `NULL` 或 `n` 指定的算法未知或不受支持,`SHA2()` 返回 `NULL`。 +`SHA2(str, n)` 函数使用 [SHA-2](https://en.wikipedia.org/wiki/SHA-2) 系列算法计算哈希值。参数 `n` 用于选择算法。如果任何参数为 `NULL` 或者 `n` 选择的算法未知或不支持,`SHA2()` 返回 `NULL`。 以下列出支持的算法: -| n | 算法 | -|-----|---------| -| 0 | SHA-256 | -| 224 | SHA-224 | -| 256 | SHA-256 | -| 384 | SHA-384 | -| 512 | SHA-512 | +| n | 算法 | +|-----|-----------| +| 0 | SHA-256 | +| 224 | SHA-224 | +| 256 | SHA-256 | +| 384 | SHA-384 | +| 512 | SHA-512 | ```sql SELECT SHA2('abc',224); @@ -230,9 +230,9 @@ SELECT SHA2('abc',224); > **注意:** > -> `SM3()` 函数是 TiDB 扩展,未在 MySQL 中实现。 +> `SM3()` 函数是 TiDB 的扩展,MySQL 中未实现。 -`SM3(str)` 函数为给定参数 `str` 计算 256 位 [ShangMi 3 (SM3)](https://zh.wikipedia.org/wiki/SM3) 哈希值。 +`SM3(str)` 函数为给定参数 `str` 计算 256 位 [商密 3 (SM3)](https://en.wikipedia.org/wiki/SM3_(hash_function)) 哈希值。 ```sql SELECT SM3('abc'); @@ -266,7 +266,7 @@ SELECT UNCOMPRESS(0x03000000789C72747206040000FFFF018D00C7); ### [`UNCOMPRESSED_LENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_uncompressed-length) -`UNCOMPRESSED_LENGTH(data)` 函数返回压缩数据的前 4 个字节,即字符串在使用 [`COMPRESS()`](#compress) 函数压缩之前的长度。 +`UNCOMPRESSED_LENGTH(data)` 函数返回压缩数据的前 4 个字节,这些字节存储了字符串在使用 [`COMPRESS()`](#compress) 函数压缩之前的长度。 ```sql SELECT UNCOMPRESSED_LENGTH(0x03000000789C72747206040000FFFF018D00C7); @@ -283,13 +283,23 @@ SELECT UNCOMPRESSED_LENGTH(0x03000000789C72747206040000FFFF018D00C7); ### [`VALIDATE_PASSWORD_STRENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_validate-password-strength) -`VALIDATE_PASSWORD_STRENGTH(str)` 函数用作 [TiDB 密码管理](/password-management.md)的一部分,它计算密码的强度并返回一个 0 到 100 之间的整数值。 + -[`validate_password.*`](/system-variables.md) 系统变量影响 `VALIDATE_PASSWORD_STRENGTH()` 函数的行为。 +`VALIDATE_PASSWORD_STRENGTH(str)` 函数作为[密码管理](/password-management.md)的一部分使用。它计算密码的强度并返回一个介于 0 和 100 之间的值。 + + + + + +`VALIDATE_PASSWORD_STRENGTH(str)` 函数作为密码管理的一部分使用。它计算密码的强度并返回一个介于 0 和 100 之间的值。 + + + +[`validate_password.*`](/system-variables.md) 系统变量会影响 `VALIDATE_PASSWORD_STRENGTH()` 函数的行为。 示例: -- 要启用密码复杂度检查,将系统变量 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 设置为 `ON`: +- 要启用密码复杂度检查,将 [`validate_password.enable`](/system-variables.md#validate_passwordenable-new-in-v650) 系统变量设置为 `ON`: ```sql SET GLOBAL validate_password.enable=ON; @@ -347,7 +357,7 @@ SELECT UNCOMPRESSED_LENGTH(0x03000000789C72747206040000FFFF018D00C7); 1 row in set (0.00 sec) ``` -- 检查较长字符串 `abcdefghi` 的密码强度,返回 `50`。此字符串长于 [`validate_password.length`](/system-variables.md#validate_passwordlength-从-v650-版本开始引入) 的默认值: +- 检查较长字符串 `abcdefghi` 的密码强度,返回 `50`。此字符串长度超过 [`validate_password.length`](/system-variables.md#validate_passwordlength-new-in-v650) 的默认值: ```sql SELECT VALIDATE_PASSWORD_STRENGTH('abcdefghi'); @@ -362,7 +372,7 @@ SELECT UNCOMPRESSED_LENGTH(0x03000000789C72747206040000FFFF018D00C7); 1 row in set (0.00 sec) ``` -- 向字符串添加大写字符不会提高密码强度: +- 添加大写字符到字符串不会提高密码强度: ```sql SELECT VALIDATE_PASSWORD_STRENGTH('Abcdefghi'); @@ -377,7 +387,7 @@ SELECT UNCOMPRESSED_LENGTH(0x03000000789C72747206040000FFFF018D00C7); 1 row in set (0.01 sec) ``` -- 向字符串添加数字也不会提高密码强度: +- 添加数字到字符串也不会提高密码强度: ```sql SELECT VALIDATE_PASSWORD_STRENGTH('Abcdefghi123'); @@ -392,7 +402,7 @@ SELECT UNCOMPRESSED_LENGTH(0x03000000789C72747206040000FFFF018D00C7); 1 row in set (0.00 sec) ``` -- 最后,向字符串添加特殊字符将密码强度提高到 `100`,表示密码强度很高: +- 最后,添加特殊字符到字符串使密码强度达到 `100`,表示这是一个强密码: ```sql SELECT VALIDATE_PASSWORD_STRENGTH('Abcdefghi123%$#'); @@ -409,10 +419,10 @@ SELECT UNCOMPRESSED_LENGTH(0x03000000789C72747206040000FFFF018D00C7); ## 不支持的函数 -* TiDB 不支持只在 MySQL 企业版中支持的函数。见 [Issue #2632](https://github.com/pingcap/tidb/issues/2632)。 +* TiDB 不支持仅在 MySQL Enterprise 中可用的函数 [Issue #2632](https://github.com/pingcap/tidb/issues/2632)。 ## MySQL 兼容性 * TiDB 不支持 `STATEMENT_DIGEST()` 和 `STATEMENT_DIGEST_TEXT()` 函数。 -* TiDB 不支持 MySQL 8.0.30 中为 [`AES_ENCRYPT()`](#aes_encrypt) 和 [`AES_DECRYPT`](#aes_decrypt) 新增的 `kdf_name`、`salt` 和 `iterations` 参数。 -* MySQL 未实现 [`SM3()`](#sm3) 函数。 \ No newline at end of file +* TiDB 不支持 MySQL 8.0.30 中为 [`AES_ENCRYPT()`](#aes_encrypt) 和 [`AES_DECRYPT`](#aes_decrypt) 添加的 `kdf_name`、`salt` 和 `iterations` 参数。 +* MySQL 未实现 [`SM3()`](#sm3) 函数。 diff --git a/functions-and-operators/expressions-pushed-down.md b/functions-and-operators/expressions-pushed-down.md index 54ae59e70ca9..3b1228e29234 100644 --- a/functions-and-operators/expressions-pushed-down.md +++ b/functions-and-operators/expressions-pushed-down.md @@ -1,36 +1,36 @@ --- -title: 下推到 TiKV 的表达式列表 -summary: TiDB 中下推到 TiKV 的表达式列表及相关设置。 +title: 下推表达式列表 +summary: 了解可以下推到 TiKV 的表达式列表及相关操作。 --- -# 下推到 TiKV 的表达式列表 +# 下推表达式列表 -当 TiDB 从 TiKV 中读取数据的时候,TiDB 会尽量下推一些表达式运算到 TiKV 中,从而减少数据传输量以及 TiDB 单一节点的计算压力。本文将介绍 TiDB 已支持下推的表达式,以及如何禁止下推特定表达式。 +当 TiDB 从 TiKV 读取数据时,TiDB 会尝试将一些表达式(包括函数或运算符的计算)下推到 TiKV 进行处理。这减少了传输的数据量,并减轻了单个 TiDB 节点的处理负担。本文介绍了 TiDB 已支持下推的表达式,以及如何使用阻止列表禁止特定表达式的下推。 -TiFlash 也支持[本页](/tiflash/tiflash-supported-pushdown-calculations.md)列出的函数和算子下推。 +TiFlash 也支持[此页面列出的](/tiflash/tiflash-supported-pushdown-calculations.md)函数和运算符的下推。 > **注意:** > -> 当作为[窗口函数](/functions-and-operators/window-functions.md)使用时,聚合函数不支持下推到 TiKV。 +> 当聚合函数作为[窗口函数](/functions-and-operators/window-functions.md)使用时,不支持下推到 TiKV。 -## 已支持下推的表达式列表 +## 支持下推到 TiKV 的表达式 -| 表达式分类 | 具体操作 | +| 表达式类型 | 操作 | | :-------------- | :------------------------------------- | -| [逻辑运算](/functions-and-operators/operators.md#逻辑操作符) | AND (&&), OR (||), NOT (!), XOR | -| [位运算](/functions-and-operators/operators.md#操作符) | [&](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-and), [~](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-invert), [\|](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-or), [`^`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-xor), [`<<`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_left-shift), [`>>`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_right-shift) | -| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than), [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal), [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal), [`!= (<>)`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal), [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than), [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal), [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to), [BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between), [COALESCE()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce), [IN()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in), [INTERVAL()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_interval), [IS NOT NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not-null), [IS NOT](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not), [IS NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null), [IS](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is), [ISNULL()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull), [LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like), [NOT BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between), [NOT IN()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in), [NOT LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like), [STRCMP()](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp) | -| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | [+](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus), [-](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus), [*](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_times), [/](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_divide), [DIV](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_div), [% (MOD)](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_mod), [-](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_unary-minus), [ABS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_abs), [ACOS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_acos), [ASIN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_asin), [ATAN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan), [ATAN2(), ATAN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan2), [CEIL()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceil), [CEILING()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceiling), [CONV()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_conv), [COS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cos), [COT()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cot), [CRC32()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_crc32), [DEGREES()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_degrees), [EXP()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_exp), [FLOOR()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_floor), [LN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ln), [LOG()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log), [LOG10()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log10), [LOG2()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log2), [MOD()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_mod), [PI()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pi), [POW()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pow), [POWER()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_power), [RADIANS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_radians), [RAND()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_rand), [ROUND()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_round), [SIGN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sign), [SIN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sin), [SQRT()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sqrt) | -| [控制流运算](/functions-and-operators/control-flow-functions.md) | [CASE](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case), [IF()](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if), [IFNULL()](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) | -| [JSON 运算](/functions-and-operators/json-functions.md) | [JSON_ARRAY([val[, val] ...])](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-array),
[JSON_CONTAINS(target, candidate[, path])](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains),
[JSON_EXTRACT(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-extract),
[JSON_INSERT(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-insert),
[JSON_LENGTH(json_doc[, path])](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-length),
[JSON_MERGE(json_doc, json_doc[, json_doc] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-merge),
[JSON_OBJECT([key, val[, key, val] ...])](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-object),
[JSON_REMOVE(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-remove),
[JSON_SET(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-set),
[JSON_TYPE(json_val)](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-type),
[JSON_UNQUOTE(json_val)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-unquote),
[JSON_VALID(val)](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-valid),
[value MEMBER OF(json_array)](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of) | -| [日期运算](/functions-and-operators/date-and-time-functions.md) | [DATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date), [DATE_FORMAT()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format), [DATEDIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_datediff), [DAYOFMONTH()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofmonth), [DAYOFWEEK()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofweek), [DAYOFYEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofyear), [FROM_DAYS()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_from-days), [HOUR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour), [MAKEDATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_makedate), [MAKETIME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_maketime), [MICROSECOND()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_microsecond), [MINUTE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_minute), [MONTH()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_month), [MONTHNAME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_monthname), [PERIOD_ADD()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-add), [PERIOD_DIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-diff), [SEC_TO_TIME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sec-to-time), [SECOND()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_second), [SYSDATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sysdate), [TIME_TO_SEC()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time-to-sec), [TIMEDIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timediff), [WEEK()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_week), [WEEKOFYEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekofyear), [YEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_year) | +| [逻辑运算符](/functions-and-operators/operators.md#logical-operators) | AND (&&), OR (||), NOT (!), XOR | +| [位运算符](/functions-and-operators/operators.md#operators) | [&](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-and), [~](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-invert), [\|](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-or), [`^`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-xor), [`<<`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_left-shift), [`>>`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_right-shift) | +| [比较函数和运算符](/functions-and-operators/operators.md#comparison-functions-and-operators) | [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than), [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal), [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal), [`!= (<>)`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal), [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than), [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal), [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to), [BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between), [COALESCE()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce), [IN()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in), [INTERVAL()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_interval), [IS NOT NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not-null), [IS NOT](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not), [IS NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null), [IS](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is), [ISNULL()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull), [LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like), [NOT BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between), [NOT IN()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in), [NOT LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like), [STRCMP()](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp) | +| [数值函数和运算符](/functions-and-operators/numeric-functions-and-operators.md) | [+](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus), [-](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus), [*](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_times), [/](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_divide), [DIV](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_div), [% (MOD)](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_mod), [-](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_unary-minus), [ABS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_abs), [ACOS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_acos), [ASIN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_asin), [ATAN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan), [ATAN2(), ATAN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan2), [CEIL()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceil), [CEILING()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceiling), [CONV()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_conv), [COS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cos), [COT()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cot), [CRC32()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_crc32), [DEGREES()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_degrees), [EXP()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_exp), [FLOOR()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_floor), [LN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ln), [LOG()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log), [LOG10()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log10), [LOG2()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log2), [MOD()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_mod), [PI()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pi), [POW()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pow), [POWER()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_power), [RADIANS()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_radians), [RAND()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_rand), [ROUND()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_round), [SIGN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sign), [SIN()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sin), [SQRT()](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sqrt) | +| [流程控制函数](/functions-and-operators/control-flow-functions.md) | [CASE](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case), [IF()](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if), [IFNULL()](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) | +| [JSON 函数](/functions-and-operators/json-functions.md) | [JSON_ARRAY([val[, val] ...])](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-array),
[JSON_CONTAINS(target, candidate[, path])](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains),
[JSON_EXTRACT(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-extract),
[JSON_INSERT(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-insert),
[JSON_LENGTH(json_doc[, path])](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-length),
[JSON_MERGE(json_doc, json_doc[, json_doc] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-merge),
[JSON_OBJECT([key, val[, key, val] ...])](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-object),
[JSON_REMOVE(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-remove),
[JSON_SET(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-set),
[JSON_TYPE(json_val)](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-type),
[JSON_UNQUOTE(json_val)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-unquote),
[JSON_VALID(val)](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-valid),
[value MEMBER OF(json_array)](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of) | +| [日期和时间函数](/functions-and-operators/date-and-time-functions.md) | [DATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date), [DATE_FORMAT()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format), [DATEDIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_datediff), [DAYOFMONTH()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofmonth), [DAYOFWEEK()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofweek), [DAYOFYEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofyear), [FROM_DAYS()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_from-days), [HOUR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour), [MAKEDATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_makedate), [MAKETIME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_maketime), [MICROSECOND()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_microsecond), [MINUTE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_minute), [MONTH()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_month), [MONTHNAME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_monthname), [PERIOD_ADD()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-add), [PERIOD_DIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-diff), [SEC_TO_TIME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sec-to-time), [SECOND()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_second), [SYSDATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sysdate), [TIME_TO_SEC()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time-to-sec), [TIMEDIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timediff), [WEEK()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_week), [WEEKOFYEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekofyear), [YEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_year) | | [字符串函数](/functions-and-operators/string-functions.md) | [ASCII()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ascii), [BIT_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_bit-length), [CHAR()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char), [CHAR_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char-length), [CONCAT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat), [CONCAT_WS()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat-ws), [ELT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_elt), [FIELD()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_field), [HEX()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_hex), [LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_length), [LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like), [LOWER()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_lower), [LTRIM()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ltrim), [MID()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_mid), [NOT LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like), [NOT REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_not-regexp), [REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp), [REGEXP_INSTR()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-instr), [REGEXP_LIKE()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-like), [REGEXP_REPLACE()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-replace), [REGEXP_SUBSTR()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-substr), [REPLACE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_replace), [REVERSE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_reverse), [RIGHT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_right), [RLIKE](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp), [RTRIM()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_rtrim), [SPACE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_space), [STRCMP()](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp), [SUBSTR()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substr), [SUBSTRING()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substring), [UPPER()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_upper) | -| [聚合函数](/functions-and-operators/aggregate-group-by-functions.md#group-by-聚合函数) | [COUNT()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count), [COUNT(DISTINCT)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct), [SUM()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_sum), [AVG()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_avg), [MAX()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max), [MIN()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min), [VARIANCE()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_variance), [VAR_POP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-pop), [STD()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_std), [STDDEV()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev), [STDDEV_POP](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-pop), [VAR_SAMP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-samp), [STDDEV_SAMP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-samp), [JSON_ARRAYAGG(key)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-arrayagg), [JSON_OBJECTAGG(key, value)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-objectagg) | -| [加密和压缩函数](/functions-and-operators/encryption-and-compression-functions.md#加密和压缩函数) | [MD5()](/functions-and-operators/encryption-and-compression-functions.md#md5), [SHA1(), SHA()](/functions-and-operators/encryption-and-compression-functions.md#sha1), [UNCOMPRESSED_LENGTH()](/functions-and-operators/encryption-and-compression-functions.md#uncompressed_length) | -| [Cast 函数](/functions-and-operators/cast-functions-and-operators.md#cast-函数和操作符) | [CAST()](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast), [CONVERT()](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_convert) | -| [其他函数](/functions-and-operators/miscellaneous-functions.md#支持的函数) | [UUID()](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_uuid) | +| [聚合函数](/functions-and-operators/aggregate-group-by-functions.md#aggregate-group-by-functions) | [COUNT()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count), [COUNT(DISTINCT)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct), [SUM()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_sum), [AVG()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_avg), [MAX()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max), [MIN()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min), [VARIANCE()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_variance), [VAR_POP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-pop), [STD()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_std), [STDDEV()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev), [STDDEV_POP](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-pop), [VAR_SAMP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-samp), [STDDEV_SAMP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-samp), [JSON_ARRAYAGG(key)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-arrayagg), [JSON_OBJECTAGG(key, value)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-objectagg) | +| [加密和压缩函数](/functions-and-operators/encryption-and-compression-functions.md#encryption-and-compression-functions) | [MD5()](/functions-and-operators/encryption-and-compression-functions.md#md5), [SHA1(), SHA()](/functions-and-operators/encryption-and-compression-functions.md#sha1), [UNCOMPRESSED_LENGTH()](/functions-and-operators/encryption-and-compression-functions.md#uncompressed_length) | +| [类型转换函数和运算符](/functions-and-operators/cast-functions-and-operators.md#cast-functions-and-operators) | [CAST()](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast), [CONVERT()](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_convert) | +| [其他函数](/functions-and-operators/miscellaneous-functions.md#supported-functions) | [UUID()](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_uuid) | | [窗口函数](/functions-and-operators/window-functions.md) | 无 | -## 禁止特定表达式下推 +## 阻止特定表达式下推 -当[已支持下推的表达式列表](#已支持下推的表达式列表)中的函数和运算符,或特定的数据类型(**仅限** [`ENUM` 类型](/data-type-string.md#enum-类型)和 [`BIT` 类型](/data-type-numeric.md#bit-类型))的计算过程因下推而出现异常时,你可以使用黑名单功能禁止其下推,从而快速恢复 TiDB 业务。具体而言,你可以将函数名、运算符名,或数据列类型加入黑名单 `mysql.expr_pushdown_blacklist` 中,以禁止特定表达式下推。具体方法,请参阅[表达式下推黑名单](/blocklist-control-plan.md#禁止特定表达式下推)。 +如果在下推[支持的表达式](#支持下推到-tikv-的表达式)或特定数据类型(**仅限**[`ENUM` 类型](/data-type-string.md#enum-type)和[`BIT` 类型](/data-type-numeric.md#bit-type))时计算过程中出现意外行为,你可以通过禁止相应函数、运算符或数据类型的下推来快速恢复应用。具体来说,你可以通过将它们添加到阻止列表 `mysql.expr_pushdown_blacklist` 来禁止函数、运算符或数据类型的下推。详情请参考[添加到阻止列表](/blocklist-control-plan.md#禁用特定表达式的下推)。 diff --git a/functions-and-operators/functions-and-operators-overview.md b/functions-and-operators/functions-and-operators-overview.md index a5585229c03e..696b60c37cf3 100644 --- a/functions-and-operators/functions-and-operators-overview.md +++ b/functions-and-operators/functions-and-operators-overview.md @@ -1,15 +1,15 @@ --- -title: 函数和操作符概述 -summary: TiDB 中的函数和操作符使用方法与 MySQL 基本一致。在 SQL 语句中,表达式可用于诸如 SELECT 语句的 ORDER BY 或 HAVING 子句,SELECT/DELETE/UPDATE 语句的 WHERE 子句,或 SET 语句之类的地方。可使用字面值,列名,NULL,内置函数,操作符等来书写表达式。其中有些表达式下推到 TiKV 上执行,详见下推到 TiKV 的表达式列表。 +title: 函数和运算符参考 +summary: 了解如何使用函数和运算符。 --- -# 函数和操作符概述 +# 函数和运算符参考 -TiDB 中函数和操作符使用方法与 MySQL 基本一致,详情参见:[Functions and Operators](https://dev.mysql.com/doc/refman/8.0/en/functions.html)。 +TiDB 中函数和运算符的使用方式与 MySQL 类似。请参见 [MySQL 中的函数和运算符](https://dev.mysql.com/doc/refman/8.0/en/functions.html)。 -在 SQL 语句中,表达式可用于诸如 [`SELECT`](/sql-statements/sql-statement-select.md) 语句的 `ORDER BY` 或 `HAVING` 子句,[`SELECT`](/sql-statements/sql-statement-select.md)、[`DELETE`](/sql-statements/sql-statement-delete.md) 或 [`UPDATE`](/sql-statements/sql-statement-update.md) 语句的 `WHERE` 子句,或 [`SET`](/sql-statements/sql-statement-set-variable.md) 语句之类的地方。 +在 SQL 语句中,表达式可以用在 [`SELECT`](/sql-statements/sql-statement-select.md) 语句的 `ORDER BY` 和 `HAVING` 子句中,[`SELECT`](/sql-statements/sql-statement-select.md)/[`DELETE`](/sql-statements/sql-statement-delete.md)/[`UPDATE`](/sql-statements/sql-statement-update.md) 语句的 `WHERE` 子句中,以及 [`SET`](/sql-statements/sql-statement-set-variable.md) 语句中。 -你可以使用字面值、列名、`NULL`、内置函数、操作符等来编写表达式。 +你可以使用字面量、列名、`NULL`、内置函数、运算符等来编写表达式。 -- TiDB 支持下推到 TiKV 上执行的表达式,请参阅[支持下推到 TiKV 的表达式](/functions-and-operators/expressions-pushed-down.md#已支持下推的表达式列表)。 -- TiDB 支持下推到 [TiFlash](/tiflash/tiflash-overview.md) 上执行的表达式,请参阅[支持下推到 TiFlash 的表达式](/tiflash/tiflash-supported-pushdown-calculations.md#支持下推的表达式)。 \ No newline at end of file +- 关于 TiDB 支持下推到 TiKV 的表达式,请参见[可下推表达式列表](/functions-and-operators/expressions-pushed-down.md)。 +- 关于 TiDB 支持下推到 [TiFlash](/tiflash/tiflash-overview.md) 的表达式,请参见[下推表达式](/tiflash/tiflash-supported-pushdown-calculations.md#push-down-expressions)。 diff --git a/functions-and-operators/group-by-modifier.md b/functions-and-operators/group-by-modifier.md index 9c9f0e390d01..45a27dae8430 100644 --- a/functions-and-operators/group-by-modifier.md +++ b/functions-and-operators/group-by-modifier.md @@ -5,16 +5,18 @@ summary: 了解如何使用 TiDB GROUP BY 修饰符。 # GROUP BY 修饰符 -自 v7.4.0 起,TiDB 的 `GROUP BY` 子句支持 `WITH ROLLUP` 修饰符。 +从 v7.4.0 版本开始,TiDB 的 `GROUP BY` 子句支持 `WITH ROLLUP` 修饰符。 -你可以在 `GROUP BY` 子句中指定一个或多个列,形成一个分组列表,然后添加 `WITH ROLLUP` 修饰符。TiDB 将会按照分组列表中的列进行多维度的递减分组,并在输出中为你提供各个分组数据的汇总结果。 +在 `GROUP BY` 子句中,你可以指定一个或多个列作为分组列表,并在列表后添加 `WITH ROLLUP` 修饰符。然后,TiDB 将基于分组列表中的列进行多维度降序分组,并在输出中为每个分组提供汇总结果。 -- 分组方式: - - 第一个分组维度为分组表列表中的所有列。 - - 后面的维度将从分组列表的最右侧(尾端)开始,每次递减一个元素,形成新的分组。 -- 聚合汇总:在每个维度上,查询都会执行聚合操作,然后将该维度的计算结果与前面所有维度的结果进行汇总。这意味着你可以看到不同维度的聚合数据,从详细到总体。 +- 分组方法: -按照这种分组方式,当分组列表中有 N 个列时,查询的计算结果将会在 N+1 个分组上进行聚合后输出。 + - 第一个分组维度包含分组列表中的所有列。 + - 后续分组维度从分组列表的右端开始,每次多排除一列来形成新的分组。 + +- 聚合汇总:对于每个维度,查询执行聚合操作,然后将该维度的结果与所有前序维度的结果进行聚合。这意味着你可以获得不同维度的聚合数据,从详细到整体。 + +通过这种分组方法,如果分组列表中有 `N` 个列,TiDB 会在 `N+1` 个分组上聚合查询结果。 例如: @@ -22,25 +24,29 @@ summary: 了解如何使用 TiDB GROUP BY 修饰符。 SELECT count(1) FROM t GROUP BY a,b,c WITH ROLLUP; ``` -在此示例中,count(1) 的计算结果将分别在 {a,b,c}、{a,b}、{a}、{} 一共 4 个分组上进行聚合,然后输出各分组的汇总数据。 +在这个例子中,TiDB 将在 4 个分组(即 `{a, b, c}`、`{a, b}`、`{a}` 和 `{}`)上聚合 `count(1)` 的计算结果,并输出每个分组的汇总结果。 > **注意:** > -> TiDB 暂不支持 Cube 语法。 +> 目前,TiDB 不支持 Cube 语法。 ## 使用场景 -多列数据的聚合汇总输出一般常用于 OLAP(Online Analytical Processing)场景。通过使用 `WITH ROLLUP` 修饰符,你可以在聚合结果中得到额外的行,以展示不同维度的汇总信息,从而实现高级的数据分析和报表生成。 +从多个列聚合和汇总数据在 OLAP(在线分析处理)场景中很常见。通过使用 `WITH ROLLUP` 修饰符,你可以在聚合结果中获得额外的行,这些行显示来自其他高级维度的超级汇总信息。然后,你可以使用这些超级汇总信息进行高级数据分析和报表生成。 + +## 前提条件 + +目前,TiDB 仅在 TiFlash MPP 模式下支持为 `WITH ROLLUP` 语法生成有效的执行计划。因此,请确保你的 TiDB 集群已部署 TiFlash 节点,并且目标事实表已正确配置 TiFlash 副本。 -## 准备条件 + -目前,TiDB 仅在 TiFlash MPP 模式下支持为 `WITH ROLLUP` 语法生成有效的执行计划,因此你的 TiDB 集群需要包含 TiFlash 节点,并且对目标分析表进行了正确的 TiFlash 副本的配置。 +更多信息,请参见[扩容 TiFlash 节点](/scale-tidb-using-tiup.md#扩容-tiflash-节点)。 -更多信息,请参考[扩容 TiFlash 节点](/scale-tidb-using-tiup.md#扩容-tiflash-节点)。 + -## 使用示例 +## 示例 -假如有一张名为 `bank` 的银行利润表,包含年(`year`)、月(`month`)、日(`day`)和利润(`profit`)列。 +假设你有一个名为 `bank` 的利润表,包含 `year`、`month`、`day` 和 `profit` 列。 ```sql CREATE TABLE bank @@ -51,12 +57,12 @@ CREATE TABLE bank profit DECIMAL(13, 7) ); -ALTER TABLE bank SET TIFLASH REPLICA 1; -- 为该表添加一个 TiFlash 副本 +ALTER TABLE bank SET TIFLASH REPLICA 1; -- 为表添加 TiFlash 副本 INSERT INTO bank VALUES(2000, "Jan", 1, 10.3),(2001, "Feb", 2, 22.4),(2000,"Mar", 3, 31.6) ``` -如需查看银行每年的利润,可以用一个简单的 `GROUP BY` 的子句来实现: +要获取银行每年的利润,你可以使用简单的 `GROUP BY` 子句,如下所示: ```sql SELECT year, SUM(profit) AS profit FROM bank GROUP BY year; @@ -69,7 +75,7 @@ SELECT year, SUM(profit) AS profit FROM bank GROUP BY year; 2 rows in set (0.15 sec) ``` -对于银行报表来说,除了每年的利润之外,通常还需要计算所有年份的总利润或每个月的总利润,以进行更高层次或更详细的利润分析。在 v7.4.0 之前的版本中,你需要在多个查询中使用不同的 `GROUP BY` 子句,并将结果使用 UNION 连接,才能得到聚合汇总的结果。从 v7.4.0 起,你可以直接在单个查询的 `GROUP BY` 子句中添加 `WITH ROLLUP` 修饰符,即可得到所需的结果: +除了年度利润外,银行报表通常还需要包括所有年份的总体利润或按月划分的利润,以便进行详细的利润分析。在 v7.4.0 之前,你必须在多个查询中使用不同的 `GROUP BY` 子句,并使用 UNION 连接结果以获得聚合汇总。从 v7.4.0 开始,你只需在 `GROUP BY` 子句后添加 `WITH ROLLUP` 修饰符,就可以在单个查询中实现所需的结果。 ```sql SELECT year, month, SUM(profit) AS profit from bank GROUP BY year, month WITH ROLLUP ORDER BY year desc, month desc; @@ -86,20 +92,20 @@ SELECT year, month, SUM(profit) AS profit from bank GROUP BY year, month WITH RO 6 rows in set (0.025 sec) ``` -以上结果包含了按照年份和月份、按照年份、以及整体所有维度的聚合数据。其中,未出现 `NULL` 值的行表示该行 `profit` 是同时按照年份和月份分组计算的结果,`month` 列的 `NULL` 值表示该行 `profit` 是按照该年份的所有月份聚合计算的结果,`year` 列的 `NULL` 值表示该行 `profit` 是按照所有年份聚合计算的结果。 +上述结果包括不同维度的聚合数据:按年和月、按年以及总体。在结果中,没有 `NULL` 值的行表示该行的 `profit` 是通过同时按年和月分组计算得出的。`month` 列中有 `NULL` 值的行表示该行的 `profit` 是通过聚合一年中所有月份计算得出的,而 `year` 列中有 `NULL` 值的行表示该行的 `profit` 是通过聚合所有年份计算得出的。 具体来说: -* 第一行的 `profit` 值来自 2 维分组 {year, month},为 {2000, “Jan”} 的细粒度分组的聚合结果。 -* 第二行的 `profit` 值来自 1 维分组 {year},为 {2001} 的中层粒度分组下的聚合结果。 -* 最后一行的 `profit` 值来自 0 维分组 {},即整体的聚合结果。 +- 第一行的 `profit` 值来自二维分组 `{year, month}`,表示细粒度 `{2000, "Jan"}` 分组的聚合结果。 +- 第二行的 `profit` 值来自一维分组 `{year}`,表示中级 `{2001}` 分组的聚合结果。 +- 最后一行的 `profit` 值来自零维分组 `{}`,表示总体聚合结果。 -`WITH ROLLUP` 结果中的 `NULL` 值是在应用 Aggregate 算子之前生成的,因此你可以将 `NULL` 值应用于 `SELECT`、`HAVING`、`ORDER BY` 子句中,进一步过滤聚合结果。 +`WITH ROLLUP` 结果中的 `NULL` 值是在应用聚合运算符之前生成的。因此,你可以在 `SELECT`、`HAVING` 和 `ORDER BY` 子句中使用 `NULL` 值来进一步过滤聚合结果。 -例如,你可以在 `HAVING` 子句中通过 `NULL` 过滤并只看 2 维度分组下的聚合结果输出。 +例如,你可以在 `HAVING` 子句中使用 `NULL` 来仅查看二维分组的聚合结果: ```sql -SELECT year, month, SUM(profit) AS profit FROM bank GROUP BY year, month WITH ROLLUP HAVING year IS NOT null AND month IS NOT null; +SELECT year, month, SUM(profit) AS profit FROM bank GROUP BY year, month WITH ROLLUP HAVING year IS NOT null AND month IS NOT null; +------+-------+--------------------+ | year | month | profit | +------+-------+--------------------+ @@ -110,9 +116,9 @@ SELECT year, month, SUM(profit) AS profit FROM bank GROUP BY year, month WITH RO 3 rows in set (0.02 sec) ``` -需要注意的是,如果 `GROUP BY` 分组列表中的某列包含原生的 `NULL` 值,`WITH ROLLUP` 的分组聚合可能会对查询结果产生误导。为了解决这个问题,你可以使用 `GROUPING ()` 函数区分原生的 `NULL` 值和 `WITH ROLLUP` 生成的 `NULL` 值。该函数接受分组表达式作为参数,并输出 `0` 或 `1`,表示该分组表达式是否在当前结果中被聚合。`1` 表示被聚合,`0` 表示没有。 +请注意,如果 `GROUP BY` 列表中的列包含原生 `NULL` 值,`WITH ROLLUP` 的聚合结果可能会误导查询结果。为解决此问题,你可以使用 `GROUPING()` 函数来区分原生 `NULL` 值和由 `WITH ROLLUP` 生成的 `NULL` 值。此函数接受一个分组表达式作为参数,并返回 `0` 或 `1` 来指示当前结果中是否聚合了分组表达式。`1` 表示已聚合,`0` 表示未聚合。 -以下是如何使用 `GROUPING ()` 函数的示例: +以下示例展示如何使用 `GROUPING()` 函数: ```sql SELECT year, month, SUM(profit) AS profit, grouping(year) as grp_year, grouping(month) as grp_month FROM bank GROUP BY year, month WITH ROLLUP ORDER BY year DESC, month DESC; @@ -129,9 +135,9 @@ SELECT year, month, SUM(profit) AS profit, grouping(year) as grp_year, grouping( 6 rows in set (0.028 sec) ``` -在此输出中,你可以直接通过 `grp_year` 和 `grp_month` 的结果来判断该聚合结果行所在的聚合维度,以防止分组表达式 `year` 和 `month` 原生的 `NULL` 值的干扰。 +从这个输出中,你可以直接从 `grp_year` 和 `grp_month` 的结果了解一行的聚合维度,这可以防止 `year` 和 `month` 分组表达式中的原生 `NULL` 值的干扰。 -`GROUPING()` 函数最多可以接受 64 个分组表达式作为参数。在多参数的输出中,每个参数都可以生成一个 `0` 或 `1` 的结果,多个参数综合组成每一个比特位是 `0` 或 `1` 总体是 64 位的 `UNSIGNED LONGLONG`。各个参数在比特数位中的位置可以通过以下公式计算: +`GROUPING()` 函数最多可以接受 64 个分组表达式作为参数。在多个参数的输出中,每个参数生成一个 `0` 或 `1` 的结果,这些参数共同形成一个 64 位的 `UNSIGNED LONGLONG`,每个位为 `0` 或 `1`。你可以使用以下公式获取每个参数的位置: ```go GROUPING(day, month, year): @@ -140,7 +146,7 @@ GROUPING(day, month, year): + result for GROUPING(day) << 2 ``` -在 `GROUPING()` 的函数中使用组合参数可以快速过滤出任何高维度的聚合结果。例如,你可以通过 `GROUPING(year, month)` 快速过滤出每年以及所有年份的聚合结果: +通过在 `GROUPING()` 函数中使用多个参数,你可以高效地过滤任何高维度的聚合结果。例如,你可以使用 `GROUPING(year, month)` 快速过滤每年和所有年份的聚合结果。 ```sql SELECT year, month, SUM(profit) AS profit, grouping(year) as grp_year, grouping(month) as grp_month FROM bank GROUP BY year, month WITH ROLLUP HAVING GROUPING(year, month) <> 0 ORDER BY year DESC, month DESC; @@ -154,13 +160,13 @@ SELECT year, month, SUM(profit) AS profit, grouping(year) as grp_year, grouping( 3 rows in set (0.023 sec) ``` -## 如何阅读 ROLLUP 的执行计划 +## 如何解读 ROLLUP 执行计划 -多维度数据聚合使用了 `Expand` 算子来复制数据以满足多维度分组的需求,每个复制的数据副本都对应一个特定维度的分组。通过 MPP 的数据 shuffle 能力,`Expand` 算子能够快速地在多个 TiFlash 节点之间重新组织和计算大量的数据,充分利用每个节点的计算能力。 +为了满足多维度分组的要求,多维数据聚合使用 `Expand` 算子来复制数据。每个副本对应特定维度的一个分组。通过 MPP 的数据分发能力,`Expand` 算子可以在多个 TiFlash 节点之间快速重组和计算大量数据,充分利用每个节点的计算能力。 -`Expand` 算子的实现类似 `Projection` 算子,但区别在于 `Expand` 是多层级的 `Projection`,具有多层级投影运算表达式。对于每行原始数据行,`Projection` 算子只会生成一行结果输出,而 `Expand` 算子会生成多行结果(行数等于多层级投影运算表达式的层数)。 +`Expand` 算子的实现类似于 `Projection` 算子。不同之处在于 `Expand` 是一个多级 `Projection`,包含多个级别的投影操作表达式。对于原始数据的每一行,`Projection` 算子在结果中只生成一行,而 `Expand` 算子在结果中生成多行(行数等于投影操作表达式的级别数)。 -以下为一个执行计划示例: +以下是一个执行计划示例: ```sql explain SELECT year, month, grouping(year), grouping(month), SUM(profit) AS profit FROM bank GROUP BY year, month WITH ROLLUP; @@ -181,13 +187,13 @@ explain SELECT year, month, grouping(year), grouping(month), SUM(profit) AS prof 10 rows in set (0.05 sec) ``` -在这个示例执行计划中,你可以在 `Expand_20` 这行的 `operator info` 列查看 `Expand` 算子的层级表达式,其由 2 维表达式组成,行末有 `Expand` 算子的 Schema 信息 `schema: [test.bank.profit,Column#6,Column#7,gid]`。 +在这个执行计划示例中,你可以在 `Expand_20` 行的 `operator info` 列中查看 `Expand` 算子的多级表达式。它由二维表达式组成,你可以在该行末尾查看 `Expand` 算子的 schema 信息,即 `schema: [test.bank.profit, Column#6, Column#7, gid]`。 -在 `Expand` 算子的 schema 信息中,`GID` 会作为额外的生成列来输出,其值是由 `Expand` 算子根据不同维度的分组逻辑计算得出,反映了当前数据副本和维度分组的关系。最常见的情况是使用位掩码运算, 它可以表示 63 种分组项的 ROLLUP 组合,对应 64 种维度的分组。在这种模式下,`GID` 值的生成根据当前数据副本复制时所需维度分组中是否有分组表达式,按照要进行分组的列,顺序填充一个 64 位的 UINT64 的值。 +在 `Expand` 算子的 schema 信息中,`GID` 作为额外列生成。其值由 `Expand` 算子根据不同维度的分组逻辑计算得出,该值反映了当前数据副本与 `grouping set` 的关系。在大多数情况下,`Expand` 算子使用位与运算,可以表示 ROLLUP 的 63 种分组项组合,对应 64 个分组维度。在这种模式下,TiDB 根据当前数据副本复制时所需维度的 `grouping set` 是否包含分组表达式来生成 `GID` 值,并按待分组列的顺序填充一个 64 位的 UINT64 值。 -例如,这里分组列表中列的顺序是 [year, month],而 ROLLUP 语法生成的维度分组集合为:{year, month}, {year}, {}。对于维度分组 {year, month} 来说,`year` 和 `month` 都是当前维度分组所需的列,对应填充比特位 1 和 1,组成 UINT64 为 11...0 即 3,因此投影表达式为 `[test.bank.profit, Column#6, Column#7, 3->gid]`。(`column#6` 对应 `year`,`column#7` 对应 `month`) +在上述示例中,分组列表中列的顺序是 `[year, month]`,ROLLUP 语法生成的维度分组是 `{year, month}`、`{year}` 和 `{}`。对于维度分组 `{year, month}`,`year` 和 `month` 都是必需列,所以 TiDB 分别用 1 和 1 填充它们的位置。这形成了一个 UINT64 的 `11...0`,十进制为 3。因此,投影表达式为 `[test.bank.profit, Column#6, Column#7, 3->gid]`(其中 `column#6` 对应 `year`,`column#7` 对应 `month`)。 -以原始数据中的下面这行为例: +以下是原始数据的一个示例行: ```sql +------+-------+------+------------+ @@ -197,18 +203,18 @@ explain SELECT year, month, grouping(year), grouping(month), SUM(profit) AS prof +------+-------+------+------------+ ``` -经过 `Expand` 算子之后,可以得到以下三行结果: +应用 `Expand` 算子后,你可以得到以下三行结果: ```sql -+------------+------+-------+-----+ -| profit | year | month | gid | +------------+------+-------+-----+ -| 10.3000000 | 2000 | Jan | 3 | -+------------+------+-------+-----+ -| 10.3000000 | 2000 | NULL | 1 | -+------------+------+-------+-----+ -| 10.3000000 | NULL | NULL | 0 | +| profit | year | month | gid | ++------------+------+-------+-----+ +| 10.3000000 | 2000 | Jan | 3 | ++------------+------+-------+-----+ +| 10.3000000 | 2000 | NULL | 1 | ++------------+------+-------+-----+ +| 10.3000000 | NULL | NULL | 0 | +------------+------+-------+-----+ ``` -需要注意的是,该查询的 `SELECT` 子句中使用了 `GROUPING` 函数。当在 `SELECT`、`HAVING`、`ORDER BY` 子句中使用 `GROUPING` 函数时,TiDB 会在逻辑优化阶段对其进行改写,将 `GROUPING` 函数与分组项(`GROUP BY` items)之间的关系,转化为与维度分组计算逻辑有关的 `GID`,并将此 `GID` 以 metadata 形式填充到新的 `GROUPING` 函数当中。 \ No newline at end of file +注意,查询中的 `SELECT` 子句使用了 `GROUPING` 函数。当在 `SELECT`、`HAVING` 或 `ORDER BY` 子句中使用 `GROUPING` 函数时,TiDB 在逻辑优化阶段会重写它,将 `GROUPING` 函数与 `GROUP BY` 项之间的关系转换为与维度分组(也称为 `grouping set`)逻辑相关的 `GID`,并将此 `GID` 作为元数据填充到新的 `GROUPING` 函数中。 diff --git a/functions-and-operators/information-functions.md b/functions-and-operators/information-functions.md index a022980e4533..89607c1c6169 100644 --- a/functions-and-operators/information-functions.md +++ b/functions-and-operators/information-functions.md @@ -1,33 +1,33 @@ --- title: 信息函数 -summary: TiDB 支持 MySQL 8.0 中提供的大部分信息函数。 +summary: 了解信息函数。 --- # 信息函数 -TiDB 支持使用 MySQL 8.0 中提供的大部分[信息函数](https://dev.mysql.com/doc/refman/8.0/en/information-functions.html)。 - -## TiDB 支持的 MySQL 信息函数 - -| 函数名 | 功能描述 | -| ------ | ---------------------------------------- | -| [`BENCHMARK()`](#benchmark) | 循环执行一个表达式 | -| [`CONNECTION_ID()`](#connection_id) | 返回当前连接的连接 ID(线程 ID) | -| [`CURRENT_ROLE()`](#current_role) | 返回当前连接的角色 | -| [`CURRENT_USER()`, `CURRENT_USER`](#current_user) | 返回当前用户的用户名和主机名 | -| [`DATABASE()`](#database) | 返回默认(当前)的数据库 | -| [`FOUND_ROWS()`](#found_rows) | 该函数对于一个包含 `LIMIT` 的 `SELECT` 查询语句,返回在不包含 `LIMIT` 的情况下的记录数 | -| [`LAST_INSERT_ID()`](#last_insert_id) | 返回上一条 `INSERT` 语句中自增列的值 | -| [`ROW_COUNT()`](#row_count) | 影响的行数 | -| [`SCHEMA()`](#schema) | 与 `DATABASE()` 同义 | -| [`SESSION_USER()`](#session_user) | 与 `USER()` 同义 | -| [`SYSTEM_USER()`](#system_user) | 与 `USER()` 同义 | -| [`USER()`](#user) | 返回客户端提供的用户名和主机名 | -| [`VERSION()`](#version) | 返回当前 MySQL 服务器的版本信息 | +TiDB 支持大多数 MySQL 8.0 中可用的[信息函数](https://dev.mysql.com/doc/refman/8.0/en/information-functions.html)。 + +## TiDB 支持的 MySQL 函数 + +| 名称 | 描述 | +|:-----|:------------| +| [`BENCHMARK()`](#benchmark) | 在循环中执行表达式 | +| [`CONNECTION_ID()`](#connection_id) | 返回连接 ID(线程 ID) | +| [`CURRENT_ROLE()`](#current_role) | 返回连接当前使用的角色 | +| [`CURRENT_USER()`, `CURRENT_USER`](#current_user) | 返回已认证的用户名和主机名 | +| [`DATABASE()`](#database) | 返回默认(当前)数据库名称 | +| [`FOUND_ROWS()`](#found_rows) | 对于带有 `LIMIT` 子句的 `SELECT`,返回如果没有 `LIMIT` 子句时将返回的行数 | +| [`LAST_INSERT_ID()`](#last_insert_id) | 返回最后一次 `INSERT` 的 `AUTOINCREMENT` 列的值 | +| [`ROW_COUNT()`](#row_count) | 受影响的行数 | +| [`SCHEMA()`](#schema) | `DATABASE()` 的同义词 | +| [`SESSION_USER()`](#session_user) | `USER()` 的同义词 | +| [`SYSTEM_USER()`](#system_user) | `USER()` 的同义词 | +| [`USER()`](#user) | 返回客户端提供的用户名和主机名 | +| [`VERSION()`](#version) | 返回表示 MySQL 服务器版本的字符串 | ### BENCHMARK() -`BENCHMARK()` 函数可以按照指定的次数重复执行给定的表达式。 +`BENCHMARK()` 函数将给定表达式执行指定次数。 语法: @@ -35,7 +35,7 @@ TiDB 支持使用 MySQL 8.0 中提供的大部分[信息函数](https://dev.mysq BENCHMARK(count, expression) ``` -- `count`:要执行表达式的次数。 +- `count`:表达式要执行的次数。 - `expression`:要重复执行的表达式。 示例: @@ -55,9 +55,21 @@ SELECT BENCHMARK(5, SLEEP(2)); ### CONNECTION_ID() -`CONNECTION_ID()` 函数返回连接的 ID。根据 TiDB 的 [`enable-32bits-connection-id`](/tidb-configuration-file.md#enable-32bits-connection-id-从-v730-版本开始引入) 配置项的值不同,该函数将返回一个 32 位或 64 位的连接 ID。 + -如果启用了 [`enable-global-kill`](/tidb-configuration-file.md#enable-global-kill-从-v610-版本开始引入),连接的 ID 可用于在同一集群的多个 TiDB 实例中终止查询。 +`CONNECTION_ID()` 函数返回连接的 ID。根据 TiDB 的 [`enable-32bits-connection-id`](/tidb-configuration-file.md#enable-32bits-connection-id-new-in-v730) 配置项的值,此函数返回 32 位或 64 位连接 ID。 + +如果启用了 [`enable-global-kill`](/tidb-configuration-file.md#enable-global-kill-new-in-v610),则可以使用连接 ID 在同一集群的多个 TiDB 实例之间终止查询。 + + + + + +`CONNECTION_ID()` 函数返回连接的 ID。根据 TiDB 的 [`enable-32bits-connection-id`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#enable-32bits-connection-id-new-in-v730) 配置项的值,此函数返回 32 位或 64 位连接 ID。 + +如果启用了 [`enable-global-kill`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#enable-global-kill-new-in-v610),则可以使用连接 ID 在同一集群的多个 TiDB 实例之间终止查询。 + + ```sql SELECT CONNECTION_ID(); @@ -74,8 +86,18 @@ SELECT CONNECTION_ID(); ### CURRENT_ROLE() + + `CURRENT_ROLE()` 函数返回当前会话的当前[角色](/role-based-access-control.md)。 + + + + +`CURRENT_ROLE()` 函数返回当前会话的当前[角色](https://docs.pingcap.com/tidb/stable/role-based-access-control)。 + + + ```sql SELECT CURRENT_ROLE(); ``` @@ -91,7 +113,7 @@ SELECT CURRENT_ROLE(); ### CURRENT_USER() -`CURRENT_USER()` 函数返回当前会话中使用的账户。 +`CURRENT_USER()` 函数返回当前会话使用的账户。 ```sql SELECT CURRENT_USER(); @@ -108,7 +130,7 @@ SELECT CURRENT_USER(); ### DATABASE() -`DATABASE()` 函数返回当前会话正在使用的数据库名。 +`DATABASE()` 函数返回当前会话正在使用的数据库架构。 ```sql SELECT DATABASE(); @@ -125,7 +147,7 @@ SELECT DATABASE(); ### FOUND_ROWS() -`FOUND_ROWS()` 函数返回上一条执行的 `SELECT` 语句的结果集中的行数。 +`FOUND_ROWS()` 函数返回最后执行的 `SELECT` 语句结果集中的行数。 ```sql SELECT 1 UNION ALL SELECT 2; @@ -156,11 +178,11 @@ SELECT FOUND_ROWS(); > **注意:** > -> `SQL_CALC_FOUND_ROWS` 查询修饰符用于计算在没有 `LIMIT` 子句的情况下结果集中的总行数,只有在启用了 [`tidb_enable_noop_functions`](/system-variables.md#tidb_enable_noop_functions-从-v40-版本开始引入) 时才能使用。从 MySQL 8.0.17 开始,该查询修饰符已废弃。建议使用 `COUNT(*)` 代替。 +> `SQL_CALC_FOUND_ROWS` 查询修饰符(用于计算结果集中的总行数而不考虑 `LIMIT` 子句)仅在启用 [`tidb_enable_noop_functions`](/system-variables.md#tidb_enable_noop_functions-new-in-v40) 时才被接受。从 MySQL 8.0.17 开始,此查询修饰符已被弃用。建议使用 `COUNT(*)` 代替。 ### LAST_INSERT_ID() -`LAST_INSERT_ID()` 函数返回包含 [`AUTO_INCREMENT`](/auto-increment.md) 或 [`AUTO_RANDOM`](/auto-random.md) 列的表中最后插入行的 ID。 +`LAST_INSERT_ID()` 函数返回最后插入到包含 [`AUTO_INCREMENT`](/auto-increment.md) 或 [`AUTO_RANDOM`](/auto-random.md) 列的表中的行的 ID。 ```sql CREATE TABLE t1(id SERIAL); @@ -192,9 +214,9 @@ TABLE t1; > **注意** > -> - 在 TiDB 中,[`AUTO_ID_CACHE`](/auto-increment.md#auto_id_cache) 可能会导致该函数的返回结果与 MySQL 不同。这是因为 TiDB 在每个节点上都会各自缓存 ID,这可能导致分配的 ID 出现无序或间隔。如果你的应用程序依赖于严格的 ID 顺序,可以启用[兼容 MySQL 的自增列模式](/auto-increment.md#兼容-mysql-的自增列模式)。 +> - 在 TiDB 中,[`AUTO_ID_CACHE`](/auto-increment.md#auto_id_cache) 可能导致结果与 MySQL 返回的结果不同。这种差异是因为 TiDB 在每个节点上缓存 ID,可能导致 ID 不按顺序或有间隔。如果您的应用程序需要严格的 ID 顺序,可以启用 [MySQL 兼容模式](/auto-increment.md#mysql-compatibility-mode)。 > -> - 在以上示例中,ID 是以 2 递增的,而 MySQL 在相同场景中生成的 ID 是以 1 递增的。关于兼容性的更多信息,请参见[自增 ID](/mysql-compatibility.md#自增-id)。 +> - 在上面的示例中,ID 增加了 2,而 MySQL 在相同情况下会生成增加 1 的 ID。有关更多兼容性信息,请参见[自增 ID](/mysql-compatibility.md#auto-increment-id)。 ### ROW_COUNT() @@ -219,19 +241,19 @@ SELECT ROW_COUNT(); ### SCHEMA() -`SCHEMA()` 函数与 [`DATABASE()`](#database) 同义。 +`SCHEMA()` 函数是 [`DATABASE()`](#database) 的同义词。 ### SESSION_USER() -`SESSION_USER()` 函数与 [`USER()`](#user) 同义。 +`SESSION_USER()` 函数是 [`USER()`](#user) 的同义词。 ### SYSTEM_USER() -`SYSTEM_USER()` 函数与 [`USER()`](#user) 同义。 +`SYSTEM_USER()` 函数是 [`USER()`](#user) 的同义词。 ### USER() -`USER()` 函数返回当前连接的用户。该函数的输出可能与 `CURRENT_USER()` 的输出略有不同,因为 `USER()` 显示的是实际 IP 地址,而不是通配符。 +`USER()` 函数返回当前连接的用户。这可能与 `CURRENT_USER()` 的输出略有不同,因为 `USER()` 显示实际的 IP 地址而不是通配符。 ```sql SELECT USER(), CURRENT_USER(); @@ -248,7 +270,7 @@ SELECT USER(), CURRENT_USER(); ### VERSION() -`VERSION()` 函数以与 MySQL 兼容的格式返回 TiDB 版本。如需获取更详细的版本信息,可以使用 [`TIDB_VERSION()`](/functions-and-operators/tidb-functions.md#tidb_version) 函数。 +`VERSION()` 函数返回与 MySQL 兼容格式的 TiDB 版本。要获取更详细的结果,可以使用 [`TIDB_VERSION()`](/functions-and-operators/tidb-functions.md#tidb_version) 函数。 ```sql SELECT VERSION(); @@ -275,19 +297,23 @@ Store: tikv 1 row in set (0.00 sec) ``` -以上示例来自 TiDB v7.5.1,它会将自身标识为 MySQL 8.0.11。 +上述示例来自 TiDB v7.5.1,它将自己标识为 MySQL 8.0.11。 + + + +如果要更改返回的版本,可以修改 [`server-version`](/tidb-configuration-file.md#server-version) 配置项。 -如需更改该函数返回的版本,可以修改 [`server-version`](/tidb-configuration-file.md#server-version) 配置项。 + -## TiDB 特有的信息函数 +## TiDB 特有函数 -下列函数为 TiDB 中特有的信息函数,MySQL 中无对应的函数。 +以下函数仅由 TiDB 支持,在 MySQL 中没有等效函数。 -| 函数名 | 功能描述 | -| ------ | ---------------------------------------- | -| [`CURRENT_RESOURCE_GROUP()`](/functions-and-operators/tidb-functions.md#current_resource_group) | 返回当前连接的资源组名 | +| 名称 | 描述 | +|:-----|:------------| +| [`CURRENT_RESOURCE_GROUP()`](/functions-and-operators/tidb-functions.md#current_resource_group) | 返回当前会话绑定的资源组名称 | -## TiDB 不支持的信息函数 +## 不支持的函数 * `CHARSET()` * `COERCIBILITY()` diff --git a/functions-and-operators/json-functions.md b/functions-and-operators/json-functions.md index 1d46deec8f41..b2b5e159c201 100644 --- a/functions-and-operators/json-functions.md +++ b/functions-and-operators/json-functions.md @@ -1,88 +1,88 @@ --- title: JSON 函数 -summary: TiDB 支持 MySQL 8.0 中提供的大部分 JSON 函数。 +summary: 了解 JSON 函数。 --- # JSON 函数 -你可以使用 JSON 函数处理 [JSON 类型](/data-type-json.md)的数据。 +您可以使用 JSON 函数来处理 [JSON 数据类型](/data-type-json.md) 中的数据。 ## 创建 JSON 值的函数 -| 函数 | 功能描述 | -| ------------------------------------------------------------------ | ---------------------------------------------------------- | -| [JSON_ARRAY()](/functions-and-operators/json-functions/json-functions-create.md#json_array) | 根据一系列元素(也可以为空)创建一个 JSON 数组 | -| [JSON_OBJECT()](/functions-and-operators/json-functions/json-functions-create.md#json_object) | 根据一系列包含 (key, value) 键值对的元素(也可以为空)创建一个 JSON 对象 | -| [JSON_QUOTE()](/functions-and-operators/json-functions/json-functions-create.md#json_quote) | 返回一个字符串,该字符串为带引号的 JSON 值 | +| 函数名 | 描述 | +| --------------------------------- | ----------- | +| [JSON_ARRAY()](/functions-and-operators/json-functions/json-functions-create.md#json_array) | 计算一个(可能为空的)值列表并返回包含这些值的 JSON 数组 | +| [JSON_OBJECT()](/functions-and-operators/json-functions/json-functions-create.md#json_object) | 计算一个(可能为空的)键值对列表并返回包含这些键值对的 JSON 对象 | +| [JSON_QUOTE()](/functions-and-operators/json-functions/json-functions-create.md#json_quote) | 将字符串作为带引号的 JSON 值返回 | ## 搜索 JSON 值的函数 -| 函数 | 功能描述 | -| ------------------------------------------------------------ | ------------------------------------------------------------ | -| [JSON_CONTAINS()](/functions-and-operators/json-functions/json-functions-search.md#json_contains) | 通过返回 1 或 0 来表示目标 JSON 文档中是否包含给定的 candidate JSON 文档 | -| [JSON_CONTAINS_PATH()](/functions-and-operators/json-functions/json-functions-search.md#json_contains_path) | 通过返回 0 或 1 来表示一个 JSON 文档在给定路径是否包含数据 | -| [JSON_EXTRACT()](/functions-and-operators/json-functions/json-functions-search.md#json_extract) | 从 JSON 文档中解出某一路径对应的子文档 | -| [->](/functions-and-operators/json-functions/json-functions-search.md#-) | 返回执行路径后面的 JSON 列的值;`JSON_EXTRACT(doc, path_literal)` 的别名 | -| [->>](/functions-and-operators/json-functions/json-functions-search.md#--1) | 返回执行路径后面的 JSON 列的值和转义后的结果; `JSON_UNQUOTE(JSON_EXTRACT(doc, path_literal))` 的别名 | -| [JSON_KEYS()](/functions-and-operators/json-functions/json-functions-search.md#json_keys) | 返回从 JSON 对象的顶级值作为 JSON array 的键,如果给定了路径参数,则从选定路径中获取顶级键 | -| [JSON_SEARCH()](/functions-and-operators/json-functions/json-functions-search.md#json_search) | 在 JSON 文档中搜索字符串的一个或所有匹配项 | -| [MEMBER OF()](/functions-and-operators/json-functions/json-functions-search.md#member-of) | 如果传入值是 JSON array 中的一个元素,返回 1,否则返回 0 | -| [JSON_OVERLAPS()](/functions-and-operators/json-functions/json-functions-search.md#json_overlaps) | 表示两个 JSON 文档中是否包含公共部分。返回 1 表示两个 JSON 文档中包含公共部分,否则返回 0 | +| 函数名 | 描述 | +| --------------------------------- | ----------- | +| [JSON_CONTAINS()](/functions-and-operators/json-functions/json-functions-search.md#json_contains) | 通过返回 1 或 0 来表示给定的候选 JSON 文档是否包含在目标 JSON 文档中 | +| [JSON_CONTAINS_PATH()](/functions-and-operators/json-functions/json-functions-search.md#json_contains_path) | 返回 0 或 1 以指示 JSON 文档在给定路径或多个路径中是否包含数据 | +| [JSON_EXTRACT()](/functions-and-operators/json-functions/json-functions-search.md#json_extract) | 从 JSON 文档中返回数据,从与 `path` 参数匹配的文档部分中选择 | +| [->](/functions-and-operators/json-functions/json-functions-search.md#-) | 在计算路径后从 JSON 列返回值;是 `JSON_EXTRACT(doc, path_literal)` 的别名 | +| [->>](/functions-and-operators/json-functions/json-functions-search.md#--1) | 在计算路径后从 JSON 列返回值并去除引号;是 `JSON_UNQUOTE(JSON_EXTRACT(doc, path_literal))` 的别名 | +| [JSON_KEYS()](/functions-and-operators/json-functions/json-functions-search.md#json_keys) | 以 JSON 数组的形式返回 JSON 对象顶层值的键,如果给定了路径参数,则返回所选路径的顶层键 | +| [JSON_SEARCH()](/functions-and-operators/json-functions/json-functions-search.md#json_search) | 在 JSON 文档中搜索字符串的一个或所有匹配项 | +| [MEMBER OF()](/functions-and-operators/json-functions/json-functions-search.md#member-of) | 如果传入的值是 JSON 数组的元素,则返回 1。否则返回 0。 | +| [JSON_OVERLAPS()](/functions-and-operators/json-functions/json-functions-search.md#json_overlaps) | 指示两个 JSON 文档是否有重叠部分。如果有,返回 1。如果没有,返回 0。 | ## 修改 JSON 值的函数 -| 函数 | 功能描述 | +| 函数名 | 描述 | | --------------------------------- | ----------- | -| [JSON_APPEND()](/functions-and-operators/json-functions/json-functions-modify.md#json_append) | `JSON_ARRAY_APPEND()` 的别名 | -| [JSON_ARRAY_APPEND()](/functions-and-operators/json-functions/json-functions-modify.md#json_array_append) | 将值添加到 JSON 文档指定数组的末尾,并返回添加结果 | -| [JSON_ARRAY_INSERT()](/functions-and-operators/json-functions/json-functions-modify.md#json_array_insert) | 将值插入到 JSON 文档中的指定位置并返回结果 | -| [JSON_INSERT()](/functions-and-operators/json-functions/json-functions-modify.md#json_insert) | 在 JSON 文档中在某一路径下插入子文档 | -| [JSON_MERGE_PATCH()](/functions-and-operators/json-functions/json-functions-modify.md#json_merge_patch) | 将两个或多个 JSON 文档合并为一个 JSON 文档,但不保留重复键的值 | -| [JSON_MERGE_PRESERVE()](/functions-and-operators/json-functions/json-functions-modify.md#json_merge_preserve) | 通过保留所有值的方式将两个或多个 JSON 文档合并成一个文档,并返回合并结果 | -| [JSON_MERGE()](/functions-and-operators/json-functions/json-functions-modify.md#json_merge) | 已废弃,`JSON_MERGE_PRESERVE()` 的别名 | -| [JSON_REMOVE()](/functions-and-operators/json-functions/json-functions-modify.md#json_remove) | 移除 JSON 文档中某一路径下的子文档,并返回结果 | -| [JSON_REPLACE()](/functions-and-operators/json-functions/json-functions-modify.md#json_replace)| 替换 JSON 文档中的某一路径下的子文档,并返回结果 | -| [JSON_SET()](/functions-and-operators/json-functions/json-functions-modify.md#json_set) | 在 JSON 文档中为某一路径设置子文档,并返回结果 | -| [JSON_UNQUOTE()](/functions-and-operators/json-functions/json-functions-modify.md#json_unquote) | 去掉 JSON 值外面的引号,返回结果为字符串 | +| [JSON_APPEND()](/functions-and-operators/json-functions/json-functions-modify.md#json_append) | `JSON_ARRAY_APPEND()` 的别名 | +| [JSON_ARRAY_APPEND()](/functions-and-operators/json-functions/json-functions-modify.md#json_array_append) | 将值追加到 JSON 文档中指定数组的末尾并返回结果 | +| [JSON_ARRAY_INSERT()](/functions-and-operators/json-functions/json-functions-modify.md#json_array_insert) | 将值插入到 JSON 文档的指定位置并返回结果 | +| [JSON_INSERT()](/functions-and-operators/json-functions/json-functions-modify.md#json_insert) | 将数据插入 JSON 文档并返回结果 | +| [JSON_MERGE_PATCH()](/functions-and-operators/json-functions/json-functions-modify.md#json_merge_patch) | 合并两个或多个 JSON 文档,不保留重复键的值 | +| [JSON_MERGE_PRESERVE()](/functions-and-operators/json-functions/json-functions-modify.md#json_merge_preserve) | 通过保留所有值来合并两个或多个 JSON 文档 | +| [JSON_MERGE()](/functions-and-operators/json-functions/json-functions-modify.md#json_merge) | `JSON_MERGE_PRESERVE()` 的已弃用别名 | +| [JSON_REMOVE()](/functions-and-operators/json-functions/json-functions-modify.md#json_remove) | 从 JSON 文档中删除数据并返回结果 | +| [JSON_REPLACE()](/functions-and-operators/json-functions/json-functions-modify.md#json_replace) | 替换 JSON 文档中的现有值并返回结果 | +| [JSON_SET()](/functions-and-operators/json-functions/json-functions-modify.md#json_set) | 在 JSON 文档中插入或更新数据并返回结果 | +| [JSON_UNQUOTE()](/functions-and-operators/json-functions/json-functions-modify.md#json_unquote) | 去除 JSON 值的引号并将结果作为字符串返回 | ## 返回 JSON 值属性的函数 -| 函数 | 功能描述 | +| 函数名 | 描述 | | --------------------------------- | ----------- | | [JSON_DEPTH()](/functions-and-operators/json-functions/json-functions-return.md#json_depth) | 返回 JSON 文档的最大深度 | -| [JSON_LENGTH()](/functions-and-operators/json-functions/json-functions-return.md#json_length) | 返回 JSON 文档的长度;如果路径参数已定,则返回该路径下值的长度 | -| [JSON_TYPE()](/functions-and-operators/json-functions/json-functions-return.md#json_type) | 检查某 JSON 文档内部内容的类型 | -| [JSON_VALID()](/functions-and-operators/json-functions/json-functions-return.md#json_valid) | 检查 json\_doc 是否为有效的 JSON 文档 | +| [JSON_LENGTH()](/functions-and-operators/json-functions/json-functions-return.md#json_length) | 返回 JSON 文档的长度,如果给定了路径参数,则返回该路径内值的长度 | +| [JSON_TYPE()](/functions-and-operators/json-functions/json-functions-return.md#json_type) | 返回指示 JSON 值类型的字符串 | +| [JSON_VALID()](/functions-and-operators/json-functions/json-functions-return.md#json_valid) | 检查 json\_doc 是否为有效的 JSON。 | -## 效用函数 +## 实用函数 -| 函数 | 功能描述 | +| 函数名 | 描述 | | --------------------------------- | ----------- | -| [JSON_PRETTY()](/functions-and-operators/json-functions/json-functions-utility.md#json_pretty) |格式化 JSON 文档 | -| [JSON_STORAGE_FREE()](/functions-and-operators/json-functions/json-functions-utility.md#json_storage_free) | 返回 JSON 值在原地更新操作后释放了多少存储空间,以二进制表示。 | -| [JSON_STORAGE_SIZE()](/functions-and-operators/json-functions/json-functions-utility.md#json_storage_size) | 返回存储 JSON 值所需的大致字节大小,由于不考虑 TiKV 压缩的字节大小,因此函数的输出与 MySQL 不严格兼容 | +| [JSON_PRETTY()](/functions-and-operators/json-functions/json-functions-utility.md#json_pretty) | JSON 文档的美化格式 | +| [JSON_STORAGE_FREE()](/functions-and-operators/json-functions/json-functions-utility.md#json_storage_free) | 返回 JSON 值原地更新后在其二进制表示中释放了多少存储空间。 | +| [JSON_STORAGE_SIZE()](/functions-and-operators/json-functions/json-functions-utility.md#json_storage_size) | 返回存储 JSON 值所需的大致字节数。由于该大小未考虑 TiKV 使用压缩,因此此函数的输出与 MySQL 不完全兼容。 | ## 聚合函数 -| 函数 | 功能描述 | +| 函数名 | 描述 | | --------------------------------- | ----------- | -| [JSON_ARRAYAGG()](/functions-and-operators/json-functions/json-functions-aggregate.md#json_arrayagg) | 提供指定列 key 的聚合 | -| [JSON_OBJECTAGG()](/functions-and-operators/json-functions/json-functions-aggregate.md#json_objectagg) | 提供给定两列键值对的聚合 | +| [JSON_ARRAYAGG()](/functions-and-operators/json-functions/json-functions-aggregate.md#json_arrayagg) | 提供键的聚合。 | +| [JSON_OBJECTAGG()](/functions-and-operators/json-functions/json-functions-aggregate.md#json_objectagg) | 提供给定键的值的聚合。 | ## JSONPath -许多 JSON 函数都使用 [JSONPath](https://www.rfc-editor.org/rfc/rfc9535.html) 来选择 JSON 文档中的特定内容。 +许多 JSON 函数使用 [JSONPath](https://www.rfc-editor.org/rfc/rfc9535.html) 来选择 JSON 文档的部分内容。 | 符号 | 描述 | | -------------- | ---------------------------- | -| `$` | 文件根目录 | -| `.` | 选择成员 | -| `[]` | 选择数组 | +| `$` | 文档根 | +| `.` | 成员选择 | +| `[]` | 数组选择 | | `*` | 通配符 | -| `**` | 路径通配符 | -| `[ to ]` | 选择数组范围 | +| `**` | 路径通配符 | +| `[ to ]` | 数组范围选择 | -下面以如下 JSON 文档为例,说明如何使用 JSONPath: +以下内容以这个 JSON 文档为例来演示如何使用 JSONPath: ```json { @@ -99,10 +99,10 @@ summary: TiDB 支持 MySQL 8.0 中提供的大部分 JSON 函数。 { "version": "v8.1.2", "type": "lts", - "release_date": "2024-12-26" + "release_date": "2024-12-26" }, { - "version": "v8.0.0", + "version": "v8.0.0", "type": "dmr", "release_date": "2024-03-29" } @@ -111,7 +111,7 @@ summary: TiDB 支持 MySQL 8.0 中提供的大部分 JSON 函数。 "migration_tool": { "name": "TiDB Data Migration", "features": [ - "MySQL compatible", + "MySQL compatible", "Shard merging" ], "license": "Apache-2.0 license" @@ -119,25 +119,25 @@ summary: TiDB 支持 MySQL 8.0 中提供的大部分 JSON 函数。 } ``` -| JSONPath | 描述 | [`JSON_EXTRACT()`](/functions-and-operators/json-functions/json-functions-search.md#json_extract) 示例| +| JSONPath | 描述 | 使用 [`JSON_EXTRACT()`](/functions-and-operators/json-functions/json-functions-search.md#json_extract) 的示例 | |-------------------------------------- |-----------------------------------------|-------------------------------| -| `$` | 文档根目录 | 返回完整文档 | -| `$.database` | `database` 对象 | 返回以 `"database"` 开头的完整结构。不包括 `"migration_tool"` 和其下的结构。 | -| `$.database.name` | `database` 的 `name` 值 | `"TiDB"` | -| `$.database.features` | `database` 的 `features` 值 | `["distributed", "scalable", "relational", "cloud native"]` | -| `$.database.features[0]` | `database` 的 `features` 中的第一个值 | `"distributed"` | -| `$.database.features[2]` | `database` 的 `features` 中的第三个值 | `"relational"` | -| `$.database.versions[0].type` | `database` 的 `versions` 中第一个元素的 `type` 值 | `"lts"` | -| `$.database.versions[*].release_date` | `versions` 中所有的 `release_date` 值 | `["2024-12-26","2024-03-29"]` | -| `$.*.features` | 由所有的 `features` 值组成的两个数组 | `[["distributed", "scalable", "relational", "cloud native"], ["MySQL compatible", "Shard merging"]]` | -| `$**.version` | 包含用通配符匹配到所有的 `version` 值 | `["v8.1.2","v8.0.0"]` | -| `$.database.features[0 to 2]` | `database` 中指定范围的 `features` 值,`features[0 to 2]` 代表从 `features` 的第一个值到第三个值 | `["scalable","relational"]` | - -更多信息,请参考 [JSONPath -- XPath for JSON](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html)。 +| `$` | 文档的根 | 返回完整文档 | +| `$.database` | `database` 对象 | 返回以 `"database"` 开始的完整结构。不包括 `"migration_tool"` 及其下的结构。 | +| `$.database.name` | 数据库的名称 | `"TiDB"` | +| `$.database.features` | 所有数据库特性 | `["distributed", "scalable", "relational", "cloud native"]` | +| `$.database.features[0]` | 第一个数据库特性 | `"distributed"` | +| `$.database.features[2]` | 第三个数据库特性 | `"relational"` | +| `$.database.versions[0].type` | 第一个数据库版本的类型 | `"lts"` | +| `$.database.versions[*].release_date` | 所有版本的发布日期 | `["2024-12-26","2024-03-29"]` | +| `$.*.features` | 两个特性数组 | `[["distributed", "scalable", "relational", "cloud native"], ["MySQL compatible", "Shard merging"]]` | +| `$**.version` | 使用路径通配符的所有版本 | `["v8.1.2","v8.0.0"]` | +| `$.database.features[0 to 2]` | 从第一个到第三个的数据库特性范围 | `["scalable","relational"]` | + +更多信息,请参见 [IETF 的 JSONPath 草案](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html)。 ## 另请参阅 -- [JSON 数据类型](/data-type-json.md) +* [JSON 数据类型](/data-type-json.md) ## 不支持的函数 @@ -146,8 +146,8 @@ summary: TiDB 支持 MySQL 8.0 中提供的大部分 JSON 函数。 - `JSON_TABLE()` - `JSON_VALUE()` -更多信息,请参考 [#14486](https://github.com/pingcap/tidb/issues/14486)。 +更多信息,请参见 [#14486](https://github.com/pingcap/tidb/issues/14486)。 ## MySQL 兼容性 -- TiDB 支持 MySQL 8.0 中的大部分 [JSON 函数](https://dev.mysql.com/doc/refman/8.0/en/json-functions.html)。 +- TiDB 支持 MySQL 8.0 中提供的大多数 [JSON 函数](https://dev.mysql.com/doc/refman/8.0/en/json-functions.html)。 diff --git a/functions-and-operators/json-functions/json-functions-aggregate.md b/functions-and-operators/json-functions/json-functions-aggregate.md index a419676cc506..dcb8a696d7cb 100644 --- a/functions-and-operators/json-functions/json-functions-aggregate.md +++ b/functions-and-operators/json-functions/json-functions-aggregate.md @@ -1,19 +1,19 @@ --- title: 聚合 JSON 值的 JSON 函数 -summary: 了解聚合 JSON 值的 JSON 函数。 +summary: 了解用于聚合 JSON 值的 JSON 函数。 --- # 聚合 JSON 值的 JSON 函数 -本文档介绍 TiDB [聚合函数](/functions-and-operators/aggregate-group-by-functions.md) 中专门用于处理 JSON 的聚合函数。 +本页列出的函数是 TiDB 支持的[聚合函数](/functions-and-operators/aggregate-group-by-functions.md)的一部分,专门用于处理 JSON。 ## [JSON_ARRAYAGG()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-arrayagg) -`JSON_ARRAYAGG(key)` 函数可以根据给定的 `key` 将 `key` 值聚合到一个 JSON 数组中。`key` 通常为表达式或列名。 +`JSON_ARRAYAGG(key)` 函数根据给定的 `key` 将键的值聚合成一个 JSON 数组。`key` 通常是一个表达式或列名。 示例: -在下面示例中,表格一列中的两条记录被聚合到一个 JSON 数组中。 +以下示例中,表中一列的两行数据被聚合成一个 JSON 数组。 ```sql SELECT JSON_ARRAYAGG(v) FROM (SELECT 1 'v' UNION SELECT 2); @@ -30,11 +30,11 @@ SELECT JSON_ARRAYAGG(v) FROM (SELECT 1 'v' UNION SELECT 2); ## [JSON_OBJECTAGG()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-objectagg) -`JSON_OBJECTAGG(key,value)` 函数可以根据给定的 `key` 和 `value` 将 `key` 值和 `value` 值聚合成一个 JSON 对象。`key` 和 `value` 通常为表达式或列名。 +`JSON_OBJECTAGG(key,value)` 函数根据给定的 `key` 和 `value` 将键和值聚合成一个 JSON 对象。`key` 和 `value` 通常都是表达式或列名。 示例: -首先创建两个表,并在其中添加几行数据。 +首先,创建两个表并添加一些行数据。 ```sql CREATE TABLE plants ( @@ -66,7 +66,7 @@ VALUES (3, "thorns","no"); ``` -查看创建的表格的结果。 +现在可以查看创建的表的内容。 ```sql TABLE plants; @@ -102,7 +102,7 @@ TABLE plant_attributes; 7 rows in set (0.00 sec) ``` -你可以使用 `JSON_OBJECTAGG()` 函数来处理这些数据。在下面示例中,你可以看到每个 Group 中,多个键/值对被聚合成一个 JSON 对象。 +你可以使用 `JSON_OBJECTAGG()` 函数处理这些数据。在下面的示例中,你可以看到对于每个分组,多个键值对被聚合成一个 JSON 对象。 ```sql SELECT @@ -128,5 +128,5 @@ GROUP BY ## 另请参阅 -- [JSON 函数](/functions-and-operators/json-functions.md) -- [JSON 数据类型](/data-type-json.md) \ No newline at end of file +- [JSON 函数概览](/functions-and-operators/json-functions.md) +- [JSON 数据类型](/data-type-json.md) diff --git a/functions-and-operators/json-functions/json-functions-create.md b/functions-and-operators/json-functions/json-functions-create.md index fc8d3b3faa2f..bcde7ba27da1 100644 --- a/functions-and-operators/json-functions/json-functions-create.md +++ b/functions-and-operators/json-functions/json-functions-create.md @@ -1,15 +1,15 @@ --- title: 创建 JSON 值的 JSON 函数 -summary: 了解创建 JSON 值的 JSON 函数。 +summary: 了解用于创建 JSON 值的 JSON 函数。 --- # 创建 JSON 值的 JSON 函数 -本文档介绍用于创建 JSON 值的 JSON 函数。 +本文档描述了用于创建 JSON 值的 JSON 函数。 ## [JSON_ARRAY()](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-array) -`JSON_ARRAY([val[, val] ...])` 函数接受一个值列表(可能为空)作为参数,并返回一个包含这些值的 JSON 数组。 +`JSON_ARRAY([val[, val] ...])` 函数计算一个(可能为空的)值列表,并返回包含这些值的 JSON 数组。 ```sql SELECT JSON_ARRAY(1,2,3,4,5), JSON_ARRAY("foo", "bar"); @@ -26,7 +26,7 @@ SELECT JSON_ARRAY(1,2,3,4,5), JSON_ARRAY("foo", "bar"); ## [JSON_OBJECT()](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-object) -`JSON_OBJECT([key,val[,key,val]...])` 函数接受一个键值对列表(可能为空)作为参数,并返回一个包含这些键值对的 JSON 对象。 +`JSON_OBJECT([key, val[, key, val] ...])` 函数计算一个(可能为空的)键值对列表,并返回包含这些键值对的 JSON 对象。 ```sql SELECT JSON_OBJECT("database", "TiDB", "distributed", TRUE); @@ -43,7 +43,7 @@ SELECT JSON_OBJECT("database", "TiDB", "distributed", TRUE); ## [JSON_QUOTE()](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-quote) -`JSON_QUOTE(str)` 函数将字符串返回为带引号的 JSON 值。 +`JSON_QUOTE(str)` 函数将字符串作为带引号的 JSON 值返回。 ```sql SELECT JSON_QUOTE('The name is "O\'Neil"'); @@ -60,5 +60,5 @@ SELECT JSON_QUOTE('The name is "O\'Neil"'); ## 另请参阅 -- [JSON 函数](/functions-and-operators/json-functions.md) -- [JSON 数据类型](/data-type-json.md) \ No newline at end of file +- [JSON 函数概览](/functions-and-operators/json-functions.md) +- [JSON 数据类型](/data-type-json.md) diff --git a/functions-and-operators/json-functions/json-functions-modify.md b/functions-and-operators/json-functions/json-functions-modify.md index 2f4f170c5759..46c6b9309f63 100644 --- a/functions-and-operators/json-functions/json-functions-modify.md +++ b/functions-and-operators/json-functions/json-functions-modify.md @@ -1,25 +1,25 @@ --- title: 修改 JSON 值的 JSON 函数 -summary: 了解修改 JSON 值的 JSON 函数。 +summary: 了解用于修改 JSON 值的 JSON 函数。 --- # 修改 JSON 值的 JSON 函数 -本文档介绍用于修改 JSON 值的 JSON 函数。 +本文档描述用于修改 JSON 值的 JSON 函数。 ## [JSON_APPEND()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-append) -该函数为 [`JSON_ARRAY_APPEND()`](#json_array_append) 的别名。 +[`JSON_ARRAY_APPEND()`](#json_array_append) 的别名。 ## [JSON_ARRAY_APPEND()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-array-append) -`JSON_ARRAY_APPEND(json_array, path, value [,path, value] ...)` 函数将 `value` 插入 `path` 中指定的 `json_array` 数组的末尾,并返回结果。 +`JSON_ARRAY_APPEND(json_array, path, value [,path, value] ...)` 函数将值追加到 JSON 文档中指定 `path` 的数组末尾,并返回结果。 -该函数可接受成对的 `path` 和 `value` 参数。 +此函数接受成对的参数,每对参数包含一个 `path` 和一个 `value`。 示例: -下面示例向 JSON 文档根目录的数组添加了一个元素。 +以下示例将一个项目添加到作为 JSON 文档根的数组中。 ```sql SELECT JSON_ARRAY_APPEND('["Car", "Boat", "Train"]', '$', "Airplane") AS "Transport options"; @@ -34,7 +34,7 @@ SELECT JSON_ARRAY_APPEND('["Car", "Boat", "Train"]', '$', "Airplane") AS "Transp 1 row in set (0.00 sec) ``` -下面的示例向指定路径下的数组添加了一个元素。 +以下示例将一个项目添加到指定路径的数组中。 ```sql SELECT JSON_ARRAY_APPEND('{"transport_options": ["Car", "Boat", "Train"]}', '$.transport_options', "Airplane") AS "Transport options"; @@ -51,13 +51,13 @@ SELECT JSON_ARRAY_APPEND('{"transport_options": ["Car", "Boat", "Train"]}', '$.t ## [JSON_ARRAY_INSERT()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-array-insert) -`JSON_ARRAY_INSERT(json_array, path, value [,path, value] ...)` 函数将 `value` 插入 `path` 中 `json_array` 的指定位置,并返回结果。 +`JSON_ARRAY_INSERT(json_array, path, value [,path, value] ...)` 函数将 `value` 插入到 `path` 中指定的 `json_array` 位置,并返回结果。 -该函数可接受成对的 `path` 和 `value` 参数。 +此函数接受成对的参数,每对参数包含一个 `path` 和一个 `value`。 示例: -下面的示例在数组中索引为 0 的位置插入了一个值。 +以下示例在数组的索引 0 位置插入一个值。 ```sql SELECT JSON_ARRAY_INSERT('["Car", "Boat", "Train"]', '$[0]', "Airplane") AS "Transport options"; @@ -72,7 +72,7 @@ SELECT JSON_ARRAY_INSERT('["Car", "Boat", "Train"]', '$[0]', "Airplane") AS "Tra 1 row in set (0.01 sec) ``` -下面的示例在数组中索引为 1 的位置插入了一个值。 +以下示例在数组的索引 1 位置插入一个值。 ```sql SELECT JSON_ARRAY_INSERT('["Car", "Boat", "Train"]', '$[1]', "Airplane") AS "Transport options"; @@ -89,9 +89,9 @@ SELECT JSON_ARRAY_INSERT('["Car", "Boat", "Train"]', '$[1]', "Airplane") AS "Tra ## [JSON_INSERT()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-insert) -`JSON_INSERT(json_doc,path,value[,path,value] ...)` 函数将一个或多个值插入到 JSON 文档,并返回结果。 +`JSON_INSERT(json_doc, path, value [,path, value] ...)` 函数将一个或多个值插入到 JSON 文档中并返回结果。 -该函数可接受成对的 `path` 和 `value` 参数。 +此函数接受成对的参数,每对参数包含一个 `path` 和一个 `value`。 ```sql SELECT JSON_INSERT( @@ -110,7 +110,7 @@ SELECT JSON_INSERT( 1 row in set (0.00 sec) ``` -请注意,该函数不会覆盖现有属性。例如,以下语句看起来会覆盖 `"a"` 属性现有的值,但实际上并不会。 +注意,此函数不会覆盖现有属性的值。例如,以下语句看似要覆盖 `"a"` 属性,但实际上并不会这样做。 ```sql SELECT JSON_INSERT('{"a": 61, "b": 62}', '$.a', 41, '$.c', 63); @@ -127,11 +127,11 @@ SELECT JSON_INSERT('{"a": 61, "b": 62}', '$.a', 41, '$.c', 63); ## [JSON_MERGE_PATCH()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-merge-patch) -`JSON_MERGE_PATCH(json_doc, json_doc [,json_doc] ...)` 将两个或多个 JSON 文档合并为一个 JSON 文档,但不保留重复键的值。如果其中某些 `json_doc` 参数包含重复的键,合并后的结果只保留后面指定的那个 `json_doc` 参数中的值。 +`JSON_MERGE_PATCH(json_doc, json_doc [,json_doc] ...)` 函数将两个或多个 JSON 文档合并为单个 JSON 文档,不保留重复键的值。对于具有重复键的 `json_doc` 参数,合并结果中仅保留后面指定的 `json_doc` 参数中的值。 示例: -在下面的示例中,可以看到合并结果中 `a` 的值被第二个参数覆盖,而 `c` 被添加为一个新属性。 +在以下示例中,可以看到 `a` 的值被参数 2 覆盖,而 `c` 作为新属性添加到合并结果中。 ```sql SELECT JSON_MERGE_PATCH( @@ -152,11 +152,11 @@ SELECT JSON_MERGE_PATCH( ## [JSON_MERGE_PRESERVE()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-merge-preserve) -`JSON_MERGE_PRESERVE(json_doc, json_doc [,json_doc] ...)` 函数通过保留所有键值的方式合并两个或多个 JSON 文档,并返回合并结果。 +`JSON_MERGE_PRESERVE(json_doc, json_doc [,json_doc] ...)` 函数在保留与每个键关联的所有值的同时合并两个或多个 JSON 文档,并返回合并结果。 示例: -在下面的示例中,可以看到第二个参数的值被附加到了 `a` 中,并且 `c` 被添加为一个新属性。 +在以下示例中,可以看到参数 2 的值被追加到 `a` 中,而 `c` 作为新属性添加。 ```sql SELECT JSON_MERGE_PRESERVE('{"a": 1, "b": 2}','{"a": 100}', '{"c": 300}'); @@ -175,17 +175,17 @@ SELECT JSON_MERGE_PRESERVE('{"a": 1, "b": 2}','{"a": 100}', '{"c": 300}'); > **警告:** > -> 该函数已废弃。 +> 此函数已弃用。 -该函数为 [`JSON_MERGE_PRESERVE()`](#json_merge_preserve) 已废弃的别名。 +[`JSON_MERGE_PRESERVE()`](#json_merge_preserve) 的已弃用别名。 ## [JSON_REMOVE()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-remove) -`JSON_REMOVE(json_doc,path [,path] ...)` 函数从 JSON 文档中删除指定 `path` 的数据并返回结果。 +`JSON_REMOVE(json_doc, path [,path] ...)` 函数从 JSON 文档中删除指定 `path` 的数据并返回结果。 示例: -下面示例删除了 JSON 文档中的 `b` 属性。 +此示例从 JSON 文档中删除 `b` 属性。 ```sql SELECT JSON_REMOVE('{"a": 61, "b": 62, "c": 63}','$.b'); @@ -200,7 +200,7 @@ SELECT JSON_REMOVE('{"a": 61, "b": 62, "c": 63}','$.b'); 1 row in set (0.00 sec) ``` -下面示例删除了 JSON 文档中的 `b` 和 `c` 属性。 +此示例从 JSON 文档中删除 `b` 和 `c` 属性。 ```sql SELECT JSON_REMOVE('{"a": 61, "b": 62, "c": 63}','$.b','$.c'); @@ -217,13 +217,13 @@ SELECT JSON_REMOVE('{"a": 61, "b": 62, "c": 63}','$.b','$.c'); ## [JSON_REPLACE()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-replace) -`JSON_REPLACE(json_doc,path,value[,path,value]...)` 函数替换 JSON 文档中的现有的值并返回结果。如果指定的路径不存在,该路径对应的值不会添加到结果中。 +`JSON_REPLACE(json_doc, path, value [, path, value] ...)` 函数替换 JSON 文档中指定路径的值并返回结果。如果指定的路径不存在,则不会将对应路径的值添加到结果中。 -该函数可接受成对的 `path` 和 `value` 参数。 +此函数接受成对的参数,每对参数包含一个 `path` 和一个 `value`。 示例: -下面的示例将 `$.b` 的值从 `62` 替换为 `42`。 +在以下示例中,将 `$.b` 的值从 `62` 更改为 `42`。 ```sql SELECT JSON_REPLACE('{"a": 41, "b": 62}','$.b',42); @@ -238,7 +238,7 @@ SELECT JSON_REPLACE('{"a": 41, "b": 62}','$.b',42); 1 row in set (0.00 sec) ``` -下面的示例将 `$.b` 的值从 `62` 替换为 `42`。此外,该语句试图用 `43` 替换 `$.c` 中的值,但不会替换成功,因为在 `{"a": 41, "b": 62}` 中 `$.c` 路径不存在。 +在以下示例中,将 `$.b` 的值从 `62` 更改为 `42`。此外,该语句尝试将 `$.c` 的值替换为 `43`,但这不起作用,因为 `$.c` 路径在 `{"a": 41, "b": 62}` 中不存在。 ```sql SELECT JSON_REPLACE('{"a": 41, "b": 62}','$.b',42,'$.c',43); @@ -255,13 +255,13 @@ SELECT JSON_REPLACE('{"a": 41, "b": 62}','$.b',42,'$.c',43); ## [JSON_SET()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-set) -`JSON_SET(json_doc,path,value[,path,value] ...)` 函数在 JSON 文档中插入或更新数据,并返回结果。 +`JSON_SET(json_doc, path, value [,path, value] ...)` 函数在 JSON 文档中插入或更新数据并返回结果。 -该函数可接受成对的 `path` 和 `value` 参数。 +此函数接受成对的参数,每对参数包含一个 `path` 和一个 `value`。 示例: -下面的示例将 `$.version` 从 `1.1` 更新为 `1.2`。 +在以下示例中,将 `$.version` 从 `1.1` 更新为 `1.2`。 ```sql SELECT JSON_SET('{"version": 1.1, "name": "example"}','$.version',1.2); @@ -276,7 +276,7 @@ SELECT JSON_SET('{"version": 1.1, "name": "example"}','$.version',1.2); 1 row in set (0.00 sec) ``` -下面的示例将 `$.version` 从 `1.1` 更新为 `1.2`,并将之前不存在的 `$.branch` 更新为 `main`。 +在以下示例中,将 `$.version` 从 `1.1` 更新为 `1.2`。并将之前不存在的 `$.branch` 更新为 `main`。 ```sql SELECT JSON_SET('{"version": 1.1, "name": "example"}','$.version',1.2,'$.branch', "main"); @@ -293,11 +293,11 @@ SELECT JSON_SET('{"version": 1.1, "name": "example"}','$.version',1.2,'$.branch' ## [JSON_UNQUOTE()](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-unquote) -`JSON_UNQUOTE(json)` 函数去掉 JSON 值的引号,并以字符串形式返回结果。该函数与 [`JSON_QUOTE()`](/functions-and-operators/json-functions/json-functions-create.md#json_quote) 函数作用相反。 +`JSON_UNQUOTE(json)` 函数取消引用 JSON 值并将结果作为字符串返回。这与 [`JSON_QUOTE()`](/functions-and-operators/json-functions/json-functions-create.md#json_quote) 函数相反。 示例: -下面示例将 `"foo"` 去掉引号,变成 `foo`。 +在示例中,`"foo"` 被取消引用为 `foo`。 ```sql SELECT JSON_UNQUOTE('"foo"'); @@ -312,7 +312,7 @@ SELECT JSON_UNQUOTE('"foo"'); 1 row in set (0.00 sec) ``` -该函数通常与 [`JSON_EXTRACT()`](/functions-and-operators/json-functions/json-functions-search.md#json_extract) 一起使用。在下面的示例中,第一个示例提取带引号的 JSON 值,第二个示例通过将两个函数结合使用去掉提取值的引号。请注意,你可以使用 [`->>`](/functions-and-operators/json-functions/json-functions-search.md#--1) 操作符来代替 `JSON_UNQUOTE(JSON_EXTRACT(...))`。 +此函数通常与 [`JSON_EXTRACT()`](/functions-and-operators/json-functions/json-functions-search.md#json_extract) 一起使用。对于以下示例,您可以在第一个示例中提取带引号的 JSON 值,然后在第二个示例中一起使用这两个函数来取消引用该值。请注意,您可以使用 [`->>`](/functions-and-operators/json-functions/json-functions-search.md#--1) 运算符代替 `JSON_UNQUOTE(JSON_EXTRACT(...))`。 ```sql SELECT JSON_EXTRACT('{"database": "TiDB"}', '$.database'); @@ -342,5 +342,5 @@ SELECT JSON_UNQUOTE(JSON_EXTRACT('{"database": "TiDB"}', '$.database')); ## 另请参阅 -- [JSON 函数](/functions-and-operators/json-functions.md) -- [JSON 数据类型](/data-type-json.md) \ No newline at end of file +- [JSON 函数概览](/functions-and-operators/json-functions.md) +- [JSON 数据类型](/data-type-json.md) diff --git a/functions-and-operators/json-functions/json-functions-return.md b/functions-and-operators/json-functions/json-functions-return.md index 9adb89071d6b..274528e5fcca 100644 --- a/functions-and-operators/json-functions/json-functions-return.md +++ b/functions-and-operators/json-functions/json-functions-return.md @@ -5,7 +5,7 @@ summary: 了解返回 JSON 值的 JSON 函数。 # 返回 JSON 值的 JSON 函数 -本文介绍返回 JSON 值的 JSON 函数。 +本文档描述了返回 JSON 值的 JSON 函数。 ## [JSON_DEPTH()](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-depth) @@ -13,9 +13,9 @@ summary: 了解返回 JSON 值的 JSON 函数。 示例: -在下面的示例中,`JSON_DEPTH()` 返回 `3`,因为有三层: +在以下示例中,`JSON_DEPTH()` 返回 `3`,因为有三个层级: -- root (`$`) +- 根级别 (`$`) - weather (`$.weather`) - weather current (`$.weather.sunny`) @@ -34,11 +34,11 @@ SELECT JSON_DEPTH('{"weather": {"current": "sunny"}}'); ## [JSON_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-length) -`JSON_LENGTH(json_doc [,path])` 函数返回 JSON 文档的长度。如果指定了 `path` 参数,则返回路径中的值的长度。 +`JSON_LENGTH(json_doc [,path])` 函数返回 JSON 文档的长度。如果提供了 `path` 参数,则返回该路径下值的长度。 示例: -在下面的示例中,返回值是 `1`,因为文档根目录下仅有一个元素 `weather`。 +在以下示例中,返回值为 `1`,因为文档根级别只有一个项目 `weather`。 ```sql SELECT JSON_LENGTH('{"weather": {"current": "sunny", "tomorrow": "cloudy"}}','$'); @@ -53,7 +53,7 @@ SELECT JSON_LENGTH('{"weather": {"current": "sunny", "tomorrow": "cloudy"}}','$' 1 row in set (0.00 sec) ``` -在下面的示例中,`$.weather` 包含两个元素 `current` 和`tomorrow`,因此返回值为 `2`。 +在以下示例中,返回值为 `2`,因为在 `$.weather` 路径下有两个项目:`current` 和 `tomorrow`。 ```sql SELECT JSON_LENGTH('{"weather": {"current": "sunny", "tomorrow": "cloudy"}}','$.weather'); @@ -70,19 +70,19 @@ SELECT JSON_LENGTH('{"weather": {"current": "sunny", "tomorrow": "cloudy"}}','$. ## [JSON_TYPE()](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-type) -`JSON_TYPE(json_val)` 函数返回一个字符串,表示 [JSON 值的类型](/data-type-json.md#json-值的类型)。 +`JSON_TYPE(json_val)` 函数返回一个字符串,表示 [JSON 值的类型](/data-type-json.md#json-value-types)。 示例: ```sql WITH demo AS ( - SELECT 'null' AS 'v' - UNION SELECT '"foobar"' - UNION SELECT 'true' - UNION SELECT '5' - UNION SELECT '1.14' - UNION SELECT '[]' - UNION SELECT '{}' + SELECT 'null' AS 'v' + UNION SELECT '"foobar"' + UNION SELECT 'true' + UNION SELECT '5' + UNION SELECT '1.14' + UNION SELECT '[]' + UNION SELECT '{}' UNION SELECT POW(2,63) ) SELECT v, JSON_TYPE(v) FROM demo ORDER BY 2; @@ -104,7 +104,7 @@ SELECT v, JSON_TYPE(v) FROM demo ORDER BY 2; 8 rows in set (0.00 sec) ``` -请注意,看起来相同的值可能属于不同的类型,如下例所示。 +请注意,看起来相同的值可能具有不同的类型,如以下示例所示。 ```sql SELECT '"2025-06-14"',CAST(CAST('2025-06-14' AS date) AS json); @@ -134,7 +134,7 @@ SELECT JSON_TYPE('"2025-06-14"'),JSON_TYPE(CAST(CAST('2025-06-14' AS date) AS js ## [JSON_VALID()](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-valid) -`JSON_VALID(str)` 函数检查输入的参数是否为有效的 JSON 格式。该函数对于在将列转换为 `JSON` 类型之前进行检查非常有用。 +`JSON_VALID(str)` 函数检查参数是否为有效的 JSON。这在将列转换为 `JSON` 类型之前进行检查时很有用。 ```sql SELECT JSON_VALID('{"foo"="bar"}'); @@ -162,7 +162,7 @@ SELECT JSON_VALID('{"foo": "bar"}'); 1 row in set (0.01 sec) ``` -## 另请参考 +## 另请参阅 -- [JSON 函数](/functions-and-operators/json-functions.md) +- [JSON 函数概览](/functions-and-operators/json-functions.md) - [JSON 数据类型](/data-type-json.md) diff --git a/functions-and-operators/json-functions/json-functions-search.md b/functions-and-operators/json-functions/json-functions-search.md index ee9d4e626b61..9ebfe7e1e5a3 100644 --- a/functions-and-operators/json-functions/json-functions-search.md +++ b/functions-and-operators/json-functions/json-functions-search.md @@ -1,19 +1,19 @@ --- title: 搜索 JSON 值的 JSON 函数 -summary: 了解搜索 JSON 值的 JSON 函数。 +summary: 了解用于搜索 JSON 值的 JSON 函数。 --- # 搜索 JSON 值的 JSON 函数 -本文档介绍用于搜索 JSON 值的 JSON 函数。 +本文档描述了用于搜索 JSON 值的 JSON 函数。 ## [JSON_CONTAINS()](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains) -通过返回 `1` 或 `0`,`JSON_CONTAINS(json_doc, candidate [,path])` 函数用于确认指定的 JSON 文档 `candidate` 是否包含在目标 JSON 文档中。 +`JSON_CONTAINS(json_doc, candidate [,path])` 函数通过返回 `1` 或 `0` 来指示给定的 `candidate` JSON 文档是否包含在目标 JSON 文档中。 示例: -下面示例中,`a` 包含在了目标文档中。 +这里 `a` 包含在目标文档中。 ```sql SELECT JSON_CONTAINS('["a","b","c"]','"a"'); @@ -28,7 +28,7 @@ SELECT JSON_CONTAINS('["a","b","c"]','"a"'); 1 row in set (0.00 sec) ``` -下面示例中,`a` 没有包含在目标文档中。 +这里 `e` 不包含在目标文档中。 ```sql SELECT JSON_CONTAINS('["a","b","c"]','"e"'); @@ -43,7 +43,7 @@ SELECT JSON_CONTAINS('["a","b","c"]','"e"'); 1 row in set (0.00 sec) ``` -下面示例中,`{"foo": "bar"}` 包含在了目标文档中。 +这里 `{"foo": "bar"}` 包含在目标文档中。 ```sql SELECT JSON_CONTAINS('{"foo": "bar", "aaa": 5}','{"foo": "bar"}'); @@ -58,7 +58,7 @@ SELECT JSON_CONTAINS('{"foo": "bar", "aaa": 5}','{"foo": "bar"}'); 1 row in set (0.00 sec) ``` -下面示例中,`"bar"` 没有包含在目标文档的根目录中。 +这里 `"bar"` 不包含在目标文档的根部。 ```sql SELECT JSON_CONTAINS('{"foo": "bar", "aaa": 5}','"bar"'); @@ -73,7 +73,7 @@ SELECT JSON_CONTAINS('{"foo": "bar", "aaa": 5}','"bar"'); 1 row in set (0.00 sec) ``` -下面示例中,`"bar"` 包含在了目标文档的 `$.foo` 属性中。 +这里 `"bar"` 包含在目标文档的 `$.foo` 属性中。 ```sql SELECT JSON_CONTAINS('{"foo": "bar", "aaa": 5}','"bar"', '$.foo'); @@ -90,11 +90,11 @@ SELECT JSON_CONTAINS('{"foo": "bar", "aaa": 5}','"bar"', '$.foo'); ## [JSON_CONTAINS_PATH()](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains-path) -`JSON_CONTAINS_PATH(json_doc,all_or_one,path [,path, ...])` 函数返回 `0` 或 `1`,表示 JSON 文档是否包含指定路径下的数据。 +`JSON_CONTAINS_PATH(json_doc, all_or_one, path [,path, ...])` 函数返回 `0` 或 `1` 来指示 JSON 文档在给定路径或多个路径上是否包含数据。 示例: -下面的示例文档中包含 `$.foo`。 +这里文档包含 `$.foo`。 ```sql SELECT JSON_CONTAINS_PATH('{"foo": "bar", "aaa": 5}','all','$.foo'); @@ -109,7 +109,7 @@ SELECT JSON_CONTAINS_PATH('{"foo": "bar", "aaa": 5}','all','$.foo'); 1 row in set (0.00 sec) ``` -下面的示例文档中没有包含 `$.bar`。 +这里文档不包含 `$.bar`。 ```sql SELECT JSON_CONTAINS_PATH('{"foo": "bar", "aaa": 5}','all','$.bar'); @@ -124,7 +124,7 @@ SELECT JSON_CONTAINS_PATH('{"foo": "bar", "aaa": 5}','all','$.bar'); 1 row in set (0.00 sec) ``` -下面的示例文档中包含了 `$.foo` 和 `$.aaa`。 +这里文档同时包含 `$.foo` 和 `$.aaa`。 ```sql SELECT JSON_CONTAINS_PATH('{"foo": "bar", "aaa": 5}','all','$.foo', '$.aaa'); @@ -141,7 +141,7 @@ SELECT JSON_CONTAINS_PATH('{"foo": "bar", "aaa": 5}','all','$.foo', '$.aaa'); ## [JSON_EXTRACT()](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-extract) -`JSON_EXTRACT(json_doc, path[, path] ...)` 函数从 JSON 文档中提取与 `path` 参数匹配的数据。 +`JSON_EXTRACT(json_doc, path[, path] ...)` 函数从 JSON 文档中提取数据,选择由 `path` 参数匹配的文档部分。 ```sql SELECT JSON_EXTRACT('{"foo": "bar", "aaa": 5}', '$.foo'); @@ -158,7 +158,7 @@ SELECT JSON_EXTRACT('{"foo": "bar", "aaa": 5}', '$.foo'); ## [->](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_json-column-path) -`column->path` 函数返回 `column` 中与 `path` 参数匹配的数据。该函数是 [`JSON_EXTRACT()`](#json_extract) 的别名。 +`column->path` 函数返回 `column` 中匹配 `path` 参数的数据。它是 [`JSON_EXTRACT()`](#json_extract) 的别名。 ```sql SELECT @@ -181,7 +181,7 @@ FROM ( ## [->>](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_json-inline-path) -`column->>path` 函数去掉 `column` 中与 `path` 参数匹配的数据的引号。它是 `JSON_UNQUOTE(JSON_EXTRACT(doc,path_literal))` 的别名。 +`column->>path` 函数对 `column` 中匹配 `path` 参数的数据进行去引号处理。它是 `JSON_UNQUOTE(JSON_EXTRACT(doc, path_literal))` 的别名。 ```sql SELECT @@ -206,11 +206,11 @@ FROM ( ## [JSON_KEYS()](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-keys) -`JSON_KEYS(json_doc [,path])` 函数以 JSON 数组的形式返回 JSON 对象的顶层键 (key)。如果指定了 `path` 参数,则返回所选路径的顶层键 (key)。 +`JSON_KEYS(json_doc [,path])` 函数以 JSON 数组的形式返回 JSON 对象的顶层键。如果提供了 `path` 参数,它将返回所选路径中的顶层键。 示例: -下面示例返回了 JSON 文档中的两个顶层键。 +以下示例返回 JSON 文档中的两个顶层键。 ```sql SELECT JSON_KEYS('{"name": {"first": "John", "last": "Doe"}, "type": "Person"}'); @@ -225,7 +225,7 @@ SELECT JSON_KEYS('{"name": {"first": "John", "last": "Doe"}, "type": "Person"}') 1 row in set (0.00 sec) ``` -下面示例返回了 JSON 文档的 `$.name` 路径中的顶层键。 +以下示例返回 JSON 文档中 `$.name` 路径下的顶层键。 ```sql SELECT JSON_KEYS('{"name": {"first": "John", "last": "Doe"}, "type": "Person"}', '$.name'); @@ -242,11 +242,11 @@ SELECT JSON_KEYS('{"name": {"first": "John", "last": "Doe"}, "type": "Person"}', ## [JSON_SEARCH()](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-search) -`JSON_SEARCH(json_doc,one_or_all,str)` 函数会在 JSON 文档中搜索与字符串匹配的一个或所有的匹配项。 +`JSON_SEARCH(json_doc, one_or_all, str)` 函数在 JSON 文档中搜索一个或所有匹配的字符串。 示例: -在下面的示例中,搜索 `cc` 的第一个结果,它在 `a` 数组中索引为 2 的位置。 +在以下示例中,你可以搜索 `cc` 的第一个结果,它位于 `a` 数组的索引 2 位置。 ```sql SELECT JSON_SEARCH('{"a": ["aa", "bb", "cc"], "b": ["cc", "dd"]}','one','cc'); @@ -261,9 +261,9 @@ SELECT JSON_SEARCH('{"a": ["aa", "bb", "cc"], "b": ["cc", "dd"]}','one','cc'); 1 row in set (0.00 sec) ``` -现在执行和上个示例类似的操作,但将 `one_or_all` 设置为 `all`。这将获取全部搜索结果,而不仅仅是第一个结果。 +现在你执行相同的操作,但将 `one_or_all` 设置为 `all` 以获取不仅是第一个结果,而是所有结果。 -```json +```sql SELECT JSON_SEARCH('{"a": ["aa", "bb", "cc"], "b": ["cc", "dd"]}','all','cc'); ``` @@ -278,83 +278,82 @@ SELECT JSON_SEARCH('{"a": ["aa", "bb", "cc"], "b": ["cc", "dd"]}','all','cc'); ## [MEMBER OF()](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of) -`str MEMBER OF (json_array)` 函数测试传入的 `str` 值是否是 `json_array` 的元素,如果是则返回 `1`,否则返回 `0`。如果任一参数为 `NULL`,则返回 `NULL`。 +`str MEMBER OF (json_array)` 函数测试传入的值 `str` 是否是 `json_array` 的元素,如果是则返回 `1`。否则返回 `0`。如果任何参数为 `NULL`,则返回 `NULL`。 ``` -SELECT '🍍' MEMBER OF ('["🍍","🥥","🥭"]') AS 'Contains pineapple'; +SELECT '🍍' MEMBER OF ('["🍍","🥥","🥭"]') AS '包含菠萝'; ``` ``` -+--------------------+ -| Contains pineapple | -+--------------------+ -| 1 | -+--------------------+ ++----------+ +| 包含菠萝 | ++----------+ +| 1 | ++----------+ 1 row in set (0.00 sec) - ``` ## [JSON_OVERLAPS()](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-overlaps) -`JSON_OVERLAPS(json_doc, json_doc)` 函数检查两个 JSON 文档是否有重叠部分。如果有重叠,则返回 `1`,如果没有重叠,则返回 `0`。如果任一参数为 `NULL`,则返回 `NULL`。 +`JSON_OVERLAPS(json_doc, json_doc)` 函数指示两个 JSON 文档是否有重叠部分。如果有,返回 `1`。如果没有,返回 `0`。如果任何参数为 `NULL`,则返回 `NULL`。 示例: -下面的示例显示没有重叠,因为数组值的元素数量不一样。 +以下示例显示没有重叠,因为数组值的元素数量不同。 ```sql SELECT JSON_OVERLAPS( '{"languages": ["Go","Rust","C#"]}', '{"languages": ["Go","Rust"]}' -) AS 'Overlaps'; +) AS '重叠'; ``` ``` -+----------+ -| Overlaps | -+----------+ -| 0 | -+----------+ ++--------+ +| 重叠 | ++--------+ +| 0 | ++--------+ 1 row in set (0.00 sec) ``` -下面的示例显示两个 JSON 文档重叠,因为它们完全相同。 +以下示例显示两个 JSON 文档重叠,因为它们完全相同。 ```sql SELECT JSON_OVERLAPS( '{"languages": ["Go","Rust","C#"]}', '{"languages": ["Go","Rust","C#"]}' -) AS 'Overlaps'; +) AS '重叠'; ``` ``` -+----------+ -| Overlaps | -+----------+ -| 1 | -+----------+ ++--------+ +| 重叠 | ++--------+ +| 1 | ++--------+ 1 row in set (0.00 sec) ``` -下面的示例显示存在重叠,而第二个文件有一个额外的属性。 +以下示例显示存在重叠,虽然第二个文档有一个额外的属性。 ```sql SELECT JSON_OVERLAPS( '{"languages": ["Go","Rust","C#"]}', '{"languages": ["Go","Rust","C#"], "arch": ["arm64"]}' -) AS 'Overlaps'; +) AS '重叠'; ``` ``` -+----------+ -| Overlaps | -+----------+ -| 1 | -+----------+ ++--------+ +| 重叠 | ++--------+ +| 1 | ++--------+ 1 row in set (0.00 sec) ``` ## 另请参阅 -- [JSON 函数](/functions-and-operators/json-functions.md) -- [JSON 数据类型](/data-type-json.md) \ No newline at end of file +- [JSON 函数概览](/functions-and-operators/json-functions.md) +- [JSON 数据类型](/data-type-json.md) diff --git a/functions-and-operators/json-functions/json-functions-utility.md b/functions-and-operators/json-functions/json-functions-utility.md index 3c60681b006f..b1c2193ffb96 100644 --- a/functions-and-operators/json-functions/json-functions-utility.md +++ b/functions-and-operators/json-functions/json-functions-utility.md @@ -1,15 +1,15 @@ --- -title: JSON 效用函数 -summary: 了解 JSON 效用函数。 +title: JSON 实用函数 +summary: 了解 JSON 实用函数。 --- -# JSON 效用函数 +# JSON 实用函数 -本文档介绍 JSON 效用函数。 +本文档描述了 JSON 实用函数。 ## [JSON_PRETTY()](https://dev.mysql.com/doc/refman/8.0/en/json-utility-functions.html#function_json-pretty) -`JSON_PRETTY(json_doc)` 函数用于格式化 JSON 文档。 +`JSON_PRETTY(json_doc)` 函数对 JSON 文档进行美化格式化。 ```sql SELECT JSON_PRETTY('{"person":{"name":{"first":"John","last":"Doe"},"age":23}}')\G @@ -31,11 +31,11 @@ JSON_PRETTY('{"person":{"name":{"first":"John","last":"Doe"},"age":23}}'): { ## [JSON_STORAGE_FREE()](https://dev.mysql.com/doc/refman/8.0/en/json-utility-functions.html#function_json-storage-free) -`JSON_STORAGE_FREE(json_doc)` 函数返回 JSON 值在原地更新操作后释放了多少存储空间,以二进制表示。 +`JSON_STORAGE_FREE(json_doc)` 函数返回 JSON 值在原地更新后其二进制表示中释放的存储空间大小。 > **注意:** > -> 由于 TiDB 的存储架构与 MySQL 不同,因此对于有效的 JSON 值,该函数总是返回 `0`,而且它的实现是为了[与 MySQL 8.0 兼容](/mysql-compatibility.md)。请注意,TiDB 不能进行原地更新。更多信息,请参阅 [RocksDB 的空间占用](/storage-engine/rocksdb-overview.md#rocksdb-的空间占用)。 +> 由于 TiDB 的存储架构与 MySQL 不同,此函数对于有效的 JSON 值始终返回 `0`,它的实现是为了[与 MySQL 8.0 兼容](/mysql-compatibility.md)。请注意,TiDB 不进行原地更新。更多信息,请参见 [RocksDB 空间使用](/storage-engine/rocksdb-overview.md#rocksdb-space-usage)。 ```sql SELECT JSON_STORAGE_FREE('{}'); @@ -52,7 +52,7 @@ SELECT JSON_STORAGE_FREE('{}'); ## [JSON_STORAGE_SIZE()](https://dev.mysql.com/doc/refman/8.0/en/json-utility-functions.html#function_json-storage-size) -`JSON_STORAGE_SIZE(json_doc)` 函数返回存储 JSON 值所需的大致字节数。由于计算该大小时不考虑 TiKV 对数据的压缩,因此该函数的输出与 MySQL 并不完全兼容。 +`JSON_STORAGE_SIZE(json_doc)` 函数返回存储 JSON 值所需的大致字节数。由于此大小没有考虑 TiKV 使用压缩的情况,因此该函数的输出与 MySQL 并不严格兼容。 ```sql SELECT JSON_STORAGE_SIZE('{}'); @@ -69,5 +69,5 @@ SELECT JSON_STORAGE_SIZE('{}'); ## 另请参阅 -- [JSON 函数](/functions-and-operators/json-functions.md) -- [JSON 数据类型](/data-type-json.md) \ No newline at end of file +- [JSON 函数概览](/functions-and-operators/json-functions.md) +- [JSON 数据类型](/data-type-json.md) diff --git a/functions-and-operators/locking-functions.md b/functions-and-operators/locking-functions.md index 530fb01ff94e..5ec19981bb4c 100644 --- a/functions-and-operators/locking-functions.md +++ b/functions-and-operators/locking-functions.md @@ -1,25 +1,25 @@ --- -title: 锁函数 -summary: 了解 TiDB 中的用户级锁函数。 +title: 锁定函数 +summary: 了解 TiDB 中的用户级锁定函数。 --- -# 锁函数 +# 锁定函数 -TiDB 支持 MySQL 8.0 中的大部分用户级[锁函数](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html)。 +TiDB 支持 MySQL 8.0 中提供的大多数用户级[锁定函数](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html)。 ## 支持的函数 -| 函数名 | 功能描述 | +| 名称 | 描述 | |:---------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------| -| [`GET_LOCK(lockName, timeout)`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_get-lock) | 获取咨询锁。`lockName` 参数不得超过 64 个字符。在超时前,TiDB 最长等待 `timeout` 秒并返回失败。 | +| [`GET_LOCK(lockName, timeout)`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_get-lock) | 获取一个建议性锁。`lockName` 参数不能超过 64 个字符。在超时并返回失败之前最多等待 `timeout` 秒。 | | [`IS_FREE_LOCK(lockName)`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_is-free-lock) | 检查锁是否空闲。 | -| [`IS_USED_LOCK(lockName)`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_is-used-lock) | 检查锁是否正在使用。如果正在使用,则返回相应的连接 ID。 | -| [`RELEASE_LOCK(lockName)`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-lock) | 释放先前获取的锁。`lockName` 参数不得超过 64 个字符。 | -| [`RELEASE_ALL_LOCKS()`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks) | 释放当前会话持有的所有锁。 | +| [`IS_USED_LOCK(lockName)`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_is-used-lock) | 检查锁是否正在使用。如果是,则返回相应的连接 ID。 | +| [`RELEASE_ALL_LOCKS()`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks) | 释放当前会话持有的所有锁。 | +| [`RELEASE_LOCK(lockName)`](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-lock) | 释放先前获取的锁。`lockName` 参数不能超过 64 个字符。 | ## MySQL 兼容性 -* TiDB 允许的最短超时时间为 1 秒,最长超时时间为 1 小时(即 3600 秒)。而 MySQL 允许最短 0 秒和最长无限超时(`timeout=-1`)。TiDB 会自动将超出范围的值转换为最接近的允许值,`timeout=-1` 会被转换为 3600 秒。 -* TiDB 不会自动检测用户级锁导致的死锁。死锁会话将在 1 小时内超时,但你也可以在任一受影响的会话上使用 [`KILL`](/sql-statements/sql-statement-kill.md) 语句手动终止死锁。你还可以通过始终用相同顺序获取用户级锁的方法来防止死锁。 -* 在 TiDB 中,锁对集群中所有 TiDB 服务器生效。而在 MySQL Cluster 和 Group Replication 中,锁只对本地单个服务器生效。 -* 如果从另一个会话调用 `IS_USED_LOCK()` 并且无法返回持有锁的进程 ID,则返回 `1`。 +* TiDB 允许的最小超时时间是 1 秒,最大超时时间是 1 小时(3600 秒)。这与 MySQL 不同,MySQL 允许 0 秒和无限超时(`timeout=-1`)。TiDB 会自动将超出范围的值转换为最接近的允许值,并将 `timeout=-1` 转换为 3600 秒。 +* TiDB 不会自动检测用户级锁导致的死锁。死锁的会话将在最多 1 小时后超时,但也可以通过对受影响的会话之一使用 [`KILL`](/sql-statements/sql-statement-kill.md) 来手动解决。你也可以通过始终按相同顺序获取用户级锁来防止死锁。 +* 锁在集群中的所有 TiDB 服务器上生效。这与 MySQL Cluster 和 Group Replication 不同,后者的锁仅在单个服务器上本地生效。 +* 如果从另一个会话调用 `IS_USED_LOCK()`,且无法返回持有锁的进程 ID,则返回 `1`。 diff --git a/functions-and-operators/miscellaneous-functions.md b/functions-and-operators/miscellaneous-functions.md index 17e3a7130b2f..0ca3c46d0799 100644 --- a/functions-and-operators/miscellaneous-functions.md +++ b/functions-and-operators/miscellaneous-functions.md @@ -1,38 +1,38 @@ --- title: 其他函数 -summary: TiDB 支持使用 MySQL 8.0 中提供的大部分其他函数。 +summary: 了解 TiDB 中的其他函数。 --- # 其他函数 -TiDB 支持使用 MySQL 8.0 中提供的大部分[其他函数](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html)。 +TiDB 支持 MySQL 8.0 中提供的大多数[其他函数](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html)。 ## 支持的函数 -| 函数名 | 功能描述 | -|:------------|:-------------------------------------------------------------------------------| -| [`ANY_VALUE()`](#any_value) | 在 `ONLY_FULL_GROUP_BY` 模式下,防止带有 `GROUP BY` 的语句报错 | -| [`BIN_TO_UUID()`](#bin_to_uuid) | 将通用唯一识别码 (UUID) 从二进制格式转换为文本格式 | -| [`DEFAULT()`](#default) | 返回表的某一列的默认值 | +| 名称 | 描述 | +|:------------|:-----------------------------------------------------------------------------------------------| +| [`ANY_VALUE()`](#any_value) | 抑制 `ONLY_FULL_GROUP_BY` 值拒绝 | +| [`BIN_TO_UUID()`](#bin_to_uuid) | 将 UUID 从二进制格式转换为文本格式 | +| [`DEFAULT()`](#default) | 返回表列的默认值 | | [`GROUPING()`](#grouping) | `GROUP BY` 操作的修饰符 | -| [`INET_ATON()`](#inet_aton) | 将 IP 地址转换为数值 | -| [`INET_NTOA()`](#inet_ntoa) | 将数值转换为 IP 地址 | -| [`INET6_ATON()`](#inet6_aton) | 将 IPv6 地址转换为数值 | -| [`INET6_NTOA()`](#inet6_ntoa) | 将数值转换为 IPv6 地址 | +| [`INET_ATON()`](#inet_aton) | 返回 IP 地址的数值 | +| [`INET_NTOA()`](#inet_ntoa) | 从数值返回 IP 地址 | +| [`INET6_ATON()`](#inet6_aton) | 返回 IPv6 地址的数值 | +| [`INET6_NTOA()`](#inet6_ntoa) | 从数值返回 IPv6 地址 | | [`IS_IPV4()`](#is_ipv4) | 判断参数是否为 IPv4 地址 | -| [`IS_IPV4_COMPAT()`](#is_ipv4_compat) | 判断参数是否为兼容 IPv4 的地址 | -| [`IS_IPV4_MAPPED()`](#is_ipv4_mapped) | 判断参数是否为 IPv4 映射的地址 | +| [`IS_IPV4_COMPAT()`](#is_ipv4_compat) | 判断参数是否为 IPv4 兼容地址 | +| [`IS_IPV4_MAPPED()`](#is_ipv4_mapped) | 判断参数是否为 IPv4 映射地址 | | [`IS_IPV6()`](#is_ipv6) | 判断参数是否为 IPv6 地址 | | [`IS_UUID()`](#is_uuid) | 判断参数是否为 UUID | -| [`NAME_CONST()`](#name_const) | 可以用于重命名列名 | -| [`SLEEP()`](#sleep) | 让语句暂停执行几秒时间 | -| [`UUID()`](#uuid) | 返回一个通用唯一识别码 (UUID) | +| [`NAME_CONST()`](#name_const) | 可用于重命名列名 | +| [`SLEEP()`](#sleep) | 休眠指定的秒数。注意,对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群,`SLEEP()` 函数有一个限制,即最大休眠时间只能支持 300 秒。 | +| [`UUID()`](#uuid) | 返回通用唯一标识符 (UUID) | | [`UUID_TO_BIN()`](#uuid_to_bin) | 将 UUID 从文本格式转换为二进制格式 | -| [`VALUES()`](#values) | 定义 `INSERT` 语句使用的值 | +| [`VALUES()`](#values) | 定义在 INSERT 期间要使用的值 | ### ANY_VALUE() -`ANY_VALUE()` 函数可以从一组值中返回其中任意一个值。通常,该函数用于需要在 `SELECT` 语句中包含非聚合列以及 `GROUP BY` 子句的场景中。 +`ANY_VALUE()` 函数从一组值中返回任意一个值。通常,它用在需要在 `SELECT` 语句中包含非聚合列和 `GROUP BY` 子句的场景中。 ```sql CREATE TABLE fruits (id INT PRIMARY KEY, name VARCHAR(255)); @@ -57,14 +57,14 @@ SELECT ANY_VALUE(id),GROUP_CONCAT(id),name FROM fruits GROUP BY name; 4 rows in set (0.00 sec) ``` -在以上示例中,执行了第一条 `SELECT` 语句后,TiDB 返回了一条错误,这是因为 `id` 列是非聚合列且未包含在 `GROUP BY` 子句中。为了解决此问题,第二个 `SELECT` 查询使用了 `ANY_VALUE()` 从每个组中获取任意值,并使用了 `GROUP_CONCAT()` 将每个组中 `id` 列的所有值拼接成一个字符串。通过这种方法,你可以获取每个组中的一个值以及该组的所有值,而无需改变非聚合列的 SQL 模式。 +在上述示例中,第一个 `SELECT` 语句返回错误,因为 `id` 列是非聚合的且未包含在 `GROUP BY` 子句中。为解决此问题,第二个 `SELECT` 查询使用 `ANY_VALUE()` 从每个组中获取任意值,并使用 `GROUP_CONCAT()` 将每个组内 `id` 列的所有值连接成单个字符串。这种方法使您能够在不更改非聚合列的 SQL 模式的情况下,获取每个组的一个值和该组的所有值。 ### BIN_TO_UUID() -`BIN_TO_UUID()` 和 `UUID_TO_BIN()` 用于在文本格式 UUID 和二进制格式 UUID 之间进行转换。这两个函数都可以接受两个参数。 +`BIN_TO_UUID()` 和 `UUID_TO_BIN()` 可用于在文本格式 UUID 和二进制格式之间进行转换。这两个函数都接受两个参数。 -- 第一个参数用于指定要转换的值。 -- 第二个参数(可选)用于控制二进制格式中字段的排序。 +- 第一个参数指定要转换的值。 +- 第二个参数(可选)控制二进制格式中字段的排序。 ```sql SET @a := UUID(); @@ -137,7 +137,7 @@ TABLE t1; 1 row in set (0.00 sec) ``` -在以上示例中,`UPDATE` 语句将 `c1` 列的值设置为列的默认值(即 `5`)加 `3`,从而得到一个新值 `8`。 +在上述示例中,`UPDATE` 语句将 `c1` 列的值设置为该列的默认值(即 `5`)加 `3`,得到新值 `8`。 ### GROUPING() @@ -145,7 +145,7 @@ TABLE t1; ### INET_ATON() -`INET_ATON()` 函数用于将点分十进制形式表示的 IPv4 地址转换为可有效存储的二进制形式。 +`INET_ATON()` 函数将点分四段表示法的 IPv4 地址转换为可以高效存储的二进制版本。 ```sql SELECT INET_ATON('127.0.0.1'); @@ -162,7 +162,7 @@ SELECT INET_ATON('127.0.0.1'); ### INET_NTOA() -`INET_NTOA()` 函数用于将二进制 IPv4 地址转换为点分十进制表示形式。 +`INET_NTOA()` 函数将二进制 IPv4 地址转换为点分四段表示法。 ```sql SELECT INET_NTOA(2130706433); @@ -179,7 +179,7 @@ SELECT INET_NTOA(2130706433); ### INET6_ATON() -`INET6_ATON()` 函数的功能类似于 [`INET_ATON()`](#inet_aton),但 `INET6_ATON()` 还可以处理 IPv6 地址。 +`INET6_ATON()` 函数类似于 [`INET_ATON()`](#inet_aton),但 `INET6_ATON()` 也可以处理 IPv6 地址。 ```sql SELECT INET6_ATON('::1'); @@ -196,7 +196,7 @@ SELECT INET6_ATON('::1'); ### INET6_NTOA() -`INET6_NTOA()` 函数的功能类似于 [`INET_NTOA()`](#inet_ntoa),但 `INET6_NTOA()` 还可以处理 IPv6 地址。 +`INET6_NTOA()` 函数类似于 [`INET_NTOA()`](#inet_ntoa),但 `INET6_NTOA()` 也可以处理 IPv6 地址。 ```sql SELECT INET6_NTOA(0x00000000000000000000000000000001); @@ -213,7 +213,7 @@ SELECT INET6_NTOA(0x00000000000000000000000000000001); ### IS_IPV4() -`IS_IPV4()` 函数用于判断输入的参数是否为 IPv4 地址。 +`IS_IPV4()` 函数测试给定参数是否为 IPv4 地址。 ```sql SELECT IS_IPV4('127.0.0.1'); @@ -243,7 +243,7 @@ SELECT IS_IPV4('300.0.0.1'); ### IS_IPV4_COMPAT() -`IS_IPV4_COMPAT()` 函数用于判断输入的参数是否为兼容 IPv4 的地址。 +`IS_IPV4_COMPAT()` 函数测试给定参数是否为 IPv4 兼容地址。 ```sql SELECT IS_IPV4_COMPAT(INET6_ATON('::127.0.0.1')); @@ -260,7 +260,7 @@ SELECT IS_IPV4_COMPAT(INET6_ATON('::127.0.0.1')); ### IS_IPV4_MAPPED() -`IS_IPV4_MAPPED()` 函数用于判断输入的参数是否为 IPv4 映射的地址。 +`IS_IPV4_MAPPED()` 函数测试给定参数是否为 IPv4 映射地址。 ```sql SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:127.0.0.1')); @@ -277,7 +277,7 @@ SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:127.0.0.1')); ### IS_IPV6() -`IS_IPV6()` 函数用于判断输入的参数是否为 IPv6 地址。 +`IS_IPV6()` 函数测试给定参数是否为 IPv6 地址。 ```sql SELECT IS_IPV6('::1'); @@ -294,7 +294,7 @@ SELECT IS_IPV6('::1'); ### IS_UUID() -`IS_UUID()` 函数用于判断输入的参数是否为 [UUID](/best-practices/uuid.md)。 +`IS_UUID()` 函数测试给定参数是否为 [UUID](/best-practices/uuid.md)。 ```sql SELECT IS_UUID('eb48c08c-eb71-11ee-bacf-5405db7aad56'); @@ -311,7 +311,7 @@ SELECT IS_UUID('eb48c08c-eb71-11ee-bacf-5405db7aad56'); ### NAME_CONST() -函数 `NAME_CONST()` 用于命名列。建议使用列别名功能代替。 +`NAME_CONST()` 函数用于命名列。建议使用列别名代替。 ```sql SELECT NAME_CONST('column name', 'value') UNION ALL SELECT 'another value'; @@ -327,7 +327,7 @@ SELECT NAME_CONST('column name', 'value') UNION ALL SELECT 'another value'; 2 rows in set (0.00 sec) ``` -上面这条语句使用了 `NAME_CONST()`,下面这条语句使用了列别名的方式(推荐)。 +上述语句使用 `NAME_CONST()`,而下面的语句使用推荐的列别名方式。 ```sql SELECT 'value' AS 'column name' UNION ALL SELECT 'another value'; @@ -345,7 +345,7 @@ SELECT 'value' AS 'column name' UNION ALL SELECT 'another value'; ### SLEEP() -`SLEEP()` 函数用于将查询暂停执行几秒。 +`SLEEP()` 函数用于暂停查询执行指定的秒数。 ```sql SELECT SLEEP(1.5); @@ -362,7 +362,7 @@ SELECT SLEEP(1.5); ### UUID() -`UUID()` 函数用于返回通用唯一标识符 (UUID) version 1。UUID 的定义可参考 [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122)。 +`UUID()` 函数返回一个符合 [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) 定义的版本 1 通用唯一标识符 (UUID)。 ```sql SELECT UUID(); @@ -414,6 +414,6 @@ TABLE t1; ## 不支持的函数 -| 函数名 | 功能描述 | -|:------|:-----------| -| [`UUID_SHORT()`](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_uuid-short) | 基于特定假设提供唯一的 UUID,目前这些假设在 TiDB 中不存在,详见 [TiDB #4620](https://github.com/pingcap/tidb/issues/4620) | +| 名称 | 描述 | +|:------------|:-----------------------------------------------------------------------------------------------| +| [`UUID_SHORT()`](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_uuid-short) | 提供在 TiDB 中不存在的某些假设条件下唯一的 UUID [TiDB #4620](https://github.com/pingcap/tidb/issues/4620) | diff --git a/functions-and-operators/numeric-functions-and-operators.md b/functions-and-operators/numeric-functions-and-operators.md index 2e209ad56030..5daa37bf410e 100644 --- a/functions-and-operators/numeric-functions-and-operators.md +++ b/functions-and-operators/numeric-functions-and-operators.md @@ -1,59 +1,59 @@ --- -title: 数值函数与操作符 -summary: TiDB 支持 MySQL 8.0 中的所有数值函数和操作符。 +title: 数值函数和运算符 +summary: 了解数值函数和运算符。 --- -# 数值函数与操作符 +# 数值函数和运算符 -TiDB 支持使用 MySQL 8.0 中提供的所有[数值函数与操作符](https://dev.mysql.com/doc/refman/8.0/en/numeric-functions.html)。 +TiDB 支持 MySQL 8.0 中提供的所有[数值函数和运算符](https://dev.mysql.com/doc/refman/8.0/en/numeric-functions.html)。 -## 算术操作符 +## 算术运算符 -| 操作符名 | 功能描述 | -|:-------------|:--------------------------------| -| [`+`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | 加号 | -| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | 减号 | -| [`*`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_times) | 乘号 | -| [`/`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_divide) | 除号 | +| 名称 | 描述 | +|:----------------------------------------------------------------------------------------------|:----------------------------------| +| [`+`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | 加法运算符 | +| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | 减法运算符 | +| [`*`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_times) | 乘法运算符 | +| [`/`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_divide) | 除法运算符 | | [`DIV`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_div) | 整数除法 | -| [`%`, `MOD`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_mod) | 模运算,取余 | -| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_unary-minus) | 更改参数符号 | +| [`%`, `MOD`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_mod) | 取模运算符 | +| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_unary-minus) | 改变参数的符号 | ## 数学函数 -| 函数名 | 功能描述 | +| 名称 | 描述 | |:----------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------| -| [`ABS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_abs) | 返回参数的绝对值 | -| [`ACOS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_acos) | 返回参数的反余弦值 | -| [`ASIN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_asin) | 返回参数的反正弦值 | -| [`ATAN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan) | 返回参数的反正切值 | -| [`ATAN2(), ATAN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan2) | 返回两个参数的反正切值 | -| [`CEIL()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceil) | 返回不小于参数的最小整数值 | -| [`CEILING()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceiling) | 返回不小于参数的最小整数值 | -| [`CONV()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_conv) | 不同数基间转换数字,返回数字的字符串表示 | -| [`COS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cos) | 返回参数的余弦值 | -| [`COT()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cot) | 返回参数的余切值 | -| [`CRC32()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_crc32) | 计算循环冗余码校验值并返回一个 32 位无符号值 | -| [`DEGREES()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_degrees) | 返回由弧度转化为度的参数 | -| [`EXP()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_exp) | 返回 e(自然对数的底)的指定乘方后的值 | +| [`ABS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_abs) | 返回绝对值 | +| [`ACOS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_acos) | 返回反余弦值 | +| [`ASIN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_asin) | 返回反正弦值 | +| [`ATAN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan) | 返回反正切值 | +| [`ATAN2(), ATAN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_atan2) | 返回两个参数的反正切值 | +| [`CEIL()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceil) | 返回不小于参数的最小整数值 | +| [`CEILING()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ceiling) | 返回不小于参数的最小整数值 | +| [`CONV()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_conv) | 在不同进制之间转换数字 | +| [`COS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cos) | 返回余弦值 | +| [`COT()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_cot) | 返回余切值 | +| [`CRC32()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_crc32) | 计算循环冗余校验值 | +| [`DEGREES()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_degrees) | 将弧度转换为角度 | +| [`EXP()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_exp) | 返回 e 的幂 | | [`FLOOR()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_floor) | 返回不大于参数的最大整数值 | -| [`LN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ln) | 返回参数的自然对数 | +| [`LN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_ln) | 返回参数的自然对数 | | [`LOG()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log) | 返回第一个参数的自然对数 | -| [`LOG10()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log10) | 返回参数以 10 为底的对数 | -| [`LOG2()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log2) | 返回参数以 2 为底的对数 | +| [`LOG10()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log10) | 返回参数的以 10 为底的对数 | +| [`LOG2()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_log2) | 返回参数的以 2 为底的对数 | | [`MOD()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_mod) | 返回余数 | -| [`PI()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pi) | 返回 pi 的值 | -| [`POW()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pow) | 返回参数的指定乘方的结果值 | -| [`POWER()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_power) | 返回参数的指定乘方的结果值 | -| [`RADIANS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_radians) | 返回由度转化为弧度的参数 | -| [`RAND()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_rand) | 返回一个随机浮点值 | -| [`ROUND()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_round) | 返回参数最近似的整数或指定小数位数的数值 | -| [`SIGN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sign) | 返回参数的符号 | -| [`SIN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sin) | 返回参数的正弦值 | -| [`SQRT()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sqrt) | 返回非负数的二次方根 | -| [`TAN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_tan) | 返回参数的正切值 | -| [`TRUNCATE()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_truncate) | 返回被舍位至指定小数位数的数字 | +| [`PI()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pi) | 返回圆周率值 | +| [`POW()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_pow) | 返回参数的指定次幂 | +| [`POWER()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_power) | 返回参数的指定次幂 | +| [`RADIANS()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_radians) | 将参数转换为弧度 | +| [`RAND()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_rand) | 返回随机浮点值 | +| [`ROUND()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_round) | 对参数进行四舍五入 | +| [`SIGN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sign) | 返回参数的符号 | +| [`SIN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sin) | 返回参数的正弦值 | +| [`SQRT()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_sqrt) | 返回参数的平方根 | +| [`TAN()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_tan) | 返回参数的正切值 | +| [`TRUNCATE()`](https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_truncate) | 截断到指定的小数位数 | ## 相关系统变量 -通过 [`div_precision_increment`](/system-variables.md#div_precision_increment-从-v800-版本开始引入) 可以设置 `/` 运算符的精度。 +[`div_precision_increment`](/system-variables.md#div_precision_increment-new-in-v800) 用于设置 `/` 运算符的精度。 diff --git a/functions-and-operators/operators.md b/functions-and-operators/operators.md index 9505b51e72a9..a8d032d39985 100644 --- a/functions-and-operators/operators.md +++ b/functions-and-operators/operators.md @@ -1,134 +1,143 @@ --- -title: 操作符 -summary: 操作符是用于在 MySQL 中执行各种操作的关键元素。它们包括逻辑操作符(如 AND、OR、NOT、XOR)、赋值操作符(如 =、:=)、比较操作符(如 =、<、>、LIKE、BETWEEN)、以及其他操作符(如 +、-、*、/)。操作符具有不同的优先级,可以用于执行各种复杂的操作。需要注意的是,MySQL 不支持 ILIKE 操作符。 +title: 运算符 +summary: 了解运算符优先级、比较函数和运算符、逻辑运算符以及赋值运算符。 --- -# 操作符 - -| 操作符名 | 功能描述 | -| ------- | -------------------------------- | -| [`AND`, &&](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_and) | 逻辑与 | -| [`=`](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-equal) | 赋值(可用于 [`SET`](https://dev.mysql.com/doc/refman/8.0/en/set-variable.html) 语句中,或用于 [`UPDATE`](https://dev.mysql.com/doc/refman/8.0/en/update.html) 语句的 `SET` 中) | -| [`:=`](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-value) | 赋值 | -| [`BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | 判断值满足范围 | -| [`BINARY`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#operator_binary) | 将一个字符串转换为一个二进制字符串 | -| [&](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-and) | 位与 | -| [~](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-invert) | 位非 | -| [\|](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-or) | 位或 | -| [`^`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-xor) | 按位异或 | -| [`CASE`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) | case 操作符 | -| [`DIV`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_div) | 整数除 | -| [`/`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_divide) | 除法 | -| [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | 相等比较 | -| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | 空值安全型相等比较 | -| [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | 大于 | -| [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | 大于或等于 | -| [`IS`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is) | 判断一个值是否等于一个布尔值 | -| [`IS NOT`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not) | 判断一个值是否不等于一个布尔值 | -| [`IS NOT NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not-null) | 非空判断 | -| [`IS NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | 空值判断 | -| [`<<`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_left-shift) | 左移 | -| [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | 小于 | -| [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | 小于或等于 | -| [`LIKE`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like) | 简单模式匹配 | -| [`ILIKE`](https://www.postgresql.org/docs/current/functions-matching.html) | 大小写不敏感的简单模式匹配(TiDB 支持但 MySQL 不支持) | -| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | 减 | -| [`%`, `MOD`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_mod) | 求余 | -| [`NOT`, `!`](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_not) | 取反 | -| [`NOT BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | 判断值是否不在范围内 | -| [`!=`, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | 不等于 | -| [`NOT LIKE`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like) | 不符合简单模式匹配 | -| [`NOT REGEXP`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_not-regexp) | 不符合正则表达式模式匹配 | -| [\|\|, `OR`](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_or) | 逻辑或 | -| [`+`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | 加 | -| [`REGEXP`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp) | 使用正则表达式进行模式匹配 | -| [`>>`](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_right-shift) | 右移 | -| [`RLIKE`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp) | REGEXP 同义词 | -| [`*`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_times) | 乘 | -| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_unary-minus) | 取反符号 | -| [`XOR`](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_xor) | 逻辑亦或 | - -## 不支持的操作符 +# 运算符 + +本文档描述运算符优先级、比较函数和运算符、逻辑运算符以及赋值运算符。 + +- [运算符优先级](#运算符优先级) +- [比较函数和运算符](#比较函数和运算符) +- [逻辑运算符](#逻辑运算符) +- [赋值运算符](#赋值运算符) + +| 名称 | 描述 | +| ---------------------------------------- | ---------------------------------------- | +| [AND, &&](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_and) | 逻辑与 | +| [=](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-equal) | 赋值(作为 [`SET`](https://dev.mysql.com/doc/refman/8.0/en/set-variable.html) 语句的一部分,或作为 [`UPDATE`](https://dev.mysql.com/doc/refman/8.0/en/update.html) 语句中 `SET` 子句的一部分) | +| [:=](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-value) | 赋值 | +| [BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | 检查值是否在某个范围内 | +| [BINARY](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#operator_binary) | 将字符串转换为二进制字符串 | +| [&](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-and) | 按位与 | +| [~](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-invert) | 按位取反 | +| [\|](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-or) | 按位或 | +| [^](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_bitwise-xor) | 按位异或 | +| [CASE](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) | Case 运算符 | +| [DIV](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_div) | 整数除法 | +| [/](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_divide) | 除法运算符 | +| [=](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | 等于运算符 | +| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | NULL 安全的等于运算符 | +| [>](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | 大于运算符 | +| [>=](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | 大于等于运算符 | +| [IS](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is) | 测试值是否为布尔值 | +| [IS NOT](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not) | 测试值是否为布尔值 | +| [IS NOT NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not-null) | 非 NULL 值测试 | +| [IS NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | NULL 值测试 | +| [->](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_json-column-path) | 在评估路径后从 JSON 列返回值;等同于 `JSON_EXTRACT()` | +| [->>](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_json-inline-path) | 在评估路径后从 JSON 列返回值并对结果去引号;等同于 `JSON_UNQUOTE(JSON_EXTRACT())` | +| [<<](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_left-shift) | 左移 | +| [<](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | 小于运算符 | +| [<=](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | 小于等于运算符 | +| [LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like) | 简单模式匹配 | +| [ILIKE](https://www.postgresql.org/docs/current/functions-matching.html) | 不区分大小写的简单模式匹配(TiDB 支持,但 MySQL 不支持) | +| [-](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | 减法运算符 | +| [%, MOD](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_mod) | 取模运算符 | +| [NOT, !](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_not) | 取反值 | +| [NOT BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | 检查值是否不在某个范围内 | +| [!=, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | 不等于运算符 | +| [NOT LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like) | 简单模式匹配的否定 | +| [NOT REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_not-regexp) | REGEXP 的否定 | +| [\|\|, OR](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_or) | 逻辑或 | +| [+](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | 加法运算符 | +| [REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp) | 使用正则表达式的模式匹配 | +| [>>](https://dev.mysql.com/doc/refman/8.0/en/bit-functions.html#operator_right-shift) | 右移 | +| [RLIKE](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp) | REGEXP 的同义词 | +| [*](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_times) | 乘法运算符 | +| [-](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_unary-minus) | 改变参数的符号 | +| [XOR](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_xor) | 逻辑异或 | + +## 不支持的运算符 * [`SOUNDS LIKE`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#operator_sounds-like) -## 操作符优先级 +## 运算符优先级 -操作符优先级显示在以下列表中,从最高优先级到最低优先级。同一行显示的操作符具有相同的优先级。 +以下列表显示了运算符的优先级,从最高优先级到最低优先级。同一行显示的运算符具有相同的优先级。 ```sql INTERVAL -BINARY +BINARY, COLLATE ! -- (unary minus), ~ (unary bit inversion) +- (一元减号), ~ (一元按位取反) ^ *, /, DIV, %, MOD -, + <<, >> & | -= (comparison), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN += (比较), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN BETWEEN, CASE, WHEN, THEN, ELSE NOT AND, && XOR OR, || -= (assignment), := += (赋值), := ``` -详情参见[这里](https://dev.mysql.com/doc/refman/8.0/en/operator-precedence.html)。 - -## 比较方法和操作符 - -| 操作符名 | 功能描述 | -| ------- | -------------------------------- | -| [`BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | 判断值是否在范围内 | -| [`COALESCE()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce) | 返回第一个非空值 | -| [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | 相等比较 | -| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | 空值安全型相等比较 | -| [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | 大于 | -| [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | 大于或等于 | -| [`GREATEST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_greatest) | 返回最大值 | -| [`IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in) | 判断值是否在一个值的集合内 | -| [`INTERVAL()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_interval) | 返回一个小于第一个参数的参数的下标 | -| [`IS`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is) | 判断是否等于一个布尔值 | -| [`IS NOT`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not) | 判断是否不等于一个布尔值 | -| [`IS NOT NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not-null) | 非空判断 | -| [`IS NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | 空值判断 | -| [`ISNULL()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull) | 判断参数是否为空 | -| [`LEAST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_least) | 返回最小值 | -| [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | 小于 | -| [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | 小于或等于 | -| [`LIKE`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like) | 简单模式匹配 | -| [`ILIKE`](https://www.postgresql.org/docs/current/functions-matching.html) | 大小写不敏感的简单模式匹配(TiDB 支持但 MySQL 不支持) | -| [`NOT BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | 判断值是否不在范围内 | -| [`!=`, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | 不等于 | -| [`NOT IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in) | 判断值是否不在一个值的集合内 | -| [`NOT LIKE`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like) | 不满足简单模式匹配 | -| [`STRCMP()`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp) | 比较两个字符串 | - -详情参见[这里](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html)。 - -## 逻辑操作符 - -| 操作符名 | 功能描述 | -| ------- | -------------------------------- | -| [`AND`, &&](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_and) | 逻辑与 | -| [`NOT`, `!`](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_not) | 逻辑非 | -| [\|\|, `OR`](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_or) | 逻辑或 | -| [`XOR`](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_xor) | 逻辑异或 | - -详情参见[这里](https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html)。 - -## 赋值操作符 - -| 操作符名 | 功能描述 | -| ------- | -------------------------------- | -| [`=`](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-equal) | 赋值(可用于 [`SET`](https://dev.mysql.com/doc/refman/8.0/en/set-variable.html) 语句中,或用于 [`UPDATE`](https://dev.mysql.com/doc/refman/8.0/en/update.html) 语句的 `SET` 中) | -| [`:=`](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-value) | 赋值 | - -详情参见[这里](https://dev.mysql.com/doc/refman/8.0/en/group-by-functional-dependence.html)。 +详情请参见 [运算符优先级](https://dev.mysql.com/doc/refman/8.0/en/operator-precedence.html)。 + +## 比较函数和运算符 + +| 名称 | 描述 | +| ---------------------------------------- | ---------------------------------------- | +| [BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | 检查值是否在某个范围内 | +| [COALESCE()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce) | 返回第一个非 NULL 参数 | +| [=](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | 等于运算符 | +| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | NULL 安全的等于运算符 | +| [>](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | 大于运算符 | +| [>=](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | 大于等于运算符 | +| [GREATEST()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_greatest) | 返回最大的参数 | +| [IN()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in) | 检查值是否在一组值中 | +| [INTERVAL()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_interval) | 返回小于第一个参数的参数的索引 | +| [IS](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is) | 测试值是否为布尔值 | +| [IS NOT](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not) | 测试值是否为布尔值 | +| [IS NOT NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-not-null) | 非 NULL 值测试 | +| [IS NULL](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | NULL 值测试 | +| [ISNULL()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull) | 测试参数是否为 NULL | +| [LEAST()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_least) | 返回最小的参数 | +| [<](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | 小于运算符 | +| [<=](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | 小于等于运算符 | +| [LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like) | 简单模式匹配 | +| [ILIKE](https://www.postgresql.org/docs/current/functions-matching.html) | 不区分大小写的简单模式匹配(TiDB 支持,但 MySQL 不支持) | +| [NOT BETWEEN ... AND ...](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | 检查值是否不在某个范围内 | +| [!=, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | 不等于运算符 | +| [NOT IN()](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in) | 检查值是否不在一组值中 | +| [NOT LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like) | 简单模式匹配的否定 | +| [STRCMP()](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp) | 比较两个字符串 | + +详情请参见 [比较函数和运算符](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html)。 + +## 逻辑运算符 + +| 名称 | 描述 | +| ---------------------------------------- | ------------- | +| [AND, &&](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_and) | 逻辑与 | +| [NOT, !](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_not) | 取反值 | +| [\|\|, OR](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_or) | 逻辑或 | +| [XOR](https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_xor) | 逻辑异或 | + +详情请参见 [MySQL 对 GROUP BY 的处理](https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html)。 + +## 赋值运算符 + +| 名称 | 描述 | +| ---------------------------------------- | ---------------------------------------- | +| [=](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-equal) | 赋值(作为 [`SET`](https://dev.mysql.com/doc/refman/8.0/en/set-variable.html) 语句的一部分,或作为 [`UPDATE`](https://dev.mysql.com/doc/refman/8.0/en/update.html) 语句中 `SET` 子句的一部分) | +| [:=](https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-value) | 赋值 | + +详情请参见 [函数依赖性检测](https://dev.mysql.com/doc/refman/8.0/en/group-by-functional-dependence.html)。 ## MySQL 兼容性 -* MySQL 不支持 `ILIKE` 操作符。 +* MySQL 不支持 `ILIKE` 运算符。 diff --git a/functions-and-operators/precision-math.md b/functions-and-operators/precision-math.md index 2288a4357890..582c7b5f4ac9 100644 --- a/functions-and-operators/precision-math.md +++ b/functions-and-operators/precision-math.md @@ -1,45 +1,42 @@ --- -title: 精度数学 -summary: TiDB 中的精确数值运算与 MySQL 基本一致。精确数值运算包括整型和 DECIMAL 类型,以及精确值数字字面量。DECIMAL 数据类型是定点数类型,其运算是精确计算。在表达式计算中,TiDB 会尽可能不做任何修改的使用每个输入的数值。数值修约时,`round()` 函数将使用四舍五入的规则。向 DECIMAL 或整数类型列插入数据时,round 的规则将采用 round half away from zero 的方式。 +title: 精确数学 +summary: 了解 TiDB 中的精确数学。 --- -# 精度数学 +# 精确数学 -TiDB 中精度数学计算与 MySQL 中基本一致。详情请参见:[Precision Math](https://dev.mysql.com/doc/refman/8.0/en/precision-math.html) - -- 数值类型 -- DECIMAL 数据类型的特性 +TiDB 中的精确数学支持与 MySQL 一致。更多信息,请参见 [MySQL 中的精确数学](https://dev.mysql.com/doc/refman/8.0/en/precision-math.html)。 ## 数值类型 -精确数值运算的范围包括精确值数据类型(整型和 DECIMAL 类型),以及精确值数字字面量。近似值数据类型和近似值数字字面量被作为浮点数来处理。 +精确数学的作用范围包括精确值数据类型(整数和 DECIMAL 类型)和精确值数字字面量。近似值数据类型和数字字面量作为浮点数处理。 -精确值数字字面量包含整数部分或小数部分,或二者都包含。精确值数字字面量可以包含符号位。例如:`1`, `.2`, `3.4`, `-5`, `-6.78`, `+9.10`。 +精确值数字字面量具有整数部分或小数部分,或两者都有。它们可以带符号。示例:`1`、`.2`、`3.4`、`-5`、`-6.78`、`+9.10`。 -近似值数字字面量以一个包含尾数和指数的科学计数法表示(基数为 10)。其中尾数和指数可以分别或同时带有符号位。例如:`1.2E3`, `1.2E-3`, `-1.2E3`, `-1.2E-3`。 +近似值数字字面量以科学计数法(10的幂)表示,包含尾数和指数。任一部分或两部分都可以带符号。示例:`1.2E3`、`1.2E-3`、`-1.2E3`、`-1.2E-3`。 -两个看起来相似的数字可能会被以不同的方式进行处理。例如:`2.34` 是精确值(定点数),而 `2.3E0` 是近似值(浮点数)。 +看起来相似的两个数字可能会被不同对待。例如,`2.34` 是精确值(定点)数字,而 `2.34E0` 是近似值(浮点)数字。 -DECIMAL 数据类型是定点数类型,其运算是精确计算。FLOAT 和 DOUBLE 数据类型是浮点类型,其运算是近似计算。 +DECIMAL 数据类型是定点类型,计算是精确的。FLOAT 和 DOUBLE 数据类型是浮点类型,计算是近似的。 -## DECIMAL 数据类型的特性 +## DECIMAL 数据类型特征 -本节讨论 DECIMAL 数据类型的特性,主要涉及以下几点: +本节讨论 DECIMAL 数据类型(及其同义词)的以下特征: -1. 最大位数 -2. 存储格式 -3. 存储要求 +- 最大位数 +- 存储格式 +- 存储要求 -DECIMAL 列的声明语法为 DECIMAL(M, D)。其中参数值意义及其范围如下: +DECIMAL 列的声明语法是 `DECIMAL(M,D)`。参数的取值范围如下: -- M 表示最大的数字位数(精度),1<= M <= 65。 -- D 表示小数点右边数字的位数(标度)。1 <= D <= 30 且不大于 M。 +- M 是最大位数(精度)。1 <= M <= 65。 +- D 是小数点右边的位数(标度)。1 <= D <= 30,且 D 不能大于 M。 -M 的最大值 65 表示 DECIMAL 值的计算精确到 65 位数字。该精度同样适用于其精确值字面量。 +M 的最大值为 65 意味着 DECIMAL 值的计算精确到 65 位。这个 65 位精度的限制也适用于精确值数字字面量。 -DECIMAL 列的值采用二进制进行存储,其将每 9 位十进制数字包装成 4 个字节。其中整数和小数部分分别确定所需的存储空间。如果数字位数为 9 的倍数,则每 9 位十进制数字各采用 4 个字节进行存储,对于剩余不足 9 位的数字,所需的存储空间如下表所示 +DECIMAL 列的值使用二进制格式存储,将 9 个十进制数字打包到 4 个字节中。每个值的整数部分和小数部分的存储要求是分别确定的。每 9 位数字需要 4 个字节,剩余的数字需要 4 个字节的一部分。剩余数字所需的存储空间由下表给出。 -| 剩余数字位数 | 存储所需字节数 | +| 剩余位数 | 字节数 | | --- | --- | | 0 | 0 | | 1–2 | 1 | @@ -47,123 +44,91 @@ DECIMAL 列的值采用二进制进行存储,其将每 9 位十进制数字包 | 5–6 | 3 | | 7–9 | 4 | -例如: - -+ 定义类型为 DECIMAL(18, 9) 的列,其小数点两侧均各包含 9 位十进制数字。因此,分别需要 4 个字节的存储空间。 - -+ 定义类型为 DECIMAL(20, 6) 的列,其小数部分包含 6 位十进制数字,整数部分包含 14 位十进制数字。整数部分中 9 位数字需要 4 个字节进行存储,其余 5 位数字需要 3 个字节进行存储。小数部分 6 位数字需要 3 个字节进行存储。 - -DECIMAL 列不存储前导的字符 `+` 或字符 `-` 或数字 `0`。如果将 `+0003.1` 插入到 DECIMAL(5, 1) 列中,则将其存储为 `3.1`。对于负数,不存储字符 `-` 的字面值。 +例如,`DECIMAL(18,9)` 列在小数点两边各有 9 位数字,因此整数部分和小数部分各需要 4 个字节。`DECIMAL(20,6)` 列有 14 位整数和 6 位小数。整数位需要 4 个字节存储其中的 9 位数字,剩余的 5 位需要 3 个字节。6 位小数需要 3 个字节。 -DECIMAL 列不允许插入大于列定义的隐含范围的值。例如:DECIMAL(3, 0) 列范围为`-999` 到 `999`。DECIMAL(M, D) 列小数点左边部分最多支持 M-D 位数字。 +DECIMAL 列不存储前导 `+` 字符或 `-` 字符或前导 `0` 数字。如果您将 `+0003.1` 插入到 `DECIMAL(5,1)` 列中,它将被存储为 `3.1`。对于负数,不存储字面的 `-` 字符。 -有关 DECIMAL 值的内部格式完整说明,请参阅 TiDB 源码文件 [`types/mydecimal.go`](https://github.com/pingcap/tidb/blob/release-8.1/pkg/types/mydecimal.go)。 +DECIMAL 列不允许超出列定义所暗示范围的值。例如,`DECIMAL(3,0)` 列支持 `-999` 到 `999` 的范围。`DECIMAL(M,D)` 列在小数点左边最多允许 `M - D` 位数字。 -## 表达式计算 +有关 DECIMAL 值内部格式的更多信息,请参见 TiDB 源代码中的 [`mydecimal.go`](https://github.com/pingcap/tidb/blob/release-8.1/pkg/types/mydecimal.go)。 -在涉及精度数学计算的表达式中,TiDB 会尽可能不做任何修改的使用每个输入的数值。比如:在计算比较函数时,参与运算的数字将不做任何改变。在严格 SQL 模式下,向一个数据列插入一个值时,如果该值处于这一列的值域范围内,这个值将直接不做任何修改的直接插入进去,提取这个值的时候,取得的值和插入的值将会是同一个值。当处于非严格 SQL 模式时,TiDB 会允许数据插入过程中发生的数据截断。 +## 表达式处理 -处理数值类型表达式取决于这个表达式参数的具体值: +对于精确数学的表达式,TiDB 尽可能使用给定的精确值数字。例如,比较中的数字按原样使用,不改变值。在严格 SQL 模式下,如果您将精确数据类型添加到列中,如果数字在列范围内,则按其精确值插入。检索时,值与插入的值相同。如果未启用严格 SQL 模式,TiDB 允许 INSERT 时进行截断。 -* 当表达式参数中包含近似值时,这个表达式的结果也是近似值,TiDB 会使用浮点数对应的计算逻辑返回一个浮点数的结果。 -* 当表达式参数中不包含任何近似值时(也就是说表达式的参数全部是精确值),如果某个精确值包含小数部分,TIDB 会对这个表达式使用 `DECIMAL` 对应的计算逻辑,返回一个 `DECIMAL` 的结果,精确到 65 位数字。 -* 其他情况下,表达式只会包含整数参数,这个表达式的结果也是精确的,TiDB 会使用整数对应的计算逻辑返回一个整数结果,精度和 `BIGINT` 保持一致(64 位)。 +如何处理数值表达式取决于表达式的值: -如果数值类型表达式中包含字符串参数,这些字符串参数将被转换成双精度浮点数,这个表达式的计算结果将是个近似值。 +- 如果表达式包含任何近似值,结果是近似的。TiDB 使用浮点运算评估表达式。 +- 如果表达式不包含近似值,即仅包含精确值,且如果任何精确值包含小数部分,则使用 DECIMAL 精确运算评估表达式,精度为 65 位。 +- 否则,表达式仅包含整数值。表达式是精确的。TiDB 使用整数运算评估表达式,精度与 BIGINT(64 位)相同。 -向一个数值类型列插入数据的具体行为会受到 SQL 模式的影响。接下来的讨论将围绕严格模式以及 `ERROR_FOR_DIVISION_BY_ZERO` 模式展开,如果要打开所有的限制,可以简单的使用 `TRADITIONAL` 模式,这个模式将同时使用严格模式以及 `ERROR_FOR_DIVISION_BY_ZERO` 模式: +如果数值表达式包含字符串,字符串将转换为双精度浮点值,表达式的结果是近似的。 -{{< copyable "sql" >}} +插入数值列受 SQL 模式影响。以下讨论提到严格模式和 `ERROR_FOR_DIVISION_BY_ZERO`。要启用所有限制,您可以简单地使用 `TRADITIONAL` 模式,它包括严格模式值和 `ERROR_FOR_DIVISION_BY_ZERO`: ```sql -SET sql_mode = 'TRADITIONAL'; +SET sql_mode = 'TRADITIONAL`; ``` -向一个具有精确值类型(`DECIMAL` 或者整数类型)的列插入数据时,如果插入的数据位于该列的值域范围内将使用该数据的精确值。如果该数据的小数部分太长,将会发生数值修约,这时会有 warning 产生,具体内容可以看"数值修约"。 +如果将数字插入精确类型列(DECIMAL 或整数),如果它在列范围内,则按其精确值插入。对于这个数字: -如果该数据整数部分太长: +- 如果小数部分的位数过多,会进行舍入并生成警告。 +- 如果整数部分的位数过多,数值太大,处理如下: + - 如果未启用严格模式,值会截断为最接近的合法值并生成警告。 + - 如果启用严格模式,会发生溢出错误。 -* 如果没有开启严格模式,这个值会被截断并产生一个 warning。 -* 如果开启了严格模式,将会产生一个数据溢出的 error。 +要将字符串插入数值列,如果字符串包含非数字内容,TiDB 按如下方式处理从字符串到数字的转换: -如果向一个数值类型列插入字符串,如果该字符串中包含非数值部分,TiDB 将这样做类型转换: +- 在严格模式下,不以数字开头的字符串(包括空字符串)不能用作数字。会发生错误或警告。 +- 以数字开头的字符串可以转换,但会截断尾部的非数字部分。在严格模式下,如果截断的部分包含除空格以外的任何内容,会发生错误或警告。 -* 在严格模式下,没有以数字开头的字符串(即使是一个空字符串)不能被被用作数字值并会返回一个 error 或者是 warning。 -* 以数字开头的字符串可以被转换,不过末尾的非数字部分会被截断。如果被截断的部分包含的不全是空格,在严格模式下这回产生一个 error 或者 warning。 +默认情况下,除以 0 的结果为 NULL,且不会有警告。通过适当设置 SQL 模式,可以限制除以 0。如果启用 `ERROR_FOR_DIVISION_BY_ZERO` SQL 模式,TiDB 对除以 0 的处理不同: -默认情况下,如果计算的过程中发生了除数是 0 的现象将会得到一个 `NULL` 结果,并且不会有 warning 产生。通过设置适当的 SQL 模式,除以 0 的操作可以被限制。当设置 `ERROR_FOR_DIVISION_BY_ZERO` SQL 模式时,TiDB 的行为是: +- 在严格模式下,禁止插入和更新,并发生错误。 +- 如果不在严格模式下,会发生警告。 -* 如果设置了严格 SQL 模式,`INSERT` 和 `UPDATE` 的过程中如果发生了除以 0 的操作,正在进行的 `INSERT` 或者 `UPDATE` 操作会被禁止,并且会返回一个 error。 -* 如果没有设置严格 SQL 模式,除以 0 的操作仅会返回一个 warning。 - -假设我们有如下的 SQL 语句: - -{{< copyable "sql" >}} +在以下 SQL 语句中: ```sql INSERT INTO t SET i = 1/0; ``` -不同的 SQL 模式将会导致不同的结果如下: +在不同的 SQL 模式下返回以下结果: -| `sql_mode` 的值 | 结果 | +| `sql_mode` 值 | 结果 | | :--- | :--- | -| '' | 没有 warning,没有 error,i 被设为 NULL | -| strict | 没有 warning,没有 error,i 被设为 NULL | -| `ERROR_FOR_DIVISION_BY_ZERO` | 有 warning,没有 error,i 被设为 NULL | -| strict, `ERROR_FOR_DIVISION_BY_ZERO` | 有 error,插入失败 | - -## 数值修约 +| '' | 无警告,无错误;i 设置为 NULL。| +| strict | 无警告,无错误;i 设置为 NULL。 | +| `ERROR_FOR_DIVISION_BY_ZERO` | 有警告,无错误;i 设置为 NULL。 | +| strict, `ERROR_FOR_DIVISION_BY_ZERO` | 错误;不插入行。 | -`round()` 函数的结果取决于他的参数是否是精确值: +## 舍入行为 -* 如果参数是精确值,`round()` 函数将使用四舍五入的规则。 -* 如果参数是一个近似值,`round()` 表达式的结果可能和 MySQL 不太一样。 +`ROUND()` 函数的结果取决于其参数是精确值还是近似值: -{{< copyable "sql" >}} +- 对于精确值数字,`ROUND()` 函数使用"四舍五入"规则。 +- 对于近似值数字,TiDB 中的结果与 MySQL 中的不同: -```sql -SELECT ROUND(2.5), ROUND(25E-1); -``` + ```sql + TiDB > SELECT ROUND(2.5), ROUND(25E-1); + +------------+--------------+ + | ROUND(2.5) | ROUND(25E-1) | + +------------+--------------+ + | 3 | 3 | + +------------+--------------+ + 1 row in set (0.00 sec) + ``` -``` -+------------+--------------+ -| ROUND(2.5) | ROUND(25E-1) | -+------------+--------------+ -| 3 | 3 | -+------------+--------------+ -1 row in set (0.00 sec) -``` - -向一个 `DECIMAL` 或者整数类型列插入数据时,round 的规则将采用 [round half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero) 的方式: - -{{< copyable "sql" >}} +对于插入到 DECIMAL 或整数列中的值,舍入使用[远离零舍入](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero)。 ```sql -CREATE TABLE t (d DECIMAL(10,0)); -``` - -``` +TiDB > CREATE TABLE t (d DECIMAL(10,0)); Query OK, 0 rows affected (0.01 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t VALUES(2.5),(2.5E0); -``` -``` +TiDB > INSERT INTO t VALUES(2.5),(2.5E0); Query OK, 2 rows affected, 2 warnings (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT d FROM t; -``` - -``` +TiDB > SELECT d FROM t; +------+ | d | +------+ diff --git a/functions-and-operators/sequence-functions.md b/functions-and-operators/sequence-functions.md index 8735e976befb..34e5e2921f7f 100644 --- a/functions-and-operators/sequence-functions.md +++ b/functions-and-operators/sequence-functions.md @@ -1,18 +1,18 @@ --- title: 序列函数 -summary: 了解 TiDB 中的序列函数。 +summary: 本文档介绍 TiDB 支持的序列函数。 --- # 序列函数 TiDB 中的序列函数用于返回或设置使用 [`CREATE SEQUENCE`](/sql-statements/sql-statement-create-sequence.md) 语句创建的序列对象的值。 -| 函数名称 | 功能描述 | -| :-------- | :-------------------------- | -| [`NEXTVAL()`](#nextval) | 返回序列的下一个值 | -| [`NEXT VALUE FOR`](#next-value-for) | 返回序列的下一个值(`NEXTVAL()` 的别名) | -| [`SETVAL()`](#setval) | 设置序列的当前值 | -| [`LASTVAL()`](#lastval) | 返回当前会话中最近一次生成的序列值 | +| 函数名 | 描述 | +| :-------------- | :------------------------------------- | +| [`NEXTVAL()`](#nextval) | 返回序列的下一个值。 | +| [`NEXT VALUE FOR`](#next-value-for) | 返回序列的下一个值(`NEXTVAL()` 的别名)。 | +| [`SETVAL()`](#setval) | 设置序列的当前值。 | +| [`LASTVAL()`](#lastval) | 返回序列在当前会话中生成的最后一个值。 | ## `NEXTVAL()` @@ -20,19 +20,19 @@ TiDB 中的序列函数用于返回或设置使用 [`CREATE SEQUENCE`](/sql-stat 示例: -创建一个序列 `s1`: +创建一个名为 `s1` 的序列: ```sql CREATE SEQUENCE s1; ``` -从序列 `s1` 中获取下一个值: +获取 `s1` 的下一个值: ```sql SELECT NEXTVAL(s1); ``` -输出结果如下: +输出如下: ``` +-------------+ @@ -49,13 +49,13 @@ SELECT NEXTVAL(s1); 示例: -使用 `NEXTVAL()` 从序列 `s1` 中获取下一个值: +使用 `NEXTVAL()` 获取 `s1` 的下一个值: ```sql SELECT NEXTVAL(s1); ``` -输出结果如下: +输出如下: ``` +-------------+ @@ -66,13 +66,13 @@ SELECT NEXTVAL(s1); 1 row in set (0.00 sec) ``` -使用 `NEXT VALUE FOR` 从序列 `s1` 中获取下一个值: +使用 `NEXT VALUE FOR` 获取 `s1` 的下一个值: ```sql SELECT NEXT VALUE FOR s1; ``` -输出结果如下: +输出如下: ``` +-------------------+ @@ -89,13 +89,13 @@ SELECT NEXT VALUE FOR s1; 示例: -从序列 `s1` 中获取下一个值: +获取 `s1` 的下一个值: ```sql SELECT NEXTVAL(s1); ``` -输出结果如下: +输出如下: ``` +-------------+ @@ -106,13 +106,13 @@ SELECT NEXTVAL(s1); 1 row in set (0.00 sec) ``` -将序列 `s1` 的当前值设置为 `10`: +将 `s1` 的当前值设置为 `10`: ```sql SELECT SETVAL(s1, 10); ``` -输出结果如下: +输出如下: ``` +----------------+ @@ -123,13 +123,13 @@ SELECT SETVAL(s1, 10); 1 row in set (0.00 sec) ``` -验证设置序列的当前值为 `10` 后的下一个值: +验证设置为 `10` 后的下一个值: ```sql SELECT NEXTVAL(s1); ``` -输出结果如下: +输出如下: ``` +-------------+ @@ -142,17 +142,17 @@ SELECT NEXTVAL(s1); ## `LASTVAL()` -`LASTVAL()` 函数返回**当前会话中**最近一次生成的序列值。 +`LASTVAL()` 函数返回序列在**当前会话**中生成的最后一个值。 示例: -获取当前会话中最后使用的 `s1` 序列的值: +获取 `s1` 在当前会话中生成的最后一个值: ```sql SELECT LASTVAL(s1); ``` -输出结果如下: +输出如下: ``` +-------------+ @@ -165,4 +165,4 @@ SELECT LASTVAL(s1); ## MySQL 兼容性 -根据 [ISO/IEC 9075-2](https://www.iso.org/standard/76584.html),MySQL 不支持创建和操作序列的函数和语句。 +MySQL 不支持 [ISO/IEC 9075-2](https://www.iso.org/standard/76584.html) 中定义的用于创建和操作序列的函数和语句。 diff --git a/functions-and-operators/set-operators.md b/functions-and-operators/set-operators.md index 81a6ae1f481e..f9f37f452ade 100644 --- a/functions-and-operators/set-operators.md +++ b/functions-and-operators/set-operators.md @@ -5,11 +5,11 @@ summary: 了解 TiDB 支持的集合运算。 # 集合运算 -TiDB 支持三种集合运算:并集 (UNION),差集 (EXCEPT) 和交集 (INTERSECT)。最小的集合单位是一个 [`SELECT` 语句](/sql-statements/sql-statement-select.md)。 +TiDB 支持使用 UNION、EXCEPT 和 INTERSECT 运算符进行三种集合运算。集合的最小单位是 [`SELECT` 语句](/sql-statements/sql-statement-select.md)。 -## 并集 (UNION) +## UNION 运算符 -数学上,两个集合 A 和 B 的并集是含有所有属于 A 或属于 B 的元素。下面是一个 UNION 的例子: +在数学中,两个集合 A 和 B 的并集由 A 或 B 中的所有元素组成。例如: ```sql SELECT 1 UNION SELECT 2; @@ -22,9 +22,7 @@ SELECT 1 UNION SELECT 2; 2 rows in set (0.00 sec) ``` -TiDB 支持 `UNION ALL` 和 `UNION DISTINCT` 并集,两者区别在于 `UNION DISTINCT` 会对并集结果去重复,而 `UNION ALL` 不会。TiDB 中默认使用 `UNION DISTINCT`。 - -{{< copyable "sql" >}} +TiDB 同时支持 `UNION DISTINCT` 和 `UNION ALL` 运算符。`UNION DISTINCT` 从结果集中删除重复记录,而 `UNION ALL` 保留所有记录,包括重复项。在 TiDB 中默认使用 `UNION DISTINCT`。 ```sql CREATE TABLE t1 (a int); @@ -33,7 +31,7 @@ INSERT INTO t1 VALUES (1),(2); INSERT INTO t2 VALUES (1),(3); ``` -`UNION DISTINCT`与 `UNION ALL` 的结果分别如下: +以下分别是 `UNION DISTINCT` 和 `UNION ALL` 查询的示例: ```sql SELECT * FROM t1 UNION DISTINCT SELECT * FROM t2; @@ -58,9 +56,9 @@ SELECT * FROM t1 UNION ALL SELECT * FROM t2; 4 rows in set (0.00 sec) ``` -## 差集 (EXCEPT) +## EXCEPT 运算符 -若 A 和 B 是集合,则 A 与 B 的差集是由所有属于 A 但不属于 B 的元素组成的集合。 +如果 A 和 B 是两个集合,EXCEPT 返回 A 和 B 的差集,即在 A 中但不在 B 中的元素组成的集合。 ```sql SELECT * FROM t1 EXCEPT SELECT * FROM t2; @@ -72,11 +70,11 @@ SELECT * FROM t1 EXCEPT SELECT * FROM t2; 1 rows in set (0.00 sec) ``` -差集 (EXCEPT) 暂时不支持 `EXCEPT ALL`。 +目前尚不支持 `EXCEPT ALL` 运算符。 -## 交集 (INTERSECT) +## INTERSECT 运算符 -数学上,两个集合 A 和 B 的交集是含有所有既属于 A 又属于 B 的元素,而且没有其他元素的集合。 +在数学中,两个集合 A 和 B 的交集由同时在 A 和 B 中的所有元素组成,不包含其他元素。 ```sql SELECT * FROM t1 INTERSECT SELECT * FROM t2; @@ -88,7 +86,7 @@ SELECT * FROM t1 INTERSECT SELECT * FROM t2; 1 rows in set (0.00 sec) ``` -交集 (INTERSECT) 暂时不支持 `INTERSECT ALL`。交集 (INTERSECT) 的计算优先级大于差集 (EXCEPT) 和并集 (UNION)。 +目前尚不支持 `INTERSECT ALL` 运算符。INTERSECT 运算符的优先级高于 EXCEPT 和 UNION 运算符。 ```sql SELECT * FROM t1 UNION ALL SELECT * FROM t1 INTERSECT SELECT * FROM t2; @@ -102,9 +100,9 @@ SELECT * FROM t1 UNION ALL SELECT * FROM t1 INTERSECT SELECT * FROM t2; 3 rows in set (0.00 sec) ``` -## 括号优先 +## 括号 -TiDB 支持使用括号修改集合运算的优先级,如同[四则运算](https://zh.wikipedia.org/zh-hans/%E5%9B%9B%E5%88%99%E8%BF%90%E7%AE%97)中先计算括号部分,集合运算也先计算括号内的部分。 +TiDB 支持使用括号来指定集合运算的优先级。括号中的表达式会首先被处理。 ```sql (SELECT * FROM t1 UNION ALL SELECT * FROM t1) INTERSECT SELECT * FROM t2; @@ -116,9 +114,9 @@ TiDB 支持使用括号修改集合运算的优先级,如同[四则运算](htt 1 rows in set (0.00 sec) ``` -## 与 `ORDER BY` 和 `LIMIT` 结合 +## 使用 `ORDER BY` 和 `LIMIT` -TiDB 支持对整个集合运算的结果使用 `ORDER BY` 或 `LIMIT` 子句。这两个子句必须位于整个语句的末尾。 +TiDB 支持在集合运算的整个结果上使用 `ORDER BY` 或 `LIMIT` 子句。这两个子句必须位于整个语句的末尾。 ```sql (SELECT * FROM t1 UNION ALL SELECT * FROM t1 INTERSECT SELECT * FROM t2) ORDER BY a LIMIT 2; diff --git a/functions-and-operators/string-functions.md b/functions-and-operators/string-functions.md index 1cc31dadd96a..0e18029eb4d2 100644 --- a/functions-and-operators/string-functions.md +++ b/functions-and-operators/string-functions.md @@ -1,35 +1,39 @@ --- title: 字符串函数 -summary: TiDB 支持 MySQL 8.0 中提供的大部分字符串函数以及 Oracle 21 中提供的部分函数。 +summary: 了解 TiDB 中的字符串函数。 --- # 字符串函数 -TiDB 支持使用 MySQL 8.0 中提供的大部分[字符串函数](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html)以及 Oracle 21 中提供的部分[函数](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlqr/SQL-Functions.html#GUID-93EC62F8-415D-4A7E-B050-5D5B2C127009)。 +TiDB 支持大多数 [MySQL 8.0 中的字符串函数](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html),以及一些 [Oracle 21 中可用的函数](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlqr/SQL-Functions.html#GUID-93EC62F8-415D-4A7E-B050-5D5B2C127009)。 -关于 Oracle 函数和 TiDB 函数的对照关系,请参考 [Oracle 与 TiDB 函数和语法差异对照](/oracle-functions-to-tidb.md)。 + + +关于 Oracle 和 TiDB 函数和语法的比较,请参见[Oracle 和 TiDB 函数和语法的比较](/oracle-functions-to-tidb.md)。 + + ## 支持的函数 -### [`ASCII()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ascii) +### `ASCII()` -`ASCII()` 函数用于获取输入的参数中最左字符的 ASCII 值。该参数可以为字符串或数字。 +`ASCII(str)` 函数用于获取给定参数最左边字符的 ASCII 值。参数可以是字符串或数字。 -- 如果输入参数不为空,该函数返回参数中最左字符的 ASCII 值。 -- 如果输入参数为空字符串,该函数返回 `0`。 -- 如果输入参数为 `NULL`,该函数返回 `NULL`。 +- 如果参数不为空,函数返回最左边字符的 ASCII 值。 +- 如果参数是空字符串,函数返回 `0`。 +- 如果参数是 `NULL`,函数返回 `NULL`。 > **注意:** > -> `ASCII()` 只能处理那些用 8 个二进制数字(即单个字节)来表示的字符。 +> `ASCII(str)` 仅适用于使用 8 位二进制数字(一个字节)表示的字符。 -查询示例: +示例: ```sql SELECT ASCII('A'), ASCII('TiDB'), ASCII(23); ``` -返回结果: +输出: ```sql +------------+---------------+-----------+ @@ -39,24 +43,24 @@ SELECT ASCII('A'), ASCII('TiDB'), ASCII(23); +------------+---------------+-----------+ ``` -### [`BIN()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_bin) +### `BIN()` -`BIN()` 函数用于将输入的参数转换为其二进制值的字符串表示形式。该参数可以为字符串或数字。 +`BIN()` 函数用于将给定参数转换为其二进制值的字符串表示。参数可以是字符串或数字。 -- 如果输入参数为正数,该函数返回该参数的二进制值的字符串表示形式。 -- 如果输入参数为负数,该函数会将该参数的绝对值转换为其二进制值,然后对二进制值的每位取反(`0` 变为 `1`,`1` 变为 `0`),最后加上 `1`。 -- 如果输入参数为字符串,且该字符串中只包含数字,该函数将按照该数字返回结果。例如,`"123"` 与 `123` 的返回结果相同。 -- 如果输入参数为字符串,且该字符串第一个字符不是数字(如 `"q123"`),该函数返回 `0`。 -- 如果输入参数为字符串,且该字符串由数字和非数字组成,该函数将按照该参数中最前面连续的数字返回结果。例如,`'123q123'` 与 `123` 的返回结果相同,但 `BIN('123q123')` 会产生一个 `Truncated incorrect INTEGER value: '123q123'` 的警告。 -- 如果输入参数为 `NULL`,该函数返回 `NULL`。 +- 如果参数是正数,函数返回其二进制值的字符串表示。 +- 如果参数是负数,函数将参数的绝对值转换为二进制表示,然后对二进制值的每一位取反(将 `0` 变为 `1`,将 `1` 变为 `0`),最后加 1。 +- 如果参数是仅包含数字的字符串,函数根据这些数字返回结果。例如,`"123"` 和 `123` 的结果相同。 +- 如果参数是字符串且其第一个字符不是数字(如 `"q123"`),函数返回 `0`。 +- 如果参数是由数字和非数字组成的字符串,函数根据参数开头的连续数字返回结果。例如,`"123q123"` 和 `123` 的结果相同,但会生成警告。 +- 如果参数是 `NULL`,函数返回 `NULL`。 -查询示例 1: +示例: ```sql SELECT BIN(123), BIN('123q123'); ``` -返回结果 1: +输出: ```sql +----------+----------------+ @@ -66,139 +70,9 @@ SELECT BIN(123), BIN('123q123'); +----------+----------------+ ``` -查询示例 2: - -```sql -SELECT BIN(-7); -``` - -返回结果 2: - -```sql -+------------------------------------------------------------------+ -| BIN(-7) | -+------------------------------------------------------------------+ -| 1111111111111111111111111111111111111111111111111111111111111001 | -+------------------------------------------------------------------+ -``` - -### [`BIT_LENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_bit-length) - -`BIT_LENGTH()` 函数用于返回输入参数的长度,单位为 bit。 - -示例: - -```sql -SELECT BIT_LENGTH("TiDB"); - -+--------------------+ -| BIT_LENGTH("TiDB") | -+--------------------+ -| 32 | -+--------------------+ -``` - -每个字符 8 位 x 4 个字符 = 32 位 - -```sql -SELECT BIT_LENGTH("PingCAP 123"); - -+---------------------------+ -| BIT_LENGTH("PingCAP 123") | -+---------------------------+ -| 88 | -+---------------------------+ -``` - -每个字符 8 位(空格也会被计算在内,因为它是非字母数字字符) x 11 个字符 = 88 位 - -```sql -SELECT CustomerName, BIT_LENGTH(CustomerName) AS BitLengthOfName FROM Customers; - -+--------------------+-----------------+ -| CustomerName | BitLengthOfName | -+--------------------+-----------------+ -| Albert Einstein | 120 | -| Robert Oppenheimer | 144 | -+--------------------+-----------------+ -``` - -> **注意:** -> -> 上面这个示例假设数据库中存在一个名为 `Customers` 的表,表中有一个名为 `CustomerName` 的列。 - -### [`CHAR()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char) - -`CHAR()` 函数用于获取指定 ASCII 值的对应字符。该函数执行的操作与 `ASCII()` 相反,`ASCII()` 用于返回指定字符的 ASCII 值。如果提供了多个参数,`CHAR()` 函数将作用于所有参数并将它们的结果拼接在一起返回。 - -示例: - -```sql -SELECT CHAR(65); - -+------------+ -| CHAR(65) | -+------------+ -| A | -+------------+ -``` - -```sql -SELECT CHAR(84); - -+------------+ -| CHAR(84) | -+------------+ -| T | -+------------+ -``` - -`CHAR()` 函数还可用于获取超出标准 ASCII 范围(`0` - `127`)的 ASCII 值的对应字符。 - -```sql -/*For extended ASCII: */ - -SELECT CHAR(128); - -+------------+ -| CHAR(128) | -+------------+ -| 0x80 | -+------------+ -``` - -`CHAR()` 函数还可用于获取 Unicode 值的对应字符。 - -```sql -/* For Unicode: */ - ---skip-binary-as-hex - -SELECT CHAR(50089); - -+--------------+ -| CHAR(50089) | -+--------------+ -| é | -+--------------+ -``` - -```sql -SELECT CHAR(65,66,67); -``` - -``` -+----------------+ -| CHAR(65,66,67) | -+----------------+ -| ABC | -+----------------+ -1 row in set (0.00 sec) -``` - -### [`CHAR_LENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char-length) +### `CHAR_LENGTH()` -`CHAR_LENGTH()` 函数用于获取输入参数中字符的总数。 +`CHAR_LENGTH()` 函数用于获取给定参数中字符的总数,返回一个整数。 示例: @@ -212,28 +86,13 @@ SELECT CHAR_LENGTH("TiDB") AS LengthOfString; +----------------+ ``` -```sql -SELECT CustomerName, CHAR_LENGTH(CustomerName) AS LengthOfName FROM Customers; - -+--------------------+--------------+ -| CustomerName | LengthOfName | -+--------------------+--------------+ -| Albert Einstein | 15 | -| Robert Oppenheimer | 18 | -+--------------------+--------------+ -``` - -> **注意:** -> -> 上面这个示例假设数据库中存在一个名为 `Customers` 的表,表中有一个名为 `CustomerName` 的列。 - -### [`CHARACTER_LENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_character-length) +### `CHARACTER_LENGTH()` -`CHARACTER_LENGTH()` 函数与 `CHAR_LENGTH()` 函数功能相同,返回结果相同,可以互换使用。 +`CHARACTER_LENGTH()` 函数与 `CHAR_LENGTH()` 函数相同。这两个函数可以同义使用,因为它们生成相同的输出。 -### [`CONCAT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat) +### `CONCAT()` -`CONCAT()` 函数用于将输入的参数连接成一个字符串。 +`CONCAT()` 函数将一个或多个参数连接成一个字符串。 语法: @@ -241,15 +100,17 @@ SELECT CustomerName, CHAR_LENGTH(CustomerName) AS LengthOfName FROM Customers; CONCAT(str1,str2,...) ``` -`str1, str2, ...` 为要连接的参数。该参数可以是字符串或数字。 +`str1, str2, ...` 是要连接的参数列表。每个参数可以是字符串或数字。 -查询示例: +如果任何参数为 `NULL`,`CONCAT()` 返回 `NULL`。 + +示例: ```sql SELECT CONCAT('TiDB', ' ', 'Server', '-', 1, TRUE); ``` -返回结果: +输出: ```sql +---------------------------------------------+ @@ -258,2102 +119,3 @@ SELECT CONCAT('TiDB', ' ', 'Server', '-', 1, TRUE); | TiDB Server-11 | +---------------------------------------------+ ``` - -如果任一参数的值为 `NULL`, 则 `CONCAT()` 返回 `NULL`。 - -查询示例: - -```sql -SELECT CONCAT('TiDB', NULL, 'Server'); -``` - -返回结果: - -```sql -+--------------------------------+ -| CONCAT('TiDB', NULL, 'Server') | -+--------------------------------+ -| NULL | -+--------------------------------+ -``` - -除了使用 `CONCAT()` 函数外,你也可以通过字符串彼此相邻的方式获取拼接字符串,但是该方式不支持数字类型。例如: - -```sql -SELECT 'Ti' 'DB' ' ' 'Server'; -``` - -返回结果: - -```sql -+-------------+ -| Ti | -+-------------+ -| TiDB Server | -+-------------+ -``` - -### [`CONCAT_WS()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat-ws) - -`CONCAT_WS()` 函数是一种带分隔符的 [`CONCAT()`](#concat),返回由分隔符连接的字符串。 - -语法: - -```sql -CONCAT_WS(separator,str1,str2,...) -``` - -- `separator`:第一个参数为分隔符,用于连接其余的不为 `NULL` 的参数。 -- `str1, str2, ...`:要连接的参数。该参数可以为字符串或数字。 - -查询示例: - -```sql -SELECT CONCAT_WS(',', 'TiDB Server', 'TiKV', 'PD'); -``` - -返回结果: - -```sql -+---------------------------------------------+ -| CONCAT_WS(',', 'TiDB Server', 'TiKV', 'PD') | -+---------------------------------------------+ -| TiDB Server,TiKV,PD | -+---------------------------------------------+ -``` - -- 如果分隔符为空,则 `CONCAT_WS()` 等效于 `CONCAT()`,返回其余参数连接后的字符串。 - - 查询示例: - - ```sql - SELECT CONCAT_WS('', 'TiDB Server', 'TiKV', 'PD'); - ``` - - 返回结果: - - ```sql - +--------------------------------------------+ - | CONCAT_WS('', 'TiDB Server', 'TiKV', 'PD') | - +--------------------------------------------+ - | TiDB ServerTiKVPD | - +--------------------------------------------+ - ``` - -- 如果分隔符为 `NULL`,则 `CONCAT_WS()`返回 `NULL`。 - - 查询示例: - - ```sql - SELECT CONCAT_WS(NULL, 'TiDB Server', 'TiKV', 'PD'); - ``` - - 返回结果: - - ```sql - +----------------------------------------------+ - | CONCAT_WS(NULL, 'TiDB Server', 'TiKV', 'PD') | - +----------------------------------------------+ - | NULL | - +----------------------------------------------+ - ``` - -- 如果用于连接的参数中只有一个不为 `NULL`,则 `CONCAT_WS()` 返回此参数。 - - 查询示例: - - ```sql - SELECT CONCAT_WS(',', 'TiDB Server', NULL); - ``` - - 返回结果: - - ```sql - +-------------------------------------+ - | CONCAT_WS(',', 'TiDB Server', NULL) | - +-------------------------------------+ - | TiDB Server | - +-------------------------------------+ - ``` - -- 如果用于连接的参数中有 `NULL`,`CONCAT_WS()`会忽略 `NULL`。 - - 查询示例: - - ```sql - SELECT CONCAT_WS(',', 'TiDB Server', NULL, 'PD'); - ``` - - 返回结果: - - ```sql - +-------------------------------------------+ - | CONCAT_WS(',', 'TiDB Server', NULL, 'PD') | - +-------------------------------------------+ - | TiDB Server,PD | - +-------------------------------------------+ - ``` - -- 如果用于连接的参数中有空字符串,`CONCAT_WS()` 不会忽略该字符串。 - - 查询示例: - - ```sql - SELECT CONCAT_WS(',', 'TiDB Server', '', 'PD'); - ``` - - 返回结果: - - ```sql - +-----------------------------------------+ - | CONCAT_WS(',', 'TiDB Server', '', 'PD') | - +-----------------------------------------+ - | TiDB Server,,PD | - +-----------------------------------------+ - ``` - -### [`ELT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_elt) - -`ELT()` 函数返回索引号对应的元素。 - -```sql -SELECT ELT(3, 'This', 'is', 'TiDB'); -``` - -```sql -+------------------------------+ -| ELT(3, 'This', 'is', 'TiDB') | -+------------------------------+ -| TiDB | -+------------------------------+ -1 row in set (0.00 sec) -``` - -在以上示例中,该函数返回第三个元素,即 `'TiDB'`。 - -### [`EXPORT_SET()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_export-set) - -`EXPORT_SET()` 函数返回一个由指定数量 (`number_of_bits`) 的 `on`/`off` 值组成的字符串,各个值之间可以用 `separator` 分隔(可选)。这些值将基于输入的 `bits` 参数中的相应 bit 是否为 `1` 而确定,其中第一个值对应于 `bits` 中的最右边(即最低)的 bit。 - -语法: - -```sql -EXPORT_SET(bits, on, off, [separator[, number_of_bits]]) -``` - -- `bits`:一个代表 bits 值的整数。 -- `on`:如果对应的 bit 为 `1`,则返回该字符串。 -- `off`:如果对应的 bit 为 `0`,则返回该字符串。 -- `separator`(可选):输出字符串中的分隔符。 -- `number_of_bits`(可选):要处理的位数。如果未设置,则默认使用 `64`(最大位数),这意味着 `bits` 将被视为一个无符号 64 位整数。 - -示例: - -在以下示例中,`number_of_bits` 设置为 `5`,因此该函数返回由 `|` 分隔的 5 个值。`'101'` 里的 bit 值只有三位,所以其他位被视为未设置。因此,将 `number_of_bits` 设置为 `101` 或设置为 `00101` 的返回结果相同。 - -```sql -SELECT EXPORT_SET(b'101',"ON",'off','|',5); -``` - -```sql -+-------------------------------------+ -| EXPORT_SET(b'101',"ON",'off','|',5) | -+-------------------------------------+ -| ON|off|ON|off|off | -+-------------------------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,`bits` 设置为 `00001111`,`on` 设置为 `x`,`off` 设置为 `_`。这使函数在这些 `0` 位上返回 `____`,在这些 `1` 位上返回 `xxxx`。因此,从右到左处理 `00001111` 中的位时,该函数返回 `xxxx____`。 - -```sql -SELECT EXPORT_SET(b'00001111', 'x', '_', '', 8); -``` - -```sql -+------------------------------------------+ -| EXPORT_SET(b'00001111', 'x', '_', '', 8) | -+------------------------------------------+ -| xxxx____ | -+------------------------------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,`bits` 设置为 `00001111`,`on` 设置为 `x`,`off` 设置为 `_`。这使函数在每个 `1` 位上返回 `x`,在每个 `0` 位上返回 `_`。因此,从右到左处理 `01010101` 中的位时,该函数返回 `x_x_x_x_`。 - -```sql -SELECT EXPORT_SET(b'01010101', 'x', '_', '', 8); -``` - -```sql -+------------------------------------------+ -| EXPORT_SET(b'01010101', 'x', '_', '', 8) | -+------------------------------------------+ -| x_x_x_x_ | -+------------------------------------------+ -1 row in set (0.00 sec) -``` - -### [`FIELD()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_field) - -返回参数在后续参数中出现的第一个位置 - -在以下示例中,`FIELD()` 的第一个参数是 `needle`,它与后续列表中的第二个参数匹配,因此函数返回 `2`。 - -```sql -SELECT FIELD('needle', 'A', 'needle', 'in', 'a', 'haystack'); -+-------------------------------------------------------+ -| FIELD('needle', 'A', 'needle', 'in', 'a', 'haystack') | -+-------------------------------------------------------+ -| 2 | -+-------------------------------------------------------+ -1 row in set (0.00 sec) -``` - -### [`FIND_IN_SET()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_find-in-set) - -返回第一个参数在第二个参数中出现的位置 - -该函数通常与 [`SET`](/data-type-string.md#set-类型) 数据类型一起使用。 - -在以下示例中,`Go` 是集合 `COBOL,BASIC,Rust,Go,Java,Fortran` 中的第四个元素,因此函数返回 `4`。 - -```sql -SELECT FIND_IN_SET('Go', 'COBOL,BASIC,Rust,Go,Java,Fortran'); -+-------------------------------------------------------+ -| FIND_IN_SET('Go', 'COBOL,BASIC,Rust,Go,Java,Fortran') | -+-------------------------------------------------------+ -| 4 | -+-------------------------------------------------------+ -1 row in set (0.00 sec) -``` - -### [`FORMAT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_format) - -`FORMAT(X,D[,locale])` 函数用于将数字 `X` 格式化为类似于 `“#,###,###.##”` 的格式,四舍五入保留 `D` 位小数,并将结果作为字符串返回。 - -参数: - -- `X`:要格式化的数字。可以是直接的数字值、数字字符串、或科学记数法格式的数字。 -- `D`:指定返回值的小数位数。该函数根据 `D` 对 `X` 进行四舍五入。如果 `D` 大于 `X` 的实际小数位数,则会在结果中填充相应长度的零。 -- `[locale]`:指定一个区域设置,用于结果中数字的小数点、千位分隔符和分隔符之间的分组。合法的区域设置值与 [`lc_time_names`](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_lc_time_names) 系统变量的合法值相同。如果未指定或者设置为 `NULL`,则默认使用 `'en_US'` 区域设置。该参数可选。 - -行为细节: - -- 如果输入的第一个参数为字符串,且该字符串中只包含数字时,该函数将按照该数字返回结果。例如,`FORMAT('12.36', 1)` 与 `FORMAT(12.36, 1)` 的返回结果相同。 -- 如果输入的第一个参数为科学计数法(`E/e`)表示的数字时,该函数将按照该数字返回结果。例如,`FORMAT('1E2', 3)`),函数返回 `100.000`。 -- 如果输入的第一个参数为非数字开头的字符串时,该函数除了返回零值外,还返回一个警告 `(Code 1292)`。例如,`FORMAT('q12.36', 5)` 函数返回 `0.00000`,还会包含一个警告 `Warning (Code 1292): Truncated incorrect DOUBLE value: 'q12.36'`。 -- 如果输入的第一个参数为数字和非数字混合的字符串时,该函数将基于该参数中开头连续的数字部分返回结果,还返回一个警告 `(Code 1292)`。例如,`FORMAT('12.36q56.78', 1)` 与 `FORMAT('12.36', 1)` 的返回的数字结果相同,但 `FORMAT('12.36q56.78', 1)` 还会包含一个警告 `Warning (Code 1292): Truncated incorrect DOUBLE value: '12.36q56.78'`。 -- 如果输入的第二个参数为零或负数,该函数将四舍五入小数部分并返回整数。 -- 如果输入的任意参数为 `NULL`,函数将返回 `NULL`。 - -示例: - -格式化数字 12.36 到不同的小数位数: - -```sql -mysql> SELECT FORMAT(12.36, 1); -+------------------+ -| FORMAT(12.36, 1) | -+------------------+ -| 12.4 | -+------------------+ -``` - -```sql -mysql> SELECT FORMAT(12.36, 5); -+------------------+ -| FORMAT(12.36, 5) | -+------------------+ -| 12.36000 | -+------------------+ -``` - -```sql -mysql> SELECT FORMAT(1234.56, 1, 'en_US'); -+-----------------------------+ -| FORMAT(1234.56, 1, 'en_US') | -+-----------------------------+ -| 1,234.6 | -+-----------------------------+ -``` - -### [`FROM_BASE64()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_from-base64) - -`FROM_BASE64(str)` 函数用于对 [Base64](https://datatracker.ietf.org/doc/html/rfc4648) 编码的字符串进行解码,并将解码结果以十六进制字符串的形式返回。 - -- 此函数接受一个单一参数,即需要解码的 Base64 编码字符串。 -- 如果输入参数为 `NULL` 或无效的 Base64 编码字符串,`FROM_BASE64()` 函数将返回 `NULL`。 - -示例: - -以下示例解码 Base64 编码的字符串 `'SGVsbG8gVGlEQg=='`,该字符串是 `'Hello TiDB'` 经过 [`TO_BASE64()`](#to_base64) 函数编码的结果。 - -```sql -mysql> SELECT TO_BASE64('Hello TiDB'); -+-------------------------+ -| TO_BASE64('Hello TiDB') | -+-------------------------+ -| SGVsbG8gVGlEQg== | -+-------------------------+ - -mysql> SELECT FROM_BASE64('SGVsbG8gVGlEQg=='); -+------------------------------------------------------------------+ -| FROM_BASE64('SGVsbG8gVGlEQg==') | -+------------------------------------------------------------------+ -| 0x48656C6C6F2054694442 | -+------------------------------------------------------------------+ -``` - -```sql -mysql> SELECT CONVERT(FROM_BASE64('SGVsbG8gVGlEQg==') USING utf8mb4); -+--------------------------------------------------------+ -| CONVERT(FROM_BASE64('SGVsbG8gVGlEQg==') USING utf8mb4) | -+--------------------------------------------------------+ -| Hello TiDB | -+--------------------------------------------------------+ -``` - -以下示例解码 Base64 编码的数字 `MTIzNDU2`,该字符串是 `123456` 经过 [`TO_BASE64()`](#to_base64) 函数编码的结果。 - -```sql -mysql> SELECT FROM_BASE64('MTIzNDU2'); -+--------------------------------------------------+ -| FROM_BASE64('MTIzNDU2') | -+--------------------------------------------------+ -| 0x313233343536 | -+--------------------------------------------------+ -``` - -### [`HEX()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_hex) - -`HEX()` 函数用于将输入的参数转换为其十六进制值的字符串表示形式。该参数可以为字符串或数字。 - -- 如果输入参数为字符串,`HEX(str)` 返回 `str` 的十六进制字符串表示。该函数将 `str` 中每个字符的每个字节转换为两个十六进制数字。例如,在 UTF-8 或 ASCII 字符集中,字符 `a` 的二进制表示为 `00111101`,十六进制表示为 `61`。 -- 如果输入参数为数字,`HEX(n)` 返回 `n` 的十六进制字符串表示。该函数将参数 `n` 视为 `BIGINT` 数字,相当于 `CONV(n, 10, 16)`。 -- 如果输入参数为 `NULL`,该函数返回 `NULL`。 - -> **注意:** -> -> 在 MySQL 客户端中,[`--binary-as-hex`](https://dev.mysql.com/doc/refman/8.0/en/mysql-command-options.html#option_mysql_binary-as-hex) 选项在交互模式下默认启用,这会导致客户端将无法识别的字符集数据显示为[十六进制字面量 (Hexadecimal literal)](https://dev.mysql.com/doc/refman/8.0/en/hexadecimal-literals.html)。你可以使用 `--skip-binary-as-hex` 选项来禁用此行为。 - -示例(使用 `mysql --skip-binary-as-hex`): - -```sql -SELECT X'616263', HEX('abc'), UNHEX(HEX('abc')), 0x616263; -+-----------+------------+-------------------+----------+ -| X'616263' | HEX('abc') | UNHEX(HEX('abc')) | 0x616263 | -+-----------+------------+-------------------+----------+ -| abc | 616263 | abc | abc | -+-----------+------------+-------------------+----------+ -``` - -```sql -SELECT X'F09F8DA3', HEX('🍣'), UNHEX(HEX('🍣')), 0xF09F8DA3; -+-------------+-------------+--------------------+------------+ -| X'F09F8DA3' | HEX('🍣') | UNHEX(HEX('🍣')) | 0xF09F8DA3 | -+-------------+-------------+--------------------+------------+ -| 🍣 | F09F8DA3 | 🍣 | 🍣 | -+-------------+-------------+--------------------+------------+ -``` - -```sql -SELECT HEX(255), CONV(HEX(255), 16, 10); -+----------+------------------------+ -| HEX(255) | CONV(HEX(255), 16, 10) | -+----------+------------------------+ -| FF | 255 | -+----------+------------------------+ -``` - -```sql -SELECT HEX(NULL); -+-----------+ -| HEX(NULL) | -+-----------+ -| NULL | -+-----------+ -``` - -### [`INSERT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_insert) - -`INSERT(str, pos, len, newstr)` 函数用于将字符串 `str` 中的一个子字符串(从位置 `pos` 开始,长度为 `len`)替换为字符串 `newstr`。该函数是多字节安全的。 - -- 如果 `pos` 超过了 `str` 的长度,函数返回原始字符串 `str` 而不做修改。 -- 如果 `len` 超过了从位置 `pos` 开始的 `str` 的剩余长度,函数将从位置 `pos` 开始替换字符串的其余部分。 -- 如果任一参数为 `NULL`,该函数返回 `NULL`。 - -示例: - -```sql -SELECT INSERT('He likes tennis', 4, 5, 'plays'); -+------------------------------------------+ -| INSERT('He likes tennis', 4, 5, 'plays') | -+------------------------------------------+ -| He plays tennis | -+------------------------------------------+ -``` - -```sql -SELECT INSERT('He likes tennis', -1, 5, 'plays'); -+-------------------------------------------+ -| INSERT('He likes tennis', -1, 5, 'plays') | -+-------------------------------------------+ -| He likes tennis | -+-------------------------------------------+ -``` - -```sql -SELECT INSERT('He likes tennis', 4, 100, 'plays'); -+--------------------------------------------+ -| INSERT('He likes tennis', 4, 100, 'plays') | -+--------------------------------------------+ -| He plays | -+--------------------------------------------+ -``` - -```sql -SELECT INSERT('He likes tennis', 10, 100, '🍣'); -+-------------------------------------------+ -| INSERT('He likes tennis', 10, 100, '🍣') | -+-------------------------------------------+ -| He likes 🍣 | -+-------------------------------------------+ -``` - -```sql -SELECT INSERT('PingCAP 数据库', 1, 7, 'TiDB'); -+-------------------------------------------+ -| INSERT('PingCAP 数据库', 1, 7, 'TiDB') | -+-------------------------------------------+ -| TiDB 数据库 | -+-------------------------------------------+ -``` - -### [`INSTR()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_instr) - -`INSTR(str, substr)` 函数用于获取子字符串 `substr` 在字符串 `str` 中第一次出现的位置。`substr` 和 `str` 均可以为字符串或数字。该函数与 [`LOCATE(substr, str)`](#locate) 函数的两参数版本功能相同,但参数顺序相反。 - -> **注意:** -> -> `INSTR(str, substr)` 函数是否区分大小取决于 TiDB 所使用的[排序规则](/character-set-and-collation.md)。二进制排序规则(以 `_bin` 为后缀)区分大小写,而通用排序规则(以 `_general_ci` 或 `_ai_ci` 为后缀)不区分大小写。 - -- 如果任一输入参数为数字,该函数将数字视为字符串处理。 -- 如果 `substr` 不在 `str` 中,函数返回 `0`。否则,返回 `substr` 在 `str` 中第一次出现的位置。 -- 如果任一参数为 `NULL`,该函数返回 `NULL`。 - -示例: - -```sql -SELECT INSTR("pingcap.com", "tidb"); -+------------------------------+ -| INSTR("pingcap.com", "tidb") | -+------------------------------+ -| 0 | -+------------------------------+ -``` - -```sql -SELECT INSTR("pingcap.com/tidb", "tidb"); -+-----------------------------------+ -| INSTR("pingcap.com/tidb", "tidb") | -+-----------------------------------+ -| 13 | -+-----------------------------------+ -``` - -```sql -SELECT INSTR("pingcap.com/tidb" COLLATE utf8mb4_bin, "TiDB"); -+-------------------------------------------------------+ -| INSTR("pingcap.com/tidb" COLLATE utf8mb4_bin, "TiDB") | -+-------------------------------------------------------+ -| 0 | -+-------------------------------------------------------+ -``` - -```sql -SELECT INSTR("pingcap.com/tidb" COLLATE utf8mb4_general_ci, "TiDB"); -+--------------------------------------------------------------+ -| INSTR("pingcap.com/tidb" COLLATE utf8mb4_general_ci, "TiDB") | -+--------------------------------------------------------------+ -| 13 | -+--------------------------------------------------------------+ -``` - -```sql -SELECT INSTR(0123, "12"); -+-------------------+ -| INSTR(0123, "12") | -+-------------------+ -| 1 | -+-------------------+ -``` - -### [`LCASE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_lcase) - -`LCASE(str)`函数与 [`LOWER(str)`](#lower) 函数功能相同,都是返回输入参数的小写形式。 - -### [`LEFT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_left) - -`LEFT()` 函数用于返回字符串左侧指定数量的字符。 - -语法: - -```sql -LEFT(`str`, `len`) -``` - -- `str`:要提取字符的原始字符串。如果 `str` 包含一个多字节字符,该函数将其视为一个字符。 -- `len`:要返回的字符长度。 - - 如果 `len` 小于或等于 0,该函数返回空字符串。 - - 如果 `len` 大于或等于 `str` 的长度,该函数将返回原始的 `str`。 -- 如果任何参数为 `NULL`,该函数返回 `NULL`。 - -示例: - -```sql -SELECT LEFT('ABCED', 3); -+------------------+ -| LEFT('ABCED', 3) | -+------------------+ -| ABC | -+------------------+ - -SELECT LEFT('ABCED', 6); -+------------------+ -| LEFT('ABCED', 6) | -+------------------+ -| ABCED | -+------------------+ -``` - -```sql -SELECT LEFT('ABCED', 0); -+------------------+ -| LEFT('ABCED', 0) | -+------------------+ -| | -+------------------+ - -SELECT LEFT('ABCED', -1); -+-------------------+ -| LEFT('ABCED', -1) | -+-------------------+ -| | -+-------------------+ -``` - -```sql -SELECT LEFT('🍣ABC', 3); -+--------------------+ -| LEFT('🍣ABC', 3) | -+--------------------+ -| 🍣AB | -+--------------------+ -``` - -```sql -SELECT LEFT('ABC', NULL); -+-------------------+ -| LEFT('ABC', NULL) | -+-------------------+ -| NULL | -+-------------------+ - -SELECT LEFT(NULL, 3); -+------------------------------+ -| LEFT(NULL, 3) | -+------------------------------+ -| NULL | -+------------------------------+ -``` - -### [`LENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_length) - -`LENGTH()` 函数用于返回字符串的字节长度。`LENGTH()` 将单个多字节字符视为多个字节,而 `CHAR_LENGTH()` 将单个多字节字符视为单个字符。 - -如果输入参数为 `NULL`,该函数将返回 `NULL`。 - -示例: - -```sql -SELECT LENGTH('ABC'); -+---------------+ -| LENGTH('ABC') | -+---------------+ -| 3 | -+---------------+ - -SELECT LENGTH('🍣ABC'); -+-------------------+ -| LENGTH('🍣ABC') | -+-------------------+ -| 7 | -+-------------------+ - -SELECT CHAR_LENGTH('🍣ABC'); -+------------------------+ -| CHAR_LENGTH('🍣ABC') | -+------------------------+ -| 4 | -+------------------------+ -``` - -```sql -SELECT LENGTH(NULL); -+--------------+ -| LENGTH(NULL) | -+--------------+ -| NULL | -+--------------+ -``` - -### [`LIKE`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like) - -`LIKE` 用于进行简单字符串匹配。表达式 `expr LIKE pat [ESCAPE 'escape_char']` 返回 `1` (`TRUE`) 或 `0` (`FALSE`)。如果 `expr` 或 `pat` 中任一个为 `NULL`,结果为 `NULL`。 - -你可以在 `LIKE` 中使用以下两个通配符: - -- `%` 匹配任意数量的字符,包括零个字符。 -- `_` 精确匹配一个字符。 - -以下示例使用 `utf8mb4_bin` 排序规则: - -```sql -SET collation_connection='utf8mb4_bin'; -SHOW VARIABLES LIKE 'collation_connection'; -+----------------------+-------------+ -| Variable_name | Value | -+----------------------+-------------+ -| collation_connection | utf8mb4_bin | -+----------------------+-------------+ -``` - -```sql -SELECT NULL LIKE '%' as result; -+--------+ -| result | -+--------+ -| NULL | -+--------+ -``` - -```sql -SELECT 'sushi!!!' LIKE 'sushi_' AS result; -+--------+ -| result | -+--------+ -| 0 | -+--------+ -``` - -```sql -SELECT '🍣🍺sushi🍣🍺' LIKE '%sushi%' AS result; -+--------+ -| result | -+--------+ -| 1 | -+--------+ -``` - -```sql -SELECT '🍣🍺sushi🍣🍺' LIKE '%SUSHI%' AS result; -+--------+ -| result | -+--------+ -| 0 | -+--------+ -``` - -```sql -SELECT '🍣🍺sushi🍣🍺' LIKE '%🍣%' AS result; -+--------+ -| result | -+--------+ -| 1 | -+--------+ -``` - -默认的转义字符是 `\`: - -```sql -SELECT 'sushi!!!' LIKE 'sushi\_' AS result; -+--------+ -| result | -+--------+ -| 0 | -+--------+ -``` - -```sql -SELECT 'sushi_' LIKE 'sushi\_' AS result; -+--------+ -| result | -+--------+ -| 1 | -+--------+ -``` - -你可以使用 `ESCAPE` 子句指定一个不同的转义字符,例如 `*`: - -```sql -SELECT 'sushi_' LIKE 'sushi*_' ESCAPE '*' AS result; -+--------+ -| result | -+--------+ -| 1 | -+--------+ -``` - -```sql -SELECT 'sushi!' LIKE 'sushi*_' ESCAPE '*' AS result; -+--------+ -| result | -+--------+ -| 0 | -+--------+ -``` - -你可以使用 `LIKE` 匹配一个数字: - -```sql -SELECT 10 LIKE '1%' AS result; -+--------+ -| result | -+--------+ -| 1 | -+--------+ -``` - -```sql -SELECT 10000 LIKE '12%' AS result; -+--------+ -| result | -+--------+ -| 0 | -+--------+ -``` - -你可以使用 `COLLATE` 显式指定一个排序规则,例如 `utf8mb4_unicode_ci`: - -```sql -SELECT '🍣🍺Sushi🍣🍺' COLLATE utf8mb4_unicode_ci LIKE '%SUSHI%' AS result; -+--------+ -| result | -+--------+ -| 1 | -+--------+ -``` - -### [`LOCATE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_locate) - -`LOCATE(substr, str[, pos])` 函数用于返回子字符串 `substr` 在字符串 `str` 中第一次出现的位置。`pos` 参数是可选的,用于指定查找的起始位置。 - -- 如果子字符串 `substr` 不在字符串 `str` 中,该函数返回 `0`。 -- 如果任一参数为 `NULL`,该函数返回 `NULL`。 -- 该函数是多字节安全的,并且只有当至少一个参数是二进制字符串时,才执行区分大小写的查找。 - -以下示例使用 `utf8mb4_bin` 排序规则: - -```sql -SET collation_connection='utf8mb4_bin'; -SHOW VARIABLES LIKE 'collation_connection'; -+----------------------+-------------+ -| Variable_name | Value | -+----------------------+-------------+ -| collation_connection | utf8mb4_bin | -+----------------------+-------------+ -``` - -```sql -SELECT LOCATE('bar', 'foobarbar'); -+----------------------------+ -| LOCATE('bar', 'foobarbar') | -+----------------------------+ -| 4 | -+----------------------------+ -``` - -```sql -SELECT LOCATE('baz', 'foobarbar'); -+----------------------------+ -| LOCATE('baz', 'foobarbar') | -+----------------------------+ -| 0 | -+----------------------------+ -``` - -```sql -SELECT LOCATE('bar', 'fooBARBAR'); -+----------------------------+ -| LOCATE('bar', 'fooBARBAR') | -+----------------------------+ -| 0 | -+----------------------------+ -``` - -```sql -SELECT LOCATE('bar', 'foobarBAR', 100); -+---------------------------------+ -| LOCATE('bar', 'foobarBAR', 100) | -+---------------------------------+ -| 0 | -+---------------------------------+ -``` - -```sql -SELECT LOCATE('bar', 'foobarbar', 5); -+-------------------------------+ -| LOCATE('bar', 'foobarbar', 5) | -+-------------------------------+ -| 7 | -+-------------------------------+ -``` - -```sql -SELECT LOCATE('bar', NULL); -+---------------------+ -| LOCATE('bar', NULL) | -+---------------------+ -| NULL | -+---------------------+ -``` - -```sql -SELECT LOCATE('DB', 'TiDB tidb 数据库'); -+-------------------------------------+ -| LOCATE('DB', 'TiDB tidb 数据库') | -+-------------------------------------+ -| 3 | -+-------------------------------------+ -``` - -```sql -SELECT LOCATE('DB', 'TiDB tidb 数据库', 4); -+----------------------------------------+ -| LOCATE('DB', 'TiDB tidb 数据库', 4) | -+----------------------------------------+ -| 0 | -+----------------------------------------+ -``` - -以下示例使用 `utf8mb4_unicode_ci` 排序规则: - -```sql -SET collation_connection='utf8mb4_unicode_ci'; -SHOW VARIABLES LIKE 'collation_connection'; -+----------------------+--------------------+ -| Variable_name | Value | -+----------------------+--------------------+ -| collation_connection | utf8mb4_unicode_ci | -+----------------------+--------------------+ -``` - -```sql -SELECT LOCATE('DB', 'TiDB tidb 数据库', 4); -+----------------------------------------+ -| LOCATE('DB', 'TiDB tidb 数据库', 4) | -+----------------------------------------+ -| 8 | -+----------------------------------------+ -``` - -```sql -SELECT LOCATE('🍺', '🍣🍣🍣🍺🍺'); -+----------------------------------------+ -| LOCATE('🍺', '🍣🍣🍣🍺🍺') | -+----------------------------------------+ -| 1 | -+----------------------------------------+ -``` - -以下多字节和二进制字符串示例使用 `utf8mb4_bin` 排序规则: - -```sql -SET collation_connection='utf8mb4_bin'; -SHOW VARIABLES LIKE 'collation_connection'; -+----------------------+-------------+ -| Variable_name | Value | -+----------------------+-------------+ -| collation_connection | utf8mb4_bin | -+----------------------+-------------+ -``` - -```sql -SELECT LOCATE('🍺', '🍣🍣🍣🍺🍺'); -+----------------------------------------+ -| LOCATE('🍺', '🍣🍣🍣🍺🍺') | -+----------------------------------------+ -| 4 | -+----------------------------------------+ -``` - -```sql -SELECT LOCATE('b', _binary'aBcde'); -+-----------------------------+ -| LOCATE('b', _binary'aBcde') | -+-----------------------------+ -| 0 | -+-----------------------------+ -``` - -```sql -SELECT LOCATE('B', _binary'aBcde'); -+-----------------------------+ -| LOCATE('B', _binary'aBcde') | -+-----------------------------+ -| 2 | -+-----------------------------+ -``` - -```sql -SELECT LOCATE(_binary'b', 'aBcde'); -+-----------------------------+ -| LOCATE(_binary'b', 'aBcde') | -+-----------------------------+ -| 0 | -+-----------------------------+ -``` - -```sql -SELECT LOCATE(_binary'B', 'aBcde'); -+-----------------------------+ -| LOCATE(_binary'B', 'aBcde') | -+-----------------------------+ -| 2 | -+-----------------------------+ -``` - -### [`LOWER()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_lower) - -`LOWER(str)` 函数用于将输入的参数 `str` 中的所有字符转换为小写。该参数可以为字符串或数字。 - -- 如果输入参数为字符串,该函数返回字符串的小写形式。 -- 如果输入参数为数字,该函数将会去掉该数字中的前导零。 -- 如果输入参数为 `NULL`,该函数返回 `NULL`。 - -示例: - -```sql -SELECT LOWER("TiDB"); - -+---------------+ -| LOWER("TiDB") | -+---------------+ -| tidb | -+---------------+ -``` - -```sql -SELECT LOWER(-012); - -+-------------+ -| LOWER(-012) | -+-------------+ -| -12 | -+-------------+ -``` - -### [`LPAD()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_lpad) - -`LPAD(str, len, padstr)` 函数返回字符串参数,左侧填充指定字符串 `padstr`,直到字符串长度达到 `len` 个字符。 - -- 如果 `len` 小于字符串 `str` 的长度,函数将字符串 `str` 截断到长度 `len`。 -- 如果 `len` 为负数,函数返回 `NULL`。 -- 如果任一参数为 `NULL`,该函数返回 `NULL`。 - -示例: - -```sql -SELECT LPAD('TiDB',8,'>'); -+--------------------+ -| LPAD('TiDB',8,'>') | -+--------------------+ -| >>>>TiDB | -+--------------------+ -1 row in set (0.00 sec) -``` - -```sql -SELECT LPAD('TiDB',2,'>'); -+--------------------+ -| LPAD('TiDB',2,'>') | -+--------------------+ -| Ti | -+--------------------+ -1 row in set (0.00 sec) -``` - -```sql -SELECT LPAD('TiDB',-2,'>'); -+---------------------+ -| LPAD('TiDB',-2,'>') | -+---------------------+ -| NULL | -+---------------------+ -1 row in set (0.00 sec) -``` - -### [`LTRIM()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ltrim) - -`LTRIM()` 函数用于删除给定的字符串中的前导空格(即字符串开头的连续空格)。 - -如果输入的参数为 `NULL`,该函数将返回 `NULL`。 - -> **注意:** -> -> 该函数只去掉空格字符(U+0020),不去掉其他类似空格的字符,如制表符(U+0009)或非分隔符(U+00A0)。 - -示例: - -在以下示例中,`LTRIM()` 函数删除了 `' hello'` 中的前导空格,并返回 `hello`。 - -```sql -SELECT LTRIM(' hello'); -``` - -``` -+--------------------+ -| LTRIM(' hello') | -+--------------------+ -| hello | -+--------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,[`CONCAT()`](#concat) 用于将 `LTRIM(' hello')` 的结果用 `«` 和 `»` 包裹起来。通过这种格式,可以更容易地看到所有前导空格都被删除了。 - -```sql -SELECT CONCAT('«',LTRIM(' hello'),'»'); -``` - -``` -+------------------------------------+ -| CONCAT('«',LTRIM(' hello'),'»') | -+------------------------------------+ -| «hello» | -+------------------------------------+ -1 row in set (0.00 sec) -``` - -### [`MAKE_SET()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_make-set) - -`MAKE_SET()` 函数根据输入的 `bits` 参数中相应的 bit 是否为 `1` 返回一组由逗号分隔的字符串。 - -语法: - -```sql -MAKE_SET(bits, str1, str2, ...) -``` - -- `bits`:控制其后的字符串参数中的哪些参数会包含到输出结果中。如果 `bits` 为 `NULL`,该函数将返回 `NULL`。 -- `str1, str2, ...`:字符串参数列表。每个字符串与 `bits` 参数中从右到左的一个 bit 依次对应。`str1` 对应于 `bits` 中从右起的第一个 bit,`str2` 对应于从右起的第二个 bit,依此类推。如果相应的 bit 为 `1`,则该字符串将包含在输出结果中;否则,将不包含在输出结果中。 - -示例: - -在以下示例中,因为 `bits` 参数中的所有 bit 都为 `0`,该函数将不会在结果中包含 `bits` 后的任何字符串参数,因此返回空字符串。 - -```sql -SELECT MAKE_SET(b'000','foo','bar','baz'); -``` - -``` -+------------------------------------+ -| MAKE_SET(b'000','foo','bar','baz') | -+------------------------------------+ -| | -+------------------------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,因为只有从右起的第一个 bit 为 `1`,该函数只返回第一个字符串 `foo`。 - -```sql -SELECT MAKE_SET(b'001','foo','bar','baz'); -``` - -``` -+------------------------------------+ -| MAKE_SET(b'001','foo','bar','baz') | -+------------------------------------+ -| foo | -+------------------------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,因为只有从右起的第二个 bit 为 `1`,该函数只返回第二个字符串 `bar`。 - -```sql -SELECT MAKE_SET(b'010','foo','bar','baz'); -``` - -``` -+------------------------------------+ -| MAKE_SET(b'010','foo','bar','baz') | -+------------------------------------+ -| bar | -+------------------------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,因为只有从右起的第三个 bit 为 `1`,该函数只返回第三个字符串 `baz`。 - -```sql -SELECT MAKE_SET(b'100','foo','bar','baz'); -``` - -``` -+------------------------------------+ -| MAKE_SET(b'100','foo','bar','baz') | -+------------------------------------+ -| baz | -+------------------------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,因为所有 bit 都为 `1`,该函数将返回全部的三个字符串,并以逗号分隔。 - -```sql -SELECT MAKE_SET(b'111','foo','bar','baz'); -``` - -``` -+------------------------------------+ -| MAKE_SET(b'111','foo','bar','baz') | -+------------------------------------+ -| foo,bar,baz | -+------------------------------------+ -1 row in set (0.0002 sec) -``` - -### [`MID()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_mid) - -`MID(str,pos,len)` 函数返回从指定的 `pos` 位置开始的长度为 `len` 的子字符串。 - -如果任一参数为 `NULL`,该函数将返回 `NULL`。 - -TiDB 不支持该函数的两参数版本。更多信息,请参见 [#52420](https://github.com/pingcap/tidb/issues/52420)。 - -示例: - -在以下示例中,`MID()` 返回给定的字符串中从第二个字符 (`b`) 开始的长度为 `3` 个字符的的子字符串。 - -```sql -SELECT MID('abcdef',2,3); -``` - -``` -+-------------------+ -| MID('abcdef',2,3) | -+-------------------+ -| bcd | -+-------------------+ -1 row in set (0.00 sec) -``` - -### [`NOT LIKE`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like) - -否定简单模式匹配。 - -该函数的功能与 [`LIKE`](#like) 函数相反。 - -示例: - -在以下示例中,因为 `aaa` 匹配 `a%` 模式,`NOT LIKE` 返回 `0`(代表结果为 False)。 - -```sql -SELECT 'aaa' LIKE 'a%', 'aaa' NOT LIKE 'a%'; -``` - -``` -+-----------------+---------------------+ -| 'aaa' LIKE 'a%' | 'aaa' NOT LIKE 'a%' | -+-----------------+---------------------+ -| 1 | 0 | -+-----------------+---------------------+ -1 row in set (0.00 sec) -``` - -在以下示例中,因为 `aaa` 与 `b%` 模式不匹配,`NOT LIKE` 返回 `1`(代表结果为 True)。 - -```sql -SELECT 'aaa' LIKE 'b%', 'aaa' NOT LIKE 'b%'; -``` - -``` -+-----------------+---------------------+ -| 'aaa' LIKE 'b%' | 'aaa' NOT LIKE 'b%' | -+-----------------+---------------------+ -| 0 | 1 | -+-----------------+---------------------+ -1 row in set (0.00 sec) -``` - -### [`NOT REGEXP`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_not-regexp) - -[`REGEXP`](#regexp) 的否定形式 - -### [`OCT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_oct) - -`OCT()` 函数用于返回一个数值的[八进制](https://zh.wikipedia.org/wiki/八进制)表示,形式为字符串。 - -示例: - -以下示例使用[递归的公共表表达式 (CTE)](/develop/dev-guide-use-common-table-expression.md#递归的-cte) 生成从 0 到 20 的数字序列,然后使用 `OCT()` 函数将每个数字转换为其八进制表示。从 0 到 7 的十进制数在八进制中有相同的表示,从 8 到 15 的十进制数对应从 10 到 17 的八进制数。 - -```sql -WITH RECURSIVE nr(n) AS ( - SELECT 0 AS n - UNION ALL - SELECT n+1 FROM nr WHERE n<20 -) -SELECT n, OCT(n) FROM nr; -``` - -``` -+------+--------+ -| n | OCT(n) | -+------+--------+ -| 0 | 0 | -| 1 | 1 | -| 2 | 2 | -| 3 | 3 | -| 4 | 4 | -| 5 | 5 | -| 6 | 6 | -| 7 | 7 | -| 8 | 10 | -| 9 | 11 | -| 10 | 12 | -| 11 | 13 | -| 12 | 14 | -| 13 | 15 | -| 14 | 16 | -| 15 | 17 | -| 16 | 20 | -| 17 | 21 | -| 18 | 22 | -| 19 | 23 | -| 20 | 24 | -+------+--------+ -20 rows in set (0.00 sec) -``` - -### [`OCTET_LENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_octet-length) - -与 [`LENGTH()`](#length) 功能相同 - -### [`ORD()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ord) - -返回给定的参数中最左侧字符的字符编码。 - -该函数的功能类似于 [`CHAR()`](#char),但处理方式相反。 - -示例: - -以 `a` 和 `A` 为例,`ORD()` 返回 `a` 的字符代码 `97` 和 `A` 的字符代码 `65`。 - -```sql -SELECT ORD('a'), ORD('A'); -``` - -``` -+----------+----------+ -| ORD('a') | ORD('A') | -+----------+----------+ -| 97 | 65 | -+----------+----------+ -1 row in set (0.00 sec) -``` - -如果将从 `ORD()` 获得的字符代码作为 `CHAR()` 函数的输入,即可获取原始字符。请注意,以下输出的格式可能会根据你的 MySQL 客户端是否启用了 `binary-as-hex` 选项而有所不同。 - -```sql -SELECT CHAR(97), CHAR(65); -``` - -``` -+----------+----------+ -| CHAR(97) | CHAR(65) | -+----------+----------+ -| a | A | -+----------+----------+ -1 row in set (0.01 sec) -``` - -以下示例展示了 `ORD()` 如何处理多字节字符。`101` 和 `0x65` 都是 `e` 字符的 UTF-8 编码值,但格式不同。`50091` 和 `0xC3AB` 也表示的是相同的值,但对应 `ë` 字符。 - -```sql -SELECT ORD('e'), ORD('ë'), HEX('e'), HEX('ë'); -``` - -``` -+----------+-----------+----------+-----------+ -| ORD('e') | ORD('ë') | HEX('e') | HEX('ë') | -+----------+-----------+----------+-----------+ -| 101 | 50091 | 65 | C3AB | -+----------+-----------+----------+-----------+ -1 row in set (0.00 sec) -``` - -### [`POSITION()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_position) - -与 [`LOCATE()`](#locate) 功能相同 - -### [`QUOTE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_quote) - -`QUOTE()` 函数用于转义字符串,使其可以在 SQL 语句中使用。 - -如果输入参数为 `NULL`,该函数返回 `NULL`。 - -示例: - -为了直接显示查询结果,而不是以十六进制编码的形式展示,你需要使用 [`--skip-binary-as-hex`](https://dev.mysql.com/doc/refman/8.0/en/mysql-command-options.html#option_mysql_binary-as-hex) 选项启动 MySQL 客户端。 - -以下示例显示了 ASCII NULL 字符被转义为 `\0`,单引号字符 `'` 被转义为 `\'`: - -```sql -SELECT QUOTE(0x002774657374); -``` - -``` -+-----------------------+ -| QUOTE(0x002774657374) | -+-----------------------+ -| '\0\'test' | -+-----------------------+ -1 row in set (0.00 sec) -``` - -### [`REGEXP`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp) - -使用正则表达式匹配模式 - -示例: - -下面示例使用了两个正则表达式来匹配一些字符串。 - -```sql -WITH vals AS ( - SELECT 'TiDB' AS v - UNION ALL - SELECT 'Titanium' - UNION ALL - SELECT 'Tungsten' - UNION ALL - SELECT 'Rust' -) -SELECT - v, - v REGEXP '^Ti' AS 'starts with "Ti"', - v REGEXP '^.{4}$' AS 'Length is 4 characters' -FROM - vals; -``` - -``` -+----------+------------------+------------------------+ -| v | starts with "Ti" | Length is 4 characters | -+----------+------------------+------------------------+ -| TiDB | 1 | 1 | -| Titanium | 1 | 0 | -| Tungsten | 0 | 0 | -| Rust | 0 | 1 | -+----------+------------------+------------------------+ -4 rows in set (0.00 sec) -``` - -`REGEXP` 并不限于只在 `SELECT` 子句中使用。例如,`REGEXP` 还可以用于查询的 `WHERE` 子句中。 - -```sql -SELECT - v -FROM ( - SELECT 'TiDB' AS v - ) AS vals -WHERE - v REGEXP 'DB$'; -``` - -``` -+------+ -| v | -+------+ -| TiDB | -+------+ -1 row in set (0.01 sec) -``` - -### [`REGEXP_INSTR()`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-instr) - -返回满足正则的子字符串的第一个索引位置(与 MySQL 不完全兼容,具体请参考[正则函数与 MySQL 的兼容性](#正则函数与-mysql-的兼容性)) - -`REGEXP_INSTR(str, regexp, [start, [match, [ret, [match_type]]]])` 函数返回正则表达式(`regexp`)匹配字符串(`str`)的位置。 - -如果 `str` 或 `regexp` 为 `NULL`,则该函数返回 `NULL`。 - -示例: - -下面示例展示了 `^.b.$` 匹配 `abc` 的情况。 - -```sql -SELECT REGEXP_INSTR('abc','^.b.$'); -``` - -``` -+-----------------------------+ -| REGEXP_INSTR('abc','^.b.$') | -+-----------------------------+ -| 1 | -+-----------------------------+ -1 row in set (0.00 sec) -``` - -下面示例展示了使用第三个参数来从字符串的指定位置起查找匹配值的情况。 - -```sql -SELECT REGEXP_INSTR('abcabc','a'); -``` - -``` -+----------------------------+ -| REGEXP_INSTR('abcabc','a') | -+----------------------------+ -| 1 | -+----------------------------+ -1 row in set (0.00 sec) -``` - -```sql -SELECT REGEXP_INSTR('abcabc','a',2); -``` - -``` -+------------------------------+ -| REGEXP_INSTR('abcabc','a',2) | -+------------------------------+ -| 4 | -+------------------------------+ -1 row in set (0.00 sec) -``` - -下面示例展示了使用第四个参数来查找第二个匹配值的情况。 - -```sql -SELECT REGEXP_INSTR('abcabc','a',1,2); -``` - -``` -+--------------------------------+ -| REGEXP_INSTR('abcabc','a',1,2) | -+--------------------------------+ -| 4 | -+--------------------------------+ -1 row in set (0.00 sec) -``` - -下面示例展示了使用第五个参数来返回匹配值后面的那个值的位置,而不是返回匹配值的位置。 - -```sql -SELECT REGEXP_INSTR('abcabc','a',1,1,1); -``` - -``` -+----------------------------------+ -| REGEXP_INSTR('abcabc','a',1,1,1) | -+----------------------------------+ -| 2 | -+----------------------------------+ -1 row in set (0.00 sec) -``` - -下面示例展示了使用第六个参数来添加 `i` 标志以获得不区分大小写的匹配。有关正则表达式 `match_type` 的更多详细信息,请参阅 [`match_type` 兼容性](#匹配模式-match_type-兼容性)。 - -```sql -SELECT REGEXP_INSTR('abcabc','A',1,1,0,''); -``` - -``` -+-------------------------------------+ -| REGEXP_INSTR('abcabc','A',1,1,0,'') | -+-------------------------------------+ -| 0 | -+-------------------------------------+ -1 row in set (0.00 sec) -``` - -```sql -SELECT REGEXP_INSTR('abcabc','A',1,1,0,'i'); -``` - -``` -+--------------------------------------+ -| REGEXP_INSTR('abcabc','A',1,1,0,'i') | -+--------------------------------------+ -| 1 | -+--------------------------------------+ -1 row in set (0.00 sec) -``` - -除了 `match_type`,[排序规则](/character-set-and-collation.md) 也会影响匹配。在下面的示例中,使用了区分大小写和不区分大小写的排序规则来展示这种影响。 - -```sql -SELECT REGEXP_INSTR('abcabc','A' COLLATE utf8mb4_general_ci); -``` - -``` -+-------------------------------------------------------+ -| REGEXP_INSTR('abcabc','A' COLLATE utf8mb4_general_ci) | -+-------------------------------------------------------+ -| 1 | -+-------------------------------------------------------+ -1 row in set (0.01 sec) -``` - -```sql -SELECT REGEXP_INSTR('abcabc','A' COLLATE utf8mb4_bin); -``` - -``` -+------------------------------------------------+ -| REGEXP_INSTR('abcabc','A' COLLATE utf8mb4_bin) | -+------------------------------------------------+ -| 0 | -+------------------------------------------------+ -1 row in set (0.00 sec) -``` - -### [`REGEXP_LIKE()`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-like) - -判断字符串是否满足正则表达式(与 MySQL 不完全兼容,具体请参考[正则函数与 MySQL 的兼容性](#正则函数与-mysql-的兼容性)) - -`REGEXP_LIKE(str, regex, [match_type])` 函数用于判断正则表达式是否匹配字符串。可选的 `match_type` 参数可以用于更改匹配行为。 - -示例: - -下面示例展示了 `^a` 匹配 `abc` 的情况。 - -```sql -SELECT REGEXP_LIKE('abc','^a'); -``` - -``` -+-------------------------+ -| REGEXP_LIKE('abc','^a') | -+-------------------------+ -| 1 | -+-------------------------+ -1 row in set (0.00 sec) -``` - -下面示例展示了 `^A` 不匹配 `abc` 的情况。 - -```sql -SELECT REGEXP_LIKE('abc','^A'); -``` - -``` -+-------------------------+ -| REGEXP_LIKE('abc','^A') | -+-------------------------+ -| 0 | -+-------------------------+ -1 row in set (0.00 sec) -``` - -下面示例展示了 `^A` 匹配 `abc` 的情况,因为 `i` 标志启用了不区分大小写的匹配,所以能够匹配上。关于正则表达式 `match_type` 的更多详细信息,请参阅 [`match_type` 兼容性](#匹配模式-match_type-兼容性)。 - -```sql -SELECT REGEXP_LIKE('abc','^A','i'); -``` - -``` -+-----------------------------+ -| REGEXP_LIKE('abc','^A','i') | -+-----------------------------+ -| 1 | -+-----------------------------+ -1 row in set (0.00 sec) -``` - -### [`REGEXP_REPLACE()`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-replace) - -替换满足正则表达式的子字符串(与 MySQL 不完全兼容,具体请参考[正则函数与 MySQL 的兼容性](#正则函数与-mysql-的兼容性)) - -`REGEXP_REPLACE(str, regexp, replace, [start, [match, [match_type]]])` 函数可以用于基于正则表达式替换字符串。 - -示例: - -下面的示例中,两个 `o` 被替换为 `i`。 - -```sql -SELECT REGEXP_REPLACE('TooDB', 'o{2}', 'i'); -``` - -``` -+--------------------------------------+ -| REGEXP_REPLACE('TooDB', 'o{2}', 'i') | -+--------------------------------------+ -| TiDB | -+--------------------------------------+ -1 row in set (0.00 sec) -``` - -下面示例从第三个字符开始匹配,导致正则表达式不匹配,不进行任何替换。 - -```sql -SELECT REGEXP_REPLACE('TooDB', 'o{2}', 'i',3); -``` - -``` -+----------------------------------------+ -| REGEXP_REPLACE('TooDB', 'o{2}', 'i',3) | -+----------------------------------------+ -| TooDB | -+----------------------------------------+ -1 row in set (0.00 sec) -``` - -下面示例中,第五个参数用于设置替换第一个或第二个匹配的值。 - -```sql -SELECT REGEXP_REPLACE('TooDB', 'o', 'i',1,1); -``` - -``` -+---------------------------------------+ -| REGEXP_REPLACE('TooDB', 'o', 'i',1,1) | -+---------------------------------------+ -| TioDB | -+---------------------------------------+ -1 row in set (0.00 sec) -``` - -```sql -SELECT REGEXP_REPLACE('TooDB', 'o', 'i',1,2); -``` - -``` -+---------------------------------------+ -| REGEXP_REPLACE('TooDB', 'o', 'i',1,2) | -+---------------------------------------+ -| ToiDB | -+---------------------------------------+ -1 row in set (0.00 sec) -``` - -下面示例中,第六个参数用于设置 `match_type` 为不区分大小写的匹配。更多关于正则表达式 `match_type` 的详细信息,请参阅 [`match_type` 兼容性](#匹配模式-match_type-兼容性)。 - -```sql -SELECT REGEXP_REPLACE('TooDB', 'O{2}','i',1,1); -``` - -``` -+-----------------------------------------+ -| REGEXP_REPLACE('TooDB', 'O{2}','i',1,1) | -+-----------------------------------------+ -| TooDB | -+-----------------------------------------+ -1 row in set (0.00 sec) -``` - -```sql -SELECT REGEXP_REPLACE('TooDB', 'O{2}','i',1,1,'i'); -``` - -``` -+---------------------------------------------+ -| REGEXP_REPLACE('TooDB', 'O{2}','i',1,1,'i') | -+---------------------------------------------+ -| TiDB | -+---------------------------------------------+ -1 row in set (0.00 sec) -``` - -### [`REGEXP_SUBSTR()`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-substr) - -返回满足正则表达式的子字符串(与 MySQL 不完全兼容,具体请参考[正则函数与 MySQL 的兼容性](#正则函数与-mysql-的兼容性)) - -`REGEXP_SUBSTR(str, regexp, [start, [match, [match_type]]])` 函数用于基于正则表达式获取子字符串。 - -下面示例使用 `Ti.{2}` 正则表达式从 `This is TiDB` 字符串中获取 `TiDB` 子字符串。 - -```sql -SELECT REGEXP_SUBSTR('This is TiDB','Ti.{2}'); -``` - -``` -+----------------------------------------+ -| REGEXP_SUBSTR('This is TiDB','Ti.{2}') | -+----------------------------------------+ -| TiDB | -+----------------------------------------+ -1 row in set (0.00 sec) -``` - -### [`REPEAT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_repeat) - -`REPEAT()` 函数用于以指定次数重复一个字符串。 - -示例: - -以下示例使用[递归的公共表表达式 (CTE)](/develop/dev-guide-use-common-table-expression.md#递归的-cte) 生成从 1 到 20 的数字序列,并使用 `REPEAT()` 函数重复对应次数的 `x` 字符串: - -```sql -WITH RECURSIVE nr(n) AS ( - SELECT 1 AS n - UNION ALL - SELECT n+1 FROM nr WHERE n<20 -) -SELECT n, REPEAT('x',n) FROM nr; -``` - -``` -+------+----------------------+ -| n | REPEAT('x',n) | -+------+----------------------+ -| 1 | x | -| 2 | xx | -| 3 | xxx | -| 4 | xxxx | -| 5 | xxxxx | -| 6 | xxxxxx | -| 7 | xxxxxxx | -| 8 | xxxxxxxx | -| 9 | xxxxxxxxx | -| 10 | xxxxxxxxxx | -| 11 | xxxxxxxxxxx | -| 12 | xxxxxxxxxxxx | -| 13 | xxxxxxxxxxxxx | -| 14 | xxxxxxxxxxxxxx | -| 15 | xxxxxxxxxxxxxxx | -| 16 | xxxxxxxxxxxxxxxx | -| 17 | xxxxxxxxxxxxxxxxx | -| 18 | xxxxxxxxxxxxxxxxxx | -| 19 | xxxxxxxxxxxxxxxxxxx | -| 20 | xxxxxxxxxxxxxxxxxxxx | -+------+----------------------+ -20 rows in set (0.01 sec) -``` - -以下示例演示了 `REPEAT()` 可以处理包含多个字符的字符串: - -```sql -SELECT REPEAT('ha',3); -``` - -``` -+----------------+ -| REPEAT('ha',3) | -+----------------+ -| hahaha | -+----------------+ -1 row in set (0.00 sec) -``` - -### [`REPLACE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_replace) - -替换所有出现的指定字符串 - -### [`REVERSE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_reverse) - -反转字符串里的所有字符 - -### [`RIGHT()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_right) - -返回指定数量的最右侧的字符 - -### [`RLIKE`](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp) - -与 [`REGEXP`](#regexp) 功能相同 - -### [`RPAD()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_rpad) - -以指定次数添加字符串 - -### [`RTRIM()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_rtrim) - -去掉后缀空格 - -### [`SPACE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_space) - -返回指定数量的空格,形式为字符串 - -### [`STRCMP()`](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp) - -比较两个字符串 - -### [`SUBSTR()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substr) - -返回指定的子字符串 - -### [`SUBSTRING()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substring) - -返回指定的子字符串 - -### [`SUBSTRING_INDEX()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substring-index) - -`SUBSTRING_INDEX()` 函数用于按照指定的分隔符和次数从字符串中提取子字符串。该函数在处理以特定分隔符分隔的数据时特别有用,例如解析 CSV 数据或处理日志文件。 - -语法: - -```sql -SUBSTRING_INDEX(str, delim, count) -``` - -- `str`:要处理的字符串。 -- `delim`:指定字符串中的分隔符,大小写敏感。 -- `count`:指定分隔符出现的次数。 - - 如果 `count` 为正数,该函数返回从字符串左边开始的第 `count` 个分隔符之前的子字符串。 - - 如果 `count` 为负数,该函数返回从字符串右边开始的第 `count` 个分隔符之后的子字符串。 - - 如果 `count` 为 `0`,该函数返回一个空字符串。 - -查询示例 1: - -```sql -SELECT SUBSTRING_INDEX('www.tidbcloud.com', '.', 2); -``` - -返回结果 1: - -```sql -+-----------------------------------------+ -| SUBSTRING_INDEX('www.tidbcloud.com', '.', 2) | -+-----------------------------------------+ -| www.tidbcloud | -+-----------------------------------------+ -``` - -查询示例 2: - -```sql -SELECT SUBSTRING_INDEX('www.tidbcloud.com', '.', -1); -``` - -返回结果 2: - -```sql -+------------------------------------------+ -| SUBSTRING_INDEX('www.tidbcloud.com', '.', -1) | -+------------------------------------------+ -| com | -+------------------------------------------+ -``` - -### [`TO_BASE64()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_to-base64) - -`TO_BASE64()` 函数用于将输入的参数转换为 base-64 编码形式的字符串,并按照当前连接的字符集和排序规则返回结果。base-64 编码的字符串可以使用 [`FROM_BASE64()`](#from_base64) 函数进行解码。 - -语法: - -```sql -TO_BASE64(str) -``` - -- 如果输入参数不是字符串,该函数会将其转换为字符串后再进行 base-64 编码。 -- 如果输入参数为 `NULL`,该函数返回 `NULL`。 - -查询示例 1: - -```sql -SELECT TO_BASE64('abc'); -``` - -返回结果 1: - -```sql -+------------------+ -| TO_BASE64('abc') | -+------------------+ -| YWJj | -+------------------+ -``` - -查询示例 2: - -```sql -SELECT TO_BASE64(6); -``` - -返回结果 2: - -```sql -+--------------+ -| TO_BASE64(6) | -+--------------+ -| Ng== | -+--------------+ -``` - -### [`TRANSLATE()`](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/TRANSLATE.html#GUID-80F85ACB-092C-4CC7-91F6-B3A585E3A690) - -将字符串中出现的所有指定字符替换为其它字符。这个函数不会像 Oracle 一样将空字符串视为`NULL` - -### [`TRIM()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_trim) - -去掉前缀和后缀空格 - -### [`UCASE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ucase) - -`UCASE()` 函数将字符串转换为大写字母,此函数等价于 `UPPER()` 函数。 - -> **注意:** -> -> 当字符串为 null 时,则返回 `NULL`。 - -查询示例: - -```sql -SELECT UCASE('bigdata') AS result_upper, UCASE(null) AS result_null; -``` - -返回结果: - -```sql -+--------------+-------------+ -| result_upper | result_null | -+--------------+-------------+ -| BIGDATA | NULL | -+--------------+-------------+ -``` - -### [`UNHEX()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_unhex) - -`UNHEX()` 函数执行 `HEX()` 函数的逆运算,将参数中的每对字符视为十六进制数字,并将其转换为该数字表示的字符,返回值为二进制字符串。 - -> **注意:** -> -> - 传入的字符串必须是合法的十六进制数值,包含 `0~9`、`A~F`、`a~f`,如果为 `NULL` 或超出该范围,则返回 `NULL`。 -> - 在 MySQL 客户端中,[`--binary-as-hex`](https://dev.mysql.com/doc/refman/8.0/en/mysql-command-options.html#option_mysql_binary-as-hex) 选项在交互模式下默认启用,这会导致客户端将无法识别的字符集数据显示为[十六进制字面量 (Hexadecimal literal)](https://dev.mysql.com/doc/refman/8.0/en/hexadecimal-literals.html)。你可以使用 `--skip-binary-as-hex` 选项来禁用此行为。 - -查询示例: - -```sql -SELECT UNHEX('54694442'); -``` - -返回结果: - -```sql -+--------------------------------------+ -| UNHEX('54694442') | -+--------------------------------------+ -| 0x54694442 | -+--------------------------------------+ -``` - -### [`UPPER()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_upper) - -`UPPER()` 函数将字符串转换为大写字母,此函数等价于 `UCASE()` 函数。 - -> **注意:** -> -> 当字符串为 null 时,则返回 `NULL`。 - -查询示例: - -```sql -SELECT UPPER('bigdata') AS result_upper, UPPER(null) AS result_null; -``` - -返回结果: - -```sql -+--------------+-------------+ -| result_upper | result_null | -+--------------+-------------+ -| BIGDATA | NULL | -+--------------+-------------+ -``` - -### [`WEIGHT_STRING()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_weight-string) - -`WEIGHT_STRING()` 函数返回字符串的权重(二进制字符),主要用于多字符集场景下的排序和比较操作。如果参数为 `NULL`,则返回 `NULL`。语法示例如下: - -```sql -WEIGHT_STRING(str [AS {CHAR|BINARY}(N)]) -``` - -* `str`:字符串表达式。如果是非二进制字符串,例如 CHAR、VARCHAR 或 TEXT 值,则返回值包含该字符串的排序规则权重;如果是二进制字符串,例如 BINARY、VARBINARY 或 BLOB 值,则返回值与输入相同。 -* `AS {CHAR|BINARY}(N)`:可选参数,用于指定输出结果的类型和长度。`CHAR` 表示字符数据类型,而 `BINARY` 表示二进制数据类型;`N` 指定输出的长度,取值为大于等于 1 的整数。 - -> **注意:** -> -> 当 `N` 小于字符串长度时,字符串将被截断;当 `N` 超过字符串长度时,`CHAR` 类型将用空格来填充以达到指定长度,`BINARY` 类型将以 `0x00` 来填充以达到指定长度。 - -查询示例: - -```sql -SET NAMES 'utf8mb4'; -SELECT HEX(WEIGHT_STRING('ab' AS CHAR(3))) AS char_result, HEX(WEIGHT_STRING('ab' AS BINARY(3))) AS binary_result; -``` - -返回结果: - -```sql -+-------------+---------------+ -| char_result | binary_result | -+-------------+---------------+ -| 6162 | 616200 | -+-------------+---------------+ -``` - -## 不支持的函数 - -* `LOAD_FILE()` -* `MATCH()` -* `SOUNDEX()` - -## 正则函数与 MySQL 的兼容性 - -本节介绍 TiDB 中正则函数 `REGEXP_INSTR()`、`REGEXP_LIKE()`、`REGEXP_REPLACE()`、`REGEXP_SUBSTR()` 与 MySQL 的兼容情况。 - -### 语法兼容性 - -MySQL 的实现使用的是 [ICU](https://github.com/unicode-org/icu) (International Components for Unicode) 库,TiDB 的实现使用的是 [RE2](https://github.com/google/re2) 库,两个库之间的语法差异可以查阅 [ICU 文档](https://unicode-org.github.io/icu/userguide/)和 [RE2 文档](https://github.com/google/re2/wiki/Syntax)。 - -### 匹配模式 `match_type` 兼容性 - -TiDB 与 MySQL 在 `match_type` 上的差异: - -- TiDB 中 `match_type` 可选值为:`"c"`、`"i"`、`"m"`、`"s"`。MySQL 中 `match_type` 可选值为:`"c"`、`"i"`、`"m"`、`"n"`、`"u"`。 -- TiDB 中 `"s"` 对应 MySQL 中的 `"n"`,即 `.` 字符匹配行结束符。 - - 例如:MySQL 中 `SELECT REGEXP_LIKE(a, b, "n") FROM t1;` 在 TiDB 中需要修改为 `SELECT REGEXP_LIKE(a, b, "s") FROM t1;`。 - -- TiDB 不支持 `match_type` 为 `"u"`。 - -| `match_type` | MySQL | TiDB | 描述 | -|:------------:|-------|------|----------------------------------------| -| c | Yes | Yes | 大小写敏感匹配 | -| i | Yes | Yes | 大小写不敏感匹配 | -| m | Yes | Yes | 匹配多行文本的模式 | -| s | No | Yes | 匹配新行,和 MySQL 中的 `n` 相同 | -| n | Yes | No | 匹配新行,和 TiDB 中的 `s` 相同 | -| u | Yes | No | UNIX&trade 换行符 | - -### 数据类型兼容性 - -TiDB 与 MySQL 在二进制字符串 (binary string) 数据类型上的差异: - -- MySQL 8.0.22 及以上版本中正则函数不支持二进制字符串,具体信息可查看 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/regexp.html)。但在实际使用过程中,如果所有参数或者返回值的数据类型都是二进制字符串,则正则函数可以正常使用,否则报错。 -- TiDB 目前完全禁止使用二进制字符串,无论什么情况都会报错。 - -### 其它兼容性 - -- TiDB 与 MySQL 在替换空字符串上存在差异,下面以 `REGEXP_REPLACE("", "^$", "123")` 为例: - - - MySQL 不会对空串进行替换,其结果为 `""`。 - - TiDB 会对空串进行替换,其结果为 `"123"`。 - -- TiDB 与 MySQL 在捕获组的关键字上存在差异。MySQL 的捕获组关键字为`$`,而 TiDB 的捕获组关键字为`\\`。此外,TiDB 只支持编号为 `0` 到 `9` 的捕获组。 - - 例如,以下 SQL 语句在 TiDB 中的返回结果为 `ab`。 - - ```sql - SELECT REGEXP_REPLACE('abcd','(.*)(.{2})$','\\1') AS s; - ``` - -### 已知问题 - -- [GitHub Issue #37981](https://github.com/pingcap/tidb/issues/37981) \ No newline at end of file diff --git a/functions-and-operators/tidb-functions.md b/functions-and-operators/tidb-functions.md index da3539ea55a4..0844263c7948 100644 --- a/functions-and-operators/tidb-functions.md +++ b/functions-and-operators/tidb-functions.md @@ -1,39 +1,65 @@ --- -title: TiDB 特有的函数 -summary: 学习使用 TiDB 特有的函数。 +title: TiDB 特有函数 +summary: 了解 TiDB 特有函数的使用方法。 --- -# TiDB 特有的函数 +# TiDB 特有函数 -以下函数为 TiDB 中特有的函数,与 MySQL 不兼容: +以下函数是 TiDB 的扩展,在 MySQL 中不存在: -| 函数名 | 函数说明 | + + +| 函数名称 | 函数描述 | +| :-------------- | :------------------------------------- | +| [`CURRENT_RESOURCE_GROUP()`](#current_resource_group) | 返回当前会话绑定的资源组的名称。请参阅[使用资源控制实现资源隔离](/tidb-resource-control.md)。 | +| [`TIDB_BOUNDED_STALENESS()`](#tidb_bounded_staleness) | 指示 TiDB 读取指定时间范围内最新的数据。请参阅[使用 `AS OF TIMESTAMP` 子句读取历史数据](/as-of-timestamp.md)。 | +| [`TIDB_CURRENT_TSO()`](#tidb_current_tso) | 返回 TiDB 中当前的 [TimeStamp Oracle (TSO)](/tso.md)。 | +| [`TIDB_DECODE_BINARY_PLAN()`](#tidb_decode_binary_plan) | 解码二进制计划。 | +| [`TIDB_DECODE_KEY()`](#tidb_decode_key) | 将 TiDB 编码的键条目解码为包含 `_tidb_rowid` 和 `table_id` 的 JSON 结构。这些编码的键可以在一些系统表和日志输出中找到。 | +| [`TIDB_DECODE_PLAN()`](#tidb_decode_plan) | 解码 TiDB 执行计划。 | +| [`TIDB_DECODE_SQL_DIGESTS()`](#tidb_decode_sql_digests) | 查询集群中一组 SQL 摘要对应的规范化 SQL 语句(一种没有格式和参数的形式)。 | +| [`TIDB_ENCODE_SQL_DIGEST()`](#tidb_encode_sql_digest) | 获取查询字符串的摘要。 | +| [`TIDB_IS_DDL_OWNER()`](#tidb_is_ddl_owner) | 检查您连接的 TiDB 实例是否为 DDL Owner。DDL Owner 是负责代表集群中所有其他节点执行 DDL 语句的 TiDB 实例。 | +| [`TIDB_PARSE_TSO()`](#tidb_parse_tso) | 从 TiDB TSO 时间戳中提取物理时间戳。另请参阅:[`tidb_current_ts`](/system-variables.md#tidb_current_ts)。 | +| [`TIDB_PARSE_TSO_LOGICAL()`](#tidb_parse_tso_logical) | 从 TiDB TSO 时间戳中提取逻辑时间戳。 | +| [`TIDB_ROW_CHECKSUM()`](#tidb_row_checksum) | 查询行的校验和值。此函数只能在 FastPlan 进程中的 `SELECT` 语句中使用。也就是说,您可以通过 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id = ?` 或 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id IN (?, ?, ...)` 等语句进行查询。另请参阅:[单行数据的数据完整性验证](/ticdc/ticdc-integrity-check.md)。 | +| [`TIDB_SHARD()`](#tidb_shard) | 创建一个分片索引来分散索引热点。分片索引是以 `TIDB_SHARD` 函数作为前缀的表达式索引。| +| [`TIDB_VERSION()`](#tidb_version) | 返回包含其他构建信息的 TiDB 版本。 | +| [`VITESS_HASH()`](#vitess_hash) | 返回数字的哈希值。此函数与 Vitess 的 `HASH` 函数兼容,旨在帮助从 Vitess 迁移数据。 | + + + + + +| 函数名称 | 函数描述 | | :-------------- | :------------------------------------- | -| [`CURRENT_RESOURCE_GROUP()`](#current_resource_group) | 用于查询当前连接绑定的资源组名。参见[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)。 | -| [`TIDB_BOUNDED_STALENESS()`](#tidb_bounded_staleness) | 指示 TiDB 在指定时间范围内读取尽可能新的数据。参见[使用 `AS OF TIMESTAMP` 语法读取历史数据](/as-of-timestamp.md)。 | -| [`TIDB_CURRENT_TSO()`](#tidb_current_tso) | 返回当前的 [TimeStamp Oracle (TSO)](/tso.md)。 | -| [`TIDB_DECODE_BINARY_PLAN()`](#tidb_decode_binary_plan) | 用于解码以二进制格式编码的执行计划。 | -| [`TIDB_DECODE_KEY()`](#tidb_decode_key) | 用于将 TiDB 编码的键输入解码为包含 `_tidb_rowid` 和 `table_id` 的 JSON 结构。一些系统表和日志输出中有 TiDB 编码的键。 | -| [`TIDB_DECODE_PLAN()`](#tidb_decode_plan) | 用于解码 TiDB 执行计划。 | -| [`TIDB_DECODE_SQL_DIGESTS()`](#tidb_decode_sql_digests) | 用于在集群中查询一组 SQL digest 所对应的 SQL 语句的归一化形式(即去除格式和参数后的形式)。 | -| [`TIDB_ENCODE_SQL_DIGEST()`](#tidb_encode_sql_digest) | 用于为查询字符串获取 digest。 | -| [`TIDB_IS_DDL_OWNER()`](#tidb_is_ddl_owner) | 用于检查你连接的 TiDB 实例是否是 DDL Owner。DDL Owner 是代表集群中所有其他节点执行 DDL 语句的 TiDB 实例。 | -| [`TIDB_PARSE_TSO()`](#tidb_parse_tso) | 用于从 TiDB TSO 时间戳中提取物理时间戳。参见 [`tidb_current_ts`](/system-variables.md#tidb_current_ts)。 | -| [`TIDB_PARSE_TSO_LOGICAL()`](#tidb_parse_tso_logical) | 用于从 TiDB TSO 时间戳中提取逻辑时间戳。| -| [`TIDB_ROW_CHECKSUM()`](#tidb_row_checksum) | 用于查询行数据的 Checksum 值。该函数只能用于 FastPlan 流程的 `SELECT` 语句,即你可通过类似 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id = ?` 或 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id IN (?, ?, ...)` 的语句进行查询。参见[数据正确性校验](/ticdc/ticdc-integrity-check.md)。 | -| [`TIDB_SHARD()`](#tidb_shard) | 用于创建一个 SHARD INDEX 来打散热点索引。SHARD INDEX 是一种以 `TIDB_SHARD` 函数为前缀的表达式索引。 | -| [`TIDB_VERSION()`](#tidb_version) | 用于获取当前连接的 TiDB 服务器的版本以及构建信息。 | -| [`VITESS_HASH()`](#vitess_hash) | 返回与 Vitess 的 `HASH` 函数兼容的数值的哈希值,有助于从 Vitess 迁移至 TiDB。 | +| [`CURRENT_RESOURCE_GROUP()`](#current_resource_group) | 返回当前会话绑定的资源组的名称。请参阅[使用资源控制实现资源隔离](/tidb-resource-control.md)。 | +| [`TIDB_BOUNDED_STALENESS()`](#tidb_bounded_staleness) | 指示 TiDB 读取指定时间范围内最新的数据。请参阅[使用 `AS OF TIMESTAMP` 子句读取历史数据](/as-of-timestamp.md)。 | +| [`TIDB_CURRENT_TSO()`](#tidb_current_tso) | 返回 TiDB 中当前的 [TimeStamp Oracle (TSO)](/tso.md)。 | +| [`TIDB_DECODE_BINARY_PLAN()`](#tidb_decode_binary_plan) | 解码二进制计划。 | +| [`TIDB_DECODE_KEY()`](#tidb_decode_key) | 将 TiDB 编码的键条目解码为包含 `_tidb_rowid` 和 `table_id` 的 JSON 结构。这些编码的键可以在一些系统表和日志输出中找到。 | +| [`TIDB_DECODE_PLAN()`](#tidb_decode_plan) | 解码 TiDB 执行计划。 | +| [`TIDB_DECODE_SQL_DIGESTS()`](#tidb_decode_sql_digests) | 查询集群中一组 SQL 摘要对应的规范化 SQL 语句(一种没有格式和参数的形式)。 | +| [`TIDB_ENCODE_SQL_DIGEST()`](#tidb_encode_sql_digest) | 获取查询字符串的摘要。 | +| [`TIDB_IS_DDL_OWNER()`](#tidb_is_ddl_owner) | 检查您连接的 TiDB 实例是否为 DDL Owner。DDL Owner 是负责代表集群中所有其他节点执行 DDL 语句的 TiDB 实例。 | +| [`TIDB_PARSE_TSO()`](#tidb_parse_tso) | 从 TiDB TSO 时间戳中提取物理时间戳。另请参阅:[`tidb_current_ts`](/system-variables.md#tidb_current_ts)。 | +| [`TIDB_PARSE_TSO_LOGICAL()`](#tidb_parse_tso_logical) | 从 TiDB TSO 时间戳中提取逻辑时间戳。 | +| [`TIDB_ROW_CHECKSUM()`](#tidb_row_checksum) | 查询行的校验和值。此函数只能在 FastPlan 进程中的 `SELECT` 语句中使用。也就是说,您可以通过 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id = ?` 或 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id IN (?, ?, ...)` 等语句进行查询。另请参阅:[单行数据的数据完整性验证](https://docs.pingcap.com/tidb/stable/ticdc-integrity-check)。 | +| [`TIDB_SHARD()`](#tidb_shard) | 创建一个分片索引来分散索引热点。分片索引是以 `TIDB_SHARD` 函数作为前缀的表达式索引。| +| [`TIDB_VERSION()`](#tidb_version) | 返回包含其他构建信息的 TiDB 版本。 | +| [`VITESS_HASH()`](#vitess_hash) | 返回数字的哈希值。此函数与 Vitess 的 `HASH` 函数兼容,旨在帮助从 Vitess 迁移数据。 | + + ## CURRENT_RESOURCE_GROUP -`CURRENT_RESOURCE_GROUP()` 函数用于查询当前连接绑定的资源组名称。当开启[资源管控 (Resource Control)](/tidb-resource-control.md) 功能时,执行 SQL 语句对资源的占用会受到所绑定的资源组资源配置的限制。 +`CURRENT_RESOURCE_GROUP()` 函数用于显示当前会话绑定的资源组名称。当 [资源管控](/tidb-resource-control.md) 功能启用时,SQL 语句可用的资源会受到绑定资源组的资源配额限制。 -在会话建立时,TiDB 默认会将连接绑定至登录用户绑定的资源组,如果用户没有绑定任何资源组,则会将连接绑定至 `default` 资源组。在会话建立之后,绑定的资源组默认不会发生变化,即使执行了[修改用户绑定的资源组](/sql-statements/sql-statement-alter-user.md#修改用户绑定的资源组)。如需修改当前会话绑定的资源组,可以使用 [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md) 语句。 +当会话建立时,TiDB 默认将该会话绑定到登录用户所绑定的资源组。如果用户未绑定到任何资源组,则该会话将绑定到 `default` 资源组。会话建立后,默认情况下绑定的资源组不会更改,即使通过 [修改用户绑定的资源组](/sql-statements/sql-statement-alter-user.md#modify-basic-user-information) 更改了用户的绑定资源组。要更改当前会话的绑定资源组,可以使用 [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md)。 示例: -创建一个用户 `user1`,创建两个资源组 `rg1` 和 `rg2`,并将用户 `user1` 绑定资源组 `rg1`: +创建用户 `user1`,创建两个资源组 `rg1` 和 `rg2`,并将用户 `user1` 绑定到资源组 `rg1`: ```sql CREATE USER 'user1'; @@ -42,7 +68,7 @@ CREATE RESOURCE GROUP rg2 RU_PER_SEC = 2000; ALTER USER 'user1' RESOURCE GROUP `rg1`; ``` -使用 `user1` 登录,查看当前用户绑定的资源组: +使用 `user1` 登录并查看绑定到当前用户的资源组: ```sql SELECT CURRENT_RESOURCE_GROUP(); @@ -57,7 +83,7 @@ SELECT CURRENT_RESOURCE_GROUP(); 1 row in set (0.00 sec) ``` -执行 `SET RESOURCE GROUP` 将当前会话的资源组设置为 `rg2`,然后查看当前用户绑定的资源组: +执行 `SET RESOURCE GROUP` 将当前会话的资源组设置为 `rg2`,然后查看绑定到当前用户的资源组: ```sql SET RESOURCE GROUP `rg2`; @@ -75,11 +101,11 @@ SELECT CURRENT_RESOURCE_GROUP(); ## TIDB_BOUNDED_STALENESS -`TIDB_BOUNDED_STALENESS()` 函数用作 [`AS OF TIMESTAMP`](/as-of-timestamp.md) 语法的一部分。 +`TIDB_BOUNDED_STALENESS()` 函数用于 [`AS OF TIMESTAMP`](/as-of-timestamp.md) 语法的一部分。 ## TIDB_CURRENT_TSO -`TIDB_CURRENT_TSO()` 函数返回当前事务的 [TSO](/tso.md),类似于 [`tidb_current_ts`](/system-variables.md#tidb_current_ts) 变量。 +`TIDB_CURRENT_TSO()` 函数返回当前事务的 [TSO](/tso.md)。这类似于 [`tidb_current_ts`](/system-variables.md#tidb_current_ts) 系统变量。 ```sql BEGIN; @@ -117,9 +143,9 @@ SELECT @@tidb_current_ts; ## TIDB_DECODE_BINARY_PLAN -`TIDB_DECODE_BINARY_PLAN(binary_plan)` 函数用于解码以二进制格式编码的执行计划,例如 [`STATEMENTS_SUMMARY`](/statement-summary-tables.md) 表中 `BINARY_PLAN` 列的计划。 +`TIDB_DECODE_BINARY_PLAN(binary_plan)` 函数解码二进制计划,例如 [`STATEMENTS_SUMMARY`](/statement-summary-tables.md) 表的 `BINARY_PLAN` 列中的二进制计划。 -必须将 [`tidb_generate_binary_plan`](/system-variables.md#tidb_generate_binary_plan-从-v620-版本开始引入) 变量设置为 `ON`,二进制计划才可用。 +必须将 [`tidb_generate_binary_plan`](/system-variables.md#tidb_generate_binary_plan-new-in-v620) 变量设置为 `ON`,二进制计划才可用。 示例: @@ -140,28 +166,28 @@ TIDB_DECODE_BINARY_PLAN(BINARY_PLAN): ## TIDB_DECODE_KEY -`TIDB_DECODE_KEY()` 函数用于将 TiDB 编码的键输入解码为包含 `_tidb_rowid` 和 `table_id` 的 JSON 结构。在一些系统表和日志输出中有 TiDB 编码的键。 +`TIDB_DECODE_KEY()` 函数将 TiDB 编码的键条目解码为包含 `_tidb_rowid` 和 `table_id` 的 JSON 结构。这些编码的键存在于某些系统表和日志输出中。 -以下示例中,表 `t1` 有一个隐藏的 `rowid`,该 `rowid` 由 TiDB 生成。语句中使用了 `TIDB_DECODE_KEY()` 函数。结果显示,隐藏的 `rowid` 被解码后并输出,这是典型的非聚簇主键结果。 +在以下示例中,表 `t1` 具有由 TiDB 生成的隐藏 `rowid`。 `TIDB_DECODE_KEY()` 函数用于该语句中。 从结果中,您可以看到隐藏的 `rowid` 被解码并输出,这是非聚集主键的典型结果。 ```sql SELECT START_KEY, TIDB_DECODE_KEY(START_KEY) FROM information_schema.tikv_region_status WHERE table_name='t1' AND REGION_ID=2\G ``` -``` +```sql *************************** 1. row *************************** START_KEY: 7480000000000000FF3B5F728000000000FF1DE3F10000000000FA TIDB_DECODE_KEY(START_KEY): {"_tidb_rowid":1958897,"table_id":"59"} 1 row in set (0.00 sec) ``` -以下示例中,表 `t2` 有一个复合聚簇主键。由 JSON 输出可知,输出结果的 `handle` 项中包含了主键部分两列的信息,即两列的名称和对应的值。 +在以下示例中,表 `t2` 具有复合聚集主键。 从 JSON 输出中,您可以看到一个 `handle`,其中包含作为主键一部分的两个列的名称和值。 ```sql SHOW CREATE TABLE t2\G ``` -``` +```sql *************************** 1. row *************************** Table: t2 Create Table: CREATE TABLE `t2` ( @@ -177,7 +203,7 @@ Create Table: CREATE TABLE `t2` ( SELECT * FROM information_schema.tikv_region_status WHERE table_name='t2' LIMIT 1\G ``` -``` +```sql *************************** 1. row *************************** REGION_ID: 48 START_KEY: 7480000000000000FF3E5F720400000000FF0000000601633430FF3338646232FF2D64FF3531632D3131FF65FF622D386337352DFFFF3830653635303138FFFF61396265000000FF00FB000000000000F9 @@ -203,7 +229,7 @@ REPLICATIONSTATUS_STATEID: NULL SELECT tidb_decode_key('7480000000000000FF3E5F720400000000FF0000000601633430FF3338646232FF2D64FF3531632D3131FF65FF622D386337352DFFFF3830653635303138FFFF61396265000000FF00FB000000000000F9'); ``` -``` +```sql +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | tidb_decode_key('7480000000000000FF3E5F720400000000FF0000000601633430FF3338646232FF2D64FF3531632D3131FF65FF622D386337352DFFFF3830653635303138FFFF61396265000000FF00FB000000000000F9') | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -212,7 +238,7 @@ SELECT tidb_decode_key('7480000000000000FF3E5F720400000000FF0000000601633430FF33 1 row in set (0.001 sec) ``` -以下示例中,表中的第一个 Region 以一个仅包含 `table_id` 的 key 开头,表中的最后一个 Region 以 `table_id + 1` 结束。中间的 Region 有着更长的 key,包含 `_tidb_rowid` 或 `handle`。 +在以下示例中,表的第一个 Region 以仅具有表的 `table_id` 的键开头。 该表的最后一个 Region 以 `table_id + 1` 结尾。 之间的任何 Region 都有更长的键,其中包括 `_tidb_rowid` 或 `handle`。 ```sql SELECT @@ -228,7 +254,7 @@ ORDER BY START_KEY; ``` -``` +```sql +------------+-----------------------------------------------------------+-----------------------------------------------------------+ | TABLE_NAME | TIDB_DECODE_KEY(START_KEY) | TIDB_DECODE_KEY(END_KEY) | +------------+-----------------------------------------------------------+-----------------------------------------------------------+ @@ -240,21 +266,21 @@ ORDER BY 4 rows in set (0.031 sec) ``` -`TIDB_DECODE_KEY` 在解码成功时返回有效的 JSON,在解码失败时返回传入的参数值。 +`TIDB_DECODE_KEY` 成功时返回有效的 JSON,如果解码失败,则返回参数值。 ## TIDB_DECODE_PLAN -你可以在慢查询日志中找到编码形式的 TiDB 执行计划,然后使用 `TIDB_DECODE_PLAN()` 函数将编码的执行计划解码为易读的形式。 +你可以在慢查询日志中找到编码形式的 TiDB 执行计划。 `TIDB_DECODE_PLAN()` 函数用于将编码后的计划解码为人类可读的形式。 -该函数很有用,因为在执行语句时 TiDB 会捕获执行计划。重新执行 `EXPLAIN` 中的语句可能会产生不同的结果,因为数据分布和统计数据会随着时间的推移而变化。 +此函数很有用,因为计划是在语句执行时捕获的。 在 `EXPLAIN` 中重新执行该语句可能会产生不同的结果,因为数据分布和统计信息会随着时间的推移而演变。 ```sql SELECT tidb_decode_plan('8QIYMAkzMV83CQEH8E85LjA0CWRhdGE6U2VsZWN0aW9uXzYJOTYwCXRpbWU6NzEzLjHCtXMsIGxvb3BzOjIsIGNvcF90YXNrOiB7bnVtOiAxLCBtYXg6IDU2OC41wgErRHByb2Nfa2V5czogMCwgcnBjXxEpAQwFWBAgNTQ5LglZyGNvcHJfY2FjaGVfaGl0X3JhdGlvOiAwLjAwfQkzLjk5IEtCCU4vQQoxCTFfNgkxXzAJMwm2SGx0KHRlc3QudC5hLCAxMDAwMCkNuQRrdgmiAHsFbBQzMTMuOMIBmQnEDDk2MH0BUgEEGAoyCTQzXzUFVwX1oGFibGU6dCwga2VlcCBvcmRlcjpmYWxzZSwgc3RhdHM6cHNldWRvCTk2ISE2aAAIMTUzXmYA')\G ``` -``` +```sql *************************** 1. row *************************** - tidb_decode_plan('8QIYMAkzMV83CQEH8E85LjA0CWRhdGE6U2VsZWN0aW9uXzYJOTYwCXRpbWU6NzEzLjHCtXMsIGxvb3BzOjIsIGNvcF90YXNrOiB7bnVtOiAxLCBtYXg6IDU2OC41wgErRHByb2Nfa2V5czogMCwgcnBjXxEpAQwFWBAgNTQ5LglZyGNvcHJfY2FjaGVfaGl0X3JhdGlvOiAwLjAwfQkzLjk5IEtCCU4vQQoxCTFfNgkxXz: id task estRows operator info actRows execution info memory disk + tidb_decode_plan('8QIYMAkzMV83CQEH8E85LjA0CWRhdGE6U2VsZWN0aW9uXzYJOTYwCXRpbWU6NzEzLjHCtXMsIGxvb3BzOjIsIGNvcF90YXNrOiB7bnVtOiAxLCBtYXg6IDU2OC41wgErRHByb2Nfa2V5czogMCwgcnBjXxEpAQwFWBAgNTQ5LglZyGNvcHJfY2FjaGVfaGl0X3JhdGlvOiAwLjAwfQkzLjk5IEtCCU4vQQoxCTFfNgkxXzAJMwm2SGx0KHRlc3QudC5hLCAxMDAwMCkNuQRrdgmiAHsFbBQzMTMuOMIBmQnEDDk2MH0BUgEEGAoyCTQzXzUFVwX1oGFibGU6dCwga2VlcCBvcmRlcjpmYWxzZSwgc3RhdHM6cHNldWRvCTk2ISE2aAAIMTUzXmYA'): id task estRows operator info actRows execution info memory disk TableReader_7 root 319.04 data:Selection_6 960 time:713.1µs, loops:2, cop_task: {num: 1, max: 568.5µs, proc_keys: 0, rpc_num: 1, rpc_time: 549.1µs, copr_cache_hit_ratio: 0.00} 3.99 KB N/A └─Selection_6 cop[tikv] 319.04 lt(test.t.a, 10000) 960 tikv_task:{time:313.8µs, loops:960} N/A N/A └─TableFullScan_5 cop[tikv] 960 table:t, keep order:false, stats:pseudo 960 tikv_task:{time:153µs, loops:960} N/A N/A @@ -262,19 +288,19 @@ SELECT tidb_decode_plan('8QIYMAkzMV83CQEH8E85LjA0CWRhdGE6U2VsZWN0aW9uXzYJOTYwCXR ## TIDB_DECODE_SQL_DIGESTS -`TIDB_DECODE_SQL_DIGESTS()` 函数用于在集群中查询一组 SQL Digest 所对应的 SQL 语句的归一化形式(即去除格式和参数后的形式)。函数接受 1 个或 2 个参数: +`TIDB_DECODE_SQL_DIGESTS()` 函数用于查询集群中 SQL 摘要集合对应的规范化 SQL 语句(一种不包含格式和参数的形式)。此函数接受 1 个或 2 个参数: -* `digests`:字符串类型,该参数应符合 JSON 字符串数组的格式,数组中的每个字符串应为一个 SQL Digest。 -* `stmtTruncateLength`:可选参数,整数类型,用来限制返回结果中每条 SQL 语句的长度,超过指定的长度会被截断。`0` 表示不限制长度。 +* `digests`: 一个字符串。此参数的格式为 JSON 字符串数组,数组中的每个字符串都是一个 SQL 摘要。 +* `stmtTruncateLength`: 一个整数(可选)。它用于限制返回结果中每个 SQL 语句的长度。如果 SQL 语句超过指定的长度,则该语句将被截断。`0` 表示长度不受限制。 -该函数返回一个字符串,符合 JSON 字符串数组的格式,数组中的第 *i* 项为参数 `digests` 中的第 *i* 个元素所对应的语句。如果参数 `digests` 中的某一项不是一个有效的 SQL Digest 或系统无法查询到其对应的 SQL 语句,则返回结果中对应项为 `null`。如果指定了截断长度 (`stmtTruncateLength > 0`),则返回结果中每条超过该长度的语句,保留前 `stmtTruncateLength` 个字符,并在尾部增加 `"..."` 后缀表示发生了截断。如果参数 `digests` 为 `NULL`,则函数的返回值为 `NULL`。 +此函数返回一个字符串,其格式为 JSON 字符串数组。数组中的第 *i* 项是 `digests` 参数中第 *i* 个元素对应的规范化 SQL 语句。如果 `digests` 参数中的某个元素不是有效的 SQL 摘要,或者系统无法找到相应的 SQL 语句,则返回结果中对应的项为 `null`。如果指定了截断长度 (`stmtTruncateLength > 0`),对于返回结果中超过此长度的每个语句,将保留前 `stmtTruncateLength` 个字符,并在末尾添加 `"..."` 后缀以指示截断。如果 `digests` 参数为 `NULL`,则该函数的返回值为 `NULL`。 > **注意:** > -> * 仅持有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户可以使用该函数。 -> * `TIDB_DECODE_SQL_DIGESTS` 执行时,TiDB 内部从 Statement Summary 一系列表中查询每个 SQL Digest 所对应的语句,因而并不能保证对任意 SQL Digest 都总是能查询到对应的语句,只有在集群中执行过的语句才有可能被查询到,且是否能查询到受 Statement Summary 表相关配置的影响。有关 Statement Summary 表的详细说明,参见 [Statement Summary Tables](/statement-summary-tables.md)。 -> * 该函数开销较大,在行数很多的查询中(比如在规模较大、比较繁忙的集群上查询 `information_schema.cluster_tidb_trx` 全表时)直接使用该函数可能导致查询运行时间较长。请谨慎使用。 -> * 该函数开销大的原因是,其每次被调用时,都会在内部发起对 `STATEMENTS_SUMMARY`、`STATEMENTS_SUMMARY_HISTORY`、`CLUSTER_STATEMENTS_SUMMARY` 和 `CLUSTER_STATEMENTS_SUMMARY_HISTORY` 这几张表的查询,且其中涉及 `UNION` 操作。且该函数目前不支持向量化,即对于多行数据调用该函数时,对每行都会独立进行一次上述的查询。 +> * 只有具有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户才能使用此函数。 +> * 当执行 `TIDB_DECODE_SQL_DIGESTS` 时,TiDB 会从语句摘要表中查询每个 SQL 摘要对应的语句,因此不能保证始终可以为任何 SQL 摘要找到相应的语句。只能找到在集群中执行过的语句,并且是否可以查询到这些 SQL 语句也受到语句摘要表相关配置的影响。有关语句摘要表的详细描述,请参见 [语句摘要表](/statement-summary-tables.md)。 +> * 此函数开销很高。在具有大量行的查询中(例如,在大规模且繁忙的集群上查询 `information_schema.cluster_tidb_trx` 的全表),使用此函数可能会导致查询运行时间过长。请谨慎使用。 +> * 此函数开销很高,因为它每次调用时,都会在内部查询 `STATEMENTS_SUMMARY`、`STATEMENTS_SUMMARY_HISTORY`、`CLUSTER_STATEMENTS_SUMMARY` 和 `CLUSTER_STATEMENTS_SUMMARY_HISTORY` 表,并且查询涉及 `UNION` 操作。此函数目前不支持向量化,也就是说,当为多行数据调用此函数时,上述查询会为每一行单独执行。 ```sql SET @digests = '["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5","38b03afa5debbdf0326a014dbe5012a62c51957f1982b3093e748460f8b00821","e5796985ccafe2f71126ed6c0ac939ffa015a8c0744a24b7aee6d587103fd2f7"]'; @@ -282,7 +308,7 @@ SET @digests = '["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02a SELECT TIDB_DECODE_SQL_DIGESTS(@digests); ``` -``` +```sql +------------------------------------+ | TIDB_DECODE_SQL_DIGESTS(@digests) | +------------------------------------+ @@ -291,7 +317,7 @@ SELECT TIDB_DECODE_SQL_DIGESTS(@digests); 1 row in set (0.00 sec) ``` -上面的例子中,参数是一个包含 3 个 SQL Digest 的 JSON 数组,其对应的 SQL 语句分别为查询结果中给出的三项。但是其中第二条 SQL Digest 所对应的 SQL 语句未能从集群中找到,因而结果中的第二项为 `null`。 +在上面的示例中,参数是一个包含 3 个 SQL 摘要的 JSON 数组,相应的 SQL 语句是查询结果中的三个项。但是无法从集群中找到与第二个 SQL 摘要对应的 SQL 语句,因此结果中的第二项为 `null`。 ```sql SELECT TIDB_DECODE_SQL_DIGESTS(@digests, 10); @@ -306,18 +332,18 @@ SELECT TIDB_DECODE_SQL_DIGESTS(@digests, 10); 1 row in set (0.01 sec) ``` -上述调用指定了第二个参数(即截断长度)为 10,而查询结果中的第三条语句的长度大于 10,因而仅保留了前 10 个字符,并在尾部添加了 `"..."` 表示发生了截断。 +上面的调用将第二个参数(即截断长度)指定为 10,并且查询结果中第三个语句的长度大于 10。因此,仅保留前 10 个字符,并在末尾添加 `"..."`,表示截断。 另请参阅: -- [Statement Summary Tables](/statement-summary-tables.md) +- [语句摘要表](/statement-summary-tables.md) - [`INFORMATION_SCHEMA.TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) ## TIDB_ENCODE_SQL_DIGEST -`TIDB_ENCODE_SQL_DIGEST(query_str)` 函数返回查询字符串的 SQL digest。 +`TIDB_ENCODE_SQL_DIGEST(query_str)` 返回查询字符串的 SQL 摘要。 -在以下示例中,你可以看到两个查询都获得了相同的查询 digest,这是因为两个查询的 digest 都是 `select ?`。 +在以下示例中,你可以看到两个查询都获得了相同的查询摘要,这是因为对于它们来说,摘要都将是 `select ?`。 ```sql SELECT TIDB_ENCODE_SQL_DIGEST('SELECT 1'); @@ -347,7 +373,7 @@ SELECT TIDB_ENCODE_SQL_DIGEST('SELECT 2'); ## TIDB_IS_DDL_OWNER -如果你连接的 TiDB 实例是 DDL Owner,`TIDB_IS_DDL_OWNER()` 函数返回 `1`。 +`TIDB_IS_DDL_OWNER()` 函数用于判断你当前连接的实例是否为 DDL Owner,如果是则返回 `1`。 ```sql SELECT TIDB_IS_DDL_OWNER(); @@ -364,9 +390,9 @@ SELECT TIDB_IS_DDL_OWNER(); ## TIDB_PARSE_TSO -`TIDB_PARSE_TSO()` 函数用于从 TiDB TSO 时间戳中提取物理时间戳。 +`TIDB_PARSE_TSO()` 函数从 TiDB TSO 时间戳中提取物理时间戳。[TSO](/tso.md) 代表时间戳预言机(Time Stamp Oracle),是由 PD (Placement Driver) 为每个事务发出的单调递增的时间戳。 -TSO 指 Time Stamp Oracle,是 PD (Placement Driver) 为每个事务提供的单调递增的时间戳。TSO 是一串数字,包含以下两部分: +TSO 是一个由两部分组成的数字: - 一个物理时间戳 - 一个逻辑计数器 @@ -377,7 +403,7 @@ SELECT TIDB_PARSE_TSO(@@tidb_current_ts); ROLLBACK; ``` -``` +```sql +-----------------------------------+ | TIDB_PARSE_TSO(@@tidb_current_ts) | +-----------------------------------+ @@ -386,11 +412,11 @@ ROLLBACK; 1 row in set (0.0012 sec) ``` -以上示例使用 `TIDB_PARSE_TSO()` 函数从 `tidb_current_ts` 会话变量提供的可用时间戳编号中提取物理时间戳。因为每个事务都会分配到时间戳,所以此函数在事务中运行。 +这里 `TIDB_PARSE_TSO` 用于从 `tidb_current_ts` 会话变量中可用的时间戳数字中提取物理时间戳。因为时间戳是为每个事务发出的,所以此函数在事务中运行。 ## TIDB_PARSE_TSO_LOGICAL -`TIDB_PARSE_TSO_LOGICAL(tso)` 函数返回从 TiDB [TSO](/tso.md) 时间戳中提取的逻辑时间戳。 +`TIDB_PARSE_TSO_LOGICAL(tso)` 函数返回 [TSO](/tso.md) 时间戳的逻辑部分。 ```sql SELECT TIDB_PARSE_TSO_LOGICAL(450456244814610433); @@ -420,15 +446,15 @@ SELECT TIDB_PARSE_TSO_LOGICAL(450456244814610434); ## TIDB_ROW_CHECKSUM -`TIDB_ROW_CHECKSUM()` 函数用于查询行数据的 Checksum 值。该函数只能用于 FastPlan 流程的 `SELECT` 语句,即你可通过形如 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id = ?` 或 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id IN (?, ?, ...)` 的语句进行查询。 +`TIDB_ROW_CHECKSUM()` 函数用于查询行的校验和值。此函数只能在 FastPlan 进程中的 `SELECT` 语句中使用。也就是说,你可以通过类似 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id = ?` 或 `SELECT TIDB_ROW_CHECKSUM() FROM t WHERE id IN (?, ?, ...)` 的语句进行查询。 -在 TiDB 中开启行数据 Checksum 功能 [`tidb_enable_row_level_checksum`](/system-variables.md#tidb_enable_row_level_checksum-从-v710-版本开始引入): +要启用 TiDB 中单行数据的校验和功能(由系统变量 [`tidb_enable_row_level_checksum`](/system-variables.md#tidb_enable_row_level_checksum-new-in-v710) 控制),请运行以下语句: ```sql SET GLOBAL tidb_enable_row_level_checksum = ON; ``` -上述配置仅对新创建的会话生效,因此需要重新连接 TiDB。 +此配置仅对新创建的会话生效,因此你需要重新连接到 TiDB。 创建表 `t` 并插入数据: @@ -438,15 +464,15 @@ CREATE TABLE t (id INT PRIMARY KEY, k INT, c CHAR(1)); INSERT INTO t VALUES (1, 10, 'a'); ``` -查询表 `t` 中 `id = 1` 的行数据的 Checksum 值: +以下语句展示了如何查询表 `t` 中 `id = 1` 的行的校验和值: ```sql SELECT *, TIDB_ROW_CHECKSUM() FROM t WHERE id = 1; ``` -输出结果如下: +输出如下: -``` +```sql +----+------+------+---------------------+ | id | k | c | TIDB_ROW_CHECKSUM() | +----+------+------+---------------------+ @@ -457,41 +483,41 @@ SELECT *, TIDB_ROW_CHECKSUM() FROM t WHERE id = 1; ## TIDB_SHARD -`TIDB_SHARD()` 函数用于创建一个 SHARD INDEX 来打散热点索引。SHARD INDEX 是一种以 `TIDB_SHARD()` 函数为前缀的表达式索引。 +`TIDB_SHARD()` 函数用于创建 shard 索引,以分散索引热点。shard 索引是以 `TIDB_SHARD()` 函数为前缀的表达式索引。 -- 创建方式: +- 创建: - 使用 `uk((tidb_shard(a)), a))` 为字段 `a` 创建一个 SHARD INDEX。当二级唯一索引 `uk((tidb_shard(a)), a))` 的索引字段 `a` 上存在因单调递增或递减而产生的热点时,索引的前缀 `tidb_shard(a)` 会打散热点,从而提升集群可扩展性。 + 要为索引字段 `a` 创建 shard 索引,可以使用 `uk((tidb_shard(a)), a))`。当唯一二级索引 `uk((tidb_shard(a)), a))` 中的索引字段 `a` 上存在由单调递增或递减数据引起的热点时,索引的前缀 `tidb_shard(a)` 可以分散热点,从而提高集群的可扩展性。 -- 适用场景: +- 场景: - - 二级唯一索引上 key 值存在单调递增或递减导致的写入热点,且该索引包含的列是整型。 - - 业务中 SQL 语句根据该二级索引的全部字段做等值查询,查询可以是单独的 `SELECT`,也可以是 `UPDATE`,`DELETE` 等产生的内部查询,等值查询包括 `a = 1` 或 `a IN (1, 2, ......)` 两种方式。 + - 唯一二级索引上存在由单调递增或递减的键引起的写入热点,并且该索引包含整数类型字段。 + - SQL 语句基于二级索引的所有字段执行等值查询,无论是单独的 `SELECT` 还是由 `UPDATE`、`DELETE` 等生成的内部查询。等值查询包括两种方式:`a = 1` 或 `a IN (1, 2, ......)`。 -- 使用限制: +- 限制: - - 非等值查询无法使用索引。 - - 查询条件中 `AND` 和 `OR` 混合且最外层是 `AND` 算子时无法使用 SHARD INDEX。 - - `GROUP BY` 无法使用 SHARD INDEX。 - - `ORDER BY` 无法使用 SHARD INDEX。 - - `ON` 子句无法使用 SHARD INDEX。 - - `WHERE` 子查询无法使用 SHARD INDEX。 - - SHARD INDEX 只能打散整型字段的唯一索引。 - - SHARD INDEX 联合索引可能失效。 - - SHARD INDEX 无法走 FastPlan 流程,影响优化器性能。 - - SHARD INDEX 无法使用执行计划缓存。 + - 不能用于不等值查询。 + - 不能用于包含 `OR` 且与最外层 `AND` 运算符混合的查询。 + - 不能用于 `GROUP BY` 子句。 + - 不能用于 `ORDER BY` 子句。 + - 不能用于 `ON` 子句。 + - 不能用于 `WHERE` 子查询。 + - 只能用于分散整数字段的唯一索引。 + - 可能在复合索引中不起作用。 + - 不能通过 FastPlan 过程,这会影响优化器性能。 + - 不能用于准备执行计划缓存。 -`TIDB_SHARD()` 函数的使用示例如下: +以下示例展示了如何使用 `TIDB_SHARD()` 函数。 -- 使用 `TIDB_SHARD()` 函数计算 SHARD 值: +- 使用 `TIDB_SHARD()` 函数计算 SHARD 值。 - 以下示例说明如何使用 `TIDB_SHARD()` 函数计算 `12373743746` 的 SHARD 值。 + 以下语句展示了如何使用 `TIDB_SHARD()` 函数计算 `12373743746` 的 SHARD 值: ```sql SELECT TIDB_SHARD(12373743746); ``` -- 计算得出 SHARD 值为: +- SHARD 值为: ```sql +-------------------------+ @@ -502,7 +528,7 @@ SELECT *, TIDB_ROW_CHECKSUM() FROM t WHERE id = 1; 1 row in set (0.00 sec) ``` -- 使用 `TIDB_SHARD()` 函数创建 SHARD INDEX: +- 使用 `TIDB_SHARD()` 函数创建 shard 索引: ```sql CREATE TABLE test(id INT PRIMARY KEY CLUSTERED, a INT, b INT, UNIQUE KEY uk((tidb_shard(a)), a)); @@ -510,7 +536,7 @@ SELECT *, TIDB_ROW_CHECKSUM() FROM t WHERE id = 1; ## TIDB_VERSION -`TIDB_VERSION()` 函数用于获取当前连接的 TiDB 服务器版本和构建详细信息。向 GitHub 上提交 issue 时,你可使用此函数获取相关信息。 +`TIDB_VERSION()` 函数用于获取你所连接的 TiDB 服务器的版本和构建详情。你可以在 GitHub 上报告问题时使用此函数。 ```sql SELECT TIDB_VERSION()\G @@ -532,7 +558,7 @@ Store: tikv ## VITESS_HASH -`VITESS_HASH(num)` 函数以与 Vitess 相同的方式返回数值的哈希值。这有助于将数据从 Vitess 迁移到 TiDB。 +`VITESS_HASH(num)` 函数用于以与 Vitess 相同的方式哈希一个数字。这有助于从 Vitess 迁移到 TiDB。 示例: diff --git a/functions-and-operators/type-conversion-in-expression-evaluation.md b/functions-and-operators/type-conversion-in-expression-evaluation.md index 7816a7d82d78..bf5f3ba04abf 100644 --- a/functions-and-operators/type-conversion-in-expression-evaluation.md +++ b/functions-and-operators/type-conversion-in-expression-evaluation.md @@ -1,8 +1,8 @@ --- -title: 表达式求值的类型转换 -summary: TiDB 中的表达式求值类型转换与 MySQL 基本一致。详情请参见 MySQL 表达式求值类型转换文档。 +title: 表达式求值中的类型转换 +summary: 了解表达式求值中的类型转换。 --- -# 表达式求值的类型转换 +# 表达式求值中的类型转换 -TiDB 中表达式求值的类型转换与 MySQL 基本一致,详情参见 [MySQL 表达式求值的类型转换](https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html)。 +TiDB 的行为与 MySQL 相同:[https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html](https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html) diff --git a/functions-and-operators/utility-functions.md b/functions-and-operators/utility-functions.md index f69bb2d9050f..60ac6ffabf17 100644 --- a/functions-and-operators/utility-functions.md +++ b/functions-and-operators/utility-functions.md @@ -1,15 +1,15 @@ --- -title: 效用函数 -summary: 了解 TiDB 中的效用函数。 +title: 实用函数 +summary: 本文档介绍 TiDB 支持的实用函数。 --- -# 效用函数 +# 实用函数 -本文介绍了 TiDB 支持的效用函数,这些函数旨在简化常见数据转换,使结果更易于阅读和理解。 +本文档介绍 TiDB 支持的实用函数,这些函数旨在简化常见的数据转换,提高可读性。 ## `FORMAT_BYTES()` -`FORMAT_BYTES()` 函数用于将字节数格式化为易于阅读的形式。 +`FORMAT_BYTES()` 函数将字节数转换为人类可读的格式。 ```sql SELECT FORMAT_BYTES(10*1024*1024); @@ -26,7 +26,7 @@ SELECT FORMAT_BYTES(10*1024*1024); ## `FORMAT_NANO_TIME()` -`FORMAT_NANO_TIME()` 函数用于将纳秒数格式化为易于阅读的时间形式。 +`FORMAT_NANO_TIME()` 函数将纳秒数转换为人类可读的时间格式。 ```sql SELECT FORMAT_NANO_TIME(1000000); diff --git a/functions-and-operators/window-functions.md b/functions-and-operators/window-functions.md index 9a5d6783cec9..356e51dcacf9 100644 --- a/functions-and-operators/window-functions.md +++ b/functions-and-operators/window-functions.md @@ -1,39 +1,39 @@ --- title: 窗口函数 -summary: TiDB 中的窗口函数与 MySQL 8.0 基本一致。可以将 `tidb_enable_window_function` 设置为 `0` 来解决升级后无法解析语法的问题。TiDB 支持除 `GROUP_CONCAT()` 和 `APPROX_PERCENTILE()` 以外的所有 `GROUP BY` 聚合函数。其他支持的窗口函数包括 `CUME_DIST()`、`DENSE_RANK()`、`FIRST_VALUE()`、`LAG()`、`LAST_VALUE()`、`LEAD()`、`NTH_VALUE()`、`NTILE()`、`PERCENT_RANK()`、`RANK()` 和 `ROW_NUMBER()`。这些函数可以下推到 TiFlash。 +summary: 本文档介绍 TiDB 支持的窗口函数。 --- # 窗口函数 -TiDB 中窗口函数的使用方法与 MySQL 8.0 基本一致,详情可参见 [MySQL 窗口函数](https://dev.mysql.com/doc/refman/8.0/en/window-functions.html)。 +TiDB 中窗口函数的用法与 MySQL 8.0 类似。详情请参见 [MySQL 窗口函数](https://dev.mysql.com/doc/refman/8.0/en/window-functions.html)。 -在 TiDB 中,你可以使用以下系统变量来控制窗口功能: +在 TiDB 中,你可以使用以下系统变量来控制窗口函数: -- [`tidb_enable_window_function`](/system-variables.md#tidb_enable_window_function):由于窗口函数会使用一些保留[关键字](/keywords.md),TiDB 提供了该系统变量用于关闭窗口函数功能。如果原先可以正常执行的 SQL 语句在升级 TiDB 后语法无法被解析,此时可以将 [`tidb_enable_window_function`](/system-variables.md#tidb_enable_window_function) 设置为 `OFF`。 -- [`tidb_enable_pipelined_window_function`](/system-variables.md#tidb_enable_pipelined_window_function):你可以使用该系统变量禁用窗口函数的流水线执行算法。 -- [`windowing_use_high_precision`](/system-variables.md#windowing_use_high_precision):你可以使用该变量为窗口函数关闭高精度模式。 +- [`tidb_enable_window_function`](/system-variables.md#tidb_enable_window_function):由于窗口函数在解析器中保留了额外的[关键字](/keywords.md),TiDB 提供此变量来禁用窗口函数。如果在升级 TiDB 后解析 SQL 语句时出现错误,请尝试将此变量设置为 `OFF`。 +- [`tidb_enable_pipelined_window_function`](/system-variables.md#tidb_enable_pipelined_window_function):你可以使用此变量来禁用窗口函数的流水线执行算法。 +- [`windowing_use_high_precision`](/system-variables.md#windowing_use_high_precision):你可以使用此变量来禁用窗口函数的高精度模式。 -[本页](/tiflash/tiflash-supported-pushdown-calculations.md)列出的窗口函数可以下推到 TiFlash。 +[此处列出的](/tiflash/tiflash-supported-pushdown-calculations.md)窗口函数可以下推到 TiFlash。 -TiDB 支持除 `GROUP_CONCAT()` 和 `APPROX_PERCENTILE()` 以外的所有 [`GROUP BY` 聚合函数](/functions-and-operators/aggregate-group-by-functions.md)作为窗口函数。此外,TiDB 支持的其他窗口函数如下: +除了 `GROUP_CONCAT()` 和 `APPROX_PERCENTILE()` 外,TiDB 支持将所有 [`GROUP BY` 聚合函数](/functions-and-operators/aggregate-group-by-functions.md)用作窗口函数。此外,TiDB 还支持以下窗口函数: -| 函数名 | 功能描述 | -| :-------------- | :------------------------------------- | -| [`CUME_DIST()`](#cume_dist) | 返回一组值中的累积分布 | -| [`DENSE_RANK()`](#dense_rank) | 返回分区中当前行的排名,并且排名是连续的| -| [`FIRST_VALUE()`](#first_value) | 当前窗口中第一行的表达式值 | -| [`LAG()`](#lag) | 分区中当前行前面第 N 行的表达式值| -| [`LAST_VALUE()`](#last_value) | 当前窗口中最后一行的表达式值 | -| [`LEAD()`](#lead) | 分区中当前行后面第 N 行的表达式值 | -| [`NTH_VALUE()`](#nth_value) | 当前窗口中第 N 行的表达式值 | -| [`NTILE()`](#ntile) | 将分区划分为 N 桶,为分区中的每一行分配桶号 | -| [`PERCENT_RANK()`](#percent_rank)| 返回分区中小于当前行的百分比 | -| [`RANK()`](#rank) | 返回分区中当前行的排名,排名可能不连续 | -| [`ROW_NUMBER()`](#row_number) | 返回分区中当前行的编号 | +| 函数名 | 功能描述 | +| :-------------------------------- | :------------------------------------- | +| [`CUME_DIST()`](#cume_dist) | 返回一组值中某个值的累积分布。 | +| [`DENSE_RANK()`](#dense_rank) | 返回当前行在分区内的排名,排名是连续的(无间隔)。 | +| [`FIRST_VALUE()`](#first_value) | 返回当前窗口中第一行的表达式值。 | +| [`LAG()`](#lag) | 返回分区内当前行前 N 行的表达式值。 | +| [`LAST_VALUE()`](#last_value) | 返回当前窗口中最后一行的表达式值。 | +| [`LEAD()`](#lead) | 返回分区内当前行后 N 行的表达式值。 | +| [`NTH_VALUE()`](#nth_value) | 返回当前窗口中第 N 行的表达式值。 | +| [`NTILE()`](#ntile) | 将分区划分为 N 个桶,为分区中的每一行分配桶号,并返回当前行在分区内的桶号。 | +| [`PERCENT_RANK()`](#percent_rank) | 返回小于当前行值的分区值的百分比。 | +| [`RANK()`](#rank) | 返回当前行在分区内的排名。排名可能有间隔。 | +| [`ROW_NUMBER()`](#row_number) | 返回分区中当前行的编号。 | ## [`CUME_DIST()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_cume-dist) -`CUME_DIST()` 计算一个值在一组值中的累积分布。请注意,你需要在 `CUME_DIST()` 后使用 `ORDER BY` 子句对该组中的值进行排序。否则,此函数将不会返回预期值。 +`CUME_DIST()` 计算一组值中某个值的累积分布。注意,你需要使用 `ORDER BY` 子句与 `CUME_DIST()` 一起使用来对值组进行排序。否则,此函数将不会返回预期的值。 ```sql WITH RECURSIVE cte(n) AS ( @@ -67,7 +67,7 @@ FROM ## [`DENSE_RANK()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_dense-rank) -`DENSE_RANK()` 函数返回当前行的排名。它的作用类似于 [`RANK()`](#rank),但在处理具有相同值和排序条件的行时能够确保排名是连续的。 +`DENSE_RANK()` 函数返回当前行的排名。它类似于 [`RANK()`](#rank),但在出现并列(共享相同值和排序条件的行)时不会留下间隔。 ```sql SELECT @@ -105,10 +105,10 @@ FROM ( `FIRST_VALUE(expr)` 返回窗口中的第一个值。 -下面的示例使用了两个不同的窗口定义: +以下示例使用了两种不同的窗口定义: -- `PARTITION BY n MOD 2 ORDER BY n` 将表 `a` 中的数据分为两组:`1, 3` 和 `2, 4`。因此会返回 `1` 或 `2`,因为它们是这两组的第一个值。 -- `PARTITION BY n <= 2 ORDER BY n` 将表 `a` 中的数据分为两组:`1, 2` 和 `3, 4`。因此,它会返回 `1` 或 `3`,取决于 `n` 属于哪一组。 +- `PARTITION BY n MOD 2 ORDER BY n` 将表 `a` 中的数据分为两组:`1, 3` 和 `2, 4`。因此它返回 `1` 或 `2`,因为这些是这些组的第一个值。 +- `PARTITION BY n <= 2 ORDER BY n` 将表 `a` 中的数据分为两组:`1, 2` 和 `3, 4`。因此它返回 `1` 或 `3`,具体取决于 `n` 属于哪个组。 ```sql SELECT @@ -142,9 +142,9 @@ ORDER BY ## [`LAG()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_lag) -函数 `LAG(expr [, num [, default]])` 返回当前行之前第 `num` 行的 `expr` 值。如果不存在该行,则返回 `default` 值。默认情况下,未指定时,`num` 为 `1`,`default` 为 `NULL`。 +`LAG(expr [, num [, default]])` 函数返回当前行前 `num` 行的 `expr` 值。如果该行不存在,则返回 `default`。默认情况下,当未指定时,`num` 为 `1`,`default` 为 `NULL`。 -在下面的示例中,由于未指定 `num`,`LAG(n)` 返回上一行中 `n` 的值。当 `n` 为 `1` 时,由于上一行不存在,且未指定 `default` 值,`LAG(1)` 返回 `NULL`。 +在以下示例中,由于未指定 `num`,`LAG(n)` 返回前一行的 `n` 值。当 `n` 为 1 时,由于前一行不存在且未指定 `default`,`LAG(1)` 返回 `NULL`。 ```sql WITH RECURSIVE cte(n) AS ( @@ -227,9 +227,9 @@ ORDER BY ## [`LEAD()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_lead) -函数 `LEAD(expr [, num [,default]])` 返回当前行之后第 `num` 行的 `expr` 值。如果不存在该行,则返回 `default` 值。默认情况下,未指定时,`num` 为 `1`,`default` 为 `NULL`。 +`LEAD(expr [, num [,default]])` 函数返回当前行后 `num` 行的 `expr` 值。如果该行不存在,则返回 `default`。默认情况下,当未指定时,`num` 为 `1`,`default` 为 `NULL`。 -在下面的示例中,由于未指定 `num`,`LEAD(n)` 返回当前行之后下一行中 `n` 的值。当 `n` 为 `10` 时,由于下一行不存在,且未指定 `default` 值,`LEAD(10)` 返回 `NULL`。 +在以下示例中,由于未指定 `num`,`LEAD(n)` 返回下一行的 `n` 值。当 `n` 为 10 时,由于下一行不存在且未指定 `default`,`LEAD(10)` 返回 `NULL`。 ```sql WITH RECURSIVE cte(n) AS ( @@ -270,7 +270,7 @@ FROM ## [`NTH_VALUE()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_nth-value) -函数 `NTH_VALUE(expr, n)` 返回窗口的第 n 个值。 +`NTH_VALUE(expr, n)` 函数返回窗口中的第 `n` 个值。 ```sql WITH RECURSIVE cte(n) AS ( @@ -318,7 +318,7 @@ ORDER BY ## [`NTILE()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_ntile) -`NTILE(n)` 函数将窗口划分为 `n` 个分组,并返回各行的分组编号。 +`NTILE(n)` 函数将窗口分成 `n` 组,并返回每行所属的组号。 ```sql WITH RECURSIVE cte(n) AS ( @@ -360,7 +360,7 @@ FROM ## [`PERCENT_RANK()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_percent-rank) -`PERCENT_RANK()` 函数返回一个介于 0 和 1 之间的数字,表示值小于当前行值的行的百分比。 +`PERCENT_RANK()` 函数返回一个介于 0 和 1 之间的数字,表示小于当前行值的行的百分比。 ```sql SELECT @@ -397,7 +397,7 @@ FROM ( ## [`RANK()`](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_rank) -`RANK()` 函数的作用类似于 [`DENSE_RANK()`](#dense_rank),但在处理具有相同值和排序条件的行时返回的排名是不连续的。这意味着它提供的是绝对排名。例如,排名 7 意味着有 6 个行的排名更靠前。 +`RANK()` 函数类似于 [`DENSE_RANK()`](#dense_rank),但在出现并列(共享相同值和排序条件的行)时会留下间隔。这意味着它提供了一个绝对排名。例如,排名 7 意味着有 6 个排名较低的行。 ```sql SELECT diff --git a/garbage-collection-configuration.md b/garbage-collection-configuration.md index 38b5133737a6..2f6ec0ceb6ab 100644 --- a/garbage-collection-configuration.md +++ b/garbage-collection-configuration.md @@ -1,24 +1,36 @@ --- -title: GC 配置 -summary: TiDB 的 GC 配置可以通过系统变量进行设置,包括启用 GC、运行间隔、数据保留时限、并发线程数量等。此外,TiDB 还支持 GC 流控,可以限制每秒数据写入量。从 TiDB 5.0 版本开始,建议使用系统变量进行配置,避免异常行为。在 TiDB 6.1.0 版本引入了新的系统变量 `tidb_gc_max_wait_time`,用于控制活跃事务阻塞 GC safe point 推进的最长时间。另外,GC in Compaction Filter 机制可以通过配置文件或在线配置开启,但可能会影响 TiKV 扫描性能。 +title: 垃圾回收配置 +summary: 了解 GC 配置参数。 --- -# GC 配置 +# 垃圾回收配置 -你可以通过以下系统变量进行 GC 配置: +你可以使用以下系统变量配置垃圾回收(GC): -* [`tidb_gc_enable`](/system-variables.md#tidb_gc_enable-从-v50-版本开始引入):控制是否启用 TiKV 的垃圾回收 (GC) 机制。 -* [`tidb_gc_run_interval`](/system-variables.md#tidb_gc_run_interval-从-v50-版本开始引入):指定垃圾回收 (GC) 运行的时间间隔。 -* [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入):指定每次进行垃圾回收 (GC) 时保留数据的时限。 -* [`tidb_gc_concurrency`](/system-variables.md#tidb_gc_concurrency-从-v50-版本开始引入):指定 GC 在 [Resolve Locks(清理锁)](/garbage-collection-overview.md#resolve-locks清理锁)步骤中线程的数量。 -* [`tidb_gc_scan_lock_mode`](/system-variables.md#tidb_gc_scan_lock_mode-从-v50-版本开始引入):指定垃圾回收 (GC) 的 Resolve Locks(清理锁)步骤中扫描锁的方式。 -* [`tidb_gc_max_wait_time`](/system-variables.md#tidb_gc_max_wait_time-从-v610-版本开始引入):指定活跃事务阻碍 GC safe point 推进的最大时间。 +* [`tidb_gc_enable`](/system-variables.md#tidb_gc_enable-new-in-v50):控制是否启用 TiKV 的垃圾回收。 +* [`tidb_gc_run_interval`](/system-variables.md#tidb_gc_run_interval-new-in-v50):指定 GC 的运行间隔。 +* [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-new-in-v50):指定每次 GC 时保留数据的时间限制。 +* [`tidb_gc_concurrency`](/system-variables.md#tidb_gc_concurrency-new-in-v50):指定 GC 的 [Resolve Locks](/garbage-collection-overview.md#resolve-locks) 步骤中的线程数。 +* [`tidb_gc_scan_lock_mode`](/system-variables.md#tidb_gc_scan_lock_mode-new-in-v50):指定 GC 的 Resolve Locks 步骤中扫描锁的方式。 +* [`tidb_gc_max_wait_time`](/system-variables.md#tidb_gc_max_wait_time-new-in-v610):指定活跃事务阻塞 GC 安全点的最长时间。 关于如何修改系统变量的值,请参考[系统变量](/system-variables.md)。 -## 流控 +## GC I/O 限制 -TiDB 支持 GC 流控,可通过配置 `gc.max-write-bytes-per-sec` 限制 GC worker 每秒数据写入量,降低对正常请求的影响,`0` 为关闭该功能。该配置可通过 tikv-ctl 动态修改: + + +> **注意:** +> +> 本节仅适用于 TiDB Self-Managed。TiDB Cloud 默认没有 GC I/O 限制。 + + + +TiKV 支持 GC I/O 限制。你可以配置 `gc.max-write-bytes-per-sec` 来限制每个 GC worker 每秒的写入量,从而减少对正常请求的影响。 + +`0` 表示禁用此功能。 + +你可以使用 tikv-ctl 动态修改此配置: {{< copyable "shell-regular" >}} @@ -26,23 +38,33 @@ TiDB 支持 GC 流控,可通过配置 `gc.max-write-bytes-per-sec` 限制 GC w tikv-ctl --host=ip:port modify-tikv-config -n gc.max-write-bytes-per-sec -v 10MB ``` -## TiDB 5.0 引入的变化 +## TiDB 5.0 的变化 + +在 TiDB 的早期版本中,垃圾回收是通过 `mysql.tidb` 系统表配置的。虽然对该表的更改仍然受支持,但建议使用提供的系统变量。这有助于确保对配置的任何更改都可以被验证,并防止意外行为([#20655](https://github.com/pingcap/tidb/issues/20655))。 -在 TiDB 5.0 之前的版本中,GC 是通过系统表 `mysql.tidb` 进行配置的。从 TiDB 5.0 版本起,GC 仍然可以通过系统表 `mysql.tidb` 进行配置,但建议你使用系统变量进行配置,这样可以确保对配置的任何更改都能得到验证,防止造成异常行为 ([#20655](https://github.com/pingcap/tidb/issues/20655))。 +不再支持 `CENTRAL` 垃圾回收模式。将自动使用 `DISTRIBUTED` GC 模式(自 TiDB 3.0 以来一直是默认模式)。这种模式更有效,因为 TiDB 不再需要向每个 TiKV region 发送请求来触发垃圾回收。 -TiDB 5.0 及之后的版本不再需要向各个 TiKV Region 都发送触发 GC 的请求,因此不再提供 `CENTRAL` GC 模式的支持,取而代之的是效率更高的 `DISTRIBUTED` GC 模式 (自 TiDB 3.0 起的默认 GC 模式)。 +有关早期版本变更的信息,请使用左侧菜单中的 _TIDB 版本选择器_ 参考本文档的早期版本。 -如果要了解 TiDB 历史版本中 GC 配置的变化信息,请使用左侧导航栏中的 _"TIDB 版本选择器"_ 切换到本文档的历史版本。 +## TiDB 6.1.0 的变化 -## TiDB 6.1.0 引入的变化 +在 TiDB v6.1.0 之前,TiDB 中的事务不会影响 GC 安全点。从 v6.1.0 开始,TiDB 在计算 GC 安全点时会考虑事务的 startTS,以解决要访问的数据已被清除的问题。如果事务时间过长,安全点将被长时间阻塞,这会影响应用程序性能。 -在 TiDB 6.1.0 之前的版本中,TiDB 内部事务不会影响 GC safe point 推进。从 TiDB 6.1.0 版本起,计算 safe point 时会考虑内部事务的 startTS,从而解决内部事务因访问的数据被清理掉而导致失败的问题。带来的负面影响是如果内部事务运行时间过长,会导致 safe point 长时间不推进,进而会影响业务性能。 +在 TiDB v6.1.0 中,引入了系统变量 [`tidb_gc_max_wait_time`](/system-variables.md#tidb_gc_max_wait_time-new-in-v610) 来控制活跃事务阻塞 GC 安全点的最长时间。超过该值后,GC 安全点将被强制推进。 -TiDB v6.1.0 引入了系统变量 [`tidb_gc_max_wait_time`](/system-variables.md#tidb_gc_max_wait_time-从-v610-版本开始引入) 控制活跃事务阻塞 GC safe point 推进的最长时间,超过该值后 GC safe point 会强制向后推进。 +### Compaction Filter 中的 GC -## GC in Compaction Filter 机制 +基于 `DISTRIBUTED` GC 模式,Compaction Filter 中的 GC 机制使用 RocksDB 的 compaction 过程,而不是单独的 GC 工作线程来运行 GC。这种新的 GC 机制有助于避免 GC 造成的额外磁盘读取。同时,在清除过时数据后,它避免了大量剩余的墓碑标记,这些标记会降低顺序扫描性能。 -GC in Compaction Filter 机制是在分布式 GC 模式 (`DISTRIBUTED` GC mode) 的基础上,由 RocksDB 的 Compaction 过程来进行 GC,而不再使用一个单独的 GC worker 线程。这样做的好处是避免了 GC 引起的额外磁盘读取,以及避免清理掉的旧版本残留大量删除标记影响顺序扫描性能。可以由 TiKV 配置文件中的以下开关控制: + + +> **注意:** +> +> 以下修改 TiKV 配置的示例仅适用于 TiDB Self-Managed。对于 TiDB Cloud,Compaction Filter 中的 GC 机制默认启用。 + + + +以下示例展示如何在 TiKV 配置文件中启用该机制: {{< copyable "" >}} @@ -51,7 +73,7 @@ GC in Compaction Filter 机制是在分布式 GC 模式 (`DISTRIBUTED` GC mode) enable-compaction-filter = true ``` -该 GC 机制可通过在线配置变更开启: +你也可以通过动态修改配置来启用这个 GC 机制。请参考以下示例: {{< copyable "sql" >}} @@ -85,10 +107,3 @@ show config where type = 'tikv' and name like '%enable-compaction-filter%'; | tikv | 172.16.5.35:20163 | gc.enable-compaction-filter | true | +------+-------------------+-----------------------------+-------+ ``` - -> **注意:** -> -> 在使用 Compaction Filter 机制时,可能会出现 GC 进度延迟的情况,从而影响 TiKV 扫描性能。当你的负载中含有大量 coprocessor 请求,并且在 [**TiKV-Details > Coprocessor Detail**](/grafana-tikv-dashboard.md#coprocessor-detail) 面板中发现 Total Ops Details 的 `next()` 或 `prev()` 调用次数远远超过 `processed_keys` 调用的三倍时,可以采取以下措施: -> -> - 对于 TiDB v7.1.3 之前版本,建议尝试关闭 Compaction Filter,以加快 GC 速度。 -> - 从 v7.1.3 开始,TiDB 会根据每个 Region 的冗余版本数量 [`region-compact-min-redundant-rows`](/tikv-configuration-file.md#region-compact-min-redundant-rows-从-v710-版本开始引入) 和比例 [`region-compact-redundant-rows-percent`](/tikv-configuration-file.md#region-compact-redundant-rows-percent-从-v710-版本开始引入) 自动触发 compaction,从而提高 Compaction Filter 的 GC 速度。因此,在 v7.1.3 及之后的版本中,如果遇到上述情况,建议调整这两个参数,无需关闭 Compaction Filter。 diff --git a/garbage-collection-overview.md b/garbage-collection-overview.md index 9e3d832b555d..41dd7439586c 100644 --- a/garbage-collection-overview.md +++ b/garbage-collection-overview.md @@ -1,53 +1,51 @@ --- -title: GC 机制简介 -summary: TiDB 的事务实现采用了 MVCC 机制,GC 的任务是清理不再需要的旧数据。整体流程包括 GC leader 控制 GC 的运行,定期触发 GC,以及三个步骤:Resolve Locks 清理锁,Delete Ranges 删除区间,Do GC 进行 GC 清理。Resolve Locks 清理锁有两种执行模式:LEGACY 和 PHYSICAL。Delete Ranges 删除区间会快速物理删除待删除的区间及删除操作的时间戳。Do GC 进行 GC 清理会删除所有 key 的过期版本。GC 每 10 分钟触发一次,默认保留最近 10 分钟内的数据。 +title: GC 概述 +summary: 了解 TiDB 中的垃圾回收机制。 --- -# GC 机制简介 +# GC 概述 -TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。Garbage Collection (GC) 的任务便是清理不再需要的旧数据。 +TiDB 使用 MVCC 来控制事务并发。当你更新数据时,原始数据不会立即删除,而是与新数据一起保留,并使用时间戳来区分版本。垃圾回收(GC)的目标是清理过时的数据。 -## 整体流程 +## GC 过程 -一个 TiDB 集群中会有一个 TiDB 实例被选举为 GC leader,GC 的运行由 GC leader 来控制。 +每个 TiDB 集群都包含一个被选为 GC leader 的 TiDB 实例,它负责控制 GC 过程。 -GC 会被定期触发。每次 GC 时,首先,TiDB 会计算一个称为 safe point 的时间戳,接下来 TiDB 会在保证 safe point 之后的快照全部拥有正确数据的前提下,删除更早的过期数据。每一轮 GC 分为以下三个步骤: +GC 在 TiDB 上周期性运行。对于每次 GC,TiDB 首先计算一个称为"安全点"的时间戳。然后,TiDB 在确保安全点之后的所有快照都保持数据完整性的前提下清理过时的数据。具体来说,每个 GC 过程包含以下三个步骤: -1. "Resolve Locks" 阶段会对所有 Region 扫描 safe point 之前的锁,并清理这些锁。 -2. "Delete Ranges" 阶段快速地删除由于 `DROP TABLE`/`DROP INDEX` 等操作产生的整区间的废弃数据。 -3. "Do GC" 阶段每个 TiKV 节点将会各自扫描该节点上的数据,并对每一个 key 删除其不再需要的旧版本。 +1. 解决锁(Resolve Locks)。在此步骤中,TiDB 扫描所有 Region 上安全点之前的锁,并清理这些锁。 +2. 删除范围(Delete Ranges)。在此步骤中,快速清理由 `DROP TABLE`/`DROP INDEX` 操作产生的整个范围的过时数据。 +3. 执行 GC(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)。 +在默认配置中,GC 每 10 分钟触发一次。每次 GC 保留最近 10 分钟的数据,这意味着 GC 生命周期默认为 10 分钟(安全点 = 当前时间 - GC 生命周期)。如果一轮 GC 运行时间过长,在这轮 GC 完成之前,即使到了触发下一轮 GC 的时间,下一轮 GC 也不会开始。此外,为了让超过 GC 生命周期的长时间事务能够正常运行,安全点不会超过正在进行的事务的开始时间(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 锁,那么就永远无法得知该锁是否可以提交。这样,数据的正确性就无法保证。 +TiDB 事务模型是基于 [Google 的 Percolator](https://ai.google/research/pubs/pub36726) 实现的。它主要是一个两阶段提交协议,并进行了一些实践优化。当第一阶段完成时,所有相关的 key 都被锁定。在这些锁中,一个是主锁(primary lock),其他是包含指向主锁指针的次级锁(secondary locks);在第二阶段,带有主锁的 key 获得一个写记录,并移除其锁。写记录表示该 key 在历史中的写入或删除操作,或者该 key 的事务回滚记录。替换主锁的写记录类型表明相应的事务是否成功提交。然后所有次级锁被依次替换。如果由于故障等原因,这些次级锁被保留而未被替换,你仍然可以根据次级锁中的信息找到主键,并根据主键是否提交来确定整个事务是否提交。但是,如果主键信息被 GC 清理,而该事务有未提交的次级锁,你将永远无法知道这些锁是否可以提交。因此,无法保证数据完整性。 -Resolve Locks 这一步的任务即对 safe point 之前的锁进行清理。即如果一个锁对应的 Primary 已经提交,那么该锁也应该被提交;反之,则应该回滚。而如果 Primary 仍然是上锁的状态(没有提交也没有回滚),则应当将该事务视为超时失败而回滚。 +解决锁步骤清理安全点之前的锁。这意味着如果锁的主键已提交,则需要提交该锁;否则,需要回滚。如果主键仍然被锁定(未提交或回滚),则该事务被视为超时并回滚。 -Resolve Locks 有两种执行模式: - -- `LEGACY` (默认模式):由 GC leader 对所有的 Region 发送请求扫描过期的锁,并对扫到的锁查询 Primary 的状态,再发送请求对其进行提交或回滚。 -- `PHYSICAL`:TiDB 绕过 Raft 层直接扫描每个 TiKV 节点上的数据。 +解决锁步骤可以通过以下两种方式之一实现,可以使用系统变量 [`tidb_gc_scan_lock_mode`](/system-variables.md#tidb_gc_scan_lock_mode-new-in-v50) 进行配置: > **警告:** > -> `PHYSICAL`模式(即启用 Green GC)目前是实验性功能,不建议在生产环境中使用。 +> 目前,`PHYSICAL`(Green GC)是一个实验性功能。不建议在生产环境中使用。 -你可以通过修改系统变量 [`tidb_gc_scan_lock_mode`](/system-variables.md#tidb_gc_scan_lock_mode-从-v50-版本开始引入) 的值切换 Resolve Locks 的执行模式。 +- `LEGACY`(默认):GC leader 向所有 Region 发送请求以扫描过时的锁,检查扫描到的锁的主键状态,并发送请求以提交或回滚相应的事务。 +- `PHYSICAL`:TiDB 绕过 Raft 层,直接在每个 TiKV 节点上扫描数据。 -### Delete Ranges(删除区间) +### 删除范围 -在执行 `DROP TABLE/INDEX` 等操作时,会有大量连续的数据被删除。如果对每个 key 都进行删除操作、再对每个 key 进行 GC 的话,那么执行效率和空间回收速度都可能非常的低下。事实上,这种时候 TiDB 并不会对每个 key 进行删除操作,而是将这些待删除的区间及删除操作的时间戳记录下来。Delete Ranges 会将这些时间戳在 safe point 之前的区间进行快速的物理删除。 +在 `DROP TABLE/INDEX` 等操作期间,会删除大量具有连续键的数据。删除每个 key 并在之后对它们执行 GC 会导致存储回收的执行效率低下。在这种情况下,TiDB 实际上不会删除每个 key。相反,它只记录要删除的范围和删除的时间戳。然后删除范围步骤对时间戳在安全点之前的范围执行快速物理删除。 -### Do GC(进行 GC 清理) +### 执行 GC -这一步即删除所有 key 的过期版本。为了保证 safe point 之后的任何时间戳都具有一致的快照,这一步删除 safe point 之前提交的数据,但是会对每个 key 保留 safe point 前的最后一次写入(除非最后一次写入是删除)。 +执行 GC 步骤清理所有 key 的过时版本。为了保证安全点之后的所有时间戳都有一致的快照,此步骤删除安全点之前提交的数据,但保留安全点之前每个 key 的最后一次写入(只要它不是删除操作)。 -在进行这一步时,TiDB 只需要将 safe point 发送给 PD,即可结束整轮 GC。TiKV 会自行检测到 safe point 发生了更新,会对当前节点上所有作为 Region leader 进行 GC。与此同时,GC leader 可以继续触发下一轮 GC。 +在此步骤中,TiDB 只需要将安全点发送到 PD,然后整轮 GC 就完成了。TiKV 自动检测安全点的变化,并对当前节点上的所有 Region leader 执行 GC。同时,GC leader 可以继续触发下一轮 GC。 > **注意:** > -> 从 TiDB 5.0 版本起,`CENTRAL` GC 模式(需要 TiDB 服务器发送 GC 请求到各个 Region)已经废弃,Do GC 这一步将只以 `DISTRIBUTED` GC 模式(从 TiDB 3.0 版起的默认模式)运行。 +> 从 TiDB 5.0 开始,执行 GC 步骤将始终使用 `DISTRIBUTED` gc 模式。这取代了早期由 TiDB 服务器向每个 Region 发送 GC 请求实现的 `CENTRAL` gc 模式。 diff --git a/generated-columns.md b/generated-columns.md index 558982db2555..3d5263c2c89a 100644 --- a/generated-columns.md +++ b/generated-columns.md @@ -1,25 +1,25 @@ --- title: 生成列 -summary: 生成列是由列定义中的表达式计算得到的值。它包括存储生成列和虚拟生成列,存储生成列会将计算得到的值存储起来,而虚拟生成列不会存储其值。生成列可以用于从 JSON 数据类型中解出数据,并为该数据建立索引。在 INSERT 和 UPDATE 语句中,会检查生成列计算得到的值是否满足生成列的定义。生成列的局限性包括不能增加存储生成列,不能转换存储生成列为普通列,不能修改存储生成列的生成列表达式,以及不支持所有的 JSON 函数。 +summary: 了解如何使用生成列。 --- # 生成列 -本文介绍生成列的概念以及用法。 +本文介绍生成列的概念和用法。 -## 生成列的基本概念 +## 基本概念 -与一般的列不同,生成列的值由列定义中表达式计算得到。对生成列进行插入或更新操作时,并不能对之赋值,只能使用 `DEFAULT`。 +与普通列不同,生成列的值是由列定义中的表达式计算得出的。在插入或更新生成列时,你不能为其赋值,只能使用 `DEFAULT`。 -生成列包括存储生成列和虚拟生成列。存储生成列会将计算得到的值存储起来,在读取时不需要重新计算。虚拟生成列不会存储其值,在读取时会重新计算。存储生成列和虚拟生成列相比,前者在读取时性能更好,但是要占用更多的磁盘空间。 +生成列有两种类型:虚拟生成列和存储生成列。虚拟生成列不占用存储空间,在读取时计算。存储生成列在写入(插入或更新)时计算,并占用存储空间。与虚拟生成列相比,存储生成列具有更好的读取性能,但会占用更多磁盘空间。 -无论是存储生成列还是虚拟列,都可以在其上面建立索引。 +无论是虚拟生成列还是存储生成列,你都可以在其上创建索引。 -## 生成列的应用 +## 用法 -生成列的主要的作用之一:从 JSON 数据类型中解出数据,并为该数据建立索引。 +生成列的主要用途之一是从 JSON 数据类型中提取数据并为其建立索引。 -MySQL 8.0 及 TiDB 都不能直接为 JSON 类型的列添加索引,即不支持在如下表结构中的 `address_info` 上建立索引: +在 MySQL 8.0 和 TiDB 中,JSON 类型的列不能直接创建索引。也就是说,以下表结构是**不支持的**: {{< copyable "sql" >}} @@ -32,9 +32,9 @@ CREATE TABLE person ( ); ``` -如果要为 JSON 列某个字段添加索引,可以抽取该字段为生成列。 +要为 JSON 列创建索引,你必须先将其提取为生成列。 -以 `city` 这一 `address_info` 中的字段为例,可以为其建立一个虚拟生成列并添加索引: +以 `address_info` 中的 `city` 字段为例,你可以创建一个虚拟生成列并为其添加索引: {{< copyable "sql" >}} @@ -50,7 +50,7 @@ CREATE TABLE person ( ); ``` -该表中,`city` 列是一个虚拟生成列。并且在该列上建立了索引。以下语句能够利用索引加速语句的执行速度: +在这个表中,`city` 列是一个**虚拟生成列**并且有一个索引。以下查询可以使用该索引来加速执行: {{< copyable "sql" >}} @@ -64,7 +64,7 @@ SELECT name, id FROM person WHERE city = 'Beijing'; EXPLAIN SELECT name, id FROM person WHERE city = 'Beijing'; ``` -``` +```sql +---------------------------------+---------+-----------+--------------------------------+-------------------------------------------------------------+ | id | estRows | task | access object | operator info | +---------------------------------+---------+-----------+--------------------------------+-------------------------------------------------------------+ @@ -75,9 +75,9 @@ EXPLAIN SELECT name, id FROM person WHERE city = 'Beijing'; +---------------------------------+---------+-----------+--------------------------------+-------------------------------------------------------------+ ``` -从执行计划中,可以看出使用了 `city` 这个索引来读取满足 `city = 'Beijing'` 这个条件的行的 `HANDLE`,再用这个 `HANDLE` 来读取该行的数据。 +从查询执行计划可以看出,使用了 `city` 索引来读取满足条件 `city ='Beijing'` 的行的 `HANDLE`,然后使用这个 `HANDLE` 来读取行的数据。 -如果 `$.city` 路径中无数据,则 `JSON_EXTRACT` 返回 `NULL`。如果想增加约束,`city` 列必须是 `NOT NULL`,则可按照以下方式定义虚拟生成列: +如果路径 `$.city` 处不存在数据,`JSON_EXTRACT` 返回 `NULL`。如果你想强制约束 `city` 必须为 `NOT NULL`,可以按如下方式定义虚拟生成列: {{< copyable "sql" >}} @@ -91,27 +91,22 @@ CREATE TABLE person ( ); ``` -## 生成列在 INSERT 和 UPDATE 语句中的行为 +## 生成列的验证 -`INSERT` 和 `UPDATE` 语句都会检查生成列计算得到的值是否满足生成列的定义。未通过有效性检测的行会返回错误: +`INSERT` 和 `UPDATE` 语句都会检查虚拟列定义。不通过验证的行会返回错误: {{< copyable "sql" >}} ```sql -INSERT INTO person (name, address_info) VALUES ('Morgan', JSON_OBJECT('Country', 'Canada')); -``` - -``` +mysql> INSERT INTO person (name, address_info) VALUES ('Morgan', JSON_OBJECT('Country', 'Canada')); ERROR 1048 (23000): Column 'city' cannot be null ``` -## 索引生成列替换 - -当查询中出现的某个表达式与一个含索引的生成列严格同等时,TiDB 会将这个表达式替换为对应的生成列,这样就可以在生成查询计划时考虑使用这个索引。 +## 生成列索引替换规则 -下面的例子为 `a+1` 这个表达式创建生成列并添加索引,从而加速查询。其中,`a` 的列类型是 int,而 `a+1` 的列类型是 bigint。如果将生成列的类型改为 int,就不会发生替换。关于类型转换的规则,可以参见[表达式求值的类型转换](/functions-and-operators/type-conversion-in-expression-evaluation.md)。 +当查询中的表达式与带有索引的生成列严格等价时,TiDB 会用相应的生成列替换该表达式,这样优化器在构建执行计划时就可以考虑使用该索引。 -{{< copyable "sql" >}} +以下示例为表达式 `a+1` 创建生成列并添加索引。列 `a` 的类型为 int,`a+1` 的列类型为 bigint。如果将生成列的类型设置为 int,则不会发生替换。关于类型转换规则,请参见[表达式求值的类型转换](/functions-and-operators/type-conversion-in-expression-evaluation.md)。 ```sql create table t(a int); @@ -148,15 +143,15 @@ desc select a+1 from t where a+1=3; > **注意:** > -> 若待替换的表达式类型和生成列类型都是字符类型,但两种类型长度不同时,仍可通过将系统变量 [`tidb_enable_unsafe_substitute`](/system-variables.md#tidb_enable_unsafe_substitute-从-v630-版本开始引入) 设置为 `ON` 来允许其替换。配置该系统变量时,需要保证生成列计算得到的值严格满足生成列的定义,否则,可能因为长度不同,导致数据截断得到错误的结果。详情见 GitHub issue [#35490](https://github.com/pingcap/tidb/issues/35490#issuecomment-1211658886)。 +> 如果要替换的表达式和生成列都是字符串类型但长度不同,你可以通过将系统变量 [`tidb_enable_unsafe_substitute`](/system-variables.md#tidb_enable_unsafe_substitute-new-in-v630) 设置为 `ON` 来实现替换。在配置此系统变量时,请确保生成列计算的值严格满足生成列的定义。否则,由于长度差异可能导致数据被截断,从而导致结果不正确。详见 GitHub issue [#35490](https://github.com/pingcap/tidb/issues/35490#issuecomment-1211658886)。 -## 生成列的局限性 +## 限制 -目前生成列有以下局限性: +JSON 和生成列当前的限制如下: -- 不能通过 `ALTER TABLE` 增加存储生成列; -- 不能通过 `ALTER TABLE` 将存储生成列转换为普通列,也不能将普通列转换成存储生成列; -- 不能通过 `ALTER TABLE` 修改存储生成列的生成列表达式; -- 并未支持所有的 [JSON 函数](/functions-and-operators/json-functions.md); -- 不支持使用 [`NULLIF()` 函数](/functions-and-operators/control-flow-functions.md#nullif),可以使用 [`CASE` 函数](/functions-and-operators/control-flow-functions.md#case)代替; -- 目前仅当生成列是虚拟生成列时索引生成列替换规则有效,暂不支持将表达式替换为存储生成列,但仍然可以通过直接使用该生成列本身来使用索引。 +- 不能通过 `ALTER TABLE` 添加存储生成列。 +- 不能通过 `ALTER TABLE` 语句将存储生成列转换为普通列,也不能将普通列转换为存储生成列。 +- 不能通过 `ALTER TABLE` 语句修改存储生成列的表达式。 +- 不是所有的 [JSON 函数](/functions-and-operators/json-functions.md)都支持。 +- 不支持 [`NULLIF()` 函数](/functions-and-operators/control-flow-functions.md#nullif)。你可以使用 [`CASE` 函数](/functions-and-operators/control-flow-functions.md#case)代替。 +- 目前,生成列索引替换规则仅在生成列是虚拟生成列时有效。对于存储生成列不生效,但可以通过直接使用生成列本身来使用索引。 diff --git a/information-schema/client-errors-summary-by-host.md b/information-schema/client-errors-summary-by-host.md index dfe64264f925..ba7c45ddd243 100644 --- a/information-schema/client-errors-summary-by-host.md +++ b/information-schema/client-errors-summary-by-host.md @@ -1,28 +1,28 @@ --- title: CLIENT_ERRORS_SUMMARY_BY_HOST -summary: 了解 INFORMATION_SCHEMA 表 `CLIENT_ERRORS_SUMMARY_BY_HOST`。 +summary: 了解 `CLIENT_ERRORS_SUMMARY_BY_HOST` INFORMATION_SCHEMA 表。 --- # CLIENT_ERRORS_SUMMARY_BY_HOST -`CLIENT_ERRORS_SUMMARY_BY_HOST` 表汇总了已返回给连接到 TiDB 服务器的客户端的 SQL 错误和警告。这些错误和警告包括: +`CLIENT_ERRORS_SUMMARY_BY_HOST` 表提供了返回给连接到 TiDB 服务器的客户端的 SQL 错误和警告的摘要。这些包括: * 格式错误的 SQL 语句。 -* 除以零错误。 -* 尝试插入超出范围或重复的键值。 +* 除零错误。 +* 尝试插入超出范围或重复键值。 * 权限错误。 * 表不存在。 -以上错误通过 MySQL 服务器协议返回给客户端,此时应用程序应在客户端采取适当操作。`INFORMATION_SCHEMA.CLIENT_ERRORS_SUMMARY_BY_HOST` 表提供了一种有效方法,能够在应用程序没有正确处理(或记录)TiDB 服务器返回的错误的情况下检查错误。 +这些错误通过 MySQL 服务器协议返回给客户端,应用程序需要采取适当的操作。在应用程序没有正确处理(或记录)TiDB 服务器返回的错误的情况下,`INFORMATION_SCHEMA.CLIENT_ERRORS_SUMMARY_BY_HOST` 表提供了一种检查错误的有用方法。 -由于 `CLIENT_ERRORS_SUMMARY_BY_HOST` 会基于每个远程主机汇总错误,在诊断其中一台应用程序服务器比其他服务器生成更多错误的情况时很有用。可能的情况包括: +由于 `CLIENT_ERRORS_SUMMARY_BY_HOST` 按远程主机汇总错误,因此它可以用于诊断某个应用服务器产生的错误比其他服务器多的情况。可能的场景包括: * 过时的 MySQL 客户端库。 -* 过时的应用程序(可能是在推出新部署时遗漏了此服务器)。 -* 用户权限中“主机”部分的使用不正确。 -* 网络连接不可靠,导致更多超时或连接断开。 +* 过时的应用程序(可能在部署新版本时遗漏了这台服务器)。 +* 用户权限中的 "host" 部分使用不当。 +* 网络连接不稳定导致更多超时或断开连接。 -可以使用 `FLUSH CLIENT_ERRORS_SUMMARY` 语句重置汇总的计数。所汇总的是每个 TiDB 服务器的本地数据,并且只保留在内存中。如果 TiDB 服务器重新启动,会丢失汇总信息。 +可以使用 `FLUSH CLIENT_ERRORS_SUMMARY` 语句重置汇总计数。摘要信息仅在每个 TiDB 服务器本地保存,并且只保存在内存中。如果 TiDB 服务器重启,摘要信息将会丢失。 ```sql USE INFORMATION_SCHEMA; @@ -46,17 +46,17 @@ DESC CLIENT_ERRORS_SUMMARY_BY_HOST; 7 rows in set (0.00 sec) ``` -字段说明如下: +字段说明: * `HOST`:客户端的远程主机。 -* `ERROR_NUMBER`:返回的与 MySQL 兼容的错误码。 -* `ERROR_MESSAGE`:与错误码匹配的错误消息(预处理语句形式)。 -* `ERROR_COUNT`:此错误返回到客户端主机的次数。 -* `WARNING_COUNT`:此警告返回到客户端主机的次数。 -* `FIRST_SEEN`:首次从客户端主机看到此错误(或警告)的时间。 -* `LAST_SEEN`:最近一次从客户端主机看到此错误(或警告)的时间。 - -以下示例显示了客户端连接到本地 TiDB 服务器时生成的警告。执行 `FLUSH CLIENT_ERRORS_SUMMARY` 语句后,会重置汇总。 +* `ERROR_NUMBER`:返回的 MySQL 兼容错误号。 +* `ERROR_MESSAGE`:与错误号匹配的错误消息(以预处理语句形式)。 +* `ERROR_COUNT`:此错误返回给客户端主机的次数。 +* `WARNING_COUNT`:此警告返回给客户端主机的次数。 +* `FIRST_SEEN`:从客户端主机首次看到此错误(或警告)的时间。 +* `LAST_SEEN`:从客户端主机最近一次看到此错误(或警告)的时间。 + +以下示例显示了客户端连接到本地 TiDB 服务器时生成的警告。执行 `FLUSH CLIENT_ERRORS_SUMMARY` 后重置摘要: ```sql SELECT 0/0; diff --git a/information-schema/client-errors-summary-by-user.md b/information-schema/client-errors-summary-by-user.md index 13233b023d72..2ada26ae3ae8 100644 --- a/information-schema/client-errors-summary-by-user.md +++ b/information-schema/client-errors-summary-by-user.md @@ -1,33 +1,35 @@ --- title: CLIENT_ERRORS_SUMMARY_BY_USER -summary: 了解 INFORMATION_SCHEMA 表 `CLIENT_ERRORS_SUMMARY_BY_USER`。 +summary: 了解 `CLIENT_ERRORS_SUMMARY_BY_USER` INFORMATION_SCHEMA 表。 --- # CLIENT_ERRORS_SUMMARY_BY_USER -`CLIENT_ERRORS_SUMMARY_BY_USER` 表汇总了已返回给连接到 TiDB 服务器的客户端的 SQL 错误和警告。这些错误和警告包括: +`CLIENT_ERRORS_SUMMARY_BY_USER` 表提供了连接到 TiDB 服务器的客户端收到的 SQL 错误和警告的摘要信息。这些包括: * 格式错误的 SQL 语句。 -* 除以零错误。 -* 尝试插入超出范围或重复的键值。 +* 除零错误。 +* 尝试插入超出范围或重复键值。 * 权限错误。 * 表不存在。 -以上错误通过 MySQL 服务器协议返回给客户端,此时应用程序应在客户端采取适当操作。`INFORMATION_SCHEMA.CLIENT_ERRORS_SUMMARY_BY_USER` 表提供了一种有效方法,能够在应用程序没有正确处理(或记录)TiDB 服务器返回的错误的情况下检查错误。 +客户端错误通过 MySQL 服务器协议返回给客户端,应用程序需要采取适当的操作。在应用程序没有正确处理(或记录)TiDB 服务器返回的错误的情况下,`INFORMATION_SCHEMA.CLIENT_ERRORS_SUMMARY_BY_USER` 表提供了一种检查错误的有用方法。 -因为 `CLIENT_ERRORS_SUMMARY_BY_USER` 会基于每个用户汇总错误,所以在诊断一个用户服务器比其他服务器产生更多错误的方案时很有用。可能的情况包括: +由于 `CLIENT_ERRORS_SUMMARY_BY_USER` 按用户汇总错误,因此它可以用于诊断某个用户服务器产生的错误比其他服务器多的情况。可能的场景包括: * 权限错误。 -* 表或关系对象丢失。 -* SQL 语法不正确,或应用程序和 TiDB 版本之间不兼容。 +* 缺少表或关系对象。 +* SQL 语法错误,或应用程序与 TiDB 版本之间的不兼容。 -可以使用 `FLUSH CLIENT_ERRORS_SUMMARY` 语句重置汇总的计数。所汇总的是每个 TiDB 服务器的本地数据,并且只保留在内存中。如果 TiDB 服务器重新启动,会丢失汇总信息。 +可以使用 `FLUSH CLIENT_ERRORS_SUMMARY` 语句重置汇总计数。摘要信息仅在每个 TiDB 服务器本地保存,并且只保存在内存中。如果 TiDB 服务器重启,摘要信息将会丢失。 ```sql USE INFORMATION_SCHEMA; DESC CLIENT_ERRORS_SUMMARY_BY_USER; ``` +输出结果如下: + ```sql +---------------+---------------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | @@ -43,17 +45,17 @@ DESC CLIENT_ERRORS_SUMMARY_BY_USER; 7 rows in set (0.00 sec) ``` -字段说明如下: +字段说明: * `USER`:已认证的用户。 -* `ERROR_NUMBER`:返回的与 MySQL 兼容的错误码。 -* `ERROR_MESSAGE`:与错误码匹配的错误消息(预处理语句形式)。 -* `ERROR_COUNT`:返回此错误给用户的次数。 -* `WARNING_COUNT`:返回此警告给用户的次数。 -* `FIRST_SEEN`:首次向用户发送此错误(或警告)的时间。 -* `LAST_SEEN`:最近一次向用户发送此错误(或警告)的时间。 - -以下示例显示了客户端连接到本地 TiDB 服务器时生成的警告。执行 `FLUSH CLIENT_ERRORS_SUMMARY` 语句后,会重置汇总。 +* `ERROR_NUMBER`:返回的 MySQL 兼容错误号。 +* `ERROR_MESSAGE`:与错误号匹配的错误消息(以预处理语句形式)。 +* `ERROR_COUNT`:此错误返回给用户的次数。 +* `WARNING_COUNT`:此警告返回给用户的次数。 +* `FIRST_SEEN`:此错误(或警告)首次发送给用户的时间。 +* `LAST_SEEN`:此错误(或警告)最近一次发送给用户的时间。 + +以下示例展示了客户端连接到本地 TiDB 服务器时生成的警告。执行 `FLUSH CLIENT_ERRORS_SUMMARY` 后重置摘要: ```sql SELECT 0/0; diff --git a/information-schema/client-errors-summary-global.md b/information-schema/client-errors-summary-global.md index a48385c3ce38..9de7b3228152 100644 --- a/information-schema/client-errors-summary-global.md +++ b/information-schema/client-errors-summary-global.md @@ -1,28 +1,28 @@ --- title: CLIENT_ERRORS_SUMMARY_GLOBAL -summary: 了解 information_schema 表 `CLIENT_ERRORS_SUMMARY_GLOBAL`。 +summary: 了解 `CLIENT_ERRORS_SUMMARY_GLOBAL` INFORMATION_SCHEMA 表。 --- # CLIENT_ERRORS_SUMMARY_GLOBAL -`CLIENT_ERRORS_SUMMARY_GLOBAL` 表汇总了已返回给连接到 TiDB 服务器的客户端的 SQL 错误和警告。这些错误和警告包括: +`CLIENT_ERRORS_SUMMARY_GLOBAL` 表提供了连接到 TiDB 服务器的客户端收到的所有 SQL 错误和警告的全局汇总。这些包括: * 格式错误的 SQL 语句。 -* 除以零错误。 +* 除零错误。 * 尝试插入超出范围或重复的键值。 * 权限错误。 * 表不存在。 -以上错误通过 MySQL 服务器协议返回给客户端,此时应用程序应在客户端采取适当操作。`information_schema.CLIENT_ERRORS_SUMMARY_BY_GLOBAL` 表提供了高级概述,在应用程序无法正确处理(或记录)TiDB 服务器返回的错误的情况下很有用。 +客户端错误通过 MySQL 服务器协议返回给客户端,应用程序需要采取适当的操作。`INFORMATION_SCHEMA.CLIENT_ERRORS_SUMMARY_GLOBAL` 表提供了一个高层次的概览,在应用程序没有正确处理(或记录)TiDB 服务器返回的错误的情况下特别有用。 -可以使用 `FLUSH CLIENT_ERRORS_SUMMARY` 语句重置汇总的计数。所汇总的是每个 TiDB 服务器的本地数据,并且只保留在内存中。如果 TiDB 服务器重新启动,会丢失汇总信息。 +可以使用 `FLUSH CLIENT_ERRORS_SUMMARY` 语句重置汇总计数。该汇总信息对每个 TiDB 服务器都是本地的,并且仅保存在内存中。如果 TiDB 服务器重启,汇总信息将会丢失。 ```sql -USE information_schema; +USE INFORMATION_SCHEMA; DESC CLIENT_ERRORS_SUMMARY_GLOBAL; ``` -输出结果如下: +输出如下: ```sql +---------------+---------------+------+------+---------+-------+ @@ -38,16 +38,16 @@ DESC CLIENT_ERRORS_SUMMARY_GLOBAL; 6 rows in set (0.00 sec) ``` -字段说明如下: +字段说明: -* `ERROR_NUMBER`:返回的与 MySQL 兼容的错误码。 -* `ERROR_MESSAGE`:与错误码匹配的错误消息(预处理语句形式)。 -* `ERROR_COUNT`:返回此错误的次数。 -* `WARNING_COUNT`:返回此警告的次数。 -* `FIRST_SEEN`:首次返回此错误(或警告)的时间。 +* `ERROR_NUMBER`:返回的 MySQL 兼容错误号。 +* `ERROR_MESSAGE`:与错误号匹配的错误消息(以预处理语句形式)。 +* `ERROR_COUNT`:此错误返回的次数。 +* `WARNING_COUNT`:此警告返回的次数。 +* `FIRST_SEEN`:首次发送此错误(或警告)的时间。 * `LAST_SEEN`:最近一次发送此错误(或警告)的时间。 -以下示例显示了客户端连接到本地 TiDB 服务器时生成的警告。执行 `FLUSH CLIENT_ERRORS_SUMMARY` 语句后,会重置汇总。 +以下示例展示了连接到本地 TiDB 服务器时生成的警告。执行 `FLUSH CLIENT_ERRORS_SUMMARY` 后重置汇总信息: ```sql SELECT 0/0; @@ -56,7 +56,7 @@ FLUSH CLIENT_ERRORS_SUMMARY; SELECT * FROM CLIENT_ERRORS_SUMMARY_GLOBAL; ``` -输出结果如下: +输出如下: ```sql +-----+ @@ -76,4 +76,4 @@ SELECT * FROM CLIENT_ERRORS_SUMMARY_GLOBAL; Query OK, 0 rows affected (0.00 sec) Empty set (0.00 sec) -``` \ No newline at end of file +``` diff --git a/information-schema/information-schema-analyze-status.md b/information-schema/information-schema-analyze-status.md index 2634c0fbbaaa..1ecc2aa1b20d 100644 --- a/information-schema/information-schema-analyze-status.md +++ b/information-schema/information-schema-analyze-status.md @@ -1,15 +1,15 @@ --- title: ANALYZE_STATUS -summary: 了解 information_schema 表 `ANALYZE_STATUS`。 +summary: 了解 `ANALYZE_STATUS` information_schema 表。 --- # ANALYZE_STATUS -`ANALYZE_STATUS` 表提供正在执行的收集统计信息的任务以及有限条历史任务记录。 +`ANALYZE_STATUS` 表提供了正在运行的统计信息收集任务和有限数量的历史任务的信息。 -从 TiDB v6.1.0 起,`ANALYZE_STATUS` 表显示集群级别的任务,且 TiDB 重启后仍能看到重启之前的任务记录。在 TiDB v6.1.0 之前,`ANALYZE_STATUS` 仅显示实例级别的任务,且 TiDB 重启后任务记录会被清空。 +从 TiDB v6.1.0 开始,`ANALYZE_STATUS` 表支持显示集群级别的任务。即使在 TiDB 重启后,你仍然可以通过此表查看重启前的任务记录。在 TiDB v6.1.0 之前,`ANALYZE_STATUS` 表只能显示实例级别的任务,且任务记录会在 TiDB 重启后被清除。 -从 TiDB v6.1.0 起,可以通过系统表 `mysql.analyze_jobs` 查看过去 7 天内的历史任务记录。 +从 TiDB v6.1.0 开始,你可以通过系统表 `mysql.analyze_jobs` 查看最近 7 天的历史任务。 ```sql USE information_schema; @@ -38,6 +38,8 @@ DESC analyze_status; 14 rows in set (0.00 sec) ``` +{{< copyable "sql" >}} + ```sql SELECT * FROM information_schema.analyze_status; ``` @@ -57,24 +59,24 @@ SELECT * FROM information_schema.analyze_status; 6 rows in set (0.00 sec) ``` -`ANALYZE_STATUS` 表中列的含义如下: +`ANALYZE_STATUS` 表中的字段说明如下: -* `TABLE_SCHEMA`:表所属的数据库的名称。 -* `TABLE_NAME`:表的名称。 -* `PARTITION_NAME`:分区表的名称。 -* `JOB_INFO`:`ANALYZE` 任务的信息。如果分析索引,该信息会包含索引名。当 `tidb_analyze_version = 2` 时,该信息会包含采样率等配置项。 -* `PROCESSED_ROWS`:已经处理的行数。 +* `TABLE_SCHEMA`:表所属的数据库名称。 +* `TABLE_NAME`:表名。 +* `PARTITION_NAME`:分区表的分区名称。 +* `JOB_INFO`:`ANALYZE` 任务的信息。如果分析的是索引,该信息会包含索引名称。当 `tidb_analyze_version = 2` 时,该信息会包含采样率等配置项。 +* `PROCESSED_ROWS`:已处理的行数。 * `START_TIME`:`ANALYZE` 任务的开始时间。 * `END_TIME`:`ANALYZE` 任务的结束时间。 -* `STATE`:`ANALYZE` 任务的执行状态。其值可以是 `pending`、`running`、`finished` 或者 `failed`。 -* `FAIL_REASON`:任务失败的原因。如果执行成功则为 `NULL`。 +* `STATE`:`ANALYZE` 任务的执行状态。其值可以是 `pending`、`running`、`finished` 或 `failed`。 +* `FAIL_REASON`:任务失败的原因。如果执行成功,该值为 `NULL`。 * `INSTANCE`:执行任务的 TiDB 实例。 -* `PROCESS_ID`:执行任务的 process ID。 -* `REMAINING_SECONDS`:执行任务预计还需要多少秒才能完成。 -* `PROGRESS`:执行任务的进度。 -* `ESTIMATED_TOTAL_ROWS`:执行任务需要分析的总行数。 +* `PROCESS_ID`:执行任务的进程 ID。 +* `REMAINING_SECONDS`:任务完成的预计剩余时间(以秒为单位)。 +* `PROGRESS`:任务的进度。 +* `ESTIMATED_TOTAL_ROWS`:任务需要分析的总行数。 ## 另请参阅 - [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) -- [`SHOW ANALYZE STATUS`](/sql-statements/sql-statement-show-analyze-status.md) \ No newline at end of file +- [`SHOW ANALYZE STATUS`](/sql-statements/sql-statement-show-analyze-status.md) diff --git a/information-schema/information-schema-character-sets.md b/information-schema/information-schema-character-sets.md index 2f92cd4ad367..887b764c1af2 100644 --- a/information-schema/information-schema-character-sets.md +++ b/information-schema/information-schema-character-sets.md @@ -1,11 +1,11 @@ --- title: CHARACTER_SETS -summary: 了解 INFORMATION_SCHEMA 表 `CHARACTER_SETS`。 +summary: 了解 `CHARACTER_SETS` INFORMATION_SCHEMA 表。 --- # CHARACTER_SETS -`CHARACTER_SETS` 表提供[字符集](/character-set-and-collation.md)相关的信息。TiDB 目前仅支持部分字符集。 +`CHARACTER_SETS` 表提供了关于[字符集](/character-set-and-collation.md)的信息。目前,TiDB 仅支持部分字符集。 ```sql USE INFORMATION_SCHEMA; @@ -14,7 +14,7 @@ DESC CHARACTER_SETS; 输出结果如下: -```sql +``` +----------------------+-------------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------------+-------------+------+------+---------+-------+ @@ -26,7 +26,7 @@ DESC CHARACTER_SETS; 4 rows in set (0.00 sec) ``` -查看 `CHARACTER_SETS` 表的信息: +查看 `CHARACTER_SETS` 表: ```sql SELECT * FROM `CHARACTER_SETS`; @@ -48,16 +48,16 @@ SELECT * FROM `CHARACTER_SETS`; 6 rows in set (0.00 sec) ``` -`CHARACTER_SETS` 表中列的含义如下: +`CHARACTER_SETS` 表中各列的描述如下: -* `CHARACTER_SET_NAME`:字符集名称 -* `DEFAULT_COLLATE_NAME`:字符集的默认排序规则名称 -* `DESCRIPTION`:字符集的描述信息 -* `MAXLEN`:该字符集存储一个字符所需要的最大字节数 +* `CHARACTER_SET_NAME`:字符集的名称。 +* `DEFAULT_COLLATE_NAME`:字符集的默认排序规则名称。 +* `DESCRIPTION`:字符集的描述。 +* `MAXLEN`:在此字符集中存储一个字符所需的最大长度。 ## 另请参阅 - [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) - [`SHOW COLLATION`](/sql-statements/sql-statement-show-collation.md) - [`INFORMATION_SCHEMA.COLLATIONS`](/information-schema/information-schema-collations.md) -- [`INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) \ No newline at end of file +- [`INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) diff --git a/information-schema/information-schema-check-constraints.md b/information-schema/information-schema-check-constraints.md index daf979d0dd65..5dc2c218cd57 100644 --- a/information-schema/information-schema-check-constraints.md +++ b/information-schema/information-schema-check-constraints.md @@ -1,18 +1,18 @@ --- title: CHECK_CONSTRAINTS -summary: 了解 INFORMATION_SCHEMA 表 `CHECK_CONSTRAINTS`。 +summary: 了解 INFORMATION_SCHEMA 中的 `CHECK_CONSTRAINTS` 表。 --- # CHECK\_CONSTRAINTS -`CHECK_CONSTRAINTS` 表提供关于表上 [`CHECK` 约束](/constraints.md#check-约束)的信息。 +`CHECK_CONSTRAINTS` 表提供了表上 [`CHECK` 约束](/constraints.md#check)的相关信息。 ```sql USE INFORMATION_SCHEMA; DESC CHECK_CONSTRAINTS; ``` -命令输出如下: +输出如下: ```sql +--------------------+-------------+------+-----+---------+-------+ @@ -26,7 +26,7 @@ DESC CHECK_CONSTRAINTS; 4 rows in set (0.00 sec) ``` -下述示例使用 `CREATE TABLE` 语句添加 `CHECK` 约束: +以下示例使用 `CREATE TABLE` 语句添加一个 `CHECK` 约束: ```sql SET GLOBAL tidb_enable_check_constraint = ON; @@ -34,7 +34,7 @@ CREATE TABLE test.t1 (id INT PRIMARY KEY, CHECK (id%2 = 0)); SELECT * FROM CHECK_CONSTRAINTS\G ``` -命令输出如下: +输出如下: ```sql *************************** 1. row *************************** @@ -45,9 +45,9 @@ CONSTRAINT_CATALOG: def 1 row in set (0.00 sec) ``` -`CHECK_CONSTRAINTS` 表的字段描述如下: +`CHECK_CONSTRAINTS` 表中的字段说明如下: * `CONSTRAINT_CATALOG`:约束的目录,始终为 `def`。 -* `CONSTRAINT_SCHEMA`:约束的库名。 -* `CONSTRAINT_NAME`:约束的名字。 -* `CHECK_CLAUSE`:检查约束的子句。 +* `CONSTRAINT_SCHEMA`:约束所属的数据库架构。 +* `CONSTRAINT_NAME`:约束的名称。 +* `CHECK_CLAUSE`:检查约束的条件子句。 diff --git a/information-schema/information-schema-cluster-info.md b/information-schema/information-schema-cluster-info.md index 557a94577f12..46029ebf0e9f 100644 --- a/information-schema/information-schema-cluster-info.md +++ b/information-schema/information-schema-cluster-info.md @@ -1,11 +1,15 @@ --- title: CLUSTER_INFO -summary: 了解 TiDB 集群拓扑表 `CLUSTER_INFO`。 +summary: 了解 `CLUSTER_INFO` 集群拓扑信息表。 --- # CLUSTER_INFO -集群拓扑表 `CLUSTER_INFO` 提供集群当前的拓扑信息,以及各个节点的版本信息、版本对应的 Git Hash、各节点的启动时间、各实例的运行时间。 +`CLUSTER_INFO` 集群拓扑表提供了集群的当前拓扑信息,包括每个实例的版本信息、实例版本对应的 Git Hash、每个实例的启动时间以及每个实例的运行时间。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群中不可用。 {{< copyable "sql" >}} @@ -30,16 +34,16 @@ desc cluster_info; 8 rows in set (0.01 sec) ``` -字段解释: +字段说明: -* `TYPE`:节点类型,目前节点的可取值为 `tidb`,`pd` 和 `tikv`。 -* `INSTANCE`:实例地址,为 `IP:PORT` 格式的字符串。 -* `STATUS_ADDRESS`:HTTP API 的服务地址。部分 `tikv-ctl`、`pd-ctl` 或 `tidb-ctl` 命令会使用到 HTTP API 和该地址。用户也可以通过该地址获取一些额外的集群信息,详情可参考 [HTTP API 文档](https://github.com/pingcap/tidb/blob/release-8.1/docs/tidb_http_api.md)。 -* `VERSION`:对应节点的语义版本号。TiDB 版本为了兼容 MySQL 的版本号,以 `${mysql-version}-${tidb-version}` 的格式展示版本号。 -* `GIT_HASH`:编译节点版本时的 Git Commit Hash,用于识别两个节点是否是绝对一致的版本。 -* `START_TIME`:对应节点的启动时间。 -* `UPTIME`:对应节点已经运行的时间。 -* `SERVER_ID`:对应节点的服务器 ID。 +* `TYPE`:实例类型。可选值为 `tidb`、`pd` 和 `tikv`。 +* `INSTANCE`:实例地址,格式为 `IP:PORT` 的字符串。 +* `STATUS_ADDRESS`:HTTP API 的服务地址。tikv-ctl、pd-ctl 或 tidb-ctl 中的某些命令可能会使用此 API 和地址。您还可以通过此地址获取更多集群信息。详情请参考 [TiDB HTTP API 文档](https://github.com/pingcap/tidb/blob/release-8.1/docs/tidb_http_api.md)。 +* `VERSION`:对应实例的语义版本号。为了与 MySQL 版本号兼容,TiDB 版本以 `${mysql-version}-${tidb-version}` 的格式显示。 +* `GIT_HASH`:编译实例版本时的 Git Commit Hash,用于标识两个实例是否为完全一致的版本。 +* `START_TIME`:对应实例的启动时间。 +* `UPTIME`:对应实例的运行时间。 +* `SERVER_ID`:对应实例的服务器 ID。 {{< copyable "sql" >}} diff --git a/information-schema/information-schema-collation-character-set-applicability.md b/information-schema/information-schema-collation-character-set-applicability.md index a0035f058247..393e78f0906f 100644 --- a/information-schema/information-schema-collation-character-set-applicability.md +++ b/information-schema/information-schema-collation-character-set-applicability.md @@ -1,18 +1,18 @@ --- title: COLLATION_CHARACTER_SET_APPLICABILITY -summary: 了解 INFORMATION_SCHEMA 表 `COLLATION_CHARACTER_SET_APPLICABILITY`。 +summary: 了解 `COLLATION_CHARACTER_SET_APPLICABILITY` INFORMATION_SCHEMA 表。 --- # COLLATION_CHARACTER_SET_APPLICABILITY -`COLLATION_CHARACTER_SET_APPLICABILITY` 表将排序规则映射至适用的字符集名称。和 `COLLATIONS` 表一样,包含此表只是为了兼容 MySQL。 +`COLLATION_CHARACTER_SET_APPLICABILITY` 表将排序规则映射到适用的字符集名称。与 `COLLATIONS` 表类似,它仅为了与 MySQL 兼容而包含。 ```sql USE INFORMATION_SCHEMA; DESC COLLATION_CHARACTER_SET_APPLICABILITY; ``` -输出结果如下: +输出如下: ```sql +--------------------+-------------+------+------+---------+-------+ @@ -24,13 +24,13 @@ DESC COLLATION_CHARACTER_SET_APPLICABILITY; 2 rows in set (0.00 sec) ``` -查看 `COLLATION_CHARACTER_SET_APPLICABILITY` 表中 `utf8mb4` 字符集的排序规则映射: +在 `COLLATION_CHARACTER_SET_APPLICABILITY` 表中查看 `utf8mb4` 字符集的排序规则映射: ```sql SELECT * FROM COLLATION_CHARACTER_SET_APPLICABILITY WHERE character_set_name='utf8mb4'; ``` -输出结果如下: +输出如下: ```sql +--------------------+--------------------+ @@ -43,14 +43,14 @@ SELECT * FROM COLLATION_CHARACTER_SET_APPLICABILITY WHERE character_set_name='ut 3 rows in set (0.00 sec) ``` -`COLLATION_CHARACTER_SET_APPLICABILITY` 表中列的含义如下: +`COLLATION_CHARACTER_SET_APPLICABILITY` 表中各列的说明如下: -* `COLLATION_NAME`:排序规则名称 -* `CHARACTER_SET_NAME`:排序规则所属的字符集名称 +* `COLLATION_NAME`:排序规则的名称。 +* `CHARACTER_SET_NAME`:排序规则所属的字符集名称。 ## 另请参阅 - [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) - [`SHOW COLLATION`](/sql-statements/sql-statement-show-collation.md) - [`INFORMATION_SCHEMA.CHARACTER_SETS`](/information-schema/information-schema-character-sets.md) -- [`INFORMATION_SCHEMA.COLLATIONS`](/information-schema/information-schema-collations.md) \ No newline at end of file +- [`INFORMATION_SCHEMA.COLLATIONS`](/information-schema/information-schema-collations.md) diff --git a/information-schema/information-schema-collations.md b/information-schema/information-schema-collations.md index ffc027b78d28..133ca343984b 100644 --- a/information-schema/information-schema-collations.md +++ b/information-schema/information-schema-collations.md @@ -1,11 +1,11 @@ --- title: COLLATIONS -summary: 了解 information_schema 表 `COLLATIONS`。 +summary: 了解 `COLLATIONS` information_schema 表。 --- # COLLATIONS -`COLLATIONS` 表提供了 `CHARACTER_SETS` 表中字符集对应的排序规则列表。目前 TiDB 包含该表仅为兼容 MySQL。 +`COLLATIONS` 表提供了与 `CHARACTER_SETS` 表中的字符集相对应的排序规则列表。目前,此表仅为了与 MySQL 兼容而包含。 {{< copyable "sql" >}} @@ -45,18 +45,18 @@ SELECT * FROM collations WHERE character_set_name='utf8mb4'; 3 rows in set (0.001 sec) ``` -`COLLATIONS` 表中列的含义如下: +`COLLATIONS` 表中各列的描述如下: -* `COLLATION_NAME`:排序规则名称 -* `CHARACTER_SET_NAME`:排序规则所属的字符集名称 -* `ID`:排序规则的 ID -* `IS_DEFAULT`:该排序规则是否是所属字符集的默认排序规则 -* `IS_COMPILED`:字符集是否编译到服务器中 -* `SORTLEN`:排序规则在对字符进行排序时,所分配内存的最小长度 +* `COLLATION_NAME`:排序规则的名称。 +* `CHARACTER_SET_NAME`:该排序规则所属的字符集名称。 +* `ID`:排序规则的 ID。 +* `IS_DEFAULT`:该排序规则是否是其所属字符集的默认排序规则。 +* `IS_COMPILED`:该字符集是否已编译到服务器中。 +* `SORTLEN`:排序规则在排序字符时分配的最小内存长度。 ## 另请参阅 - [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) - [`SHOW COLLATION`](/sql-statements/sql-statement-show-collation.md) - [`INFORMATION_SCHEMA.CHARACTER_SETS`](/information-schema/information-schema-character-sets.md) -- [`INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) \ No newline at end of file +- [`INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) diff --git a/information-schema/information-schema-columns.md b/information-schema/information-schema-columns.md index 05b2c86117ed..d9bb1d3a363f 100644 --- a/information-schema/information-schema-columns.md +++ b/information-schema/information-schema-columns.md @@ -1,11 +1,11 @@ --- title: COLUMNS -summary: 了解 INFORMATION_SCHEMA 表 `COLUMNS`。 +summary: 了解 `COLUMNS` INFORMATION_SCHEMA 表。 --- # COLUMNS -`COLUMNS` 表提供了表的所有列的信息。 +`COLUMNS` 表提供了关于表中列的详细信息。 ```sql USE INFORMATION_SCHEMA; @@ -32,7 +32,7 @@ DESC COLUMNS; | NUMERIC_SCALE | bigint(21) | YES | | NULL | | | DATETIME_PRECISION | bigint(21) | YES | | NULL | | | CHARACTER_SET_NAME | varchar(32) | YES | | NULL | | -| COLLATION_NAME | varchar(32) | YES | | NULL | | +| COLLATION_NAME | varchar(32) | YES | | NULL | | | COLUMN_TYPE | text | YES | | NULL | | | COLUMN_KEY | varchar(3) | YES | | NULL | | | EXTRA | varchar(30) | YES | | NULL | | @@ -43,7 +43,7 @@ DESC COLUMNS; 21 rows in set (0.00 sec) ``` -创建表 `test.t1`,并查询 `COLUMNS` 表的信息: +创建表 `test.t1` 并查询 `COLUMNS` 表中的信息: ```sql CREATE TABLE test.t1 (a int); @@ -78,33 +78,33 @@ CHARACTER_MAXIMUM_LENGTH: NULL 1 row in set (0.02 sec) ``` -`COLUMNS` 表中列的含义如下: - -* `TABLE_CATALOG`:包含列的表所属的目录的名称。该值始终为 `def`。 -* `TABLE_SCHEMA`:包含列的表所属的数据库的名称。 -* `TABLE_NAME`:包含列的表的名称。 -* `COLUMN_NAME`:列的名称。 -* `ORDINAL_POSITION`:表中列的位置。 -* `COLUMN_DEFAULT`:列的默认值。如果列的显式默认值为 `NULL`,或者列定义中不包含 `default` 子句,则此值为 `NULL`。 -* `IS_NULLABLE`:列的可空性。如果列中可以存储空值,则该值为 `YES`,否则为 `NO`。 -* `DATA_TYPE`:列的数据类型。 -* `CHARACTER_MAXIMUM_LENGTH`:对于字符串列,以字符为单位的最大长度。 -* `CHARACTER_OCTET_LENGTH`:对于字符串列,以字节为单位的最大长度。 -* `NUMERIC_PRECISION`:对于数字列,为数字精度。 -* `NUMERIC_SCALE`:对于数字列,为数字刻度。 -* `DATETIME_PRECISION`:对于时间列,小数秒精度。 -* `CHARACTER_SET_NAME`:对于字符串列,字符集名称。 -* `COLLATION_NAME`:对于字符串列,排序规则名称。 +`COLUMNS` 表中各列的描述如下: + +* `TABLE_CATALOG`:包含该列的表所属的目录名称。该值始终为 `def`。 +* `TABLE_SCHEMA`:包含该列的表所在的数据库(schema)名称。 +* `TABLE_NAME`:包含该列的表名。 +* `COLUMN_NAME`:列名。 +* `ORDINAL_POSITION`:该列在表中的位置。 +* `COLUMN_DEFAULT`:列的默认值。如果显式默认值为 `NULL`,或者列定义中不包含 `default` 子句,则该值为 `NULL`。 +* `IS_NULLABLE`:该列是否可为空。如果该列可以存储 NULL 值,则该值为 `YES`;否则为 `NO`。 +* `DATA_TYPE`:列中数据的类型。 +* `CHARACTER_MAXIMUM_LENGTH`:对于字符串列,表示最大字符长度。 +* `CHARACTER_OCTET_LENGTH`:对于字符串列,表示最大字节长度。 +* `NUMERIC_PRECISION`:数字类型列的数值精度。 +* `NUMERIC_SCALE`:数字类型列的数值小数位数。 +* `DATETIME_PRECISION`:对于时间类型列,表示小数秒精度。 +* `CHARACTER_SET_NAME`:字符串列的字符集名称。 +* `COLLATION_NAME`:字符串列的排序规则名称。 * `COLUMN_TYPE`:列类型。 -* `COLUMN_KEY`:该列是否被索引。具体显示如下: - * 如果此值为空,则该列要么未被索引,要么被索引且是多列非唯一索引中的第二列。 - * 如果此值是 `PRI`,则该列是主键,或者是多列主键中的一列。 - * 如果此值是 `UNI`,则该列是唯一索引的第一列。 - * 如果此值是 `MUL`,则该列是非唯一索引的第一列,在该列中允许给定值的多次出现。 -* `EXTRA`:关于给定列的任何附加信息。 -* `PRIVILEGES`:当前用户对该列拥有的权限。目前在 TiDB 中,此值为定值,一直为 `select,insert,update,references`。 +* `COLUMN_KEY`:该列是否被索引。该字段可能有以下值: + * 空:该列未被索引,或该列被索引但是是多列非唯一索引中的第二列。 + * `PRI`:该列是主键或多个主键之一。 + * `UNI`:该列是唯一索引的第一列。 + * `MUL`:该列是非唯一索引的第一列,其中给定值允许出现多次。 +* `EXTRA`:给定列的任何附加信息。 +* `PRIVILEGES`:当前用户对该列拥有的权限。目前在 TiDB 中该值是固定的,始终为 `select,insert,update,references`。 * `COLUMN_COMMENT`:列定义中包含的注释。 -* `GENERATION_EXPRESSION`:对于生成的列,显示用于计算列值的表达式。对于未生成的列为空。 +* `GENERATION_EXPRESSION`:对于生成列,该值显示用于计算列值的表达式。对于非生成列,该值为空。 对应的 `SHOW` 语句如下: @@ -125,4 +125,4 @@ SHOW COLUMNS FROM t1 FROM test; ## 另请参阅 -- [`SHOW COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) \ No newline at end of file +- [`SHOW COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) diff --git a/information-schema/information-schema-data-lock-waits.md b/information-schema/information-schema-data-lock-waits.md index a3158ff9bbfe..43cd4e0f95f3 100644 --- a/information-schema/information-schema-data-lock-waits.md +++ b/information-schema/information-schema-data-lock-waits.md @@ -1,11 +1,11 @@ --- title: DATA_LOCK_WAITS -summary: 了解 information_schema 表 `DATA_LOCK_WAITS`。 +summary: 了解 `DATA_LOCK_WAITS` information_schema 表。 --- # DATA_LOCK_WAITS -`DATA_LOCK_WAITS` 表展示了集群中所有 TiKV 节点上当前正在发生的等锁情况,包括悲观锁的等锁情况和乐观事务被阻塞的信息。 +`DATA_LOCK_WAITS` 表显示集群中所有 TiKV 节点上正在进行的锁等待信息,包括悲观事务的锁等待信息和被阻塞的乐观事务的信息。 {{< copyable "sql" >}} @@ -27,47 +27,47 @@ DESC data_lock_waits; +------------------------+---------------------+------+------+---------+-------+ ``` -`DATA_LOCK_WAITS` 表中各列的字段含义如下: +`DATA_LOCK_WAITS` 表中各列字段的含义如下: -* `KEY`:正在发生等锁的 key,以十六进制编码的形式显示。 -* `KEY_INFO`:对 `KEY` 进行解读得出的一些详细信息,见 [KEY_INFO](#key_info)。 -* `TRX_ID`:正在等锁的事务 ID,即 `start_ts`。 -* `CURRENT_HOLDING_TRX_ID`:当前持有锁的事务 ID,即 `start_ts`。 -* `SQL_DIGEST`:当前正在等锁的事务中被阻塞的 SQL 语句的 Digest。 -* `SQL_DIGEST_TEXT`:当前正在等锁的事务中被阻塞的 SQL 语句的归一化形式,即去除了参数和格式的 SQL 语句。与 `SQL_DIGEST` 对应。 +* `KEY`:正在等待锁的键,以十六进制形式表示。 +* `KEY_INFO`:`KEY` 的详细信息。参见 [KEY_INFO](#key_info) 部分。 +* `TRX_ID`:等待锁的事务 ID。此 ID 也是事务的 `start_ts`。 +* `CURRENT_HOLDING_TRX_ID`:当前持有锁的事务 ID。此 ID 也是事务的 `start_ts`。 +* `SQL_DIGEST`:锁等待事务中当前被阻塞的 SQL 语句的摘要。 +* `SQL_DIGEST_TEXT`:锁等待事务中当前被阻塞的规范化 SQL 语句(不含参数和格式的 SQL 语句)。它与 `SQL_DIGEST` 相对应。 > **警告:** > -> * 仅拥有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户可以查询该表。 -> * 由于实现限制,目前对于乐观事务被阻塞情况的 `SQL_DIGEST` 和 `SQL_DIGEST_TEXT` 字段为 `null`。如果需要知道导致阻塞的 SQL 语句,可以将此表与 [`CLUSTER_TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) 进行 `JOIN` 来获得对应事务的所有 SQL 语句。 -> * `DATA_LOCK_WAITS` 表中的信息是在查询时,从所有 TiKV 节点实时获取的。目前,即使加上了 `WHERE` 查询条件,也无法避免对所有 TiKV 节点都进行信息收集。如果集群规模很大、负载很高,查询该表有造成性能抖动的潜在风险,因此请根据实际情况使用。 -> * 来自不同 TiKV 节点的信息不能保证是同一时间点的快照。 -> * `SQL_DIGEST` 列中的信息(SQL Digest)为 SQL 语句进行归一化后计算得到的哈希值。`SQL_DIGEST_TEXT` 列中的信息为内部从 Statements Summary 系列表中查询得到,因而存在内部查询不到对应语句的可能性。关于 SQL Digest 和 Statements Summary 相关表的详细说明,请参阅[Statement Summary Tables](/statement-summary-tables.md)。 +> * 只有具有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户才能查询此表。 +> * 目前,对于乐观事务,`SQL_DIGEST` 和 `SQL_DIGEST_TEXT` 字段为 `null`(表示不可用)。作为解决方法,要找出导致阻塞的 SQL 语句,你可以将此表与 [`CLUSTER_TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) 联合查询,以获取乐观事务的所有 SQL 语句。 +> * `DATA_LOCK_WAITS` 表中的信息是在查询期间从所有 TiKV 节点实时获取的。目前,即使查询有 `WHERE` 条件,信息收集仍会在所有 TiKV 节点上进行。如果你的集群较大且负载较高,查询此表可能会带来性能抖动的潜在风险。因此,请根据实际情况使用。 +> * 来自不同 TiKV 节点的信息不保证是同一时间点的快照。 +> * `SQL_DIGEST` 列中的信息(SQL 摘要)是从规范化 SQL 语句计算得出的哈希值。`SQL_DIGEST_TEXT` 列中的信息是从语句概要表内部查询的,因此可能找不到相应的语句。有关 SQL 摘要和语句概要表的详细说明,请参见[语句概要表](/statement-summary-tables.md)。 ## `KEY_INFO` -`KEY_INFO` 列中展示了对 `KEY` 列中所给出的 key 的详细信息,以 JSON 格式给出。其包含的信息如下: - -* `"db_id"`:该 key 所属的数据库(schema)的 ID。 -* `"db_name"`:该 key 所属的数据库(schema)的名称。 -* `"table_id"`:该 key 所属的表的 ID。 -* `"table_name"`:该 key 所属的表的名称。 -* `"partition_id"`:该 key 所在的分区(partition)的 ID。 -* `"partition_name"`:该 key 所在的分区(partition)的名称。 -* `"handle_type"`:该 row key (即储存一行数据的 key)的 handle 类型,其可能的值有: - * `"int"`:handle 为 int 类型,即 handle 为 row ID - * `"common"`:非 int64 类型的 handle,在启用 clustered index 时非 int 类型的主键会显示为此类型 - * `"unknown"`:当前暂不支持的 handle 类型 -* `"handle_value"`:handle 的值。 -* `"index_id"`:该 index key (即储存索引的 key)所属的 index ID。 -* `"index_name"`:该 index key 所属的 index 名称。 -* `"index_values"`:该 index key 中的 index value。 - -其中,不适用或当前无法查询到的信息会被省略。比如,row key 的信息中不会包含 `index_id`、`index_name` 和 `index_values`;index key 不会包含 `handle_type` 和 `handle_value`;非分区表不会显示 `partition_id` 和 `partition_name`;已经被删除掉的表中的 key 的信息无法获取 `table_name`、`db_id`、`db_name`、`index_name` 等 schema 信息,且无法区分是否为分区表。 +`KEY_INFO` 列显示 `KEY` 列的详细信息。信息以 JSON 格式显示。各字段说明如下: + +* `"db_id"`:键所属 schema 的 ID。 +* `"db_name"`:键所属 schema 的名称。 +* `"table_id"`:键所属表的 ID。 +* `"table_name"`:键所属表的名称。 +* `"partition_id"`:键所在分区的 ID。 +* `"partition_name"`:键所在分区的名称。 +* `"handle_type"`:行键(即存储一行数据的键)的句柄类型。可能的值如下: + * `"int"`:句柄类型为 int,表示句柄是行 ID。 + * `"common"`:句柄类型不是 int64。这种类型在启用聚簇索引时的非整数主键中显示。 + * `"unknown"`:当前不支持的句柄类型。 +* `"handle_value"`:句柄值。 +* `"index_id"`:索引键(存储索引的键)所属的索引 ID。 +* `"index_name"`:索引键所属的索引名称。 +* `"index_values"`:索引键中的索引值。 + +在上述字段中,如果某个字段的信息不适用或当前不可用,则该字段在查询结果中会被省略。例如,行键信息不包含 `index_id`、`index_name` 和 `index_values`;索引键不包含 `handle_type` 和 `handle_value`;非分区表不显示 `partition_id` 和 `partition_name`;已删除表中的键信息无法获取 `table_name`、`db_id`、`db_name` 和 `index_name` 等 schema 信息,也无法区分该表是否为分区表。 > **注意:** > -> 如果一个 key 来自一张启用了分区的表,而在查询时,由于某些原因(例如,其所属的表已经被删除)导致无法查询其所属的 schema 信息,则其所属的分区的 ID 可能会出现在 `table_id` 字段中。这是因为,TiDB 对不同分区的 key 的编码方式与对几张独立的表的 key 的编码方式一致,因而在缺失 schema 信息时无法确认该 key 属于一张未分区的表还是某张表的一个分区。 +> 如果一个键来自启用了分区的表,并且在查询期间由于某些原因(例如,键所属的表已被删除)无法查询到该键所属的 schema 信息,则该键所属的分区的 ID 可能会出现在 `table_id` 字段中。这是因为 TiDB 对不同分区的键的编码方式与对几个独立表的键的编码方式相同。因此,当缺少 schema 信息时,TiDB 无法确认该键是属于非分区表还是属于某个表的一个分区。 ## 示例 @@ -88,4 +88,4 @@ CURRENT_HOLDING_TRX_ID: 426790590082449409 1 row in set (0.01 sec) ``` -以上查询结果显示,ID 为 `426790594290122753` 的事务在执行 Digest 为 `"38b03afa5debbdf0326a014dbe5012a62c51957f1982b3093e748460f8b00821"`、形如 ``update `t` set `v` = `v` + ? where `id` = ?`` 的语句的过程中,试图在 `"7480000000000000355F728000000000000001"` 这个 key 上获取悲观锁,但是该 key 上的锁目前被 ID 为 `426790590082449409` 的事务持有。 +上述查询结果显示,ID 为 `426790594290122753` 的事务在执行摘要为 `"38b03afa5debbdf0326a014dbe5012a62c51957f1982b3093e748460f8b00821"` 且形式为 ``update `t` set `v` = `v` + ? where `id` = ?`` 的语句时,正在尝试获取键 `"7480000000000000355F728000000000000001"` 的悲观锁,但该键的锁被 ID 为 `426790590082449409` 的事务持有。 diff --git a/information-schema/information-schema-ddl-jobs.md b/information-schema/information-schema-ddl-jobs.md index 36eb63a47a97..af897429743b 100644 --- a/information-schema/information-schema-ddl-jobs.md +++ b/information-schema/information-schema-ddl-jobs.md @@ -1,11 +1,11 @@ --- title: DDL_JOBS -summary: 了解 information_schema 表 `DDL_JOBS`。 +summary: 了解 `DDL_JOBS` information_schema 表。 --- # DDL_JOBS -`DDL_JOBS` 表为 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 命令提供了一个 `INFORMATION_SCHEMA` 接口。它提供了 TiDB 集群中 DDL 操作的当前状态、DDL 语句、起始时间、结束时间、库表名称等信息。 +`DDL_JOBS` 表为 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 命令提供了一个 `INFORMATION_SCHEMA` 接口。它提供了 TiDB 集群中 DDL 操作的相关信息,例如当前状态、DDL 语句、开始时间、结束时间、数据库名称和表名。 ```sql USE information_schema; diff --git a/information-schema/information-schema-deadlocks.md b/information-schema/information-schema-deadlocks.md index 37545f1296ec..9a6cce281e3f 100644 --- a/information-schema/information-schema-deadlocks.md +++ b/information-schema/information-schema-deadlocks.md @@ -1,15 +1,15 @@ --- title: DEADLOCKS -summary: 了解 INFORMATION_SCHEMA 表 `DEADLOCKS`。 +summary: 了解 `DEADLOCKS` INFORMATION_SCHEMA 表。 --- # DEADLOCKS -`DEADLOCKS` 表提供当前 TiDB 节点上最近发生的若干次死锁错误的信息。 +`DEADLOCKS` 表显示当前 TiDB 节点上最近发生的几次死锁错误的信息。 ```sql USE INFORMATION_SCHEMA; -DESC DEADLOCKS; +DESC deadlocks; ``` 输出结果如下: @@ -30,97 +30,121 @@ DESC DEADLOCKS; +-------------------------+---------------------+------+------+---------+-------+ ``` -`DEADLOCKS` 表中需要用多行来表示同一个死锁事件,每行显示参与死锁的其中一个事务的信息。当该 TiDB 节点记录了多次死锁错误时,需要按照 `DEADLOCK_ID` 列来区分,相同的 `DEADLOCK_ID` 表示同一个死锁事件。需要注意,`DEADLOCK_ID` **并不保证全局唯一,也不会持久化**,因而其只能在同一个结果集里表示同一个死锁事件。 +`DEADLOCKS` 表使用多行来显示同一个死锁事件,每一行显示死锁事件中涉及的其中一个事务的信息。如果 TiDB 节点记录了多个死锁错误,则使用 `DEADLOCK_ID` 列来区分每个错误。相同的 `DEADLOCK_ID` 表示同一个死锁事件。注意,`DEADLOCK_ID` **不保证全局唯一性且不会被持久化**,它仅用于在同一个结果集中表示同一个死锁事件。 -`DEADLOCKS` 表中各列的字段含义如下: +`DEADLOCKS` 表中各列字段的含义如下: -* `DEADLOCK_ID`:死锁事件的 ID。当表内存在多次死锁错误的信息时,需要使用该列来区分属于不同死锁错误的行。 -* `OCCUR_TIME`:发生该次死锁错误的时间。 -* `RETRYABLE`:该次死锁错误是否可重试。关于可重试的死锁错误的说明,参见[可重试的死锁错误](#可重试的死锁错误)小节。 -* `TRY_LOCK_TRX_ID`:试图上锁的事务 ID,即事务的 `start_ts`。 -* `CURRENT_SQL_DIGEST`:试图上锁的事务中当前正在执行的 SQL 语句的 Digest。 -* `CURRENT_SQL_DIGEST_TEXT`:试图上锁的事务中当前正在执行的 SQL 语句的归一化形式。 -* `KEY`:该事务试图上锁、但是被阻塞的 key,以十六进制编码的形式显示。 -* `KEY_INFO`:对 `KEY` 进行解读得出的一些详细信息,详见 [`KEY_INFO`](#key_info)。 -* `TRX_HOLDING_LOCK`:该 key 上当前持锁并导致阻塞的事务 ID,即事务的 `start_ts`。 +* `DEADLOCK_ID`:死锁事件的 ID。当表中存在多个死锁错误时,可以使用此列来区分属于不同死锁错误的行。 +* `OCCUR_TIME`:死锁错误发生的时间。 +* `RETRYABLE`:死锁错误是否可以重试。关于可重试死锁错误的说明,请参见[可重试死锁错误](#可重试死锁错误)部分。 +* `TRY_LOCK_TRX_ID`:尝试获取锁的事务 ID。此 ID 也是事务的 `start_ts`。 +* `CURRENT_SQL_DIGEST`:获取锁事务中当前正在执行的 SQL 语句的摘要。 +* `CURRENT_SQL_DIGEST_TEXT`:获取锁事务中当前正在执行的 SQL 语句的规范化形式。 +* `KEY`:事务尝试锁定的被阻塞的键。此字段的值以十六进制字符串形式显示。 +* `KEY_INFO`:`KEY` 的详细信息。参见 [`KEY_INFO`](#key_info) 部分。 +* `TRX_HOLDING_LOCK`:当前持有该键的锁并导致阻塞的事务 ID。此 ID 也是事务的 `start_ts`。 -要调整 `DEADLOCKS` 表中可以容纳的死锁事件数量,可通过 TiDB 配置文件中的 [`pessimistic-txn.deadlock-history-capacity`](/tidb-configuration-file.md#deadlock-history-capacity) 配置项进行调整,默认容纳最近 10 次死锁错误的信息。 + -> **注意:** +要调整 `DEADLOCKS` 表中可以记录的最大死锁事件数,请在 TiDB 配置文件中调整 [`pessimistic-txn.deadlock-history-capacity`](/tidb-configuration-file.md#deadlock-history-capacity) 配置。默认情况下,表中记录最近 10 次死锁事件的信息。 + + + + + +`DEADLOCKS` 表中记录最近 10 次死锁事件的信息。 + + + +> **警告:** > -> * 仅拥有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户可以查询该表。 -> * `CURRENT_SQL_DIGEST` 列中的信息 (SQL Digest) 为 SQL 语句进行归一化后计算得到的哈希值。`CURRENT_SQL_DIGEST_TEXT` 列中的信息为内部从 Statements Summary 系列表中查询得到,因而存在内部查询不到对应语句的可能性。关于 SQL Digest 和 Statements Summary 相关表的详细说明,请参阅[Statement Summary Tables](/statement-summary-tables.md)。 +> * 只有具有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户才能查询此表。 +> * `CURRENT_SQL_DIGEST` 列中的信息(SQL 摘要)是从规范化 SQL 语句计算得出的哈希值。`CURRENT_SQL_DIGEST_TEXT` 列中的信息是从语句概要表内部查询的,因此可能找不到相应的语句。有关 SQL 摘要和语句概要表的详细说明,请参见[语句概要表](/statement-summary-tables.md)。 ## `KEY_INFO` -`KEY_INFO` 列中展示了对 `KEY` 列中所给出的 key 的详细信息,以 JSON 格式给出。其包含的信息如下: - -* `"db_id"`:该 key 所属的数据库 (schema) 的 ID。 -* `"db_name"`:该 key 所属的数据库 (schema) 的名称。 -* `"table_id"`:该 key 所属的表的 ID。 -* `"table_name"`:该 key 所属的表的名称。 -* `"partition_id"`:该 key 所在的分区 (partition) 的 ID。 -* `"partition_name"`:该 key 所在的分区 (partition) 的名称。 -* `"handle_type"`:该 row key(即储存一行数据的 key)的 handle 类型,其可能的值有: - * `"int"`:handle 为 int 类型,即 handle 为 row ID - * `"common"`:非 int64 类型的 handle,在启用 clustered index 时非 int 类型的主键会显示为此类型 - * `"unknown"`:当前暂不支持的 handle 类型 -* `"handle_value"`:handle 的值。 -* `"index_id"`:该 index key(即储存索引的 key)所属的 index ID。 -* `"index_name"`:该 index key 所属的 index 名称。 -* `"index_values"`:该 index key 中的 index value。 - -其中,不适用或当前无法查询到的信息会被省略。比如,row key 的信息中不会包含 `index_id`、`index_name` 和 `index_values`;index key 不会包含 `handle_type` 和 `handle_value`;非分区表不会显示 `partition_id` 和 `partition_name`;已经被删除掉的表中的 key 的信息无法获取 `table_name`、`db_id`、`db_name`、`index_name` 等 schema 信息,且无法区分是否为分区表。 +`KEY_INFO` 列显示 `KEY` 列的详细信息。信息以 JSON 格式显示。各字段说明如下: + +* `"db_id"`:键所属 schema 的 ID。 +* `"db_name"`:键所属 schema 的名称。 +* `"table_id"`:键所属表的 ID。 +* `"table_name"`:键所属表的名称。 +* `"partition_id"`:键所在分区的 ID。 +* `"partition_name"`:键所在分区的名称。 +* `"handle_type"`:行键(即存储一行数据的键)的句柄类型。可能的值如下: + * `"int"`:句柄类型为 int,表示句柄是行 ID。 + * `"common"`:句柄类型不是 int64。这种类型在启用聚簇索引时的非整数主键中显示。 + * `"unknown"`:当前不支持的句柄类型。 +* `"handle_value"`:句柄值。 +* `"index_id"`:索引键(存储索引的键)所属的索引 ID。 +* `"index_name"`:索引键所属的索引名称。 +* `"index_values"`:索引键中的索引值。 + +在上述字段中,如果某个字段的信息不适用或当前不可用,则该字段在查询结果中会被省略。例如,行键信息不包含 `index_id`、`index_name` 和 `index_values`;索引键不包含 `handle_type` 和 `handle_value`;非分区表不显示 `partition_id` 和 `partition_name`;已删除表中的键信息无法获取 `table_name`、`db_id`、`db_name` 和 `index_name` 等 schema 信息,也无法区分该表是否为分区表。 > **注意:** > -> 如果一个 key 来自一张启用了分区的表,而在查询时,由于某些原因(例如,其所属的表已经被删除)导致无法查询其所属的 schema 信息,则其所属的分区的 ID 可能会出现在 `table_id` 字段中。这是因为,TiDB 对不同分区的 key 的编码方式与对几张独立的表的 key 的编码方式一致,因而在缺失 schema 信息时无法确认该 key 属于一张未分区的表还是某张表的一个分区。 +> 如果一个键来自启用了分区的表,并且在查询期间由于某些原因(例如,键所属的表已被删除)无法查询到该键所属的 schema 信息,则该键所属的分区的 ID 可能会出现在 `table_id` 字段中。这是因为 TiDB 对不同分区的键的编码方式与对几个独立表的键的编码方式相同。因此,当缺少 schema 信息时,TiDB 无法确认该键是属于非分区表还是属于某个表的一个分区。 + +## 可重试死锁错误 -## 可重试的死锁错误 + > **注意:** > -> `DEADLOCKS` 表中默认不收集可重试的死锁错误的信息。如果需要收集,可通过 TiDB 配置文件中的 [`pessimistic-txn.deadlock-history-collect-retryable`](/tidb-configuration-file.md#deadlock-history-collect-retryable) 配置项进行调整。 +> 此部分不适用于 TiDB Cloud。 -当事务 A 被另一个事务 B 已经持有的锁阻塞,而事务 B 直接或间接地被当前事务 A 持有的锁阻塞,将会引发一个死锁错误。这里: + -+ 情况一:事务 B 可能(直接或间接地)被事务 A 开始后到被阻塞前这段时间内已经执行完成的语句产生的锁阻塞 -+ 情况二:事务 B 也可能被事务 A 目前正在执行的语句阻塞 + -对于情况一,TiDB 将会向事务 A 的客户端报告死锁错误,并终止该事务;而对于情况二,事务 A 当前正在执行的语句将在 TiDB 内部被自动重试。例如,假设事务 A 执行了如下语句: +> **注意:** +> +> 默认情况下,`DEADLOCKS` 表不收集可重试死锁错误的信息。如果你希望表收集可重试死锁错误信息,可以在 TiDB 配置文件中调整 [`pessimistic-txn.deadlock-history-collect-retryable`](/tidb-configuration-file.md#deadlock-history-collect-retryable) 的值。 + + + +当事务 A 被事务 B 已持有的锁阻塞,而事务 B 又直接或间接地被当前事务 A 持有的锁阻塞时,就会发生死锁错误。在这个死锁中,可能存在两种情况: + ++ 情况 1:事务 B 可能被事务 A 在开始后、被阻塞前执行的语句生成的锁(直接或间接)阻塞。 ++ 情况 2:事务 B 也可能被事务 A 当前正在执行的语句阻塞。 + +在情况 1 中,TiDB 会向事务 A 的客户端报告死锁错误并终止事务。 + +在情况 2 中,TiDB 会自动重试事务 A 当前正在执行的语句。例如,假设事务 A 执行以下语句: ```sql UPDATE t SET v = v + 1 WHERE id = 1 OR id = 2; ``` -事务 B 则先后执行如下两条语句: +事务 B 依次执行以下两条语句: ```sql UPDATE t SET v = 4 WHERE id = 2; UPDATE t SET v = 2 WHERE id = 1; ``` -那么如果事务 A 先后对 `id = 1` 和 `id = 2` 的两行分别上锁,且两个事务以如下时序运行: +然后,如果事务 A 锁定 `id = 1` 和 `id = 2` 的两行,并且两个事务按以下顺序运行: -1. 事务 A 对 `id = 1` 的行上锁 -2. 事务 B 执行第一条语句并对 `id = 2` 的行上锁 -3. 事务 B 执行第二条语句试图对 `id = 1` 的行上锁,被事务 A 阻塞 -4. 事务 A 试图对 `id = 2` 的行上锁,被 B 阻塞,形成死锁 +1. 事务 A 锁定 `id = 1` 的行。 +2. 事务 B 执行第一条语句并锁定 `id = 2` 的行。 +3. 事务 B 执行第二条语句并尝试锁定 `id = 1` 的行,被事务 A 阻塞。 +4. 事务 A 尝试锁定 `id = 2` 的行并被事务 B 阻塞,形成死锁。 -对于情况二,由于事务 A 阻塞其它事务的语句也是当前正在执行的语句,因而可以解除当前语句所上的悲观锁(使得事务 B 可以继续运行),并重试当前语句。TiDB 内部使用 key 的哈希值来判断是否属于这种情况。 +对于这种情况,由于阻塞其他事务的事务 A 的语句也是当前正在执行的语句,因此可以解除当前语句的悲观锁(以便事务 B 可以继续运行),并重试当前语句。TiDB 内部使用键的哈希来判断是否属于这种情况。 -当可重试的死锁发生时,内部自动重试并不会引起事务报错,因而对客户端透明,但是这种情况的频繁发生可能影响性能。当这种情况发生时,在 TiDB 的日志中可以观察到 `single statement deadlock, retry statement` 字样的日志。 +当发生可重试死锁时,内部自动重试不会导致事务错误,因此对客户端是透明的。但是,如果这种情况频繁发生,可能会影响性能。发生这种情况时,你可以在 TiDB 日志中看到 `single statement deadlock, retry statement`。 ## 示例 1 -假设有如下表定义和初始数据: +假设表定义和初始数据如下: ```sql CREATE TABLE t (id int primary key, v int); INSERT INTO t VALUES (1, 10), (2, 20); ``` -使两个事务按如下顺序执行: +两个事务按以下顺序执行: | 事务 1 | 事务 2 | 说明 | |--------------------------------------|--------------------------------------|----------------------| @@ -128,16 +152,16 @@ INSERT INTO t VALUES (1, 10), (2, 20); | | `BEGIN;` | | | `UPDATE t SET v = 11 WHERE id = 1;` | | | | | `UPDATE t SET v = 21 WHERE id = 2;` | | -| `UPDATE t SET v = 12 WHERE id = 2;` | | 事务 1 阻塞 | -| | `UPDATE t SET v = 22 WHERE id = 1;` | 事务 2 报出死锁错误 | +| `UPDATE t SET v = 12 WHERE id = 2;` | | 事务 1 被阻塞 | +| | `UPDATE t SET v = 22 WHERE id = 1;` | 事务 2 报告死锁错误 | -接下来,事务 2 将报出死锁错误。此时,查询 `DEADLOCKS` 表: +接下来,事务 2 报告死锁错误。此时,查询 `DEADLOCKS` 表: ```sql SELECT * FROM INFORMATION_SCHEMA.DEADLOCKS; ``` -输出结果如下: +预期输出如下: ```sql +-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+ @@ -148,11 +172,11 @@ SELECT * FROM INFORMATION_SCHEMA.DEADLOCKS; +-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+ ``` -该表中产生了两行数据,两行的 `DEADLOCK_ID` 字段皆为 1,表示这两行数据包含同一次死锁错误的信息。第一行显示 ID 为 `426812829645406216` 的事务,在 `"7480000000000000355F728000000000000002"` 这个 key 上,被 ID 为 `"426812829645406217"` 的事务阻塞了;第二行则显示 ID 为 `"426812829645406217"` 的事务在 `"7480000000000000355F728000000000000001"` 这个 key 上被 ID 为 `426812829645406216` 的事务阻塞了,构成了相互阻塞的状态,形成了死锁。 +在 `DEADLOCKS` 表中生成了两行数据。两行的 `DEADLOCK_ID` 字段都是 `1`,表示两行中的信息属于同一个死锁错误。第一行显示,在键 `"7480000000000000355F728000000000000002"` 上,ID 为 `"426812829645406216"` 的事务被 ID 为 `"426812829645406217"` 的事务阻塞。第二行显示,在键 `"7480000000000000355F728000000000000001"` 上,ID 为 `"426812829645406217"` 的事务被 ID 为 `426812829645406216` 的事务阻塞,这构成了互相阻塞,形成了死锁。 ## 示例 2 -假设查询 `DEADLOCKS` 表得到了如下结果集: +假设你查询 `DEADLOCKS` 表,得到以下结果: ```sql +-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+ @@ -166,19 +190,21 @@ SELECT * FROM INFORMATION_SCHEMA.DEADLOCKS; +-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+ ``` -以上查询结果中的 `DEADLOCK_ID` 列表明,前两行共同表示一次死锁错误的信息,两条事务相互等待构成了死锁;而后三行共同表示另一次死锁信息,三个事务循环等待构成了死锁。 +上述查询结果中的 `DEADLOCK_ID` 列显示,前两行一起表示一个死锁错误的信息,两个相互等待的事务形成了死锁。接下来的三行一起表示另一个死锁错误的信息,三个循环等待的事务形成了死锁。 ## CLUSTER_DEADLOCKS -`CLUSTER_DEADLOCKS` 表返回整个集群上每个 TiDB 节点中最近发生的数次死锁错误的信息,即将每个节点上的 `DEADLOCKS` 表内的信息合并在一起。`CLUSTER_DEADLOCKS` 还包含额外的 `INSTANCE` 列展示所属节点的 IP 地址和端口,用以区分不同的 TiDB 节点。 +`CLUSTER_DEADLOCKS` 表返回整个集群中每个 TiDB 节点上最近的死锁错误信息,这是每个节点上 `DEADLOCKS` 表信息的组合。`CLUSTER_DEADLOCKS` 还包括一个额外的 `INSTANCE` 列,用于显示节点的 IP 地址和端口,以区分不同的 TiDB 节点。 -需要注意的是,由于 `DEADLOCK_ID` 并不保证全局唯一,所以在 `CLUSTER_DEADLOCKS` 表的查询结果中,需要 `INSTANCE` 和 `DEADLOCK_ID` 两个字段共同区分结果集中的不同死锁错误的信息。 +注意,由于 `DEADLOCK_ID` 不保证全局唯一性,在 `CLUSTER_DEADLOCKS` 表的查询结果中,你需要同时使用 `INSTANCE` 和 `DEADLOCK_ID` 来区分结果集中不同死锁错误的信息。 ```sql USE INFORMATION_SCHEMA; DESC CLUSTER_DEADLOCKS; ``` +输出结果如下: + ```sql +-------------------------+---------------------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | diff --git a/information-schema/information-schema-engines.md b/information-schema/information-schema-engines.md index 640e66baef61..15a645822a78 100644 --- a/information-schema/information-schema-engines.md +++ b/information-schema/information-schema-engines.md @@ -1,11 +1,11 @@ --- title: ENGINES -summary: 了解 information_schema 表 `ENGINES`。 +summary: 了解 `ENGINES` information_schema 表。 --- # ENGINES -`ENGINES` 表提供了关于存储引擎的信息。从和 MySQL 兼容性上考虑,TiDB 会一直将 InnoDB 描述为唯一支持的引擎。此外,`ENGINES` 表中其它列值也都是定值。 +`ENGINES` 表提供了存储引擎的相关信息。为了保持兼容性,TiDB 将始终将 InnoDB 描述为唯一支持的引擎。此外,`ENGINES` 表中的其他列值也都是固定值。 ```sql USE information_schema; @@ -30,7 +30,7 @@ DESC engines; SELECT * FROM engines; ``` -```sql +``` +--------+---------+------------------------------------------------------------+--------------+------+------------+ | ENGINE | SUPPORT | COMMENT | TRANSACTIONS | XA | SAVEPOINTS | +--------+---------+------------------------------------------------------------+--------------+------+------------+ @@ -39,15 +39,15 @@ SELECT * FROM engines; 1 row in set (0.01 sec) ``` -`ENGINES` 表中列的含义如下: +`ENGINES` 表中各列的描述如下: -* `ENGINE`:存储引擎的名称。 -* `SUPPORT`:服务器对存储引擎的支持级别,在 TiDB 中此值一直是 `DEFAULT`。 -* `COMMENT`:存储引擎的简要描述。 -* `TRANSACTIONS`:存储引擎是否支持事务。 -* `XA`:存储引擎是否支持 XA 事务。 -* `SAVEPOINTS`:存储引擎是否支持 `savepoints`。 +* `ENGINES`:存储引擎的名称。 +* `SUPPORT`:服务器对该存储引擎的支持级别。在 TiDB 中,该值始终为 `DEFAULT`。 +* `COMMENT`:关于该存储引擎的简短说明。 +* `TRANSACTIONS`:该存储引擎是否支持事务。 +* `XA`:该存储引擎是否支持 XA 事务。 +* `SAVEPOINTS`:该存储引擎是否支持 `savepoints`。 ## 另请参阅 -- [`SHOW ENGINES`](/sql-statements/sql-statement-show-engines.md) \ No newline at end of file +- [`SHOW ENGINES`](/sql-statements/sql-statement-show-engines.md) diff --git a/information-schema/information-schema-key-column-usage.md b/information-schema/information-schema-key-column-usage.md index 3c9f51a5e6df..ba0d4450b23f 100644 --- a/information-schema/information-schema-key-column-usage.md +++ b/information-schema/information-schema-key-column-usage.md @@ -1,11 +1,11 @@ --- title: KEY_COLUMN_USAGE -summary: 了解 information_schema 表 `KEY_COLUMN_USAGE`。 +summary: 了解 `KEY_COLUMN_USAGE` information_schema 表。 --- # KEY_COLUMN_USAGE -`KEY_COLUMN_USAGE` 表描述了列的键约束,比如主键约束。 +`KEY_COLUMN_USAGE` 表描述了列的键约束,例如主键约束。 {{< copyable "sql" >}} @@ -14,7 +14,7 @@ USE information_schema; DESC key_column_usage; ``` -```sql +``` +-------------------------------+--------------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------------------+--------------+------+------+---------+-------+ @@ -40,7 +40,7 @@ DESC key_column_usage; SELECT * FROM key_column_usage WHERE table_schema='mysql' and table_name='user'; ``` -```sql +``` *************************** 1. row *************************** CONSTRAINT_CATALOG: def CONSTRAINT_SCHEMA: mysql @@ -70,17 +70,17 @@ POSITION_IN_UNIQUE_CONSTRAINT: NULL 2 rows in set (0.00 sec) ``` -`KEY_COLUMN_USAGE` 表中列的含义如下: +`KEY_COLUMN_USAGE` 表中各列的描述如下: -* `CONSTRAINT_CATALOG`:约束所属的目录的名称。该值始终为 `def`。 -* `CONSTRAINT_SCHEMA`:约束所属的数据库的名称。 -* `CONSTRAINT_NAME`:约束名称。 -* `TABLE_CATALOG`:表所属目录的名称。该值始终为 `def`。 -* `TABLE_SCHEMA`:表所属的架构数据库的名称。 -* `TABLE_NAME`:具有约束的表的名称。 -* `COLUMN_NAME`:具有约束的列的名称。 -* `ORDINAL_POSITION`:列在约束中的位置,而不是列在表中的位置。列位置从 1 开始编号。 -* `POSITION_IN_UNIQUE_CONSTRAINT`:唯一约束和主键约束为空。对于外键约束,此列是被引用的表的键的序号位置。 -* `REFERENCED_TABLE_SCHEMA`:约束引用的数据库的名称。目前在 TiDB 中,除了外键约束,其它约束此列的值都为 `nil`。 -* `REFERENCED_TABLE_NAME`:约束引用的表的名称。目前在 TiDB 中,除了外键约束,其它约束此列的值都为 `nil`。 -* `REFERENCED_COLUMN_NAME`:约束引用的列的名称。目前在 TiDB 中,除了外键约束,其它约束此列的值都为 `nil`。 +* `CONSTRAINT_CATALOG`:约束所属的目录名称。该值始终为 `def`。 +* `CONSTRAINT_SCHEMA`:约束所属的数据库(schema)名称。 +* `CONSTRAINT_NAME`:约束的名称。 +* `TABLE_CATALOG`:表所属的目录名称。该值始终为 `def`。 +* `TABLE_SCHEMA`:表所属的数据库(schema)名称。 +* `TABLE_NAME`:具有约束的表名。 +* `COLUMN_NAME`:具有约束的列名。 +* `ORDINAL_POSITION`:列在约束中的位置,而不是在表中的位置。位置编号从 `1` 开始。 +* `POSITION_IN_UNIQUE_CONSTRAINT`:唯一约束和主键约束为空。对于外键约束,此列是被引用表的键的位置。 +* `REFERENCED_TABLE_SCHEMA`:约束引用的数据库(schema)名称。目前在 TiDB 中,除外键约束外,所有约束中该列的值都为 `nil`。 +* `REFERENCED_TABLE_NAME`:约束引用的表名。目前在 TiDB 中,除外键约束外,所有约束中该列的值都为 `nil`。 +* `REFERENCED_COLUMN_NAME`:约束引用的列名。目前在 TiDB 中,除外键约束外,所有约束中该列的值都为 `nil`。 diff --git a/information-schema/information-schema-keywords.md b/information-schema/information-schema-keywords.md index 94781edb6c02..d4d5cba9eebf 100644 --- a/information-schema/information-schema-keywords.md +++ b/information-schema/information-schema-keywords.md @@ -1,11 +1,11 @@ --- title: KEYWORDS -summary: 了解 INFORMATION_SCHEMA 表 `KEYWORDS`。 +summary: 了解 `KEYWORDS` INFORMATION_SCHEMA 表。 --- # KEYWORDS -TiDB 从 v7.5.3 和 v7.6.0 开始提供 `KEYWORDS` 表,你可以使用该表查看 TiDB 中[关键字](/keywords.md)的信息。 +从 v7.5.3 和 v7.6.0 版本开始,TiDB 提供了 `KEYWORDS` 表。你可以使用此表获取 TiDB 中[关键字](/keywords.md)的相关信息。 ```sql USE INFORMATION_SCHEMA; @@ -24,18 +24,18 @@ DESC keywords; 2 rows in set (0.00 sec) ``` -字段含义如下: +字段说明: -- `WORD`:关键字 -- `RESERVED`:关键字是否为保留关键字 +- `WORD`:关键字。 +- `RESERVED`:表示该关键字是否为保留关键字。 -例如,你可以使用以下 SQL 语句查询 `ADD` 和 `USER` 关键字的信息: +以下语句查询 `ADD` 和 `USER` 关键字的信息: ```sql SELECT * FROM INFORMATION_SCHEMA.KEYWORDS WHERE WORD IN ('ADD','USER'); ``` -输出结果显示 `ADD` 是一个保留关键字,`USER` 是一个非保留关键字。 +从输出结果可以看出,`ADD` 是保留关键字,而 `USER` 是非保留关键字。 ``` +------+----------+ diff --git a/information-schema/information-schema-memory-usage-ops-history.md b/information-schema/information-schema-memory-usage-ops-history.md index 05d987de39f7..d89b5543f85b 100644 --- a/information-schema/information-schema-memory-usage-ops-history.md +++ b/information-schema/information-schema-memory-usage-ops-history.md @@ -1,11 +1,11 @@ --- title: MEMORY_USAGE_OPS_HISTORY -summary: 了解 information_schema 表 `MEMORY_USAGE_OPS_HISTORY`。 +summary: 了解 `MEMORY_USAGE_OPS_HISTORY` information_schema 系统表。 --- # MEMORY_USAGE_OPS_HISTORY -`MEMORY_USAGE_OPS_HISTORY` 表描述了 TiDB 实例内存相关的历史操作和执行依据。 +`MEMORY_USAGE_OPS_HISTORY` 表描述了当前 TiDB 实例的内存相关操作历史记录和执行依据。 ```sql USE information_schema; @@ -47,17 +47,17 @@ SELECT * FROM information_schema.memory_usage_ops_history; 2 rows in set (0.002 sec) ``` -`MEMORY_USAGE_OPS_HISTORY` 表中列的含义如下: - -* TIME:终止会话的时间戳。 -* OPS:"SessionKill" -* MEMORY_LIMIT:TiDB 终止会话时的内存使用限制,单位为 byte。其值和系统变量 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 相同。 -* MEMORY_CURRENT:TiDB 当前的内存使用量,单位为 byte。 -* PROCESSID:被终止会话的客户连接 ID。 -* MEM:被终止的会话已使用的内存使用量,单位是 byte。 -* DISK:被终止的会话已使用的硬盘使用量,单位是 byte。 -* CLIENT:被终止的会话的客户连接的地址。 -* DB:被终止的会话所连接的数据库名。 -* USER:被终止的会话的用户名。 -* SQL_DIGEST:被终止的会话正在执行 SQL 语句的 digest。 -* SQL_TEXT: 被终止的会话正在执行的 SQL 语句。 +`MEMORY_USAGE_OPS_HISTORY` 表中的列说明如下: + +* `TIME`:会话终止的时间戳。 +* `OPS`:"SessionKill" +* `MEMORY_LIMIT`:终止时 TiDB 的内存使用限制,单位为字节。其值与系统变量 `tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-new-in-v640) 的值相同。 +* `MEMORY_CURRENT`:TiDB 当前的内存使用量,单位为字节。 +* `PROCESSID`:被终止会话的连接 ID。 +* `MEM`:被终止会话的内存使用量,单位为字节。 +* `DISK`:被终止会话的磁盘使用量,单位为字节。 +* `CLIENT`:被终止会话的客户端连接地址。 +* `DB`:被终止会话连接的数据库名称。 +* `USER`:被终止会话的用户名。 +* `SQL_DIGEST`:被终止会话中正在执行的 SQL 语句的摘要。 +* `SQL_TEXT`:被终止会话中正在执行的 SQL 语句。 diff --git a/information-schema/information-schema-memory-usage.md b/information-schema/information-schema-memory-usage.md index 8348c03b61e6..17cf557b4c91 100644 --- a/information-schema/information-schema-memory-usage.md +++ b/information-schema/information-schema-memory-usage.md @@ -1,11 +1,11 @@ --- title: MEMORY_USAGE -summary: 了解 information_schema 表 `MEMORY_USAGE`。 +summary: 了解 `MEMORY_USAGE` information_schema 系统表。 --- # MEMORY_USAGE -`MEMORY_USAGE` 表描述了 TiDB 实例当前的内存使用情况。 +`MEMORY_USAGE` 表描述了当前 TiDB 实例的内存使用情况。 ```sql USE information_schema; @@ -46,21 +46,32 @@ SELECT * FROM information_schema.memory_usage; 2 rows in set (0.002 sec) ``` -`MEMORY_USAGE` 表中列的含义如下: +`MEMORY_USAGE` 表中各列的描述如下: -* MEMORY_TOTAL:TiDB 的可用内存总量,单位为 byte。 -* MEMORY_LIMIT:TiDB 的内存使用限制,单位为 byte。其值与系统变量 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 的值相同。 -* MEMORY_CURRENT:TiDB 当前的内存使用量,单位为 byte。 -* MEMORY_MAX_USED:从 TiDB 启动到当前的最大内存使用量,单位为 byte。 -* CURRENT_OPS:"shrinking" | null。"shrinking" 表示 TiDB 正在执行收缩内存用量的操作。 -* SESSION_KILL_LAST:上一次终止会话的时间戳。 -* SESSION_KILL_TOTAL:从 TiDB 启动到当前累计终止会话的次数。 -* GC_LAST:上一次由内存使用触发 Golang GC 的时间戳。 -* GC_TOTAL:从 TiDB 启动到当前累计由内存使用触发 Golang GC 的次数。 -* DISK_USAGE:当前数据落盘的硬盘使用量,单位为 byte。 -* QUERY_FORCE_DISK:从 TiDB 启动到当前累计的落盘次数。 +* MEMORY_TOTAL:TiDB 可用的总内存,单位为字节。 +* MEMORY_LIMIT:TiDB 的内存使用限制,单位为字节。该值与系统变量 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-new-in-v640) 的值相同。 +* MEMORY_CURRENT:TiDB 当前的内存使用量,单位为字节。 +* MEMORY_MAX_USED:从 TiDB 启动到当前时间的最大内存使用量,单位为字节。 +* CURRENT_OPS:"shrinking" | null。"shrinking" 表示 TiDB 正在执行收缩内存使用的操作。 +* SESSION_KILL_LAST:最后一次终止会话的时间戳。 +* SESSION_KILL_TOTAL:从 TiDB 启动到当前时间,终止会话的总次数。 +* GC_LAST:最后一次由内存使用触发 Golang GC 的时间戳。 +* GC_TOTAL:从 TiDB 启动到当前时间,由内存使用触发 Golang GC 的总次数。 +* DISK_USAGE:当前数据溢出操作的磁盘使用量,单位为字节。 +* QUERY_FORCE_DISK:从 TiDB 启动到当前时间,数据溢出到磁盘的总次数。 ## 另请参阅 + + - [TiDB 内存控制](/configure-memory-usage.md) -- [TiKV 内存参数性能调优](/tune-tikv-memory-performance.md) \ No newline at end of file +- [调优 TiKV 内存参数性能](/tune-tikv-memory-performance.md) + + + + + +- [TiDB 内存控制](https://docs.pingcap.com/tidb/stable/configure-memory-usage) +- [调优 TiKV 内存参数性能](https://docs.pingcap.com/tidb/stable/tune-tikv-memory-performance) + + diff --git a/information-schema/information-schema-partitions.md b/information-schema/information-schema-partitions.md index 007113f7b1b1..fd962f88e0a4 100644 --- a/information-schema/information-schema-partitions.md +++ b/information-schema/information-schema-partitions.md @@ -1,18 +1,18 @@ --- title: PARTITIONS -summary: 了解 INFORMATION_SCHEMA 表 `PARTITIONS`。 +summary: 了解 `PARTITIONS` INFORMATION_SCHEMA 表。 --- # PARTITIONS -`PARTITIONS` 表提供有关[分区表](/partitioned-table.md)的信息。 +`PARTITIONS` 表提供了关于[分区表](/partitioned-table.md)的信息。 ```sql USE INFORMATION_SCHEMA; -DESC PARTITIONS; +DESC partitions; ``` -输出结果如下: +输出如下: ```sql +-------------------------------+--------------+------+------+---------+-------+ @@ -54,7 +54,7 @@ CREATE TABLE test.t1 (id INT NOT NULL PRIMARY KEY) PARTITION BY HASH (id) PARTIT SELECT * FROM PARTITIONS WHERE table_schema='test' AND table_name='t1'\G ``` -输出结果如下: +输出如下: ```sql *************************** 1. row *************************** @@ -118,4 +118,4 @@ SUBPARTITION_ORDINAL_POSITION: NULL ## 另请参阅 -- [用 EXPLAIN 查看分区查询的执行计划](/explain-partitions.md) \ No newline at end of file +- [使用分区的 Explain 语句](/explain-partitions.md) diff --git a/information-schema/information-schema-placement-policies.md b/information-schema/information-schema-placement-policies.md index d233ce487703..b31644706b18 100644 --- a/information-schema/information-schema-placement-policies.md +++ b/information-schema/information-schema-placement-policies.md @@ -1,11 +1,15 @@ --- title: PLACEMENT_POLICIES -summary: 了解 information_schema 表 `PLACEMENT_POLICIES`。 +summary: 了解 `PLACEMENT_POLICIES` information_schema 表。 --- # PLACEMENT_POLICIES -`PLACEMENT_POLICIES` 表展示所有放置策略 (placement policy) 的信息,见 [Placement Rules in SQL](/placement-rules-in-sql.md)。 +`PLACEMENT_POLICIES` 表提供了所有放置策略的信息。详情请参考[放置规则 (Placement Rules) 在 SQL 中的使用](/placement-rules-in-sql.md)。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群中不可用。 {{< copyable "sql" >}} @@ -36,16 +40,16 @@ DESC placement_policies; ## 示例 -`PLACEMENT_POLICIES` 表只展示放置策略 (placement policy) 的信息。如需查看所有信息的规范版本(放置策略,以及绑定放置策略的对象),请改用 `SHOW PLACEMENT` 语句: +`PLACEMENT_POLICIES` 表仅显示所有放置策略。要查看放置规则的规范版本(包括所有放置策略和分配了放置策略的对象),请使用 `SHOW PLACEMENT` 语句: {{< copyable "sql" >}} ```sql -CREATE TABLE t1 (a INT); +CREATE TABLE t1 (a INT); CREATE PLACEMENT POLICY p1 primary_region="us-east-1" regions="us-east-1"; CREATE TABLE t3 (a INT) PLACEMENT POLICY=p1; -SHOW PLACEMENT; -- 显示所有信息,包含 t3。 -SELECT * FROM information_schema.placement_policies; -- 只显示放置策略,不包含 t3。 +SHOW PLACEMENT; -- 显示所有信息,包括表 t3 +SELECT * FROM information_schema.placement_policies; -- 仅显示放置策略,不包括 t3 ``` ```sql @@ -59,7 +63,7 @@ Query OK, 0 rows affected (0.08 sec) | Target | Placement | Scheduling_State | +---------------+------------------------------------------------+------------------+ | POLICY p1 | PRIMARY_REGION="us-east-1" REGIONS="us-east-1" | NULL | -| TABLE test.t3 | PRIMARY_REGION="us-east-1" REGIONS="us-east-1" | SCHEDULED | +| TABLE test.t3 | PRIMARY_REGION="us-east-1" REGIONS="us-east-1" | PENDING | +---------------+------------------------------------------------+------------------+ 2 rows in set (0.00 sec) diff --git a/information-schema/information-schema-processlist.md b/information-schema/information-schema-processlist.md index ab8493cdf741..466aa0c328e0 100644 --- a/information-schema/information-schema-processlist.md +++ b/information-schema/information-schema-processlist.md @@ -1,19 +1,19 @@ --- title: PROCESSLIST -summary: 了解 information_schema 表 `PROCESSLIST`。 +summary: 了解 `PROCESSLIST` information_schema 表。 --- # PROCESSLIST -`PROCESSLIST` 和 [`SHOW PROCESSLIST`](/sql-statements/sql-statement-show-processlist.md) 的功能一样,都是查看当前正在处理的请求。 +`PROCESSLIST` 与 [`SHOW PROCESSLIST`](/sql-statements/sql-statement-show-processlist.md) 一样,用于查看正在处理的请求。 -`PROCESSLIST` 表比 `SHOW PROCESSLIST` 的结果多出下面几列: +`PROCESSLIST` 表比 `SHOW PROCESSLIST` 多了以下列: -* `DIGEST` 列:显示 SQL 语句的 digest。 -* `MEM` 列:显示正在处理的请求已使用的内存,单位是 byte。 -* `DISK` 列:显示磁盘空间使用情况,单位是 byte。 -* `TxnStart`列:显示事务的开始时间。 -* `RESOURCE_GROUP`列:显示对应的资源组名称。 +* `DIGEST` 列,用于显示 SQL 语句的摘要。 +* `MEM` 列,用于显示正在处理的请求使用的内存,单位为字节。 +* `DISK` 列,用于显示磁盘使用量,单位为字节。 +* `TxnStart` 列,用于显示事务的开始时间。 +* `RESOURCE_GROUP` 列,用于显示资源组名称。 ```sql USE information_schema; @@ -63,27 +63,25 @@ SELECT * FROM processlist\G 1 row in set (0.00 sec) ``` -`PROCESSLIST` 表各列的含义如下: - -* `ID` 列:客户连接 ID。 -* `USER` 列:执行当前 PROCESS 的用户名。 -* `HOST` 列:客户连接的地址。 -* `DB` 列:当前连接的默认数据库名。 -* `COMMAND` 列:当前 PROCESS 执行的命令类型。 -* `TIME` 列:当前 PROCESS 的已经执行的时间,单位是秒。 -* `STATE` 列:当前连接的状态。 -* `INFO` 列:正在处理的请求语句。 -* `DIGEST` 列:SQL 语句的 digest。 -* `MEM` 列:正在处理的请求已使用的内存,单位是 byte。 -* `DISK` 列:磁盘空间使用情况,单位是 byte。 -* `TxnStart`列:显示事务的开始时间。 -* `RESOURCE_GROUP`列:显示对应的资源组名称。 +`PROCESSLIST` 表中的字段说明如下: + +* ID:用户连接的 ID。 +* USER:执行 `PROCESS` 的用户名。 +* HOST:用户连接的地址。 +* DB:当前连接的默认数据库名称。 +* COMMAND:`PROCESS` 正在执行的命令类型。 +* TIME:`PROCESS` 当前执行的持续时间,单位为秒。 +* STATE:当前连接状态。 +* INFO:正在处理的请求语句。 +* DIGEST:SQL 语句的摘要。 +* MEM:正在处理的请求使用的内存,单位为字节。 +* DISK:磁盘使用量,单位为字节。 +* TxnStart:事务的开始时间。 +* RESOURCE_GROUP:资源组名称。 ## CLUSTER_PROCESSLIST -`CLUSTER_PROCESSLIST` 是 `PROCESSLIST` 对应的集群系统表,用于查询集群中所有 TiDB 节点的 `PROCESSLIST` 信息。`CLUSTER_PROCESSLIST` 表结构上比 `PROCESSLIST` 多一列 `INSTANCE`,表示该行数据来自的 TiDB 节点地址。 - -{{< copyable "sql" >}} +`CLUSTER_PROCESSLIST` 是对应于 `PROCESSLIST` 的集群系统表,用于查询集群中所有 TiDB 节点的 `PROCESSLIST` 信息。`CLUSTER_PROCESSLIST` 的表结构比 `PROCESSLIST` 多一列 `INSTANCE`,用于存储该行数据来自哪个 TiDB 节点的地址。 ```sql SELECT * FROM information_schema.cluster_processlist; diff --git a/information-schema/information-schema-referential-constraints.md b/information-schema/information-schema-referential-constraints.md index 74ee8558e355..f6334343f08d 100644 --- a/information-schema/information-schema-referential-constraints.md +++ b/information-schema/information-schema-referential-constraints.md @@ -1,11 +1,11 @@ --- title: REFERENTIAL_CONSTRAINTS -summary: 了解 INFORMATION_SCHEMA 表 `REFERENTIAL_CONSTRAINTS`。 +summary: 了解 `REFERENTIAL_CONSTRAINTS` INFORMATION_SCHEMA 表。 --- # REFERENTIAL_CONSTRAINTS -`REFERENTIAL_CONSTRAINTS` 表提供 TiDB 表之间 [`FOREIGN KEY`](/foreign-key.md) 关系的信息。 +`REFERENTIAL_CONSTRAINTS` 表提供了表之间的 [`FOREIGN KEY`](/foreign-key.md)(外键)关系信息。 ```sql USE INFORMATION_SCHEMA; @@ -25,8 +25,8 @@ DESC REFERENTIAL_CONSTRAINTS; | UNIQUE_CONSTRAINT_SCHEMA | varchar(64) | NO | | NULL | | | UNIQUE_CONSTRAINT_NAME | varchar(64) | YES | | NULL | | | MATCH_OPTION | varchar(64) | NO | | NULL | | -| UPDATE_RULE | varchar(64) | NO | | NULL | | -| DELETE_RULE | varchar(64) | NO | | NULL | | +| UPDATE_RULE | varchar(64) | NO | | NULL | | +| DELETE_RULE | varchar(64) | NO | | NULL | | | TABLE_NAME | varchar(64) | NO | | NULL | | | REFERENCED_TABLE_NAME | varchar(64) | NO | | NULL | | +---------------------------+--------------+------+------+---------+-------+ diff --git a/information-schema/information-schema-resource-groups.md b/information-schema/information-schema-resource-groups.md index 8751a0de4337..e276130bb3cf 100644 --- a/information-schema/information-schema-resource-groups.md +++ b/information-schema/information-schema-resource-groups.md @@ -1,11 +1,15 @@ --- title: RESOURCE_GROUPS -summary: 了解 information_schema 表 `RESOURCE_GROUPS`。 +summary: 了解 `RESOURCE_GROUPS` information_schema 表。 --- # RESOURCE_GROUPS -`RESOURCE_GROUPS` 表展示所有资源组 (resource group) 的信息,见[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)。 +`RESOURCE_GROUPS` 表显示了所有资源组的信息。更多信息,请参见[使用资源控制实现资源隔离](/tidb-resource-control.md)。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ```sql USE information_schema; @@ -27,7 +31,7 @@ DESC resource_groups; ## 示例 ```sql -SELECT * FROM information_schema.resource_groups; -- 查看资源组,TiDB 默认预置 `default` 资源组 +SELECT * FROM information_schema.resource_groups; -- 查看所有资源组。TiDB 有一个 `default` 资源组。 ``` ```sql @@ -47,7 +51,7 @@ Query OK, 0 rows affected (0.34 sec) ``` ```sql -SHOW CREATE RESOURCE GROUP rg1; -- 显示 `rg1` 资源组的定义 +SHOW CREATE RESOURCE GROUP rg1; -- 显示资源组 `rg1` 的定义 ``` ```sql @@ -72,13 +76,13 @@ SELECT * FROM information_schema.resource_groups WHERE NAME = 'rg1'; -- 查看 1 row in set (0.00 sec) ``` -`RESOURCE_GROUPS` 表中列的含义如下: +`RESOURCE_GROUPS` 表中各列的描述如下: -* `NAME`:资源组名称。 -* `RU_PER_SEC`:资源组的回填速度,单位为每秒回填的 [Request Unit (RU)](/tidb-resource-control.md#什么是-request-unit-ru) 数量。 -* `PRIORITY`:任务在 TiKV 上处理的绝对优先级。不同的资源按照 `PRIORITY` 的设置进行调度,`PRIORITY` 高的任务会被优先调度。如果资源组的 `PRIORITY` 相同,则会根据 `RU_PER_SEC` 的配置按比例调度。如果不指定 `PRIORITY`,资源组的默认优先级为 `MEDIUM`。 -* `BURSTABLE`:是否允许此资源组超额使用剩余的系统资源。 +* `NAME`:资源组的名称。 +* `RU_PER_SEC`:资源组的回填速度。单位为 RU/秒,其中 RU 表示[请求单元(Request Unit)](/tidb-resource-control.md#what-is-request-unit-ru)。 +* `PRIORITY`:在 TiKV 上处理任务的绝对优先级。不同资源按照 `PRIORITY` 设置进行调度。高 `PRIORITY` 的任务优先调度。对于具有相同 `PRIORITY` 的资源组,将根据 `RU_PER_SEC` 配置按比例调度任务。如果未指定 `PRIORITY`,默认优先级为 `MEDIUM`。 +* `BURSTABLE`:是否允许资源组超用可用的系统资源。 > **注意:** > -> TiDB 集群在初始化时会自动创建 `default` 资源组,其 `RU_PER_SEC` 的默认值为 `UNLIMITED` (等同于 `INT` 类型最大值,即 `2147483647`),且为 `BURSTABLE` 模式。所有未绑定资源组的请求都将自动绑定至此资源组。在新建配置其他资源组时,建议根据实际情况修改 `default` 资源组的配置。 +> TiDB 在集群初始化时会自动创建一个 `default` 资源组。对于该资源组,`RU_PER_SEC` 的默认值为 `UNLIMITED`(相当于 `INT` 类型的最大值,即 `2147483647`),并且处于 `BURSTABLE` 模式。所有未绑定到任何资源组的请求都会自动绑定到这个 `default` 资源组。当你为其他资源组创建新配置时,建议根据需要修改 `default` 资源组配置。 diff --git a/information-schema/information-schema-runaway-watches.md b/information-schema/information-schema-runaway-watches.md index d5d7ef4be5f1..6c1ec82fe96e 100644 --- a/information-schema/information-schema-runaway-watches.md +++ b/information-schema/information-schema-runaway-watches.md @@ -1,11 +1,15 @@ --- title: RUNAWAY_WATCHES -summary: 了解 INFORMATION_SCHEMA 表 `RUNAWAY_WATCHES`。 +summary: 了解 `RUNAWAY_WATCHES` INFORMATION_SCHEMA 表。 --- # RUNAWAY_WATCHES -`RUNAWAY_WATCHES` 表展示资源消耗超出预期的查询 Runaway Queries 监控列表,见 [Runaway Queries](/tidb-resource-control.md#管理资源消耗超出预期的查询-runaway-queries)。 +`RUNAWAY_WATCHES` 表显示了消耗资源超出预期的失控查询的监视列表。更多信息,请参见[失控查询](/tidb-resource-control.md#manage-queries-that-consume-more-resources-than-expected-runaway-queries)。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ```sql USE INFORMATION_SCHEMA; @@ -30,7 +34,7 @@ DESC RUNAWAY_WATCHES; ## 示例 -查询 Runaway Queries 识别名单: +查询失控查询的监视列表: ```sql SELECT * FROM INFORMATION_SCHEMA.RUNAWAY_WATCHES\G @@ -60,13 +64,13 @@ RESOURCE_GROUP_NAME: rg2 2 rows in set (0.00 sec) ``` -添加一个识别项到资源组 `rg1`: +向资源组 `rg1` 的列表中添加一个监视项: ```sql QUERY WATCH ADD RESOURCE GROUP rg1 SQL TEXT EXACT TO 'select * from sbtest.sbtest1'; ``` -再次查询 Runaway Queries 识别名单: +再次查询失控查询的监视列表: ```sql SELECT * FROM INFORMATION_SCHEMA.RUNAWAY_WATCHES\G @@ -105,15 +109,15 @@ RESOURCE_GROUP_NAME: rg1 3 row in set (0.00 sec) ``` -`RUNAWAY_WATCHES` 表中列的含义如下: - -* `ID`:识别项 ID。 -* `RESOURCE_GROUP_NAME`:资源组名称。 -* `START_TIME`:开始时间。 -* `END_TIME`:结束时间。`UNLIMITED` 表示识别项的有效时间无限长。 -* `WATCH`:识别匹配类型,其值如下: - - `Plan` 表示按照 Plan Digest 匹配,此时列 `WATCH_TEXT` 显示 Plan Digest。 - - `Similar` 表示按照 SQL Digest 匹配,此时列 `WATCH_TEXT` 显示 SQL Digest。 - - `Exact` 表示按照 SQL 文本匹配,此时列 `WATCH_TEXT` 显示 SQL 文本。 -* `SOURCE`:识别项来源,如果是被 `QUERY_LIMIT` 规则识别,则显示识别到的 TiDB IP;如果是手动添加,则显示 `manual`。 -* `ACTION`:识别后的对应操作。 +`RUNAWAY_WATCHES` 表中各列字段的含义如下: + +- `ID`:监视项的 ID。 +- `RESOURCE_GROUP_NAME`:资源组的名称。 +- `START_TIME`:开始时间。 +- `END_TIME`:结束时间。`UNLIMITED` 表示该监视项具有无限期的有效期。 +- `WATCH`:快速识别的匹配类型。取值如下: + - `Plan` 表示匹配 Plan Digest,此时 `WATCH_TEXT` 列显示 Plan Digest。 + - `Similar` 表示匹配 SQL Digest,此时 `WATCH_TEXT` 列显示 SQL Digest。 + - `Exact` 表示匹配 SQL 文本,此时 `WATCH_TEXT` 列显示 SQL 文本。 +- `SOURCE`:监视项的来源。如果是由 `QUERY_LIMIT` 规则识别的,则显示识别的 TiDB IP 地址;如果是手动添加的,则显示 `manual`。 +- `ACTION`:识别后的对应操作。 diff --git a/information-schema/information-schema-schemata.md b/information-schema/information-schema-schemata.md index 78d439fd0013..293558381fc3 100644 --- a/information-schema/information-schema-schemata.md +++ b/information-schema/information-schema-schemata.md @@ -1,18 +1,18 @@ --- title: SCHEMATA -summary: 了解 information_schema 表 `SCHEMATA`。 +summary: 了解 `SCHEMATA` information_schema 表。 --- # SCHEMATA -`SCHEMATA` 表提供了关于数据库的信息。表中的数据与 [`SHOW DATABASES`](/sql-statements/sql-statement-show-databases.md) 语句的执行结果等价。 +`SCHEMATA` 表提供了数据库的相关信息。该表的数据等同于 [`SHOW DATABASES`](/sql-statements/sql-statement-show-databases.md) 语句的结果。 ```sql USE information_schema; desc SCHEMATA; ``` -```sql +``` +----------------------------+--------------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------------------+--------------+------+------+---------+-------+ @@ -29,7 +29,7 @@ desc SCHEMATA; SELECT * FROM SCHEMATA; ``` -```sql +``` +--------------+--------------------+----------------------------+------------------------+----------+ | CATALOG_NAME | SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | SQL_PATH | +--------------+--------------------+----------------------------+------------------------+----------+ @@ -42,10 +42,10 @@ SELECT * FROM SCHEMATA; 5 rows in set (0.00 sec) ``` -`SCHEMATA` 表各列字段含义如下: +`SCHEMATA` 表中的字段说明如下: -* CATALOG_NAME:数据库归属的目录名,该列值永远为 `def`。 -* SCHEMA_NAME:数据库的名字。 -* DEFAULT_CHARACTER_SET_NAME:数据库的默认字符集。 -* DEFAULT_COLLATION_NAME:数据库的默认 collation。 -* SQL_PATH:该项值永远为 `NULL`。 +* `CATALOG_NAME`:数据库所属的目录。 +* `SCHEMA_NAME`:数据库名称。 +* `DEFAULT_CHARACTER_SET_NAME`:数据库的默认字符集。 +* `DEFAULT_COLLATION_NAME`:数据库的默认排序规则。 +* `SQL_PATH`:该项的值始终为 `NULL`。 diff --git a/information-schema/information-schema-sequences.md b/information-schema/information-schema-sequences.md index 5578536c3515..d892b5eacaa8 100644 --- a/information-schema/information-schema-sequences.md +++ b/information-schema/information-schema-sequences.md @@ -1,11 +1,11 @@ --- title: SEQUENCES -summary: 了解 INFORMATION_SCHEMA 表 `SEQUENCES`。 +summary: 了解 `SEQUENCES` INFORMATION_SCHEMA 表。 --- # SEQUENCES -`SEQUENCES` 表提供了有关序列的信息。TiDB 中[序列](/sql-statements/sql-statement-create-sequence.md)的功能是参照 MariaDB 中的类似功能来实现的。 +`SEQUENCES` 表提供了关于序列的信息。[序列功能](/sql-statements/sql-statement-create-sequence.md)是基于 MariaDB 中类似功能建模的。 ```sql USE INFORMATION_SCHEMA; @@ -33,11 +33,12 @@ DESC SEQUENCES; 11 rows in set (0.00 sec) ``` -创建一个名为 `test.seq` 的序列,并查询这个序列的下一个值: +创建序列 `test.seq` 并查询序列的下一个值: ```sql CREATE SEQUENCE test.seq; SELECT NEXTVAL(test.seq); +SELECT * FROM sequences\G ``` 输出结果如下: @@ -51,7 +52,7 @@ SELECT NEXTVAL(test.seq); 1 row in set (0.01 sec) ``` -查询数据库中的所有序列: +查看所有序列: ```sql SELECT * FROM SEQUENCES\G @@ -81,4 +82,4 @@ SEQUENCE_SCHEMA: test - [`SHOW CREATE SEQUENCE`](/sql-statements/sql-statement-show-create-sequence.md) - [`ALTER SEQUENCE`](/sql-statements/sql-statement-alter-sequence.md) - [`DROP SEQUENCE`](/sql-statements/sql-statement-drop-sequence.md) -- [序列函数](/functions-and-operators/sequence-functions.md) \ No newline at end of file +- [序列函数](/functions-and-operators/sequence-functions.md) diff --git a/information-schema/information-schema-session-variables.md b/information-schema/information-schema-session-variables.md index 5fe809bc277a..ebf7c5bcab93 100644 --- a/information-schema/information-schema-session-variables.md +++ b/information-schema/information-schema-session-variables.md @@ -1,11 +1,11 @@ --- title: SESSION_VARIABLES -summary: 了解 INFORMATION_SCHEMA 表 `SESSION_VARIABLES`。 +summary: 了解 `SESSION_VARIABLES` INFORMATION_SCHEMA 表。 --- # SESSION_VARIABLES -`SESSION_VARIABLES` 表提供了关于 session 变量的信息。表中的数据跟 [`SHOW SESSION VARIABLES`](/sql-statements/sql-statement-show-variables.md) 语句执行结果类似。 +`SESSION_VARIABLES` 表提供了会话变量的相关信息。该表的数据类似于 [`SHOW SESSION VARIABLES`](/sql-statements/sql-statement-show-variables.md) 语句的结果。 ```sql USE INFORMATION_SCHEMA; @@ -24,7 +24,7 @@ DESC SESSION_VARIABLES; 2 rows in set (0.00 sec) ``` -查看 `SESSION_VARIABLES` 表的前 10 条信息: +查询 `SESSION_VARIABLES` 表的前 10 行: ```sql SELECT * FROM SESSION_VARIABLES ORDER BY variable_name LIMIT 10; @@ -50,7 +50,7 @@ SELECT * FROM SESSION_VARIABLES ORDER BY variable_name LIMIT 10; 10 rows in set (0.00 sec) ``` -`SESSION_VARIABLES` 表各列字段含义如下: +`SESSION_VARIABLES` 表中各列的描述如下: -* `VARIABLE_NAME`:数据库中 session 级变量的名称。 -* `VARIABLE_VALUE`:数据库中对应该 session 变量名的具体值。 +* `VARIABLE_NAME`:数据库中会话级变量的名称。 +* `VARIABLE_VALUE`:数据库中会话级变量的值。 diff --git a/information-schema/information-schema-slow-query.md b/information-schema/information-schema-slow-query.md index 009bc347284a..3862ce352b47 100644 --- a/information-schema/information-schema-slow-query.md +++ b/information-schema/information-schema-slow-query.md @@ -1,20 +1,40 @@ --- title: SLOW_QUERY -summary: 了解 INFORMATION_SCHEMA 表 `SLOW_QUERY`。 +summary: 了解 `SLOW_QUERY` INFORMATION_SCHEMA 表。 --- # SLOW_QUERY -`SLOW_QUERY` 表中提供了当前节点的慢查询相关的信息,其内容通过解析当前节点的 TiDB [慢查询日志](/tidb-configuration-file.md#slow-query-file)而来,列名和慢日志中的字段名是一一对应。关于如何使用该表调查和改善慢查询,请参考[慢查询日志文档](/identify-slow-queries.md)。 + + +`SLOW_QUERY` 表提供当前节点的慢查询信息,这些信息是 TiDB [慢日志文件](/tidb-configuration-file.md#slow-query-file)的解析结果。表中的列名与慢日志中的字段名相对应。 + + + + + +`SLOW_QUERY` 表提供当前节点的慢查询信息,这些信息是 TiDB [慢日志文件](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#slow-query-file)的解析结果。表中的列名与慢日志中的字段名相对应。 + + + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群中不可用。 + + + +关于如何使用此表来识别有问题的语句并改进查询性能,请参见[慢查询日志文档](/identify-slow-queries.md)。 + + ```sql USE INFORMATION_SCHEMA; -DESC slow_query; +DESC SLOW_QUERY; ``` -输出结果示例如下: +输出结果如下: -```sql +``` +-------------------------------+---------------------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------------------+---------------------+------+------+---------+-------+ @@ -101,15 +121,27 @@ DESC slow_query; 79 rows in set (0.00 sec) ``` -## CLUSTER_SLOW_QUERY table +`Query` 列的最大语句长度受系统变量 [`tidb_stmt_summary_max_sql_length`](/system-variables.md#tidb_stmt_summary_max_sql_length-new-in-v40) 限制。 + +## CLUSTER_SLOW_QUERY 表 + +`CLUSTER_SLOW_QUERY` 表提供集群中所有节点的慢查询信息,这些信息是 TiDB 慢日志文件的解析结果。你可以像使用 `SLOW_QUERY` 表一样使用 `CLUSTER_SLOW_QUERY` 表。`CLUSTER_SLOW_QUERY` 表的表结构与 `SLOW_QUERY` 表的区别在于前者多了一个 `INSTANCE` 列。`INSTANCE` 列表示该行慢查询信息所在的 TiDB 节点地址。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群中不可用。 + + + +关于如何使用此表来识别有问题的语句并改进查询性能,请参见[慢查询日志文档](/identify-slow-queries.md)。 -`CLUSTER_SLOW_QUERY` 表中提供了集群所有节点的慢查询相关的信息,其内容通过解析 TiDB 慢查询日志而来,该表使用上和 `SLOW_QUERY` 表一样。`CLUSTER_SLOW_QUERY` 表结构上比 `SLOW_QUERY` 多一列 `INSTANCE`,表示该行慢查询信息来自的 TiDB 节点地址。关于如何使用该表调查和改善慢查询,请参考[慢查询日志文档](/identify-slow-queries.md)。 + ```sql DESC CLUSTER_SLOW_QUERY; ``` -输出结果示例如下: +输出结果如下: ```sql +-------------------------------+---------------------+------+------+---------+-------+ @@ -199,13 +231,13 @@ DESC CLUSTER_SLOW_QUERY; 80 rows in set (0.00 sec) ``` -查询集群系统表时,TiDB 也会将相关计算下推给其他节点执行,而不是把所有节点的数据都取回来,可以查看执行计划,如下: +当查询集群系统表时,TiDB 不会从所有节点获取数据,而是将相关计算下推到其他节点。执行计划如下: ```sql DESC SELECT COUNT(*) FROM CLUSTER_SLOW_QUERY WHERE user = 'u1'; ``` -输出结果示例如下: +输出结果如下: ```sql +----------------------------+----------+-----------+--------------------------+------------------------------------------------------+ @@ -219,9 +251,9 @@ DESC SELECT COUNT(*) FROM CLUSTER_SLOW_QUERY WHERE user = 'u1'; 4 rows in set (0.00 sec) ``` -上面执行计划表示,会将 `user = u1` 条件下推给其他的 (`cop`) TiDB 节点执行,也会把聚合算子(即上面输出结果中的 `StreamAgg` 算子)下推。 +在上述执行计划中,`user = u1` 条件被下推到其他(`cop`)TiDB 节点,聚合运算符也被下推(图中的 `StreamAgg` 运算符)。 -目前由于没有对系统表收集统计信息,所以有时会导致某些聚合算子不能下推,导致执行较慢,用户可以通过手动指定聚合下推的 SQL HINT 来将聚合算子下推,示例如下: +目前,由于系统表的统计信息未被收集,有时一些聚合运算符无法下推,导致执行较慢。在这种情况下,你可以手动指定 SQL HINT 来下推聚合运算符。例如: ```sql SELECT /*+ AGG_TO_COP() */ COUNT(*) FROM CLUSTER_SLOW_QUERY GROUP BY user; diff --git a/information-schema/information-schema-statistics.md b/information-schema/information-schema-statistics.md index 58012b1b5093..1c09285705fd 100644 --- a/information-schema/information-schema-statistics.md +++ b/information-schema/information-schema-statistics.md @@ -1,6 +1,6 @@ --- title: STATISTICS -summary: 了解 information_schema 表 `STATISTICS`。 +summary: 了解 `STATISTICS` information_schema 表。 --- # STATISTICS @@ -40,28 +40,28 @@ DESC statistics; 18 rows in set (0.00 sec) ``` -`STATISTICS` 表中列的含义如下: +`STATISTICS` 表中各字段的描述如下: -* `TABLE_CATALOG`:包含索引的表所属的目录的名称。这个值总是 `def`。 -* `TABLE_SCHEMA`:包含索引的表所属的数据库的名称。 -* `TABLE_NAME`:包含索引的表的名称。 -* `NON_UNIQUE`:如果索引不能包含重复项,则为 `0`;如果可以,则为 `1`。 -* `INDEX_SCHEMA`:索引所属的数据库的名称。 -* `INDEX_NAME`:索引的名称。如果索引是主键,那么名称总是 `PRIMARY`。 +* `TABLE_CATALOG`:包含索引的表所属的目录名称。该值始终为 `def`。 +* `TABLE_SCHEMA`:包含索引的表所属的数据库名称。 +* `TABLE_NAME`:包含索引的表名。 +* `NON_UNIQUE`:如果索引不能包含重复值,则值为 `0`;如果索引允许重复值,则值为 `1`。 +* `INDEX_SCHEMA`:索引所属的数据库名称。 +* `INDEX_NAME`:索引的名称。如果该索引是主键,则值始终为 `PRIMARY`。 * `SEQ_IN_INDEX`:索引中的列序号,从 `1` 开始。 -* `COLUMN_NAME`:列名。请参见表达式列的说明。 -* `COLLATION`:列在索引中的排序方式。取值可以是 `A`(升序)、`D`(降序)或 `NULL`(未排序)。 -* `CARDINALITY`:TiDB 未使用该字段。该字段的值总是 `0`。 -* `SUB_PART`:索引的前缀。如果只对列的部分前缀进行索引,则为索引字符的数量;如果对整个列进行索引,则为 `NULL`。 -* `PACKED`:TiDB 未使用该字段。这个值总是 `NULL`。 -* `NULLABLE`:如果列可能包含 `NULL` 值,则值为 `YES`;如果不包含,则值为 `''`。 +* `COLUMN_NAME`:列名。请参见 `Expression` 列的描述。 +* `COLLATION`:索引中列的排序方式。值可以是 `A`(升序),`D`(降序)或 `NULL`(未排序)。 +* `CARDINALITY`:TiDB 不使用此字段。字段值始终为 `0`。 +* `SUB_PART`:索引的前缀。如果只对列的部分前缀进行索引,则值为已索引的字符数;如果对整列进行索引,则值为 `NULL`。 +* `PACKED`:TiDB 不使用此字段。该值始终为 `NULL`。 +* `NULLABLE`:如果列可能包含 `NULL` 值,则值为 `YES`;如果不可能,则值为 `''`。 * `INDEX_TYPE`:索引的类型。 -* `COMMENT`:其他与索引有关的信息。 -* `INDEX_COMMENT`:在创建索引时为索引提供的带有注释属性的任何注释。 -* `IS_VISIBLE`:优化器能否使用该索引。 -* `Expression` 对于非表达式部分的索引键,这个值为 `NULL`;对于表达式部分的索引键,这个值为表达式本身。可参考[表达式索引](/sql-statements/sql-statement-create-index.md#表达式索引) +* `COMMENT`:与索引相关的其他信息。 +* `INDEX_COMMENT`:创建索引时为索引提供的任何带有注释属性的注释。 +* `IS_VISIBLE`:优化器是否可以使用此索引。 +* `Expression`:对于非表达式部分的索引键,该值为 `NULL`;对于表达式部分的索引键,该值为表达式本身。参考[表达式索引](/sql-statements/sql-statement-create-index.md#expression-index)。 -下列语句是等价的: +以下语句是等价的: ```sql SELECT * FROM INFORMATION_SCHEMA.STATISTICS diff --git a/information-schema/information-schema-table-constraints.md b/information-schema/information-schema-table-constraints.md index a3ef2f8e90c9..03c90bf92b50 100644 --- a/information-schema/information-schema-table-constraints.md +++ b/information-schema/information-schema-table-constraints.md @@ -1,11 +1,11 @@ --- title: TABLE_CONSTRAINTS -summary: 了解 information_schema 表 `TABLE_CONSTRAINTS`。 +summary: 了解 `TABLE_CONSTRAINTS` information_schema 表。 --- # TABLE_CONSTRAINTS -`TABLE_CONSTRAINTS` 表记录了表的[约束](/constraints.md)信息。 +`TABLE_CONSTRAINTS` 表描述了哪些表具有[约束](/constraints.md)。 {{< copyable "sql" >}} @@ -49,10 +49,10 @@ SELECT * FROM table_constraints WHERE constraint_type='UNIQUE'; 7 rows in set (0.01 sec) ``` -`TABLE_CONSTRAINTS` 表中列的含义如下: +`TABLE_CONSTRAINTS` 表中的字段说明如下: -* `CONSTRAINT_CATALOG`:约束所属的目录的名称。这个值总是 `def`。 -* `CONSTRAINT_SCHEMA`:约束所属的数据库的名称。 +* `CONSTRAINT_CATALOG`:约束所属的目录名称。该值始终为 `def`。 +* `CONSTRAINT_SCHEMA`:约束所属的数据库名称。 * `CONSTRAINT_NAME`:约束的名称。 * `TABLE_NAME`:表的名称。 -* `CONSTRAINT_TYPE`:约束的类型。取值可以是 `UNIQUE`、`PRIMARY KEY` 或者 `FOREIGN KEY`。`UNIQUE` 和 `PRIMARY KEY` 信息与 `SHOW INDEX` 语句的执行结果类似。 +* `CONSTRAINT_TYPE`:约束的类型。值可以是 `UNIQUE`、`PRIMARY KEY` 或 `FOREIGN KEY`。`UNIQUE` 和 `PRIMARY KEY` 信息类似于 `SHOW INDEX` 语句的执行结果。 diff --git a/information-schema/information-schema-table-storage-stats.md b/information-schema/information-schema-table-storage-stats.md index 0fb9e5910bae..47787c35973f 100644 --- a/information-schema/information-schema-table-storage-stats.md +++ b/information-schema/information-schema-table-storage-stats.md @@ -1,11 +1,11 @@ --- title: TABLE_STORAGE_STATS -summary: 了解 INFORMATION_SCHEMA 表 `TABLE_STORAGE_STATS`。 +summary: 了解 `TABLE_STORAGE_STATS` INFORMATION_SCHEMA 表。 --- # TABLE_STORAGE_STATS -`TABLE_STORAGE_STATS` 表提供有关由存储引擎 (TiKV) 存储的表大小的信息。 +`TABLE_STORAGE_STATS` 表提供了存储引擎(TiKV)中表大小的相关信息。 ```sql USE INFORMATION_SCHEMA; @@ -51,13 +51,13 @@ EMPTY_REGION_COUNT: 1 1 row in set (0.00 sec) ``` -`TABLE_STORAGE_STATS` 表各列字段含义如下: +`TABLE_STORAGE_STATS` 表中的字段说明如下: -* `TABLE_SCHEMA`:表所在 schema 名字 -* `TABLE_NAME`:表名 -* `TABLE_ID`:表 ID -* `PEER_COUNT`:副本个数 -* `REGION_COUNT`:表所在的 Region 个数 -* `EMPTY_REGION_COUNT`:没有该表数据的 Region 个数 -* `TABLE_SIZE`:数据量大小,单位 MiB -* `TABLE_KEYS`:表记录个数 +* `TABLE_SCHEMA`:表所属的 schema 名称。 +* `TABLE_NAME`:表名。 +* `TABLE_ID`:表的 ID。 +* `PEER_COUNT`:表的副本数量。 +* `REGION_COUNT`:Region 的数量。 +* `EMPTY_REGION_COUNT`:此表中不包含数据的 Region 数量。 +* `TABLE_SIZE`:表的总大小,单位为 MiB。 +* `TABLE_KEYS`:表中的总记录数。 diff --git a/information-schema/information-schema-tables.md b/information-schema/information-schema-tables.md index ff7ac01c5887..fe4f97c29f40 100644 --- a/information-schema/information-schema-tables.md +++ b/information-schema/information-schema-tables.md @@ -1,11 +1,11 @@ --- title: TABLES -summary: 了解 information_schema 表 `TABLES`。 +summary: 了解 `TABLES` information_schema 表。 --- # TABLES -`TABLES` 表提供了数据库里关于表的信息。 +`TABLES` 表提供了数据库中表的相关信息: {{< copyable "sql" >}} @@ -79,7 +79,7 @@ TIDB_ROW_ID_SHARDING_INFO: NULL 1 row in set (0.00 sec) ``` -下列语句是等价的: +以下语句是等价的: ```sql SELECT table_name FROM INFORMATION_SCHEMA.TABLES @@ -91,36 +91,36 @@ SHOW TABLES [LIKE 'wild'] ``` -`TABLES` 表各列字段含义如下: +`TABLES` 表中各列的描述如下: -* `TABLE_CATALOG`:表所属的目录的名称。该值始终为 `def`。 -* `TABLE_SCHEMA`:表所属数据库的名称。 +* `TABLE_CATALOG`:表所属的目录名称。该值始终为 `def`。 +* `TABLE_SCHEMA`:表所属的数据库名称。 * `TABLE_NAME`:表的名称。 * `TABLE_TYPE`:表的类型。 -* `ENGINE`:存储引擎类型。该值暂为 ‘InnoDB’。 -* `VERSION`:版本,默认值为 10。 -* `ROW_FORMAT`:行格式。该值暂为 ‘Compact’。 -* `TABLE_ROWS`:统计信息中该表所存的行数。 -* `AVG_ROW_LENGTH`:该表中所存数据的平均行长度。平均行长度 = DATA_LENGTH / 统计信息中的行数。 -* `DATA_LENGTH`:数据长度。数据长度 = 统计信息中的行数 × 元组各列存储长度和,这里尚未考虑 TiKV 的副本数。 -* `MAX_DATA_LENGTH`:最大数据长度。该值暂为 0,表示没有最大数据长度的限制。 -* `INDEX_LENGTH`:索引长度。索引长度 = 统计信息中的行数 × 索引元组各列长度和,这里尚未考虑 TiKV 的副本数。 -* `DATA_FREE`:空间碎片。该值暂为 0。 -* `AUTO_INCREMENT`:该表中自增主键自动增量的当前值。 -* `CREATE_TIME`:该表的创建时间。 -* `UPDATE_TIME`:该表的更新时间。 -* `CHECK_TIME`:该表的检查时间。 -* `TABLE_COLLATION`:该表的字符校验编码集。 +* `ENGINE`:存储引擎的类型。当前值为 `InnoDB`。 +* `VERSION`:版本号。默认值为 `10`。 +* `ROW_FORMAT`:行格式。当前值为 `Compact`。 +* `TABLE_ROWS`:统计信息中的表行数。 +* `AVG_ROW_LENGTH`:表的平均行长度。`AVG_ROW_LENGTH` = `DATA_LENGTH` / `TABLE_ROWS`。 +* `DATA_LENGTH`:数据长度。`DATA_LENGTH` = `TABLE_ROWS` \* 元组中列的存储长度之和。不考虑 TiKV 的副本。 +* `MAX_DATA_LENGTH`:最大数据长度。当前值为 `0`,表示数据长度没有上限。 +* `INDEX_LENGTH`:索引长度。`INDEX_LENGTH` = `TABLE_ROWS` \* 索引元组中列的长度之和。不考虑 TiKV 的副本。 +* `DATA_FREE`:数据碎片。当前值为 `0`。 +* `AUTO_INCREMENT`:自增主键的当前步长。 +* `CREATE_TIME`:表的创建时间。 +* `UPDATE_TIME`:表的更新时间。 +* `CHECK_TIME`:表的检查时间。 +* `TABLE_COLLATION`:表中字符串的排序规则。 * `CHECKSUM`:校验和。 * `CREATE_OPTIONS`:创建选项。 -* `TABLE_COMMENT`:表的注释、备注。 +* `TABLE_COMMENT`:表的注释和备注。 -表中的信息大部分定义自 MySQL,只有两列是 TiDB 新增的: +表中的大部分信息与 MySQL 相同。只有两列是 TiDB 新定义的: -* `TIDB_TABLE_ID`:标识表的内部 ID,该 ID 在一个 TiDB 集群内部唯一。 -* `TIDB_ROW_ID_SHARDING_INFO`:标识表的 Sharding 类型,可能的值为: - - `"NOT_SHARDED"`:表未被 Shard。 - - `"NOT_SHARDED(PK_IS_HANDLE)"`:一个定义了整型主键的表未被 Shard。 - - `"PK_AUTO_RANDOM_BITS={bit_number}"`:一个定义了整型主键的表由于定义了 `AUTO_RANDOM` 而被 Shard。 - - `"SHARD_BITS={bit_number}"`:表使用 `SHARD_ROW_ID_BITS={bit_number}` 进行了 Shard。 - - NULL:表属于系统表或 View,无法被 Shard。 +* `TIDB_TABLE_ID`:表示表的内部 ID。此 ID 在 TiDB 集群中是唯一的。 +* `TIDB_ROW_ID_SHARDING_INFO`:表示表的分片类型。可能的值如下: + - `"NOT_SHARDED"`:表未分片。 + - `"NOT_SHARDED(PK_IS_HANDLE)"`:将整数主键定义为其行 ID 的表未分片。 + - `"PK_AUTO_RANDOM_BITS={bit_number}"`:将整数主键定义为其行 ID 的表已分片,因为主键被赋予了 `AUTO_RANDOM` 属性。 + - `"SHARD_BITS={bit_number}"`:使用 `SHARD_ROW_ID_BITS={bit_number}` 对表进行分片。 + - NULL:表是系统表或视图,因此无法分片。 diff --git a/information-schema/information-schema-tidb-check-constraints.md b/information-schema/information-schema-tidb-check-constraints.md index 06c061bfb1b6..0a79c42d8da1 100644 --- a/information-schema/information-schema-tidb-check-constraints.md +++ b/information-schema/information-schema-tidb-check-constraints.md @@ -1,18 +1,18 @@ --- title: TIDB_CHECK_CONSTRAINTS -summary: 了解 INFORMATION_SCHEMA 表 `TIDB_CHECK_CONSTRAINTS`。 +summary: 了解 `TIDB_CHECK_CONSTRAINTS` INFORMATION_SCHEMA 表。 --- # TIDB\_CHECK\_CONSTRAINTS -`TIDB_CHECK_CONSTRAINTS` 表提供关于表上 [`CHECK` 约束](/constraints.md#check-约束)的信息。除了包含 [`CHECK_CONSTRAINTS`](/information-schema/information-schema-check-constraints.md) 表中的信息之外,`TIDB_CHECK_CONSTRAINTS` 还提供了定义 `CHECK` 约束的表名和表 ID。 +`TIDB_CHECK_CONSTRAINTS` 表提供了表上 [`CHECK` 约束](/constraints.md#check)的信息。除了 [`CHECK_CONSTRAINTS`](/information-schema/information-schema-check-constraints.md) 中的列外,`TIDB_CHECK_CONSTRAINTS` 还提供了定义 `CHECK` 约束的表的名称和 ID。 ```sql USE INFORMATION_SCHEMA; DESC TIDB_CHECK_CONSTRAINTS; ``` -命令输出如下: +输出如下: ```sql +--------------------+-------------+------+------+---------+-------+ @@ -28,7 +28,7 @@ DESC TIDB_CHECK_CONSTRAINTS; 6 rows in set (0.00 sec) ``` -下述示例使用 `CREATE TABLE` 语句添加 `CHECK` 约束: +以下示例使用 `CREATE TABLE` 语句添加一个 `CHECK` 约束: ```sql SET GLOBAL tidb_enable_check_constraint = ON; @@ -36,7 +36,7 @@ CREATE TABLE test.t1 (id INT PRIMARY KEY, CHECK (id%2 = 0)); SELECT * FROM TIDB_CHECK_CONSTRAINTS\G ``` -命令输出如下: +输出如下: ```sql *************************** 1. row *************************** @@ -49,11 +49,11 @@ CONSTRAINT_CATALOG: def 1 row in set (0.02 sec) ``` -`TIDB_CHECK_CONSTRAINTS` 表的字段描述如下: +`TIDB_CHECK_CONSTRAINTS` 表中的字段说明如下: * `CONSTRAINT_CATALOG`:约束的目录,始终为 `def`。 -* `CONSTRAINT_SCHEMA`:约束的库名。 -* `CONSTRAINT_NAME`:约束的名字。 +* `CONSTRAINT_SCHEMA`:约束的模式。 +* `CONSTRAINT_NAME`:约束的名称。 * `CHECK_CLAUSE`:检查约束的子句。 -* `TABLE_NAME`:约束所在表的名字。 +* `TABLE_NAME`:约束所在表的名称。 * `TABLE_ID`:约束所在表的 ID。 diff --git a/information-schema/information-schema-tidb-hot-regions-history.md b/information-schema/information-schema-tidb-hot-regions-history.md index 43118bbde6f2..4d2affb7b3e6 100644 --- a/information-schema/information-schema-tidb-hot-regions-history.md +++ b/information-schema/information-schema-tidb-hot-regions-history.md @@ -1,11 +1,27 @@ --- title: TIDB_HOT_REGIONS_HISTORY -summary: 了解 information_schema 表 `TIDB_HOT_REGIONS_HISTORY`。 +summary: 了解 `TIDB_HOT_REGIONS_HISTORY` information_schema 表。 --- # TIDB_HOT_REGIONS_HISTORY -`TIDB_HOT_REGIONS_HISTORY` 表提供了关于历史热点 Region 的相关信息,这些信息由 PD 定期存储在本地,存储间隔为 [`hot-regions-write-interval`](/pd-configuration-file.md#hot-regions-write-interval-从-v540-版本开始引入) 的值(默认值为 10m),历史热点信息保持的期限为 [`hot-regions-reserved-days`](/pd-configuration-file.md#hot-regions-reserved-days-从-v540-版本开始引入) 的值(默认值为 `7`),详情参见 [PD 配置文件描述](/pd-configuration-file.md#hot-regions-write-interval-从-v540-版本开始引入)。 +`TIDB_HOT_REGIONS_HISTORY` 表提供了由 PD 定期在本地记录的热点 Region 历史信息。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群中不可用。 + + + +你可以通过配置 [`hot-regions-write-interval`](/pd-configuration-file.md#hot-regions-write-interval-new-in-v540) 来指定记录间隔。默认值为 10 分钟。你可以通过配置 [`hot-regions-reserved-days`](/pd-configuration-file.md#hot-regions-reserved-days-new-in-v540) 来指定保留热点 Region 历史信息的时间。默认值为 7 天。详情请参见 [PD 配置文件描述](/pd-configuration-file.md#hot-regions-write-interval-new-in-v540)。 + + + + + +默认情况下,记录间隔为 10 分钟,保留热点 Region 历史信息的时间为 7 天。 + + {{< copyable "sql" >}} @@ -38,32 +54,32 @@ DESC tidb_hot_regions_history; 16 rows in set (0.00 sec) ``` -`TIDB_HOT_REGIONS_HISTORY` 表各列字段含义如下: +`TIDB_HOT_REGIONS_HISTORY` 表中的字段说明如下: -* UPDATE_TIME:热点 Region 更新时间。 -* DB_NAME:热点 Region 所在数据库对象的数据库名。 +* UPDATE_TIME:热点 Region 的更新时间。 +* DB_NAME:热点 Region 所在对象的数据库名称。 * TABLE_ID:热点 Region 所在表的 ID。 * TABLE_NAME:热点 Region 所在表的名称。 * INDEX_NAME:热点 Region 所在索引的名称。 * INDEX_ID:热点 Region 所在索引的 ID。 * REGION_ID:热点 Region 的 ID。 -* STORE_ID:热点 Region 所在 TiKV Store 的 ID。 -* PEER_ID:热点 Region 对应的副本 Peer 的 ID。 -* IS_LEARNER:PEER 是否是 LEARNER。 -* IS_LEADER:PEER 是否是 LEADER。 +* STORE_ID:热点 Region 所在 store 的 ID。 +* PEER_ID:热点 Region 对应的 Peer ID。 +* IS_LEARNER:该 PEER 是否为 LEARNER。 +* IS_LEADER:该 PEER 是否为 LEADER。 * TYPE:热点 Region 的类型。 -* HOT_DEGREE:该热点 Region 的热度。 -* FLOW_BYTES:该 Region 内读写的字节数量。 -* KEY_RATE:该 Region 内读写的 Key 数量。 -* QUERY_RATE:该 Region 内读写的 Query 数量。 +* HOT_DEGREE:热点 Region 的热度。 +* FLOW_BYTES:Region 中写入和读取的字节数。 +* KEY_RATE:Region 中写入和读取的键数量。 +* QUERY_RATE:Region 中写入和读取的查询数量。 > **注意:** > -> `TIDB_HOT_REGIONS_HISTORY` 表的 `UPDATE_TIME`、`REGION_ID`、`STORE_ID`、`PEER_ID`、`IS_LEARNER`、`IS_LEADER`、`TYPE` 字段会下推到 PD 服务器执行。所以为了降低使用该表的开销,必须指定搜索时间范围,然后尽可能地指定更多的条件。例如 `select * from tidb_hot_regions_history where store_id = 11 and update_time > '2020-05-18 20:40:00' and update_time < '2020-05-18 21:40:00' and type='write'`。 +> `UPDATE_TIME`、`REGION_ID`、`STORE_ID`、`PEER_ID`、`IS_LEARNER`、`IS_LEADER` 和 `TYPE` 字段会下推到 PD 服务器执行。为了减少使用该表的开销,必须指定搜索的时间范围,并尽可能多地指定条件。例如,`select * from tidb_hot_regions_history where store_id = 11 and update_time > '2020-05-18 20:40:00' and update_time < '2020-05-18 21:40:00' and type='write'`。 ## 常见使用场景 -* 查询一段时间内的所有热点 Regions。将以下语句中的 `update_time` 替换为实际所需的时间即可。 +* 查询特定时间段内的热点 Region。将 `update_time` 替换为你的实际时间。 {{< copyable "sql" >}} @@ -73,9 +89,9 @@ DESC tidb_hot_regions_history; > **注意:** > - > `UPDATE_TIME` 同样支持 Unix 时间戳。例如: `update_time >TIMESTAMP('2012-08-18 21:40:00')` 或 `update_time > FROM_UNIXTIME(1629294000.000)`。 + > `UPDATE_TIME` 也支持 Unix 时间戳。例如,`update_time >TIMESTAMP('2021-08-18 21:40:00')` 或 `update_time > FROM_UNIXTIME(1629294000.000)`。 -* 查询某张表指定时间内的热点 Regions,替换 `update_time`、`table_name` 即可。 +* 查询特定时间段内某个表的热点 Region。将 `update_time` 和 `table_name` 替换为你的实际值。 {{< copyable "sql" >}} @@ -83,7 +99,7 @@ DESC tidb_hot_regions_history; SELECT * FROM INFORMATION_SCHEMA.TIDB_HOT_REGIONS_HISTORY WHERE update_time >'2021-08-18 21:40:00' and update_time <'2021-09-19 00:00:00' and TABLE_NAME = 'table_name'; ``` -* 查询某张表指定时间内热点 Regions 的分布,替换 `update_time`、`table_name` 即可。 +* 查询特定时间段内热点 Region 的分布情况。将 `update_time` 和 `table_name` 替换为你的实际值。 {{< copyable "sql" >}} @@ -91,7 +107,7 @@ DESC tidb_hot_regions_history; SELECT count(region_id) cnt, store_id FROM INFORMATION_SCHEMA.TIDB_HOT_REGIONS_HISTORY WHERE update_time >'2021-08-18 21:40:00' and update_time <'2021-09-19 00:00:00' and table_name = 'table_name' GROUP BY STORE_ID ORDER BY cnt DESC; ``` -* 查询某张表指定时间内热点 Leader Regions 的分布,替换 `update_time`、`table_name` 即可。 +* 查询特定时间段内热点 Leader Region 的分布情况。将 `update_time` 和 `table_name` 替换为你的实际值。 {{< copyable "sql" >}} @@ -99,7 +115,7 @@ DESC tidb_hot_regions_history; SELECT count(region_id) cnt, store_id FROM INFORMATION_SCHEMA.TIDB_HOT_REGIONS_HISTORY WHERE update_time >'2021-08-18 21:40:00' and update_time <'2021-09-19 00:00:00' and table_name = 'table_name' and is_leader=1 GROUP BY STORE_ID ORDER BY cnt DESC; ``` -* 查询某张表指定时间内热点 Index Regions 的分布,替换 `update_time`、`table_name` 即可。 +* 查询特定时间段内热点 Index Region 的分布情况。将 `update_time` 和 `table_name` 替换为你的实际值。 {{< copyable "sql" >}} @@ -107,10 +123,10 @@ DESC tidb_hot_regions_history; SELECT count(region_id) cnt, index_name, store_id FROM INFORMATION_SCHEMA.TIDB_HOT_REGIONS_HISTORY WHERE update_time >'2021-08-18 21:40:00' and update_time <'2021-09-19 00:00:00' and table_name = 'table_name' group by index_name, store_id order by index_name,cnt desc; ``` -* 查询某张表指定时间内热点 Index Leader Regions 的分布,替换 `update_time`、`table_name` 即可。 +* 查询特定时间段内热点 Index Leader Region 的分布情况。将 `update_time` 和 `table_name` 替换为你的实际值。 {{< copyable "sql" >}} ```sql SELECT count(region_id) cnt, index_name, store_id FROM INFORMATION_SCHEMA.TIDB_HOT_REGIONS_HISTORY WHERE update_time >'2021-08-18 21:40:00' and update_time <'2022-09-19 00:00:00' and table_name = 'table_name' and is_leader=1 group by index_name, store_id order by index_name,cnt desc; - ``` \ No newline at end of file + ``` diff --git a/information-schema/information-schema-tidb-index-usage.md b/information-schema/information-schema-tidb-index-usage.md index 4d77e85e8ccd..4bc81e9e890f 100644 --- a/information-schema/information-schema-tidb-index-usage.md +++ b/information-schema/information-schema-tidb-index-usage.md @@ -1,11 +1,21 @@ --- title: TIDB_INDEX_USAGE -summary: 了解 INFORMATION_SCHEMA 表 `TIDB_INDEX_USAGE`。 +summary: 了解 `TIDB_INDEX_USAGE` INFORMATION_SCHEMA 表。 --- # TIDB_INDEX_USAGE -TiDB 从 v8.0.0 开始提供 `TIDB_INDEX_USAGE` 表,你可以使用该表查看当前 TiDB 节点中所有索引的访问统计信息。在 SQL 语句执行时,TiDB 默认维护访问索引有关的统计信息,可以通过修改配置项 [`instance.tidb_enable_collect_execution_info`](/tidb-configuration-file.md#tidb_enable_collect_execution_info) 或者系统变量 [`tidb_enable_collect_execution_info`](/system-variables.md#tidb_enable_collect_execution_info) 将其关闭。 + + +从 v8.0.0 开始,TiDB 提供了 `TIDB_INDEX_USAGE` 表。你可以使用 `TIDB_INDEX_USAGE` 获取当前 TiDB 节点上所有索引的使用统计信息。默认情况下,TiDB 在执行 SQL 语句时会收集这些索引使用统计信息。你可以通过关闭 [`instance.tidb_enable_collect_execution_info`](/tidb-configuration-file.md#tidb_enable_collect_execution_info) 配置项或 [`tidb_enable_collect_execution_info`](/system-variables.md#tidb_enable_collect_execution_info) 系统变量来禁用此功能。 + + + + + +从 v8.0.0 开始,TiDB 提供了 `TIDB_INDEX_USAGE` 表。你可以使用 `TIDB_INDEX_USAGE` 获取当前 TiDB 节点上所有索引的使用统计信息。默认情况下,TiDB 在执行 SQL 语句时会收集这些索引使用统计信息。你可以通过关闭 [`instance.tidb_enable_collect_execution_info`](https://docs.pingcap.com/tidb/v8.0/tidb-configuration-file#tidb_enable_collect_execution_info) 配置项或 [`tidb_enable_collect_execution_info`](/system-variables.md#tidb_enable_collect_execution_info) 系统变量来禁用此功能。 + + ```sql USE INFORMATION_SCHEMA; @@ -34,28 +44,28 @@ DESC TIDB_INDEX_USAGE; 14 rows in set (0.00 sec) ``` -`TIDB_INDEX_USAGE` 表中列的含义如下: +`TIDB_INDEX_USAGE` 表中的列说明如下: -* `TABLE_SCHEMA`:索引所在表的所属数据库的名称。 -* `TABLE_NAME`:索引所在表的名称。 -* `INDEX_NAME`:索引的名称。 +* `TABLE_SCHEMA`:包含索引的表所属的数据库名称。 +* `TABLE_NAME`:包含索引的表名。 +* `INDEX_NAME`:索引名称。 * `QUERY_TOTAL`:访问该索引的语句总数。 -* `KV_REQ_TOTAL`:访问该索引时产生的 KV 请求总数。 -* `ROWS_ACCESS_TOTAL`:访问该索引时扫描的总行数。 -* `PERCENTAGE_ACCESS_0`:行访问比例(访问行数占表总行数的百分比)为 0 的次数。 -* `PERCENTAGE_ACCESS_0_1`:行访问比例为 0 到 1% 的次数。 -* `PERCENTAGE_ACCESS_1_10`:行访问比例为 1% 到 10% 的次数。 -* `PERCENTAGE_ACCESS_10_20`:行访问比例为 10% 到 20% 的次数。 -* `PERCENTAGE_ACCESS_20_50`:行访问比例为 20% 到 50% 的次数。 -* `PERCENTAGE_ACCESS_50_100`:行访问比例为 50% 到 100% 的次数。 +* `KV_REQ_TOTAL`:访问该索引时生成的 KV 请求总数。 +* `ROWS_ACCESS_TOTAL`:访问该索引时扫描的行数总和。 +* `PERCENTAGE_ACCESS_0`:行访问比例(访问的行数占表总行数的百分比)为 0 的次数。 +* `PERCENTAGE_ACCESS_0_1`:行访问比例在 0% 到 1% 之间的次数。 +* `PERCENTAGE_ACCESS_1_10`:行访问比例在 1% 到 10% 之间的次数。 +* `PERCENTAGE_ACCESS_10_20`:行访问比例在 10% 到 20% 之间的次数。 +* `PERCENTAGE_ACCESS_20_50`:行访问比例在 20% 到 50% 之间的次数。 +* `PERCENTAGE_ACCESS_50_100`:行访问比例在 50% 到 100% 之间的次数。 * `PERCENTAGE_ACCESS_100`:行访问比例为 100% 的次数。 * `LAST_ACCESS_TIME`:最近一次访问该索引的时间。 ## CLUSTER_TIDB_INDEX_USAGE -`TIDB_INDEX_USAGE` 表仅提供单个 TiDB 节点中所有索引的访问统计信息。如果要查看整个集群上所有 TiDB 节点中索引的访问统计信息,需要查询 `CLUSTER_TIDB_INDEX_USAGE` 表。 +`TIDB_INDEX_USAGE` 表仅提供单个 TiDB 节点上所有索引的使用统计信息。要获取集群中所有 TiDB 节点的索引使用统计信息,你需要查询 `CLUSTER_TIDB_INDEX_USAGE` 表。 -与 `TIDB_INDEX_USAGE` 表的查询结果相比,`CLUSTER_TIDB_INDEX_USAGE` 表的查询结果额外包含了 `INSTANCE` 字段。`INSTANCE` 字段展示了集群中各节点的 IP 地址和端口,用于区分不同节点上的统计信息。 +与 `TIDB_INDEX_USAGE` 表相比,`CLUSTER_TIDB_INDEX_USAGE` 表的查询结果多了一个 `INSTANCE` 字段。该字段显示集群中每个节点的 IP 地址和端口,帮助你区分不同节点的统计信息。 ```sql USE INFORMATION_SCHEMA; @@ -87,12 +97,12 @@ DESC CLUSTER_TIDB_INDEX_USAGE; 15 rows in set (0.00 sec) ``` -## 使用限制 +## 限制 -- `TIDB_INDEX_USAGE` 表中的数据可能存在最多 5 分钟的延迟。 -- 在 TiDB 重启后,`TIDB_INDEX_USAGE` 表中的数据会被清空。 -- 只有在表具有有效统计信息时,TiDB 才会记录该表的索引使用情况。 +- `TIDB_INDEX_USAGE` 表中的数据可能会有最多 5 分钟的延迟。 +- TiDB 重启后,`TIDB_INDEX_USAGE` 表中的数据会被清空。 +- TiDB 只有在表有有效的统计信息时才会记录该表的索引使用情况。 -## 更多阅读 +## 更多信息 - [`sys.schema_unused_indexes`](/sys-schema/sys-schema-unused-indexes.md) diff --git a/information-schema/information-schema-tidb-indexes.md b/information-schema/information-schema-tidb-indexes.md index 012553a7c5ac..d2198242a148 100644 --- a/information-schema/information-schema-tidb-indexes.md +++ b/information-schema/information-schema-tidb-indexes.md @@ -1,11 +1,11 @@ --- title: TIDB_INDEXES -summary: 了解 information_schema 表 `TIDB_INDEXES`。 +summary: 了解 `TIDB_INDEXES` information_schema 表。 --- # TIDB_INDEXES -`TIDB_INDEXES` 记录了所有表中的 INDEX 信息。 +`TIDB_INDEXES` 表提供了所有表的索引信息。 {{< copyable "sql" >}} @@ -14,7 +14,7 @@ USE information_schema; DESC tidb_indexes; ``` -```sql +``` +---------------+---------------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+---------------+------+------+---------+-------+ @@ -34,9 +34,9 @@ DESC tidb_indexes; 12 rows in set (0.00 sec) ``` -`INDEX_ID` 是 TiDB 为每个索引分配的唯一 ID。它可以与从另一个表或 API 获得的 `INDEX_ID` 一起执行 `join` 操作。 +`INDEX_ID` 是 TiDB 为每个索引分配的唯一 ID。它可以用于与从其他表或 API 获取的 `INDEX_ID` 进行联接操作。 -例如,你可以在 [`SLOW_QUERY` 表](/information-schema/information-schema-slow-query.md) 中获取某些慢查询所涉及的 `TABLE_ID` 和 `INDEX_ID`,然后使用以下 SQL 语句获取特定索引信息: +例如,你可以在 [`SLOW_QUERY` 表](/information-schema/information-schema-slow-query.md)中获取某些慢查询涉及的 `TABLE_ID` 和 `INDEX_ID`,然后使用以下 SQL 语句获取具体的索引信息: ```sql SELECT @@ -51,16 +51,16 @@ WHERE AND index_id = ? ``` -`TIDB_INDEXES` 表中列的含义如下: +`TIDB_INDEXES` 表中各字段的描述如下: -* `TABLE_SCHEMA`:索引所在表的所属数据库的名称。 -* `TABLE_NAME`:索引所在表的名称。 -* `NON_UNIQUE`:如果索引是唯一的,则为 `0`,否则为 `1`。 -* `KEY_NAME`:索引的名称。如果索引是主键,则名称为 `PRIMARY`。 -* `SEQ_IN_INDEX`:索引中列的顺序编号,从 `1` 开始。 -* `COLUMN_NAME`:索引所在的列名。 -* `SUB_PART`:索引前缀长度。如果列是部分被索引,则该值为被索引的字符数量,否则为 `NULL`。 -* `INDEX_COMMENT`:创建索引时以 `COMMENT` 标注的注释。 -* `INDEX_ID`:索引的 ID。 +* `TABLE_SCHEMA`:索引所属的数据库(schema)名称。 +* `TABLE_NAME`:索引所属的表名。 +* `NON_UNIQUE`:如果索引是唯一的,则值为 `0`;否则值为 `1`。 +* `KEY_NAME`:索引名称。如果该索引是主键,则名称为 `PRIMARY`。 +* `SEQ_IN_INDEX`:索引中列的顺序号,从 `1` 开始。 +* `COLUMN_NAME`:索引所在列的名称。 +* `SUB_PART`:索引的前缀长度。如果列是部分索引,则 `SUB_PART` 值是已索引字符的数量;否则值为 `NULL`。 +* `INDEX_COMMENT`:创建索引时的索引注释。 +* `INDEX_ID`:索引 ID。 * `IS_VISIBLE`:索引是否可见。 * `CLUSTERED`:是否为[聚簇索引](/clustered-indexes.md)。 diff --git a/information-schema/information-schema-tidb-servers-info.md b/information-schema/information-schema-tidb-servers-info.md index c7ddbdcd449d..845e3d8270b6 100644 --- a/information-schema/information-schema-tidb-servers-info.md +++ b/information-schema/information-schema-tidb-servers-info.md @@ -1,15 +1,19 @@ --- title: TIDB_SERVERS_INFO -summary: 了解 INFORMATION_SCHEMA 表 `TIDB_SERVERS_INFO`。 +summary: 了解 `TIDB_SERVERS_INFO` INFORMATION_SCHEMA 表。 --- # TIDB_SERVERS_INFO -`TIDB_SERVERS_INFO` 表提供了 TiDB 集群中 TiDB 服务器的信息(即 tidb-server 进程)。 +`TIDB_SERVERS_INFO` 表提供了 TiDB 集群中 TiDB 服务器(即 tidb-server 进程)的信息。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ```sql USE INFORMATION_SCHEMA; -DESC TIDB_SERVERS_INFO; +DESC tidb_servers_info; ``` 输出结果如下: @@ -31,7 +35,7 @@ DESC TIDB_SERVERS_INFO; 9 rows in set (0.00 sec) ``` -查看 `TIDB_SERVERS_INFO` 表的信息: +查看 `TIDB_SERVERS_INFO` 表: ```sql SELECT * FROM TIDB_SERVERS_INFO\G @@ -47,7 +51,7 @@ SELECT * FROM TIDB_SERVERS_INFO\G STATUS_PORT: 10080 LEASE: 45s VERSION: 8.0.11-TiDB-v8.1.2 - GIT_HASH: 635a4362235e8a3c0043542e629532e3c7bb2756 + GIT_HASH: 827d8ff2d22ac4c93ae1b841b79d468211e1d393 BINLOG_STATUS: Off LABELS: 1 row in set (0.006 sec) diff --git a/information-schema/information-schema-tidb-trx.md b/information-schema/information-schema-tidb-trx.md index 6d2ac381ef38..f223023a6fde 100644 --- a/information-schema/information-schema-tidb-trx.md +++ b/information-schema/information-schema-tidb-trx.md @@ -1,11 +1,11 @@ --- title: TIDB_TRX -summary: 了解 INFORMATION_SCHEMA 表 `TIDB_TRX`。 +summary: 了解 `TIDB_TRX` INFORMATION_SCHEMA 表。 --- # TIDB_TRX -`TIDB_TRX` 表提供了当前 TiDB 节点上正在执行的事务的信息。 +`TIDB_TRX` 表提供 TiDB 节点上当前正在执行的事务信息。 ```sql USE INFORMATION_SCHEMA; @@ -34,37 +34,37 @@ DESC TIDB_TRX; +-------------------------+-----------------------------------------------------------------+------+------+---------+-------+ ``` -`TIDB_TRX` 表中各列的字段含义如下: +`TIDB_TRX` 表中各列字段的含义如下: -* `ID`:事务 ID,即事务的开始时间戳 `start_ts`。 -* `START_TIME`:事务的开始时间,即事务的 `start_ts` 所对应的物理时间。 -* `CURRENT_SQL_DIGEST`:该事务当前正在执行的 SQL 语句的 Digest。 -* `CURRENT_SQL_DIGEST_TEXT`:该事务当前正在执行的 SQL 语句的归一化形式,即去除了参数和格式的 SQL 语句。与 `CURRENT_SQL_DIGEST` 对应。 -* `STATE`:该事务当前所处的状态。其可能的值包括: - * `Idle`:事务处于闲置状态,即正在等待用户输入查询。 - * `Running`:事务正在正常执行一个查询。 - * `LockWaiting`:事务处于正在等待悲观锁上锁完成的状态。需要注意的是,事务刚开始进行悲观锁上锁操作时即进入该状态,无论是否有被其它事务阻塞。 +* `ID`:事务 ID,即事务的 `start_ts`(开始时间戳)。 +* `START_TIME`:事务的开始时间,即事务的 `start_ts` 对应的物理时间。 +* `CURRENT_SQL_DIGEST`:事务中当前正在执行的 SQL 语句的摘要。 +* `CURRENT_SQL_DIGEST_TEXT`:事务当前正在执行的 SQL 语句的规范化形式,即不含参数和格式的 SQL 语句。它与 `CURRENT_SQL_DIGEST` 相对应。 +* `STATE`:事务的当前状态。可能的值包括: + * `Idle`:事务处于空闲状态,即正在等待用户输入查询。 + * `Running`:事务正在执行查询。 + * `LockWaiting`:事务正在等待获取悲观锁。注意,事务在悲观锁定操作开始时就会进入此状态,无论是否被其他事务阻塞。 * `Committing`:事务正在提交过程中。 - * `RollingBack`:事务正在回滚过程中。 -* `WAITING_START_TIME`:当 `STATE` 值为 `LockWaiting` 时,该列显示等待的开始时间。 -* `MEM_BUFFER_KEYS`:当前事务写入内存缓冲区的 key 的个数。 -* `MEM_BUFFER_BYTES`:当前事务写入内存缓冲区的 key 和 value 的总字节数。 -* `SESSION_ID`:该事务所属的 session 的 ID。 -* `USER`:执行该事务的用户名。 -* `DB`:执行该事务的 session 当前的默认数据库名。 -* `ALL_SQL_DIGESTS`:该事务已经执行过的语句的 Digest 的列表,表示为一个 JSON 格式的字符串数组。每个事务最多记录前 50 条语句。通过 [`TIDB_DECODE_SQL_DIGESTS`](/functions-and-operators/tidb-functions.md#tidb_decode_sql_digests) 函数可以将该列的信息变换为对应的归一化 SQL 语句的列表。 -* `RELATED_TABLE_IDS`:该事务访问的表、视图等对象的 ID。 + * `RollingBack`:事务正在回滚中。 +* `WAITING_START_TIME`:当 `STATE` 的值为 `LockWaiting` 时,此列显示等待的开始时间。 +* `MEM_BUFFER_KEYS`:当前事务写入内存缓冲区的键的数量。 +* `MEM_BUFFER_BYTES`:当前事务写入内存缓冲区的键值对的总字节数。 +* `SESSION_ID`:此事务所属会话的 ID。 +* `USER`:执行事务的用户名。 +* `DB`:执行事务的会话当前默认的数据库名。 +* `ALL_SQL_DIGESTS`:事务已执行的语句的摘要列表。列表以 JSON 格式的字符串数组形式显示。每个事务最多记录前 50 条语句。使用 [`TIDB_DECODE_SQL_DIGESTS`](/functions-and-operators/tidb-functions.md#tidb_decode_sql_digests) 函数,可以将此列中的信息转换为相应的规范化 SQL 语句列表。 +* `RELATED_TABLE_IDS`:事务访问的表、视图和其他对象的 ID。 > **注意:** > -> * 仅拥有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户可以获取该表中的完整信息。没有 PROCESS 权限的用户则只能查询到当前用户所执行的事务的信息。 -> * `CURRENT_SQL_DIGEST` 和 `ALL_SQL_DIGESTS` 列中的信息 (SQL Digest) 为 SQL 语句进行归一化后计算得到的哈希值。`CURRENT_SQL_DIGEST_TEXT` 列中的信息和函数 `TIDB_DECODE_SQL_DIGESTS` 所得到的结果均为内部从 Statements Summary 系列表中查询得到,因而存在内部查询不到对应语句的可能性。关于 SQL Digest 和 Statements Summary 相关表的详细说明,请参阅[Statement Summary Tables](/statement-summary-tables.md)。 -> * [`TIDB_DECODE_SQL_DIGESTS`](/functions-and-operators/tidb-functions.md#tidb_decode_sql_digests) 函数调用开销较大,如果对大量事务的信息调用该函数查询历史 SQL,可能查询耗时较长。如果集群规模较大、同一时刻并发运行的事务较多,请避免直接在查询 `TIDB_TRX` 全表的同时直接将该函数用于 `ALL_SQL_DIGEST` 列(即尽量避免 ``SELECT *, tidb_decode_sql_digests(all_sql_digests) FROM TIDB_TRX`` 这样的用法)。 -> * 目前 `TIDB_TRX` 表暂不支持显示 TiDB 内部事务相关的信息。 +> * 只有具有 [PROCESS](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process) 权限的用户才能获取此表中的完整信息。没有 PROCESS 权限的用户只能查询当前用户执行的事务的信息。 +> * `CURRENT_SQL_DIGEST` 和 `ALL_SQL_DIGESTS` 列中的信息(SQL 摘要)是从规范化 SQL 语句计算得出的哈希值。`CURRENT_SQL_DIGEST_TEXT` 列中的信息和 `TIDB_DECODE_SQL_DIGESTS` 函数返回的结果是从语句概要表内部查询的,因此可能找不到相应的语句。有关 SQL 摘要和语句概要表的详细说明,请参见[语句概要表](/statement-summary-tables.md)。 +> * [`TIDB_DECODE_SQL_DIGESTS`](/functions-and-operators/tidb-functions.md#tidb_decode_sql_digests) 函数调用开销较高。如果对大量事务查询历史 SQL 语句,调用此函数可能需要较长时间。如果集群较大且并发事务较多,在查询 `TIDB_TRX` 的完整表时,避免直接在 `ALL_SQL_DIGEST` 列上使用此函数。这意味着要避免使用类似 ``SELECT *, tidb_decode_sql_digests(all_sql_digests) FROM TIDB_TRX`` 的 SQL 语句。 +> * 目前 `TIDB_TRX` 表不支持显示 TiDB 内部事务的信息。 ## 示例 -查看 `TIDB_TRX` 表中的信息: +查看 `TIDB_TRX` 表: ```sql SELECT * FROM INFORMATION_SCHEMA.TIDB_TRX\G @@ -102,7 +102,7 @@ CURRENT_SQL_DIGEST_TEXT: update `t` set `v` = `v` + ? where `id` = ? 2 rows in set (0.01 sec) ``` -此示例的查询结果表示:当前节点有两个运行中的事务,第一个事务正在闲置状态(`STATE` 为 `Idle`,`CURRENT_SQL_DIGEST` 为 `NULL`),该事务已经执行过 3 条语句(`ALL_SQL_DIGESTS` 列表中有三条记录,分别为执行过的 3 条语句的 Digest);第二个事务正在执行一条语句并正在等锁(`STATE` 为 `LockWaiting`,`WAITING_START_TIME` 显示了等锁开始的时间),该事务已经执行过两条语句,当前正在执行的语句形如 ``"update `t` set `v` = `v` + ? where `id` = ?"``。 +从这个示例的查询结果可以看出:当前节点有两个正在进行的事务。一个事务处于空闲状态(`STATE` 为 `Idle` 且 `CURRENT_SQL_DIGEST` 为 `NULL`),这个事务已经执行了 3 条语句(`ALL_SQL_DIGESTS` 列表中有三条记录,是已执行的三条 SQL 语句的摘要)。另一个事务正在执行语句并等待锁(`STATE` 为 `LockWaiting`,`WAITING_START_TIME` 显示等待锁的开始时间)。该事务已执行 2 条语句,当前正在执行的语句形式为 ``"update `t` set `v` = `v` + ? where `id` = ?"``。 ```sql SELECT id, all_sql_digests, tidb_decode_sql_digests(all_sql_digests) AS all_sqls FROM INFORMATION_SCHEMA.TIDB_TRX\G @@ -121,11 +121,11 @@ all_sql_digests: ["e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02 all_sqls: ["begin","update `t` set `v` = `v` + ? where `id` = ?"] ``` -此查询对 `TIDB_TRX` 表的 `ALL_SQL_DIGESTS` 列调用了 [`TIDB_DECODE_SQL_DIGESTS`](/functions-and-operators/tidb-functions.md#tidb_decode_sql_digests) 函数,将 SQL Digest 的数组通过系统内部的查询转换成归一化 SQL 语句的数组,以便于直观地获取事务历史执行过的语句的信息。但是需要注意上述查询扫描了 `TIDB_TRX` 全表,并对每一行都调用了 `TIDB_DECODE_SQL_DIGESTS` 函数;而 `TIDB_DECODE_SQL_DIGESTS` 函数调用的开销很大,所以如果集群中并发事务数量较多,请尽量避免这种查询。 +此查询在 `TIDB_TRX` 表的 `ALL_SQL_DIGESTS` 列上调用 [`TIDB_DECODE_SQL_DIGESTS`](/functions-and-operators/tidb-functions.md#tidb_decode_sql_digests) 函数,通过系统内部查询将 SQL 摘要数组转换为规范化 SQL 语句数组。这有助于你直观地获取事务历史执行的语句信息。但是请注意,上述查询扫描了 `TIDB_TRX` 的整个表,并对每一行调用 `TIDB_DECODE_SQL_DIGESTS` 函数。调用 `TIDB_DECODE_SQL_DIGESTS` 函数的开销较高。因此,如果集群中存在许多并发事务,请尽量避免这种类型的查询。 ## CLUSTER_TIDB_TRX -`TIDB_TRX` 表仅提供单个 TiDB 节点中正在执行的事务信息。如果要查看整个集群上所有 TiDB 节点中正在执行的事务信息,需要查询 `CLUSTER_TIDB_TRX` 表。与 `TIDB_TRX` 表的查询结果相比,`CLUSTER_TIDB_TRX` 表的查询结果额外包含了 `INSTANCE` 字段。`INSTANCE` 字段展示了集群中各节点的 IP 地址和端口,用于区分事务所在的 TiDB 节点。 +`TIDB_TRX` 表仅提供单个 TiDB 节点上正在执行的事务信息。如果你想查看整个集群中所有 TiDB 节点上正在执行的事务信息,需要查询 `CLUSTER_TIDB_TRX` 表。与 `TIDB_TRX` 表的查询结果相比,`CLUSTER_TIDB_TRX` 表的查询结果多了一个 `INSTANCE` 字段。`INSTANCE` 字段显示集群中每个节点的 IP 地址和端口,用于区分事务所在的 TiDB 节点。 ```sql USE INFORMATION_SCHEMA; diff --git a/information-schema/information-schema-tiflash-replica.md b/information-schema/information-schema-tiflash-replica.md index ab8cdc4c14a9..c3396c0e8c5e 100644 --- a/information-schema/information-schema-tiflash-replica.md +++ b/information-schema/information-schema-tiflash-replica.md @@ -1,11 +1,11 @@ --- title: TIFLASH_REPLICA -summary: 了解 INFORMATION_SCHEMA 表 `TIFLASH_REPLICA`。 +summary: 了解 `TIFLASH_REPLICA` INFORMATION_SCHEMA 表。 --- # TIFLASH_REPLICA -`TIFLASH_REPLICA` 表提供了有关可用的 TiFlash 副本的信息。 +`TIFLASH_REPLICA` 表提供了可用的 TiFlash 副本信息。 ```sql USE INFORMATION_SCHEMA; @@ -29,12 +29,12 @@ DESC TIFLASH_REPLICA; 7 rows in set (0.01 sec) ``` -`TIFLASH_REPLICA` 表中各列的字段含义如下: +`TIFLASH_REPLICA` 表中各字段的描述如下: -- `TABLE_SCHEMA`:表所属的数据库的名称。 +- `TABLE_SCHEMA`:表所属的数据库名称。 - `TABLE_NAME`:表的名称。 -- `TABLE_ID`:表的内部 ID,该 ID 在一个 TiDB 集群内部唯一。 -- `REPLICA_COUNT`:TiFlash 副本数。 -- `LOCATION_LABELS`:设置 TiFlash 副本时设置的 LocationLabelList。 -- `AVAILABLE`:表的 TiFlash 副本是否可用。`1` 代表可用,TiDB 优化器将依据查询代价智能选择下推查询到 TiKV 或 TiFlash;`0` 代表不可用,TiDB 将不会下推查询到 TiFlash。副本状态变为可用之后就不再改变。 -- `PROGRESS`:TiFlash 副本同步进度,范围是 `[0, 1]`,精确到小数点后两位,刷新的精度为分钟级。当 `AVAILABLE` 字段为 1 时,如果 `PROGRESS` 小于 1,表示 TiFlash 副本落后 TiKV 较多,下推到 TiFlash 的查询很可能会因为等待数据同步超时而失败。 +- `TABLE_ID`:表的内部 ID,在 TiDB 集群中是唯一的。 +- `REPLICA_COUNT`:TiFlash 副本的数量。 +- `LOCATION_LABELS`:创建 TiFlash 副本时设置的 LocationLabelList。 +- `AVAILABLE`:表示表的 TiFlash 副本是否可用。当值为 `1`(可用)时,TiDB 优化器可以根据查询成本智能地选择将查询下推到 TiKV 或 TiFlash。当值为 `0`(不可用)时,TiDB 不会将查询下推到 TiFlash。一旦该字段的值变为 `1`(可用),就不会再改变。 +- `PROGRESS`:TiFlash 副本的复制进度,精确到小数点后两位,以分钟为单位。该字段的范围是 `[0, 1]`。当 `AVAILABLE` 字段为 `1` 且 `PROGRESS` 小于 1 时,表示 TiFlash 副本远落后于 TiKV,下推到 TiFlash 的查询可能会因等待数据复制超时而失败。 diff --git a/information-schema/information-schema-tiflash-segments.md b/information-schema/information-schema-tiflash-segments.md index 78841ab5a096..4ea5f49e5faf 100644 --- a/information-schema/information-schema-tiflash-segments.md +++ b/information-schema/information-schema-tiflash-segments.md @@ -1,15 +1,15 @@ --- title: TIFLASH_SEGMENTS -summary: 了解 information_schema 表 `TIFLASH_SEGMENTS`。 +summary: 了解 `TIFLASH_SEGMENTS` information_schema 表。 --- # TIFLASH_SEGMENTS > **警告:** > -> 请不要在生产环境中使用该系统表,因为该表字段信息尚未固定下来,可能会在 TiDB 未来版本中发生变化。 +> 请勿在生产环境中使用此表,因为表中的字段不稳定,可能会在新版本的 TiDB 中发生变更,且不会提前通知。 -`TIFLASH_SEGMENTS` 表提供了 TiFlash 内部数据表的统计信息。 +`TIFLASH_SEGMENTS` 表提供了 TiFlash 中数据表的统计信息。 ```sql USE information_schema; @@ -57,38 +57,38 @@ DESC tiflash_segments; 33 rows in set (0.00 sec) ``` -`TIFLASH_SEGMENTS` 表中各列的字段含义如下: +`TIFLASH_SEGMENTS` 表中的字段说明如下: -- `DATABASE`:Segment 所属表在 TiFlash 内部所属的数据库的名称。 -- `TABLE`:Segment 所属表在 TiFlash 内部的名称。 -- `TIDB_DATABASE`:Segment 所属表所属的数据库的名称。 -- `TIDB_TABLE`:Segment 所属表的名称。 -- `TABLE_ID`:Segment 所属表的内部 ID,该 ID 在一个 TiDB 集群内部唯一。 -- `IS_TOMBSTONE`:表示该 Segment 所属表是否处于待回收状态,为 1 表示该表处于待回收状态,为 0 则表示处于正常状态。 -- `SEGMENT_ID`:Segment ID,该 ID 在每张表内部唯一。 -- `RANGE`:Segment 包含数据的范围。 -- `EPOCH`:Segment 的更新版本号,每个 Segment 的版本号单调递增。 -- `ROWS`:Segment 的数据总行数。 -- `SIZE`:Segment 的数据总大小(单位:字节)。 -- `DELTA_RATE`:Delta 层的数据总行数占 Segment 数据总行数的比例。 -- `DELTA_MEMTABLE_ROWS`:Delta 层缓存中的数据总行数。 -- `DELTA_MEMTABLE_SIZE`:Delta 层缓存中的数据总大小(单位:字节)。 -- `DELTA_MEMTABLE_COLUMN_FILES`:Delta 层缓存中 Column File 数量。 -- `DELTA_MEMTABLE_DELETE_RANGES`:Delta 层缓存中 Delete Range 数量。 -- `DELTA_PERSISTED_PAGE_ID`:Delta 层数据在磁盘上存储的 ID。 -- `DELTA_PERSISTED_ROWS`:Delta 层已落盘的数据总行数。 -- `DELTA_PERSISTED_SIZE`:Delta 层已落盘的数据总大小(单位:字节)。 -- `DELTA_PERSISTED_COLUMN_FILES`:Delta 层已落盘 Column File 数量。 -- `DELTA_PERSISTED_DELETE_RANGES`:Delta 层已落盘 Delete Range 数量。 -- `DELTA_CACHE_SIZE`:Delta 层缓存大小(单位:字节)。 -- `DELTA_INDEX_SIZE`:Delta 层索引大小(单位:字节)。 -- `STABLE_PAGE_ID`:Stable 层数据在磁盘上存储的标识。 -- `STABLE_ROWS`:Stable 层的数据总行数。 -- `STABLE_SIZE`:Stable 层的数据总大小(单位:字节)。 -- `STABLE_DMFILES`:Stable 层 DMFile 数量。 -- `STABLE_DMFILES_ID_0`:Stable 层第一个 DMFile 在磁盘上存储的 ID。 -- `STABLE_DMFILES_ROWS`:Stable 层 DMFile 中的数据总行数。 -- `STABLE_DMFILES_SIZE`:Stable 层 DMFile 中的数据总大小(单位:字节)。 -- `STABLE_DMFILES_SIZE_ON_DISK`:Stable 层 DMFile 中的数据在磁盘占据的空间大小(单位:字节)。 -- `STABLE_DMFILES_PACKS`:Stable 层 DMFile 中包含的 Pack 数量。 -- `TIFLASH_INSTANCE`:TiFlash 实例地址。 +- `DATABASE`:TiFlash 中的数据库名称。该段所属的表在此数据库中。 +- `TABLE`:TiFlash 中的表名。该段属于此表。 +- `TIDB_DATABASE`:TiDB 中的数据库名称。该段所属的表在此数据库中。 +- `TIDB_TABLE`:TiDB 中的表名。该段属于此表。 +- `TABLE_ID`:该段所属表的内部 ID。此 ID 在 TiDB 集群内唯一。 +- `IS_TOMBSTONE`:表示该段所属的表是否可以被回收。`1` 表示表可以被回收,`0` 表示表处于正常状态。 +- `SEGMENT_ID`:段 ID,在表内唯一。 +- `RANGE`:该段包含的数据范围。 +- `EPOCH`:该段的更新版本。每个段的版本号单调递增。 +- `ROWS`:该段中的总行数。 +- `SIZE`:该段数据的总大小(以字节为单位)。 +- `DELTA_RATE`:Delta 层中的总行数与该段中总行数的比率。 +- `DELTA_MEMTABLE_ROWS`:Delta 层中缓存的总行数。 +- `DELTA_MEMTABLE_SIZE`:Delta 层中缓存的数据总大小(以字节为单位)。 +- `DELTA_MEMTABLE_COLUMN_FILES`:Delta 层中缓存的 Column Files 数量。 +- `DELTA_MEMTABLE_DELETE_RANGES`:Delta 层中缓存的 Delete Ranges 数量。 +- `DELTA_PERSISTED_PAGE_ID`:Delta 层中存储在磁盘上的数据的 ID。 +- `DELTA_PERSISTED_ROWS`:Delta 层中持久化数据的总行数。 +- `DELTA_PERSISTED_SIZE`:Delta 层中持久化数据的总大小(以字节为单位)。 +- `DELTA_PERSISTED_COLUMN_FILES`:Delta 层中持久化的 Column Files 数量。 +- `DELTA_PERSISTED_DELETE_RANGES`:Delta 层中持久化的 Delete Ranges 数量。 +- `DELTA_CACHE_SIZE`:Delta 层中缓存的大小(以字节为单位)。 +- `DELTA_INDEX_SIZE`:Delta 层中索引的大小(以字节为单位)。 +- `STABLE_PAGE_ID`:Stable 层中数据的磁盘存储 ID。 +- `STABLE_ROWS`:Stable 层中的总行数。 +- `STABLE_SIZE`:Stable 层中数据的总大小(以字节为单位)。 +- `STABLE_DMFILES`:Stable 层中的 DMFiles 数量。 +- `STABLE_DMFILES_ID_0`:Stable 层中第一个 DMFile 的磁盘存储 ID。 +- `STABLE_DMFILES_ROWS`:Stable 层中 DMFile 的总行数。 +- `STABLE_DMFILES_SIZE`:Stable 层中 DMFile 数据的总大小(以字节为单位)。 +- `STABLE_DMFILES_SIZE_ON_DISK`:Stable 层中 DMFile 占用的磁盘空间(以字节为单位)。 +- `STABLE_DMFILES_PACKS`:Stable 层中 DMFile 的 Packs 数量。 +- `TIFLASH_INSTANCE`:TiFlash 实例的地址。 diff --git a/information-schema/information-schema-tiflash-tables.md b/information-schema/information-schema-tiflash-tables.md index eed2af3ad6d6..974836a0ad2c 100644 --- a/information-schema/information-schema-tiflash-tables.md +++ b/information-schema/information-schema-tiflash-tables.md @@ -1,15 +1,15 @@ --- title: TIFLASH_TABLES -summary: 了解 information_schema 表 `TIFLASH_TABLES`。 +summary: 了解 `TIFLASH_TABLES` information_schema 表。 --- # TIFLASH_TABLES > **警告:** > -> 请不要在生产环境中使用该系统表,因为该表字段信息尚未固定下来,可能会在 TiDB 未来版本中发生变化。 +> 请勿在生产环境中使用此表,因为该表的字段不稳定,可能会在新版本的 TiDB 中发生变更,且不会预先通知。 -`TIFLASH_TABLES` 表提供了 TiFlash 内部数据表的统计信息。 +`TIFLASH_TABLES` 表提供了 TiFlash 中数据表的统计信息。 ```sql USE information_schema; @@ -78,59 +78,59 @@ DESC tiflash_tables; 54 rows in set (0.00 sec) ``` -`TIFLASH_TABLES` 表中各列的字段含义如下: +`TIFLASH_TABLES` 表中的字段说明如下: -- `DATABASE`:表在 TiFlash 内部所属的数据库的名称。 -- `TABLE`:表在 TiFlash 内部的名称。 -- `TIDB_DATABASE`:表所属的数据库的名称。 -- `TIDB_TABLE`:表的名称。 -- `TABLE_ID`:表的内部 ID,该 ID 在一个 TiDB 集群内部唯一。 -- `IS_TOMBSTONE`:表示该表是否处于待回收状态,为 1 表示该表处于待回收状态,为 0 则表示处于正常状态。 -- `SEGMENT_COUNT`:表的 Segment 数量,其中 Segment 为 TiFlash 内部管理数据的单元。 -- `TOTAL_ROWS`:表的总行数。 -- `TOTAL_SIZE`:表的总大小(单位:字节)。 -- `TOTAL_DELETE_RANGES`:表当前 Delete Range 的数量。 -- `DELTA_RATE_ROWS`:表 Delta 层数据总行数占该表总行数的比例。 -- `DELTA_RATE_SEGMENTS`:表所有 Segment 中包含非空 Delta 层的 Segment 的比例。 -- `DELTA_PLACED_RATE`:表 Delta 层数据行中已经完成 Index 构建的比例。 -- `DELTA_CACHE_SIZE`:表 Delta 层缓存大小(单位:字节)。 -- `DELTA_CACHE_RATE`:表 Delta 层数据的缓存比例。 -- `DELTA_CACHE_WASTED_RATE`:表 Delta 层缓存中无效数据的比例。 -- `DELTA_INDEX_SIZE`:Delta Index 占用的内存大小(单位:字节)。 -- `AVG_SEGMENT_ROWS`:表所有 Segment 的平均行数。 -- `AVG_SEGMENT_SIZE`:表所有 Segment 的平均大小(单位:字节)。 -- `DELTA_COUNT`:表中包含 Delta 层的 Segment 的个数。 -- `TOTAL_DELTA_ROWS`:所有 Delta 层的数据总行数。 -- `TOTAL_DELTA_SIZE`:所有 Delta 层的数据总大小(单位:字节)。 -- `AVG_DELTA_ROWS`:所有 Delta 层的平均数据行数。 -- `AVG_DELTA_SIZE`:所有 Delta 层的平均数据大小(单位:字节)。 -- `AVG_DELTA_DELETE_RANGES`:所有 Delta 层的平均 Delete Range 操作个数。 -- `STABLE_COUNT`:表中包含非空 Stable 层的 Segment 的个数。 -- `TOTAL_STABLE_ROWS`:所有 Stable 层的数据总行数。 -- `TOTAL_STABLE_SIZE`:所有 Stable 层的数据总大小(单位:字节)。 -- `TOTAL_STABLE_SIZE_ON_DISK`:所有 Stable 层的数据在磁盘占据的空间大小(单位:字节)。 -- `AVG_STABLE_ROWS`:所有 Stable 层的平均数据行数。 -- `AVG_STABLE_SIZE`:所有 Stable 层的平均数据大小(单位:字节)。 -- `TOTAL_PACK_COUNT_IN_DELTA`:所有 Delta 层的 Column File 总数量。 -- `MAX_PACK_COUNT_IN_DELTA`:单个 Delta 层包含 Column File 数量的最大值。 -- `AVG_PACK_COUNT_IN_DELTA`:所有 Delta 层的平均 Column File 数量。 -- `AVG_PACK_ROWS_IN_DELTA`:Delta 层所有 Column File 的平均数据行数。 -- `AVG_PACK_SIZE_IN_DELTA`:Delta 层所有 Column File 的平均数据大小(单位:字节)。 -- `TOTAL_PACK_COUNT_IN_STABLE`:所有 Stable 层的 Pack 总数量。 -- `AVG_PACK_COUNT_IN_STABLE`:所有 Stable 层的平均 Pack 数量。 -- `AVG_PACK_ROWS_IN_STABLE`:Stable 层所有 Pack 的平均数据行数。 -- `AVG_PACK_SIZE_IN_STABLE`:Stable 层所有 Pack 的平均数据大小(单位:字节)。 -- `STORAGE_STABLE_NUM_SNAPSHOTS`:Stable 层 Snapshot 数量。 -- `STORAGE_STABLE_OLDEST_SNAPSHOT_LIFETIME`:Stable 层最早 Snapshot 的持续时间(单位:秒)。 -- `STORAGE_STABLE_OLDEST_SNAPSHOT_THREAD_ID`:Stable 层最早 Snapshot 对应的线程 ID。 -- `STORAGE_STABLE_OLDEST_SNAPSHOT_TRACING_ID`:Stable 层最早 Snapshot 对应的跟踪 ID。 -- `STORAGE_DELTA_NUM_SNAPSHOTS`:Delta 层 Snapshot 数量。 -- `STORAGE_DELTA_OLDEST_SNAPSHOT_LIFETIME`:Delta 层最早 Snapshot 的持续时间(单位:秒)。 -- `STORAGE_DELTA_OLDEST_SNAPSHOT_THREAD_ID`:Delta 层最早 Snapshot 对应的线程 ID。 -- `STORAGE_DELTA_OLDEST_SNAPSHOT_TRACING_ID`:Delta 层最早 Snapshot 对应的跟踪 ID。 -- `STORAGE_META_NUM_SNAPSHOTS`:Meta 元信息 Snapshot 数量。 -- `STORAGE_META_OLDEST_SNAPSHOT_LIFETIME`:Meta 元信息最早 Snapshot 的持续时间。(单位:秒) -- `STORAGE_META_OLDEST_SNAPSHOT_THREAD_ID`:Meta 元信息最早 Snapshot 对应的线程 ID。 -- `STORAGE_META_OLDEST_SNAPSHOT_TRACING_ID`:Meta 元信息最早 Snapshot 对应的跟踪 ID。 -- `BACKGROUND_TASKS_LENGTH`:后台任务队列长度。 -- `TIFLASH_INSTANCE`:TiFlash 实例地址。 +- `DATABASE`:表在 TiFlash 中所属的数据库名称。 +- `TABLE`:表在 TiFlash 中的名称。 +- `TIDB_DATABASE`:表在 TiDB 中所属的数据库名称。 +- `TIDB_TABLE`:表在 TiDB 中的名称。 +- `TABLE_ID`:表的内部 ID,在 TiDB 集群内唯一。 +- `IS_TOMBSTONE`:表示表是否可以被回收。`1` 表示表可以被回收,`0` 表示表处于正常状态。 +- `SEGMENT_COUNT`:表中的段数量。段是 TiFlash 中的数据管理单元。 +- `TOTAL_ROWS`:表中的总行数。 +- `TOTAL_SIZE`:表的总大小(字节)。 +- `TOTAL_DELETE_RANGES`:表中 Delete Range 的总数。 +- `DELTA_RATE_ROWS`:表在 Delta 层的总行数与该表总行数的比率。 +- `DELTA_RATE_SEGMENTS`:表中包含非空 Delta 层的段的比例。 +- `DELTA_PLACED_RATE`:表在 Delta 层中已完成索引构建的行的比例。 +- `DELTA_CACHE_SIZE`:表在 Delta 层的缓存大小(字节)。 +- `DELTA_CACHE_RATE`:表在 Delta 层的缓存数据比例。 +- `DELTA_CACHE_WASTED_RATE`:表在 Delta 层的无效缓存数据比例。 +- `DELTA_INDEX_SIZE`:Delta 层中索引占用的内存大小(字节)。 +- `AVG_SEGMENT_ROWS`:表中所有段的平均行数。 +- `AVG_SEGMENT_SIZE`:表中所有段的平均大小(字节)。 +- `DELTA_COUNT`:表中包含非空 Delta 层的段数量。 +- `TOTAL_DELTA_ROWS`:Delta 层中的总行数。 +- `TOTAL_DELTA_SIZE`:Delta 层中数据的总大小(字节)。 +- `AVG_DELTA_ROWS`:所有 Delta 层中数据的平均行数。 +- `AVG_DELTA_SIZE`:所有 Delta 层中数据的平均大小(字节)。 +- `AVG_DELTA_DELETE_RANGES`:所有 Delta 层中 Delete Range 操作的平均数量。 +- `STABLE_COUNT`:表中包含非空 Stable 层的段数量。 +- `TOTAL_STABLE_ROWS`:所有 Stable 层中的总行数。 +- `TOTAL_STABLE_SIZE`:所有 Stable 层中数据的总大小(字节)。 +- `TOTAL_STABLE_SIZE_ON_DISK`:所有 Stable 层中数据占用的磁盘空间(字节)。 +- `AVG_STABLE_ROWS`:所有 Stable 层中数据的平均行数。 +- `AVG_STABLE_SIZE`:所有 Stable 层中数据的平均大小(字节)。 +- `TOTAL_PACK_COUNT_IN_DELTA`:所有 Delta 层中的列文件总数。 +- `MAX_PACK_COUNT_IN_DELTA`:单个 Delta 层中的最大列文件数。 +- `AVG_PACK_COUNT_IN_DELTA`:所有 Delta 层中的平均列文件数。 +- `AVG_PACK_ROWS_IN_DELTA`:所有 Delta 层中所有列文件的平均行数。 +- `AVG_PACK_SIZE_IN_DELTA`:所有 Delta 层中所有列文件的平均数据大小(字节)。 +- `TOTAL_PACK_COUNT_IN_STABLE`:所有 Stable 层中的 Pack 总数。 +- `AVG_PACK_COUNT_IN_STABLE`:所有 Stable 层中的平均 Pack 数。 +- `AVG_PACK_ROWS_IN_STABLE`:所有 Stable 层中所有 Pack 的平均行数。 +- `AVG_PACK_SIZE_IN_STABLE`:Stable 层中所有 Pack 的平均数据大小(字节)。 +- `STORAGE_STABLE_NUM_SNAPSHOTS`:Stable 层中的快照数量。 +- `STORAGE_STABLE_OLDEST_SNAPSHOT_LIFETIME`:Stable 层中最早快照的持续时间(秒)。 +- `STORAGE_STABLE_OLDEST_SNAPSHOT_THREAD_ID`:Stable 层中最早快照的线程 ID。 +- `STORAGE_STABLE_OLDEST_SNAPSHOT_TRACING_ID`:Stable 层中最早快照的追踪 ID。 +- `STORAGE_DELTA_NUM_SNAPSHOTS`:Delta 层中的快照数量。 +- `STORAGE_DELTA_OLDEST_SNAPSHOT_LIFETIME`:Delta 层中最早快照的持续时间(秒)。 +- `STORAGE_DELTA_OLDEST_SNAPSHOT_THREAD_ID`:Delta 层中最早快照的线程 ID。 +- `STORAGE_DELTA_OLDEST_SNAPSHOT_TRACING_ID`:Delta 层中最早快照的追踪 ID。 +- `STORAGE_META_NUM_SNAPSHOTS`:元信息中的快照数量。 +- `STORAGE_META_OLDEST_SNAPSHOT_LIFETIME`:元信息中最早快照的持续时间(秒)。 +- `STORAGE_META_OLDEST_SNAPSHOT_THREAD_ID`:元信息中最早快照的线程 ID。 +- `STORAGE_META_OLDEST_SNAPSHOT_TRACING_ID`:元信息中最早快照的追踪 ID。 +- `BACKGROUND_TASKS_LENGTH`:后台任务队列的长度。 +- `TIFLASH_INSTANCE`:TiFlash 实例的地址。 diff --git a/information-schema/information-schema-tikv-region-peers.md b/information-schema/information-schema-tikv-region-peers.md index 25e0cd41adfc..128df4af13c7 100644 --- a/information-schema/information-schema-tikv-region-peers.md +++ b/information-schema/information-schema-tikv-region-peers.md @@ -1,18 +1,22 @@ --- title: TIKV_REGION_PEERS -summary: 了解 INFORMATION_SCHEMA 表 `TIKV_REGION_PEERS`。 +summary: 了解 `TIKV_REGION_PEERS` INFORMATION_SCHEMA 表。 --- # TIKV_REGION_PEERS -`TIKV_REGION_PEERS` 表提供了 TiKV 中单个 Region 节点的详细信息,比如它是一个 learner 还是一个 leader。 +`TIKV_REGION_PEERS` 表显示了 TiKV 中单个 Region 节点的详细信息,例如它是否是 learner 或 leader。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ```sql USE INFORMATION_SCHEMA; DESC TIKV_REGION_PEERS; ``` -输出结果如下: +输出如下: ```sql +--------------+-------------+------+------+---------+-------+ @@ -29,7 +33,7 @@ DESC TIKV_REGION_PEERS; 7 rows in set (0.01 sec) ``` -例如,使用以下 SQL 语句,你可以查询 `WRITTEN_BYTES` 最大的前 3 个 Region 所在的 TiKV 地址: +例如,你可以使用以下 SQL 语句查询 `WRITTEN_BYTES` 值最大的前 3 个 Region 对应的具体 TiKV 地址: ```sql SELECT @@ -46,15 +50,15 @@ WHERE AND peer.store_id = tikv.store_id; ``` -`TIKV_REGION_PEERS` 表各列含义如下: - -* `REGION_ID`:REGION 的 ID。 -* `PEER_ID`:REGION 中对应的副本 Peer 的 ID。 -* `STORE_ID`:REGION 所在 TiKV Store 的 ID。 -* `IS_LEARNER`:Peer 是否是 LEARNER。 -* `IS_LEADER`:Peer 是否是 LEADER。 -* `STATUS`:Peer 的状态,一共有 3 种状态: - * `PENDING`:暂时不可用状态。 - * `DOWN`:下线转态,该 Peer 不再提供服务。 - * `NORMAL`:正常状态。 -* `DOWN_SECONDS`:处于下线状态的时间,单位是秒。 +`TIKV_REGION_PEERS` 表中的字段说明如下: + +* REGION_ID:Region 的 ID。 +* PEER_ID:Region peer 的 ID。 +* STORE_ID:Region 所在 TiKV store 的 ID。 +* IS_LEARNER:peer 是否为 learner。 +* IS_LEADER:peer 是否为 leader。 +* STATUS:peer 的状态: + * PENDING:暂时不可用。 + * DOWN:离线且已转换。该 peer 不再提供服务。 + * NORMAL:正常运行。 +* DOWN_SECONDS:离线持续时间,单位为秒。 diff --git a/information-schema/information-schema-tikv-region-status.md b/information-schema/information-schema-tikv-region-status.md index 60716e258b8c..97673cc0251b 100644 --- a/information-schema/information-schema-tikv-region-status.md +++ b/information-schema/information-schema-tikv-region-status.md @@ -1,11 +1,15 @@ --- title: TIKV_REGION_STATUS -summary: 了解 information_schema 表 `TIKV_REGION_STATUS`。 +summary: 了解 `TIKV_REGION_STATUS` information_schema 表。 --- # TIKV_REGION_STATUS -`TIKV_REGION_STATUS` 表通过 PD 的 API 展示 TiKV Region 的基本信息,比如 Region ID、开始和结束键值以及读写流量。 +`TIKV_REGION_STATUS` 表通过 PD 的 API 显示了 TiKV Region 的一些基本信息,如 Region ID、起始和结束键值、读写流量等。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ```sql USE INFORMATION_SCHEMA; @@ -42,35 +46,33 @@ DESC TIKV_REGION_STATUS; 20 rows in set (0.00 sec) ``` -`TIKV_REGION_STATUS` 表中列的含义如下: +`TIKV_REGION_STATUS` 表中各列的描述如下: * `REGION_ID`:Region 的 ID。 -* `START_KEY`:Region 的起始 key 的值。 -* `END_KEY`:Region 的末尾 key 的值。 -* `TABLE_ID`:Region 所属的表的 ID。 -* `DB_NAME`:`TABLE_ID` 所属的数据库的名称。 -* `TABLE_NAME`:Region 所属的表的名称。 -* `IS_INDEX`:Region 数据是否是索引,0 代表不是索引,1 代表是索引。如果当前 Region 同时包含表数据和索引数据,会有多行记录,`IS_INDEX` 分别是 0 和 1。 -* `INDEX_ID`:Region 所属的索引的 ID。如果 `IS_INDEX` 为 0,这一列的值就为 NULL。 -* `INDEX_NAME`:Region 所属的索引的名称。如果 `IS_INDEX` 为 0,这一列的值就为 NULL。 +* `START_KEY`:Region 的起始键值。 +* `END_KEY`:Region 的结束键值。 +* `TABLE_ID`:Region 所属表的 ID。 +* `DB_NAME`:`TABLE_ID` 所属的数据库名称。 +* `TABLE_NAME`:Region 所属的表名。 +* `IS_INDEX`:Region 数据是否为索引。0 表示不是索引,1 表示是索引。如果当前 Region 同时包含表数据和索引数据,将会有多行记录,`IS_INDEX` 分别为 0 和 1。 +* `INDEX_ID`:Region 所属索引的 ID。如果 `IS_INDEX` 为 0,则该列值为 NULL。 +* `INDEX_NAME`:Region 所属索引的名称。如果 `IS_INDEX` 为 0,则该列值为 NULL。 * `IS_PARTITION`:Region 所属的表是否为分区表。 -* `PARTITION_ID`:如果 Region 所属的表为分区表,显示 Region 所属的分区的 ID。 -* `PARTITION_NAME`:如果 Region 所属的表为分区表,显示 Region 所属的分区的名字。 -* `EPOCH_CONF_VER`:Region 的配置的版本号,在增加或减少 peer 时版本号会递增。 -* `EPOCH_VERSION`:Region 的当前版本号,在分裂或合并时版本号会递增。 -* `WRITTEN_BYTES`:已经往 Region 写入的数据量 (bytes)。 -* `READ_BYTES`:已经从 Region 读取的数据量 (bytes)。 -* `APPROXIMATE_SIZE`:Region 的近似数据量 (MB)。 -* `APPROXIMATE_KEYS`:Region 中 key 的近似数量。 -* `REPLICATIONSTATUS_STATE`:Region 当前的同步状态,可能为 `UNKNOWN` / `SIMPLE_MAJORITY` / `INTEGRITY_OVER_LABEL` 其中一种状态。 -* `REPLICATIONSTATUS_STATEID`:`REPLICATIONSTATUS_STATE` 对应的标识符。 +* `PARTITION_ID`:如果 Region 所属的表是分区表,该列显示 Region 所属分区的 ID。 +* `PARTITION_NAME`:如果 Region 所属的表是分区表,该列显示 Region 所属分区的名称。 +* `EPOCH_CONF_VER`:Region 配置的版本号。当添加或删除节点时,版本号会增加。 +* `EPOCH_VERSION`:Region 的当前版本号。当 Region 发生分裂或合并时,版本号会增加。 +* `WRITTEN_BYTES`:写入 Region 的数据量(字节)。 +* `READ_BYTES`:从 Region 读取的数据量(字节)。 +* `APPROXIMATE_SIZE`:Region 的近似数据大小(MB)。 +* `APPROXIMATE_KEYS`:Region 中近似的键数量。 +* `REPLICATIONSTATUS_STATE`:Region 当前的复制状态。状态可能为 `UNKNOWN`、`SIMPLE_MAJORITY` 或 `INTEGRITY_OVER_LABEL`。 +* `REPLICATIONSTATUS_STATEID`:与 `REPLICATIONSTATUS_STATE` 对应的标识符。 -通过在 `EPOCH_CONF_VER`、`WRITTEN_BYTES` 和 `READ_BYTES` 列上执行 `ORDER BY X LIMIT Y` 操作,你可以在 pd-ctl 中实现 `top confver`、`top read` 和 `top write` 操作。 +此外,你可以通过对 `EPOCH_CONF_VER`、`WRITTEN_BYTES` 和 `READ_BYTES` 列执行 `ORDER BY X LIMIT Y` 操作来实现 pd-ctl 中的 `top confver`、`top read` 和 `top write` 操作。 你可以使用以下 SQL 语句查询写入数据最多的前 3 个 Region: -{{< copyable "sql" >}} - ```sql SELECT * FROM tikv_region_status ORDER BY written_bytes DESC LIMIT 3; ``` diff --git a/information-schema/information-schema-tikv-store-status.md b/information-schema/information-schema-tikv-store-status.md index 4477c64d69ad..20621ae9dd77 100644 --- a/information-schema/information-schema-tikv-store-status.md +++ b/information-schema/information-schema-tikv-store-status.md @@ -1,11 +1,15 @@ --- title: TIKV_STORE_STATUS -summary: 了解 INFORMATION_SCHEMA 表 `TIKV_STORE_STATUS`。 +summary: 了解 `TIKV_STORE_STATUS` INFORMATION_SCHEMA 表。 --- # TIKV_STORE_STATUS -`TIKV_STORE_STATUS` 表通过 PD 的 API 显示了 TiKV 节点的一些基本信息,例如在集群中分配的 ID、地址和端口、状态、容量以及当前节点的 Region leader 的数量。 +`TIKV_STORE_STATUS` 表通过 PD 的 API 显示 TiKV 节点的一些基本信息,如在集群中分配的 ID、地址和端口,以及当前节点的状态、容量和 Region leader 的数量。 + +> **注意:** +> +> 此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ```sql USE INFORMATION_SCHEMA; @@ -41,24 +45,24 @@ DESC TIKV_STORE_STATUS; 19 rows in set (0.00 sec) ``` -`TIKV_STORE_STATUS` 表中列的含义如下: +`TIKV_STORE_STATUS` 表中各列的描述如下: * `STORE_ID`:Store 的 ID。 * `ADDRESS`:Store 的地址。 * `STORE_STATE`:Store 状态的标识符,与 `STORE_STATE_NAME` 相对应。 -* `STORE_STATE_NAME`:Store 状态的名字,为 `Up`、`Offline`、`Tombstone` 中的一种。 -* `LABEL`:给 Store 设置的标签。 +* `STORE_STATE_NAME`:Store 状态的名称。名称为 `Up`、`Offline` 或 `Tombstone`。 +* `LABEL`:为 Store 设置的标签。 * `VERSION`:Store 的版本号。 * `CAPACITY`:Store 的存储容量。 * `AVAILABLE`:Store 的剩余存储空间。 -* `LEADER_COUNT`:Store 上的 leader 的数量。 +* `LEADER_COUNT`:Store 上的 leader 数量。 * `LEADER_WEIGHT`:Store 的 leader 权重。 -* `LEADER_SCORE`:Store 的 leader 评分。 -* `LEADER_SIZE`:Store 上的所有 leader 的近似总数据量 (MB)。 -* `REGION_COUNT`:Store 上的 Region 总数。 +* `LEADER_SCORE`:Store 的 leader 分数。 +* `LEADER_SIZE`:Store 上所有 leader 的大致总数据大小(MB)。 +* `REGION_COUNT`:Store 上的 Region 数量。 * `REGION_WEIGHT`:Store 的 Region 权重。 -* `REGION_SCORE`:Store 的 Region 评分。 -* `REGION_SIZE`:Store 上的所有 Region 的近似总数据量 (MB)。 -* `START_TS`:Store 启动时的时间戳。 -* `LAST_HEARTBEAT_TS`:Store 上次发出心跳的时间戳。 +* `REGION_SCORE`:Store 的 Region 分数。 +* `REGION_SIZE`:Store 上所有 Region 的大致总数据大小(MB)。 +* `START_TS`:Store 启动的时间戳。 +* `LAST_HEARTBEAT_TS`:Store 发送的最后一次心跳的时间戳。 * `UPTIME`:Store 启动以来的总时间。 diff --git a/information-schema/information-schema-user-attributes.md b/information-schema/information-schema-user-attributes.md index 8cd9ca272b5f..2e2c09100486 100644 --- a/information-schema/information-schema-user-attributes.md +++ b/information-schema/information-schema-user-attributes.md @@ -1,11 +1,11 @@ --- title: USER_ATTRIBUTES -summary: 了解 INFORMATION_SCHEMA 表 `USER_ATTRIBUTES`。 +summary: 了解 `USER_ATTRIBUTES` INFORMATION_SCHEMA 表。 --- # USER_ATTRIBUTES -`USER_ATTRIBUTES` 表提供了用户的注释和属性。该表的数据根据 `mysql.user` 系统表生成。 +`USER_PRIVILEGES` 表提供了用户注释和用户属性的相关信息。这些信息来自 `mysql.user` 系统表。 ```sql USE information_schema; @@ -23,13 +23,13 @@ DESC user_attributes; 3 rows in set (0.00 sec) ``` -`USER_ATTRIBUTES` 表中列的含义如下: +`USER_ATTRIBUTES` 表中的字段说明如下: * `USER`:用户名。 -* `HOST`:用户可用于连接的主机。百分号(`%`)表示主机名不受限制。 -* `ATTRIBUTE`:通过 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 或 [`ALTER USER`](/sql-statements/sql-statement-alter-user.md) 语句设置的用户相关的注释和属性。 +* `HOST`:用户可以从哪个主机连接到 TiDB。如果该字段的值为 `%`,表示用户可以从任何主机连接到 TiDB。 +* `ATTRIBUTE`:用户的注释和属性,通过 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 或 [`ALTER USER`](/sql-statements/sql-statement-alter-user.md) 语句设置。 -示例: +以下是一个示例: ```sql CREATE USER testuser1 COMMENT 'This user is created only for test'; diff --git a/information-schema/information-schema-user-privileges.md b/information-schema/information-schema-user-privileges.md index 5ec5fe6ddab6..4596ca7b01c1 100644 --- a/information-schema/information-schema-user-privileges.md +++ b/information-schema/information-schema-user-privileges.md @@ -1,11 +1,11 @@ --- title: USER_PRIVILEGES -summary: 了解 INFORMATION_SCHEMA 表 `USER_PRIVILEGES`。 +summary: 了解 `USER_PRIVILEGES` information_schema 表。 --- # USER_PRIVILEGES -`USER_PRIVILEGES` 表提供了关于全局权限的信息。该表的数据根据 `mysql.user` 系统表生成。 +`USER_PRIVILEGES` 表提供全局权限的信息。这些信息来自 `mysql.user` 系统表: ```sql USE INFORMATION_SCHEMA; @@ -26,7 +26,7 @@ DESC USER_PRIVILEGES; 4 rows in set (0.00 sec) ``` -查看 `USER_PRIVILEGES` 表的信息: +查看 `USER_PRIVILEGES` 表中的信息: ```sql SELECT * FROM USER_PRIVILEGES; @@ -34,6 +34,8 @@ SELECT * FROM USER_PRIVILEGES; 输出结果如下: + + ```sql +------------+---------------+-------------------------+--------------+ | GRANTEE | TABLE_CATALOG | PRIVILEGE_TYPE | IS_GRANTABLE | @@ -73,12 +75,57 @@ SELECT * FROM USER_PRIVILEGES; 31 rows in set (0.00 sec) ``` -`USER_PRIVILEGES` 表中列的含义如下: + + + + + + +```sql ++------------+---------------+-------------------------+--------------+ +| GRANTEE | TABLE_CATALOG | PRIVILEGE_TYPE | IS_GRANTABLE | ++------------+---------------+-------------------------+--------------+ +| 'root'@'%' | def | SELECT | YES | +| 'root'@'%' | def | INSERT | YES | +| 'root'@'%' | def | UPDATE | YES | +| 'root'@'%' | def | DELETE | YES | +| 'root'@'%' | def | CREATE | YES | +| 'root'@'%' | def | DROP | YES | +| 'root'@'%' | def | PROCESS | YES | +| 'root'@'%' | def | REFERENCES | YES | +| 'root'@'%' | def | ALTER | YES | +| 'root'@'%' | def | SHOW DATABASES | YES | +| 'root'@'%' | def | SUPER | YES | +| 'root'@'%' | def | EXECUTE | YES | +| 'root'@'%' | def | INDEX | YES | +| 'root'@'%' | def | CREATE USER | YES | +| 'root'@'%' | def | CREATE TABLESPACE | YES | +| 'root'@'%' | def | TRIGGER | YES | +| 'root'@'%' | def | CREATE VIEW | YES | +| 'root'@'%' | def | SHOW VIEW | YES | +| 'root'@'%' | def | CREATE ROLE | YES | +| 'root'@'%' | def | DROP ROLE | YES | +| 'root'@'%' | def | CREATE TEMPORARY TABLES | YES | +| 'root'@'%' | def | LOCK TABLES | YES | +| 'root'@'%' | def | CREATE ROUTINE | YES | +| 'root'@'%' | def | ALTER ROUTINE | YES | +| 'root'@'%' | def | EVENT | YES | +| 'root'@'%' | def | RELOAD | YES | +| 'root'@'%' | def | FILE | YES | +| 'root'@'%' | def | REPLICATION CLIENT | YES | +| 'root'@'%' | def | REPLICATION SLAVE | YES | ++------------+---------------+-------------------------+--------------+ +29 rows in set (0.00 sec) +``` + + + +`USER_PRIVILEGES` 表中的字段说明如下: -* `GRANTEE`:被授权的用户名称,格式为 `'user_name'@'host_name'`。 -* `TABLE_CATALOG`:表所属的目录的名称。该值始终为 `def`。 -* `PRIVILEGE_TYPE`:被授权的权限类型,每行只列一个权限。 -* `IS_GRANTABLE`:如果用户有 `GRANT OPTION` 的权限,则为 `YES`,否则为 `NO`。 +* `GRANTEE`:被授予权限的用户名,格式为 `'user_name'@'host_name'`。 +* `TABLE_CATALOG`:表所属的目录名称。此值始终为 `def`。 +* `PRIVILEGE_TYPE`:要授予的权限类型。每行仅显示一种权限类型。 +* `IS_GRANTABLE`:如果你具有 `GRANT OPTION` 权限,则值为 `YES`;否则,值为 `NO`。 ## 另请参阅 diff --git a/information-schema/information-schema-variables-info.md b/information-schema/information-schema-variables-info.md index 056eb8f0081e..540a2b0600ba 100644 --- a/information-schema/information-schema-variables-info.md +++ b/information-schema/information-schema-variables-info.md @@ -1,11 +1,11 @@ --- title: VARIABLES_INFO -summary: 了解 information_schema 表 `VARIABLES_INFO`。 +summary: 了解 `VARIABLES_INFO` information_schema 表。 --- # VARIABLES_INFO -`VARIABLES_INFO` 可用于查看当前 TiDB 集群或实例的[系统变量](/system-variables.md)默认值、当前值以及作用域等信息。 +`VARIABLES_INFO` 表提供了当前 TiDB 实例或 TiDB 集群中[系统变量](/system-variables.md)的默认值、当前值和作用范围等信息。 ```sql USE information_schema; @@ -43,13 +43,13 @@ SELECT * FROM variables_info ORDER BY variable_name LIMIT 3; 3 rows in set (0.01 sec) ``` -`VARIABLES_INFO` 表中列的含义如下: +`VARIABLES_INFO` 表中各字段的描述如下: -* `VARIABLE_NAME`:系统变量名称。 -* `VARIABLE_SCOPE`:系统变量的作用域。`SESSION` 表示当前 session 可见;`INSTANCE` 表示当前 TiDB 实例可见;`GLOBAL` 表示集群内可见;`NONE` 表示全局只读。 +* `VARIABLE_NAME`:系统变量的名称。 +* `VARIABLE_SCOPE`:系统变量的作用范围。`SESSION` 表示系统变量仅在当前会话中有效。`INSTANCE` 表示系统变量在 TiDB 实例中有效。`GLOBAL` 表示系统变量在 TiDB 集群中有效。`NONE` 表示系统变量在 TiDB 集群中为只读。 * `DEFAULT_VALUE`:系统变量的默认值。 -* `CURRENT_VALUE`:系统变量的当前值。如果应用范围中包含 `SESSION`,则显示当前 session 的值。 -* `MIN_VALUE`:数值类型的系统变量允许的最小值。如果变量值为非数值类型,则为 NULL。 -* `MAX_VALUE`:数值类型的系统变量允许的最大值。如果变量值为非数值类型,则为 NULL。 -* `POSSIBLE_VALUES`:系统变量所有可能的值。如果变量值不可枚举,则为 NULL。 -* `IS_NOOP`:是否为 `noop` 的系统变量。 +* `CURRENT_VALUE`:系统变量的当前值。如果作用范围包含 `SESSION`,则 `CURRENT_VALUE` 为当前会话中的值。 +* `MIN_VALUE`:系统变量允许的最小值。如果系统变量不是数值类型,则 `MIN_VALUE` 为 NULL。 +* `MAX_VALUE`:系统变量允许的最大值。如果系统变量不是数值类型,则 `MAX_VALUE` 为 NULL。 +* `POSSIBLE_VALUES`:系统变量的可能值。如果系统变量不是枚举类型,则 `POSSIBLE_VALUES` 为 NULL。 +* `IS_NOOP`:系统变量是否为 `noop`(无操作)系统变量。 diff --git a/information-schema/information-schema-views.md b/information-schema/information-schema-views.md index 021d7cb033d0..d95cb0f2d257 100644 --- a/information-schema/information-schema-views.md +++ b/information-schema/information-schema-views.md @@ -1,11 +1,11 @@ --- title: VIEWS -summary: 了解 INFORMATION_SCHEMA 表 `VIEWS`。 +summary: 了解 `VIEWS` INFORMATION_SCHEMA 表。 --- # VIEWS -`VIEWS` 表提供了关于 [SQL 视图](/views.md)的信息。 +`VIEWS` 表提供了关于 [SQL 视图](/views.md) 的信息。 ```sql USE INFORMATION_SCHEMA; @@ -32,7 +32,7 @@ DESC VIEWS; 10 rows in set (0.00 sec) ``` -创建视图并查询 `VIEWS` 表信息: +创建一个视图并查询 `VIEWS` 表: ```sql CREATE VIEW test.v1 AS SELECT 1; @@ -56,20 +56,20 @@ COLLATION_CONNECTION: utf8mb4_0900_ai_ci 1 row in set (0.00 sec) ``` -`VIEWS` 表中列的含义如下: +`VIEWS` 表中各字段的描述如下: -* `TABLE_CATALOG`:视图所属的目录的名称。该值始终为 `def`。 -* `TABLE_SCHEMA`:视图所属的数据库的名称。 +* `TABLE_CATALOG`:视图所属的目录名称。该值始终为 `def`。 +* `TABLE_SCHEMA`:视图所属的数据库名称。 * `TABLE_NAME`:视图名称。 -* `VIEW_DEFINITION`:视图的定义,由创建视图时 `SELECT` 部分的语句组成。 -* `CHECK_OPTION`:`CHECK_OPTION` 的值。取值为 `NONE`、`CASCADE` 或 `LOCAL`。 -* `IS_UPDATABLE`:`UPDATE`/`INSERT`/`DELETE` 是否对该视图可用。在 TiDB,始终为 `NO`。 -* `DEFINER`:视图的创建者用户名称,格式为 `'user_name'@'host_name'`。 -* `SECURITY_TYPE`:`SQL SECURITY` 的值,取值为 `DEFINER` 或 `INVOKER`。 -* `CHARACTER_SET_CLIENT`:在视图创建时 session 变量 `character_set_client` 的值。 -* `COLLATION_CONNECTION`:在视图创建时 session 变量 `collation_connection` 的值。 +* `VIEW_DEFINITION`:视图的定义,即创建视图时的 `SELECT` 语句。 +* `CHECK_OPTION`:`CHECK_OPTION` 的值。可选值为 `NONE`、`CASCADE` 和 `LOCAL`。 +* `IS_UPDATABLE`:视图是否可以执行 `UPDATE`/`INSERT`/`DELETE` 操作。在 TiDB 中,该值始终为 `NO`。 +* `DEFINER`:创建视图的用户名,格式为 `'user_name'@'host_name'`。 +* `SECURITY_TYPE`:`SQL SECURITY` 的值。可选值为 `DEFINER` 和 `INVOKER`。 +* `CHARACTER_SET_CLIENT`:创建视图时 `character_set_client` 会话变量的值。 +* `COLLATION_CONNECTION`:创建视图时 `collation_connection` 会话变量的值。 ## 另请参阅 - [`CREATE VIEW`](/sql-statements/sql-statement-create-view.md) -- [`DROP VIEW`](/sql-statements/sql-statement-drop-view.md) \ No newline at end of file +- [`DROP VIEW`](/sql-statements/sql-statement-drop-view.md) diff --git a/information-schema/information-schema.md b/information-schema/information-schema.md index a2b8505a5e93..7399a2bf71cd 100644 --- a/information-schema/information-schema.md +++ b/information-schema/information-schema.md @@ -1,102 +1,209 @@ --- title: Information Schema -summary: Information Schema 是一种查看系统元数据的 ANSI 标准方法。TiDB 提供了许多自定义的 `INFORMATION_SCHEMA` 表,包括与 MySQL 兼容的表和 TiDB 中的扩展表。这些表提供了关于字符集、排序规则、列、存储引擎、索引、表大小、慢查询等信息,帮助用户进行系统监控和优化。 +summary: TiDB 实现了 ANSI 标准的 information_schema,用于查看系统元数据。 --- # Information Schema -Information Schema 提供了一种查看系统元数据的 ANSI 标准方法。除了包含与 MySQL 兼容的表外,TiDB 还提供了许多自定义的 `INFORMATION_SCHEMA` 表。 - -许多 `INFORMATION_SCHEMA` 表都可以通过相应的 `SHOW` 语句查看。查询 `INFORMATION_SCHEMA` 的好处是可以在表之间进行 `join` 操作。 - -## 与 MySQL 兼容的表 - -| 表名 | 描述 | -| -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | -| [`CHARACTER_SETS`](/information-schema/information-schema-character-sets.md) | 提供 TiDB 支持的字符集列表。 | -| [`CHECK_CONSTRAINTS`](/information-schema/information-schema-check-constraints.md) | 提供关于表上 [`CHECK` 约束](/constraints.md#check-约束)的信息。 | -| [`COLLATIONS`](/information-schema/information-schema-collations.md) | 提供 TiDB 支持的排序规则列表。 | -| [`COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) | 说明哪些排序规则适用于哪些字符集。 | -| [`COLUMNS`](/information-schema/information-schema-columns.md) | 提供所有表中列的列表。 | -| `COLUMN_PRIVILEGES` | TiDB 未实现,返回零行。 | -| `COLUMN_STATISTICS` | TiDB 未实现,返回零行。 | -| [`ENGINES`](/information-schema/information-schema-engines.md) | 提供支持的存储引擎列表。 | -| `EVENTS` | TiDB 未实现,返回零行。 | -| `FILES` | TiDB 未实现,返回零行。 | -| `GLOBAL_STATUS` | TiDB 未实现,返回零行。 | -| `GLOBAL_VARIABLES` | TiDB 未实现,返回零行。 | -| [`KEYWORDS`](/information-schema/information-schema-keywords.md) | 提供关键字列表。 | -| [`KEY_COLUMN_USAGE`](/information-schema/information-schema-key-column-usage.md) | 描述列的键约束,例如主键约束。 | -| `OPTIMIZER_TRACE` | TiDB 未实现,返回零行。 | -| `PARAMETERS` | TiDB 未实现,返回零行。 | -| [`PARTITIONS`](/information-schema/information-schema-partitions.md) | 提供表分区的列表。 | -| `PLUGINS` | TiDB 未实现,返回零行。 | -| [`PROCESSLIST`](/information-schema/information-schema-processlist.md) | 提供与 `SHOW PROCESSLIST` 命令类似的信息。 | -| `PROFILING` | TiDB 未实现,返回零行。 | -| `REFERENTIAL_CONSTRAINTS` | 提供有关 `FOREIGN KEY` 约束的信息。 | -| `ROUTINES` | TiDB 未实现,返回零行。 | -| [`SCHEMATA`](/information-schema/information-schema-schemata.md) | 提供与 `SHOW DATABASES` 命令类似的信息。 | -| `SCHEMA_PRIVILEGES` | TiDB 未实现,返回零行。 | -| `SESSION_STATUS` | TiDB 未实现,返回零行。 | -| [`SESSION_VARIABLES`](/information-schema/information-schema-session-variables.md) | 提供与 `SHOW SESSION VARIABLES` 命令类似的功能。 | -| [`STATISTICS`](/information-schema/information-schema-statistics.md) | 提供有关表索引的信息。 | -| [`TABLES`](/information-schema/information-schema-tables.md) | 提供当前用户可见的表的列表。 类似于 `SHOW TABLES`。 | -| `TABLESPACES` | TiDB 未实现,返回零行。 | -| [`TABLE_CONSTRAINTS`](/information-schema/information-schema-table-constraints.md) | 提供有关主键、唯一索引和外键的信息。 | -| `TABLE_PRIVILEGES` | TiDB 未实现,返回零行。 | -| `TRIGGERS` | TiDB 未实现,返回零行。 | -| [`USER_ATTRIBUTES`](/information-schema/information-schema-user-attributes.md) | 汇总用户的注释和属性信息。 | -| [`USER_PRIVILEGES`](/information-schema/information-schema-user-privileges.md) | 汇总与当前用户相关的权限。 | -| [`VARIABLES_INFO`](/information-schema/information-schema-variables-info.md) | 提供 TiDB 系统变量的信息。 | -| [`VIEWS`](/information-schema/information-schema-views.md) | 提供当前用户可见的视图列表。类似于 `SHOW FULL TABLES WHERE table_type = 'VIEW'`。 | - -## TiDB 中的扩展表 - -| 表名 | 描述 | -| --------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -| [`ANALYZE_STATUS`](/information-schema/information-schema-analyze-status.md) | 提供有关收集统计信息的任务的信息。 | -| [`CLIENT_ERRORS_SUMMARY_BY_HOST`](/information-schema/client-errors-summary-by-host.md) | 汇总由客户端请求生成并返回给客户端的错误和警告。 | -| [`CLIENT_ERRORS_SUMMARY_BY_USER`](/information-schema/client-errors-summary-by-user.md) | 汇总由客户端产生的错误和警告。 | -| [`CLIENT_ERRORS_SUMMARY_GLOBAL`](/information-schema/client-errors-summary-global.md) | 汇总由客户端产生的错误和警告。 | -| [`CLUSTER_CONFIG`](/information-schema/information-schema-cluster-config.md) | 提供有关整个 TiDB 集群的配置设置的详细信息。 | -| `CLUSTER_DEADLOCKS` | 提供 `DEADLOCKS` 表的集群级别的视图。 | -| [`CLUSTER_HARDWARE`](/information-schema/information-schema-cluster-hardware.md) | 提供在每个 TiDB 组件上发现的底层物理硬件的详细信息。 | -| [`CLUSTER_INFO`](/information-schema/information-schema-cluster-info.md) | 提供当前集群拓扑的详细信息。 | -| [`CLUSTER_LOAD`](/information-schema/information-schema-cluster-load.md) | 提供集群中 TiDB 服务器的当前负载信息。 | -| [`CLUSTER_LOG`](/information-schema/information-schema-cluster-log.md) | 提供整个 TiDB 集群的日志。 | -| `CLUSTER_MEMORY_USAGE` | 提供 `MEMORY_USAGE` 表的集群级别的视图。 | -| `CLUSTER_MEMORY_USAGE_OPS_HISTORY` | 提供 `MEMORY_USAGE_OPS_HISTORY` 表的集群级别的视图。 | -| `CLUSTER_PROCESSLIST` | 提供 `PROCESSLIST` 表的集群级别的视图。 | -| `CLUSTER_SLOW_QUERY` | 提供 `SLOW_QUERY` 表的集群级别的视图。 | -| `CLUSTER_STATEMENTS_SUMMARY` | 提供 `STATEMENTS_SUMMARY` 表的集群级别的视图。 | -| `CLUSTER_STATEMENTS_SUMMARY_HISTORY` | 提供 `STATEMENTS_SUMMARY_HISTORY` 表的集群级别的视图。 | -| `CLUSTER_TIDB_INDEX_USAGE` | 提供 `TIDB_INDEX_USAGE` 表的集群级别的视图。 | -| `CLUSTER_TIDB_TRX` | 提供 `TIDB_TRX` 表的集群级别的视图。 | -| [`CLUSTER_SYSTEMINFO`](/information-schema/information-schema-cluster-systeminfo.md) | 提供集群中服务器的内核参数配置的详细信息。 | -| [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md) | 提供 TiKV 服务器上的等锁信息。 | -| [`DDL_JOBS`](/information-schema/information-schema-ddl-jobs.md) | 提供与 `ADMIN SHOW DDL JOBS` 类似的输出。 | -| [`DEADLOCKS`](/information-schema/information-schema-deadlocks.md) | 提供 TiDB 节点上最近发生的数次死锁错误的信息。 | -| [`INSPECTION_RESULT`](/information-schema/information-schema-inspection-result.md) | 触发内部诊断检查。 | -| [`INSPECTION_RULES`](/information-schema/information-schema-inspection-rules.md) | 进行的内部诊断检查的列表。 | -| [`INSPECTION_SUMMARY`](/information-schema/information-schema-inspection-summary.md) | 重要监视指标的摘要报告。 | -| [`MEMORY_USAGE`](/information-schema/information-schema-memory-usage.md) | 提供当前 TiDB 实例的内存使用情况。 | -| [`MEMORY_USAGE_OPS_HISTORY`](/information-schema/information-schema-memory-usage-ops-history.md) | 提供当前 TiDB 实例内存相关的历史操作和执行依据。 | -| [`METRICS_SUMMARY`](/information-schema/information-schema-metrics-summary.md) | 从 Prometheus 获取的指标的摘要。 | -| `METRICS_SUMMARY_BY_LABEL` | 参见 `METRICS_SUMMARY` 表。 | -| [`METRICS_TABLES`](/information-schema/information-schema-metrics-tables.md) | 为 `METRICS_SCHEMA` 中的表提供 PromQL 定义。 | -| [`PLACEMENT_POLICIES`](/information-schema/information-schema-placement-policies.md) | 提供所有放置策略的定义信息。 | -| [`SEQUENCES`](/information-schema/information-schema-sequences.md) | 描述了基于 MariaDB 实现的 TiDB 序列。 | -| [`SLOW_QUERY`](/information-schema/information-schema-slow-query.md) | 提供当前 TiDB 服务器上慢查询的信息。 | -| [`STATEMENTS_SUMMARY`](/statement-summary-tables.md) | 类似于 MySQL 中的 performance_schema 语句摘要。 | -| [`STATEMENTS_SUMMARY_HISTORY`](/statement-summary-tables.md) | 类似于 MySQL 中的 performance_schema 语句摘要历史。 | -| [`TABLE_STORAGE_STATS`](/information-schema/information-schema-table-storage-stats.md) | 提供存储的表的大小的详细信息。 | -| [`TIDB_HOT_REGIONS`](/information-schema/information-schema-tidb-hot-regions.md) | 提供有关哪些 Region 访问次数最多的统计信息。 | -| [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md)| 提供有关哪些 Region 访问次数最多的历史统计信息。 | -| [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) | 提供有关 TiDB 表的索引信息。 | -| [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) | 提供 TiDB 节点上有关访问索引的统计信息。 | -| [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) | 提供 TiDB 服务器的列表 | -| [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) | 提供 TiDB 节点上正在执行的事务的信息。 | -| [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) | 提供有关 TiFlash 副本的详细信息。 | -| [`TIKV_REGION_PEERS`](/information-schema/information-schema-tikv-region-peers.md) | 提供 Region 存储位置的详细信息。 | -| [`TIKV_REGION_STATUS`](/information-schema/information-schema-tikv-region-status.md) | 提供 Region 的统计信息。 | -| [`TIKV_STORE_STATUS`](/information-schema/information-schema-tikv-store-status.md) | 提供 TiKV 服务器的基本信息。 | +Information Schema 提供了一种 ANSI 标准的方式来查看系统元数据。除了为了与 MySQL 兼容而包含的表之外,TiDB 还提供了一些自定义的 `INFORMATION_SCHEMA` 表。 + +许多 `INFORMATION_SCHEMA` 表都有相应的 `SHOW` 语句。查询 `INFORMATION_SCHEMA` 的好处是可以进行表之间的连接。 + +## MySQL 兼容性表 + + + +| 表名 | 描述 | +|-----------------------------------------------------------------------------------------|------------------------------------| +| [`CHARACTER_SETS`](/information-schema/information-schema-character-sets.md) | 提供服务器支持的字符集列表。 | +| [`CHECK_CONSTRAINTS`](/information-schema/information-schema-check-constraints.md) | 提供关于表的 [`CHECK` 约束](/constraints.md#check) 的信息。 | +| [`COLLATIONS`](/information-schema/information-schema-collations.md) | 提供服务器支持的排序规则列表。 | +| [`COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) | 解释哪些排序规则适用于哪些字符集。 | +| [`COLUMNS`](/information-schema/information-schema-columns.md) | 提供所有表的列的列表。 | +| `COLUMN_PRIVILEGES` | TiDB 未实现。返回零行。 | +| `COLUMN_STATISTICS` | TiDB 未实现。返回零行。 | +| [`ENGINES`](/information-schema/information-schema-engines.md) | 提供支持的存储引擎列表。 | +| `EVENTS` | TiDB 未实现。返回零行。 | +| `FILES` | TiDB 未实现。返回零行。 | +| `GLOBAL_STATUS` | TiDB 未实现。返回零行。 | +| `GLOBAL_VARIABLES` | TiDB 未实现。返回零行。 | +| [`KEYWORDS`](/information-schema/information-schema-keywords.md) | 提供完整的关键字列表。 | +| [`KEY_COLUMN_USAGE`](/information-schema/information-schema-key-column-usage.md) | 描述列的键约束,例如主键约束。 | +| `OPTIMIZER_TRACE` | TiDB 未实现。返回零行。 | +| `PARAMETERS` | TiDB 未实现。返回零行。 | +| [`PARTITIONS`](/information-schema/information-schema-partitions.md) | 提供表分区的列表。 | +| `PLUGINS` | TiDB 未实现。返回零行。 | +| [`PROCESSLIST`](/information-schema/information-schema-processlist.md) | 提供与命令 `SHOW PROCESSLIST` 类似的信息。 | +| `PROFILING` | TiDB 未实现。返回零行。 | +| `REFERENTIAL_CONSTRAINTS` | 提供关于 `FOREIGN KEY` 约束的信息。 | +| `ROUTINES` | TiDB 未实现。返回零行。 | +| [`SCHEMATA`](/information-schema/information-schema-schemata.md) | 提供与 `SHOW DATABASES` 类似的信息。 | +| `SCHEMA_PRIVILEGES` | TiDB 未实现。返回零行。 | +| `SESSION_STATUS` | TiDB 未实现。返回零行。 | +| [`SESSION_VARIABLES`](/information-schema/information-schema-session-variables.md) | 提供与命令 `SHOW SESSION VARIABLES` 类似的功能。 | +| [`STATISTICS`](/information-schema/information-schema-statistics.md) | 提供关于表索引的信息。 | +| [`TABLES`](/information-schema/information-schema-tables.md) | 提供当前用户可见的表列表。类似于 `SHOW TABLES`。 | +| `TABLESPACES` | TiDB 未实现。返回零行。 | +| [`TABLE_CONSTRAINTS`](/information-schema/information-schema-table-constraints.md) | 提供关于主键、唯一索引和外键的信息。 | +| `TABLE_PRIVILEGES` | TiDB 未实现。返回零行。 | +| `TRIGGERS` | TiDB 未实现。返回零行。 | +| [`USER_ATTRIBUTES`](/information-schema/information-schema-user-attributes.md) | 总结有关用户评论和用户属性的信息。 | +| [`USER_PRIVILEGES`](/information-schema/information-schema-user-privileges.md) | 总结与当前用户关联的权限。 | +| [`VARIABLES_INFO`](/information-schema/information-schema-variables-info.md) | 提供关于 TiDB 系统变量的信息。 | +| [`VIEWS`](/information-schema/information-schema-views.md) | 提供当前用户可见的视图列表。类似于运行 `SHOW FULL TABLES WHERE table_type = 'VIEW'` | + + + + + +| 表名 | 描述 | +|-----------------------------------------------------------------------------------------|------------------------------------| +| [`CHARACTER_SETS`](/information-schema/information-schema-character-sets.md) | 提供服务器支持的字符集列表。 | +| [`CHECK_CONSTRAINTS`](/information-schema/information-schema-check-constraints.md) | 提供关于表的 [`CHECK` 约束](/constraints.md#check) 的信息。 | +| [`COLLATIONS`](/information-schema/information-schema-collations.md) | 提供服务器支持的排序规则列表。 | +| [`COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) | 解释哪些排序规则适用于哪些字符集。 | +| [`COLUMNS`](/information-schema/information-schema-columns.md) | 提供所有表的列的列表。 | +| `COLUMN_PRIVILEGES` | TiDB 未实现。返回零行。 | +| `COLUMN_STATISTICS` | TiDB 未实现。返回零行。 | +| [`ENGINES`](/information-schema/information-schema-engines.md) | 提供支持的存储引擎列表。 | +| `EVENTS` | TiDB 未实现。返回零行。 | +| `FILES` | TiDB 未实现。返回零行。 | +| `GLOBAL_STATUS` | TiDB 未实现。返回零行。 | +| `GLOBAL_VARIABLES` | TiDB 未实现。返回零行。 | +| [`KEY_COLUMN_USAGE`](/information-schema/information-schema-key-column-usage.md) | 描述列的键约束,例如主键约束。 | +| `OPTIMIZER_TRACE` | TiDB 未实现。返回零行。 | +| `PARAMETERS` | TiDB 未实现。返回零行。 | +| [`PARTITIONS`](/information-schema/information-schema-partitions.md) | 提供表分区的列表。 | +| `PLUGINS` | TiDB 未实现。返回零行。 | +| [`PROCESSLIST`](/information-schema/information-schema-processlist.md) | 提供与命令 `SHOW PROCESSLIST` 类似的信息。 | +| `PROFILING` | TiDB 未实现。返回零行。 | +| `REFERENTIAL_CONSTRAINTS` | 提供关于 `FOREIGN KEY` 约束的信息。 | +| `ROUTINES` | TiDB 未实现。返回零行。 | +| [`SCHEMATA`](/information-schema/information-schema-schemata.md) | 提供与 `SHOW DATABASES` 类似的信息。 | +| `SCHEMA_PRIVILEGES` | TiDB 未实现。返回零行。 | +| `SESSION_STATUS` | TiDB 未实现。返回零行。 | +| [`SESSION_VARIABLES`](/information-schema/information-schema-session-variables.md) | 提供与命令 `SHOW SESSION VARIABLES` 类似的功能。 | +| [`STATISTICS`](/information-schema/information-schema-statistics.md) | 提供关于表索引的信息。 | +| [`TABLES`](/information-schema/information-schema-tables.md) | 提供当前用户可见的表列表。类似于 `SHOW TABLES`。 | +| `TABLESPACES` | TiDB 未实现。返回零行。 | +| [`TABLE_CONSTRAINTS`](/information-schema/information-schema-table-constraints.md) | 提供关于主键、唯一索引和外键的信息。 | +| `TABLE_PRIVILEGES` | TiDB 未实现。返回零行。 | +| `TRIGGERS` | TiDB 未实现。返回零行。 | +| [`USER_ATTRIBUTES`](/information-schema/information-schema-user-attributes.md) | 总结有关用户评论和用户属性的信息。 | +| [`USER_PRIVILEGES`](/information-schema/information-schema-user-privileges.md) | 总结与当前用户关联的权限。 | +| [`VARIABLES_INFO`](/information-schema/information-schema-variables-info.md) | 提供关于 TiDB 系统变量的信息。 | +| [`VIEWS`](/information-schema/information-schema-views.md) | 提供当前用户可见的视图列表。类似于运行 `SHOW FULL TABLES WHERE table_type = 'VIEW'` | + + + + +## 属于 TiDB 扩展的表 + + + +> **注意:** +> +> 以下某些表仅在 TiDB Self-Managed 上受支持,在 TiDB Cloud 上不受支持。要获取 TiDB Cloud 上不支持的表的完整列表,请参阅[系统表](https://docs.pingcap.com/tidbcloud/limited-sql-features#system-tables)。 + +| 表名 | 描述 | +|-----------------------------------------------------------------------------------------|-------------| +| [`ANALYZE_STATUS`](/information-schema/information-schema-analyze-status.md) | 提供有关收集统计信息的任务的信息。 | +| [`CLIENT_ERRORS_SUMMARY_BY_HOST`](/information-schema/client-errors-summary-by-host.md) | 提供客户端请求生成并返回给客户端的错误和警告的摘要。 | +| [`CLIENT_ERRORS_SUMMARY_BY_USER`](/information-schema/client-errors-summary-by-user.md) | 提供客户端生成的错误和警告的摘要。 | +| [`CLIENT_ERRORS_SUMMARY_GLOBAL`](/information-schema/client-errors-summary-global.md) | 提供客户端生成的错误和警告的摘要。 | +| [`CLUSTER_CONFIG`](/information-schema/information-schema-cluster-config.md) | 提供有关整个 TiDB 集群的配置设置的详细信息。此表不适用于 TiDB Cloud。 | +| `CLUSTER_DEADLOCKS` | 提供 `DEADLOCKS` 表的集群级别视图。 | +| [`CLUSTER_HARDWARE`](/information-schema/information-schema-cluster-hardware.md) | 提供有关在每个 TiDB 组件上发现的底层物理硬件的详细信息。此表不适用于 TiDB Cloud。 | +| [`CLUSTER_INFO`](/information-schema/information-schema-cluster-info.md) | 提供有关当前集群拓扑的详细信息。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`CLUSTER_LOAD`](/information-schema/information-schema-cluster-load.md) | 提供集群中 TiDB 服务器的当前负载信息。此表不适用于 TiDB Cloud。 | +| [`CLUSTER_LOG`](/information-schema/information-schema-cluster-log.md) | 提供整个 TiDB 集群的日志。此表不适用于 TiDB Cloud。 | +| `CLUSTER_MEMORY_USAGE` | 提供 `MEMORY_USAGE` 表的集群级别视图。 | +| `CLUSTER_MEMORY_USAGE_OPS_HISTORY` | 提供 `MEMORY_USAGE_OPS_HISTORY` 表的集群级别视图。 | +| `CLUSTER_PROCESSLIST` | 提供 `PROCESSLIST` 表的集群级别视图。 | +| `CLUSTER_SLOW_QUERY` | 提供 `SLOW_QUERY` 表的集群级别视图。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| `CLUSTER_STATEMENTS_SUMMARY` | 提供 `STATEMENTS_SUMMARY` 表的集群级别视图。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| `CLUSTER_STATEMENTS_SUMMARY_HISTORY` | 提供 `STATEMENTS_SUMMARY_HISTORY` 表的集群级别视图。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| `CLUSTER_TIDB_INDEX_USAGE` | 提供 `TIDB_INDEX_USAGE` 表的集群级别视图。 | +| `CLUSTER_TIDB_TRX` | 提供 `TIDB_TRX` 表的集群级别视图。 | +| [`CLUSTER_SYSTEMINFO`](/information-schema/information-schema-cluster-systeminfo.md) | 提供有关集群中服务器的内核参数配置的详细信息。此表不适用于 TiDB Cloud。 | +| [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md) | 提供 TiKV 服务器上的锁等待信息。 | +| [`DDL_JOBS`](/information-schema/information-schema-ddl-jobs.md) | 提供与 `ADMIN SHOW DDL JOBS` 类似的输出 | +| [`DEADLOCKS`](/information-schema/information-schema-deadlocks.md) | 提供最近发生的几个死锁错误的信息。 | +| [`INSPECTION_RESULT`](/information-schema/information-schema-inspection-result.md) | 触发内部诊断检查。此表不适用于 TiDB Cloud。 | +| [`INSPECTION_RULES`](/information-schema/information-schema-inspection-rules.md) | 执行的内部诊断检查的列表。此表不适用于 TiDB Cloud。 | +| [`INSPECTION_SUMMARY`](/information-schema/information-schema-inspection-summary.md) | 重要监控指标的汇总报告。此表不适用于 TiDB Cloud。 | +| [`MEMORY_USAGE`](/information-schema/information-schema-memory-usage.md) | 当前 TiDB 实例的内存使用情况。 | +| [`MEMORY_USAGE_OPS_HISTORY`](/information-schema/information-schema-memory-usage-ops-history.md) | 当前 TiDB 实例的内存相关操作的历史记录和执行依据。 | +| [`METRICS_SUMMARY`](/information-schema/information-schema-metrics-summary.md) | 从 Prometheus 提取的指标的摘要。此表不适用于 TiDB Cloud。 | +| `METRICS_SUMMARY_BY_LABEL` | 请参阅 `METRICS_SUMMARY` 表。此表不适用于 TiDB Cloud。 | +| [`METRICS_TABLES`](/information-schema/information-schema-metrics-tables.md) | 提供 `METRICS_SCHEMA` 中表的 PromQL 定义。此表不适用于 TiDB Cloud。 | +| [`PLACEMENT_POLICIES`](/information-schema/information-schema-placement-policies.md) | 提供有关所有放置策略的信息。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`SEQUENCES`](/information-schema/information-schema-sequences.md) | TiDB 的序列实现基于 MariaDB。 | +| [`SLOW_QUERY`](/information-schema/information-schema-slow-query.md) | 提供有关当前 TiDB 服务器上的慢查询的信息。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`STATEMENTS_SUMMARY`](/statement-summary-tables.md) | 类似于 MySQL 中的 performance_schema statement summary。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`STATEMENTS_SUMMARY_HISTORY`](/statement-summary-tables.md) | 类似于 MySQL 中的 performance_schema statement summary history。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`TABLE_STORAGE_STATS`](/information-schema/information-schema-table-storage-stats.md) | 提供有关存储中表大小的详细信息。 | +| [`TIDB_HOT_REGIONS`](/information-schema/information-schema-tidb-hot-regions.md) | 提供有关哪些区域是热点区域的统计信息。 | +| [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md) | 提供有关哪些区域是热点区域的历史统计信息。 | +| [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) | 提供有关 TiDB 表的索引信息。 | +| [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) | 提供 TiDB 节点上索引使用情况统计信息。 | +| [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) | 提供 TiDB 服务器(即 tidb-server 组件)的列表 | +| [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) | 提供有关在 TiDB 节点上执行的事务的信息。 | +| [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) | 提供有关 TiFlash 副本的详细信息。 | +| [`TIKV_REGION_PEERS`](/information-schema/information-schema-tikv-region-peers.md) | 提供有关区域存储位置的详细信息。 | +| [`TIKV_REGION_STATUS`](/information-schema/information-schema-tikv-region-status.md) | 提供有关区域的统计信息。 | +| [`TIKV_STORE_STATUS`](/information-schema/information-schema-tikv-store-status.md) | 提供有关 TiKV 服务器的基本信息。 | + + + + + +| 表名 | 描述 | +|-----------------------------------------------------------------------------------------|-------------| +| [`ANALYZE_STATUS`](/information-schema/information-schema-analyze-status.md) | 提供有关收集统计信息的任务的信息。 | +| [`CLIENT_ERRORS_SUMMARY_BY_HOST`](/information-schema/client-errors-summary-by-host.md) | 提供客户端请求生成并返回给客户端的错误和警告的摘要。 | +| [`CLIENT_ERRORS_SUMMARY_BY_USER`](/information-schema/client-errors-summary-by-user.md) | 提供客户端生成的错误和警告的摘要。 | +| [`CLIENT_ERRORS_SUMMARY_GLOBAL`](/information-schema/client-errors-summary-global.md) | 提供客户端生成的错误和警告的摘要。 | +| [`CLUSTER_CONFIG`](https://docs.pingcap.com/tidb/stable/information-schema-cluster-config) | 提供有关整个 TiDB 集群的配置设置的详细信息。此表不适用于 TiDB Cloud。 | +| `CLUSTER_DEADLOCKS` | 提供 `DEADLOCKS` 表的集群级别视图。 | +| [`CLUSTER_HARDWARE`](https://docs.pingcap.com/tidb/stable/information-schema-cluster-hardware) | 提供有关在每个 TiDB 组件上发现的底层物理硬件的详细信息。此表不适用于 TiDB Cloud。 | +| [`CLUSTER_INFO`](/information-schema/information-schema-cluster-info.md) | 提供有关当前集群拓扑的详细信息。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`CLUSTER_LOAD`](https://docs.pingcap.com/tidb/stable/information-schema-cluster-load) | 提供集群中 TiDB 服务器的当前负载信息。此表不适用于 TiDB Cloud。 | +| [`CLUSTER_LOG`](https://docs.pingcap.com/tidb/stable/information-schema-cluster-log) | 提供整个 TiDB 集群的日志。此表不适用于 TiDB Cloud。 | +| `CLUSTER_MEMORY_USAGE` | 提供 `MEMORY_USAGE` 表的集群级别视图。此表不适用于 TiDB Cloud。 | +| `CLUSTER_MEMORY_USAGE_OPS_HISTORY` | 提供 `MEMORY_USAGE_OPS_HISTORY` 表的集群级别视图。此表不适用于 TiDB Cloud。 | +| `CLUSTER_PROCESSLIST` | 提供 `PROCESSLIST` 表的集群级别视图。 | +| `CLUSTER_SLOW_QUERY` | 提供 `SLOW_QUERY` 表的集群级别视图。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| `CLUSTER_STATEMENTS_SUMMARY` | 提供 `STATEMENTS_SUMMARY` 表的集群级别视图。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| `CLUSTER_STATEMENTS_SUMMARY_HISTORY` | 提供 `STATEMENTS_SUMMARY_HISTORY` 表的集群级别视图。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| `CLUSTER_TIDB_TRX` | 提供 `TIDB_TRX` 表的集群级别视图。 | +| [`CLUSTER_SYSTEMINFO`](https://docs.pingcap.com/tidb/stable/information-schema-cluster-systeminfo) | 提供有关集群中服务器的内核参数配置的详细信息。此表不适用于 TiDB Cloud。 | +| [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md) | 提供 TiKV 服务器上的锁等待信息。 | +| [`DDL_JOBS`](/information-schema/information-schema-ddl-jobs.md) | 提供与 `ADMIN SHOW DDL JOBS` 类似的输出 | +| [`DEADLOCKS`](/information-schema/information-schema-deadlocks.md) | 提供最近发生的几个死锁错误的信息。 | +| [`INSPECTION_RESULT`](https://docs.pingcap.com/tidb/stable/information-schema-inspection-result) | 触发内部诊断检查。此表不适用于 TiDB Cloud。 | +| [`INSPECTION_RULES`](https://docs.pingcap.com/tidb/stable/information-schema-inspection-rules) | 执行的内部诊断检查的列表。此表不适用于 TiDB Cloud。 | +| [`INSPECTION_SUMMARY`](https://docs.pingcap.com/tidb/stable/information-schema-inspection-summary) | 重要监控指标的汇总报告。此表不适用于 TiDB Cloud。 | +| [`MEMORY_USAGE`](/information-schema/information-schema-memory-usage.md) | 当前 TiDB 实例的内存使用情况。 | +| [`MEMORY_USAGE_OPS_HISTORY`](/information-schema/information-schema-memory-usage-ops-history.md) | 当前 TiDB 实例的内存相关操作的历史记录和执行依据。 | +| [`METRICS_SUMMARY`](https://docs.pingcap.com/tidb/stable/information-schema-metrics-summary) | 从 Prometheus 提取的指标的摘要。此表不适用于 TiDB Cloud。 | +| `METRICS_SUMMARY_BY_LABEL` | 请参阅 `METRICS_SUMMARY` 表。此表不适用于 TiDB Cloud。 | +| [`METRICS_TABLES`](https://docs.pingcap.com/tidb/stable/information-schema-metrics-tables) | 提供 `METRICS_SCHEMA` 中表的 PromQL 定义。此表不适用于 TiDB Cloud。 | +| [`PLACEMENT_POLICIES`](https://docs.pingcap.com/tidb/stable/information-schema-placement-policies) | 提供有关所有放置策略的信息。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`SEQUENCES`](/information-schema/information-schema-sequences.md) | TiDB 的序列实现基于 MariaDB。 | +| [`SLOW_QUERY`](/information-schema/information-schema-slow-query.md) | 提供有关当前 TiDB 服务器上慢查询的信息。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`STATEMENTS_SUMMARY`](/statement-summary-tables.md) | 类似于 MySQL 中的 performance_schema statement summary。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 | +| [`STATEMENTS_SUMMARY_HISTORY`](/statement-summary-tables.md) | 类似于 MySQL 中的 performance_schema statement summary history。此表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。| +| [`TABLE_STORAGE_STATS`](/information-schema/information-schema-table-storage-stats.md) | 提供有关存储中表大小的详细信息。 | +| [`TIDB_HOT_REGIONS`](https://docs.pingcap.com/tidb/stable/information-schema-tidb-hot-regions) | 提供有关哪些区域是热点区域的统计信息。此表不适用于 TiDB Cloud。 | +| [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md) | 提供有关哪些区域是热点区域的历史统计信息。 | +| [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) | 提供有关 TiDB 表的索引信息。 | +| [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) | 提供有关 TiDB 节点上索引使用情况统计的信息。 | +| [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) | 提供 TiDB 服务器(即 tidb-server 组件)的列表 | +| [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) | 提供有关在 TiDB 节点上执行的事务的信息。 | +| [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) | 提供有关 TiFlash 副本的详细信息。 | +| [`TIKV_REGION_PEERS`](/information-schema/information-schema-tikv-region-peers.md) | 提供有关区域存储位置的详细信息。 | +| [`TIKV_REGION_STATUS`](/information-schema/information-schema-tikv-region-status.md) | 提供有关区域的统计信息。 | +| [`TIKV_STORE_STATUS`](/information-schema/information-schema-tikv-store-status.md) | 提供有关 TiKV 服务器的基本信息。 | + + \ No newline at end of file diff --git a/join-reorder.md b/join-reorder.md index 1174f8b4754a..ac5e1ce9d40d 100644 --- a/join-reorder.md +++ b/join-reorder.md @@ -1,51 +1,70 @@ --- -title: Join Reorder 算法简介 -summary: Join Reorder 算法决定了多表 Join 的顺序,影响执行效率。TiDB 中有贪心算法和动态规划算法两种实现。贪心算法选择行数最小的表与其他表做 Join,直到所有节点完成 Join。动态规划算法枚举所有可能的 Join 顺序,选择最优的。算法受系统变量控制,且存在一些限制,如无法保证一定选到合适的 Join 顺序。 +title: Join Reorder 简介 +summary: 在 TiDB 中使用 Join Reorder 算法进行多表连接。 --- -# Join Reorder 算法简介 +# Join Reorder 简介 -在实际的业务场景中,多个表的 Join 语句是很常见的,而 Join 的执行效率和各个表参与 Join 的顺序有关系。如 `select * from t1, t2, t3 where t1.a=t2.a and t3.a=t2.a`,这个 SQL 中可能的执行顺序有“t1 和 t2 先做 Join,然后再和 t3 做 Join”以及“t2 和 t3 先做 Join,然后再和 t1 做 Join”两种情况。根据 `t1` 和 `t3` 的数据量及数据分布,这两种执行顺序会有不同的性能表现。 +在实际应用场景中,多表连接是很常见的。连接的执行效率与各个表的连接顺序有关。 -因此优化器需要实现一种决定 Join 顺序的算法。目前 TiDB 中存在两种 Join Reorder 算法,贪心算法和动态规划算法。 +例如: -- Join Reorder 贪心算法:在所有参与 Join 的节点中,选择行数最小的表与其他各表分别做一次 Join 的结果估算,然后选择其中结果最小的一对进行 Join,再继续这个过程进入下一轮的选择和 Join,直到所有的节点都完成 Join。 -- Join Reorder 动态规划算法:在所有参与 Join 的节点中,枚举所有可能的 Join 顺序,然后选择最优的 Join 顺序。 +{{< copyable "sql" >}} -## Join Reorder 贪心算法实例 +```sql +SELECT * FROM t1, t2, t3 WHERE t1.a=t2.a AND t3.a=t2.a; +``` -以三个表 t1、t2、t3 的 Join 为例。首先获取所有参与 Join 的节点,将所有节点按照行数多少,从少到多进行排序。 +在这个查询中,表可以按以下两种顺序进行连接: + +- t1 与 t2 连接,然后与 t3 连接 +- t2 与 t3 连接,然后与 t1 连接 + +由于 t1 和 t3 具有不同的数据量和分布,这两种执行顺序可能会表现出不同的性能。 + +因此,优化器需要一个算法来确定连接顺序。目前,TiDB 中使用以下两种 Join Reorder 算法: + +- 贪心算法:在所有参与连接的节点中,TiDB 选择行数最少的表,估算它与其他每个表的连接结果,然后选择连接结果最小的一对。之后,TiDB 继续类似的过程,为下一轮选择和连接其他节点,直到所有节点都完成连接。 +- 动态规划算法:在所有参与连接的节点中,TiDB 枚举所有可能的连接顺序,并选择最优的连接顺序。 + +## 示例:Join Reorder 的贪心算法 + +以前面的三个表(t1、t2 和 t3)为例。 + +首先,TiDB 获取所有参与连接操作的节点,并按行数升序排序。 ![join-reorder-1](/media/join-reorder-1.png) -之后选定其中最小的表,将其与其他两个表分别做一次 Join,观察输出的结果集大小,选择其中结果更小的一对。 +之后,选择行数最少的表,分别与其他两个表进行连接。通过比较输出结果集的大小,TiDB 选择结果集较小的一对。 ![join-reorder-2](/media/join-reorder-2.png) -然后进入下一轮的选择,如果这时是四个表,那么就继续比较输出结果集的大小,进行选择。这里只有三个表,因此就直接得到了最终的 Join 结果。 +然后 TiDB 进入下一轮选择。如果你尝试连接四个表,TiDB 会继续比较输出结果集的大小,并选择结果集较小的一对。 + +在这个例子中只连接了三个表,所以 TiDB 得到最终的连接结果。 ![join-reorder-3](/media/join-reorder-3.png) -## Join Reorder 动态规划算法实例 +## 示例:Join Reorder 的动态规划算法 -仍然以上述例子为例。动态规划算法会枚举所有的可能性,因此相对贪心算法必须从 `t1` 表开始枚举,动态规划算法可以枚举如下的 Join 顺序。 +再次以前面的三个表(t1、t2 和 t3)为例,动态规划算法可以枚举所有可能性。因此,与必须从 `t1` 表(行数最少的表)开始的贪心算法相比,动态规划算法可以枚举如下的连接顺序: ![join-reorder-4](/media/join-reorder-4.png) -当该选择比贪心算法更优时,动态规划算法便可以选择到更优的 Join 顺序。 +当这个选择比贪心算法更好时,动态规划算法可以选择更好的连接顺序。 -相应地,因为会枚举所有的可能性,动态规划算法会消耗更多的时间,也会更容易受统计信息影响。 +由于枚举了所有可能性,动态规划算法消耗更多时间,并且更容易受统计信息的影响。 -## Join Reorder 算法的控制 +## Join Reorder 算法的选择 -目前 Join Reorder 算法由变量 [`tidb_opt_join_reorder_threshold`](/system-variables.md#tidb_opt_join_reorder_threshold) 控制,当参与 Join Reorder 的节点个数大于该阈值时选择贪心算法,反之选择动态规划算法。 +TiDB Join Reorder 算法的选择由 [`tidb_opt_join_reorder_threshold`](/system-variables.md#tidb_opt_join_reorder_threshold) 变量控制。如果参与 Join Reorder 的节点数量大于此阈值,TiDB 使用贪心算法。否则,TiDB 使用动态规划算法。 -## Join Reorder 算法限制 +## Join Reorder 算法的限制 -当前的 Join Reorder 算法存在如下限制: +当前的 Join Reorder 算法有以下限制: -- 受结果集的计算算法所限并不会保证一定会选到合适的 Join order -- 是否启用 Outer Join 的 Join Reorder 功能由系统变量 [`tidb_enable_outer_join_reorder`](/system-variables.md#tidb_enable_outer_join_reorder-从-v610-版本开始引入) 控制。 -- 目前动态规划算法无法进行 Outer Join 的 Join Reorder。 +- 受限于结果集的计算方法,该算法不能保证选择最优的连接顺序。 +- Join Reorder 算法对外连接(Outer Join)的支持由 [`tidb_enable_outer_join_reorder`](/system-variables.md#tidb_enable_outer_join_reorder-new-in-v610) 系统变量控制。 +- 目前,动态规划算法不能对外连接执行 Join Reorder。 -目前 TiDB 中支持使用 `STRAIGHT_JOIN` 语法来强制指定一种 Join 顺序,参见[语法元素说明](/sql-statements/sql-statement-select.md#语法元素说明)。 +目前,TiDB 支持使用 `STRAIGHT_JOIN` 语法来强制指定连接顺序。更多信息,请参考[语法元素说明](/sql-statements/sql-statement-select.md#description-of-the-syntax-elements)。 diff --git a/keywords.md b/keywords.md index 7fb30a290b06..9449c4d03a0a 100644 --- a/keywords.md +++ b/keywords.md @@ -1,15 +1,15 @@ --- title: 关键字 -summary: 本文介绍 TiDB 的关键字。 +summary: 关键字和保留字 --- # 关键字 -本文介绍 TiDB 的关键字,对保留字和非保留字作出区分,并汇总所有的关键字以供查询使用。 +本文介绍 TiDB 中的关键字、保留字和非保留字之间的区别,并总结了所有可查询的关键字。 -关键字是 SQL 语句中具有特殊含义的单词,例如 [`SELECT`](/sql-statements/sql-statement-select.md)、[`UPDATE`](/sql-statements/sql-statement-update.md) 和 [`DELETE`](/sql-statements/sql-statement-delete.md) 等等。它们之中有的能够直接作为标识符,被称为**非保留关键字**(简称**非保留字**),但有需要经过特殊处理才能作为标识符的字,被称为**保留关键字**(简称**保留字**)。 +关键字是在 SQL 语句中具有特殊含义的词,例如 [`SELECT`](/sql-statements/sql-statement-select.md)、[`UPDATE`](/sql-statements/sql-statement-update.md) 和 [`DELETE`](/sql-statements/sql-statement-delete.md)。其中一些可以直接用作标识符,这些被称为**非保留关键字**。另一些在用作标识符之前需要特殊处理,这些被称为**保留关键字**。 -对于保留字,必须使用反引号包裹,才能作为标识符被使用。例如: +要将保留关键字用作标识符,你必须将它们用反引号 `` ` `` 括起来: ```sql CREATE TABLE select (a INT); @@ -27,7 +27,7 @@ CREATE TABLE `select` (a INT); Query OK, 0 rows affected (0.09 sec) ``` -而非保留字则不需要反引号也能直接作为标识符。例如 `BEGIN` 和 `END` 是非保留字,以下语句能够正常执行: +非保留关键字不需要反引号,例如 `BEGIN` 和 `END`,可以在以下语句中成功用作标识符: ```sql CREATE TABLE `select` (BEGIN int, END int); @@ -37,7 +37,7 @@ CREATE TABLE `select` (BEGIN int, END int); Query OK, 0 rows affected (0.09 sec) ``` -有一种特殊情况,如果使用了限定符 `.`,那么也不需要用反引号: +在特殊情况下,如果保留关键字与 `.` 分隔符一起使用,则不需要反引号: ```sql CREATE TABLE test.select (BEGIN int, END int); @@ -47,11 +47,11 @@ CREATE TABLE test.select (BEGIN int, END int); Query OK, 0 rows affected (0.08 sec) ``` -TiDB 从 v7.5.3 和 v7.6.0 开始提供 [`INFORMATION_SCHEMA.KEYWORDS`](/information-schema/information-schema-keywords.md) 表,可以用于查询 TiDB 中所有的关键字。 +从 v7.5.3 和 v7.6.0 版本开始,TiDB 在 [`INFORMATION_SCHEMA.KEYWORDS`](/information-schema/information-schema-keywords.md) 表中提供了完整的关键字列表。 ## 关键字列表 -下表列出了 TiDB 中所有的关键字。其中保留字用 `(R)` 来标识。[窗口函数](/functions-and-operators/window-functions.md)的保留字用 `(R-Window)` 来标识。 +以下列表显示了 TiDB 中的关键字。保留关键字标记为 `(R)`。[窗口函数](/functions-and-operators/window-functions.md)的保留关键字标记为 `(R-Window)`。 diff --git a/literal-values.md b/literal-values.md index ecc590dbcc53..3cda9753d6b0 100644 --- a/literal-values.md +++ b/literal-values.md @@ -1,22 +1,24 @@ --- title: 字面值 -summary: 本文介绍了 TiDB SQL 语句的字面值。 +summary: 本文介绍 TiDB SQL 语句中的字面值。 --- # 字面值 -TiDB 字面值包括字符字面值、数值字面值、时间日期字面值、十六进制、二进制字面值和 NULL 字面值。以下分别对这些字面值进行一一介绍。 +TiDB 字面值包括字符字面值、数值字面值、时间和日期字面值、十六进制字面值、二进制字面值和 NULL 字面值。本文介绍这些字面值。 -## String Literals +本文描述了字符串字面值、数值字面值、NULL 值、十六进制字面值、日期和时间字面值、布尔字面值以及位值字面值。 -String Literals 是一个 bytes 或者 characters 的序列,两端被单引号 `'` 或者双引号 `"` 包围,例如: +## 字符串字面值 + +字符串是一个字节或字符序列,由单引号 `'` 或双引号 `"` 包围。例如: ``` 'example string' "example string" ``` -如果字符串是连续的,会被合并为一个独立的 string。以下表示是一样的: +相邻的带引号字符串会被连接成一个单独的字符串。以下几行是等价的: ``` 'a string' @@ -24,14 +26,14 @@ String Literals 是一个 bytes 或者 characters 的序列,两端被单引号 "a" ' ' "string" ``` -如果开启了 `ANSI_QUOTES` SQL MODE,那么只有单引号内的会被认为是 String Literals,对于双引号内的字符串,会被认为是一个 identifier。 +如果启用了 `ANSI_QUOTES` SQL 模式,字符串字面值只能用单引号引起来,因为双引号引起来的字符串会被解释为标识符。 -字符串分为以下两种: +字符串分为以下两种类型: -+ 二进制字符串 (binary string):由字节序列构成,它的 charset 和 collation 都是 `binary`,在互相比较时利用**字节**作为单位。 -+ 非二进制字符串:由字符序列构成,有除 `binary` 以外的多种 charset 和 collation,在相互比较时用**字符**(一个字符可能包含多个字节,取决于 charset 的选择)作为单位。 ++ 二进制字符串:由一个字节序列组成,其字符集和排序规则都是 `binary`,在相互比较时使用**字节**作为单位。 ++ 非二进制字符串:由一个字符序列组成,具有除 `binary` 之外的各种字符集和排序规则。在相互比较时使用**字符**作为单位。一个字符可能包含多个字节,这取决于字符集。 -一个 String Literal 可以拥有一个可选的 `character set introducer` 和 `COLLATE clause`,可以用来指定特定的 charset 和 collation。 +字符串字面值可以有一个可选的 `字符集引入器` 和 `COLLATE 子句`,用于指定使用特定的字符集和排序规则。 ``` [_charset_name]'string' [COLLATE collation_name] @@ -39,98 +41,91 @@ String Literals 是一个 bytes 或者 characters 的序列,两端被单引号 例如: -{{< copyable "sql" >}} - -```sql +``` SELECT _latin1'string'; SELECT _binary'string'; SELECT _utf8'string' COLLATE utf8_bin; ``` -你可以使用 `N'literal'` 或者 `n'literal'` 来创建使用 national character set 的字符串,下列语句是一样的: - -{{< copyable "sql" >}} +你可以使用 N'literal'(或 n'literal')来创建国家字符集中的字符串。以下语句是等价的: -```sql +``` SELECT N'some text'; SELECT n'some text'; SELECT _utf8'some text'; ``` -要在字符串中表示某些特殊字符,可以利用转义字符进行转义: +要在字符串中表示一些特殊字符,你可以使用转义字符进行转义: | 转义字符 | 含义 | -| :------ | :---- | +| :---------------- | :------ | | \\0 | ASCII NUL (X'00') 字符 | -| \\' | 单引号 | -| \\" | 双引号 | -| \\b | 退格符号 | +| \\' | 单引号 `'` 字符 | +| \\" | 双引号 `"` 字符 | +| \\b | 退格字符 | | \\n | 换行符 | | \\r | 回车符 | -| \\t | tab 符(制表符) | +| \\t | 制表符 | | \\z | ASCII 26 (Ctrl + Z) | -| \\\\ | 反斜杠 \\ | -| \\% | \% | -| \\_ | \_ | - -如果要在 `'` 包围的字符串中表示 `"`,或者在 `"` 包围的字符串中表示 `'`,可以不使用转义字符。 +| \\\\ | 反斜杠 `\` 字符 | +| \\% | `%` 字符 | +| \\_ | `_` 字符 | -更多细节见 [MySQL 官方文档](https://dev.mysql.com/doc/refman/8.0/en/string-literals.html)。 +如果你想在由 `'` 包围的字符串中表示 `"`,或在由 `"` 包围的字符串中表示 `'`,则不需要使用转义字符。 -## Numeric Literals +更多信息,请参见 [MySQL 中的字符串字面值](https://dev.mysql.com/doc/refman/8.0/en/string-literals.html)。 -数值字面值包括 integer 跟 Decimal 类型跟浮点数字面值。 +## 数值字面值 -integer 可以包括 `.` 作为小数点分隔,数字前可以有 `-` 或者 `+` 来表示正数或者负数。 +数值字面值包括整数和 DECIMAL 字面值以及浮点字面值。 -精确数值字面值可以表示为如下格式:`1, .2, 3.4, -5, -6.78, +9.10`. +整数可以包含 `.` 作为小数分隔符。数字前面可以有 `-` 或 `+` 来表示负值或正值。 -科学记数法也是被允许的,表示为如下格式:`1.2E3, 1.2E-3, -1.2E3, -1.2E-3`。 +精确值数值字面值可以表示为 `1, .2, 3.4, -5, -6.78, +9.10`。 -更多细节见 [MySQL 官方文档](https://dev.mysql.com/doc/refman/8.0/en/number-literals.html)。 +数值字面值也可以用科学记数法表示,如 `1.2E3, 1.2E-3, -1.2E3, -1.2E-3`。 -## Date and Time Literals +更多信息,请参见 [MySQL 中的数值字面值](https://dev.mysql.com/doc/refman/8.0/en/number-literals.html)。 -Date 跟 Time 字面值有几种格式,例如用字符串表示,或者直接用数字表示。在 TiDB 里面,当 TiDB 期望一个 Date 的时候,它会把 `'2017-08-24'`,`'20170824'`,`20170824` 当做是 Date。 +## 日期和时间字面值 -TiDB 的 Date 值有以下几种格式: +日期和时间字面值可以用多种格式表示,如带引号的字符串或数字。当 TiDB 期望一个日期时,它会将 `'2017-08-24'`、`'20170824'` 和 `20170824` 都解释为日期。 -* `'YYYY-MM-DD'` 或者 `'YY-MM-DD'`,这里的 `-` 分隔符并不是严格的,可以是任意的标点符号。比如 `'2017-08-24'`,`'2017&08&24'`,`'2012@12^31'` 都是一样的。唯一需要特别对待的是 '.' 号,它被当做是小数点,用于分隔整数和小数部分。 +TiDB 支持以下日期格式: - Date 和 Time 部分可以被 'T' 分隔,它的作用跟空格符是一样的,例如 `2017-8-24 10:42:00` 跟 `2017-8-24T10:42:00` 是一样的。 +* `'YYYY-MM-DD'` 或 `'YY-MM-DD'`:这里的 `-` 分隔符不是严格的。它可以是任何标点符号。例如,`'2017-08-24'`、`'2017&08&24'`、`'2012@12^31'` 都是有效的日期格式。唯一的特殊标点是 '.',它被视为小数点来分隔整数部分和小数部分。日期和时间可以用 `T` 或空格分隔。例如,`2017-8-24 10:42:00` 和 `2017-8-24T10:42:00` 表示相同的日期和时间。 +* `'YYYYMMDDHHMMSS'` 或 `'YYMMDDHHMMSS'`:例如,`'20170824104520'` 和 `'170824104520'` 被视为 `'2017-08-24 10:45:20'`。但是,如果你提供的值超出范围,如 `'170824304520'`,则不会被视为有效日期。注意,不正确的格式如 `YYYYMMDD HHMMSS`、`YYYYMMDD HH:MM:DD` 或 `YYYY-MM-DD HHMMSS` 将无法插入。 +* `YYYYMMDDHHMMSS` 或 `YYMMDDHHMMSS`:注意这些格式没有单引号或双引号,而是一个数字。例如,`20170824104520` 被解释为 `'2017-08-24 10:45:20'`。 -* `'YYYYMMDDHHMMSS'` 或者 `'YYMMDDHHMMSS'`,例如 `'20170824104520'` 和 `'170824104520'` 被当做是 `'2017-08-24 10:45:20'`,但是如果你提供了一个超过范围的值,例如`'170824304520'`,那这就不是一个有效的 Date 字面值。需要注意 `YYYYMMDD HHMMSS`、`YYYYMMDD HH:MM:DD` 和 `YYYY-MM-DD HHMMSS` 等不正确的格式会插入失败。 -* `YYYYMMDDHHMMSS` 或者 `YYMMDDHHMMSS`,注意这里没有单引号或者双引号,是一个数字。例如 `20170824104520` 表示 `'2017-08-24 10:45:20'`。 +DATETIME 或 TIMESTAMP 值后面可以跟一个小数部分,用于表示微秒精度(6 位数字)。小数部分应始终用小数点 `.` 与时间的其余部分分隔。 -DATETIME 或者 TIMESTAMP 值可以接一个小数部分,用来表示微秒(精度最多到小数点后 6 位),用小数点 `.` 分隔。 +只包含两位数字的年份值是模糊的。建议使用四位数字的年份格式。TiDB 根据以下规则解释两位数字的年份值: -如果 Date 的 year 部分只有两个数字,这是有歧义的(推荐使用四个数字的格式),TiDB 会尝试用以下的规则来解释: +* 如果年份值在 `70-99` 范围内,它被转换为 `1970-1999`。 +* 如果年份值在 `00-69` 范围内,它被转换为 `2000-2069`。 -* year 值如果在 `70-99` 范围,那么被转换成 `1970-1999`。 -* year 值如果在 `00-69` 范围,那么被转换成 `2000-2069`。 +对于小于 10 的月份或日期值,`'2017-8-4'` 与 `'2017-08-04'` 相同。时间也是如此。例如,`'2017-08-24 1:2:3'` 与 `'2017-08-24 01:02:03'` 相同。 -对于小于 10 的 month 或者 day 值,`'2017-8-4'` 跟 `'2017-08-04'` 是一样的。对于 Time 也是一样,比如 `'2017-08-24 1:2:3'` 跟 `'2017-08-24 01:02:03'`是一样的。 +当需要日期或时间值时,TiDB 根据值的长度选择指定的格式: -在需要 Date 或者 Time 的语境下,对于数值,TiDB 会根据数值的长度来选定指定的格式: +* 6 位数字:`YYMMDD`。 +* 12 位数字:`YYMMDDHHMMSS`。 +* 8 位数字:`YYYYMMDD`。 +* 14 位数字:`YYYYMMDDHHMMSS`。 -* 6 个数字,会被解释为 `YYMMDD`。 -* 12 个数字,会被解释为 `YYMMDDHHMMSS`。 -* 8 个数字,会解释为 `YYYYMMDD`。 -* 14 个数字,会被解释为 `YYYYMMDDHHMMSS`。 +TiDB 支持以下时间值格式: -对于 Time 类型,TiDB 用以下格式来表示: +* `'D HH:MM:SS'`,或 `'HH:MM:SS'`、`'HH:MM'`、`'D HH:MM'`、`'D HH'`、`'SS'`:`D` 表示天数,有效值范围是 `0-34`。 +* `HHMMSS` 格式的数字:例如,`231010` 被解释为 `'23:10:10'`。 +* `SS`、`MMSS` 和 `HHMMSS` 格式的数字都可以被视为时间。 -* `'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 位数字。 -Time 类型的小数点也是 `.`,精度最多小数点后 6 位。 +更多详情请参见 [MySQL 日期和时间字面值](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-literals.html)。 -更多细节见 [MySQL 官方文档](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-literals.html)。 +## 布尔字面值 -## Boolean Literals - -常量 `TRUE` 和 `FALSE` 等于 1 和 0,它是大小写不敏感的。 +常量 `TRUE` 和 `FALSE` 分别等于 1 和 0,不区分大小写。 {{< copyable "sql" >}} @@ -147,11 +142,11 @@ SELECT TRUE, true, tRuE, FALSE, FaLsE, false; 1 row in set (0.00 sec) ``` -## Hexadecimal Literals +## 十六进制字面值 -十六进制字面值是有 `X` 和 `0x` 前缀的字符串,后接表示十六进制的数字。注意 `0x` 是大小写敏感的,不能表示为 `0X`。 +十六进制字面值使用 `X'val'` 或 `0xval` 表示法编写,其中 `val` 包含十六进制数字。前导 `0x` 区分大小写,不能写成 `0X`。 -例如: +合法的十六进制字面值: ``` X'ac12' @@ -162,32 +157,19 @@ x'12AC' 0x12AC ``` -以下是不合法的十六进制字面值: +非法的十六进制字面值: ``` -X'1z' (z 不是合法的十六进制值) -0X12AC (0X 必须用小写的 0x) +X'1z' (z 不是合法的十六进制数字) +0X12AC (0X 必须写成 0x) ``` -对于使用 `X'val'` 格式的十六进制字面值,`val` 必须包含偶数个字符,如果 `val` 的长度是奇数(比如 X'A'、X'11A'),可以在前面补一个 0 来避免语法错误。 - -{{< copyable "sql" >}} +使用 `X'val'` 表示法编写的十六进制字面值必须包含偶数个数字。如果 `val` 的长度是奇数(例如,`X'A'` 或 `X'11A'`),为避免语法错误,请在值前面补零: ```sql -select X'aff'; -``` - -``` +mysql> select X'aff'; ERROR 1105 (HY000): line 0 column 13 near ""hex literal: invalid hexadecimal format, must even numbers, but 3 (total length 13) -``` - -{{< copyable "sql" >}} - -```sql -select X'0aff'; -``` - -``` +mysql> select X'0aff'; +---------+ | X'0aff' | +---------+ @@ -196,32 +178,20 @@ select X'0aff'; 1 row in set (0.00 sec) ``` -默认情况,十六进制字面值是一个二进制字符串。 +默认情况下,十六进制字面值是二进制字符串。 -如果需要将一个字符串或者数字转换为十六进制字面值,可以使用内建函数 `HEX()`: - -{{< copyable "sql" >}} +要将字符串或数字转换为十六进制格式的字符串,请使用 `HEX()` 函数: ```sql -SELECT HEX('TiDB'); -``` - -``` +mysql> SELECT HEX('TiDB'); +-------------+ | HEX('TiDB') | +-------------+ | 54694442 | +-------------+ 1 row in set (0.01 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT X'54694442'; -``` - -``` +mysql> SELECT X'54694442'; +-------------+ | X'54694442' | +-------------+ @@ -230,41 +200,36 @@ SELECT X'54694442'; 1 row in set (0.00 sec) ``` -## Bit-Value Literals - -位值字面值用 `b` 或者 `0b` 做前缀,后接以 0 和 1 组成的二进制数字。其中 `0b` 是区分大小写的,`0B` 则会报错。 +## 位值字面值 -合法的 Bit-value: +位值字面值使用 `b'val'` 或 `0bval` 表示法编写。`val` 是使用零和一编写的二进制值。前导 `0b` 区分大小写,不能写成 `0B`。 -* b'01' -* B'01' -* 0b01 +合法的位值字面值: -非法的 Bit-value: +``` +b'01' +B'01' +0b01 +``` -* `b'2'`(2 不是二进制数值,必须为 0 或 1) -* `0B01`(0B 必须是小写 0b) +非法的位值字面值: -默认情况,位值字面值是一个二进制字符串。 +``` +b'2' (2 不是二进制数字;它必须是 0 或 1) +0B01 (0B 必须写成 0b) +``` -Bit-value 是作为二进制返回的,所以输出到 MySQL Client 可能会无法显示,如果要转换为可打印的字符,可以使用内建函数 `BIN()` 或者 `HEX()`: +默认情况下,位值字面值是二进制字符串。 -{{< copyable "sql" >}} +位值以二进制值形式返回,在 MySQL 客户端中可能显示不好。要将位值转换为可打印形式,你可以使用转换函数,如 `BIN()` 或 `HEX()`。 ```sql CREATE TABLE t (b BIT(8)); INSERT INTO t SET b = b'00010011'; INSERT INTO t SET b = b'1110'; INSERT INTO t SET b = b'100101'; -``` -{{< copyable "sql" >}} - -```sql -SELECT b+0, BIN(b), HEX(b) FROM t; -``` - -``` +mysql> SELECT b+0, BIN(b), HEX(b) FROM t; +------+--------+--------+ | b+0 | BIN(b) | HEX(b) | +------+--------+--------+ @@ -275,10 +240,10 @@ SELECT b+0, BIN(b), HEX(b) FROM t; 3 rows in set (0.00 sec) ``` -## NULL Values +## NULL 值 -`NULL` 代表数据为空,它是大小写不敏感的,与 `\N`(大小写敏感)同义。 +`NULL` 表示数据为空,不区分大小写,与 `\N`(区分大小写)同义。 > **注意:** > -> `NULL` 跟 `0` 并不一样,跟空字符串 `''` 也不一样。 +> `NULL` 不同于 `0`,也不同于空字符串 `''`。 diff --git a/max-min-eliminate.md b/max-min-eliminate.md index 455d389b3afd..6c22050034c7 100644 --- a/max-min-eliminate.md +++ b/max-min-eliminate.md @@ -1,23 +1,23 @@ --- -title: Max/Min 函数消除规则 -summary: SQL 中的 max/min 函数消除规则能够将 max/min 聚合函数转换为 TopN 算子,利用索引进行查询。当只有一个 max/min 函数时,会重写为 select max(a) from (select a from t where a is not null order by a desc limit 1) t,利用索引只扫描一行数据。存在多个 max/min 函数时,会先检查列是否有索引能够保序,然后重写为两个子查询的笛卡尔积,最终避免对整个表的扫描。 +title: 消除 Max/Min +summary: 介绍消除 Max/Min 函数的规则。 --- -# Max/Min 函数消除规则 +# 消除 Max/Min -在 SQL 中包含了 `max`/`min` 函数时,查询优化器会尝试使用 `max`/`min` 消除优化规则来将 `max`/`min` 聚合函数转换为 TopN 算子,从而能够有效地利用索引进行查询。 +当 SQL 语句中包含 `max`/`min` 函数时,查询优化器会尝试通过应用 `max`/`min` 优化规则将 `max`/`min` 聚合函数转换为 TopN 算子。通过这种方式,TiDB 可以通过索引更高效地执行查询。 -根据 `select` 语句中 `max`/`min` 函数的个数,这一优化规则有以下两种表现形式: +根据 `select` 语句中 `max`/`min` 函数的数量,这个优化规则分为以下两种类型: -+ [只有一个 max/min 函数时的优化规则](#只有一个-maxmin-函数时的优化规则) -+ [存在多个 max/min 函数时的优化规则](#存在多个-maxmin-函数时的优化规则) +- [只有一个 `max`/`min` 函数的语句](#one-maxmin-function) +- [有多个 `max`/`min` 函数的语句](#multiple-maxmin-functions) -## 只有一个 max/min 函数时的优化规则 +## 一个 `max`/`min` 函数 -当一个 SQL 满足以下条件时,就会应用这个规则: +当 SQL 语句满足以下条件时,会应用此规则: -+ 只有一个聚合函数,且为 `max` 或者 `min` 函数。 -+ 聚合函数没有相应的 `group by` 语句。 +- 语句只包含一个聚合函数,该函数是 `max` 或 `min`。 +- 该聚合函数没有相关的 `group by` 子句。 例如: @@ -27,7 +27,7 @@ summary: SQL 中的 max/min 函数消除规则能够将 max/min 聚合函数转 select max(a) from t ``` -这时 `max`/`min` 消除优化规则会将其重写为: +优化规则将语句重写如下: {{< copyable "sql" >}} @@ -35,11 +35,11 @@ select max(a) from t select max(a) from (select a from t where a is not null order by a desc limit 1) t ``` -这个新的 SQL 语句在 `a` 列存在索引(或 `a` 列是某个联合索引的前缀)时,能够利用索引只扫描一行数据来得到最大或者最小值,从而避免对整个表的扫描。 +当列 `a` 有索引,或者列 `a` 是某个复合索引的前缀时,在索引的帮助下,新的 SQL 语句只需扫描一行数据就能找到最大值或最小值。这种优化避免了全表扫描。 -上述例子最终得到的执行计划如下: +示例语句的执行计划如下: -``` +```sql mysql> explain select max(a) from t; +------------------------------+---------+-----------+-------------------------+-------------------------------------+ | id | estRows | task | access object | operator info | @@ -53,15 +53,15 @@ mysql> explain select max(a) from t; 5 rows in set (0.00 sec) ``` -## 存在多个 max/min 函数时的优化规则 +## 多个 `max`/`min` 函数 -当一个 SQL 满足以下条件时,就会应用这个规则: +当 SQL 语句满足以下条件时,会应用此规则: -+ 有多个聚合函数,且所有的聚合函数都是 max/min -+ 聚合函数没有相应的 `group by` 语句。 -+ 每个 `max`/`min` 聚合函数参数中的列都有索引能够保序。 +- 语句包含多个聚合函数,这些函数都是 `max` 或 `min` 函数。 +- 所有聚合函数都没有相关的 `group by` 子句。 +- 每个 `max`/`min` 函数中的列都有保序的索引。 -下面是一个简单的例子: +例如: {{< copyable "sql" >}} @@ -69,7 +69,7 @@ mysql> explain select max(a) from t; select max(a) - min(a) from t ``` -优化规则会先检查 `a` 列是否存在索引能够为其保序,如果存在,这个 SQL 会先被重写为两个子查询的笛卡尔积: +优化规则首先检查列 `a` 是否有保序的索引。如果有,SQL 语句会被重写为两个子查询的笛卡尔积: {{< copyable "sql" >}} @@ -80,7 +80,7 @@ from (select min(a) as min_a from t) t2 ``` -这样,两个子句中的 `max`/`min` 函数就可以使用上述“只有一个 `max`/`min` 函数时的优化规则”分别进行优化,最终重写为: +通过重写,优化器可以分别对两个子查询应用只有一个 `max`/`min` 函数的语句规则。然后语句被重写如下: {{< copyable "sql" >}} @@ -91,11 +91,11 @@ from (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` 列没有可以保序的索引,这个变换会使原本只需一次的全表扫描变成两次,因此这个规则就不会被应用。 +同样,如果列 `a` 有保序的索引,优化后的执行只需扫描两行数据而不是整个表。但是,如果列 `a` 没有保序的索引,这个规则会导致两次全表扫描,而不重写的话只需要一次全表扫描。因此,在这种情况下不会应用此规则。 -最后得到的执行计划: +最终的执行计划如下: -``` +```sql mysql> explain select max(a)-min(a) from t; +------------------------------------+---------+-----------+-------------------------+-------------------------------------+ | id | estRows | task | access object | operator info | diff --git a/metadata-lock.md b/metadata-lock.md index 410c8e3de4b6..f884defc724c 100644 --- a/metadata-lock.md +++ b/metadata-lock.md @@ -1,47 +1,47 @@ --- title: 元数据锁 -summary: 介绍 TiDB 中元数据锁的概念、原理、实现和影响。 +summary: 介绍 TiDB 中元数据锁的概念、原理和实现细节。 --- # 元数据锁 -本文介绍了 TiDB 中的元数据锁。 +本文介绍 TiDB 中的元数据锁。 -## 元数据锁的概念 +## 概念 -在 TiDB 中,对元数据对象的更改采用的是在线异步变更算法。事务在执行时会获取开始时对应的元数据快照。如果事务执行过程中相关表上发生了元数据的更改,为了保证数据的一致性,TiDB 会返回 `Information schema is changed` 的错误,导致用户事务提交失败。 +TiDB 使用在线异步 schema 变更算法来支持元数据对象的变更。当执行事务时,事务会在开始时获取相应的元数据快照。如果在事务执行期间元数据发生变更,为了保证数据一致性,TiDB 会返回 `Information schema is changed` 错误,事务提交失败。 -为了解决这个问题,在 TiDB v6.3.0 中,online DDL 算法中引入了元数据锁特性。通过协调表元数据变更过程中 DML 语句和 DDL 语句的优先级,让执行中的 DDL 语句等待持有旧版本元数据的 DML 语句提交,尽可能避免 DML 语句报错。 +为了解决这个问题,TiDB v6.3.0 在在线 DDL 算法中引入了元数据锁。为了避免大多数 DML 错误,TiDB 在表元数据变更期间协调 DML 和 DDL 的优先级,使执行 DDL 等待使用旧元数据的 DML 提交。 -## 适用场景 +## 应用场景 -元数据锁适用于所有的 DDL 语句,包括但不限于: +TiDB 中的元数据锁适用于所有 DDL 语句,例如: - [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) - [`ADD COLUMN`](/sql-statements/sql-statement-add-column.md) - [`DROP COLUMN`](/sql-statements/sql-statement-drop-column.md) - [`DROP INDEX`](/sql-statements/sql-statement-drop-index.md) -- [`DROP PARTITION`](/partitioned-table.md#分区管理) +- [`DROP PARTITION`](/partitioned-table.md#partition-management) - [`TRUNCATE TABLE`](/sql-statements/sql-statement-truncate.md) -- [`EXCHANGE PARTITION`](/partitioned-table.md#分区管理) +- [`EXCHANGE PARTITION`](/partitioned-table.md#partition-management) - [`CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) - [`MODIFY COLUMN`](/sql-statements/sql-statement-modify-column.md) -使用元数据锁机制会给 TiDB DDL 任务的执行带来一定的性能影响。为了降低元数据锁对 DDL 任务的影响,下列场景不需要加元数据锁: +启用元数据锁可能会对 TiDB 中 DDL 任务的执行性能产生一些影响。为了减少影响,以下列出了一些不需要元数据锁的场景: -- 开启了 auto-commit 的查询语句 -- 开启了 Stale Read 功能 -- 访问临时表 ++ 启用自动提交的 `SELECT` 查询 ++ 启用 Stale Read ++ 访问临时表 -## 使用元数据锁 +## 使用方法 -在 v6.5.0 及之后的版本中,TiDB 默认开启元数据锁特性。当集群从 v6.5.0 之前的版本升级到 v6.5.0 及之后的版本时,TiDB 会自动开启元数据锁功能。如果需要关闭元数据锁,你可以将系统变量 [`tidb_enable_metadata_lock`](/system-variables.md#tidb_enable_metadata_lock-从-v630-版本开始引入) 设置为 `OFF`。 +从 v6.5.0 开始,TiDB 默认启用元数据锁。当你将现有集群从 v6.4.0 或更早版本升级到 v6.5.0 或更高版本时,TiDB 会自动启用元数据锁。要禁用元数据锁,你可以将系统变量 [`tidb_enable_metadata_lock`](/system-variables.md#tidb_enable_metadata_lock-new-in-v630) 设置为 `OFF`。 -## 元数据锁的影响 +## 影响 -- 对于 DML 语句来说,元数据锁不会导致 DML 语句被阻塞,因此也不会存在死锁的问题。 -- 开启元数据锁后,事务中某个元数据对象的元数据信息在第一次访问时确定,之后不再变化。 -- 对于 DDL 语句来说,在进行元数据状态变更时,会被涉及相关元数据的旧事务所阻塞。例如以下的执行流程: +- 对于 DML,元数据锁不会阻塞其执行,也不会造成任何死锁。 +- 当启用元数据锁时,事务中元数据对象的信息在首次访问时确定,之后不会改变。 +- 对于 DDL,在更改元数据状态时,DDL 可能会被旧事务阻塞。以下是一个示例: | Session 1 | Session 2 | |:---------------------------|:----------| @@ -49,10 +49,10 @@ summary: 介绍 TiDB 中元数据锁的概念、原理、实现和影响。 | `INSERT INTO t VALUES(1);` | | | `BEGIN;` | | | | `ALTER TABLE t ADD COLUMN b INT;` | - | `SELECT * FROM t;`
(采用 `t` 表当前的元数据版本,返回 `(a=1,b=NULL)`,同时给表 `t` 加锁)| | - | | `ALTER TABLE t ADD COLUMN c INT;`(被 Session 1 阻塞)| + | `SELECT * FROM t;`
(使用表 `t` 的当前元数据版本。返回 `(a=1, b=NULL)` 并锁定表 `t`。) | | + | | `ALTER TABLE t ADD COLUMN c INT;`(被 Session 1 阻塞) | - 在可重复读隔离级别下,如果从事务开始到确定一个表的元数据过程中,执行了加索引或者变更列类型等需要更改数据的 DDL,则有以下表现: + 在可重复读隔离级别下,从事务开始到确定表元数据的时间点之间,如果执行了需要数据变更的 DDL,例如添加索引或更改列类型,DDL 会返回如下错误: | Session 1 | Session 2 | |:---------------------------|:------------------------------------------| @@ -60,21 +60,21 @@ summary: 介绍 TiDB 中元数据锁的概念、原理、实现和影响。 | `INSERT INTO t VALUES(1);` | | | `BEGIN;` | | | | `ALTER TABLE t ADD INDEX idx(a);` | - | `SELECT * FROM t;`(索引 `idx` 不可用)| | + | `SELECT * FROM t;`(索引 `idx` 不可用) | | | `COMMIT;` | | | `BEGIN;` | | | | `ALTER TABLE t MODIFY COLUMN a CHAR(10);` | - | `SELECT * FROM t;`(报错 `ERROR 8028 (HY000): public column a has changed`) | | + | `SELECT * FROM t;`(返回 `ERROR 8028 (HY000): public column a has changed`) | | -## 元数据锁的可观测性 +## 可观察性 -TiDB v6.3.0 引入了 `mysql.tidb_mdl_view` 视图,可以用于查看当前阻塞的 DDL 的相关信息。 +TiDB v6.3.0 引入了 `mysql.tidb_mdl_view` 视图,帮助你获取当前被阻塞的 DDL 信息。 > **注意:** > -> 查询 `mysql.tidb_mdl_view` 视图需要有 [`PROCESS` 权限](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process)。 +> 查询 `mysql.tidb_mdl_view` 视图需要 [`PROCESS` 权限](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_process)。 -下面以给表 `t` 添加索引为例,假设有 DDL 语句 `ALTER TABLE t ADD INDEX idx(a)`: +以下以为表 `t` 添加索引为例。假设有一个 DDL 语句 `ALTER TABLE t ADD INDEX idx(a)`: ```sql SELECT * FROM mysql.tidb_mdl_view\G @@ -89,31 +89,31 @@ SQL_DIGESTS: ["begin","select * from `t`"] 1 row in set (0.02 sec) ``` -可以从上面的输出结果中了解到,有一个 `SESSION ID` 为 `2199023255957` 的事务阻塞了该添加索引 DDL 的执行。该事务执行的 SQL 语句如 `SQL_DIGESTS` 中所示,即 ``["begin","select * from `t`"]``。如果想要使被阻塞的 DDL 能够继续执行,可以通过如下 Global `KILL` 命令中止 `SESSION ID` 为 `2199023255957` 的事务: +从上述输出中可以看到,`SESSION ID` 为 `2199023255957` 的事务阻塞了 `ADD INDEX` DDL。`SQL_DIGEST` 显示了该事务执行的 SQL 语句,即 ``["begin","select * from `t`"]``。要使被阻塞的 DDL 继续执行,你可以使用以下全局 `KILL` 语句来终止 `2199023255957` 事务: ```sql mysql> KILL 2199023255957; Query OK, 0 rows affected (0.00 sec) ``` -中止该事务后,再次查询 `mysql.tidb_mdl_view` 视图。此时,查询结果不再显示上面的事务信息,说明 DDL 不再被阻塞: +终止事务后,你可以再次查询 `mysql.tidb_mdl_view` 视图。此时,上述事务不会出现在输出中,这意味着 DDL 不再被阻塞。 ```sql SELECT * FROM mysql.tidb_mdl_view\G Empty set (0.01 sec) ``` -## 元数据锁的原理 +## 原理 ### 问题描述 -TiDB 中 DDL 操作使用的是 online DDL 模式。一个 DDL 语句在执行过程中,需要修改定义的对象元数据版本可能会进行多次小版本变更,而元数据在线异步变更的算法只论证了相邻的两个小版本之间是兼容的,即在相邻的两个元数据版本间操作,不会破坏 DDL 变更对象所存储的数据一致性。 +TiDB 中的 DDL 操作是在线 DDL 模式。当执行 DDL 语句时,要修改的定义对象的元数据版本可能会经历多个小版本变更。在线异步元数据变更算法只建立了相邻两个小版本之间的兼容性,即两个版本之间的操作不会破坏 DDL 变更对象的数据一致性。 -以添加索引为例,DDL 语句的状态会经历 None -> Delete Only,Delete Only -> Write Only,Write Only -> Write Reorg,Write Reorg -> Public 这四个变化。 +在为表添加索引时,DDL 语句的状态变更如下:None -> Delete Only, Delete Only -> Write Only, Write Only -> Write Reorg, Write Reorg -> Public。 -以下的提交流程将违反“相邻的两个小版本之间是兼容的”约束: +以下事务的提交过程违反了上述约束: -| 事务 | 所用的版本 | 集群最新版本 | 版本差 | +| 事务 | 事务使用的版本 | 集群中的最新版本 | 版本差异 | |:-----|:-----------|:-----------|:----| | txn1 | None | None | 0 | | txn2 | DeleteOnly | DeleteOnly | 0 | @@ -123,11 +123,11 @@ TiDB 中 DDL 操作使用的是 online DDL 模式。一个 DDL 语句在执行 | txn6 | WriteOnly | WriteReorg | 1 | | txn7 | Public | Public | 0 | -其中 `txn4` 提交时采用的元数据版本与集群最新的元数据版本相差了两个版本,会影响数据正确性。 +在上表中,`txn4` 提交时使用的元数据版本与集群中的最新版本相差两个版本。这可能会导致数据不一致。 -### 实现 +### 实现细节 -引入元数据锁会保证整个 TiDB 集群中的所有事务所用的元数据版本最多相差一个版本。为此: +元数据锁可以确保 TiDB 集群中所有事务使用的元数据版本最多相差一个版本。为了实现这个目标,TiDB 实现了以下两个规则: -- 执行 DML 语句时,TiDB 会在事务上下文中记录该 DML 语句访问的元数据对象,例如表、视图,以及对应的元数据版本。事务提交时会清空这些记录。 -- DDL 语句进行状态变更时,会向所有的 TiDB 节点推送最新版本的元数据。如果一个 TiDB 节点上所有与这次状态变更相关的事务使用的元数据版本与当前元数据版本之差小于 2,则称这个 TiDB 节点获得了该元数据对象的元数据锁。当集群中的所有 TiDB 节点都获得了该元数据对象的元数据锁后,才能进行下一次状态变更。 \ No newline at end of file +- 执行 DML 时,TiDB 在事务上下文中记录 DML 访问的元数据对象,如表、视图和相应的元数据版本。这些记录在事务提交时被清理。 +- 当 DDL 语句改变状态时,最新版本的元数据被推送到所有 TiDB 节点。如果 TiDB 节点上与此状态变更相关的所有事务使用的元数据版本与当前元数据版本的差异小于两个,则认为该 TiDB 节点获得了元数据对象的元数据锁。只有在集群中所有 TiDB 节点都获得元数据对象的元数据锁后,才能执行下一个状态变更。 diff --git a/mysql-compatibility.md b/mysql-compatibility.md index a8a108f10971..a2cfce85560f 100644 --- a/mysql-compatibility.md +++ b/mysql-compatibility.md @@ -1,71 +1,95 @@ --- -title: 与 MySQL 兼容性对比 -summary: 本文对 TiDB 和 MySQL 二者之间从语法和功能特性上做出详细的对比。 +title: MySQL 兼容性 +summary: 了解 TiDB 与 MySQL 的兼容性,以及不支持和有差异的功能。 --- -# 与 MySQL 兼容性对比 +# MySQL 兼容性 -TiDB 高度兼容 MySQL 协议,以及 MySQL 5.7 和 MySQL 8.0 常用的功能及语法。MySQL 生态中的系统工具(PHPMyAdmin、Navicat、MySQL Workbench、DBeaver 和[其他工具](/develop/dev-guide-third-party-support.md#gui))、客户端等均适用于 TiDB。 + -但 TiDB 尚未支持一些 MySQL 功能,可能的原因如下: +TiDB 高度兼容 MySQL 协议以及 MySQL 5.7 和 MySQL 8.0 的常用功能和语法。MySQL 生态系统工具(PHPMyAdmin、Navicat、MySQL Workbench、DBeaver 和[更多](/develop/dev-guide-third-party-support.md#gui))以及 MySQL 客户端都可以用于 TiDB。 -- 有更好的解决方案,例如 JSON 取代 XML 函数。 -- 目前对这些功能的需求度不高,例如存储过程和函数。 -- 一些功能在分布式系统上的实现难度较大。 + -除此以外,TiDB 不支持 MySQL 复制协议,但提供了专用工具用于与 MySQL 复制数据: + -- 从 MySQL 复制:[TiDB Data Migration (DM)](/dm/dm-overview.md) 是将 MySQL/MariaDB 数据迁移到 TiDB 的工具,可用于增量数据的复制。 -- 向 MySQL 复制:[TiCDC](/ticdc/ticdc-overview.md) 是一款通过拉取 TiKV 变更日志实现的 TiDB 增量数据同步工具,可通过 [MySQL sink](/ticdc/ticdc-sink-to-mysql.md) 将 TiDB 增量数据复制到 MySQL。 +TiDB 高度兼容 MySQL 协议以及 MySQL 5.7 和 MySQL 8.0 的常用功能和语法。MySQL 生态系统工具(PHPMyAdmin、Navicat、MySQL Workbench、DBeaver 和[更多](https://docs.pingcap.com/tidb/v7.2/dev-guide-third-party-support#gui))以及 MySQL 客户端都可以用于 TiDB。 + + + +然而,TiDB 不支持 MySQL 的某些功能。这可能是因为现在有更好的解决方案(比如使用 JSON 而不是 XML 函数),或者当前需求相对于所需工作量较小(比如存储过程和函数)。此外,某些功能在分布式系统中可能难以实现。 + + + +需要注意的是,TiDB 不支持 MySQL 复制协议。相反,提供了特定工具来与 MySQL 进行数据复制: + +- 从 MySQL 复制数据:[TiDB Data Migration (DM)](/dm/dm-overview.md) 是一个支持从 MySQL 或 MariaDB 到 TiDB 进行全量数据迁移和增量数据复制的工具。 +- 复制数据到 MySQL:[TiCDC](/ticdc/ticdc-overview.md) 是一个通过拉取 TiKV 变更日志来复制 TiDB 增量数据的工具。TiCDC 使用 [MySQL sink](/ticdc/ticdc-overview.md#replication-consistency) 将 TiDB 的增量数据复制到 MySQL。 + + + + > **注意:** > -> 本页内容仅涉及 MySQL 与 TiDB 的总体差异。关于[安全特性](/security-compatibility-with-mysql.md)、[悲观事务模式](/pessimistic-transaction.md#和-mysql-innodb-的差异)相关的兼容信息,请查看各自具体页面。 - -## 不支持的功能特性 - -* 存储过程与函数 -* 触发器 -* 事件 -* 自定义函数 -* 全文语法与索引 [#1793](https://github.com/pingcap/tidb/issues/1793) -* 空间类型的函数(即 `GIS`/`GEOMETRY`)、数据类型和索引 [#6347](https://github.com/pingcap/tidb/issues/6347) -* 非 `ascii`、`latin1`、`binary`、`utf8`、`utf8mb4`、`gbk` 的字符集 -* MySQL 追踪优化器 -* XML 函数 -* X-Protocol [#1109](https://github.com/pingcap/tidb/issues/1109) -* 列级权限 [#9766](https://github.com/pingcap/tidb/issues/9766) -* `XA` 语法(TiDB 内部使用两阶段提交,但并没有通过 SQL 接口公开) -* `CREATE TABLE tblName AS SELECT stmt` 语法 [#4754](https://github.com/pingcap/tidb/issues/4754) -* `CHECK TABLE` 语法 [#4673](https://github.com/pingcap/tidb/issues/4673) -* `CHECKSUM TABLE` 语法 [#1895](https://github.com/pingcap/tidb/issues/1895) -* `REPAIR TABLE` 语法 -* `OPTIMIZE TABLE` 语法 -* `HANDLER` 语句 -* `CREATE TABLESPACE` 语句 -* "Session Tracker: 将 GTID 上下文信息添加到 OK 包中" -* 降序索引 [#2519](https://github.com/pingcap/tidb/issues/2519) -* `SKIP LOCKED` 语法 [#18207](https://github.com/pingcap/tidb/issues/18207) -* 横向派生表 [#40328](https://github.com/pingcap/tidb/issues/40328) -* JOIN 的 ON 子句的子查询 [#11414](https://github.com/pingcap/tidb/issues/11414) - -## 与 MySQL 有差异的特性详细说明 +> 本页描述了 MySQL 和 TiDB 之间的一般差异。有关安全性和悲观事务模式方面与 MySQL 的兼容性的更多信息,请参阅专门的[安全性](/security-compatibility-with-mysql.md)和[悲观事务模式](/pessimistic-transaction.md#difference-with-mysql-innodb)页面。 + + + + + +> **注意:** +> +> 关于 MySQL 和 TiDB 之间的事务差异信息,请参阅[悲观事务模式](/pessimistic-transaction.md#difference-with-mysql-innodb)。 + + + +你可以在 [TiDB Playground](https://play.tidbcloud.com/?utm_source=docs&utm_medium=mysql_compatibility) 上试用 TiDB 功能。 + +## 不支持的功能 + ++ 存储过程和函数 ++ 触发器 ++ 事件 ++ 用户定义函数 ++ `FULLTEXT` 语法和索引 [#1793](https://github.com/pingcap/tidb/issues/1793) ++ `SPATIAL`(也称为 `GIS`/`GEOMETRY`)函数、数据类型和索引 [#6347](https://github.com/pingcap/tidb/issues/6347) ++ 除 `ascii`、`latin1`、`binary`、`utf8`、`utf8mb4` 和 `gbk` 之外的字符集 ++ 优化器跟踪 ++ XML 函数 ++ X-Protocol [#1109](https://github.com/pingcap/tidb/issues/1109) ++ 列级权限 [#9766](https://github.com/pingcap/tidb/issues/9766) ++ `XA` 语法(TiDB 内部使用两阶段提交,但这不通过 SQL 接口暴露) ++ `CREATE TABLE tblName AS SELECT stmt` 语法 [#4754](https://github.com/pingcap/tidb/issues/4754) ++ `CHECK TABLE` 语法 [#4673](https://github.com/pingcap/tidb/issues/4673) ++ `CHECKSUM TABLE` 语法 [#1895](https://github.com/pingcap/tidb/issues/1895) ++ `REPAIR TABLE` 语法 ++ `OPTIMIZE TABLE` 语法 ++ `HANDLER` 语句 ++ `CREATE TABLESPACE` 语句 ++ "会话跟踪器:在 OK 数据包中添加 GTIDs 上下文" ++ 降序索引 [#2519](https://github.com/pingcap/tidb/issues/2519) ++ `SKIP LOCKED` 语法 [#18207](https://github.com/pingcap/tidb/issues/18207) ++ 横向派生表 [#40328](https://github.com/pingcap/tidb/issues/40328) ++ JOIN ON 子查询 [#11414](https://github.com/pingcap/tidb/issues/11414) + +## 与 MySQL 的差异 ### 自增 ID -- TiDB 的自增列既能保证唯一,也能保证在单个 TiDB server 中自增,使用 [`AUTO_INCREMENT` 兼容 MySQL 的自增列模式](/auto-increment.md#兼容-mysql-的自增列模式)能保证多个 TiDB server 中自增 ID,但不保证自动分配的值的连续性。建议避免将缺省值和自定义值混用,以免出现 `Duplicated Error` 的错误。 ++ 在 TiDB 中,自增列值(ID)在单个 TiDB 服务器内是全局唯一且递增的。要使 ID 在多个 TiDB 服务器之间递增,你可以使用 [`AUTO_INCREMENT` MySQL 兼容模式](/auto-increment.md#mysql-compatibility-mode)。但是,ID 不一定是连续分配的,因此建议避免混合使用默认值和自定义值,以防遇到 `Duplicated Error` 消息。 -- TiDB 可通过 `tidb_allow_remove_auto_inc` 系统变量开启或者关闭允许移除列的 `AUTO_INCREMENT` 属性。删除列属性的语法是:`ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE`。 ++ 你可以使用 `tidb_allow_remove_auto_inc` 系统变量来允许或禁止移除 `AUTO_INCREMENT` 列属性。要移除列属性,请使用 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 语法。 -- TiDB 不支持添加列的 `AUTO_INCREMENT` 属性,移除该属性后不可恢复。 ++ TiDB 不支持添加 `AUTO_INCREMENT` 列属性,一旦移除,就无法恢复。 -- 对于 v6.6.0 及更早的 TiDB 版本,TiDB 的自增列行为与 MySQL InnoDB 保持一致,要求自增列必须为主键或者索引前缀。从 v7.0.0 开始,TiDB 移除了该限制,允许用户更灵活地定义表的主键。关于此更改的详细信息,请参阅 [#40580](https://github.com/pingcap/tidb/issues/40580) ++ 对于 TiDB v6.6.0 及更早版本,TiDB 中的自增列的行为与 MySQL InnoDB 相同,要求它们是主键或索引前缀。从 v7.0.0 开始,TiDB 移除了这个限制,允许更灵活的表主键定义。[#40580](https://github.com/pingcap/tidb/issues/40580) -自增 ID 详情可参阅 [AUTO_INCREMENT](/auto-increment.md)。 +更多详情,请参阅 [`AUTO_INCREMENT`](/auto-increment.md)。 > **注意:** > -> 若创建表时没有指定主键时,TiDB 会使用 `_tidb_rowid` 来标识行,该数值的分配会和自增列(如果存在的话)共用一个分配器。如果指定了自增列为主键,则 TiDB 会用该列来标识行。因此会有以下的示例情况: +> + 如果在创建表时未指定主键,TiDB 使用 `_tidb_rowid` 来标识行。此值的分配与自增列(如果存在)共享一个分配器。如果将自增列指定为主键,TiDB 使用该列来标识行。在这种情况下,可能会出现以下情况: ```sql mysql> CREATE TABLE t(id INT UNIQUE KEY AUTO_INCREMENT); @@ -91,152 +115,179 @@ mysql> SELECT _tidb_rowid, id FROM t; 3 rows in set (0.01 sec) ``` -可以看到,由于共用分配器,id 每次自增步长是 2。在[兼容 MySQL 的自增列模式](/auto-increment.md#兼容-mysql-的自增列模式)中改掉了该行为,没有共用分配器,因此不会跳号。 +如图所示,由于共享分配器,`id` 每次增加 2。在 [MySQL 兼容模式](/auto-increment.md#mysql-compatibility-mode)下,此行为会改变,因为没有共享分配器,因此不会跳过数字。 + + > **注意:** > -> 使用 `AUTO_INCREMENT` 可能会给生产环境带热点问题,因此推荐使用 [`AUTO_RANDOM`](/auto-random.md) 代替。详情请参考 [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md#tidb-热点问题处理)。 +> `AUTO_INCREMENT` 属性可能在生产环境中造成热点问题。详情请参阅[热点问题处理](/troubleshoot-hot-spot-issues.md)。建议改用 [`AUTO_RANDOM`](/auto-random.md)。 + + + + + +> **注意:** +> +> `AUTO_INCREMENT` 属性可能在生产环境中造成热点问题。详情请参阅[热点问题处理](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues#handle-auto-increment-primary-key-hotspot-tables-using-auto_random)。建议改用 [`AUTO_RANDOM`](/auto-random.md)。 + + ### Performance schema -TiDB 主要使用 Prometheus 和 Grafana 来存储及查询相关的性能监控指标。因此,TiDB 的大多数 [performance schema 表](/performance-schema/performance-schema.md)返回空结果。 + + +TiDB 使用 [Prometheus 和 Grafana](/tidb-monitoring-api.md) 的组合来存储和查询性能监控指标。在 TiDB 中,大多数[性能 schema 表](/performance-schema/performance-schema.md)不返回任何结果。 + + -### 查询计划 + -TiDB 中,执行计划(`EXPLAIN` 和 `EXPLAIN FOR`)在输出格式、内容、权限设置方面与 MySQL 有较大差别。 +要在 TiDB Cloud 中检查性能指标,你可以查看 TiDB Cloud 控制台中的集群概览页面,或使用[第三方监控集成](/tidb-cloud/third-party-monitoring-integrations.md)。在 TiDB 中,大多数[性能 schema 表](/performance-schema/performance-schema.md)返回空结果。 -MySQL 系统变量 `optimizer_switch` 在 TiDB 中是只读的,对查询计划没有影响。你还可以在 [optimizer hints](/optimizer-hints.md) 中使用与 MySQL 类似的语法,但可用的 hint 和实现原理可能会有所不同。 + -详情参见[理解 TiDB 执行计划](/explain-overview.md)。 +### 查询执行计划 -### 内建函数 +TiDB 中查询执行计划(`EXPLAIN`/`EXPLAIN FOR`)的输出格式、内容和权限设置与 MySQL 有显著差异。 -支持常用的 MySQL 内建函数,有部分函数并未支持。可通过执行 [`SHOW BUILTINS`](/sql-statements/sql-statement-show-builtins.md) 语句查看可用的内建函数。 +在 TiDB 中,MySQL 系统变量 `optimizer_switch` 是只读的,对查询计划没有影响。虽然优化器提示可以使用类似 MySQL 的语法,但可用的提示及其实现可能有所不同。 -### DDL 的限制 +更多信息,请参阅[理解查询执行计划](/explain-overview.md)。 -TiDB 中,所有支持的 DDL 变更操作都是在线执行的。与 MySQL 相比,TiDB 中的 DDL 存在以下限制: +### 内置函数 -* 使用 `ALTER TABLE` 语句修改一个表的多个模式对象(如列、索引)时,不允许在多个更改中指定同一个模式对象。例如,`ALTER TABLE t1 MODIFY COLUMN c1 INT, DROP COLUMN c1` 在两个更改中都指定了 `c1` 列,执行该语句会输出 `Unsupported operate same column/index` 的错误。 -* 不支持使用单个 `ALTER TABLE` 语句同时修改多个 TiDB 特有的模式对象,包括 `TIFLASH REPLICA`,`SHARD_ROW_ID_BITS`,`AUTO_ID_CACHE` 等。 -* `ALTER TABLE` 不支持少部分类型的变更。比如,TiDB 不支持从 `DECIMAL` 到 `DATE` 的变更。当遇到不支持的类型变更时,TiDB 将会报 `Unsupported modify column: type %d not match origin %d` 的错误。更多细节,请参考 [`ALTER TABLE`](/sql-statements/sql-statement-modify-column.md)。 -* TiDB 中,`ALGORITHM={INSTANT,INPLACE,COPY}` 语法只作为一种指定,并不更改 `ALTER` 算法,详情参阅 [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md)。 -* 不支持添加或删除 `CLUSTERED` 类型的主键。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 -* 不支持指定不同类型的索引 (`HASH|BTREE|RTREE|FULLTEXT`)。若指定了不同类型的索引,TiDB 会解析并忽略这些索引。 -* 分区表支持 `HASH`、`RANGE`、`LIST` 和 `KEY` 分区类型。对于不支持的分区类型,TiDB 会报 `Warning: Unsupported partition type %s, treat as normal table` 错误,其中 `%s` 为不支持的具体分区类型。 -* Range、Range COLUMNS、List、List COLUMNS 分区表支持 `ADD`、`DROP`、`TRUNCATE`、`REORGANIZE` 操作,其他分区操作会被忽略。 -* Hash 和 Key 分区表支持 `ADD`、`COALESCE`、`TRUNCATE` 操作,其他分区操作会被忽略。 -* TiDB 不支持以下分区表语法: +TiDB 支持 MySQL 中的大多数内置函数,但不是全部。你可以使用 [`SHOW BUILTINS`](/sql-statements/sql-statement-show-builtins.md) 语句获取可用函数列表。 - + `SUBPARTITION` - + `{CHECK|OPTIMIZE|REPAIR|IMPORT|DISCARD|REBUILD} PARTITION` +### DDL 操作 - 更多详情,请参考[分区表文档](/partitioned-table.md)。 +在 TiDB 中,所有支持的 DDL 更改都可以在线执行。但是,与 MySQL 相比,TiDB 中的 DDL 操作有一些主要限制: -### `ANALYZE TABLE` +* 使用单个 `ALTER TABLE` 语句修改表的多个架构对象(如列或索引)时,不支持在多个更改中指定相同的对象。例如,如果执行 `ALTER TABLE t1 MODIFY COLUMN c1 INT, DROP COLUMN c1` 命令,将输出 `Unsupported operate same column/index` 错误。 +* 不支持使用单个 `ALTER TABLE` 语句修改多个 TiDB 特定的架构对象,如 `TIFLASH REPLICA`、`SHARD_ROW_ID_BITS` 和 `AUTO_ID_CACHE`。 +* TiDB 不支持使用 `ALTER TABLE` 更改某些数据类型。例如,TiDB 不支持从 `DECIMAL` 类型更改为 `DATE` 类型。如果数据类型更改不受支持,TiDB 会报告 `Unsupported modify column: type %d not match origin %d` 错误。更多详情请参阅 [`ALTER TABLE`](/sql-statements/sql-statement-modify-column.md)。 +* `ALGORITHM={INSTANT,INPLACE,COPY}` 语法在 TiDB 中仅作为断言功能,不会修改 `ALTER` 算法。更多详情请参阅 [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md)。 +* 不支持添加/删除 `CLUSTERED` 类型的主键。关于 `CLUSTERED` 类型的主键的更多详情,请参阅[聚簇索引](/clustered-indexes.md)。 +* 不支持不同类型的索引(`HASH|BTREE|RTREE|FULLTEXT`),指定时会被解析并忽略。 +* TiDB 支持 `HASH`、`RANGE`、`LIST` 和 `KEY` 分区类型。对于不支持的分区类型,TiDB 返回 `Warning: Unsupported partition type %s, treat as normal table`,其中 `%s` 是具体的不支持的分区类型。 +* Range、Range COLUMNS、List 和 List COLUMNS 分区表支持 `ADD`、`DROP`、`TRUNCATE` 和 `REORGANIZE` 操作。其他分区操作将被忽略。 +* Hash 和 Key 分区表支持 `ADD`、`COALESCE` 和 `TRUNCATE` 操作。其他分区操作将被忽略。 +* 分区表不支持以下语法: -TiDB 中的[信息统计](/statistics.md#手动收集)与 MySQL 中的有所不同:TiDB 中的信息统计会完全重构表的统计数据,语句消耗较多资源,执行过程较长,但在 MySQL/InnoDB 中,它是一个轻量级语句,执行过程较短。 + - `SUBPARTITION` + - `{CHECK|OPTIMIZE|REPAIR|IMPORT|DISCARD|REBUILD} PARTITION` -更多信息统计的差异请参阅 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md)。 + 关于分区的更多详情,请参阅[分区表](/partitioned-table.md)。 -### `SELECT` 的限制 +### 分析表 -TiDB 的 `SELECT` 语法有以下限制: +在 TiDB 中,[统计信息收集](/statistics.md#manual-collection)与 MySQL 不同,它完全重建表的统计信息,使其成为一个更耗费资源且需要更长时间完成的操作。相比之下,MySQL/InnoDB 执行的是相对轻量级且短暂的操作。 -- 不支持 `SELECT ... INTO @变量` 语法。 -- TiDB 中的 `SELECT .. GROUP BY expr` 的返回结果与 MySQL 5.7 并不一致。MySQL 5.7 的结果等价于 `GROUP BY expr ORDER BY expr`。 +更多信息,请参阅 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md)。 -详情参见 [`SELECT`](/sql-statements/sql-statement-select.md)。 +### `SELECT` 语法的限制 + +TiDB 不支持以下 `SELECT` 语法: + +- `SELECT ... INTO @variable` +- `SELECT .. GROUP BY expr` 不像在 MySQL 5.7 中那样隐含 `GROUP BY expr ORDER BY expr` + +更多详情,请参阅 [`SELECT`](/sql-statements/sql-statement-select.md) 语句参考。 ### `UPDATE` 语句 -详情参见 [`UPDATE`](/sql-statements/sql-statement-update.md)。 +请参阅 [`UPDATE`](/sql-statements/sql-statement-update.md) 语句参考。 ### 视图 -TiDB 中的视图不可更新,不支持 `UPDATE`、`INSERT`、`DELETE` 等写入操作。 +TiDB 中的视图不可更新,不支持写操作,如 `UPDATE`、`INSERT` 和 `DELETE`。 ### 临时表 -详见 [TiDB 本地临时表与 MySQL 临时表的兼容性](/temporary-tables.md#与-mysql-临时表的兼容性)。 +更多信息,请参阅 [TiDB 本地临时表与 MySQL 临时表的兼容性](/temporary-tables.md#compatibility-with-mysql-temporary-tables)。 ### 字符集和排序规则 -* 关于 TiDB 对字符集和排序规则的支持情况,详见[字符集和排序规则](/character-set-and-collation.md)。 +* 要了解 TiDB 支持的字符集和排序规则,请参阅[字符集和排序规则概述](/character-set-and-collation.md)。 -* 关于 GBK 字符集与 MySQL 的兼容情况,详见 [GBK 兼容情况](/character-set-gbk.md#与-mysql-的兼容性)。 +* 关于 GBK 字符集的 MySQL 兼容性信息,请参阅 [GBK 兼容性](/character-set-gbk.md#mysql-compatibility)。 * TiDB 继承表中使用的字符集作为国家字符集。 ### 存储引擎 -- 仅在语法上兼容创建表时指定存储引擎,实际上 TiDB 会将元信息统一描述为 InnoDB 存储引擎。TiDB 支持类似 MySQL 的存储引擎抽象,但需要在系统启动时通过 [`--store`](/command-line-flags-for-tidb-configuration.md#--store) 配置项来指定存储引擎。 +TiDB 允许使用替代存储引擎创建表。尽管如此,TiDB 描述的元数据是针对 InnoDB 存储引擎的,这是为了确保兼容性。 -### SQL 模式 - -TiDB 支持大部分 [SQL 模式](/sql-mode.md)。不支持的 SQL 模式如下: + -- 不支持兼容模式,例如:`Oracle` 和 `PostgreSQL`(TiDB 解析但会忽略这两个兼容模式),MySQL 5.7 已弃用兼容模式,MySQL 8.0 已移除兼容模式。 -- TiDB 的 `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。 +要使用 [`--store`](/command-line-flags-for-tidb-configuration.md#--store) 选项指定存储引擎,需要启动 TiDB 服务器。这个存储引擎抽象功能类似于 MySQL。 -### 默认设置 + -TiDB 的默认设置与 MySQL 5.7 和 MySQL 8.0 有以下区别: +### SQL 模式 -- 字符集: - + TiDB 默认:`utf8mb4`。 - + MySQL 5.7 默认:`latin1`。 - + MySQL 8.0 默认:`utf8mb4`。 +TiDB 支持大多数 [SQL 模式](/sql-mode.md): -- 排序规则: - + TiDB 中 `utf8mb4` 字符集默认:`utf8mb4_bin`。 - + MySQL 5.7 中 `utf8mb4` 字符集默认:`utf8mb4_general_ci`。 - + MySQL 8.0 中 `utf8mb4` 字符集默认:`utf8mb4_0900_ai_ci`。 +- 兼容模式,如 `Oracle` 和 `PostgreSQL` 会被解析但被忽略。兼容模式在 MySQL 5.7 中已弃用,在 MySQL 8.0 中已移除。 +- `ONLY_FULL_GROUP_BY` 模式与 MySQL 5.7 相比有细微的[语义差异](/functions-and-operators/aggregate-group-by-functions.md#differences-from-mysql)。 +- MySQL 中的 `NO_DIR_IN_CREATE` 和 `NO_ENGINE_SUBSTITUTION` SQL 模式为了兼容性而被接受,但不适用于 TiDB。 -- 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`,表示表名和数据库名按照在 `CREATE TABLE` 或 `CREATE DATABASE` 语句中指定的字母大小写存储在磁盘上,且名称比较时区分大小写。 - - Windows 系统中该值为 `1`,表示表名按照小写字母存储在磁盘上,名称比较时不区分大小写。MySQL 在存储和查询时将所有表名转换为小写。该行为也适用于数据库名称和表的别名。 - - macOS 系统中该值为 `2`,表示表名和数据库名按照在 `CREATE TABLE` 或 `CREATE DATABASE` 语句中指定的字母大小写存储在磁盘上,但 MySQL 在查询时将它们转换为小写。名称比较时不区分大小写。 +TiDB 与 MySQL 5.7 和 MySQL 8.0 相比有默认值差异: -- `explicit_defaults_for_timestamp`: - + TiDB 默认:`ON`,且仅支持设置该值为 `ON`。 - + MySQL 5.7 默认:`OFF`。 - + MySQL 8.0 默认:`ON`。 +- 默认字符集: + - TiDB 的默认值是 `utf8mb4`。 + - MySQL 5.7 的默认值是 `latin1`。 + - MySQL 8.0 的默认值是 `utf8mb4`。 +- 默认排序规则: + - TiDB 的默认排序规则是 `utf8mb4_bin`。 + - MySQL 5.7 的默认排序规则是 `utf8mb4_general_ci`。 + - MySQL 8.0 的默认排序规则是 `utf8mb4_0900_ai_ci`。 +- 默认 SQL 模式: + - TiDB 的默认 SQL 模式包括这些模式:`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 的默认 SQL 模式: + - MySQL 5.7 中的默认 SQL 模式与 TiDB 相同。 + - MySQL 8.0 中的默认 SQL 模式包括这些模式:`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`。这意味着表和数据库名称按照 `CREATE TABLE` 或 `CREATE DATABASE` 语句中指定的字母大小写存储在磁盘上。名称比较区分大小写。 + - 在 Windows 上:`1`。这意味着表名以小写形式存储在磁盘上,名称比较不区分大小写。MySQL 在存储和查找时将所有表名转换为小写。这种行为也适用于数据库名称和表别名。 + - 在 macOS 上:`2`。这意味着表和数据库名称按照 `CREATE TABLE` 或 `CREATE DATABASE` 语句中指定的字母大小写存储在磁盘上,但 MySQL 在查找时将它们转换为小写。名称比较不区分大小写。 +- `explicit_defaults_for_timestamp` 的默认值: + - TiDB 中的默认值是 `ON`,目前仅支持 `ON`。 + - MySQL 默认值如下: + - MySQL 5.7:`OFF`。 + - MySQL 8.0:`ON`。 -### 日期时间处理的区别 +### 日期和时间 -TiDB 与 MySQL 在日期时间处理上有如下差异: +TiDB 支持命名时区,但有以下注意事项: -- TiDB 采用系统当前安装的所有时区规则进行计算(一般为 `tzdata` 包),不需要导入时区表数据就能使用所有时区名称,导入时区表数据不会修改计算规则。 ++ TiDB 使用系统中当前安装的所有时区规则进行计算,通常是 `tzdata` 包。这使得可以使用所有时区名称,而无需导入时区表数据。导入时区表数据不会改变计算规则。 ++ 目前,MySQL 默认使用本地时区,然后依赖系统内置的当前时区规则(例如,夏令时开始时)进行计算。如果不[导入时区表数据](https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html#time-zone-installation),MySQL 无法通过名称指定时区。 -- MySQL 默认使用本地时区,依赖于系统内置的当前的时区规则(例如什么时候开始夏令时等)进行计算;且在未[导入时区表数据](https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html#time-zone-installation)的情况下不能通过时区名称来指定时区。 +### 类型系统差异 -### 类型系统 +以下列类型被 MySQL 支持但**不**被 TiDB 支持: -MySQL 支持 `SQL_TSI_*`(包括 `SQL_TSI_MONTH`、`SQL_TSI_WEEK`、`SQL_TSI_DAY`、`SQL_TSI_HOUR`、`SQL_TSI_MINUTE` 和 `SQL_TSI_SECOND`,但不包括 `SQL_TSI_YEAR`),但 TiDB 不支持。 +- `SQL_TSI_*`(包括 SQL_TSI_MONTH、SQL_TSI_WEEK、SQL_TSI_DAY、SQL_TSI_HOUR、SQL_TSI_MINUTE 和 SQL_TSI_SECOND,但不包括 SQL_TSI_YEAR) -### 正则函数 +### 正则表达式 -关于 TiDB 中正则函数 `REGEXP_INSTR()`、`REGEXP_LIKE()`、`REGEXP_REPLACE()`、`REGEXP_SUBSTR()` 与 MySQL 的兼容情况,请参考[正则函数与 MySQL 的兼容性](/functions-and-operators/string-functions.md#正则函数与-mysql-的兼容性)。 +关于 TiDB 正则表达式与 MySQL 的兼容性信息,包括 `REGEXP_INSTR()`、`REGEXP_LIKE()`、`REGEXP_REPLACE()` 和 `REGEXP_SUBSTR()`,请参阅[正则表达式与 MySQL 的兼容性](/functions-and-operators/string-functions.md#regular-expression-compatibility-with-mysql)。 -### MySQL 弃用功能导致的不兼容问题 +### 由于弃用功能导致的不兼容性 -TiDB 不支持 MySQL 中标记为弃用的功能,包括: +TiDB 不实现 MySQL 中已弃用的特定功能,包括: -* 指定浮点类型的精度。MySQL 8.0 [弃用](https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)了此功能,建议改用 `DECIMAL` 类型。 -* `ZEROFILL` 属性。MySQL 8.0 [弃用](https://dev.mysql.com/doc/refman/8.0/en/numeric-type-attributes.html)了此功能,建议在业务应用中填充数字值。 +- 为浮点类型指定精度。MySQL 8.0 [弃用](https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)此功能,建议改用 `DECIMAL` 类型。 +- `ZEROFILL` 属性。MySQL 8.0 [弃用](https://dev.mysql.com/doc/refman/8.0/en/numeric-type-attributes.html)此功能,建议在应用程序中对数值进行填充。 -### `CREATE RESOURCE GROUP`,`DROP RESOURCE GROUP` 和 `ALTER RESOURCE GROUP` +### `CREATE RESOURCE GROUP`、`DROP RESOURCE GROUP` 和 `ALTER RESOURCE GROUP` 语句 -TiDB 资源组创建与修改语句的语法与 MySQL 官方不同,详情参见: +以下用于创建、修改和删除资源组的语句支持的参数与 MySQL 不同。详情请参阅以下文档: - [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) - [`DROP RESOURCE GROUP`](/sql-statements/sql-statement-drop-resource-group.md) diff --git a/mysql-schema/mysql-schema-user.md b/mysql-schema/mysql-schema-user.md index 53d290963129..e4a745e9f267 100644 --- a/mysql-schema/mysql-schema-user.md +++ b/mysql-schema/mysql-schema-user.md @@ -1,19 +1,19 @@ --- title: mysql.user -summary: 了解 `mysql` 系统表 `user`。 +summary: 了解 `mysql` 架构中的 `user` 表。 --- # `mysql.user` -`mysql.user` 表提供用户账户及其权限的信息。 +`mysql.user` 表提供了用户账户及其权限的信息。 -使用以下 SQL 语句查看 `mysql.user` 表的结构: +要查看 `mysql.user` 的结构,请使用以下 SQL 语句: ```sql DESC mysql.user; ``` -输出结果如下: +输出如下: ``` +------------------------+----------------------+------+------+-------------------+-------+ @@ -67,21 +67,44 @@ DESC mysql.user; 44 rows in set (0.00 sec) ``` -`mysql.user` 表包含多个字段,可分为三组: +`mysql.user` 表包含多个字段,可以分为三类: -* 账户相关字段: - * `Host`:指定 TiDB 用户账户的主机名。 - * `User`:指定 TiDB 用户账户的用户名。 -* 权限相关字段: + - 以 `_priv` 或 `_Priv` 结尾的字段定义授予用户账户的权限。例如,`Select_priv` 表示用户账户具有全局 `Select` 权限。更多信息,请参考 [TiDB 各操作需要的权限](/privilege-management.md#tidb-各操作需要的权限)。 +* 作用域: + * `Host`:指定 TiDB 账户的主机名。 + * `User`:指定 TiDB 账户的用户名。 +* 权限: -* 安全相关字段: - * `authentication_string` 和 `plugin`:`authentication_string` 存储用户账户的凭证。凭证根据 `plugin` 字段指定的认证插件进行验证。 + 以 `_priv` 或 `_Priv` 结尾的字段定义了授予用户账户的权限。例如,`Select_priv` 表示用户具有全局 `Select` 权限。更多信息,请参见[TiDB 操作所需权限](/privilege-management.md#privileges-required-for-tidb-operations)。 + +* 安全: + * `authentication_string` 和 `plugin`:`authentication_string` 存储用户账户的凭据。凭据的解释基于 `plugin` 字段中指定的认证插件。 * `Account_locked`:表示用户账户是否被锁定。 - * `Password_reuse_history` 和 `Password_reuse_time`:用于[密码重用策略](/password-management.md#密码重用策略)。 - * `User_attributes`:提供用户账户注释和用户账户属性信息。 + * `Password_reuse_history` 和 `Password_reuse_time`:用于[密码重用策略](/password-management.md#password-reuse-policy)。 + * `User_attributes`:提供用户注释和用户属性信息。 * `Token_issuer`:用于 [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) 认证插件。 - * `Password_expired`、`Password_last_changed` 和 `Password_lifetime`:用于[密码过期策略](/password-management.md#密码过期策略)。 + * `Password_expired`、`Password_last_changed` 和 `Password_lifetime`:用于[密码过期策略](/password-management.md#password-expiration-policy)。 + + + + + +* 作用域: + * `Host`:指定 TiDB 账户的主机名。 + * `User`:指定 TiDB 账户的用户名。 +* 权限: + + 以 `_priv` 或 `_Priv` 结尾的字段定义了授予用户账户的权限。例如,`Select_priv` 表示用户具有全局 `Select` 权限。更多信息,请参见[TiDB 操作所需权限](https://docs.pingcap.com/tidb/stable/privilege-management#privileges-required-for-tidb-operations)。 + +* 安全: + * `authentication_string` 和 `plugin`:`authentication_string` 存储用户账户的凭据。凭据的解释基于 `plugin` 字段中指定的认证插件。 + * `Account_locked`:表示用户账户是否被锁定。 + * `Password_reuse_history` 和 `Password_reuse_time`:用于[密码重用策略](https://docs.pingcap.com/tidb/stable/password-management#password-reuse-policy)。 + * `User_attributes`:提供用户注释和用户属性信息。 + * `Token_issuer`:用于 [`tidb_auth_token`](https://docs.pingcap.com/tidb/stable/security-compatibility-with-mysql#tidb_auth_token) 认证插件。 + * `Password_expired`、`Password_last_changed` 和 `Password_lifetime`:用于[密码过期策略](https://docs.pingcap.com/tidb/stable/password-management#password-expiration-policy)。 + + -虽然 TiDB `mysql.user` 表中的大多数字段也存在于 MySQL `mysql.user` 表中,但 `Token_issuer` 字段是 TiDB 特有的。 \ No newline at end of file +虽然 TiDB `mysql.user` 表中的大多数字段也存在于 MySQL `mysql.user` 表中,但 `Token_issuer` 字段是 TiDB 特有的。 diff --git a/mysql-schema/mysql-schema.md b/mysql-schema/mysql-schema.md index a0a0418e45f1..d0b599061e53 100644 --- a/mysql-schema/mysql-schema.md +++ b/mysql-schema/mysql-schema.md @@ -1,118 +1,136 @@ --- -title: mysql Schema +title: mysql 系统库 summary: 了解 TiDB 系统表。 --- -# `mysql` Schema +# `mysql` 系统库 -`mysql` 库里存储的是 TiDB 系统表。该设计类似于 MySQL 中的 `mysql` 库,其中 `mysql.user` 之类的表可以直接编辑。该库还包含许多 MySQL 的扩展表。 +`mysql` 系统库包含 TiDB 的系统表。其设计类似于 MySQL 中的 `mysql` 系统库,可以直接编辑如 `mysql.user` 等表。它还包含了一些 MySQL 的扩展表。 > **注意:** > -> 在大多数情况下,不建议直接使用 `INSERT`、`UPDATE` 或 `DELETE` 更改系统表的内容。而是建议使用 [`CREATE USER`](/sql-statements/sql-statement-create-user.md)、[`ALTER USER`](/sql-statements/sql-statement-alter-user.md)、[`DROP USER`](/sql-statements/sql-statement-drop-user.md)、[`GRANT`](/sql-statements/sql-statement-grant-privileges.md)、[`REVOKE`](/sql-statements/sql-statement-revoke-privileges.md) 和 [`SHOW CREATE USER`](/sql-statements/sql-statement-show-create-user.md) 等语句管理用户和权限。如果必须直接修改系统表,请使用 [`FLUSH PRIVILEGES`](/sql-statements/sql-statement-flush-privileges.md) 使更改生效。 +> 在大多数情况下,不建议使用 `INSERT`、`UPDATE` 或 `DELETE` 直接修改系统表的内容。相反,应使用 [`CREATE USER`](/sql-statements/sql-statement-create-user.md)、[`ALTER USER`](/sql-statements/sql-statement-alter-user.md)、[`DROP USER`](/sql-statements/sql-statement-drop-user.md)、[`GRANT`](/sql-statements/sql-statement-grant-privileges.md)、[`REVOKE`](/sql-statements/sql-statement-revoke-privileges.md) 和 [`SHOW CREATE USER`](/sql-statements/sql-statement-show-create-user.md) 等语句来管理用户和权限。如果必须直接修改系统表,请使用 [`FLUSH PRIVILEGES`](/sql-statements/sql-statement-flush-privileges.md) 使更改生效。 -## 权限系统表 +## 授权系统表 -这些系统表里面包含了用户账户以及相应的授权信息: +这些系统表包含用户账户及其权限的授权信息: -* [`user`](/mysql-schema/mysql-schema-user.md) 用户账户,全局权限,以及其它一些非权限的列 -* `db` 数据库级别的权限 -* `tables_priv` 表级的权限 -* `columns_priv` 列级的权限 -* `password_history` 记录密码更改历史 -* `default_roles` 默认启用的角色 -* `global_grants` 动态权限 -* `global_priv` 基于证书的认证信息 -* `role_edges` 角色之间的关系信息 +- [`user`](/mysql-schema/mysql-schema-user.md):用户账户、全局权限和其他非权限列 +- `db`:数据库级别权限 +- `tables_priv`:表级别权限 +- `columns_priv`:列级别权限 +- `password_history`:密码修改历史 +- `default_roles`:用户的默认角色 +- `global_grants`:动态权限 +- `global_priv`:基于证书的认证信息 +- `role_edges`:角色之间的关系 ## 集群状态系统表 -* `tidb` 用于记录 TiDB 的一些全局信息 +* `tidb` 表包含一些 TiDB 的全局信息: - * `bootstrapped` 用于记录 TiDB 集群是否已完成初始化,注意该值为只读,不可修改。 - * `tidb_server_version` 用于记录 TiDB 在初始化时的版本信息,注意该值为只读,不可修改。 - * `system_tz` 用于记录 TiDB 的系统时区 - * `new_collation_enabled` 用于记录 TiDB 是否开启了[新排序规则框架](/character-set-and-collation.md#新框架下的排序规则支持),注意该值为只读,不可修改。 + * `bootstrapped`:TiDB 集群是否已初始化。注意该值为只读,不可修改。 + * `tidb_server_version`:TiDB 初始化时的版本信息。注意该值为只读,不可修改。 + * `system_tz`:TiDB 的系统时区。 + * `new_collation_enabled`:TiDB 是否启用了[新的排序规则框架](/character-set-and-collation.md#new-framework-for-collations)。注意该值为只读,不可修改。 -## 服务端帮助信息系统表 +## 服务器端帮助系统表 -* `help_topic` 目前为空 +目前,`help_topic` 为空。 -## 统计信息相关系统表 +## 统计信息系统表 -* `stats_buckets` 统计信息的桶 -* `stats_histograms` 统计信息的直方图 -* `stats_top_n` 统计信息的 TopN -* `stats_meta` 表的元信息,比如总行数和修改数 -* `stats_extended` 扩展统计信息,比如列之间的顺序相关性 -* `stats_feedback` 统计信息的查询反馈 -* `stats_fm_sketch` 统计信息列的直方图 FMSketch 分布 -* `stats_table_locked` 被锁定的统计信息 -* `stats_meta_history` 历史统计信息中的元信息部分 -* `stats_history` 历史统计信息中的其它部分 -* `analyze_options` 各个表默认的 `analyze` 参数 -* `column_stats_usage` 列统计信息的使用情况 -* `analyze_jobs` 正在执行的统计信息收集任务以及过去 7 天内的历史任务记录 +- `stats_buckets`:统计信息的桶 +- `stats_histograms`:统计信息的直方图 +- `stats_top_n`:统计信息的 TopN +- `stats_meta`:表的元信息,如总行数和更新行数 +- `stats_extended`:扩展统计信息,如列之间的顺序相关性 +- `stats_feedback`:统计信息的查询反馈 +- `stats_fm_sketch`:统计信息列直方图的 FMSketch 分布 +- `stats_table_locked`:锁定统计信息的相关信息 +- `stats_meta_history`:历史统计信息中的元信息 +- `stats_history`:历史统计信息中的其他信息 +- `analyze_options`:每个表的默认 `analyze` 选项 +- `column_stats_usage`:列统计信息的使用情况 +- `analyze_jobs`:正在进行的统计信息收集任务和最近 7 天的历史任务记录 ## 执行计划相关系统表 -* `bind_info` 执行计划的绑定信息 -* `capture_plan_baselines_blacklist` 关于自动绑定执行计划对象的黑名单 +- `bind_info`:执行计划的绑定信息 +- `capture_plan_baselines_blacklist`:执行计划自动绑定的黑名单 ## PLAN REPLAYER 相关系统表 -* `plan_replayer_status` 存储用户注册的 [`PLAN REPLAYER CAPTURE`](/sql-plan-replayer.md#使用-plan-replayer-capture-功能) 抓取任务 -* `plan_replayer_task` 存储 [`PLAN REPLAYER CAPTURE`](/sql-plan-replayer.md#使用-plan-replayer-capture-功能) 抓取结果 +- `plan_replayer_status`:用户注册的 [`PLAN REPLAYER CAPTURE`](https://docs.pingcap.com/tidb/stable/sql-plan-replayer#use-plan-replayer-capture) 任务 +- `plan_replayer_task`:[`PLAN REPLAYER CAPTURE`](https://docs.pingcap.com/tidb/stable/sql-plan-replayer#use-plan-replayer-capture) 任务的结果 -## GC Worker 相关系统表 +## GC worker 系统表 -* `gc_delete_range` 需要被 GC worker 定期删除的 KV 范围段 -* `gc_delete_range_done` 已经被删除的 KV 范围段 +> **注意:** +> +> GC worker 系统表仅适用于 TiDB 自托管版本,在 [TiDB Cloud](https://docs.pingcap.com/tidbcloud/) 上不可用。 + +- `gc_delete_range`:待删除的 KV 范围 +- `gc_delete_range_done`:已删除的 KV 范围 -## 缓存表使用的系统表 +## 缓存表相关系统表 -* `table_cache_meta` 存储了缓存表的元信息 +- `table_cache_meta` 存储缓存表的元数据。 ## TTL 相关系统表 -* `tidb_ttl_table_status` 所有 TTL 表的上一次执行与正在执行的 TTL 任务 -* `tidb_ttl_task` 正在执行的 TTL 子任务 -* `tidb_ttl_job_history` 过去 90 天内 TTL 任务的执行历史 +* `tidb_ttl_table_status`:所有 TTL 表的已执行 TTL 任务和正在进行的 TTL 任务 +* `tidb_ttl_task`:当前正在进行的 TTL 子任务 +* `tidb_ttl_job_history`:最近 90 天的 TTL 任务执行历史 -## Runaway Queries 相关系统表 +## 失控查询相关系统表 -* `tidb_runaway_queries` 过去 7 天内所有识别到的 Runaway Queries 的历史记录 -* `tidb_runaway_watch` Runaway Queries 的监控列表 (Watch List) -* `tidb_runaway_watch_done` 被删除或者过期的 Runaway Queries 的监控列表 +* `tidb_runaway_queries`:过去 7 天内所有已识别的失控查询的历史记录 +* `tidb_runaway_watch`:失控查询的监视列表 +* `tidb_runaway_watch_done`:已删除或过期的失控查询监视列表 ## 元数据锁相关系统表 -* `tidb_mdl_view` 元数据锁的视图,可以用于查看当前阻塞的 DDL 的相关信息 -* `tidb_mdl_info` TiDB 内部用于同步各节点的元数据锁的相关信息 +* `tidb_mdl_view`:元数据锁的视图。可用于查看当前被阻塞的 DDL 语句信息 +* `tidb_mdl_info`:TiDB 内部用于跨节点同步元数据锁 + +## DDL 语句相关系统表 + +* `tidb_ddl_history`:DDL 语句的历史记录 +* `tidb_ddl_job`:TiDB 当前正在执行的 DDL 语句的元数据 +* `tidb_ddl_reorg`:TiDB 当前正在执行的物理 DDL 语句(如添加索引)的元数据 + +## TiDB 分布式执行框架 (DXF) 相关系统表 -## DDL 相关系统表 +* `dist_framework_meta`:分布式执行框架 (DXF) 任务调度器的元数据 +* `tidb_global_task`:当前 DXF 任务的元数据 +* `tidb_global_task_history`:历史 DXF 任务的元数据,包括成功和失败的任务 +* `tidb_background_subtask`:当前 DXF 子任务的元数据 +* `tidb_background_subtask_history`:历史 DXF 子任务的元数据 -* `tidb_ddl_history` 记录了 DDL 语句的历史记录 -* `tidb_ddl_job` TiDB 内部存放的正在执行的 DDL 的元数据,用于执行 DDL -* `tidb_ddl_reorg` TiDB 内部存放的正在执行的物理 DDL(例如加索引)的元数据,用于执行物理 DDL +## 资源控制相关系统表 -## 分布式执行框架相关系统表 +* `request_unit_by_group`:所有资源组消耗的资源单位 (RUs) 的历史记录 + +## 其他系统表 + + + +> **注意:** +> +> `tidb`、`expr_pushdown_blacklist`、`opt_rule_blacklist`、`table_cache_meta`、`tidb_import_jobs` 和 `tidb_timers` 系统表仅适用于 TiDB 自托管版本,在 [TiDB Cloud](https://docs.pingcap.com/tidbcloud/) 上不可用。 -* `dist_framework_meta` 存放分布式执行框架任务调度的元信息 -* `tidb_global_task` 存放当前分布式框架正在执行的任务元信息 -* `tidb_global_task_history` 存放分布式执行框架完成(成功或者失败)的任务元信息 -* `tidb_background_subtask` 存放当前正在执行的分布式执行框架任务的子任务元信息 -* `tidb_background_subtask_history` 存放历史的分布式执行框架任务的子任务元信息 +- `GLOBAL_VARIABLES`:全局系统变量表 +- `expr_pushdown_blacklist`:表达式下推的黑名单 +- `opt_rule_blacklist`:逻辑优化规则的黑名单 +- `tidb_import_jobs`:[`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 的作业信息 +- `tidb_timers`:内部定时器的元数据 +- `advisory_locks`:与[锁定函数](/functions-and-operators/locking-functions.md)相关的信息 -## 资源管控相关系统表 + -* `request_unit_by_group` 存放资源组 RU 消耗统计的历史记录 + -## 其它系统表 +- `GLOBAL_VARIABLES`:全局系统变量表 -* `GLOBAL_VARIABLES` 全局系统变量表 -* `expr_pushdown_blacklist` 表达式下推的黑名单 -* `opt_rule_blacklist` 逻辑优化规则的黑名单 -* `tidb_import_jobs` 记录 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 任务信息 -* `tidb_timers` 存储内部定时器的相关元信息 -* `advisory_locks` 存储[锁函数](/functions-and-operators/locking-functions.md)相关的信息 + diff --git a/non-transactional-dml.md b/non-transactional-dml.md index afee2fece7e0..14b6e23ee83d 100644 --- a/non-transactional-dml.md +++ b/non-transactional-dml.md @@ -1,15 +1,15 @@ --- title: 非事务 DML 语句 -summary: 以事务的原子性和隔离性为代价,将 DML 语句拆成多个语句依次执行,用以提升批量数据处理场景的稳定性和易用性。 +summary: 了解 TiDB 中的非事务 DML 语句。通过牺牲原子性和隔离性,将一个 DML 语句拆分为多个语句按顺序执行,从而提高批量数据处理场景下的稳定性和易用性。 --- # 非事务 DML 语句 -本文档介绍非事务 DML 语句的使用场景、使用方法、使用限制和使用该功能的常见问题。 +本文档介绍 TiDB 中非事务 DML 语句的使用场景、使用方法和限制。此外,还说明了实现原理和常见问题。 -非事务 DML 语句是将一个普通 DML 语句拆成多个 SQL 语句(即多个 batch)执行,以牺牲事务的原子性和隔离性为代价,增强批量数据处理场景下的性能和易用性。 +非事务 DML 语句是将一个 DML 语句拆分成多个 SQL 语句(即多个批次)按顺序执行。它以牺牲事务的原子性和隔离性为代价,提高了批量数据处理的性能和易用性。 -通常,对于消耗内存过多的大事务,你需要在应用中拆分 SQL 语句以绕过事务大小限制。非事务 DML 语句将这一过程集成到 TiDB 内核中,实现等价的效果。非事务 DML 语句的执行效果可以通过拆分 SQL 语句的结果来理解,`DRY RUN` 语法提供了预览拆分后语句的功能。 +通常,内存消耗较大的事务需要拆分成多个 SQL 语句以绕过事务大小限制。非事务 DML 语句将这个过程集成到 TiDB 内核中以实现相同的效果。通过拆分 SQL 语句来理解非事务 DML 语句的效果会很有帮助。可以使用 `DRY RUN` 语法来预览拆分后的语句。 非事务 DML 语句包括: @@ -18,41 +18,42 @@ summary: 以事务的原子性和隔离性为代价,将 DML 语句拆成多个 - `UPDATE` - `DELETE` -详细的语法介绍见 [`BATCH`](/sql-statements/sql-statement-batch.md)。 +详细语法请参见 [`BATCH`](/sql-statements/sql-statement-batch.md)。 > **注意:** > -> - 非事务 DML 语句不保证该语句的原子性和隔离性,不能认为它和原始 DML 语句等价。 -> - 在任意 DML 语句改写为非事务 DML 语句后,不应假设其行为与原来一致。 -> - 使用非事务 DML 前需要分析其拆分后的语句是否会互相影响。 +> - 非事务 DML 语句不保证语句的原子性和隔离性,且与原始 DML 语句不等价。 +> - 将 DML 语句重写为非事务 DML 语句后,不能假设其行为与原始语句一致。 +> - 在使用非事务 DML 之前,需要分析拆分后的语句是否会相互影响。 ## 使用场景 -在大批量的数据处理场景,用户经常需要对一大批数据执行相同的操作。如果直接使用一个 SQL 语句执行操作,很可能导致事务大小超过限制,而大事务会明显影响执行性能。 +在大数据处理场景中,你可能经常需要对大批量数据执行相同的操作。如果直接使用单个 SQL 语句执行操作,事务大小可能会超出限制并影响执行性能。 -批量数据处理操作往往和在线业务操作不具有时间或数据上的交集。没有并发操作时,隔离性是不必要的。如果将批量数据操作设计成幂等的,或者易于重试的,那么原子性也是不必要的。如果你的业务满足这两个条件,那么可以考虑使用非事务 DML 语句。 +批量数据处理通常与在线应用操作在时间或数据上没有重叠。当不存在并发操作时,隔离性(ACID 中的 I)是不必要的。如果批量数据操作是幂等的或容易重试,原子性也是不必要的。如果你的应用程序既不需要数据隔离也不需要原子性,可以考虑使用非事务 DML 语句。 -非事务 DML 语句用于在特定场景下绕过大事务的事务大小限制,用一条语句完成原本需要拆分成多个事务完成的任务,且执行效率更高,占用资源更少。 +非事务 DML 语句用于在某些场景下绕过大事务的大小限制。使用一条语句完成原本需要手动拆分事务的任务,具有更高的执行效率和更少的资源消耗。 -例如,对于一个删除过期数据的需求,在确保没有任何业务会访问过期数据时,适合使用非事务 DML 语句来提升删除性能。 +例如,要删除过期数据,如果你确保没有应用程序会访问过期数据,可以使用非事务 DML 语句来提高 `DELETE` 性能。 ## 前提条件 -要使用非事务 DML 语句,必须满足以下条件: - -- 确保该语句不需要原子性,即允许执行结果中,一部分行被修改,而一部分行没有被修改。 -- 确保该语句具有幂等性,或是做好准备根据错误信息对部分数据重试。如果系统变量 `tidb_redact_log = 1` 且 `tidb_nontransactional_ignore_error = 1`,则该语句必须是幂等的。否则语句部分失败时,无法准确定位失败的部分。 -- 确保该语句将要操作的数据没有其它并发的写入,即不被其它语句同时更新。否则可能出现漏写、多写、重复修改同一行等非预期的现象。 -- 确保该语句不会修改语句自身会读取的内容,否则后续的 batch 读到之前 batch 写入的内容,容易引起非预期的情况。 - - 在使用非事务 `INSERT INTO ... SELECT` 处理同一张表时,尽量不要在插入时修改拆分列,否则可能因为多个 batch 读取到同一行,导致重复插入: - - 不推荐使用 `BATCH ON test.t.id LIMIT 10000 INSERT INTO t SELECT id+1, value FROM t;` - - 推荐使用 `BATCH ON test.t.id LIMIT 10000 INSERT INTO t SELECT id, value FROM t;` - - 当 `id` 列具有 `AUTO_INCREMENT` 属性时,推荐使用 `BATCH ON test.t.id LIMIT 10000 INSERT INTO t(value) SELECT value FROM t;` - - 在使用非事务 `UPDATE`、`INSERT ... ON DUPLICATE KEY UPDATE`、`REPLACE INTO` 时,拆分列不应该在语句中更新: - - 例如,对于一条非事务 `UPDATE` 语句,拆分后的 SQL 依次执行,前一 batch 的修改提交后被后一 batch 读到,导致同一行数据被多次修改。 - - 这类语句不支持 `BATCH ON test.t.id LIMIT 10000 UPDATE t SET test.t.id = test.t.id-1;` - - 不推荐使用 `BATCH ON test.t.id LIMIT 1 INSERT INTO t SELECT id+1, value FROM t ON DUPLICATE KEY UPDATE id = id + 1;` - - 拆分列也不应该用于 Join key。例如,下面示例将拆分列 `test.t.id` 作为 Join key,导致一个非事务 `UPDATE` 语句多次更新同一行: +在使用非事务 DML 语句之前,请确保满足以下条件: + +- 语句不需要原子性,允许在执行结果中有些行被修改而有些行保持不变。 +- 语句是幂等的,或者你准备根据错误消息对部分数据进行重试。如果系统变量设置为 `tidb_redact_log = 1` 和 `tidb_nontransactional_ignore_error = 1`,则此语句必须是幂等的。否则,当语句部分失败时,无法准确定位失败的部分。 +- 要操作的数据没有其他并发写入,即同时不会被其他语句更新。否则,可能会出现漏写、错写、多次修改同一行等意外结果。 +- 语句不修改语句本身要读取的数据。否则,后续批次将读取到前一批次写入的数据,容易造成意外结果。 + + - 在非事务 `INSERT INTO ... SELECT` 语句中从同一个表中选择并修改时,避免修改分片列。否则,多个批次可能会读取同一行并多次插入数据: + - 不建议使用 `BATCH ON test.t.id LIMIT 10000 INSERT INTO t SELECT id+1, value FROM t;` + - 建议使用 `BATCH ON test.t.id LIMIT 10000 INSERT INTO t SELECT id, value FROM t;` + - 如果分片列 `id` 具有 `AUTO_INCREMENT` 属性,建议使用 `BATCH ON test.t.id LIMIT 10000 INSERT INTO t(value) SELECT value FROM t;` + - 避免在非事务 `UPDATE`、`INSERT ... ON DUPLICATE KEY UPDATE` 或 `REPLACE INTO` 语句中更新分片列: + - 例如,对于非事务 `UPDATE` 语句,拆分的 SQL 语句按顺序执行。前一批次的修改在提交后被下一批次读取,导致同一行数据被多次修改。 + - 这些语句不支持 `BATCH ON test.t.id LIMIT 10000 UPDATE t SET test.t.id = test.t.id-1;` + - 不建议使用 `BATCH ON test.t.id LIMIT 1 INSERT INTO t SELECT id+1, value FROM t ON DUPLICATE KEY UPDATE id = id + 1;` + - 分片列不应该用作 Join 键。例如,以下示例使用分片列 `test.t.id` 作为 Join 键,导致非事务 `UPDATE` 语句多次修改同一行: ```sql CREATE TABLE t(id int, v int, key(id)); @@ -63,25 +64,25 @@ summary: 以事务的原子性和隔离性为代价,将 DML 语句拆成多个 SELECT * FROM t2; -- (4, 1) (4, 2) (4, 4) ``` -- 确认该语句满足[使用限制](#使用限制)。 -- 不建议在该 DML 语句将要读写的表上同时进行并发的 DDL 操作。 +- 语句满足[限制条件](#限制条件)。 +- 不建议对该 DML 语句要读取或写入的表执行并发 DDL 操作。 > **警告:** > -> 如果同时开启了 `tidb_redact_log` 和 `tidb_nontransactional_ignore_error`,你可能无法完整得知每个 batch 的错误信息,无法只对失败的 batch 进行重试。因此,如果同时开启了这两个系统变量,该非事务 DML 语句必须是幂等的。 +> 如果同时启用 `tidb_redact_log` 和 `tidb_nontransactional_ignore_error`,你可能无法获得每个批次的完整错误信息,也无法仅重试失败的批次。因此,如果这两个系统变量都打开,非事务 DML 语句必须是幂等的。 ## 使用示例 ### 使用非事务 DML 语句 -以下部分通过示例说明非事务 DML 语句的使用方法: +以下各节通过示例说明非事务 DML 语句的使用: -创建一张表 `t`,表结构如下: +创建一个具有以下模式的表 `t`: {{< copyable "sql" >}} ```sql -CREATE TABLE t(id int, v int, key(id)); +CREATE TABLE t (id INT, v INT, KEY(id)); ``` ```sql @@ -93,19 +94,19 @@ Query OK, 0 rows affected {{< copyable "sql" >}} ```sql -INSERT INTO t VALUES (1,2),(2,3),(3,4),(4,5),(5,6); +INSERT INTO t VALUES (1, 2), (2, 3), (3, 4), (4, 5), (5, 6); ``` ```sql Query OK, 5 rows affected ``` -以下操作使用非事务 DML 语句,删除表 `t` 的 `v` 列上小于整数 6 的行。该语句将以 2 为 batch size,以 `id` 列为划分列,拆分为两个 SQL 语句执行。 +以下操作使用非事务 DML 语句删除表 `t` 的列 `v` 上小于整数 6 的行。此语句被拆分为两个 SQL 语句,批次大小为 2,按 `id` 列分片并执行。 {{< copyable "sql" >}} ```sql -BATCH ON id LIMIT 2 DELETE FROM t where v < 6; +BATCH ON id LIMIT 2 DELETE FROM t WHERE v < 6; ``` ```sql @@ -117,7 +118,7 @@ BATCH ON id LIMIT 2 DELETE FROM t where v < 6; 1 row in set ``` -查看非事务 DML 语句的删除结果。 +检查上述非事务 DML 语句的删除结果。 {{< copyable "sql" >}} @@ -134,20 +135,20 @@ SELECT * FROM t; 1 row in set ``` -以下示例说明多表 join 的使用方法。首先创建表 `t2` 并插入数据。 +以下示例说明如何使用多表连接。首先,创建表 `t2` 并插入数据: ```sql CREATE TABLE t2(id int, v int, key(id)); INSERT INTO t2 VALUES (1,1), (3,3), (5,5); ``` -然后进行涉及多表 join 的更新(表 `t` 和 `t2`)。需要注意的是,指定拆分列时需要完整的数据库名、表名和列名(`test.t._tidb_rowid`)。 +然后,通过连接表 `t` 和 `t2` 更新表 `t2` 的数据。注意需要指定分片列的完整数据库名、表名和列名(`test.t.id`): ```sql BATCH ON test.t._tidb_rowid LIMIT 1 UPDATE t JOIN t2 ON t.id = t2.id SET t2.id = t2.id+1; ``` -查看更新后表的数据: +查询结果: ```sql SELECT * FROM t2; @@ -163,14 +164,14 @@ SELECT * FROM t2; +----+---+ ``` -### 查看非事务 DML 语句的执行进度 +### 查看执行进度 -非事务 DML 语句执行过程中,可以通过 `SHOW PROCESSLIST` 查看执行进度,返回结果中的 `Time` 表示当前 batch 执行的耗时。日志、慢日志等也会记录每个拆分后的语句在整个非事务 DML 语句中的进度。例如: +在非事务 DML 语句执行期间,可以使用 `SHOW PROCESSLIST` 查看进度。返回结果中的 `Time` 字段表示当前批次执行的时间消耗。日志和慢日志也会记录非事务 DML 执行过程中每个拆分语句的进度。例如: {{< copyable "sql" >}} ```sql -show processlist; +SHOW PROCESSLIST; ``` ```sql @@ -182,17 +183,17 @@ show processlist; +------+------+--------------------+--------+---------+------+------------+----------------------------------------------------------------------------------------------------+ ``` -### 终止一个非事务 DML 语句 +### 终止非事务 DML 语句 -通过 `KILL TIDB ` 终止一个非事务语句时,TiDB 会取消当前正在执行的 batch 之后的所有 batch。执行结果信息需要从日志里获得。 +要终止非事务 DML 语句,可以使用 `KILL TIDB `。然后 TiDB 将取消当前正在执行的批次之后的所有批次。你可以从日志中获取执行结果。 -关于 `KILL TiDB` 的更多信息,参见 [`KILL`](/sql-statements/sql-statement-kill.md)。 +有关 `KILL TIDB` 的更多信息,请参见参考 [`KILL`](/sql-statements/sql-statement-kill.md)。 -### 查询非事务 DML 语句中划分 batch 的语句 +### 查询批次划分语句 -要查询非事务 DML 语句中用于划分 batch 的语句,你可在非事务 DML 语句中添加 `DRY RUN QUERY`。添加后,TiDB 不实际执行这个查询和后续的 DML 操作。 +在非事务 DML 语句执行期间,内部使用一个语句将 DML 语句划分为多个批次。要查询此批次划分语句,可以在此非事务 DML 语句中添加 `DRY RUN QUERY`。然后 TiDB 将不执行此查询和后续的 DML 操作。 -下面这条语句查询 `BATCH ON id LIMIT 2 DELETE FROM t WHERE v < 6` 这条非事务 DML 语句内用于划分 batch 的查询语句。 +以下语句查询执行 `BATCH ON id LIMIT 2 DELETE FROM t WHERE v < 6` 期间的批次划分语句: {{< copyable "sql" >}} @@ -209,14 +210,14 @@ BATCH ON id LIMIT 2 DRY RUN QUERY DELETE FROM t WHERE v < 6; 1 row in set ``` -### 查询非事务 DML 语句中首末 batch 对应的语句 +### 查询第一个和最后一个批次对应的语句 -要查询非事务 DML 语句中第一个和最后一个 batch 对应的实际 DML 语句,你可在语句中添加 `DRY RUN`。添加后,TiDB 只划分 batch,不执行这些 SQL 语句。因为 batch 数量可能很多,不显示全部 batch,只显示第一个和最后一个 batch。 +要查询非事务 DML 语句中第一个和最后一个批次对应的实际 DML 语句,可以在此非事务 DML 语句中添加 `DRY RUN`。然后,TiDB 只划分批次而不执行这些 SQL 语句。由于可能有很多批次,不显示所有批次,只显示第一个和最后一个。 {{< copyable "sql" >}} ```sql -BATCH ON id LIMIT 2 DRY RUN DELETE FROM t where v < 6; +BATCH ON id LIMIT 2 DRY RUN DELETE FROM t WHERE v < 6; ``` ```sql @@ -229,107 +230,107 @@ BATCH ON id LIMIT 2 DRY RUN DELETE FROM t where v < 6; 2 rows in set ``` -### 在非事务 DML 语句中使用 Optimizer Hint +### 使用优化器提示 -对于 `DELETE` 语句原本支持的 Optimizer Hint,非事务 `DELETE` 语句也同样支持,hint 位置与普通 `DELETE` 语句中的位置相同: +如果 `DELETE` 语句中原本支持优化器提示,则非事务 `DELETE` 语句中也支持优化器提示。提示的位置与普通 `DELETE` 语句中的位置相同: {{< copyable "sql" >}} ```sql -BATCH ON id LIMIT 2 DELETE /*+ USE_INDEX(t)*/ FROM t where v < 6; +BATCH ON id LIMIT 2 DELETE /*+ USE_INDEX(t)*/ FROM t WHERE v < 6; ``` ## 最佳实践 -建议按照以下步骤执行非事务 DML 语句: +要使用非事务 DML 语句,建议按以下步骤操作: -1. 选择合适的[划分列](#参数说明)。建议使用整数或字符串类型。 -2. 在非事务 DML 语句中添加 `DRY RUN QUERY`,手动执行查询,确认 DML 语句影响的数据范围是否大体正确。 -3. 在非事务 DML 语句中添加 `DRY RUN`,手动执行查询,检查拆分后的语句和执行计划。需要关注: +1. 选择合适的[分片列](#参数说明)。建议使用整数或字符串类型。 +2. 在非事务 DML 语句中添加 `DRY RUN QUERY`,手动执行查询,并确认 DML 语句影响的数据范围大致正确。 +3. 在非事务 DML 语句中添加 `DRY RUN`,手动执行查询,并检查拆分语句和执行计划。需要注意以下几点: - - 一条拆分后的语句是否有可能读到之前的语句执行写入的结果,否则容易造成异常现象。 - - 索引选择效率。 - - 由 TiDB 自动选择的拆分列是否可能会被修改。 + - 拆分语句是否能读取前一条语句写入的结果,这可能会导致异常。 + - 索引选择性。 + - TiDB 自动选择的分片列是否会被修改。 4. 执行非事务 DML 语句。 -5. 如果报错,从报错信息或日志中获取具体失败的数据范围,进行重试或手动处理。 +5. 如果报错,从错误消息或日志中获取具体失败的数据范围,重试或手动处理。 ## 参数说明 -| 参数 | 说明 | 默认值 | 是否必填 | 建议值 | +| 参数 | 说明 | 默认值 | 是否必需 | 建议值 | | :-- | :-- | :-- | :-- | :-- | -| 划分列 | 用于划分 batch 的列,例如以上非事务 DML 语句 `BATCH ON id LIMIT 2 DELETE FROM t WHERE v < 6` 中的 `id` 列 | TiDB 尝试自动选择(不建议) | 否 | 选择可以最高效地满足 `WHERE` 条件的列 | -| Batch size | 用于控制每个 batch 的大小,batch 即 DML 操作拆分成的 SQL 语句个数,例如以上非事务 DML 语句 `BATCH ON id LIMIT 2 DELETE FROM t WHERE v < 6` 中的 `LIMIT 2`。batch 数量越多,batch size 越小 | N/A | 是 | 1000~1000000,过小和过大都会导致性能下降 | +| 分片列 | 用于分片批次的列,例如上述非事务 DML 语句 `BATCH ON id LIMIT 2 DELETE FROM t WHERE v < 6` 中的 `id` 列。 | TiDB 尝试自动选择分片列(不推荐)。 | 否 | 选择能以最高效方式满足 `WHERE` 条件的列。 | +| 批次大小 | 用于控制每个批次的大小。批次数是 DML 操作被拆分成的 SQL 语句数,例如上述非事务 DML 语句 `BATCH ON id LIMIT 2 DELETE FROM t WHERE v < 6` 中的 `LIMIT 2`。批次越多,批次大小越小。 | 不适用 | 是 | 1000-1000000。批次太小或太大都会导致性能下降。 | -### 划分列的选择 +### 如何选择分片列 -非事务 DML 语句需要用一个列作为数据分批的标准,该列即为划分列。为获得更高的执行效率,划分列必须能够利用索引。不同的索引和划分列所导致的执行效率可能有数十倍的差别。选择划分列时,可以考虑以下建议: +非事务 DML 语句使用一列作为数据分批的依据,即分片列。为了提高执行效率,分片列需要使用索引。不同索引和分片列带来的执行效率可能相差几十倍。选择分片列时,请考虑以下建议: -- 当你对业务数据分布有一定了解时,根据 `WHERE` 条件,选择划分 batch 后,划分范围较小的列。 - - 在理想情况下,`WHERE` 条件可以利用划分列的索引,降低每个 batch 需要扫描的数据量。例如有一个交易表,记录了每一笔交易的开始和结束时间,你希望删除结束时间在一个月之前的所有交易记录。如果在交易的开始时间有索引,且已知交易的开始和结束时间通常相差不大,那么可以选择开始时间作为划分列。 - - 在不太理想的情况下:划分列的数据分布与 `WHERE` 条件完全无关,无法利用划分列的索引来减少数据扫描的范围。 -- 有聚簇索引时,建议用主键作为划分列,这样语句执行效率更高(包括 `INT` 主键和 `_tidb_rowid`)。 +- 如果你了解应用程序的数据分布,根据 `WHERE` 条件,选择分批后数据范围较小的列。 + - 理想情况下,`WHERE` 条件可以利用分片列的索引来减少每个批次需要扫描的数据量。例如,有一个记录每个事务开始和结束时间的事务表,你想删除所有结束时间在一个月之前的事务记录。如果事务的开始时间有索引,并且事务的开始和结束时间相对接近,那么可以选择开始时间列作为分片列。 + - 不太理想的情况是,分片列的数据分布与 `WHERE` 条件完全独立,分片列的索引不能用于减少数据扫描范围。 +- 当存在聚簇索引时,建议使用主键(包括 `INT` 主键和 `_tidb_rowid`)作为分片列,这样执行效率更高。 - 选择重复值较少的列。 -你可以不指定划分列,TiDB 默认会使用 handle 的第一列作为划分列。但如果聚簇索引主键的第一列是非事务 DML 语句不支持的数据类型(即 `ENUM`,`BIT`,`SET`,`JSON`),TiDB 会报错。你可根据业务需要选择合适的划分列。 +你也可以选择不指定分片列。然后,TiDB 将默认使用 `handle` 的第一列作为分片列。但如果聚簇索引的第一列是非事务 DML 语句不支持的数据类型(即 `ENUM`、`BIT`、`SET`、`JSON`),TiDB 将报错。你可以根据应用程序需求选择合适的分片列。 -### Batch size 的选择 +### 如何设置批次大小 -非事务 DML 语句中,batch size 越大,拆分出来的 SQL 语句越少,每个 SQL 语句执行起来越慢。最优的 batch size 依据 workload 而定。根据经验值,推荐从 50000 开始尝试。过小和过大的 batch size 都会导致执行效率下降。 +在非事务 DML 语句中,批次大小越大,拆分的 SQL 语句越少,每个 SQL 语句的执行速度越慢。最佳批次大小取决于工作负载。建议从 50000 开始。批次大小太小或太大都会导致执行效率降低。 -每个 batch 的信息存储在内存里,因此 batch 数量过多会显著增加内存消耗。这也是 batch size 不能过小的原因之一。非事务语句用于存储 batch 信息消耗的内存上限与 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 相同,超出这个限制时触发的操作由系统变量 [`tidb_mem_oom_action`](/system-variables.md#tidb_mem_oom_action-从-v610-版本开始引入) 控制。 +每个批次的信息存储在内存中,因此太多批次会显著增加内存消耗。这就解释了为什么批次大小不能太小。非事务语句存储批次信息消耗的内存上限与 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 相同,超过此限制时触发的操作由配置项 [`tidb_mem_oom_action`](/system-variables.md#tidb_mem_oom_action-new-in-v610) 决定。 -## 使用限制 +## 限制条件 -非事务 DML 语句的硬性限制,不满足这些条件时 TiDB 会报错。 +以下是非事务 DML 语句的硬性限制。如果不满足这些限制,TiDB 将报错。 -- DML 语句不能包含 `ORDER BY` 或 `LIMIT` 字句。 +- DML 语句不能包含 `ORDER BY` 或 `LIMIT` 子句。 - 不支持子查询或集合操作。 -- 用于拆分的列必须被索引。该索引可以是单列的索引,或是一个联合索引的第一列。 -- 必须在 [`autocommit`](/system-variables.md#autocommit) 模式中使用。 -- 不能在开启了 batch-dml 时使用。 -- 不能在设置了 [`tidb_snapshot`](/read-historical-data.md#操作流程) 时使用。 +- 分片列必须有索引。索引可以是单列索引,也可以是联合索引的第一列。 +- 必须在 [`autocommit`](/system-variables.md#autocommit) 模式下使用。 +- 启用 batch-dml 时不能使用。 +- 设置 [`tidb_snapshot`](/read-historical-data.md) 时不能使用。 - 不能与 `prepare` 语句一起使用。 -- 划分列不支持 `ENUM`,`BIT`,`SET`,`JSON` 类型。 -- 不支持用在[临时表](/temporary-tables.md)上。 -- 不支持[公共表表达式](/develop/dev-guide-use-common-table-expression.md)。 +- 不支持将 `ENUM`、`BIT`、`SET`、`JSON` 类型作为分片列。 +- 不支持[临时表](/temporary-tables.md)。 +- 不支持[公用表表达式](/develop/dev-guide-use-common-table-expression.md)。 -## 控制 batch 执行失败 +## 控制批次执行失败 -非事务 DML 语句不满足原子性,可能存在一些 batch 成功,一些 batch 失败的情况。系统变量 [`tidb_nontransactional_ignore_error`](/system-variables.md#tidb_nontransactional_ignore_error-从-v610-版本开始引入) 控制非事务 DML 语句处理错误的行为。 +非事务 DML 语句不满足原子性。有些批次可能成功,有些可能失败。系统变量 [`tidb_nontransactional_ignore_error`](/system-variables.md#tidb_nontransactional_ignore_error-new-in-v610) 控制非事务 DML 语句如何处理错误。 -一个例外是,如果第一个 batch 就执行失败,有很大概率是语句本身有错,此时整个非事务语句会直接返回一个错误。 +一个例外是,如果第一个批次失败,很可能是语句本身有错误。在这种情况下,整个非事务语句将直接返回错误。 -## 实现原理 +## 工作原理 -非事务 DML 语句的实现原理,是将原本需要在用户侧手动执行的 SQL 语句拆分工作内置为 TiDB 的一个功能,简化用户操作。要理解非事务 DML 语句的行为,可以将其想象成一个用户脚本进行了如下操作: +非事务 DML 语句的工作原理是将 SQL 语句的自动拆分构建到 TiDB 中。如果没有非事务 DML 语句,你需要手动拆分 SQL 语句。要理解非事务 DML 语句的行为,可以将其视为执行以下任务的用户脚本: -对于非事务 DML `BATCH ON $C$ LIMIT $N$ DELETE FROM ... WHERE $P$`,其中 $C$ 为用于拆分的列,$N$ 为 batch size,$P$ 为筛选条件。 +对于非事务 DML `BATCH ON $C$ LIMIT $N$ DELETE FROM ... WHERE $P$`,$C$ 是用于划分的列,$N$ 是批次大小,$P$ 是过滤条件。 -1. TiDB 根据原始语句的筛选条件 $P$,和指定的用于拆分的列 $C$,查询出所有满足 $P$ 的 $C$。对这些 $C$ 排序后按 $N$ 分成多个分组 $B_1 \dots B_k$。对所有 $B_i$,保留它的第一个和最后一个 $C$,记为 $S_i$ 和 $E_i$。这一步所执行的查询语句,可以通过 [`DRY RUN QUERY`](/non-transactional-dml.md#查询非事务-dml-语句中划分-batch-的语句) 查看。 -2. $B_i$ 所涉及的数据就是满足 $P_i$: $C$ BETWEEN $S_i$ AND $E_i$ 的一个子集。可以通过 $P_i$ 来缩小每个 batch 需要处理的数据范围。 -3. 对 $B_i$,将上面这个条件嵌入原始语句的 WHERE 条件,使其变为 WHERE ($P_i$) AND ($P$)。这一步的执行结果,可以通过 [`DRY RUN`](/non-transactional-dml.md#查询非事务-dml-语句中首末-batch-对应的语句) 查看。 -4. 对所有 batch,依次执行新的语句。收集每个分组的错误并合并,在所有分组结束后作为整个非事务 DML 语句的结果返回。 +1. 根据原始语句的过滤条件 $P$ 和指定的划分列 $C$,TiDB 查询所有满足 $P$ 的 $C$。TiDB 根据 $N$ 将这些 $C$ 分组为 $B_1 \dots B_k$。对于所有 $B_i$,TiDB 保留其第一个和最后一个 $C$ 作为 $S_i$ 和 $E_i$。可以通过 [`DRY RUN QUERY`](/non-transactional-dml.md#查询批次划分语句) 查看此步骤执行的查询语句。 +2. $B_i$ 涉及的数据是满足 $P_i$ 的子集:$C$ BETWEEN $S_i$ AND $E_i$。你可以使用 $P_i$ 缩小每个批次需要处理的数据范围。 +3. 对于 $B_i$,TiDB 将上述条件嵌入原始语句的 `WHERE` 条件中,使其成为 WHERE ($P_i$) AND ($P$)。可以通过 [`DRY RUN`](/non-transactional-dml.md#查询第一个和最后一个批次对应的语句) 查看此步骤的执行结果。 +4. 对于所有批次,按顺序执行新语句。收集并组合每个分组的错误,在所有分组完成后作为整个非事务 DML 语句的结果返回。 -## 与 batch-dml 的异同 +## 与 batch-dml 的比较 -batch-dml 是一种在 DML 语句执行期间将一个事务拆成多个事务提交的机制。 +batch-dml 是在执行 DML 语句期间将事务拆分为多个事务提交的机制。 > **注意:** > -> batch-dml 功能使用不当时,存在数据索引不一致风险。该功能已被废弃,因此不建议使用。 +> 不建议使用已弃用的 batch-dml。当 batch-dml 功能使用不当时,存在数据索引不一致的风险。 -非事务 DML 语句尚不能替代所有的 batch-dml 使用场景。它们的主要区别有: +非事务 DML 语句尚未替代所有 batch-dml 使用场景。它们的主要区别如下: -- 性能:在[划分效率](#划分列的选择)较高的情况下,非事务 DML 语句和 batch-dml 性能接近。在划分效率较低的情况下,非事务 DML 语句可能会明显慢于 batch-dml。 +- 性能:当[分片列](#如何选择分片列)高效时,非事务 DML 语句的性能接近 batch-dml。当分片列效率较低时,非事务 DML 语句的性能显著低于 batch-dml。 -- 稳定性:batch-dml 极易因为使用不当导致数据索引不一致问题。而非事务 DML 语句不会导致数据索引不一致问题。但使用不当时,非事务 DML 语句与原始语句不等价,应用可能观察到和预期不符的现象。详见[常见问题](#常见问题)。 +- 稳定性:batch-dml 由于使用不当容易导致数据索引不一致。非事务 DML 语句不会导致数据索引不一致。但是,当使用不当时,非事务 DML 语句与原始语句不等价,应用程序可能会观察到意外行为。详见[常见问题部分](#非事务-delete-有不等价于普通-delete-的异常行为)。 ## 常见问题 -### 执行多表 join 语句后,遇到 `Unknown column xxx in 'where clause'` 错误 +### 执行多表连接语句时出现 `Unknown column xxx in 'where clause'` 错误 -当拼接查询语句时,如果 `WHERE` 子句中的条件涉及到了[划分列](#参数说明)所在表以外的其它表,就会出现该错误。例如,以下 SQL 语句中,划分列为 `t2.id`,划分列所在的表为 `t2`,但 `WHERE` 子句中的条件涉及到了 `t2` 和 `t3`。 +当 `WHERE` 子句中连接的查询涉及除[分片列](#参数说明)定义表之外的其他表时,会出现此错误。例如,在以下 SQL 语句中,分片列是 `t2.id` 并在表 `t2` 中定义,但 `WHERE` 子句涉及表 `t2` 和 `t3`。 ```sql BATCH ON test.t2.id LIMIT 1 @@ -341,7 +342,7 @@ SELECT t2.id, t2.v, t3.id FROM t2, t3 WHERE t2.id = t3.id (1054, "Unknown column 't3.id' in 'where clause'") ``` -当遇到此错误时,你可以通过 `DRY RUN QUERY` 打印出查询语句来确认。例如: +如果出现错误,可以使用 `DRY RUN QUERY` 打印查询语句进行确认。例如: ```sql BATCH ON test.t2.id LIMIT 1 @@ -349,7 +350,7 @@ DRY RUN QUERY INSERT INTO t SELECT t2.id, t2.v, t3.id FROM t2, t3 WHERE t2.id = t3.id ``` -要避免该错误,可以尝试将 `WHERE` 子句中涉及其它表的条件移动到 `JOIN` 的 `ON` 条件中。例如: +要避免错误,可以将 `WHERE` 子句中与其他表相关的条件移到 `JOIN` 子句的 `ON` 条件中。例如: ```sql BATCH ON test.t2.id LIMIT 1 @@ -365,32 +366,44 @@ SELECT t2.id, t2.v, t3.id FROM t2 JOIN t3 ON t2.id = t3.id +----------------+---------------+ ``` -### 实际的 batch 大小和指定的 batch size 不一样 +### 实际批次大小与指定的批次大小不同 + +在非事务 DML 语句执行期间,最后一个批次要处理的数据大小可能小于指定的批次大小。 + +当**分片列中存在重复值**时,每个批次将包含该批次中分片列最后一个元素的所有重复值。因此,此批次中的行数可能大于指定的批次大小。 + +此外,当发生其他并发写入时,每个批次处理的行数可能与指定的批次大小不同。 + +### 执行时出现 `Failed to restore the delete statement, probably because of unsupported type of the shard column` 错误 + +分片列不支持 `ENUM`、`BIT`、`SET`、`JSON` 类型。尝试指定新的分片列。建议使用整数或字符串类型列。 + + -在非事务 DML 语句的执行过程中,最后一个 batch 处理的数据量可能会小于 batch size。 +如果在选择的分片列不是这些不支持的类型时出现错误,请从 PingCAP 或社区[获取支持](/support.md)。 -在**划分列有重复值**时,每个 batch 会将当前 batch 中划分列的最后一个元素的所有重复值全部加入当前 batch 中,因此这个 batch 的行数可能会多于 batch size。 + -另外,在有其它并发的数据写入时,也可能导致每个 batch 实际处理的行数和 batch size 不一致。 + -### 执行时出现报错 `Failed to restore the delete statement, probably because of unsupported type of the shard column` +如果在选择的分片列不是这些不支持的类型时出现错误,请[联系 TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 -划分列的类型暂时不支持 `ENUM`、`BIT`、`SET`、`JSON` 类型,请尝试重新指定一个划分列。推荐使用整数或字符串类型的列。如果划分列不是这些类型,请从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。 + -### 非事务 `DELETE` 出现和普通的 `DELETE` 不等价的“异常”行为 +### 非事务 `DELETE` 有不等价于普通 `DELETE` 的异常行为 -非事务 DML 语句和这个 DML 语句的原始形式并不等价,这可能是由以下原因导致的: +非事务 DML 语句与此 DML 语句的原始形式不等价,可能有以下原因: -- 有并发的其它写入。 -- 非事务 DML 语句修改了语句自身会读取的值。 -- 在每个 batch 上实际执行的 SQL 语句由于改变了 `WHERE` 条件,可能会导致执行计划以及表达式计算顺序不同,由此导致了执行结果不一样。 -- DML 语句中含有非确定性的操作。 +- 存在其他并发写入。 +- 非事务 DML 语句修改了语句本身将要读取的值。 +- 每个批次执行的 SQL 语句可能因为 `WHERE` 条件改变而导致不同的执行计划和表达式计算顺序。因此,执行结果可能与原始语句不同。 +- DML 语句包含非确定性操作。 -## 兼容信息 +## MySQL 兼容性 -非事务语句是 TiDB 独有的功能,与 MySQL 不兼容。 +非事务语句是 TiDB 特有的,与 MySQL 不兼容。 -## 探索更多 +## 另请参阅 -* [BATCH](/sql-statements/sql-statement-batch.md) 语法 -* [`tidb_nontransactional_ignore_error`](/system-variables.md#tidb_nontransactional_ignore_error-从-v610-版本开始引入) +* [`BATCH`](/sql-statements/sql-statement-batch.md) 语法 +* [`tidb_nontransactional_ignore_error`](/system-variables.md#tidb_nontransactional_ignore_error-new-in-v610) diff --git a/optimistic-transaction.md b/optimistic-transaction.md index b2b2a5327651..69c7bb431a9c 100644 --- a/optimistic-transaction.md +++ b/optimistic-transaction.md @@ -1,90 +1,90 @@ --- title: TiDB 乐观事务模型 -summary: 了解 TiDB 的乐观事务模型。 +summary: 了解 TiDB 中的乐观事务模型。 --- # TiDB 乐观事务模型 -乐观事务模型下,将修改冲突视为事务提交的一部分。因此并发事务不常修改同一行时,可以跳过获取行锁的过程进而提升性能。但是并发事务频繁修改同一行(冲突)时,乐观事务的性能可能低于[悲观事务](/pessimistic-transaction.md)。 +在乐观事务中,冲突检测是在事务提交时进行的。当并发事务不经常修改相同行时,这有助于提高性能,因为可以跳过获取行锁的过程。但在并发事务频繁修改相同行(发生冲突)的情况下,乐观事务的性能可能比[悲观事务](/pessimistic-transaction.md)差。 -启用乐观事务前,请确保应用程序可正确处理 `COMMIT` 语句可能返回的错误。如果不确定应用程序将会如何处理,建议改为使用悲观事务。 +在启用乐观事务之前,请确保你的应用程序能够正确处理 `COMMIT` 语句可能返回错误的情况。如果你不确定应用程序如何处理这种情况,建议改用悲观事务。 > **注意:** > -> 自 v3.0.8 开始,TiDB 集群默认使用[悲观事务模式](/pessimistic-transaction.md)。但如果从 3.0.7 及之前版本创建的集群升级到 3.0.8 及之后的版本,不会改变默认事务模式,即**只有新创建的集群才会默认使用悲观事务模式**。 +> 从 v3.0.8 开始,TiDB 默认使用[悲观事务模式](/pessimistic-transaction.md)。但是,如果你将集群从 v3.0.7 或更早版本升级到 v3.0.8 或更高版本,这不会影响你现有的集群。换句话说,**只有新创建的集群默认使用悲观事务模式**。 ## 乐观事务原理 -为支持分布式事务,TiDB 中乐观事务使用两阶段提交协议,流程如下: +为了支持分布式事务,TiDB 在乐观事务中采用两阶段提交(2PC)。具体过程如下: -![TiDB 中的两阶段提交](/media/2pc-in-tidb.png) +![TiDB 中的 2PC](/media/2pc-in-tidb.png) 1. 客户端开始一个事务。 - TiDB 从 PD 获取一个全局唯一递增的时间戳作为当前事务的唯一事务 ID,这里称为该事务的 `start_ts`。TiDB 实现了多版本并发控制 (MVCC),因此 `start_ts` 同时也作为该事务获取的数据库快照版本。该事务只能读到此 `start_ts` 版本可以读到的数据。 + TiDB 从 PD 获取一个时间戳(单调递增且全局唯一)作为当前事务的唯一事务 ID,称为 `start_ts`。TiDB 实现了多版本并发控制,因此 `start_ts` 也作为此事务获取的数据库快照的版本。这意味着该事务只能读取数据库在 `start_ts` 时刻的数据。 -2. 客户端发起读请求。 +2. 客户端发出读取请求。 - 1. TiDB 从 PD 获取数据路由信息,即数据具体存在哪个 TiKV 节点上。 - 2. TiDB 从 TiKV 获取 `start_ts` 版本下对应的数据。 + 1. TiDB 从 PD 接收路由信息(数据在 TiKV 节点间的分布情况)。 + 2. TiDB 从 TiKV 接收 `start_ts` 版本的数据。 -3. 客户端发起写请求。 +3. 客户端发出写入请求。 - TiDB 校验写入数据是否符合约束(如数据类型是否正确、是否符合非空约束等)。**校验通过的数据将存放在 TiDB 中该事务的私有内存里。** + TiDB 检查写入的数据是否满足约束(确保数据类型正确,满足 NOT NULL 约束)。**有效数据存储在 TiDB 中该事务的私有内存中**。 -4. 客户端发起 commit。 +4. 客户端发出提交请求。 -5. TiDB 开始两阶段提交,在保证事务原子性的前提下,进行数据持久化。 +5. TiDB 开始 2PC,并在保证事务原子性的同时将数据持久化到存储中。 - 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 收到两阶段提交成功的信息。 + 1. TiDB 从要写入的数据中选择一个主键(Primary Key)。 + 2. TiDB 从 PD 接收 Region 分布信息,并相应地按 Region 对所有键进行分组。 + 3. TiDB 向所有涉及的 TiKV 节点发送预写请求。然后,TiKV 检查是否存在冲突或过期版本。有效数据被锁定。 + 4. TiDB 接收预写阶段的所有响应,预写成功。 + 5. TiDB 从 PD 接收提交版本号并标记为 `commit_ts`。 + 6. TiDB 向主键(Primary Key)所在的 TiKV 节点发起第二次提交。TiKV 检查数据,并清理预写阶段遗留的锁。 + 7. TiDB 接收到报告第二阶段成功完成的消息。 -6. TiDB 向客户端返回事务提交成功的信息。 +6. TiDB 向客户端返回消息,通知事务成功提交。 -7. TiDB 异步清理本次事务遗留的锁信息。 +7. TiDB 异步清理此事务中遗留的锁。 -## 优缺点分析 +## 优点和缺点 -通过分析 TiDB 中事务的处理流程,可以发现 TiDB 事务有如下优点: +从上述 TiDB 事务过程可以看出,TiDB 事务具有以下优点: -* 实现原理简单,易于理解。 -* 基于单实例事务实现了跨节点事务。 -* 锁管理实现了去中心化。 +* 易于理解 +* 基于单行事务实现跨节点事务 +* 去中心化的锁管理 -但 TiDB 事务也存在以下缺点: +然而,TiDB 事务也有以下缺点: -* 两阶段提交使网络交互增多。 -* 需要一个中心化的分配时间戳服务。 -* 事务数据量过大时易导致内存暴涨。 +* 由于 2PC 导致的事务延迟 +* 需要中心化的时间戳分配服务 +* 当大量数据写入内存时可能发生 OOM(内存溢出) -## 事务的重试 +## 事务重试 > **注意:** > -> 从 v8.0.0 开始,[`tidb_disable_txn_auto_retry`](/system-variables.md#tidb_disable_txn_auto_retry) 被废弃,不再支持乐观事务的自动重试。推荐使用[悲观事务模式](/pessimistic-transaction.md)。如果使用乐观事务模式发生冲突,请在应用里捕获错误并重试。 +> 从 v8.0.0 开始,[`tidb_disable_txn_auto_retry`](/system-variables.md#tidb_disable_txn_auto_retry) 系统变量已弃用,TiDB 不再支持乐观事务的自动重试。建议使用[悲观事务模式](/pessimistic-transaction.md)。如果遇到乐观事务冲突,你可以在应用程序中捕获错误并重试事务。 -使用乐观事务模型时,在高冲突率的场景中,事务容易发生写写冲突而导致提交失败。MySQL 使用悲观事务模型,在执行写入类型的 SQL 语句的过程中进行加锁并且在 Repeatable Read 隔离级别下使用了当前读的机制,能够读取到最新的数据,所以提交时一般不会出现异常。为了降低应用改造难度,TiDB 提供了数据库内部自动重试机制。 +在乐观事务模型中,在高竞争场景下,事务可能因写-写冲突而提交失败。TiDB 默认使用乐观并发控制,而 MySQL 采用悲观并发控制。这意味着 MySQL 在执行写类型的 SQL 语句时添加锁,并且其可重复读隔离级别允许当前读,因此提交通常不会遇到异常。为了降低应用程序适配的难度,TiDB 提供了内部重试机制。 -### 重试机制 +### 自动重试 -当事务提交时,如果发现写写冲突,TiDB 内部重新执行包含写操作的 SQL 语句。你可以通过设置 `tidb_disable_txn_auto_retry = OFF` 开启自动重试,并通过 `tidb_retry_limit` 设置重试次数: +如果在事务提交时发生写-写冲突,TiDB 会自动重试包含写操作的 SQL 语句。你可以通过将 `tidb_disable_txn_auto_retry` 设置为 `OFF` 来启用自动重试,并通过配置 `tidb_retry_limit` 设置重试限制: ```toml -# 设置是否禁用自动重试,默认为 “on”,即不重试。 +# 是否禁用自动重试(默认为 "on") tidb_disable_txn_auto_retry = OFF -# 控制重试次数,默认为 “10”。只有自动重试启用时该参数才会生效。 -# 当 “tidb_retry_limit = 0” 时,也会禁用自动重试。 +# 设置最大重试次数(默认为 "10") +# 当 "tidb_retry_limit = 0" 时,自动重试完全禁用 tidb_retry_limit = 10 ``` -你也可以修改当前 Session 或 Global 的值: +你可以在会话级别或全局级别启用自动重试: -- Session 级别设置: +1. 会话级别: {{< copyable "sql" >}} @@ -98,7 +98,7 @@ tidb_retry_limit = 10 SET tidb_retry_limit = 10; ``` -- Global 级别设置: +2. 全局级别: {{< copyable "sql" >}} @@ -114,40 +114,35 @@ tidb_retry_limit = 10 > **注意:** > -> `tidb_retry_limit` 变量决定了事务重试的最大次数。当它被设置为 0 时,所有事务都不会自动重试,包括自动提交的单语句隐式事务。这是彻底禁用 TiDB 中自动重试机制的方法。禁用自动重试后,所有冲突的事务都会以最快的方式上报失败信息(包含 `try again later`)给应用层。 +> `tidb_retry_limit` 变量决定最大重试次数。当此变量设置为 `0` 时,所有事务都不会自动重试,包括自动提交的隐式单语句事务。这是在 TiDB 中完全禁用自动重试机制的方法。禁用自动重试后,所有冲突的事务都会以最快的方式向应用层报告失败(包括 `try again later` 消息)。 -### 重试的局限性 +### 重试的限制 -TiDB 默认不进行事务重试,因为重试事务可能会导致更新丢失,从而破坏[可重复读的隔离级别](/transaction-isolation-levels.md)。 +默认情况下,TiDB 不会重试事务,因为这可能导致更新丢失和破坏 [`REPEATABLE READ` 隔离](/transaction-isolation-levels.md)。 -事务重试的局限性与其原理有关。事务重试可概括为以下三个步骤: +原因可以从重试的过程中观察到: -1. 重新获取 `start_ts`。 -2. 重新执行包含写操作的 SQL 语句。 -3. 再次进行两阶段提交。 +1. 分配新的时间戳并标记为 `start_ts`。 +2. 重试包含写操作的 SQL 语句。 +3. 执行两阶段提交。 -第二步中,重试时仅重新执行包含写操作的 SQL 语句,并不涉及读操作的 SQL 语句。但是当前事务中读到数据的时间与事务真正开始的时间发生了变化,写入的版本变成了重试时获取的 `start_ts` 而非事务一开始时获取的 `start_ts`。因此,当事务中存在依赖查询结果来更新的语句时,重试将无法保证事务原本可重复读的隔离级别,最终可能导致结果与预期出现不一致。 +在步骤 2 中,TiDB 只重试包含写操作的 SQL 语句。但是,在重试期间,TiDB 接收新的版本号来标记事务的开始。这意味着 TiDB 使用新的 `start_ts` 版本的数据重试 SQL 语句。在这种情况下,如果事务使用其他查询结果更新数据,结果可能不一致,因为违反了 `REPEATABLE READ` 隔离。 -如果业务可以容忍事务重试导致的异常,或并不关注事务是否以可重复读的隔离级别来执行,则可以开启自动重试。 +如果你的应用程序可以容忍更新丢失,并且不需要 `REPEATABLE READ` 隔离一致性,你可以通过设置 `tidb_disable_txn_auto_retry = OFF` 来启用此功能。 ## 冲突检测 -作为一个分布式系统,TiDB 在内存中的冲突检测是在 TiKV 中进行,主要发生在 prewrite 阶段。因为 TiDB 集群是一个分布式系统,TiDB 实例本身无状态,实例之间无法感知到彼此的存在,也就无法确认自己的写入与别的 TiDB 实例是否存在冲突,所以会在 TiKV 这一层检测具体的数据是否有冲突。 +作为分布式数据库,TiDB 在 TiKV 层执行内存中的冲突检测,主要在预写阶段进行。TiDB 实例是无状态的,彼此不知道对方的存在,这意味着它们无法知道它们的写入是否在整个集群中产生冲突。因此,冲突检测在 TiKV 层执行。 -具体配置如下: +配置如下: ```toml -# scheduler 内置一个内存锁机制,防止同时对一个 Key 进行操作。 -# 每个 Key hash 到不同的 slot。(默认为 2048000) +# 控制槽位数量(默认为 "2048000") scheduler-concurrency = 2048000 ``` -此外,TiKV 支持监控等待 latch 的时间: +此外,TiKV 支持监控调度器中等待锁存器的时间。 -![Scheduler latch wait duration](/media/optimistic-transaction-metric.png) +![调度器锁存器等待时间](/media/optimistic-transaction-metric.png) -当 `Scheduler latch wait duration` 的值特别高时,说明大量时间消耗在等待锁的请求上。如果不存在底层写入慢的问题,基本上可以判断该段时间内冲突比较多。 - -## 更多阅读 - -- [Percolator 和 TiDB 事务算法](https://pingcap.com/blog-cn/percolator-and-txn/) +当 `Scheduler latch wait duration` 较高且没有慢写入时,可以安全地得出结论,此时存在许多写冲突。 diff --git a/optimizer-fix-controls.md b/optimizer-fix-controls.md index 017d9e9774ca..80ccd98538a1 100644 --- a/optimizer-fix-controls.md +++ b/optimizer-fix-controls.md @@ -1,91 +1,101 @@ --- -title: Optimizer Fix Controls -summary: 了解 Optimizer Fix Controls 以及如何使用 `tidb_opt_fix_control` 细粒度地控制 TiDB 优化器的行为。 +title: 优化器修复控制 +summary: 了解优化器修复控制功能以及如何使用 tidb_opt_fix_control 更细粒度地控制 TiDB 优化器。 --- -# Optimizer Fix Controls +# 优化器修复控制 -随着产品迭代演进,TiDB 优化器的行为会发生变化,进而生成更加合理的执行计划。但在某些特定场景下,新的行为可能会导致非预期结果。例如: +随着产品的迭代演进,TiDB 优化器的行为会发生变化,从而生成更合理的执行计划。然而,在某些特定场景下,新的行为可能会导致意外结果。例如: -- 部分行为的效果和场景相关。有的行为改变,能在大多数场景下带来改进,但可能在极少数场景下导致回退。 -- 有时,行为细节的变化和其导致的结果之间的关系十分复杂。即使是对某处行为细节的改进,也可能在整体上导致执行计划回退。 +- 某些行为的效果依赖于特定场景。对大多数场景有改进的变更可能会导致其他场景的性能回退。 +- 有时,行为细节的变化与其后果之间的关系非常复杂。某个行为的改进可能会导致整体性能回退。 -因此,TiDB 提供了 Optimizer Fix Controls 功能,允许用户通过设置一系列 Fix 控制 TiDB 优化器的行为细节。本文档介绍了 Optimizer Fix Controls 及其使用方法,并列举了当前 TiDB 支持调整的所有 Fix。 +因此,TiDB 提供了优化器修复控制功能,允许你通过设置一组修复项的值来对 TiDB 优化器行为进行细粒度控制。本文档描述了优化器修复控制功能及其使用方法,并列出了 TiDB 当前支持的所有优化器修复控制项。 -## `tidb_opt_fix_control` 介绍 +## `tidb_opt_fix_control` 简介 -从 TiDB v6.5.3 和 v7.1.0 开始,提供了 [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-从-v653-和-v710-版本开始引入) 系统变量来更细粒度地控制优化器的行为。 +从 v6.5.3 和 v7.1.0 开始,TiDB 提供了 [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710) 系统变量,用于更细粒度地控制优化器的行为。 -一个 Fix 是用于调整 TiDB 优化器中一处行为的控制项。它以一个数字编号表示,该数字编号对应一个 GitHub Issue,在 Issue 中会有对技术细节的描述。例如 Fix `44262` 对应 [Issue 44262](https://github.com/pingcap/tidb/issues/44262)。 +每个修复项都是一个控制项,用于调整 TiDB 优化器中针对特定目的的行为。它用一个数字表示,对应包含行为变更技术细节的 GitHub Issue。例如,对于修复项 `44262`,你可以在 [Issue 44262](https://github.com/pingcap/tidb/issues/44262) 中查看它控制的内容。 -`tidb_opt_fix_control` 支持设置多个 Fix,不同 Fix 之间使用逗号 (`,`) 分隔。格式形如 `"<#issue1>:,<#issue2>:,...,<#issueN>:"`,其中 `<#issueN>` 代表 Fix 编号。例如: +[`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710) 系统变量接受多个修复项作为一个值,用逗号(`,`)分隔。格式为 `"<#issue1>:,<#issue2>:,...,<#issueN>:"`,其中 `<#issueN>` 是修复项编号。例如: ```sql SET SESSION tidb_opt_fix_control = '44262:ON,44389:ON'; ``` -## Optimizer Fix Controls 参考 +## 优化器修复控制参考 -### [`33031`](https://github.com/pingcap/tidb/issues/33031) 从 v8.0.0 版本开始引入 +### [`33031`](https://github.com/pingcap/tidb/issues/33031) v8.0.0 新增 - 默认值:`OFF` -- 可选值:`ON`、`OFF` -- 是否允许对分区表进行计划缓存。如果设置为 `ON`,则 [Prepared 语句计划缓存](/sql-prepared-plan-cache.md)和[非 Prepared 语句计划缓存](/sql-non-prepared-plan-cache.md)都不会对[分区表](/partitioned-table.md)启用。 +- 可选值:`ON`,`OFF` +- 该变量控制是否允许对分区表使用计划缓存。如果设置为 `ON`,[预处理语句计划缓存](/sql-prepared-plan-cache.md)和[非预处理语句计划缓存](/sql-non-prepared-plan-cache.md)都不会对[分区表](/partitioned-table.md)启用。 -### [`44262`](https://github.com/pingcap/tidb/issues/44262) 从 v6.5.3 和 v7.2.0 版本开始引入 +### [`44262`](https://github.com/pingcap/tidb/issues/44262) v6.5.3 和 v7.2.0 新增 - 默认值:`OFF` -- 可选值:`ON`、`OFF` -- 是否允许在缺少 [GlobalStats](/statistics.md#收集动态裁剪模式下的分区表统计信息) 的情况下使用[动态裁剪模式](/partitioned-table.md#动态裁剪模式)访问分区表。 +- 可选值:`ON`,`OFF` +- 该变量控制在缺少 [GlobalStats](/statistics.md#collect-statistics-of-partitioned-tables-in-dynamic-pruning-mode) 时是否允许使用[动态裁剪模式](/partitioned-table.md#dynamic-pruning-mode)访问分区表。 -### [`44389`](https://github.com/pingcap/tidb/issues/44389) 从 v6.5.3 和 v7.2.0 版本开始引入 +### [`44389`](https://github.com/pingcap/tidb/issues/44389) v6.5.3 和 v7.2.0 新增 - 默认值:`OFF` -- 可选值:`ON`、`OFF` -- 对形如 `c = 10 and (a = 'xx' or (a = 'kk' and b = 1))` 的过滤条件,是否尝试为 `IndexRangeScan` 更加完整地构造扫描范围,即 `range`。 +- 可选值:`ON`,`OFF` +- 对于类似 `c = 10 and (a = 'xx' or (a = 'kk' and b = 1))` 的过滤条件,该变量控制是否尝试为 `IndexRangeScan` 构建更全面的扫描范围。 -### [`44823`](https://github.com/pingcap/tidb/issues/44823) 从 v7.3.0 版本开始引入 +### [`44823`](https://github.com/pingcap/tidb/issues/44823) v7.3.0 新增 - 默认值:`200` - 可选值:`[0, 2147483647]` -- 为了节省内存,对于参数个数超过此开关指定个数的查询,Plan Cache 将不会缓存。`0` 表示无限制。 +- 为了节省内存,计划缓存不会缓存参数数量超过该变量指定值的查询。`0` 表示无限制。 -### [`44830`](https://github.com/pingcap/tidb/issues/44830) 从 v6.5.7 和 v7.3.0 版本开始引入 +### [`44830`](https://github.com/pingcap/tidb/issues/44830) v6.5.7 和 v7.3.0 新增 - 默认值:`OFF` -- 可选值:`ON`、`OFF` -- 此开关控制是否让 Plan Cache 对在物理优化阶段形成的 `PointGet` 计划进行缓存。 +- 可选值:`ON`,`OFF` +- 该变量控制计划缓存是否允许缓存在物理优化阶段生成的带有 `PointGet` 算子的执行计划。 -### [`44855`](https://github.com/pingcap/tidb/issues/44855) 从 v6.5.4 和 v7.3.0 版本开始引入 +### [`44855`](https://github.com/pingcap/tidb/issues/44855) v6.5.4 和 v7.3.0 新增 - 默认值:`OFF` -- 可选值:`ON`、`OFF` -- 在某些场景下,当 `IndexJoin` 算子的 `Probe` 端包含 `Selection` 算子时,TiDB 会严重高估 `IndexScan` 的行数,导致在 `IndexJoin` 更好的时候选择了其它的执行计划。 -- TiDB 已经引入了缓解这类问题的改进逻辑。但是由于潜在的计划回退风险,该改进并没有被默认启用。 -- 此开关控制是否启用这个改进。 +- 可选值:`ON`,`OFF` +- 在某些场景下,当 `IndexJoin` 算子的 `Probe` 端包含 `Selection` 算子时,TiDB 会严重高估 `IndexScan` 的行数。这可能导致选择次优的查询计划而不是 `IndexJoin`。 +- 为了缓解这个问题,TiDB 引入了一项改进。但由于可能存在查询计划回退风险,该改进默认是禁用的。 +- 该变量控制是否启用上述改进。 -### [`45132`](https://github.com/pingcap/tidb/issues/45132) 从 v7.4.0 版本开始引入 +### [`45132`](https://github.com/pingcap/tidb/issues/45132) v7.4.0 新增 - 默认值:`1000` - 可选值:`[0, 2147483647]` -- 此开关控制优化器进行启发式访问路径选择的阈值。当某个访问路径(如 `Index_A`)的估算行数远小于其他访问路径时(默认为 `1000` 倍),优化器会跳过代价比较直接选择 `Index_A`。 -- `0` 表示关闭此启发式访问路径选择策略。 +- 该变量设置优化器选择访问路径的启发式策略阈值。如果某个访问路径(如 `Index_A`)的估算行数远小于其他访问路径(默认为 `1000` 倍),优化器会跳过成本比较直接选择 `Index_A`。 +- `0` 表示禁用该启发式策略。 -### [`45798`](https://github.com/pingcap/tidb/issues/45798) 从 v7.5.0 版本开始引入 +### [`45798`](https://github.com/pingcap/tidb/issues/45798) v7.5.0 新增 - 默认值:`ON` -- 可选值:`ON`、`OFF` -- 此开关控制是否允许 Plan Cache 缓存访问[生成列](/generated-columns.md)的执行计划。 +- 可选值:`ON`,`OFF` +- 该变量控制计划缓存是否允许缓存访问[生成列](/generated-columns.md)的执行计划。 -### [`46177`](https://github.com/pingcap/tidb/issues/46177) 从 v6.5.6、v7.1.3 和 v7.5.0 版本开始引入 +### [`46177`](https://github.com/pingcap/tidb/issues/46177) v6.5.6、v7.1.3 和 v7.5.0 新增 - 默认值:`OFF` -- 可选值:`ON`、`OFF` -- 此开关控制优化器在查询优化的过程中,找到非强制执行计划后,是否继续查找强制执行计划进行查询优化。 +- 可选值:`ON`,`OFF` +- 该变量控制优化器在找到非强制计划后是否继续探索强制计划。 -### [`52869`](https://github.com/pingcap/tidb/issues/52869) 从 v8.1.0 版本开始引入 +### [`52869`](https://github.com/pingcap/tidb/issues/52869) v8.1.0 新增 - 默认值:`OFF` -- 可选值:`ON`、`OFF` -- 如果查询有除了全表扫描以外的单索引扫描方式可以选择,优化器不会自动选择索引合并。详情请参考[用 EXPLAIN 查看索引合并的 SQL 执行计划](/explain-index-merge.md#示例)中的**注意**部分。 -- 打开此开关后,这个限制会被解除。解除此限制能让优化器在更多查询中自动选择索引合并,但也有可能忽略其他更好的执行计划,因此建议在解除此限制前针对实际场景进行充分测试,确保不会带来性能回退。 \ No newline at end of file +- 可选值:`ON`,`OFF` +- 如[使用索引合并的 Explain 语句](/explain-index-merge.md#examples)中的**注意**所述,如果优化器可以为查询计划选择单索引扫描方法(而不是全表扫描),优化器将不会自动使用索引合并。 +- 你可以通过启用此修复控制来移除这个限制。移除此限制可以让优化器在更多查询中自动选择索引合并,但可能会导致优化器忽略最优执行计划。因此,建议在移除此限制之前,对实际使用场景进行充分测试,以确保不会导致性能回退。 + +### [`56318`](https://github.com/pingcap/tidb/issues/56318) + +> **注意:** +> +> 此功能仅适用于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless)。 + +- 默认值:`ON` +- 可选值:`ON`,`OFF` +- 该变量控制是否避免重复计算 `ORDER BY` 语句中使用的重表达式。 diff --git a/optimizer-hints.md b/optimizer-hints.md index e95a2d3c0c1d..1aac080fb689 100644 --- a/optimizer-hints.md +++ b/optimizer-hints.md @@ -1,19 +1,19 @@ --- -title: Optimizer Hints -summary: 介绍 TiDB 中 Optimizer Hints 的语法和不同生效范围的 Hint 的使用方法。 +title: 优化器提示 +summary: 使用优化器提示来影响查询执行计划 --- -# Optimizer Hints +# 优化器提示 -TiDB 支持 Optimizer Hints 语法,它基于 MySQL 5.7 中介绍的类似 comment 的语法,例如 `/*+ HINT_NAME(t1, t2) */`。当 TiDB 优化器选择的不是最优查询计划时,建议使用 Optimizer Hints。 +TiDB 支持优化器提示(Optimizer Hints),这些提示基于 MySQL 5.7 引入的注释语法。例如,一个常见的语法是 `/*+ HINT_NAME([t1_name [, t2_name] ...]) */`。建议在 TiDB 优化器选择了次优查询计划的情况下使用优化器提示。 -如果遇到 Hint 无法生效的情况,请参考[常见 Hint 不生效问题排查](#常见-hint-不生效问题排查)。 +如果遇到提示没有生效的情况,请参考[排查提示没有生效的常见问题](#排查提示没有生效的常见问题)。 ## 语法 -Optimizer Hints 不区分大小写,通过 `/*+ ... */` 注释的形式跟在 `SELECT`、`INSERT`、`UPDATE` 或 `DELETE` 关键字的后面。 +优化器提示不区分大小写,在 SQL 语句中紧跟在 `SELECT`、`INSERT`、`UPDATE` 或 `DELETE` 关键字后的 `/*+ ... */` 注释中指定。 -多个不同的 Hint 之间需用逗号隔开,例如: +多个提示可以用逗号分隔。例如,以下查询使用了三个不同的提示: {{< copyable "sql" >}} @@ -21,17 +21,17 @@ Optimizer Hints 不区分大小写,通过 `/*+ ... */` 注释的形式跟在 ` SELECT /*+ USE_INDEX(t1, idx1), HASH_AGG(), HASH_JOIN(t1) */ count(*) FROM t t1, t t2 WHERE t1.a = t2.b; ``` -可以通过 [`Explain`](/sql-statements/sql-statement-explain.md)/[`Explain Analyze`](/sql-statements/sql-statement-explain-analyze.md) 语句的输出,来查看 Optimizer Hints 对查询执行计划的影响。 +可以通过 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 和 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 的输出来观察优化器提示如何影响查询执行计划。 -如果 Optimizer Hints 包含语法错误或不完整,查询语句不会报错,而是按照没有 Optimizer Hints 的情况执行。如果 Hint 不适用于当前语句,TiDB 会返回 Warning,用户可以在查询结束后通过 `Show Warnings` 命令查看具体信息。 +不正确或不完整的提示不会导致语句错误。这是因为提示仅对查询执行具有建议(提示)语义。同样,如果提示不适用,TiDB 最多只会返回一个警告。 > **注意:** > -> 如果注释不是跟在指定的关键字后,会被当作是普通的 MySQL comment,注释不会生效,且不会上报 warning。 +> 如果注释不是紧跟在指定的关键字后面,它们将被视为普通的 MySQL 注释。这些注释不会生效,也不会报告警告。 -TiDB 目前支持的 Optimizer Hints 根据生效范围的不同可以划分为两类:第一类是在查询块范围生效的 Hint,例如 [`/*+ HASH_AGG() */`](#hash_agg);第二类是在整个查询范围生效的 Hint,例如 [`/*+ MEMORY_QUOTA(1024 MB)*/`](#memory_quotan)。 +目前,TiDB 支持两类提示,它们的作用范围不同。第一类提示在查询块范围内生效,例如 [`/*+ HASH_AGG() */`](#hash_agg);第二类提示在整个查询中生效,例如 [`/*+ MEMORY_QUOTA(1024 MB)*/`](#memory_quotan)。 -每条语句中每一个查询和子查询都对应着一个不同的查询块,每个查询块有自己对应的名字。以下面这条语句为例: +语句中的每个查询或子查询对应一个不同的查询块,每个查询块都有自己的名称。例如: {{< copyable "sql" >}} @@ -39,11 +39,13 @@ TiDB 目前支持的 Optimizer Hints 根据生效范围的不同可以划分为 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`。 +上述查询语句有三个查询块:最外层的 `SELECT` 对应第一个查询块,名称为 `sel_1`;两个 `SELECT` 子查询对应第二和第三个查询块,名称分别为 `sel_2` 和 `sel_3`。数字的顺序是基于 `SELECT` 从左到右出现的顺序。如果将第一个 `SELECT` 替换为 `DELETE` 或 `UPDATE`,则相应的查询块名称为 `del_1` 或 `upd_1`。 -## 查询块范围生效的 Hint +## 在查询块中生效的提示 -这类 Hint 可以跟在查询语句中**任意** `SELECT`、`UPDATE` 或 `DELETE` 关键字的后面。通过在 Hint 中使用查询块名字可以控制 Hint 的生效范围,以及准确标识查询中的每一个表(有可能表的名字或者别名相同),方便明确 Hint 的参数指向。若不显式地在 Hint 中指定查询块,Hint 默认作用于当前查询块。以如下查询为例: +这类提示可以跟在**任何** `SELECT`、`UPDATE` 或 `DELETE` 关键字后面。要控制提示的生效范围,可以在提示中使用查询块的名称。你可以通过准确标识查询中的每个表(以防表名或别名重复)来使提示参数更清晰。如果提示中没有指定查询块,则默认在当前块中生效。 + +例如: {{< copyable "sql" >}} @@ -51,17 +53,22 @@ SELECT * FROM (SELECT * FROM t) t1, (SELECT * FROM t) t2; 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` 表。 +这个提示在 `sel_1` 查询块中生效,其参数是 `sel_1` 中的 `t1` 和 `t3` 表(`sel_2` 中也包含一个 `t1` 表)。 + +如上所述,你可以通过以下方式在提示中指定查询块名称: -如上例所述,在 Hint 中使用查询块名字的方式有两种:第一种是作为 Hint 的第一个参数,与其他参数用空格隔开。除 `QB_NAME` 外,本节所列的所有 Hint 除自身明确列出的参数外都有一个隐藏的可选参数 `@QB_NAME`,通过使用这个参数可以指定该 Hint 的生效范围;第二种在 Hint 中使用查询块名字的方式是在参数中的某一个表名后面加 `@QB_NAME`,用以明确指出该参数是哪个查询块中的表。 +- 将查询块名称设置为提示的第一个参数,并用空格与其他参数分隔。除了 `QB_NAME` 外,本节列出的所有提示都有另一个可选的隐藏参数 `@QB_NAME`。通过使用此参数,你可以指定此提示的生效范围。 +- 在参数中的表名后附加 `@QB_NAME` 以明确指定该表属于哪个查询块。 > **注意:** > -> Hint 声明的位置必须在指定生效的查询块之中或之前,不能是在之后的查询块中,否则无法生效。 +> 你必须将提示放在提示生效的查询块中或之前。如果提示放在查询块之后,则无法生效。 ### QB_NAME -当查询语句是包含多层嵌套子查询的复杂语句时,识别某个查询块的序号和名字很可能会出错,Hint `QB_NAME` 可以方便我们使用查询块。`QB_NAME` 是 Query Block Name 的缩写,用于为某个查询块指定新的名字,同时查询块原本默认的名字依然有效。例如: +如果查询语句是包含多个嵌套查询的复杂语句,某个查询块的 ID 和名称可能会被错误识别。`QB_NAME` 提示可以帮助我们解决这个问题。 + +`QB_NAME` 表示 Query Block Name(查询块名称)。你可以为查询块指定一个新名称。指定的 `QB_NAME` 和之前的默认名称都是有效的。例如: {{< copyable "sql" >}} @@ -69,28 +76,28 @@ SELECT /*+ HASH_JOIN(@sel_1 t1@sel_1, t3) */ * FROM (SELECT t1.a, t1.b FROM t t1 SELECT /*+ QB_NAME(QB1) */ * FROM (SELECT * FROM t) t1, (SELECT * FROM t) t2; ``` -这条 Hint 将最外层 `SELECT` 查询块的命名为 `QB1`,此时 `QB1` 和默认名称 `sel_1` 对于这个查询块来说都是有效的。 +这个提示将外层 `SELECT` 查询块的名称指定为 `QB1`,这使得 `QB1` 和默认名称 `sel_1` 对该查询块都有效。 > **注意:** > -> 上述例子中,如果指定的 `QB_NAME` 为 `sel_2`,并且不给原本 `sel_2` 对应的第二个查询块指定新的 `QB_NAME`,则第二个查询块的默认名字 `sel_2` 会失效。 +> 在上面的例子中,如果提示将 `QB_NAME` 指定为 `sel_2` 并且没有为原来的第二个 `SELECT` 查询块指定新的 `QB_NAME`,那么 `sel_2` 对第二个 `SELECT` 查询块来说就变成无效名称。 ### SET_VAR(VAR_NAME=VAR_VALUE) -`SET_VAR(VAR_NAME=VAR_VALUE)` 允许在语句执行期间以 Hint 形式临时修改会话级系统变量的值。当语句执行完成后,系统变量将在当前会话中自动恢复为原始值。通过这个 Hint 可以修改一部分与优化器、执行器相关的系统变量行为。支持通过 `SET_VAR(VAR_NAME=VAR_VALUE)` Hint 修改的系统变量请查看[系统变量](/system-variables.md)。 +你可以使用 `SET_VAR(VAR_NAME=VAR_VALUE)` 提示在语句执行期间临时修改系统变量的值。语句执行完成后,当前会话中系统变量的值会自动恢复为原始值。此提示可用于修改一些与优化器和执行器相关的系统变量。有关可以使用此提示修改的系统变量列表,请参考[系统变量](/system-variables.md)。 > **警告:** > -> 强烈建议不要利用此 Hint 修改没有明确支持的变量,这可能会引发不可预知的行为。 +> 强烈建议不要修改未明确支持的变量,因为这可能会导致不可预知的行为。 -下面是一个使用示例: +以下是一个示例: ```sql SELECT /*+ SET_VAR(MAX_EXECUTION_TIME=1234) */ @@MAX_EXECUTION_TIME; SELECT @@MAX_EXECUTION_TIME; ``` -执行上述 SQL,第一个查询返回的结果是 Hint 中设置的 `1234`,而不是变量 `MAX_EXECUTION_TIME` 的默认值。第二个查询会返回变量的默认值。 +执行上述 SQL 语句后,第一个查询返回提示中设置的值 `1234`,而不是 `MAX_EXECUTION_TIME` 的默认值。第二个查询返回变量的默认值。 ```sql +----------------------+ @@ -109,23 +116,21 @@ SELECT @@MAX_EXECUTION_TIME; ### MERGE_JOIN(t1_name [, tl_name ...]) -`MERGE_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Sort Merge Join 算法。这个算法通常会占用更少的内存,但执行时间会更久。当数据量太大,或系统内存不足时,建议尝试使用。例如: +`MERGE_JOIN(t1_name [, tl_name ...])` 提示告诉优化器对指定的表使用归并连接算法。通常,这个算法消耗的内存较少但处理时间较长。如果数据量非常大或系统内存不足,建议使用此提示。例如: {{< copyable "sql" >}} ```sql -SELECT /*+ MERGE_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; +select /*+ MERGE_JOIN(t1, t2) */ * from t1, t2 where t1.id = t2.id; ``` > **注意:** > -> `MERGE_JOIN` 的别名是 `TIDB_SMJ`,在 3.0.x 及之前版本仅支持使用该别名;之后的版本同时支持使用这两种名称,但推荐使用 `MERGE_JOIN`。 +> `TIDB_SMJ` 是 TiDB 3.0.x 及更早版本中 `MERGE_JOIN` 的别名。如果你使用这些版本,必须使用 `TIDB_SMJ(t1_name [, tl_name ...])` 语法作为提示。对于更新版本的 TiDB,`TIDB_SMJ` 和 `MERGE_JOIN` 都是有效的提示名称,但建议使用 `MERGE_JOIN`。 ### NO_MERGE_JOIN(t1_name [, tl_name ...]) -`NO_MERGE_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表不要使用 Sort Merge Join 算法。例如: - -{{< copyable "sql" >}} +`NO_MERGE_JOIN(t1_name [, tl_name ...])` 提示告诉优化器不对指定的表使用归并连接算法。例如: ```sql SELECT /*+ NO_MERGE_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -135,9 +140,9 @@ SELECT /*+ NO_MERGE_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; > **注意:** > -> 部分情况下 `INL_JOIN` Hint 可能无法生效,详情请参阅 [`INL_JOIN` Hint 不生效](#inl_join-hint-不生效)。 +> 在某些情况下,`INL_JOIN` 提示可能不会生效。更多信息,请参见 [`INL_JOIN` 提示不生效](#inl_join-提示不生效)。 -`INL_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Index Nested Loop Join 算法。这个算法可能会在某些场景更快,消耗更少系统资源,有的场景会更慢,消耗更多系统资源。对于外表经过 WHERE 条件过滤后结果集较小(小于 1 万行)的场景,可以尝试使用。例如: +`INL_JOIN(t1_name [, tl_name ...])` 提示告诉优化器对指定的表使用索引嵌套循环连接算法。在某些场景下,这个算法可能消耗更少的系统资源并且处理时间更短,但在其他场景下可能会产生相反的结果。如果外表经过 `WHERE` 条件过滤后的结果集少于 10,000 行,建议使用此提示。例如: {{< copyable "sql" >}} @@ -145,19 +150,17 @@ SELECT /*+ NO_MERGE_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; SELECT /*+ INL_JOIN(t1, t2) */ * FROM t1, t2, t3 WHERE t1.id = t2.id AND t2.id = t3.id; ``` -在上面的 SQL 中,`INL_JOIN(t1, t2)` 会提示优化器对 `t1` 和 `t2` 使用 Index Nested Loop Join 算法。注意它并不是指 `t1` 和 `t2` 之间使用 Index Nested Loop Join 算法,而是 `t1` 和 `t2` 分别与其他表 (`t3`) 之间使用 Index Nested Loop Join 算法。 +在上述 SQL 语句中,`INL_JOIN(t1, t2)` 提示告诉优化器对 `t1` 和 `t2` 使用索引嵌套循环连接算法。注意,这并不意味着在 `t1` 和 `t2` 之间使用索引嵌套循环连接算法。相反,该提示表示 `t1` 和 `t2` 各自与另一个表(`t3`)使用索引嵌套循环连接算法。 -`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()` 中给出的参数是创建查询计划时内表的候选表。例如,`INL_JOIN(t1)` 意味着 TiDB 只考虑使用 `t1` 作为内表来创建查询计划。如果候选表有别名,你必须使用别名作为 `INL_JOIN()` 的参数;如果没有别名,则使用表的原始名称作为参数。例如,在 `select /*+ INL_JOIN(t1) */ * from t t1, t t2 where t1.a = t2.b;` 查询中,你必须使用 `t` 表的别名 `t1` 或 `t2` 而不是 `t` 作为 `INL_JOIN()` 的参数。 > **注意:** > -> `INL_JOIN` 的别名是 `TIDB_INLJ`,在 3.0.x 及之前版本仅支持使用该别名;之后的版本同时支持使用这两种名称,但推荐使用 `INL_JOIN`。 +> `TIDB_INLJ` 是 TiDB 3.0.x 及更早版本中 `INL_JOIN` 的别名。如果你使用这些版本,必须使用 `TIDB_INLJ(t1_name [, tl_name ...])` 语法作为提示。对于更新版本的 TiDB,`TIDB_INLJ` 和 `INL_JOIN` 都是有效的提示名称,但建议使用 `INL_JOIN`。 ### NO_INDEX_JOIN(t1_name [, tl_name ...]) -`NO_INDEX_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表不要使用 Index Nested Loop Join 算法。例如: - -{{< copyable "sql" >}} +`NO_INDEX_JOIN(t1_name [, tl_name ...])` 提示告诉优化器不对指定的表使用索引嵌套循环连接算法。例如: ```sql SELECT /*+ NO_INDEX_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -165,39 +168,37 @@ SELECT /*+ NO_INDEX_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; ### 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_HASH_JOIN(t1_name [, tl_name])` 提示告诉优化器使用索引嵌套循环哈希连接算法。使用此算法的条件与使用索引嵌套循环连接算法的条件相同。两种算法的区别在于 `INL_JOIN` 在连接的内表上创建哈希表,而 `INL_HASH_JOIN` 在连接的外表上创建哈希表。`INL_HASH_JOIN` 对内存使用有固定限制,而 `INL_JOIN` 使用的内存取决于内表中匹配的行数。 ### NO_INDEX_HASH_JOIN(t1_name [, tl_name ...]) -`NO_INDEX_HASH_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表不要使用 Index Nested Loop Hash Join 算法。 +`NO_INDEX_HASH_JOIN(t1_name [, tl_name ...])` 提示告诉优化器不对指定的表使用索引嵌套循环哈希连接算法。 ### INL_MERGE_JOIN -`INL_MERGE_JOIN(t1_name [, tl_name])` 提示优化器使用 Index Nested Loop Merge Join 算法,该算法与 Index Nested Loop Join 使用条件完全一样。 +`INL_MERGE_JOIN(t1_name [, tl_name])` 提示告诉优化器使用索引嵌套循环归并连接算法。使用此算法的条件与使用索引嵌套循环连接算法的条件相同。 ### NO_INDEX_MERGE_JOIN(t1_name [, tl_name ...]) -`NO_INDEX_MERGE_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表不要使用 Index Nested Loop Merge Join 算法。 +`NO_INDEX_MERGE_JOIN(t1_name [, tl_name ...])` 提示告诉优化器不对指定的表使用索引嵌套循环归并连接算法。 ### HASH_JOIN(t1_name [, tl_name ...]) -`HASH_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Hash Join 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存。例如: +`HASH_JOIN(t1_name [, tl_name ...])` 提示告诉优化器对指定的表使用哈希连接算法。这个算法允许查询使用多个线程并发执行,从而实现更高的处理速度,但会消耗更多内存。例如: {{< copyable "sql" >}} ```sql -SELECT /*+ HASH_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; +select /*+ HASH_JOIN(t1, t2) */ * from t1, t2 where t1.id = t2.id; ``` > **注意:** > -> `HASH_JOIN` 的别名是 `TIDB_HJ`,在 3.0.x 及之前版本仅支持使用该别名;之后的版本同时支持使用这两种名称,推荐使用 `HASH_JOIN`。 +> `TIDB_HJ` 是 TiDB 3.0.x 及更早版本中 `HASH_JOIN` 的别名。如果你使用这些版本,必须使用 `TIDB_HJ(t1_name [, tl_name ...])` 语法作为提示。对于更新版本的 TiDB,`TIDB_HJ` 和 `HASH_JOIN` 都是有效的提示名称,但建议使用 `HASH_JOIN`。 ### NO_HASH_JOIN(t1_name [, tl_name ...]) -`NO_HASH_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表不要使用 Hash Join 算法。例如: - -{{< copyable "sql" >}} +`NO_HASH_JOIN(t1_name [, tl_name ...])` 提示告诉优化器不对指定的表使用哈希连接算法。例如: ```sql SELECT /*+ NO_HASH_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -205,7 +206,7 @@ SELECT /*+ NO_HASH_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; ### HASH_JOIN_BUILD(t1_name [, tl_name ...]) -`HASH_JOIN_BUILD(t1_name [, tl_name ...])` 提示优化器对指定表使用 Hash Join 算法,同时将指定表作为 Hash Join 算法的 Build 端,即用指定表来构建哈希表。例如: +`HASH_JOIN_BUILD(t1_name [, tl_name ...])` 提示告诉优化器在指定的表上使用哈希连接算法,并将这些表作为构建侧。这样,你可以使用特定的表构建哈希表。例如: ```sql SELECT /*+ HASH_JOIN_BUILD(t1) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -213,7 +214,7 @@ SELECT /*+ HASH_JOIN_BUILD(t1) */ * FROM t1, t2 WHERE t1.id = t2.id; ### HASH_JOIN_PROBE(t1_name [, tl_name ...]) -`HASH_JOIN_PROBE(t1_name [, tl_name ...])` 提示优化器对指定表使用 Hash Join 算法,同时将指定表作为 Hash Join 算法的探测(Probe)端,即用指定表作为探测端来执行 Hash Join 算法。例如: +`HASH_JOIN_PROBE(t1_name [, tl_name ...])` 提示告诉优化器在指定的表上使用哈希连接算法,并将这些表作为探测侧。这样,你可以使用特定的表作为探测侧执行哈希连接算法。例如: ```sql SELECT /*+ HASH_JOIN_PROBE(t2) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -221,16 +222,18 @@ SELECT /*+ HASH_JOIN_PROBE(t2) */ * FROM t1, t2 WHERE t1.id = t2.id; ### SEMI_JOIN_REWRITE() -`SEMI_JOIN_REWRITE()` 提示优化器将查询语句中的半连接 (Semi Join) 改写为普通的内连接。目前该 Hint 只作用于 `EXISTS` 子查询。 +`SEMI_JOIN_REWRITE()` 提示告诉优化器将半连接查询重写为普通连接查询。目前,此提示仅适用于 `EXISTS` 子查询。 -如果不使用该 Hint 进行改写,Semi Join 在选择 Hash Join 的执行方式时,只能够使用子查询构建哈希表,因此在子查询比外查询结果集大时,执行速度可能会不及预期。Semi Join 在选择 Index Join 的执行方式时,只能够使用外查询作为驱动表,因此在子查询比外查询结果集小时,执行速度可能会不及预期。 +如果不使用此提示重写查询,当选择哈希连接作为执行计划时,半连接查询只能使用子查询来构建哈希表。在这种情况下,当子查询的结果大于外部查询的结果时,执行速度可能会比预期慢。 -在使用了 `SEMI_JOIN_REWRITE()` 进行改写后,优化器便可以扩大选择范围,选择更好的执行方式。 +同样,当选择索引连接作为执行计划时,半连接查询只能使用外部查询作为驱动表。在这种情况下,当子查询的结果小于外部查询的结果时,执行速度可能会比预期慢。 + +当使用 `SEMI_JOIN_REWRITE()` 重写查询时,优化器可以扩大选择范围以选择更好的执行计划。 {{< copyable "sql" >}} ```sql --- 不使用 SEMI_JOIN_REWRITE() 进行改写 +-- 不使用 SEMI_JOIN_REWRITE() 重写查询。 EXPLAIN SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t1 WHERE t1.a = t.a); ``` @@ -249,7 +252,7 @@ EXPLAIN SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t1 WHERE t1.a = t.a); {{< copyable "sql" >}} ```sql --- 使用 SEMI_JOIN_REWRITE() 进行改写 +-- 使用 SEMI_JOIN_REWRITE() 重写查询。 EXPLAIN SELECT * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t1 WHERE t1.a = t.a); ``` @@ -267,11 +270,11 @@ EXPLAIN SELECT * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t +------------------------------+---------+-----------+------------------------+---------------------------------------------------------------------------------------------------------------+ ``` -在上述例子中可以看到,在使用了 Hint 之后,TiDB 可以选择由表 `t1` 作为驱动表的 IndexJoin 的执行方式。 +从上面的例子可以看出,当使用 `SEMI_JOIN_REWRITE()` 提示时,TiDB 可以基于驱动表 `t1` 选择 IndexJoin 的执行方式。 ### SHUFFLE_JOIN(t1_name [, tl_name ...]) -`SHUFFLE_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Shuffle Join 算法,该 Hint 只在 MPP 模式下生效。例如: +`SHUFFLE_JOIN(t1_name [, tl_name ...])` 提示告诉优化器在指定的表上使用 Shuffle Join 算法。此提示仅在 MPP 模式下生效。例如: ```sql SELECT /*+ SHUFFLE_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -279,12 +282,12 @@ SELECT /*+ SHUFFLE_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; > **注意:** > -> - 使用该 Hint 前,需要保证当前 TiDB 集群能够支持在查询中使用 TiFlash MPP 模式,具体细节见文档[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 -> - 该 Hint 能与 [`HASH_JOIN_BUILD` Hint](#hash_join_buildt1_name--tl_name-) 和 [`HASH_JOIN_PROBE` Hint](#hash_join_probet1_name--tl_name-) 组合使用,达到控制 Shuffle Join 算法的 Build 端和 Probe 端的作用。 +> - 在使用此提示之前,请确保当前 TiDB 集群可以在查询中支持使用 TiFlash MPP 模式。详情请参考[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 +> - 此提示可以与 [`HASH_JOIN_BUILD` 提示](#hash_join_buildt1_name--tl_name-) 和 [`HASH_JOIN_PROBE` 提示](#hash_join_probet1_name--tl_name-) 结合使用,以控制 Shuffle Join 算法的 Build 侧和 Probe 侧。 ### BROADCAST_JOIN(t1_name [, tl_name ...]) -`BROADCAST_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Broadcast Join 算法,该 Hint 只在 MPP 模式下生效。例如: +`BROADCAST_JOIN(t1_name [, tl_name ...])` 提示告诉优化器在指定的表上使用 Broadcast Join 算法。此提示仅在 MPP 模式下生效。例如: ```sql SELECT /*+ BROADCAST_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; @@ -292,16 +295,16 @@ SELECT /*+ BROADCAST_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; > **注意:** > -> - 使用该 Hint 前,需要保证当前 TiDB 集群能够支持在查询中使用 TiFlash MPP 模式,具体细节见文档[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 -> - 该 Hint 能与 [`HASH_JOIN_BUILD` Hint](#hash_join_buildt1_name--tl_name-) 和 [`HASH_JOIN_PROBE` Hint](#hash_join_probet1_name--tl_name-) 组合使用,达到控制 Broadcast Join 算法的 Build 端和 Probe 端的作用。 +> - 在使用此提示之前,请确保当前 TiDB 集群可以在查询中支持使用 TiFlash MPP 模式。详情请参考[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 +> - 此提示可以与 [`HASH_JOIN_BUILD` 提示](#hash_join_buildt1_name--tl_name-) 和 [`HASH_JOIN_PROBE` 提示](#hash_join_probet1_name--tl_name-) 结合使用,以控制 Broadcast Join 算法的 Build 侧和 Probe 侧。 ### NO_DECORRELATE() -`NO_DECORRELATE()` 提示优化器不要尝试解除指定查询块中对应子查询的关联。该 Hint 适用于包含关联列的 `EXISTS`、`IN`、`ANY`、`ALL`、`SOME` 和标量子查询,即关联子查询。 +`NO_DECORRELATE()` 提示告诉优化器不要尝试对指定查询块中的相关子查询进行去相关处理。此提示适用于包含相关列的 `EXISTS`、`IN`、`ANY`、`ALL`、`SOME` 子查询和标量子查询(即相关子查询)。 -将该 Hint 写在一个查询块中后,对于该子查询和其外部查询块之间的关联列,优化器将不再尝试解除关联,而是始终使用 Apply 算子来执行查询。 +当在查询块中使用此提示时,优化器将不会尝试对子查询和其外部查询块之间的相关列进行去相关处理,而是始终使用 Apply 运算符执行查询。 -默认情况下,TiDB 会尝试对关联子查询[解除关联](/correlated-subquery-optimization.md),以达到更高的执行效率。但是在[一部分场景](/correlated-subquery-optimization.md#限制)下,解除关联反而会降低执行效率。这种情况下,可以使用该 Hint 来人工提示优化器不要进行解除关联操作。例如: +默认情况下,TiDB 会尝试对相关子查询进行[去相关处理](/correlated-subquery-optimization.md)以实现更高的执行效率。但是,在[某些场景](/correlated-subquery-optimization.md#限制)下,去相关处理实际上可能会降低执行效率。在这种情况下,你可以使用此提示手动告诉优化器不要进行去相关处理。例如: {{< copyable "sql" >}} @@ -313,7 +316,7 @@ create table t2(a int, b int, index idx(b)); {{< copyable "sql" >}} ```sql --- 不使用 NO_DECORRELATE() +-- 不使用 NO_DECORRELATE()。 explain select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b); ``` @@ -333,12 +336,12 @@ explain select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1. +----------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------+ ``` -从以上执行计划中可以发现,优化器自动解除了关联。解除关联之后的执行计划不包含 Apply 算子,取而代之的是子查询和外部查询块之间的 Join 运算,而原本的带有关联列的过滤条件 `t2.b = t1.b` 也变成了一个普通的 join 条件。 +从上面的执行计划可以看出,优化器已经自动进行了去相关处理。去相关后的执行计划没有 Apply 运算符,而是在子查询和外部查询块之间有连接操作。原始的带有相关列的过滤条件(`t2.b = t1.b`)变成了普通的连接条件。 {{< copyable "sql" >}} ```sql --- 使用 NO_DECORRELATE() +-- 使用 NO_DECORRELATE()。 explain select * from t1 where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) from t2 where t2.b = t1.b); ``` @@ -359,31 +362,31 @@ explain select * from t1 where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) +------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ``` -从以上执行计划中可以发现,优化器没有解除关联。执行计划中包含 Apply 算子,而带有关联列的条件 `t2.b = t1.b` 仍然是访问 `t2` 表时的过滤条件。 +从上面的执行计划可以看出,优化器没有进行去相关处理。执行计划仍然包含 Apply 运算符。带有相关列的过滤条件(`t2.b = t1.b`)仍然是访问 `t2` 表时的过滤条件。 ### HASH_AGG() -`HASH_AGG()` 提示优化器对指定查询块中所有聚合函数使用 Hash Aggregation 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存。例如: +`HASH_AGG()` 提示告诉优化器在指定查询块中的所有聚合函数中使用哈希聚合算法。这个算法允许查询使用多个线程并发执行,从而实现更高的处理速度,但会消耗更多内存。例如: {{< copyable "sql" >}} ```sql -SELECT /*+ HASH_AGG() */ count(*) FROM t1, t2 WHERE t1.a > 10 GROUP BY t1.id; +select /*+ HASH_AGG() */ count(*) from t1, t2 where t1.a > 10 group by t1.id; ``` ### STREAM_AGG() -`STREAM_AGG()` 提示优化器对指定查询块中所有聚合函数使用 Stream Aggregation 算法。这个算法通常会占用更少的内存,但执行时间会更久。数据量太大,或系统内存不足时,建议尝试使用。例如: +`STREAM_AGG()` 提示告诉优化器在指定查询块中的所有聚合函数中使用流式聚合算法。通常,这个算法消耗的内存较少但处理时间较长。如果数据量非常大或系统内存不足,建议使用此提示。例如: {{< copyable "sql" >}} ```sql -SELECT /*+ STREAM_AGG() */ count(*) FROM t1, t2 WHERE t1.a > 10 GROUP BY t1.id; +select /*+ STREAM_AGG() */ count(*) from t1, t2 where t1.a > 10 group by t1.id; ``` ### MPP_1PHASE_AGG() -`MPP_1PHASE_AGG()` 提示优化器对指定查询块中所有聚合函数使用一阶段聚合算法,该 Hint 只在 MPP 模式下生效。例如: +`MPP_1PHASE_AGG()` 告诉优化器在指定查询块中的所有聚合函数中使用一阶段聚合算法。此提示仅在 MPP 模式下生效。例如: ```sql SELECT /*+ MPP_1PHASE_AGG() */ COUNT(*) FROM t1, t2 WHERE t1.a > 10 GROUP BY t1.id; @@ -391,11 +394,11 @@ SELECT /*+ MPP_1PHASE_AGG() */ COUNT(*) FROM t1, t2 WHERE t1.a > 10 GROUP BY t1. > **注意:** > -> 使用该 Hint 前,需要保证当前 TiDB 集群能够支持在查询中使用 TiFlash MPP 模式,具体细节见文档[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 +> 在使用此提示之前,请确保当前 TiDB 集群可以在查询中支持使用 TiFlash MPP 模式。详情请参考[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 ### MPP_2PHASE_AGG() -`MPP_2PHASE_AGG()` 提示优化器对指定查询块中所有聚合函数使用二阶段聚合算法,该 Hint 只在 MPP 模式下生效。例如: +`MPP_2PHASE_AGG()` 告诉优化器在指定查询块中的所有聚合函数中使用两阶段聚合算法。此提示仅在 MPP 模式下生效。例如: ```sql SELECT /*+ MPP_2PHASE_AGG() */ COUNT(*) FROM t1, t2 WHERE t1.a > 10 GROUP BY t1.id; @@ -403,13 +406,11 @@ SELECT /*+ MPP_2PHASE_AGG() */ COUNT(*) FROM t1, t2 WHERE t1.a > 10 GROUP BY t1. > **注意:** > -> 使用该 Hint 前,需要保证当前 TiDB 集群能够支持在查询中使用 TiFlash MPP 模式,具体细节见文档[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 +> 在使用此提示之前,请确保当前 TiDB 集群可以在查询中支持使用 TiFlash MPP 模式。详情请参考[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 ### USE_INDEX(t1_name, idx1_name [, idx2_name ...]) -`USE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示优化器对指定表仅使用给出的索引。 - -下面例子的效果等价于 `SELECT * FROM t t1 use index(idx1, idx2);`: +`USE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示告诉优化器仅使用指定的索引来访问指定的 `t1_name` 表。例如,应用以下提示的效果与执行 `select * from t t1 use index(idx1, idx2);` 语句相同。 {{< copyable "sql" >}} @@ -419,15 +420,15 @@ SELECT /*+ USE_INDEX(t1, idx1, idx2) */ * FROM t1; > **注意:** > -> 当该 Hint 中只指定表名,不指定索引名时,表示不考虑使用任何索引,而是选择全表扫。 +> 如果在此提示中只指定表名而不指定索引名,则执行时不会考虑任何索引而是扫描整个表。 ### FORCE_INDEX(t1_name, idx1_name [, idx2_name ...]) -`FORCE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示优化器对指定表仅使用给出的索引。 +`FORCE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示告诉优化器仅使用指定的索引。 -`FORCE_INDEX(t1_name, idx1_name [, idx2_name ...])` 的使用方法、作用和 `USE_INDEX(t1_name, idx1_name [, idx2_name ...])` 相同。 +`FORCE_INDEX(t1_name, idx1_name [, idx2_name ...])` 的用法和效果与 `USE_INDEX(t1_name, idx1_name [, idx2_name ...])` 相同。 -以下四个查询语句的效果相同: +以下 4 个查询具有相同的效果: {{< copyable "sql" >}} @@ -440,25 +441,23 @@ SELECT * FROM t force index(idx1); ### IGNORE_INDEX(t1_name, idx1_name [, idx2_name ...]) -`IGNORE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示优化器对指定表忽略给出的索引。 - -下面例子的效果等价于 `SELECT * FROM t t1 ignore index(idx1, idx2);`: +`IGNORE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示告诉优化器忽略指定 `t1_name` 表的指定索引。例如,应用以下提示的效果与执行 `select * from t t1 ignore index(idx1, idx2);` 语句相同。 {{< copyable "sql" >}} ```sql -SELECT /*+ IGNORE_INDEX(t1, idx1, idx2) */ * FROM t t1; +select /*+ IGNORE_INDEX(t1, idx1, idx2) */ * from t t1; ``` ### ORDER_INDEX(t1_name, idx1_name [, idx2_name ...]) -`ORDER_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示优化器对指定表仅使用给出的索引,并且按顺序读取指定的索引。 +`ORDER_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示告诉优化器仅使用指定的索引来访问指定的表,并按顺序读取指定的索引。 > **警告:** > -> 这个 hint 有可能会导致 SQL 语句报错,建议先进行测试。如果测试时发生报错,请移除该 Hint。如果测试时运行正常,则可以继续使用。 +> 此提示可能导致 SQL 语句执行失败。建议先进行测试。如果测试时出现错误,请移除该提示。如果测试正常运行,则可以继续使用。 -此 hint 通常应用在下面这种场景中: +此提示通常应用在以下场景: ```sql CREATE TABLE t(a INT, b INT, key(a), key(b)); @@ -476,19 +475,18 @@ EXPLAIN SELECT /*+ ORDER_INDEX(t, a) */ a FROM t ORDER BY a LIMIT 10; +----------------------------+---------+-----------+---------------------+-------------------------------+ ``` -优化器对该查询会生成两类计划:`Limit + IndexScan(keep order: true)` 和 `TopN + IndexScan(keep order: false)`,当使用了 `ORDER_INDEX` Hint,优化器会选择前一种按照顺序读取索引的计划。 +优化器为此查询生成两种类型的计划:`Limit + IndexScan(keep order: true)` 和 `TopN + IndexScan(keep order: false)`。当使用 `ORDER_INDEX` 提示时,优化器选择第一个按顺序读取索引的计划。 > **注意:** > -> - 如果查询本身并不需要按顺序读取索引,即在不使用 Hint 的前提下,优化器在任何情况下都不会生成按顺序读取索引的计划。此时,如果指定了 `ORDER_INDEX` Hint,会出现报错 `Can't find a proper physical plan for this query`,此时应考虑移除对应的 `ORDER_INDEX` Hint。 -> -> - 分区表上的索引无法支持按顺序读取,所以不应该对分区表及其相关的索引使用 `ORDER_INDEX` Hint。 +> - 如果查询本身不需要按顺序读取索引(即在没有提示的情况下,优化器在任何情况下都不会生成按顺序读取索引的计划),当使用 `ORDER_INDEX` 提示时,会出现 `Can't find a proper physical plan for this query` 错误。在这种情况下,你需要移除相应的 `ORDER_INDEX` 提示。 +> - 分区表上的索引无法按顺序读取,因此不要在分区表及其相关索引上使用 `ORDER_INDEX` 提示。 ### NO_ORDER_INDEX(t1_name, idx1_name [, idx2_name ...]) -`NO_ORDER_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示优化器对指定表仅使用给出的索引,并且不按顺序读取指定的索引。通常应用在下面这种场景中: +`NO_ORDER_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示告诉优化器仅使用指定的索引来访问指定的表,但不按顺序读取指定的索引。此提示通常应用在以下场景。 -以下示例中查询语句的效果等价于 `SELECT * FROM t t1 use index(idx1, idx2);`: +以下示例显示查询语句的效果等同于 `SELECT * FROM t t1 use index(idx1, idx2);`: ```sql CREATE TABLE t(a INT, b INT, key(a), key(b)); @@ -506,21 +504,21 @@ EXPLAIN SELECT /*+ NO_ORDER_INDEX(t, a) */ a FROM t ORDER BY a LIMIT 10; +----------------------------+----------+-----------+---------------------+--------------------------------+ ``` -和 `ORDER_INDEX` Hint 的示例相同,优化器对该查询会生成两类计划:`Limit + IndexScan(keep order: true)` 和 `TopN + IndexScan(keep order: false)`,当使用了 `NO_ORDER_INDEX` Hint,优化器会选择后一种不按照顺序读取索引的计划。 +与 `ORDER_INDEX` 提示的示例相同,优化器为此查询生成两种类型的计划:`Limit + IndexScan(keep order: true)` 和 `TopN + IndexScan(keep order: false)`。当使用 `NO_ORDER_INDEX` 提示时,优化器将选择后一个不按顺序读取索引的计划。 ### AGG_TO_COP() -`AGG_TO_COP()` 提示优化器将指定查询块中的聚合函数下推到 coprocessor。如果优化器没有下推某些适合下推的聚合函数,建议尝试使用。例如: +`AGG_TO_COP()` 提示告诉优化器将指定查询块中的聚合操作下推到 coprocessor。如果优化器没有下推某些适合下推的聚合函数,则建议使用此提示。例如: {{< copyable "sql" >}} ```sql -SELECT /*+ AGG_TO_COP() */ sum(t1.a) FROM t t1; +select /*+ AGG_TO_COP() */ sum(t1.a) from t t1; ``` ### LIMIT_TO_COP() -`LIMIT_TO_COP()` 提示优化器将指定查询块中的 `Limit` 和 `TopN` 算子下推到 coprocessor。优化器没有下推 `Limit` 或者 `TopN` 算子时建议尝试使用该提示。例如: +`LIMIT_TO_COP()` 提示告诉优化器将指定查询块中的 `Limit` 和 `TopN` 运算符下推到 coprocessor。如果优化器没有执行此类操作,建议使用此提示。例如: {{< copyable "sql" >}} @@ -530,21 +528,21 @@ SELECT /*+ LIMIT_TO_COP() */ * FROM t WHERE a = 1 AND b > 10 ORDER BY c LIMIT 1; ### 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`。如果为表指定了别名,就只能使用表的别名作为 `READ_FROM_STORAGE()` 的参数;如果没有指定别名,则用表的本名作为其参数。例如: +`READ_FROM_STORAGE(TIFLASH[t1_name [, tl_name ...]], TIKV[t2_name [, tl_name ...]])` 提示告诉优化器从指定的存储引擎读取指定的表。目前,此提示支持两个存储引擎参数 - `TIKV` 和 `TIFLASH`。如果表有别名,使用别名作为 `READ_FROM_STORAGE()` 的参数;如果表没有别名,使用表的原始名称作为参数。例如: {{< copyable "sql" >}} ```sql -SELECT /*+ READ_FROM_STORAGE(TIFLASH[t1], TIKV[t2]) */ t1.a FROM t t1, t t2 WHERE t1.a = t2.a; +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 ...])` 提示优化器通过索引合并的方式来访问指定的表。索引合并分为并集型和交集型两种类型,详情参见[用 EXPLAIN 查看索引合并的 SQL 执行计划](/explain-index-merge.md)。 +`USE_INDEX_MERGE(t1_name, idx1_name [, idx2_name ...])` 提示告诉优化器使用索引合并方法访问指定的表。索引合并有两种类型:交集类型和并集类型。详情请参见[使用索引合并的 Explain 语句](/explain-index-merge.md)。 -若显式地指定索引列表,优化器会尝试在索引列表中选取索引来构建索引合并。若不指定索引列表,优化器会尝试在所有可用的索引中选取索引来构建索引合并。 +如果你明确指定了索引列表,TiDB 会从列表中选择索引来构建索引合并;如果你没有指定索引列表,TiDB 会从所有可用的索引中选择索引来构建索引合并。 -对于交集型索引合并,索引列表是必选参数。对于并集型索引合并,Hint 中的索引列表为可选参数。示例如下。 +对于交集类型的索引合并,提示中给出的索引列表是必需的参数。对于并集类型的索引合并,提示中给出的索引列表是可选参数。请参见以下示例。 {{< copyable "sql" >}} @@ -552,15 +550,15 @@ SELECT /*+ READ_FROM_STORAGE(TIFLASH[t1], TIKV[t2]) */ t1.a FROM t t1, t t2 WHER SELECT /*+ USE_INDEX_MERGE(t1, idx_a, idx_b, idx_c) */ * FROM t1 WHERE t1.a > 10 OR t1.b > 10; ``` -当对同一张表有多个 `USE_INDEX_MERGE` Hint 时,优化器会从这些 Hint 指定的索引列表的并集中尝试选取索引。 +当对同一个表使用多个 `USE_INDEX_MERGE` 提示时,优化器会尝试从这些提示指定的索引集合的并集中选择索引。 > **注意:** > -> `USE_INDEX_MERGE` 的参数是索引名,而不是列名。对于主键索引,索引名为 `primary`。 +> `USE_INDEX_MERGE` 的参数指的是索引名称,而不是列名。主键的索引名称是 `primary`。 ### LEADING(t1_name [, tl_name ...]) -`LEADING(t1_name [, tl_name ...])` 提示优化器在生成多表连接的执行计划时,按照 hint 中表名出现的顺序来确定多表连接的顺序。例如: +`LEADING(t1_name [, tl_name ...])` 提示提醒优化器在生成执行计划时,根据提示中指定的表名顺序来确定多表连接的顺序。例如: {{< copyable "sql" >}} @@ -568,26 +566,24 @@ SELECT /*+ USE_INDEX_MERGE(t1, idx_a, idx_b, idx_c) */ * FROM t1 WHERE t1.a > 10 SELECT /*+ LEADING(t1, t2) */ * FROM t1, t2, t3 WHERE t1.id = t2.id and t2.id = t3.id; ``` -在以上多表连接查询语句中,`LEADING()` 中表出现的顺序决定了优化器将会先对表 `t1` 和 `t2` 进行连接,再将结果和表 `t3` 进行连接。该 hint 比 [`STRAIGHT_JOIN`](#straight_join) 更为通用。 +在上述多表连接查询中,连接顺序由 `LEADING()` 提示中指定的表名顺序决定。优化器将首先连接 `t1` 和 `t2`,然后将结果与 `t3` 连接。这个提示比 [`STRAIGHT_JOIN`](#straight_join) 更通用。 -`LEADING` hint 在以下情况下会失效: +在以下情况下,`LEADING` 提示不会生效: -+ 指定了多个 `LEADING` hint -+ `LEADING` hint 中指定的表名不存在 -+ `LEADING` hint 中指定了重复的表名 -+ 优化器无法按照 `LEADING` hint 指定的顺序进行表连接 -+ 已经存在 `straight_join()` hint -+ 查询语句中包含 outer join 且同时指定了包含笛卡尔积的情况 ++ 指定了多个 `LEADING` 提示。 ++ `LEADING` 提示中指定的表名不存在。 ++ `LEADING` 提示中指定了重复的表名。 ++ 优化器无法按照 `LEADING` 提示指定的顺序执行连接操作。 ++ 已存在 `straight_join()` 提示。 ++ 查询同时包含外连接和笛卡尔积。 -当出现了上述失效的情况,会输出 warning 警告。 +在上述情况下,会生成一个警告。 ```sql --- 指定了多个 LEADING hint - +-- 指定了多个 `LEADING` 提示。 SELECT /*+ LEADING(t1, t2) LEADING(t3) */ * FROM t1, t2, t3 WHERE t1.id = t2.id and t2.id = t3.id; --- 通过执行 `show warnings` 了解具体产生冲突的原因 - +-- 要了解 `LEADING` 提示为什么没有生效,执行 `show warnings`。 SHOW WARNINGS; ``` @@ -601,229 +597,223 @@ SHOW WARNINGS; > **注意:** > -> 如果查询语句中包含了 outer join,你只能在 hint 中指定可以用于交换连接顺序的表。如果 hint 中存在不能用于交换的表,则该 hint 会失效。例如在 `SELECT * FROM t1 LEFT JOIN (t2 JOIN t3 JOIN t4) ON t1.a = t2.a;` 中,如果想要控制 `t2`、`t3`、`t4` 表的连接顺序,那么在使用 `LEADING` hint 时,hint 中不能出现 `t1` 表。 +> 如果查询语句包含外连接,在提示中你只能指定那些连接顺序可以交换的表。如果提示中有一个表的连接顺序不能交换,则提示将无效。例如,在 `SELECT * FROM t1 LEFT JOIN (t2 JOIN t3 JOIN t4) ON t1.a = t2.a;` 中,如果你想控制 `t2`、`t3` 和 `t4` 表的连接顺序,你不能在 `LEADING` 提示中指定 `t1`。 ### MERGE() -在含有[公共表表达式](/develop/dev-guide-use-common-table-expression.md)的查询中使用 `MERGE()` hint,可关闭对当前子查询的物化过程,并将内部查询的内联展开到外部查询。该 hint 适用于非递归的公共表表达式查询,在某些场景下,使用该 hint 会比默认分配一块临时空间的语句执行效率更高。例如将外部查询的条件下推或在嵌套的 CTE 查询中: - -{{< copyable "sql" >}} +在带有公共表表达式(CTE)的查询中使用 `MERGE()` 提示可以禁用子查询的物化,并将子查询内联展开到 CTE 中。此提示仅适用于非递归 CTE。在某些场景下,使用 `MERGE()` 比默认分配临时空间的行为具有更高的执行效率。例如,下推查询条件或在嵌套 CTE 查询中: ```sql --- 使用 hint 将外部查询条件的谓词下推 -WITH CTE AS (SELECT /*+ MERGE() */ * FROM tc WHERE tc.a < 60) SELECT * FROM CTE WHERE CTE.a <18; +-- 使用提示下推外部查询的谓词。 +WITH CTE AS (SELECT /*+ MERGE() */ * FROM tc WHERE tc.a < 60) SELECT * FROM CTE WHERE CTE.a < 18; --- 在嵌套 CTE 查询中使用该 hint 来指定将某个 CTE 内联展开到外部查询 +-- 在嵌套 CTE 查询中使用提示将 CTE 内联展开到外部查询。 WITH CTE1 AS (SELECT * FROM t1), CTE2 AS (WITH CTE3 AS (SELECT /*+ MERGE() */ * FROM t2), CTE4 AS (SELECT * FROM t3) SELECT * FROM CTE3, CTE4) SELECT * FROM CTE1, CTE2; ``` > **注意:** > -> `MERGE()` 只适用于简单的 CTE 查询,在以下情况下无法使用该 hint: +> `MERGE()` 仅适用于简单的 CTE 查询。在以下情况下不适用: > -> - [递归的 CTE 查询](/develop/dev-guide-use-common-table-expression.md#递归的-cte) -> - 子查询中有无法进行内联展开的部分,例如聚合算子、窗口函数以及 `DINSTINCT` 等 +> - [递归 CTE](https://docs.pingcap.com/tidb/stable/dev-guide-use-common-table-expression#recursive-cte) +> - 无法展开内联的子查询,如聚合运算符、窗口函数和 `DISTINCT`。 > -> 当 CTE 引用次数过多时,查询性能可能低于默认的物化方式。 +> 当 CTE 引用次数过高时,查询性能可能低于默认的物化行为。 +## 全局生效的提示 -## 全局生效的 Hint +全局提示在[视图](/views.md)中生效。当指定为全局提示时,查询中定义的提示可以在视图内部生效。要指定全局提示,首先使用 `QB_NAME` 提示定义查询块名称,然后以 `ViewName@QueryBlockName` 的形式添加目标提示。 -全局生效的 Hint 和[视图](/views.md)有关,可以使查询中定义的 Hint 能够在视图内部生效。添加这类 Hint 需要两步:先用 `QB_NAME` Hint 为视图内的查询块命名,再以“视图名@查询块名”的方式加入实际需要的 Hint。 +### 步骤 1:使用 `QB_NAME` 提示定义视图的查询块名称 -### 第 1 步:使用 `QB_NAME` Hint 重命名视图内的查询块 - -首先使用 [`QB_NAME` Hint](#qb_name) 重命名视图内部的查询块。其中针对视图的 `QB_NAME` Hint 的概念与[查询块范围生效的 `QB_NAME` Hint](#qb_name)相同,只是在语法上进行了相应的拓展。从 `QB_NAME(QB)` 拓展为 `QB_NAME(QB, 视图名@查询块名 [.视图名@查询块名 .视图名@查询块名 ...])`。 +使用 [`QB_NAME` 提示](#qb_name)为视图的每个查询块定义新名称。视图的 `QB_NAME` 提示定义与[查询块](#qb_name)的定义相同,但语法从 `QB_NAME(QB)` 扩展为 `QB_NAME(QB, ViewName@QueryBlockName [.ViewName@QueryBlockName .ViewName@QueryBlockName ...])`。 > **注意:** > -> `@查询块名` 与后面紧跟的 `.视图名@查询块名` 部分之间需要有一个空格,否则 `.视图名@查询块名` 会被视作前面 `@查询块名` 的一部分。例如,`QB_NAME(v2_1, v2@SEL_1 .@SEL_1)` 不能写为 `QB_NAME(v2_1, v2@SEL_1.@SEL_1)`。 +> `@QueryBlockName` 和紧随其后的 `.ViewName@QueryBlockName` 之间有一个空格。否则,`.ViewName@QueryBlockName` 将被视为 `QueryBlockName` 的一部分。例如,`QB_NAME(v2_1, v2@SEL_1 .@SEL_1)` 是有效的,而 `QB_NAME(v2_1, v2@SEL_1.@SEL_1)` 无法正确解析。 -- 对于单个视图、不包含子查询的简单语句,下面以重命名视图 `v` 的第一个查询块为例: +- 对于只有单个视图且没有子查询的简单语句,以下示例指定视图 `v` 的第一个查询块名称: ```sql - SELECT /* 注释:当前查询块的名字为默认的 @SEL_1 */ * FROM v; + SELECT /* Comment: 当前查询块的名称是默认的 @SEL_1 */ * FROM v; ``` - 对于视图 `v` 来说,从查询语句开始的首个视图是 `v@SEL_1`。视图 `v` 的第一个查询块可以声明为 `QB_NAME(v_1, v@SEL_1 .@SEL_1)`,也可以省略 `@SEL_1` 简写成 `QB_NAME(v_1, v)`: + 对于视图 `v`,从查询语句开始的列表(`ViewName@QueryBlockName [.ViewName@QueryBlockName .ViewName@QueryBlockName ...]`)中的第一个视图名称是 `v@SEL_1`。视图 `v` 的第一个查询块可以声明为 `QB_NAME(v_1, v@SEL_1 .@SEL_1)`,或简写为 `QB_NAME(v_1, v)`,省略 `@SEL_1`: ```sql - CREATE VIEW v AS SELECT /* 注释:当前查询块的名字为默认的 @SEL_1 */ * FROM t; + CREATE VIEW v AS SELECT /* Comment: 当前查询块的名称是默认的 @SEL_1 */ * FROM t; - -- 使用全局生效的 Hint + -- 指定全局提示 SELECT /*+ QB_NAME(v_1, v) USE_INDEX(t@v_1, idx) */ * FROM v; ``` -- 对于嵌套视图和包含子查询的复杂语句,下面以重命名视图 `v1`、`v2` 的两个查询块为例: +- 对于包含嵌套视图和子查询的复杂语句,以下示例为视图 `v1` 和 `v2` 的每个查询块指定名称: ```sql - SELECT /* 注释:当前查询块的名字为默认的 @SEL_1 */ * FROM v2 JOIN ( - SELECT /* 注释:当前查询块的名字为默认的 @SEL_2 */ * FROM v2) vv; + SELECT /* Comment: 当前查询块的名称是默认的 @SEL_1 */ * FROM v2 JOIN ( + SELECT /* Comment: 当前查询块的名称是默认的 @SEL_2 */ * FROM v2) vv; ``` - 对于第一个视图 `v2` 来说,从上面的语句开始的首个视图是 `v2@SEL_1`。对于第二个视图 `v2` 来说,首个视图表为 `v2@SEL_2`。下面的查询部分仅考虑第一个视图 `v2`。 + 对于第一个视图 `v2`,从第一个查询语句开始的列表中的第一个视图名称是 `v2@SEL_1`。对于第二个视图 `v2`,第一个视图名称是 `v2@SEL_2`。以下示例仅考虑第一个视图 `v2`。 - 视图 `v2` 的第一个查询块可以声明为 `QB_NAME(v2_1, v2@SEL_1 .@SEL_1)`,视图 `v2` 的第二个查询块可以声明为 `QB_NAME(v2_2, v2@SEL_1 .@SEL_2)`: + 视图 `v2` 的第一个查询块可以声明为 `QB_NAME(v2_1, v2@SEL_1 .@SEL_1)`,第二个查询块可以声明为 `QB_NAME(v2_2, v2@SEL_1 .@SEL_2)`: ```sql CREATE VIEW v2 AS - SELECT * FROM t JOIN /* 注释:对于视图 v2 来说,当前查询块的名字为默认的 @SEL_1,因此当前查询块的视图列表是 v2@SEL_1 .@SEL_1 */ + SELECT * FROM t JOIN /* Comment: 对于视图 v2,当前查询块的名称是默认的 @SEL_1。因此,当前查询块视图列表是 v2@SEL_1 .@SEL_1 */ ( - SELECT COUNT(*) FROM t1 JOIN v1 /* 注释:对于视图 v2 来说,当前查询块的名字为默认的 @SEL_2,因此当前查询块的视图列表是 v2@SEL_1 .@SEL_2 */ + SELECT COUNT(*) FROM t1 JOIN v1 /* Comment: 对于视图 v2,当前查询块的名称是默认的 @SEL_2。因此,当前查询块视图列表是 v2@SEL_1 .@SEL_2 */ ) tt; ``` - 对于视图 `v1` 来说,从上面的语句开始的首个视图是 `v2@SEL_1 .v1@SEL_2`。视图 `v1` 的第一个查询块可以声明为 `QB_NAME(v1_1, v2@SEL_1 .v1@SEL_2 .@SEL_1)`,视图 `v1` 的第二个查询块可以声明为 `QB_NAME(v1_2, v2@SEL_1 .v1@SEL_2 .@SEL_2)`: + 对于视图 `v1`,从前面的语句开始的列表中的第一个视图名称是 `v2@SEL_1 .v1@SEL_2`。视图 `v1` 中的第一个查询块可以声明为 `QB_NAME(v1_1, v2@SEL_1 .v1@SEL_2 .@SEL_1)`,第二个查询块可以声明为 `QB_NAME(v1_2, v2@SEL_1 .v1@SEL_2 .@SEL_2)`: ```sql - CREATE VIEW v1 AS SELECT * FROM t JOIN /* 注释:对于视图 v1 来说,当前查询块的名字为默认的 @SEL_1,因此当前查询块的视图列表是 v2@SEL_1 .v1@SEL_2 .@SEL_1 */ + CREATE VIEW v1 AS SELECT * FROM t JOIN /* Comment: 对于视图 `v1`,当前查询块的名称是默认的 @SEL_1。因此,当前查询块视图列表是 v2@SEL_1 .@SEL_2 .v1@SEL_1 */ ( - SELECT COUNT(*) FROM t1 JOIN t2 /* 注释:对于视图 v1 来说,当前查询块的名字为默认的 @SEL_2,因此当前查询块的视图列表是 v2@SEL_1 .v1@SEL_2 .@SEL_2 */ + SELECT COUNT(*) FROM t1 JOIN t2 /* Comment: 对于视图 `v1`,当前查询块的名称是默认的 @SEL_2。因此,当前查询块视图列表是 v2@SEL_1 .@SEL_2 .v1@SEL_2 */ ) tt; ``` > **注意:** > -> - 与视图相关的全局生效的 Hint 必须先定义了对应的 `QB_NAME` Hint 才能使用。 +> - 要在视图中使用全局提示,必须在视图中定义相应的 `QB_NAME` 提示。否则,全局提示将不会生效。 +> +> - 当使用提示指定视图中的多个表名时,需要确保同一个提示中出现的表名都在同一个视图的同一个查询块中。 > -> - 使用一个 Hint 来指定视图内的多个表名时,需要保证在同一个 Hint 中出现的表名处于同一个视图的同一个查询块中。 +> - 当你在视图中为最外层查询块定义 `QB_NAME` 提示时: > -> - 对于最外层的查询来说,在定义和视图相关的 `QB_NAME` Hint 时: +> - 对于 `QB_NAME` 中视图列表的第一项,如果没有明确声明 `@SEL_`,默认与定义 `QB_NAME` 的查询块位置一致。即查询 `SELECT /*+ QB_NAME(qb1, v2) */ * FROM v2 JOIN (SELECT /*+ QB_NAME(qb2, v2) */ * FROM v2) vv;` 等同于 `SELECT /*+ QB_NAME(qb1, v2@SEL_1) */ * FROM v2 JOIN (SELECT /*+ QB_NAME(qb2, v2@SEL_2) */ * FROM v2) vv;`。 +> - 对于 `QB_NAME` 中视图列表中除第一项之外的项,只能省略 `@SEL_1`。即如果在当前视图的第一个查询块中声明了 `@SEL_1`,则可以省略 `@SEL_1`。否则,不能省略 `@SEL_`。对于前面的示例: > -> - 对于 `QB_NAME` Hint 中视图列表序列的第一项,在不显式声明 `@SEL_` 时,默认和定义 `QB_NAME` Hint 的查询块位置保持一致,即省略 `@SEL_` 的查询 `SELECT /*+ QB_NAME(qb1, v2) */ * FROM v2 JOIN (SELECT /*+ QB_NAME(qb2, v2) */ * FROM v2) vv;` 相当于 `SELECT /*+ QB_NAME(qb1, v2@SEL_1) */ * FROM v2 JOIN (SELECT /*+ QB_NAME(qb2, v2@SEL_2) */ * FROM v2) vv;`。 -> - 对于 `QB_NAME` Hint 中视图列表序列第一项之外的其他部分,只有 `@SEL_1` 可省略。即,如果声明处于当前部分的第一个查询块中,则 `@SEL_1` 可以省略,否则,不能省略 `@SEL_`。对于上面的例子: -> - 视图 `v2` 的第一个查询块可以声明为 `QB_NAME(v2_1, v2)` -> - 视图 `v2` 的第二个查询块可以声明为 `QB_NAME(v2_2, v2.@SEL_2)` -> - 视图 `v1` 的第一个查询块可以声明为 `QB_NAME(v1_1, v2.v1@SEL_2)` -> - 视图 `v1` 的第二个查询块可以声明为 `QB_NAME(v1_2, v2.v1@SEL_2 .@SEL_2)` +> - 视图 `v2` 的第一个查询块可以声明为 `QB_NAME(v2_1, v2)`。 +> - 视图 `v2` 的第二个查询块可以声明为 `QB_NAME(v2_2, v2.@SEL_2)`。 +> - 视图 `v1` 的第一个查询块可以声明为 `QB_NAME(v1_1, v2.v1@SEL_2)`。 +> - 视图 `v1` 的第二个查询块可以声明为 `QB_NAME(v1_2, v2.v1@SEL_2 .@SEL_2)`。 -### 第 2 步:添加实际需要的 Hint +### 步骤 2:添加目标提示 -在定义好视图查询块部分的 `QB_NAME` Hint 后,你可以通过查询块的名字使用[查询块范围生效的 Hint](#查询块范围生效的-hint),以“视图名@查询块名”的方式加入实际需要的 Hint,使其在视图内部生效。例如: +在为视图的查询块定义了 `QB_NAME` 提示后,你可以以 `ViewName@QueryBlockName` 的形式添加所需的[在查询块中生效的提示](#在查询块中生效的提示),使其在视图内部生效。例如: -- 指定视图 `v2` 中第一个查询块的 `MERGE_JOIN()` Hint: +- 为视图 `v2` 的第一个查询块指定 `MERGE_JOIN()` 提示: ```sql SELECT /*+ QB_NAME(v2_1, v2) merge_join(t@v2_1) */ * FROM v2; ``` -- 指定视图 `v2` 中第二个查询块的 `MERGE_JOIN()` 和 `STREAM_AGG()` Hint: +- 为视图 `v2` 的第二个查询块指定 `MERGE_JOIN()` 和 `STREAM_AGG()` 提示: ```sql SELECT /*+ QB_NAME(v2_2, v2.@SEL_2) merge_join(t1@v2_2) stream_agg(@v2_2) */ * FROM v2; ``` -- 指定视图 `v1` 中第一个查询块的 `HASH_JOIN()` Hint: +- 为视图 `v1` 的第一个查询块指定 `HASH_JOIN()` 提示: ```sql SELECT /*+ QB_NAME(v1_1, v2.v1@SEL_2) hash_join(t@v1_1) */ * FROM v2; ``` -- 指定视图 `v1` 中第二个查询块的 `HASH_JOIN()` 和 `HASH_AGG()` Hint: +- 为视图 `v1` 的第二个查询块指定 `HASH_JOIN()` 和 `HASH_AGG()` 提示: ```sql SELECT /*+ QB_NAME(v1_2, v2.v1@SEL_2 .@SEL_2) hash_join(t1@v1_2) hash_agg(@v1_2) */ * FROM v2; ``` -## 查询范围生效的 Hint +## 在整个查询中生效的提示 -这类 Hint 只能跟在语句中**第一个** `SELECT`、`UPDATE` 或 `DELETE` 关键字的后面,等同于在当前这条查询运行时对指定的系统变量进行修改,其优先级高于现有系统变量的值。 +这类提示只能跟在**第一个** `SELECT`、`UPDATE` 或 `DELETE` 关键字后面,相当于在执行此查询时修改指定系统变量的值。提示的优先级高于现有系统变量。 > **注意:** > -> 这类 Hint 虽然也有隐藏的可选变量 `@QB_NAME`,但就算指定了该值,Hint 还是会在整个查询范围生效。 +> 这类提示也有一个可选的隐藏变量 `@QB_NAME`,但即使你指定了该变量,提示仍然在整个查询中生效。 ### NO_INDEX_MERGE() -`NO_INDEX_MERGE()` 会关闭优化器的 index merge 功能。 +`NO_INDEX_MERGE()` 提示禁用优化器的索引合并功能。 -下面的例子不会使用 index merge: +例如,以下查询将不会使用索引合并: {{< copyable "sql" >}} ```sql -SELECT /*+ NO_INDEX_MERGE() */ * FROM t WHERE t.a > 0 or t.b > 0; +select /*+ NO_INDEX_MERGE() */ * from t where t.a > 0 or t.b > 0; ``` -除了 Hint 外,系统变量 `tidb_enable_index_merge` 也能决定是否开启该功能。 +除了此提示外,设置 `tidb_enable_index_merge` 系统变量也可以控制是否启用此功能。 > **注意:** > -> - `NO_INDEX_MERGE` 优先级高于 `USE_INDEX_MERGE`,当这两类 Hint 同时存在时,`USE_INDEX_MERGE` 不会生效。 -> - 当存在子查询时,`NO_INDEX_MERGE` 放在最外层才能生效。 +> - `NO_INDEX_MERGE` 的优先级高于 `USE_INDEX_MERGE`。当同时使用这两个提示时,`USE_INDEX_MERGE` 不会生效。 +> - 对于子查询,`NO_INDEX_MERGE` 仅在放置在子查询最外层时才会生效。 ### USE_TOJA(boolean_value) -参数 `boolean_value` 可以是 `TRUE` 或者 `FALSE`。`USE_TOJA(TRUE)` 会开启优化器尝试将 in (subquery) 条件转换为 join 和 aggregation 的功能。相对地,`USE_TOJA(FALSE)` 会关闭该功能。 +`boolean_value` 参数可以是 `TRUE` 或 `FALSE`。`USE_TOJA(TRUE)` 提示启用优化器将包含子查询的 `in` 条件转换为连接和聚合操作。相比之下,`USE_TOJA(FALSE)` 提示禁用此功能。 -下面的例子会将 `in (SELECT t2.a FROM t2) subq` 转换为等价的 join 和 aggregation: +例如,以下查询将把 `in (select t2.a from t2) subq` 转换为相应的连接和聚合操作: {{< copyable "sql" >}} ```sql -SELECT /*+ USE_TOJA(TRUE) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2) subq; +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` 也能决定是否开启该功能。 +除了此提示外,设置 `tidb_opt_insubq_to_join_and_agg` 系统变量也可以控制是否启用此功能。 ### MAX_EXECUTION_TIME(N) -`MAX_EXECUTION_TIME(N)` 把语句的执行时间限制在 `N` 毫秒以内,超时后服务器会终止这条语句的执行。 - -下面的 Hint 设置了 1000 毫秒(即 1 秒)超时: +`MAX_EXECUTION_TIME(N)` 提示对语句的执行时间设置限制 `N`(以毫秒为单位的超时值),超过该限制服务器将终止该语句。在以下提示中,`MAX_EXECUTION_TIME(1000)` 表示超时时间为 1000 毫秒(即 1 秒): {{< copyable "sql" >}} ```sql -SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM t1 inner join t2 WHERE t1.id = t2.id; +select /*+ MAX_EXECUTION_TIME(1000) */ * from t1 inner join t2 where t1.id = t2.id; ``` -除了 Hint 之外,系统变量 `global.max_execution_time` 也能对语句执行时间进行限制。 +除了此提示外,`global.max_execution_time` 系统变量也可以限制语句的执行时间。 ### MEMORY_QUOTA(N) -`MEMORY_QUOTA(N)` 用于限制语句执行时的内存使用。该 Hint 支持 MB 和 GB 两种单位。内存使用超过该限制时会根据当前设置的内存超限行为来打出一条 log 或者终止语句的执行。 +`MEMORY_QUOTA(N)` 提示对语句的内存使用设置限制 `N`(以 MB 或 GB 为单位的阈值)。当语句的内存使用超过此限制时,TiDB 会根据语句的超限行为生成日志消息或直接终止该语句。 -下面的 Hint 设置了 1024 MB 的内存限制: +在以下提示中,`MEMORY_QUOTA(1024 MB)` 表示内存使用限制为 1024 MB: {{< copyable "sql" >}} ```sql -SELECT /*+ MEMORY_QUOTA(1024 MB) */ * FROM t; +select /*+ MEMORY_QUOTA(1024 MB) */ * from t; ``` -除了 Hint 外,系统变量 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 也能限制语句执行的内存使用。 +除了此提示外,[`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 系统变量也可以限制语句的内存使用。 ### READ_CONSISTENT_REPLICA() -`READ_CONSISTENT_REPLICA()` 会开启从数据一致的 TiKV follower 节点读取数据的特性。 - -下面的例子会从 follower 节点读取数据: +`READ_CONSISTENT_REPLICA()` 提示启用从 TiKV follower 节点读取一致性数据的功能。例如: {{< copyable "sql" >}} ```sql -SELECT /*+ READ_CONSISTENT_REPLICA() */ * FROM t; +select /*+ READ_CONSISTENT_REPLICA() */ * from t; ``` -除了 Hint 外,环境变量 `tidb_replica_read` 设为 `'follower'` 或者 `'leader'` 也能决定是否开启该特性。 +除了此提示外,将 `tidb_replica_read` 环境变量设置为 `'follower'` 或 `'leader'` 也可以控制是否启用此功能。 ### IGNORE_PLAN_CACHE() -`IGNORE_PLAN_CACHE()` 提示优化器在处理当前 `prepare` 语句时不使用 plan cache。 +`IGNORE_PLAN_CACHE()` 提示提醒优化器在处理当前 `prepare` 语句时不使用 Plan Cache。 -该 Hint 用于在 [Prepared Plan Cache](/sql-prepared-plan-cache.md) 开启的场景下临时对某类查询禁用 plan cache。 +当启用了 [prepare-plan-cache](/sql-prepared-plan-cache.md) 时,此提示用于临时禁用某类查询的 Plan Cache。 -以下示例强制该 `prepare` 语句不使用 plan cache: +在以下示例中,执行 `prepare` 语句时强制禁用 Plan Cache: {{< copyable "sql" >}} ```sql -prepare stmt FROM 'SELECT /*+ IGNORE_PLAN_CACHE() */ * FROM t WHERE t.id = ?'; +prepare stmt from 'select /*+ IGNORE_PLAN_CACHE() */ * from t where t.id = ?'; ``` ### STRAIGHT_JOIN() -`STRAIGHT_JOIN()` 提示优化器在生成表连接顺序时按照表名在 `FROM` 子句中出现的顺序进行连接。 +`STRAIGHT_JOIN()` 提示提醒优化器在生成连接计划时按照 `FROM` 子句中表名的顺序连接表。 {{< copyable "sql" >}} @@ -833,18 +823,18 @@ SELECT /*+ STRAIGHT_JOIN() */ * FROM t t1, t t2 WHERE t1.a = t2.a; > **注意:** > -> - `STRAIGHT_JOIN` 优先级高于 `LEADING`,当这两类 Hint 同时存在时,`LEADING` 不会生效。 -> - 建议使用 `LEADING` Hint,它比 `STRAIGHT_JOIN` Hint 更通用。 +> - `STRAIGHT_JOIN` 的优先级高于 `LEADING`。当同时使用这两个提示时,`LEADING` 不会生效。 +> - 建议使用 `LEADING` 提示,它比 `STRAIGHT_JOIN` 提示更通用。 ### NTH_PLAN(N) -`NTH_PLAN(N)` 提示优化器选用在物理优化阶段搜索到的第 `N` 个物理计划。`N` 必须是正整数。 +`NTH_PLAN(N)` 提示提醒优化器选择物理优化过程中找到的第 `N` 个物理计划。`N` 必须是正整数。 -如果指定的 `N` 超出了物理优化阶段的搜索范围,TiDB 会返回 warning,并根据不存在该 Hint 时一样的策略选择最优物理计划。 +如果指定的 `N` 超出物理优化的搜索范围,TiDB 将返回一个警告,并根据忽略此提示的策略选择最优的物理计划。 -该 Hint 在启用 cascades planner 的情况下不会生效。 +当启用级联优化器时,此提示不生效。 -以下示例会强制优化器在物理阶段选择搜索到的第 3 个物理计划: +在以下示例中,优化器被强制选择物理优化过程中找到的第三个物理计划: {{< copyable "sql" >}} @@ -854,36 +844,35 @@ SELECT /*+ NTH_PLAN(3) */ count(*) from t where a > 5; > **注意:** > -> `NTH_PLAN(N)` 主要用于测试用途,并且在未来不保证其兼容性,请谨慎使用。 +> `NTH_PLAN(N)` 主要用于测试,不保证在后续版本中的兼容性。请**谨慎**使用此提示。 ### RESOURCE_GROUP(resource_group_name) -`RESOURCE_GROUP(resource_group_name)` 用于[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)。此 Hint 将临时使用指定的资源组执行当前的语句。如果指定的资源组不存在,则该 Hint 将被忽略。 +`RESOURCE_GROUP(resource_group_name)` 用于[资源控制](/tidb-resource-control.md)以隔离资源。此提示临时使用指定的资源组执行当前语句。如果指定的资源组不存在,此提示将被忽略。 示例: ```sql SELECT /*+ RESOURCE_GROUP(rg1) */ * FROM t limit 10; ``` +## 排查提示没有生效的常见问题 -## 常见 Hint 不生效问题排查 - -### MySQL 命令行客户端清除 Hint 导致不生效 +### MySQL 命令行客户端删除提示导致提示不生效 -MySQL 命令行客户端在 5.7.7 版本之前默认清除了 Optimizer Hints。如果需要在这些早期版本的客户端中使用 Hint 语法,需要在启动客户端时加上 `--comments` 选项。例如 `mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 +5.7.7 之前版本的 MySQL 命令行客户端默认会删除优化器提示。如果你想在这些早期版本中使用提示语法,在启动客户端时需要添加 `--comments` 选项。例如:`mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 -### 创建连接时不指定库名导致 Hint 不生效 +### 未指定数据库名称导致提示不生效 -如果创建连接时未指定数据库名,则可能出现 Hint 失效的情况。例如: +如果在创建连接时没有指定数据库名称,提示可能不会生效。例如: -使用 `mysql -h127.0.0.1 -P4000 -uroot` 命令连接数据库时,未使用 `-D` 参数指定数据库名。然后执行下面的 SQL 语句: +当连接到 TiDB 时,你使用 `mysql -h127.0.0.1 -P4000 -uroot` 命令而没有使用 `-D` 选项,然后执行以下 SQL 语句: ```sql SELECT /*+ use_index(t, a) */ a FROM test.t; SHOW WARNINGS; ``` -由于无法识别表 `t` 对应的数据库名,因此 `use_index(t, a)` Hint 无法生效。 +因为 TiDB 无法识别表 `t` 的数据库,所以 `use_index(t, a)` 提示不会生效。 ```sql +---------+------+----------------------------------------------------------------------+ @@ -894,9 +883,9 @@ SHOW WARNINGS; 1 row in set (0.00 sec) ``` -### 跨库查询不指定库名导致 Hint 不生效 +### 跨表查询中未明确指定数据库名称导致提示不生效 -对于跨库查询中需要访问的表,需要显式地指定数据库名,否则可能出现 Hint 失效的情况。例如执行下面跨库查询的 SQL 语句: +执行跨表查询时,需要明确指定数据库名称。否则,提示可能不会生效。例如: ```sql USE test1; @@ -907,7 +896,7 @@ SELECT /*+ use_index(t1, a) */ * FROM test1.t1, t2; SHOW WARNINGS; ``` -由于 `t1` 不在当前数据库 `test2` 下,因此 `use_index(t1, a)` Hint 无法被正确地识别。 +在上述语句中,因为表 `t1` 不在当前的 `test2` 数据库中,所以 `use_index(t1, a)` 提示不会生效。 ```sql +---------+------+----------------------------------------------------------------------------------+ @@ -918,37 +907,37 @@ SHOW WARNINGS; 1 row in set (0.00 sec) ``` -此时,需要显式地指定库名,即将 `use_index(t1, a)` 修改为 `use_index(test1.t1, a)`。 +在这种情况下,你需要通过使用 `use_index(test1.t1, a)` 而不是 `use_index(t1, a)` 来明确指定数据库名称。 -### Hint 位置不正确导致不生效 +### 提示放置位置错误导致提示不生效 -如果没有按照 Optimizer Hints 语法将 Hint 正确地放在指定关键字的后面,它将无法生效。例如: +如果提示没有直接放在特定关键字后面,则无法生效。例如: ```sql SELECT * /*+ use_index(t, a) */ FROM t; SHOW WARNINGS; ``` -Warning 信息如下: +警告如下: ```sql -+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Level | Code | Message | -+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Level | Code | Message | ++---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | Warning | 1064 | You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use [parser:8066]Optimizer hint can only be followed by certain keywords like SELECT, INSERT, etc. | -+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec) ``` -在上面的示例中,你需要将 Hint 直接放在 `SELECT` 关键字之后。具体的语法规则参见 [Hint 语法](#语法)部分。 +在这种情况下,你需要将提示直接放在 `SELECT` 关键字后面。更多详情,请参见[语法](#语法)部分。 -### `INL_JOIN` Hint 不生效 +### `INL_JOIN` 提示不生效 -#### 关联表的列上使用内置函数导致 `INL_JOIN` Hint 不生效 +#### 在连接表的列上使用内置函数导致 `INL_JOIN` 提示不生效 -在某些情况下,如果在关联表的列上使用了内置函数,优化器可能无法选择 `IndexJoin` 计划,导致 `INL_JOIN` Hint 也无法生效。 +在某些情况下,如果你在连接表的列上使用内置函数,优化器可能无法选择 `IndexJoin` 计划,导致 `INL_JOIN` 提示也不会生效。 -例如,以下查询在关联表的列 `tname` 上使用了内置函数 `substr`: +例如,以下查询在连接表的列 `tname` 上使用了内置函数 `substr`: ```sql CREATE TABLE t1 (id varchar(10) primary key, tname varchar(10)); @@ -956,7 +945,7 @@ CREATE TABLE t2 (id varchar(10) primary key, tname varchar(10)); EXPLAIN SELECT /*+ INL_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id=t2.id and SUBSTR(t1.tname,1,2)=SUBSTR(t2.tname,1,2); ``` -查询计划输出结果如下: +执行计划如下: ```sql +------------------------------+----------+-----------+---------------+-----------------------------------------------------------------------+ @@ -986,9 +975,9 @@ SHOW WARNINGS; 1 row in set (0.00 sec) ``` -从该示例中可以看到,`INL_JOIN` Hint 没有生效。该问题的根本原因是优化器限制导致无法使用 `Projection` 或者 `Selection` 算子作为 `IndexJoin` 的探测 (Probe) 端。 +从上面的示例可以看出,`INL_JOIN` 提示没有生效。这是由于优化器的一个限制,它不允许使用 `Projection` 或 `Selection` 运算符作为 `IndexJoin` 的探测侧。 -从 TiDB v8.0.0 起,你通过设置 [`tidb_enable_inl_join_inner_multi_pattern`](/system-variables.md#tidb_enable_inl_join_inner_multi_pattern-从-v700-版本开始引入) 为 `ON` 来避免该问题。 +从 TiDB v8.0.0 开始,你可以通过将 [`tidb_enable_inl_join_inner_multi_pattern`](/system-variables.md#tidb_enable_inl_join_inner_multi_pattern-new-in-v700) 设置为 `ON` 来避免这个问题。 ```sql SET @@tidb_enable_inl_join_inner_multi_pattern=ON; @@ -1009,9 +998,9 @@ EXPLAIN SELECT /*+ INL_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id=t2.id AND SUBST 7 rows in set (0.00 sec) ``` -#### 排序规则不兼容导致 `INL_JOIN` Hint、`INL_HASH_JOIN` Hint、`INL_MERGE_JOIN` Hint 不生效 +#### 由于排序规则不兼容导致 `INL_JOIN`、`INL_HASH_JOIN` 和 `INL_MERGE_JOIN` 提示不生效 -如果两个表的 Join key 的排序规则不能兼容,将无法使用 IndexJoin 来执行查询。此时 [`INL_JOIN` Hint](#inl_joint1_name--tl_name-)、[`INL_HASH_JOIN` Hint](#inl_hash_join)、[`INL_MERGE_JOIN` Hint](#inl_merge_join) 将无法生效。例如: +当两个表之间连接键的排序规则不兼容时,无法使用 `IndexJoin` 运算符执行查询。在这种情况下,[`INL_JOIN`](#inl_joint1_name--tl_name-)、[`INL_HASH_JOIN`](#inl_hash_join) 和 [`INL_MERGE_JOIN`](#inl_merge_join) 提示不会生效。例如: ```sql CREATE TABLE t1 (k varchar(8), key(k)) COLLATE=utf8mb4_general_ci; @@ -1019,7 +1008,7 @@ CREATE TABLE t2 (k varchar(8), key(k)) COLLATE=utf8mb4_bin; EXPLAIN SELECT /*+ tidb_inlj(t1) */ * FROM t1, t2 WHERE t1.k=t2.k; ``` -查询计划输出结果如下: +执行计划如下: ```sql +-----------------------------+----------+-----------+----------------------+----------------------------------------------+ @@ -1034,7 +1023,7 @@ EXPLAIN SELECT /*+ tidb_inlj(t1) */ * FROM t1, t2 WHERE t1.k=t2.k; 5 rows in set, 1 warning (0.00 sec) ``` -上面的 SQL 语句中 `t1.k` 和 `t2.k` 的排序规则不能相互兼容(分别为 `utf8mb4_general_ci` 和 `utf8mb4_bin`),导致 IndexJoin 无法适用。因此 `INL_JOIN` 或 `TIDB_INLJ` Hint 也无法生效。 +在上述语句中,`t1.k` 和 `t2.k` 的排序规则不兼容(分别是 `utf8mb4_general_ci` 和 `utf8mb4_bin`),这阻止了 `INL_JOIN` 或 `TIDB_INLJ` 提示生效。 ```sql SHOW WARNINGS; @@ -1046,9 +1035,9 @@ SHOW WARNINGS; 1 row in set (0.00 sec) ``` -#### 连接顺序导致 `INL_JOIN` Hint 不生效 +#### 由于连接顺序导致 `INL_JOIN` 提示不生效 -[`INL_JOIN(t1, t2)`](#inl_joint1_name--tl_name-) 或 `TIDB_INLJ(t1, t2)` 的语义是让 `t1` 和 `t2` 作为 `IndexJoin` 的内表与其他表进行连接,而不是直接将 `t1` 和 `t2` 进行 `IndexJoin` 连接。例如: +[`INL_JOIN(t1, t2)`](#inl_joint1_name--tl_name-) 或 `TIDB_INLJ(t1, t2)` 提示在语义上指示 `t1` 和 `t2` 作为内表在 `IndexJoin` 运算符中与其他表连接,而不是直接使用 `IndexJoin` 运算符连接它们。例如: ```sql EXPLAIN SELECT /*+ inl_join(t1, t3) */ * FROM t1, t2, t3 WHERE t1.id = t2.id AND t2.id = t3.id AND t1.id = t3.id; @@ -1066,9 +1055,9 @@ EXPLAIN SELECT /*+ inl_join(t1, t3) */ * FROM t1, t2, t3 WHERE t1.id = t2.id AND +---------------------------------+----------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ``` -在上面例子中,`t1` 和 `t3` 并没有直接被一个 `IndexJoin` 连接起来。 +在上面的示例中,`t1` 和 `t3` 没有直接通过 `IndexJoin` 连接在一起。 -如果想要直接使用 `IndexJoin` 来连接 `t1` 和 `t3`,需要先使用 [`LEADING` Hint](#leadingt1_name--tl_name-) 指定 `t1` 和 `t3` 的连接顺序,然后再配合使用 `INL_JOIN`。例如: +要在 `t1` 和 `t3` 之间执行直接的 `IndexJoin`,你可以首先使用 [`LEADING(t1, t3)` 提示](#leadingt1_name--tl_name-) 指定 `t1` 和 `t3` 的连接顺序,然后使用 `INL_JOIN` 提示指定连接算法。例如: ```sql EXPLAIN SELECT /*+ leading(t1, t3), inl_join(t3) */ * FROM t1, t2, t3 WHERE t1.id = t2.id AND t2.id = t3.id AND t1.id = t3.id; @@ -1088,12 +1077,12 @@ EXPLAIN SELECT /*+ leading(t1, t3), inl_join(t3) */ * FROM t1, t2, t3 WHERE t1.i 9 rows in set (0.01 sec) ``` -### 使用 Hint 导致错误 `Can't find a proper physical plan for this query` +### 使用提示导致出现 `Can't find a proper physical plan for this query` 错误 -在下面几种情况下,可能会出现 `Can't find a proper physical plan for this query` 错误: +在以下场景中可能会出现 `Can't find a proper physical plan for this query` 错误: -- 查询本身并不需要按顺序读取索引,即在不使用 Hint 的前提下,优化器在任何情况下都不会生成按顺序读取索引的计划。此时,如果指定了 `ORDER_INDEX` Hint,会出现此报错,此时应考虑移除对应的 `ORDER_INDEX` Hint。 -- 查询使用了 `NO_JOIN` 相关的 Hint 排除了所有可能的 Join 方式。 +- 查询本身不需要按顺序读取索引。即在没有提示的情况下,优化器在任何情况下都不会生成按顺序读取索引的计划。在这种情况下,如果指定了 `ORDER_INDEX` 提示,就会出现此错误。要解决此问题,请移除相应的 `ORDER_INDEX` 提示。 +- 查询通过使用 `NO_JOIN` 相关提示排除了所有可能的连接方法。 ```sql CREATE TABLE t1 (a INT); @@ -1102,7 +1091,7 @@ EXPLAIN SELECT /*+ NO_HASH_JOIN(t1), NO_MERGE_JOIN(t1) */ * FROM t1, t2 WHERE t1 ERROR 1815 (HY000): Internal : Can't find a proper physical plan for this query ``` -- 系统变量 [`tidb_opt_enable_hash_join`](/system-variables.md#tidb_opt_enable_hash_join-从-v656v712-和-v740-版本开始引入) 设置为 `OFF`,而且其他 Join 方式也都被排除了。 +- 系统变量 [`tidb_opt_enable_hash_join`](/system-variables.md#tidb_opt_enable_hash_join-new-in-v656-v712-and-v740) 设置为 `OFF`,并且所有其他连接类型也被排除。 ```sql CREATE TABLE t1 (a INT); diff --git a/partition-pruning.md b/partition-pruning.md index 37fde24e9bfb..2e208ea66a8e 100644 --- a/partition-pruning.md +++ b/partition-pruning.md @@ -5,9 +5,9 @@ summary: 了解 TiDB 分区裁剪的使用场景。 # 分区裁剪 -分区裁剪是只有当目标表为分区表时,才可以进行的一种优化方式。分区裁剪通过分析查询语句中的过滤条件,只选择可能满足条件的分区,不扫描匹配不上的分区,进而显著地减少计算的数据量。 +分区裁剪是一种应用于分区表的性能优化。它分析查询语句中的过滤条件,并消除(_裁剪_)不包含任何所需数据的分区。通过消除不需要的分区,TiDB 能够减少需要访问的数据量,从而可能显著提高查询执行时间。 -例如: +以下是一个示例: {{< copyable "sql" >}} @@ -21,6 +21,7 @@ PARTITION BY RANGE COLUMNS(id) ( PARTITION p1 VALUES LESS THAN (200), PARTITION p2 VALUES LESS THAN (MAXVALUE) ); + INSERT INTO t1 VALUES (1, 'test1'),(101, 'test2'), (201, 'test3'); EXPLAIN SELECT * FROM t1 WHERE id BETWEEN 80 AND 120; ``` @@ -40,13 +41,15 @@ EXPLAIN SELECT * FROM t1 WHERE id BETWEEN 80 AND 120; ## 分区裁剪的使用场景 -分区表有 Range 分区和 hash 分区两种形式,分区裁剪对两种分区表也有不同的使用场景。 +分区裁剪的使用场景因分区表的类型不同而不同:范围分区表和哈希分区表。 + +### 在哈希分区表中使用分区裁剪 -### 分区裁剪在 Hash 分区表上的应用 +本节描述分区裁剪在哈希分区表中的适用和不适用场景。 -#### Hash 分区表上可以使用分区裁剪的场景 +#### 哈希分区表中的适用场景 -只有等值比较的查询条件能够支持 Hash 分区表的裁剪。 +分区裁剪仅适用于哈希分区表中的等值比较查询条件。 {{< copyable "sql" >}} @@ -65,13 +68,15 @@ explain select * from t where x = 1; +-------------------------+----------+-----------+-----------------------+--------------------------------+ ``` -在这条 SQL 中,由条件 `x = 1` 可以知道所有结果均在一个分区上。数值 `1` 在经过 Hash 后,可以确定其在分区 `p1` 中。因此只需要扫描分区 `p1`,而无需访问一定不会出现相关结果的 `p2` 、`p3` 、`p4` 分区。从执行计划来看,其中只出现了一个 `TableFullScan` 算子,且在 `access object` 中指定了 `p1` 分区,确认 `partition pruning` 生效了。 +在上面的 SQL 语句中,可以从条件 `x = 1` 知道所有结果都落在一个分区中。值 `1` 经过哈希分区后可以确定在 `p1` 分区中。因此,只需要扫描 `p1` 分区,不需要访问不会有匹配结果的 `p2`、`p3` 和 `p4` 分区。从执行计划中可以看到,只出现了一个 `TableFullScan` 算子,并且在 `access object` 中指定了 `p1` 分区,因此可以确认 `partition pruning` 生效。 + +#### 哈希分区表中的不适用场景 -#### Hash 分区表上不能使用分区裁剪的场景 +本节描述分区裁剪在哈希分区表中的两个不适用场景。 ##### 场景一 -不能确定查询结果只在一个分区上的条件:如 `in`, `between`, `> < >= <=` 等查询条件,不能使用分区裁剪的优化。 +如果无法确定查询结果只落在一个分区中的条件(如 `in`、`between`、`>`、`<`、`>=`、`<=`),则无法使用分区裁剪优化。例如: {{< copyable "sql" >}} @@ -100,11 +105,11 @@ explain select * from t where x > 2; +------------------------------+----------+-----------+-----------------------+--------------------------------+ ``` -在这条 SQL 中,`x > 2` 条件无法确定对应的 Hash Partition,所以不能使用分区裁剪。 +在这种情况下,分区裁剪不适用,因为无法通过 `x > 2` 条件确定对应的哈希分区。 ##### 场景二 -由于分区裁剪的规则优化是在查询计划的生成阶段,对于执行阶段才能获取到过滤条件的场景,无法利用分区裁剪的优化。 +因为分区裁剪的规则优化是在查询计划生成阶段进行的,所以分区裁剪不适用于只能在执行阶段获得过滤条件的场景。例如: {{< copyable "sql" >}} @@ -134,15 +139,19 @@ explain select * from t2 where x = (select * from t1 where t2.x = t1.x and t2.x +--------------------------------------+----------+-----------+------------------------+----------------------------------------------+ ``` -这个查询每从 `t2` 读取一行,都会去分区表 `t1` 上进行查询,理论上这时会满足 `t1.x = val` 的过滤条件,但实际上由于分区裁剪只作用于查询计划生成阶段,而不是执行阶段,因而不会做裁剪。 +这个查询每次从 `t2` 读取一行时,都会在分区表 `t1` 上进行查询。理论上,此时满足 `t1.x = val` 的过滤条件,但实际上分区裁剪只在查询计划生成阶段生效,而不是在执行阶段。 + +### 在范围分区表中使用分区裁剪 + +本节描述分区裁剪在范围分区表中的适用和不适用场景。 -### 分区裁剪在 Range 分区表上的应用 +#### 范围分区表中的适用场景 -#### Range 分区表上可以使用分区裁剪的场景 +本节描述分区裁剪在范围分区表中的三个适用场景。 ##### 场景一 -等值比较的查询条件可以使用分区裁剪。 +分区裁剪适用于范围分区表中的等值比较查询条件。例如: {{< copyable "sql" >}} @@ -165,7 +174,7 @@ explain select * from t where x = 3; +-------------------------+----------+-----------+-----------------------+--------------------------------+ ``` -使用 `in` 条件的等值比较查询条件也可以使用分区裁剪。 +分区裁剪也适用于使用 `in` 查询条件的等值比较。例如: {{< copyable "sql" >}} @@ -192,11 +201,11 @@ explain select * from t where x in(1,13); +-----------------------------+----------+-----------+-----------------------+--------------------------------+ ``` -在这条 SQL 中,由条件 `x in(1,13)` 可以知道所有结果只会分布在几个分区上。经过分析,发现所有 `x = 1` 的记录都在分区 `p0` 上,所有 `x = 13` 的记录都在分区 `p2` 上,因此只需要访问 `p0`、`p2` 这两个分区, +在上面的 SQL 语句中,可以从 `x in(1,13)` 条件知道所有结果都落在几个分区中。经过分析,发现 `x = 1` 的所有记录都在 `p0` 分区中,`x = 13` 的所有记录都在 `p2` 分区中,所以只需要访问 `p0` 和 `p2` 分区。 ##### 场景二 -区间比较的查询条件如 `between`, `> < = >= <=` 可以使用分区裁剪。 +分区裁剪适用于区间比较的查询条件,如 `between`、`>`、`<`、`=`、`>=`、`<=`。例如: {{< copyable "sql" >}} @@ -225,14 +234,14 @@ explain select * from t where x between 7 and 14; ##### 场景三 -分区表达式为 `fn(col)` 的简单形式,查询条件是 `>` `<` `=` `>=` `<=` 之一,且 `fn` 是单调函数,可以使用分区裁剪。 +分区裁剪适用于分区表达式为简单形式 `fn(col)` 的场景,其中查询条件是 `>`、`<`、`=`、`>=` 和 `<=` 之一,且 `fn` 函数是单调的。 -关于 `fn` 函数,对于任意 `x` `y`,如果 `x > y`,则 `fn(x) > fn(y)`,那么这种是严格递增的单调函数。非严格递增的单调函数也可以符合分区裁剪要求,只要函数 `fn` 满足:对于任意 `x` `y`,如果 `x > y`,则 `fn(x) >= fn(y)`。理论上,所有满足单调条件(严格或者非严格)的函数都支持分区裁剪。目前,TiDB 支持的单调函数如下: +如果 `fn` 函数是单调的,对于任何 `x` 和 `y`,如果 `x > y`,则 `fn(x) > fn(y)`。这种 `fn` 函数可以称为严格单调的。对于任何 `x` 和 `y`,如果 `x > y`,则 `fn(x) >= fn(y)`。在这种情况下,`fn` 也可以称为"单调的"。理论上,分区裁剪支持所有单调函数,无论是严格单调还是非严格单调。目前,TiDB 仅支持以下单调函数: * [`UNIX_TIMESTAMP()`](/functions-and-operators/date-and-time-functions.md) * [`TO_DAYS()`](/functions-and-operators/date-and-time-functions.md) -例如,分区表达式是 `fn(col)` 形式,`fn` 为我们支持的单调函数 `to_days`,就可以使用分区裁剪: +例如,当分区表达式为 `fn(col)` 形式,其中 `fn` 是单调函数 `to_days` 时,分区裁剪生效: {{< copyable "sql" >}} @@ -253,9 +262,9 @@ explain select * from t where id > '2020-04-18'; +-------------------------+----------+-----------+-----------------------+-------------------------------------------+ ``` -#### Range 分区表上不能使用分区裁剪的场景 +#### 范围分区表中的不适用场景 -由于分区裁剪的规则优化是在查询计划的生成阶段,对于执行阶段才能获取到过滤条件的场景,无法利用分区裁剪的优化。 +因为分区裁剪的规则优化是在查询计划生成阶段进行的,所以分区裁剪不适用于只能在执行阶段获得过滤条件的场景。例如: {{< copyable "sql" >}} @@ -289,4 +298,4 @@ explain select * from t2 where x < (select * from t1 where t2.x < t1.x and t2.x 14 rows in set (0.00 sec) ``` -这个查询每从 `t2` 读取一行,都会去分区表 `t1` 上进行查询,理论上这时会满足 `t1.x > val` 的过滤条件,但实际上由于分区裁剪只作用于查询计划生成阶段,而不是执行阶段,因而不会做裁剪。 +这个查询每次从 `t2` 读取一行时,都会在分区表 `t1` 上进行查询。理论上,此时满足 `t1.x > val` 的过滤条件,但实际上分区裁剪只在查询计划生成阶段生效,而不是在执行阶段。 diff --git a/partitioned-table.md b/partitioned-table.md index d24a0d971607..b3b5046dad67 100644 --- a/partitioned-table.md +++ b/partitioned-table.md @@ -1,24 +1,26 @@ --- title: 分区表 -summary: 了解如何使用 TiDB 的分区表。 +summary: 了解如何在 TiDB 中使用分区表。 --- # 分区表 -本文介绍 TiDB 的分区表。 +本文档介绍 TiDB 的分区表实现。 ## 分区类型 -本节介绍 TiDB 中的分区类型。当前支持的类型包括 [Range 分区](#range-分区)、[Range COLUMNS 分区](#range-columns-分区)、[Range INTERVAL 分区](#range-interval-分区)、[List 分区](#list-分区)、[List COLUMNS 分区](#list-columns-分区)、[Hash 分区](#hash-分区)和 [Key 分区](#key-分区)。 +本节介绍 TiDB 中的分区类型。目前,TiDB 支持[范围分区](#范围分区)、[范围列分区](#范围列分区)、[列表分区](#列表分区)、[列表列分区](#列表列分区)、[哈希分区](#哈希分区)和[键分区](#键分区)。 -- Range 分区、Range COLUMNS 分区、List 分区和 List COLUMNS 分区可以用于解决业务中大量删除带来的性能问题,支持快速删除分区。 -- Hash 分区和 Key 分区可以用于大量写入场景下的数据打散。与 Hash 分区相比,Key 分区支持多列打散和非整数类型字段的打散。 +- 范围分区、范围列分区、列表分区和列表列分区用于解决应用程序中大量删除操作导致的性能问题,并支持快速删除分区。 +- 哈希分区和键分区用于在大量写入的场景中分布数据。与哈希分区相比,键分区支持分布多个列的数据,并支持对非整数列进行分区。 -### Range 分区 +### 范围分区 -一个表按 Range 分区是指,对于表的每个分区中包含的所有行,按分区表达式计算的值都落在给定的范围内。Range 必须是连续的,并且不能有重叠,通过使用 `VALUES LESS THAN` 进行定义。 +当表按范围分区时,每个分区包含分区表达式值在给定范围内的行。范围必须是连续的但不能重叠。你可以使用 `VALUES LESS THAN` 来定义它。 -下列场景中,假设你要创建一个人事记录的表: +假设你需要创建一个包含人事记录的表,如下所示: + +{{< copyable "sql" >}} ```sql CREATE TABLE employees ( @@ -32,7 +34,9 @@ CREATE TABLE employees ( ); ``` -你可以根据需求按各种方式进行 Range 分区。其中一种方式是按 `store_id` 列进行分区: +你可以根据需要以各种方式按范围分区表。例如,你可以使用 `store_id` 列进行分区: + +{{< copyable "sql" >}} ```sql CREATE TABLE employees ( @@ -53,9 +57,11 @@ PARTITION BY RANGE (store_id) ( ); ``` -在这个分区模式中,所有 `store_id` 为 1 到 5 的员工,都存储在分区 `p0` 里面,`store_id` 为 6 到 10 的员工则存储在分区 `p1` 里面。Range 分区要求,分区的定义必须是有序的,按从小到大递增。 +在此分区方案中,所有 `store_id` 为 1 到 5 的员工对应的行存储在 `p0` 分区中,而所有 `store_id` 为 6 到 10 的员工存储在 `p1` 分区中。范围分区要求分区按从低到高的顺序排列。 -新插入一行数据 `(72, 'Tom', 'John', '2015-06-25', NULL, NULL, 15)` 将会落到分区 `p2` 里面。但如果你插入一条 `store_id` 大于 20 的记录,则会报错,因为 TiDB 无法知晓应该将它插入到哪个分区。这种情况下,可以在建表时使用最大值: +如果你插入一行数据 `(72, 'Tom', 'John', '2015-06-25', NULL, NULL, 15)`,它会落在 `p2` 分区中。但如果你插入一条 `store_id` 大于 20 的记录,则会报错,因为 TiDB 不知道该记录应该插入到哪个分区。在这种情况下,你可以在创建表时使用 `MAXVALUE`: + +{{< copyable "sql" >}} ```sql CREATE TABLE employees ( @@ -76,9 +82,11 @@ PARTITION BY RANGE (store_id) ( ); ``` -`MAXVALUE` 表示一个比所有整数都大的整数。现在,所有 `store_id` 列大于等于 16 的记录都会存储在 `p3` 分区中。 +`MAXVALUE` 表示一个大于所有其他整数值的整数值。现在,所有 `store_id` 大于或等于 16(定义的最高值)的记录都存储在 `p3` 分区中。 -你也可以按员工的职位编号进行分区,也就是使用 `job_code` 列的值进行分区。假设两位数字编号是用于普通员工,三位数字编号是用于办公室以及客户支持,四位数字编号是管理层职位,那么你可以这样建表: +你也可以按员工的工作代码(即 `job_code` 列的值)对表进行分区。假设两位数的工作代码代表普通员工,三位数代码代表办公室和客户支持人员,四位数代码代表管理人员。那么你可以创建一个分区表,如下所示: + +{{< copyable "sql" >}} ```sql CREATE TABLE employees ( @@ -98,9 +106,11 @@ PARTITION BY RANGE (job_code) ( ); ``` -在这个例子中,所有普通员工存储在 `p0` 分区,办公室以及支持人员在 `p1` 分区,管理者在 `p2` 分区。 +在此示例中,所有与普通员工相关的行存储在 `p0` 分区中,所有办公室和客户支持人员存储在 `p1` 分区中,所有管理人员存储在 `p2` 分区中。 -除了可以按 `store_id` 切分,你还可以按日期切分。例如,假设按员工离职的年份进行分区: +除了按 `store_id` 拆分表外,你还可以按日期对表进行分区。例如,你可以按员工的离职年份进行分区: + +{{< copyable "sql" >}} ```sql CREATE TABLE employees ( @@ -121,7 +131,7 @@ PARTITION BY RANGE ( YEAR(separated) ) ( ); ``` -在 Range 分区中,可以基于 `timestamp` 列的值分区,并使用 `unix_timestamp()` 函数,例如: +在范围分区中,你可以基于 `timestamp` 列的值进行分区,并使用 `unix_timestamp()` 函数,例如: {{< copyable "sql" >}} @@ -146,1931 +156,10 @@ PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) ( ); ``` -对于 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` 条件。 - -### Range COLUMNS 分区 - -Range COLUMNS 分区是 Range 分区的一种变体。你可以使用一个或者多个列作为分区键,分区列的数据类型可以是整数 (integer)、字符串(`CHAR`/`VARCHAR`),`DATE` 和 `DATETIME`。不支持使用任何表达式。 - -和 Range 分区一样,Range COLUMNS 分区同样需要分区的范围是严格递增的。不支持下面示例中的分区定义: - -```sql -CREATE TABLE t( - a int, - b datetime, - c varchar(8) -) PARTITION BY RANGE COLUMNS(`c`,`b`) -(PARTITION `p20240520A` VALUES LESS THAN ('A','2024-05-20 00:00:00'), - PARTITION `p20240520Z` VALUES LESS THAN ('Z','2024-05-20 00:00:00'), - PARTITION `p20240521A` VALUES LESS THAN ('A','2024-05-21 00:00:00')); -``` - -``` -Error 1493 (HY000): VALUES LESS THAN value must be strictly increasing for each partition -``` - -假设你想要按名字进行分区,并且能够轻松地删除旧的无效数据,那么你可以创建一个表格,如下所示: - -```sql -CREATE TABLE t ( - valid_until datetime, - name varchar(255) CHARACTER SET ascii, - notes text -) -PARTITION BY RANGE COLUMNS(name, valid_until) -(PARTITION `p2022-g` VALUES LESS THAN ('G','2023-01-01 00:00:00'), - PARTITION `p2023-g` VALUES LESS THAN ('G','2024-01-01 00:00:00'), - PARTITION `p2022-m` VALUES LESS THAN ('M','2023-01-01 00:00:00'), - PARTITION `p2023-m` VALUES LESS THAN ('M','2024-01-01 00:00:00'), - PARTITION `p2022-s` VALUES LESS THAN ('S','2023-01-01 00:00:00'), - PARTITION `p2023-s` VALUES LESS THAN ('S','2024-01-01 00:00:00')) -``` - -该语句将按名字和年份的范围 `[ ('', ''), ('G', '2023-01-01 00:00:00') )`,`[ ('G', '2023-01-01 00:00:00'), ('G', '2024-01-01 00:00:00') )`,`[ ('G', '2024-01-01 00:00:00'), ('M', '2023-01-01 00:00:00') )`,`[ ('M', '2023-01-01 00:00:00'), ('M', '2024-01-01 00:00:00') )`,`[ ('M', '2024-01-01 00:00:00'), ('S', '2023-01-01 00:00:00') )`,`[ ('S', '2023-01-01 00:00:00'), ('S', '2024-01-01 00:00:00') )` 进行分区,删除无效数据,同时仍然可以在 name 和 valid_until 列上进行分区裁剪。其中,`[,)` 是一个左闭右开区间,比如 `[ ('G', '2023-01-01 00:00:00'), ('G', '2024-01-01 00:00:00') )`,表示 name 为 `'G'` ,年份包含 2023-01-01 00:00:00 并大于 2023-01-01 00:00:00 但小于 2024-01-01 00:00:00 的数据,其中不包含 `(G, 2024-01-01 00:00:00)`。 - -### Range INTERVAL 分区 - -TiDB v6.3.0 新增了 Range INTERVAL 分区特性,作为语法糖(syntactic sugar)引入。Range INTERVAL 分区是对 Range 分区的扩展。你可以使用特定的间隔(interval)轻松创建分区。 - -其语法如下: - -```sql -PARTITION BY RANGE [COLUMNS] () -INTERVAL () -FIRST PARTITION LESS THAN () -LAST PARTITION LESS THAN () -[NULL PARTITION] -[MAXVALUE PARTITION] -``` - -示例: - -```sql -CREATE TABLE employees ( - id int unsigned NOT NULL, - fname varchar(30), - lname varchar(30), - hired date NOT NULL DEFAULT '1970-01-01', - separated date DEFAULT '9999-12-31', - job_code int, - store_id int NOT NULL -) PARTITION BY RANGE (id) -INTERVAL (100) FIRST PARTITION LESS THAN (100) LAST PARTITION LESS THAN (10000) MAXVALUE PARTITION -``` - -该示例创建的表与如下 SQL 语句相同: - -```sql -CREATE TABLE `employees` ( - `id` int unsigned NOT NULL, - `fname` varchar(30) DEFAULT NULL, - `lname` varchar(30) DEFAULT NULL, - `hired` date NOT NULL DEFAULT '1970-01-01', - `separated` date DEFAULT '9999-12-31', - `job_code` int DEFAULT NULL, - `store_id` int NOT NULL -) -PARTITION BY RANGE (`id`) -(PARTITION `P_LT_100` VALUES LESS THAN (100), - PARTITION `P_LT_200` VALUES LESS THAN (200), -... - PARTITION `P_LT_9900` VALUES LESS THAN (9900), - PARTITION `P_LT_10000` VALUES LESS THAN (10000), - PARTITION `P_MAXVALUE` VALUES LESS THAN (MAXVALUE)) -``` - -Range INTERVAL 还可以配合 [Range COLUMNS](#range-columns-分区) 分区一起使用。如下面的示例: - -```sql -CREATE TABLE monthly_report_status ( - report_id int NOT NULL, - report_status varchar(20) NOT NULL, - report_date date NOT NULL -) -PARTITION BY RANGE COLUMNS (report_date) -INTERVAL (1 MONTH) FIRST PARTITION LESS THAN ('2000-01-01') LAST PARTITION LESS THAN ('2025-01-01') -``` - -该示例创建的表与如下 SQL 语句相同: - -```sql -CREATE TABLE `monthly_report_status` ( - `report_id` int(11) NOT NULL, - `report_status` varchar(20) NOT NULL, - `report_date` date NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin -PARTITION BY RANGE COLUMNS(`report_date`) -(PARTITION `P_LT_2000-01-01` VALUES LESS THAN ('2000-01-01'), - PARTITION `P_LT_2000-02-01` VALUES LESS THAN ('2000-02-01'), -... - PARTITION `P_LT_2024-11-01` VALUES LESS THAN ('2024-11-01'), - PARTITION `P_LT_2024-12-01` VALUES LESS THAN ('2024-12-01'), - PARTITION `P_LT_2025-01-01` VALUES LESS THAN ('2025-01-01')) -``` - -可选参数 `NULL PARTITION` 会创建一个分区,其中分区表达式推导出的值为 `NULL` 的数据会放到该分区。在分区表达式中,`NULL` 会被认为是小于任何其他值。参见[分区对 NULL 值的处理](#range-分区对-null-的处理)。 - -可选参数 `MAXVALUE PARTITION` 会创建一个最后的分区,其值为 `PARTITION P_MAXVALUE VALUES LESS THAN (MAXVALUE)`。 - -#### ALTER INTERVAL 分区 - -INTERVAL 分区还增加了添加和删除分区的更加简单易用的语法。 - -下面的语句会变更第一个分区,该语句会删除所有小于给定表达式的分区,使匹配的分区成为新的第一个分区。它不会影响 `NULL PARTITION`。 - -```sql -ALTER TABLE table_name FIRST PARTITION LESS THAN () -``` - -下面的语句会变更最后一个分区,该语句会添加新的分区,分区范围扩大到给定的表达式的值。如果存在 `MAXVALUE PARTITION`,则该语句不会生效,因为它需要数据重组。 - -```sql -ALTER TABLE table_name LAST PARTITION LESS THAN () -``` - -#### INTERVAL 分区相关细节和限制 - -- INTERVAL 分区特性仅涉及 `CREATE/ALTER TABLE` 语法。元数据保持不变,因此使用该新语法创建或变更的表仍然兼容 MySQL。 -- 为保持兼容 MySQL,`SHOW CREATE TABLE` 的输出格式保持不变。 -- 遵循 INTERVAL 的存量表可以使用新的 `ALTER` 语法。不需要使用 `INTERVAL` 语法重新创建这些表。 -- 如需使用 `INTERVAL` 语法进行 `RANGE COLUMNS` 分区,只能指定一个列为分区键,且该列的类型为整数 (`INTEGER`) 、日期 (`DATE`) 或日期时间 (`DATETIME`) 。 - -### List 分区 - -在创建 List 分区表之前,请确保以下系统变量为其默认值 `ON`: - -- [`tidb_enable_list_partition`](/system-variables.md#tidb_enable_list_partition-从-v50-版本开始引入) -- [`tidb_enable_table_partition`](/system-variables.md#tidb_enable_table_partition) - -List 分区和 Range 分区有很多相似的地方。不同之处主要在于 List 分区中,对于表的每个分区中包含的所有行,按分区表达式计算的值属于给定的数据集合。每个分区定义的数据集合有任意个值,但不能有重复的值,可通过 `PARTITION ... VALUES IN (...)` 子句对值进行定义。 - -假设你要创建一张人事记录表,示例如下: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE employees ( - id INT NOT NULL, - hired DATE NOT NULL DEFAULT '1970-01-01', - store_id INT -); -``` - -假如一共有 20 个商店分布在 4 个地区,如下表所示: - -``` -| Region | Store ID Numbers | -| ------- | -------------------- | -| North | 1, 2, 3, 4, 5 | -| East | 6, 7, 8, 9, 10 | -| West | 11, 12, 13, 14, 15 | -| Central | 16, 17, 18, 19, 20 | -``` - -如果想把同一个地区商店员工的人事数据都存储在同一个分区中,你可以根据 `store_id` 来创建 List 分区: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE employees ( - id INT NOT NULL, - hired DATE NOT NULL DEFAULT '1970-01-01', - store_id INT -) -PARTITION BY LIST (store_id) ( - PARTITION pNorth VALUES IN (1, 2, 3, 4, 5), - PARTITION pEast VALUES IN (6, 7, 8, 9, 10), - PARTITION pWest VALUES IN (11, 12, 13, 14, 15), - PARTITION pCentral VALUES IN (16, 17, 18, 19, 20) -); -``` - -这样就能方便地在表中添加或删除与特定区域相关的记录。例如,假设东部地区 (East) 所有的商店都卖给了另一家公司,所有该地区商店员工相关的行数据都可以通过 `ALTER TABLE employees TRUNCATE PARTITION pEast` 删除,这比等效的 `DELETE` 语句 `DELETE FROM employees WHERE store_id IN (6, 7, 8, 9, 10)` 执行起来更加高效。 - -使用 `ALTER TABLE employees DROP PARTITION pEast` 也能删除所有这些行,但同时也会从表的定义中删除分区 `pEast`。那样你还需要使用 `ALTER TABLE ... ADD PARTITION` 语句来还原表的原始分区方案。 - -#### 默认的 List 分区 - -从 v7.3.0 版本开始,你可以为 List 或者 List COLUMNS 分区表添加默认的 List 分区。默认的 List 分区作为一个后备分区,可以存储那些不匹配任何分区数据集合的行。 - -> **注意:** -> -> 该功能是 TiDB 对 MySQL 语法的扩展。为 List 或 List COLUMNS 分区表添加默认分区后,该分区表的数据无法直接同步到 MySQL 中。 - -以下面的 List 分区表为例: - -```sql -CREATE TABLE t ( - a INT, - b INT -) -PARTITION BY LIST (a) ( - PARTITION p0 VALUES IN (1, 2, 3), - PARTITION p1 VALUES IN (4, 5, 6) -); -Query OK, 0 rows affected (0.11 sec) -``` - -通过以下语句,你可以在该表中添加一个名为 `pDef` 的默认 List 分区: - -```sql -ALTER TABLE t ADD PARTITION (PARTITION pDef DEFAULT); -``` - -或者 - -```sql -ALTER TABLE t ADD PARTITION (PARTITION pDef VALUES IN (DEFAULT)); -``` - -此时,如果新插入该表中的值不匹配任何分区的数据集合,对应的数据会自动写入默认分区。 - -```sql -INSERT INTO t VALUES (7, 7); -Query OK, 1 row affected (0.01 sec) -``` - -你也可以在创建 List 或 List COLUMNS 分区表时添加默认分区。例如: - -```sql -CREATE TABLE employees ( - id INT NOT NULL, - hired DATE NOT NULL DEFAULT '1970-01-01', - store_id INT -) -PARTITION BY LIST (store_id) ( - PARTITION pNorth VALUES IN (1, 2, 3, 4, 5), - PARTITION pEast VALUES IN (6, 7, 8, 9, 10), - PARTITION pWest VALUES IN (11, 12, 13, 14, 15), - PARTITION pCentral VALUES IN (16, 17, 18, 19, 20), - PARTITION pDefault DEFAULT -); -``` - -对于不包含默认分区的 List 或 List COLUMNS 分区表,`INSERT` 语句要插入的值需要匹配该表 `PARTITION ... VALUES IN (...)` 子句中定义的数据集合。如果要插入的值不匹配任何分区的数据集合,该语句将执行失败并报错,如下例所示: - -```sql -CREATE TABLE t ( - a INT, - b INT -) -PARTITION BY LIST (a) ( - PARTITION p0 VALUES IN (1, 2, 3), - PARTITION p1 VALUES IN (4, 5, 6) -); -Query OK, 0 rows affected (0.11 sec) - -INSERT INTO t VALUES (7, 7); -ERROR 1525 (HY000): Table has no partition for value 7 -``` - -要忽略以上错误,可以在 `INSERT` 语句中添加 `IGNORE` 关键字。添加该关键字后,`INSERT` 语句只会插入那些匹配分区数据集合的行,不会插入不匹配的行,并且不会报错: - -```sql -test> TRUNCATE t; -Query OK, 1 row affected (0.00 sec) - -test> INSERT IGNORE INTO t VALUES (1, 1), (7, 7), (8, 8), (3, 3), (5, 5); -Query OK, 3 rows affected, 2 warnings (0.01 sec) -Records: 5 Duplicates: 2 Warnings: 2 - -test> select * from t; -+------+------+ -| a | b | -+------+------+ -| 5 | 5 | -| 1 | 1 | -| 3 | 3 | -+------+------+ -3 rows in set (0.01 sec) -``` - -### List COLUMNS 分区 - -List COLUMNS 分区是 List 分区的一种变体,可以将多个列用作分区键,并且可以将整数类型以外的数据类型的列用作分区列。你还可以使用字符串类型、`DATE` 和 `DATETIME` 类型的列。 - -假设商店员工分别来自以下 12 个城市,想要根据相关规定分成 4 个区域,如下表所示: - -``` -| Region | Cities | -| :----- | ------------------------------ | -| 1 | LosAngeles,Seattle, Houston | -| 2 | Chicago, Columbus, Boston | -| 3 | NewYork, LongIsland, Baltimore | -| 4 | Atlanta, Raleigh, Cincinnati | -``` - -使用列表列分区,你可以为员工数据创建一张表,将每行数据存储在员工所在城市对应的分区中,如下所示: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE employees_1 ( - id INT NOT NULL, - fname VARCHAR(30), - lname VARCHAR(30), - hired DATE NOT NULL DEFAULT '1970-01-01', - separated DATE DEFAULT '9999-12-31', - job_code INT, - store_id INT, - city VARCHAR(15) -) -PARTITION BY LIST COLUMNS(city) ( - PARTITION pRegion_1 VALUES IN('LosAngeles', 'Seattle', 'Houston'), - PARTITION pRegion_2 VALUES IN('Chicago', 'Columbus', 'Boston'), - PARTITION pRegion_3 VALUES IN('NewYork', 'LongIsland', 'Baltimore'), - PARTITION pRegion_4 VALUES IN('Atlanta', 'Raleigh', 'Cincinnati') -); -``` - -与 List 分区不同的是,你不需要在 `COLUMNS()` 子句中使用表达式来将列值转换为整数。 - -List COLUMNS 分区也可以使用 `DATE` 和 `DATETIME` 类型的列进行分区,如以下示例中所示,该示例使用与先前的 `employees_1` 表相同的名称和列,但根据 `hired` 列采用 List COLUMNS 分区: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE employees_2 ( - id INT NOT NULL, - fname VARCHAR(30), - lname VARCHAR(30), - hired DATE NOT NULL DEFAULT '1970-01-01', - separated DATE DEFAULT '9999-12-31', - job_code INT, - store_id INT, - city VARCHAR(15) -) -PARTITION BY LIST COLUMNS(hired) ( - PARTITION pWeek_1 VALUES IN('2020-02-01', '2020-02-02', '2020-02-03', - '2020-02-04', '2020-02-05', '2020-02-06', '2020-02-07'), - PARTITION pWeek_2 VALUES IN('2020-02-08', '2020-02-09', '2020-02-10', - '2020-02-11', '2020-02-12', '2020-02-13', '2020-02-14'), - PARTITION pWeek_3 VALUES IN('2020-02-15', '2020-02-16', '2020-02-17', - '2020-02-18', '2020-02-19', '2020-02-20', '2020-02-21'), - PARTITION pWeek_4 VALUES IN('2020-02-22', '2020-02-23', '2020-02-24', - '2020-02-25', '2020-02-26', '2020-02-27', '2020-02-28') -); -``` - -另外,你也可以在 `COLUMNS()` 子句中添加多个列,例如: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE t ( - id int, - name varchar(10) -) -PARTITION BY LIST COLUMNS(id,name) ( - partition p0 values IN ((1,'a'),(2,'b')), - partition p1 values IN ((3,'c'),(4,'d')), - partition p3 values IN ((5,'e'),(null,null)) -); -``` - -### 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 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 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 -``` - -### Key 分区 - -TiDB 从 v7.0.0 开始支持 Key 分区。在 v7.0.0 之前的版本中,创建 Key 分区表时,TiDB 会将其创建为非分区表并给出告警。 - -Key 分区与 Hash 分区都可以保证将数据均匀地分散到一定数量的分区里面,区别是 Hash 分区只能根据一个指定的整数表达式或字段进行分区,而 Key 分区可以根据字段列表进行分区,且 Key 分区的分区字段不局限于整数类型。TiDB Key 分区表的 Hash 算法与 MySQL 不一样,因此表的数据分布也不一样。 - -创建 Key 分区表时,你需要在 `CREATE TABLE` 后面添加 `PARTITION BY KEY (columnList)`,其中 `columnList` 是字段列表,可以包含一个或多个字段。每个字段的类型可以是除 `BLOB`、`JSON`、`GEOMETRY` 之外的任意类型(请注意 TiDB 不支持 `GEOMETRY` 类型)。此外,你很可能还需要加上 `PARTITIONS num`,其中 `num` 是一个正整数,表示将表划分多少个分区;或者加上分区名的定义,例如,加上 `(PARTITION p0, PARTITION p1)` 代表将表划分为两个分区,分区名为 `p0` 和 `p1`。 - -下面的语句将创建一个 Key 分区表,按 `store_id` 分成 4 个分区: - -```sql -CREATE TABLE employees ( - id INT NOT NULL, - fname VARCHAR(30), - lname VARCHAR(30), - hired DATE NOT NULL DEFAULT '1970-01-01', - separated DATE DEFAULT '9999-12-31', - job_code INT, - store_id INT -) - -PARTITION BY KEY(store_id) -PARTITIONS 4; -``` - -如果不指定 `PARTITIONS num`,默认的分区数量为 1。 - -你也可以根据 VARCHAR 等非整数字段创建 Key 分区表。下面的语句按 `fname` 将表分成 4 个分区: - -```sql -CREATE TABLE employees ( - id INT NOT NULL, - fname VARCHAR(30), - lname VARCHAR(30), - hired DATE NOT NULL DEFAULT '1970-01-01', - separated DATE DEFAULT '9999-12-31', - job_code INT, - store_id INT -) - -PARTITION BY KEY(fname) -PARTITIONS 4; -``` - -你还可以根据多列字段创建 Key 分区表。下面的语句按 `fname`、`store_id` 将表分成 4 个分区: - -```sql -CREATE TABLE employees ( - id INT NOT NULL, - fname VARCHAR(30), - lname VARCHAR(30), - hired DATE NOT NULL DEFAULT '1970-01-01', - separated DATE DEFAULT '9999-12-31', - job_code INT, - store_id INT -) - -PARTITION BY KEY(fname, store_id) -PARTITIONS 4; -``` - -和 MySQL 一样,TiDB 支持分区字段列表 `PARTITION BY KEY` 为空的 Key 分区表。下面的语句将创建一个以主键 `id` 为分区键的分区表: - -```sql -CREATE TABLE employees ( - id INT NOT NULL PRIMARY KEY, - fname VARCHAR(30), - lname VARCHAR(30), - hired DATE NOT NULL DEFAULT '1970-01-01', - separated DATE DEFAULT '9999-12-31', - job_code INT, - store_id INT -) - -PARTITION BY KEY() -PARTITIONS 4; -``` - -如果表中不存在主键但有唯一键时,使用唯一键作为分区键: - -```sql -CREATE TABLE k1 ( - id INT NOT NULL, - name VARCHAR(20), - UNIQUE KEY (id) -) -PARTITION BY KEY() -PARTITIONS 2; -``` - -但是,如果唯一键列未被定义为 `NOT NULL`,上述语句将失败。 - -### TiDB 对 Linear Hash 分区的处理 - -在 v6.4.0 之前,如果在 TiDB 上执行 [MySQL Linear Hash 分区](https://dev.mysql.com/doc/refman/8.0/en/partitioning-linear-hash.html) 的 DDL 语句,TiDB 只能创建非分区表。在这种情况下,如果你仍然想要在 TiDB 中创建分区表,你需要修改这些 DDL 语句。 - -从 v6.4.0 起,TiDB 支持解析 MySQL 的 `PARTITION BY LINEAR HASH` 语法,但会忽略其中的 `LINEAR` 关键字。你可以直接在 TiDB 中执行现有的 MySQL Linear Hash 分区的 SQL 语句,而无需修改。 - -- 对于 MySQL Linear Hash 分区的 `CREATE` 语句,TiDB 将创建一个常规的非线性 Hash 分区表(注意 TiDB 内部实际不存在 Linear Hash 分区表)。如果分区数是 2 的幂,该分区表中行的分布情况与 MySQL 相同。如果分区数不是 2 的幂,该分区表中行的分布情况与 MySQL 会有所差异。这是因为 TiDB 中非线性分区表使用简单的“分区模数”,而线性分区表使用“模数的下一个 2 次方并会折叠分区数和下一个 2 次方之间的值”。详情请见 [#38450](https://github.com/pingcap/tidb/issues/38450)。 - -- 对于 MySQL Linear Hash 分区的其他 SQL 语句,TiDB 将正常返回对应的 Hash 分区的查询结果。但当分区数不是 2 的幂(意味着分区表中行的分布情况与 MySQL 不同)时,[分区选择](#分区选择)、`TRUNCATE PARTITION`、`EXCHANGE PARTITION` 返回的结果将和 MySQL 有所差异。 - -### TiDB 对 Linear Key 分区的处理 - -TiDB 从 v7.0.0 开始支持 Key 分区,并支持解析 MySQL 的 `PARTITION BY LINEAR KEY` 语法,但会忽略其中的 `LINEAR` 关键字,只采用非线性 Hash 算法。 - -在 v7.0.0 之前的版本中,创建 Key 分区表时,TiDB 会将其创建为非分区表并给出告警。 - -### 分区对 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 的最终行为以本文档描述为准。 - -#### Key 分区对 NULL 的处理 - -在 Key 分区中 NULL 值的处理与 Hash 分区一致:如果分区字段的值为 NULL,它会被当作 0 值处理。 - -## 分区管理 - -对于 `RANGE`、`RANGE COLUMNS`、`LIST`、`LIST COLUMNS` 分区表,你可以进行以下分区管理操作: - -- 使用 `ALTER TABLE <表名> ADD PARTITION (<分区说明>)` 语句添加分区。 -- 使用 `ALTER TABLE <表名> DROP PARTITION <分区列表>` 删除分区。 -- 使用 `ALTER TABLE <表名> TRUNCATE PARTITION <分区列表>` 语句清空分区里的数据。`TRUNCATE PARTITION` 的逻辑与 [`TRUNCATE TABLE`](/sql-statements/sql-statement-truncate.md) 相似,但它的操作对象为分区。 -- 使用 `ALTER TABLE <表名> REORGANIZE PARTITION <分区列表> INTO (<新的分区说明>)`语句对分区进行合并、拆分、或者其他修改。 - -对于 `HASH` 和 `KEY` 分区表,你可以进行以下分区管理操作: - -- 使用 `ALTER TABLE COALESCE PARTITION <要减少的分区数量>` 语句减少分区数量。此操作会重组分区,将所有数据按照新的分区个数复制到对应的分区。 -- 使用 `ALTER TABLE
ADD PARTITION <要增加的分区数量 | (新的分区说明)>` 语句增加分区的数量。此操作会重组分区,将所有数据按照新的分区个数复制到对应的分区。 -- 使用 `ALTER TABLE
TRUNCATE PARTITION <分区列表>` 语句清空分区里的数据。`TRUNCATE PARTITION` 的逻辑与 [`TRUNCATE TABLE`](/sql-statements/sql-statement-truncate.md) 相似,但它的操作对象为分区。 - -`EXCHANGE PARTITION` 语句用来交换分区和非分区表,类似于重命名表如 `RENAME TABLE t1 TO t1_tmp, t2 TO t1, t1_tmp TO t2` 的操作。 - -例如,`ALTER TABLE partitioned_table EXCHANGE PARTITION p1 WITH TABLE non_partitioned_table` 交换的是 `p1` 分区的 `partitioned_table` 表和 `non_partitioned_table` 表。 - -确保要交换入分区中的所有行与分区定义匹配;否则,交换将失败。 - -请注意对于以下 TiDB 专有的特性,当表结构中包含这些特性时,在 TiDB 中使用 `EXCHANGE PARTITION` 功能不仅需要满足 [MySQL 的 EXCHANGE PARTITION 条件](https://dev.mysql.com/doc/refman/8.0/en/partitioning-management-exchange.html),还要保证这些专有特性对于分区表和非分区表的定义相同。 - -* [Placement Rules in SQL](/placement-rules-in-sql.md):Placement Policy 定义相同。 -* [TiFlash](/tiflash/tiflash-overview.md):TiFlash Replica 数量相同。 -* [聚簇索引](/clustered-indexes.md):分区表和非分区表要么都是聚簇索引 (CLUSTERED),要么都不是聚簇索引 (NONCLUSTERED)。 - -此外,`EXCHANGE PARTITION` 和其他组件兼容性上存在一些限制,需要保证分区表和非分区表的一致性: - -- TiFlash:TiFlash Replica 定义不同时,无法执行 `EXCHANGE PARTITION` 操作。 -- TiCDC:分区表和非分区表都有主键或者唯一键时,TiCDC 同步 `EXCHANGE PARTITION` 操作;反之 TiCDC 将不会同步。 -- TiDB Lightning 和 BR:使用 TiDB Lightning 导入或使用 BR 恢复的过程中,不要执行 `EXCHANGE PARTITION` 操作。 - -### 管理 List 分区、List COLUMNS 分区、Range 分区、Range COLUMNS 分区 - -本小节将以如下 SQL 语句创建的分区表为例,介绍如何管理 Range 分区和 List 分区。 - -```sql -CREATE TABLE members ( - id int, - fname varchar(255), - lname varchar(255), - dob date, - data json -) -PARTITION BY RANGE (YEAR(dob)) ( - PARTITION pBefore1950 VALUES LESS THAN (1950), - PARTITION p1950 VALUES LESS THAN (1960), - PARTITION p1960 VALUES LESS THAN (1970), - PARTITION p1970 VALUES LESS THAN (1980), - PARTITION p1980 VALUES LESS THAN (1990), - PARTITION p1990 VALUES LESS THAN (2000)); - -CREATE TABLE member_level ( - id int, - level int, - achievements json -) -PARTITION BY LIST (level) ( - PARTITION l1 VALUES IN (1), - PARTITION l2 VALUES IN (2), - PARTITION l3 VALUES IN (3), - PARTITION l4 VALUES IN (4), - PARTITION l5 VALUES IN (5)); -``` - -#### 删除分区 - -```sql -ALTER TABLE members DROP PARTITION p1990; - -ALTER TABLE member_level DROP PARTITION l5; -``` - -#### 清空分区 - -```sql -ALTER TABLE members TRUNCATE PARTITION p1980; - -ALTER TABLE member_level TRUNCATE PARTITION l4; -``` - -#### 添加分区 - -```sql -ALTER TABLE members ADD PARTITION (PARTITION `p1990to2010` VALUES LESS THAN (2010)); - -ALTER TABLE member_level ADD PARTITION (PARTITION l5_6 VALUES IN (5,6)); -``` - -对于 Range 分区表,`ADD PARTITION` 只能在分区列表的最后添加新的分区。与分区列表中已有的分区相比,你需要将新分区的 `VALUES LESS THAN` 定义为更大的值。否则,执行该语句时将会报错。 - -```sql -ALTER TABLE members ADD PARTITION (PARTITION p1990 VALUES LESS THAN (2000)); -``` - -``` -ERROR 1493 (HY000): VALUES LESS THAN value must be strictly increasing for each partition -``` - -#### 重组分区 - -拆分分区: - -```sql -ALTER TABLE members REORGANIZE PARTITION `p1990to2010` INTO -(PARTITION p1990 VALUES LESS THAN (2000), - PARTITION p2000 VALUES LESS THAN (2010), - PARTITION p2010 VALUES LESS THAN (2020), - PARTITION p2020 VALUES LESS THAN (2030), - PARTITION pMax VALUES LESS THAN (MAXVALUE)); - -ALTER TABLE member_level REORGANIZE PARTITION l5_6 INTO -(PARTITION l5 VALUES IN (5), - PARTITION l6 VALUES IN (6)); -``` - -合并分区: - -```sql -ALTER TABLE members REORGANIZE PARTITION pBefore1950,p1950 INTO (PARTITION pBefore1960 VALUES LESS THAN (1960)); - -ALTER TABLE member_level REORGANIZE PARTITION l1,l2 INTO (PARTITION l1_2 VALUES IN (1,2)); -``` - -修改分区表定义: - -```sql -ALTER TABLE members REORGANIZE PARTITION pBefore1960,p1960,p1970,p1980,p1990,p2000,p2010,p2020,pMax INTO -(PARTITION p1800 VALUES LESS THAN (1900), - PARTITION p1900 VALUES LESS THAN (2000), - PARTITION p2000 VALUES LESS THAN (2100)); - -ALTER TABLE member_level REORGANIZE PARTITION l1_2,l3,l4,l5,l6 INTO -(PARTITION lOdd VALUES IN (1,3,5), - PARTITION lEven VALUES IN (2,4,6)); -``` - -在重组分区时,需要注意以下关键点: - -- 重组分区(包括合并或拆分分区)只能修改分区定义,无法修改分区表类型。例如,无法将 List 类型修改为 Range 类型,或将 Range COLUMNS 类型修改为 Range 类型。 - -- 对于 Range 分区表,你只能对表中相邻的分区进行重组: - - ```sql - ALTER TABLE members REORGANIZE PARTITION p1800,p2000 INTO (PARTITION p2000 VALUES LESS THAN (2100)); - ``` - - ``` - ERROR 8200 (HY000): Unsupported REORGANIZE PARTITION of RANGE; not adjacent partitions - ``` - -- 对于 Range 分区表,如需修改 Range 定义中的最大值,必须保证 `VALUES LESS THAN` 中新定义的值大于现有分区中的所有值。否则,TiDB 将报错,提示现有的行值对应不到分区。 - - ```sql - INSERT INTO members VALUES (313, "John", "Doe", "2022-11-22", NULL); - ALTER TABLE members REORGANIZE PARTITION p2000 INTO (PARTITION p2000 VALUES LESS THAN (2050)); -- 执行成功,因为 2050 包含了现有的所有行 - ALTER TABLE members REORGANIZE PARTITION p2000 INTO (PARTITION p2000 VALUES LESS THAN (2020)); -- 执行失败,因为 2022 将对应不到分区 - ``` - - ``` - ERROR 1526 (HY000): Table has no partition for value 2022 - ``` - -- 对于 List 分区表,如需修改分区定义中的数据集合,必须保证新的数据集合能覆盖到该分区中现有的所有值,否则 TiDB 将报错。 - - ```sql - INSERT INTO member_level (id, level) values (313, 6); - ALTER TABLE member_level REORGANIZE PARTITION lEven INTO (PARTITION lEven VALUES IN (2,4)); - ``` - - ``` - ERROR 1526 (HY000): Table has no partition for value 6 - ``` - -- 分区重组后,相应分区的统计信息将会过期,并返回以下警告。此时,你可以通过 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md)语句更新统计信息。 - - ```sql - +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Level | Code | Message | - +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Warning | 1105 | The statistics of related partitions will be outdated after reorganizing partitions. Please use 'ANALYZE TABLE' statement if you want to update it now | - +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - 1 row in set (0.00 sec) - ``` - -### 管理 Hash 分区和 Key 分区 - -本小节将以如下 SQL 语句创建的分区表为例,介绍如何管理 Hash 分区。对于 Key 分区,你也可以使用与 Hash 分区相同的分区管理语句。 - -```sql -CREATE TABLE example ( - id INT PRIMARY KEY, - data VARCHAR(1024) -) -PARTITION BY HASH(id) -PARTITIONS 2; -``` - -#### 增加分区数量 - -将 `example` 表的分区个数增加 1 个(从 2 增加到 3): - -```sql -ALTER TABLE example ADD PARTITION PARTITIONS 1; -``` - -你也可以通过添加分区定义来指定分区选项。例如,你可以通过以下语句将分区数量从 3 增加到 5,并指定新增的分区名为 `pExample4` 和 `pExample5`: - -```sql -ALTER TABLE example ADD PARTITION -(PARTITION pExample4 COMMENT = 'not p3, but pExample4 instead', - PARTITION pExample5 COMMENT = 'not p4, but pExample5 instead'); -``` - -#### 减少分区数量 - -与 Range 和 List 分区不同,Hash 和 Key 分区不支持 `DROP PARTITION`,但可以使用 `COALESCE PARTITION` 来减少分区数量,或使用 `TRUNCATE PARTITION` 清空指定分区的所有数据。 - -将 `example` 表的分区个数减少 1 个(从 5 减少到 4): - -```sql -ALTER TABLE example COALESCE PARTITION 1; -``` - -> **注意:** -> -> 更改 Hash 和 Key 分区表的分区个数的过程会重组分区,将所有数据按照新的分区个数复制到对应的分区。因此,更改 Hash 和 Key 分区表的分区个数后,会遇到以下关于过时统计信息的警告。此时,你可以通过 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 语句更新统计信息。 -> -> ```sql -> +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -> | Level | Code | Message | -> +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -> | Warning | 1105 | The statistics of related partitions will be outdated after reorganizing partitions. Please use 'ANALYZE TABLE' statement if you want to update it now | -> +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -> 1 row in set (0.00 sec) -> ``` - -为了更好地理解 `example` 表重组后的结构,你可以查看重新创建 `example` 表所使用的 SQL 语句,如下所示: - -```sql -SHOW CREATE TABLE\G -``` - -``` -*************************** 1. row *************************** - Table: example -Create Table: CREATE TABLE `example` ( - `id` int(11) NOT NULL, - `data` varchar(1024) DEFAULT NULL, - PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */ -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin -PARTITION BY HASH (`id`) -(PARTITION `p0`, - PARTITION `p1`, - PARTITION `p2`, - PARTITION `pExample4` COMMENT 'not p3, but pExample4 instead') -1 row in set (0.01 sec) -``` - -#### 清空分区 - -清空指定分区的所有数据: - -```sql -ALTER TABLE example TRUNCATE PARTITION p0; -``` - -``` -Query OK, 0 rows affected (0.03 sec) -``` - -### 将分区表转换为非分区表 - -要将分区表转换为非分区表,你可以使用以下语句。该语句在执行时将会删除分区,复制表中的所有行,并为表在线重新创建索引。 - -```sql -ALTER TABLE REMOVE PARTITIONING -``` - -例如,要将分区表 `members` 转换为非分区表,可以执行以下语句: - -```sql -ALTER TABLE members REMOVE PARTITIONING -``` - -### 对现有表进行分区 - -要对现有的非分区表进行分区或修改现有分区表的分区类型,你可以使用以下语句。该语句在执行时,将根据新的分区定义复制表中的所有行,并在线重新创建索引: - -```sql -ALTER TABLE PARTITION BY -``` - -示例: - -要将现有的 `members` 表转换为一个包含 10 个分区的 HASH 分区表,可以执行以下语句: - -```sql -ALTER TABLE members PARTITION BY HASH(id) PARTITIONS 10; -``` - -要将现有的 `member_level` 表转换为 RANGE 分区表,可以执行以下语句: - -```sql -ALTER TABLE member_level PARTITION BY RANGE(level) -(PARTITION pLow VALUES LESS THAN (1), - PARTITION pMid VALUES LESS THAN (3), - PARTITION pHigh VALUES LESS THAN (7) - PARTITION pMax VALUES LESS THAN (MAXVALUE)); -``` - -## 分区裁剪 - -有一个优化叫做[“分区裁剪”](/partition-pruning.md),它基于一个非常简单的概念:不需要扫描那些匹配不上的分区。 - -假设创建一个分区表 `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) - -分区裁剪暂不支持 `LIKE` 语句。 - -### 分区裁剪生效的场景 - -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 和 Key 分区类型,只有等值比较的查询条件能够支持分区裁剪。 - -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()`](/functions-and-operators/date-and-time-functions.md) - * [`TO_DAYS()`](/functions-and-operators/date-and-time-functions.md) - - 例如,分区表达式是简单列的情况: - - {{< 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 id > 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 dt > '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 ts > '2020-04-18 02:00:42.123'; - ``` - -## 分区选择 - -SELECT 语句中支持分区选择。实现通过使用一个 `PARTITION` 选项实现。 - -{{< copyable "sql" >}} - -```sql -SET @@sql_mode = ''; - -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 分区表的一些约束和限制。 - -- 不支持使用 [`ALTER TABLE ... CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) 语句更改分区表的列类型。 -- 不支持使用 [`ALTER TABLE ... CACHE`](/cached-tables.md) 语句将分区表设为缓存表。 -- 与 TiDB 的[临时表](/temporary-tables.md)功能不兼容。 -- 不支持在分区表上创建[外键](/foreign-key.md)。 -- [`ORDER_INDEX(t1_name, idx1_name [, idx2_name ...])`](/optimizer-hints.md#order_indext1_name-idx1_name--idx2_name-) Hint 对分区表及其相关索引不生效,因为分区表上的索引不支持按顺序读取。 - -### 分区键,主键和唯一键 - -本节讨论分区键,主键和唯一键之间的关系。一句话总结它们之间的关系要满足的规则:**分区表的每个唯一键,必须包含分区表达式中用到的所有列**。 - -这里所指的唯一也包含了主键,因为根据主键的定义,主键必须是唯一的。例如,下面这些建表语句就是无效的: - -{{< 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 t3 ( - col1 INT NOT NULL, - col2 DATE NOT NULL, - col3 INT NOT NULL, - col4 INT NOT NULL, - UNIQUE KEY (col1, col2, col3), - UNIQUE KEY (col1, col3) -) - -PARTITION BY HASH(col1 + col3) - PARTITIONS 4; -``` - -下面这个表就没法做分区了,因为无论如何都不可能找到满足条件的分区键: - -{{< 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; -``` - -以上两个例子中,主键都没有包含分区表达式中的全部的列,在主键中补充缺失列后语句即为合法: - -{{< 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, col3) -) - -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, col2, 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 分区、Range Columns 分区、List 分区、List COLUMNS 分区、Hash 分区和 Key 分区,其它的 MySQL 分区类型尚不支持。 - -对于暂不支持的分区类型,在 TiDB 中建表时会忽略分区信息,以普通表的形式创建,并且会报 Warning。 - -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_list_partition` 可以控制是否启用分区表功能。如果该变量设置为 `OFF`,则建表时会忽略分区信息,以普通表的方式建表。 - -该变量仅作用于建表,已经建表之后再修改该变量无效。详见[系统变量和语法](/system-variables.md#tidb_enable_list_partition-从-v50-版本开始引入)。 - -### 动态裁剪模式 - -TiDB 访问分区表有两种模式,`dynamic` 和 `static`。从 v6.3.0 开始,默认使用 `dynamic` 模式。但是注意,`dynamic` 模式仅在表级别汇总统计信息(即 GlobalStats)收集完成的情况下生效。如果选择了 `dynamic` 但 GlobalStats 未收集完成,TiDB 会仍采用 `static` 模式。关于 GlobalStats 更多信息,请参考[动态裁剪模式下的分区表统计信息](/statistics.md#收集动态裁剪模式下的分区表统计信息)。 - -{{< copyable "sql" >}} - -```sql -set @@session.tidb_partition_prune_mode = 'dynamic' -``` - -普通查询和手动 analyze 使用的是 session 级别的 `tidb_partition_prune_mode` 设置,后台的 auto-analyze 使用的是 global 级别的 `tidb_partition_prune_mode` 设置。 - -静态裁剪模式下,分区表使用的是分区级别的统计信息,而动态裁剪模式下,分区表用的是表级别的汇总统计信息。 - -从 `static` 静态裁剪模式切到 `dynamic` 动态裁剪模式时,需要手动检查和收集统计信息。在刚切换到 `dynamic` 时,分区表上仍然只有分区的统计信息,需要等到全局 `dynamic` 动态裁剪模式开启后的下一次 `auto-analyze` 周期,才会更新生成汇总统计信息。 - -{{< copyable "sql" >}} - -```sql -set session tidb_partition_prune_mode = 'dynamic'; -show stats_meta where table_name like "t"; -``` - -``` -+---------+------------+----------------+---------------------+--------------+-----------+ -| Db_name | Table_name | Partition_name | Update_time | Modify_count | Row_count | -+---------+------------+----------------+---------------------+--------------+-----------+ -| test | t | p0 | 2022-05-27 20:23:34 | 1 | 2 | -| test | t | p1 | 2022-05-27 20:23:34 | 2 | 4 | -| test | t | p2 | 2022-05-27 20:23:34 | 2 | 4 | -+---------+------------+----------------+---------------------+--------------+-----------+ -3 rows in set (0.01 sec) -``` - -为保证开启全局 `dynamic` 动态裁剪模式时,SQL 可以用上正确的统计信息,此时需要手动触发一次 `analyze` 来更新汇总统计信息,可以通过 `analyze` 表或者单个分区来更新。 - -{{< copyable "sql" >}} - -```sql -analyze table t partition p1; -show stats_meta where table_name like "t"; -``` - -``` -+---------+------------+----------------+---------------------+--------------+-----------+ -| Db_name | Table_name | Partition_name | Update_time | Modify_count | Row_count | -+---------+------------+----------------+---------------------+--------------+-----------+ -| test | t | global | 2022-05-27 20:50:53 | 0 | 5 | -| test | t | p0 | 2022-05-27 20:23:34 | 1 | 2 | -| test | t | p1 | 2022-05-27 20:50:52 | 0 | 2 | -| test | t | p2 | 2022-05-27 20:50:08 | 0 | 2 | -+---------+------------+----------------+---------------------+--------------+-----------+ -4 rows in set (0.00 sec) -``` - -若 analyze 过程中提示如下 warning,说明分区的统计信息之间存在不一致,需要重新收集分区或整个表统计信息。 - -``` -| Warning | 8244 | Build table: `t` column: `a` global-level stats failed due to missing partition-level column stats, please run analyze table to refresh columns of all partitions -``` - -也可以使用脚本来统一更新所有的分区表统计信息,详见[为动态裁剪模式更新所有分区表的统计信息](/partitioned-table.md#为动态裁剪模式更新所有分区表的统计信息)。 - -表级别统计信息准备好后,即可开启全局的动态裁剪模式。全局动态裁剪模式,对全局所有的 SQL 和对后台的统计信息自动收集(即 auto analyze)起作用。 - -{{< copyable "sql" >}} - -```sql -set global tidb_partition_prune_mode = dynamic -``` - -在 `static` 模式下,TiDB 用多个算子单独访问每个分区,然后通过 Union 将结果合并起来。下面例子进行了一个简单的读取操作,可以发现 TiDB 用 Union 合并了对应两个分区的结果: - -{{< copyable "sql" >}} - -```sql -mysql> create table t1(id int, age int, key(id)) partition by range(id) ( - partition p0 values less than (100), - partition p1 values less than (200), - partition p2 values less than (300), - partition p3 values less than (400)); -Query OK, 0 rows affected (0.01 sec) - -mysql> explain select * from t1 where id < 150; -``` - -``` -+------------------------------+----------+-----------+------------------------+--------------------------------+ -| id | estRows | task | access object | operator info | -+------------------------------+----------+-----------+------------------------+--------------------------------+ -| PartitionUnion_9 | 6646.67 | root | | | -| ├─TableReader_12 | 3323.33 | root | | data:Selection_11 | -| │ └─Selection_11 | 3323.33 | cop[tikv] | | lt(test.t1.id, 150) | -| │ └─TableFullScan_10 | 10000.00 | cop[tikv] | table:t1, partition:p0 | keep order:false, stats:pseudo | -| └─TableReader_18 | 3323.33 | root | | data:Selection_17 | -| └─Selection_17 | 3323.33 | cop[tikv] | | lt(test.t1.id, 150) | -| └─TableFullScan_16 | 10000.00 | cop[tikv] | table:t1, partition:p1 | keep order:false, stats:pseudo | -+------------------------------+----------+-----------+------------------------+--------------------------------+ -7 rows in set (0.00 sec) -``` - -在 `dynamic` 模式下,每个算子都支持直接访问多个分区,所以 TiDB 不再使用 Union。 - -{{< copyable "sql" >}} - -```sql -mysql> set @@session.tidb_partition_prune_mode = 'dynamic'; -Query OK, 0 rows affected (0.00 sec) - -mysql> explain select * from t1 where id < 150; -+-------------------------+----------+-----------+-----------------+--------------------------------+ -| id | estRows | task | access object | operator info | -+-------------------------+----------+-----------+-----------------+--------------------------------+ -| TableReader_7 | 3323.33 | root | partition:p0,p1 | data:Selection_6 | -| └─Selection_6 | 3323.33 | cop[tikv] | | lt(test.t1.id, 150) | -| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | -+-------------------------+----------+-----------+-----------------+--------------------------------+ -3 rows in set (0.00 sec) -``` - -从以上查询结果可知,执行计划中的 Union 消失了,分区裁剪依然生效,且执行计划只访问了 `p0` 和 `p1` 两个分区。 - -`dynamic` 模式让执行计划更简单清晰,省略 Union 操作可提高执行效率,还可避免 Union 并发管理的问题。此外 `dynamic` 模式下,执行计划可以使用 IndexJoin 的方式,这在 `static` 模式下是无法实现的。请看下面的例子: - -**示例一**:以下示例在 `static` 模式下执行计划带 IndexJoin 的查询。 - -{{< copyable "sql" >}} - -```sql -mysql> create table t1 (id int, age int, key(id)) partition by range(id) - (partition p0 values less than (100), - partition p1 values less than (200), - partition p2 values less than (300), - partition p3 values less than (400)); -Query OK, 0 rows affected (0,08 sec) -mysql> create table t2 (id int, code int); - -Query OK, 0 rows affected (0.01 sec) - -mysql> set @@tidb_partition_prune_mode = 'static'; -Query OK, 0 rows affected (0.00 sec) - -mysql> explain select /*+ TIDB_INLJ(t1, t2) */ t1.* from t1, t2 where t2.code = 0 and t2.id = t1.id; -+--------------------------------+----------+-----------+------------------------+------------------------------------------------+ -| id | estRows | task | access object | operator info | -+--------------------------------+----------+-----------+------------------------+------------------------------------------------+ -| HashJoin_13 | 12.49 | root | | inner join, equal:[eq(test.t1.id, test.t2.id)] | -| ├─TableReader_42(Build) | 9.99 | root | | data:Selection_41 | -| │ └─Selection_41 | 9.99 | cop[tikv] | | eq(test.t2.code, 0), not(isnull(test.t2.id)) | -| │ └─TableFullScan_40 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | -| └─PartitionUnion_15(Probe) | 39960.00 | root | | | -| ├─TableReader_18 | 9990.00 | root | | data:Selection_17 | -| │ └─Selection_17 | 9990.00 | cop[tikv] | | not(isnull(test.t1.id)) | -| │ └─TableFullScan_16 | 10000.00 | cop[tikv] | table:t1, partition:p0 | keep order:false, stats:pseudo | -| ├─TableReader_24 | 9990.00 | root | | data:Selection_23 | -| │ └─Selection_23 | 9990.00 | cop[tikv] | | not(isnull(test.t1.id)) | -| │ └─TableFullScan_22 | 10000.00 | cop[tikv] | table:t1, partition:p1 | keep order:false, stats:pseudo | -| ├─TableReader_30 | 9990.00 | root | | data:Selection_29 | -| │ └─Selection_29 | 9990.00 | cop[tikv] | | not(isnull(test.t1.id)) | -| │ └─TableFullScan_28 | 10000.00 | cop[tikv] | table:t1, partition:p2 | keep order:false, stats:pseudo | -| └─TableReader_36 | 9990.00 | root | | data:Selection_35 | -| └─Selection_35 | 9990.00 | cop[tikv] | | not(isnull(test.t1.id)) | -| └─TableFullScan_34 | 10000.00 | cop[tikv] | table:t1, partition:p3 | keep order:false, stats:pseudo | -+--------------------------------+----------+-----------+------------------------+------------------------------------------------+ -17 rows in set, 1 warning (0.00 sec) - -mysql> show warnings; -+---------+------+------------------------------------------------------------------------------------+ -| Level | Code | Message | -+---------+------+------------------------------------------------------------------------------------+ -| Warning | 1815 | Optimizer Hint /*+ INL_JOIN(t1, t2) */ or /*+ TIDB_INLJ(t1, t2) */ is inapplicable | -+---------+------+------------------------------------------------------------------------------------+ -1 row in set (0,00 sec) -``` - -从以上示例一结果可知,即使使用了 `TIDB_INLJ` 的 hint,也无法使得带分区表的查询选上带 IndexJoin 的执行计划。 - -**示例二**:以下示例在 `dynamic` 模式下尝试执行计划带 IndexJoin 的查询。 - -{{< copyable "sql" >}} - -```sql -mysql> set @@tidb_partition_prune_mode = 'dynamic'; -Query OK, 0 rows affected (0.00 sec) - -mysql> explain select /*+ TIDB_INLJ(t1, t2) */ t1.* from t1, t2 where t2.code = 0 and t2.id = t1.id; -+---------------------------------+----------+-----------+------------------------+---------------------------------------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+---------------------------------+----------+-----------+------------------------+---------------------------------------------------------------------------------------------------------------------+ -| IndexJoin_11 | 12.49 | root | | inner join, inner:IndexLookUp_10, outer key:test.t2.id, inner key:test.t1.id, equal cond:eq(test.t2.id, test.t1.id) | -| ├─TableReader_16(Build) | 9.99 | root | | data:Selection_15 | -| │ └─Selection_15 | 9.99 | cop[tikv] | | eq(test.t2.code, 0), not(isnull(test.t2.id)) | -| │ └─TableFullScan_14 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | -| └─IndexLookUp_10(Probe) | 12.49 | root | partition:all | | -| ├─Selection_9(Build) | 12.49 | cop[tikv] | | not(isnull(test.t1.id)) | -| │ └─IndexRangeScan_7 | 12.50 | cop[tikv] | table:t1, index:id(id) | range: decided by [eq(test.t1.id, test.t2.id)], keep order:false, stats:pseudo | -| └─TableRowIDScan_8(Probe) | 12.49 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | -+---------------------------------+----------+-----------+------------------------+---------------------------------------------------------------------------------------------------------------------+ -8 rows in set (0.00 sec) -``` - -从示例二结果可知,开启 `dynamic` 模式后,带 IndexJoin 的计划在执行查询时被选上。 - -目前,静态裁剪模式不支持执行计划缓存,包括 Prepare 语句和非 Prepare 语句。 - -#### 为动态裁剪模式更新所有分区表的统计信息 - -1. 找到所有的分区表: - - {{< copyable "sql" >}} - - ```sql - SELECT DISTINCT CONCAT(TABLE_SCHEMA,'.', TABLE_NAME) - FROM information_schema.PARTITIONS - WHERE TIDB_PARTITION_ID IS NOT NULL - AND TABLE_SCHEMA NOT IN ('INFORMATION_SCHEMA', 'mysql', 'sys', 'PERFORMANCE_SCHEMA', 'METRICS_SCHEMA'); - ``` - - ``` - +-------------------------------------+ - | concat(TABLE_SCHEMA,'.',TABLE_NAME) | - +-------------------------------------+ - | test.t | - +-------------------------------------+ - 1 row in set (0.02 sec) - ``` - -2. 生成所有分区表的更新统计信息的语句: - - ```sql - SELECT DISTINCT CONCAT('ANALYZE TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,' ALL COLUMNS;') - FROM information_schema.PARTITIONS - WHERE TIDB_PARTITION_ID IS NOT NULL - AND TABLE_SCHEMA NOT IN ('INFORMATION_SCHEMA','mysql','sys','PERFORMANCE_SCHEMA','METRICS_SCHEMA'); - ``` - - ``` - +----------------------------------------------------------------------+ - | concat('ANALYZE TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,' ALL COLUMNS;') | - +----------------------------------------------------------------------+ - | ANALYZE TABLE test.t ALL COLUMNS; | - +----------------------------------------------------------------------+ - 1 row in set (0.01 sec) - ``` - - 可以按需将 `ALL COLUMNS` 改为实际需要的列。 - -3. 将批量更新语句导出到文件: - - ```shell - mysql --host xxxx --port xxxx -u root -p -e "SELECT DISTINCT CONCAT('ANALYZE TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,' ALL COLUMNS;') \ - FROM information_schema.PARTITIONS \ - WHERE TIDB_PARTITION_ID IS NOT NULL \ - AND TABLE_SCHEMA NOT IN ('INFORMATION_SCHEMA','mysql','sys','PERFORMANCE_SCHEMA','METRICS_SCHEMA');" | tee gatherGlobalStats.sql - ``` - -4. 执行批量更新: - - 在运行 source 命令之前处理 SQL 文件: - - ``` - sed -i "" '1d' gatherGlobalStats.sql --- mac - sed -i '1d' gatherGlobalStats.sql --- linux - ``` +不允许使用包含 timestamp 列的任何其他分区表达式。 - {{< copyable "sql" >}} +在以下情况下,范围分区特别有用: - ```sql - SET session tidb_partition_prune_mode = dynamic; - source gatherGlobalStats.sql - ``` +* 你想要删除旧数据。如果使用前面示例中的 `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` 条件。 diff --git a/performance-schema/performance-schema-session-connect-attrs.md b/performance-schema/performance-schema-session-connect-attrs.md index 603f29bd1fa7..12a8cc7ffa5f 100644 --- a/performance-schema/performance-schema-session-connect-attrs.md +++ b/performance-schema/performance-schema-session-connect-attrs.md @@ -1,24 +1,26 @@ --- title: SESSION_CONNECT_ATTRS -summary: 了解 performance_schema 表 `SESSION_CONNECT_ATTRS`。 +summary: 了解 `SESSION_CONNECT_ATTRS` performance_schema 表。 --- # SESSION\_CONNECT\_ATTRS -`SESSION_CONNECT_ATTRS` 表提供了关于连接属性的信息。会话属性是在建立连接时由客户端发送的键值对。 +`SESSION_CONNECT_ATTRS` 表提供了连接属性的信息。会话属性是客户端在建立连接时发送的键值对。 常见属性: -| 属性名 | 示例 | 描述 | -|-------|-----|------| -| `_client_name` | `libmysql` | 客户端库名 | -| `_client_version` | `8.0.33` | 客户端库版本| -| `_os` | `Linux` | 操作系统 | -| `_pid` | `712927` | 进程 ID | -| `_platform` | `x86_64` | CPU 架构 | -| `program_name` | `mysqlsh` | 程序名 | +| 属性名称 | 示例 | 描述 | +|-------------------|---------------|--------------------------| +| `_client_name` | `libmysql` | 客户端库名称 | +| `_client_version` | `8.0.33` | 客户端库版本 | +| `_os` | `Linux` | 操作系统 | +| `_pid` | `712927` | 进程 ID | +| `_platform` | `x86_64` | CPU 架构 | +| `program_name` | `mysqlsh` | 程序名称 | -你可以通过以下方式查看 `SESSION_CONNECT_ATTRS` 表的列信息: +你可以按如下方式查看 `SESSION_CONNECT_ATTRS` 表的列: + +{{< copyable "sql" >}} ```sql USE performance_schema; @@ -36,7 +38,9 @@ DESCRIBE session_connect_attrs; +------------------+---------------------+------+-----+---------+-------+ ``` -你可以通过以下方式查看 `SESSION_CONNECT_ATTRS` 表中存储的会话属性信息: +你可以按如下方式查看存储在 `SESSION_CONNECT_ATTRS` 表中的会话属性信息: + +{{< copyable "sql" >}} ```sql USE performance_schema; @@ -56,9 +60,9 @@ TABLE SESSION_CONNECT_ATTRS; +----------------+-----------------+------------+------------------+ ``` -`SESSION_CONNECT_ATTRS` 表的字段描述如下: +`SESSION_CONNECT_ATTRS` 表中的字段说明如下: -* `PROCESSLIST_ID`:会话的 Processlist ID。 -* `ATTR_NAME`:属性名。 +* `PROCESSLIST_ID`:会话的进程列表 ID。 +* `ATTR_NAME`:属性名称。 * `ATTR_VALUE`:属性值。 -* `ORDINAL_POSITION`:属性名/属性值对的序号。 +* `ORDINAL_POSITION`:名称/值对的序号位置。 diff --git a/performance-schema/performance-schema.md b/performance-schema/performance-schema.md index f889670e7e2b..f2740f5085d6 100644 --- a/performance-schema/performance-schema.md +++ b/performance-schema/performance-schema.md @@ -1,50 +1,50 @@ --- title: Performance Schema -summary: 了解 TiDB `performance_schema` 系统数据库。 +summary: TiDB 实现了用于查看系统元数据的 performance_schema。 --- # Performance Schema -TiDB 实现了兼容 MySQL 的 performance schema 表。 +TiDB 实现了 performance schema 表以保持与 MySQL 的兼容性。 -## 与 MySQL 兼容的表 +## MySQL 兼容性表 -| 表名| 描述 | -| --- | --- | -| `events_stages_current` | | -| `events_stages_history`| | -| `events_stages_history_long` | | -| `events_statements_current` | | -| `events_statements_history` | | -| `events_statements_history_long` | | -| `events_statements_summary_by_digest` | | -| `events_transactions_current` | | -| `events_transactions_history` | | -| `events_transactions_history_long` | | -| `global_status` | | -| `prepared_statements_instances` | | -| [`session_connect_attrs`](/performance-schema/performance-schema-session-connect-attrs.md) | 为会话提供连接属性。 | -| `session_status` | | -| `session_variables` | | -| `setup_actors` | | -| `setup_consumers` | | -| `setup_instruments`| | -| `setup_objects` | | +| 表名 | 描述 | +|--------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `events_stages_current` | | +| `events_stages_history` | | +| `events_stages_history_long` | | +| `events_statements_current` | | +| `events_statements_history` | | +| `events_statements_history_long` | | +| `events_statements_summary_by_digest` | | +| `events_transactions_current` | | +| `events_transactions_history` | | +| `events_transactions_history_long` | | +| `global_status` | | +| `prepared_statements_instances` | | +| [`session_connect_attrs`](/performance-schema/performance-schema-session-connect-attrs.md) | 提供会话的连接属性。 | +| `session_status` | | +| `session_variables` | | +| `setup_actors` | | +| `setup_consumers` | | +| `setup_instruments` | | +| `setup_objects` | | -## TiDB 中的扩展表 +## TiDB 扩展表 -| 表名 | 描述 | -| ------------------------- | ----------- | -| `pd_profile_allocs` | | -| `pd_profile_block` | | -| `pd_profile_cpu` | | -| `pd_profile_goroutines`| | -| `pd_profile_memory` | | -| `pd_profile_mutex` | | -| `tidb_profile_allocs` | | -| `tidb_profile_block`| | -| `tidb_profile_cpu` | | -| `tidb_profile_goroutines` | | -| `tidb_profile_memory` | | -| `tidb_profile_mutex`| | -| `tikv_profile_cpu` | | +| 表名 | 描述 | +|--------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `pd_profile_allocs` | | +| `pd_profile_block` | | +| `pd_profile_cpu` | | +| `pd_profile_goroutines` | | +| `pd_profile_memory` | | +| `pd_profile_mutex` | | +| `tidb_profile_allocs` | | +| `tidb_profile_block` | | +| `tidb_profile_cpu` | | +| `tidb_profile_goroutines` | | +| `tidb_profile_memory` | | +| `tidb_profile_mutex` | | +| `tikv_profile_cpu` | | diff --git a/pessimistic-transaction.md b/pessimistic-transaction.md index 5c2a596ff4bf..6e7a0cac06e3 100644 --- a/pessimistic-transaction.md +++ b/pessimistic-transaction.md @@ -1,19 +1,19 @@ --- title: TiDB 悲观事务模式 -summary: 了解 TiDB 的悲观事务模式。 +summary: 了解 TiDB 中的悲观事务模式。 --- # TiDB 悲观事务模式 -为了使 TiDB 的使用方式更加贴近传统数据库,降低用户迁移的成本,TiDB 自 v3.0 版本开始在乐观事务模型的基础上支持了悲观事务模式。本文将介绍 TiDB 悲观事务的相关特性。 +为了让 TiDB 的使用方式更接近传统数据库并降低迁移成本,从 v3.0 开始,TiDB 在乐观事务模型的基础上支持悲观事务模式。本文介绍 TiDB 悲观事务模式的特点。 > **注意:** > -> 自 v3.0.8 开始,新创建的 TiDB 集群默认使用悲观事务模式。但如果从 v3.0.7 版本及之前创建的集群升级到 >= v3.0.8 的版本,则不会改变默认的事务模式,即**只有新创建的集群才会默认使用悲观事务模式**。 +> 从 v3.0.8 开始,新创建的 TiDB 集群默认使用悲观事务模式。但是,如果你将集群从 v3.0.7 或更早版本升级到 v3.0.8 或更高版本,这不会影响你现有的集群。换句话说,**只有新创建的集群默认使用悲观事务模式**。 -## 事务模式的修改方法 +## 切换事务模式 -你可以使用 [`tidb_txn_mode`](/system-variables.md#tidb_txn_mode) 系统变量设置事务模式。执行以下命令,即可使整个集群中所有新创建 session 执行的所有显示事务(即非 autocommit 的事务)进入悲观事务模式: +你可以通过配置 [`tidb_txn_mode`](/system-variables.md#tidb_txn_mode) 系统变量来设置事务模式。以下命令将集群中新创建会话的所有显式事务(即非自动提交事务)设置为悲观事务模式: {{< copyable "sql" >}} @@ -21,7 +21,7 @@ summary: 了解 TiDB 的悲观事务模式。 SET GLOBAL tidb_txn_mode = 'pessimistic'; ``` -除此之外,还可以执行以下 SQL 语句显式地开启悲观事务: +你也可以通过执行以下 SQL 语句显式启用悲观事务模式: {{< copyable "sql" >}} @@ -31,57 +31,61 @@ BEGIN PESSIMISTIC; {{< copyable "sql" >}} -``` +```sql BEGIN /*T! PESSIMISTIC */; ``` -`BEGIN PESSIMISTIC;` 和 `BEGIN OPTIMISTIC;` 等语句的优先级高于 `tidb_txn_mode` 系统变量。使用这两个语句开启的事务,会忽略系统变量,从而支持悲观、乐观事务混合使用。 +`BEGIN PESSIMISTIC;` 和 `BEGIN OPTIMISTIC;` 语句的优先级高于 `tidb_txn_mode` 系统变量。使用这两个语句启动的事务会忽略系统变量,并支持同时使用悲观和乐观事务模式。 -## 悲观事务模式的行为 +## 行为特征 -悲观事务的行为和 MySQL 基本一致(不一致之处详见[和 MySQL InnoDB 的差异](#和-mysql-innodb-的差异)): +TiDB 中的悲观事务行为与 MySQL 类似。请参见[与 MySQL InnoDB 的差异](#与-mysql-innodb-的差异)了解细微差别。 -- 悲观事务中引入快照读和当前读的概念: +- 对于悲观事务,TiDB 引入了快照读和当前读。 - - 快照读是一种不加锁读,读的是该事务开始时刻前已提交的版本。`SELECT` 语句中的读是快照读。 - - 当前读是一种加锁读,读取的是最新已提交的版本,`UPDATE`、`DELETE` 、`INSERT`、`SELECT FOR UPDATE` 语句中的读是当前读。 + - 快照读:是一种无锁读取,读取事务开始前已提交的版本。`SELECT` 语句中的读取是快照读。 + - 当前读:是一种加锁读取,读取最新已提交的版本。`UPDATE`、`DELETE`、`INSERT` 或 `SELECT FOR UPDATE` 语句中的读取是当前读。 - 以下示例是对快照读和当前读的详细说明: + 以下示例详细说明了快照读和当前读。 - | session 1 | session 2 | session 3 | + | 会话 1 | 会话 2 | 会话 3 | | :----| :---- | :---- | | CREATE TABLE t (a INT); | | | | INSERT INTO T VALUES(1); | | | | BEGIN PESSIMISTIC; | | | UPDATE t SET a = a + 1; | | | | | BEGIN PESSIMISTIC; | | - | | SELECT * FROM t; -- 使用快照读,读取本事务开始前已提交的版本,返回(a=1) | | + | | SELECT * FROM t; -- 使用快照读读取当前事务开始前已提交的版本。结果返回 a=1。 | | | | | BEGIN PESSIMISTIC; - | | | SELECT * FROM t FOR UPDATE; -- 使用当前读,等锁 | - | COMMIT; -- 释放锁,session 3 的 SELECT FOR UPDATE 操作获得锁,使用当前读,读到最新已提交的版本 (a=2) | | | - | | SELECT * FROM t; -- 使用快照读,读取本事务开始前已提交的版本,返回(a=1) | | + | | | SELECT * FROM t FOR UPDATE; -- 使用当前读。等待锁释放。 | + | COMMIT; -- 释放锁。会话 3 的 SELECT FOR UPDATE 操作获得锁,TiDB 使用当前读读取最新已提交的版本。结果返回 a=2。 | | | + | | SELECT * FROM t; -- 使用快照读读取当前事务开始前已提交的版本。结果返回 a=1。 | | + +- 执行 `UPDATE`、`DELETE` 或 `INSERT` 语句时,会读取**最新**的已提交数据,修改数据,并对修改的行应用悲观锁。 -- 悲观锁会在事务提交或回滚时释放。其他尝试修改这一行的写事务会被阻塞,等待悲观锁的释放。其他尝试*读取*这一行的事务不会被阻塞,因为 TiDB 采用多版本并发控制机制 (MVCC)。 +- 对于 `SELECT FOR UPDATE` 语句,会对最新已提交数据的版本应用悲观锁,而不是对修改的行应用。 -- 需要检查唯一性约束的悲观锁可以通过设置系统变量 [`tidb_constraint_check_in_place_pessimistic`](/system-variables.md#tidb_constraint_check_in_place_pessimistic-从-v630-版本开始引入) 控制是否跳过,详见[约束](/constraints.md#悲观事务)。 +- 锁会在事务提交或回滚时释放。其他尝试修改数据的事务会被阻塞,必须等待锁释放。尝试**读取**数据的事务不会被阻塞,因为 TiDB 使用多版本并发控制(MVCC)。 -- 如果多个事务尝试获取各自的锁,会出现死锁,并被检测器自动检测到。其中一个事务会被随机终止掉并返回兼容 MySQL 的错误码 `1213`。 +- 你可以通过设置系统变量 [`tidb_constraint_check_in_place_pessimistic`](/system-variables.md#tidb_constraint_check_in_place_pessimistic-new-in-v630) 来控制是否跳过带有唯一约束检查的悲观锁。详情请参见[约束](/constraints.md#悲观事务)。 -- 通过 `innodb_lock_wait_timeout` 变量,设置事务等锁的超时时间(默认值为 `50`,单位为秒)。等锁超时后返回兼容 MySQL 的错误码 `1205`。如果多个事务同时等待同一个锁释放,会大致按照事务 `start ts` 顺序获取锁。 +- 如果多个事务试图获取彼此的锁,就会发生死锁。这种情况会被自动检测到,其中一个事务会被随机终止,并返回 MySQL 兼容的错误代码 `1213`。 -- 乐观事务和悲观事务可以共存,事务可以任意指定使用乐观模式或悲观模式来执行。 +- 事务最多等待 `innodb_lock_wait_timeout` 秒(默认:50)来获取新锁。当达到此超时时间时,会返回 MySQL 兼容的错误代码 `1205`。如果多个事务在等待同一个锁,优先级顺序大致基于事务的 `start ts`。 -- 支持 `FOR UPDATE NOWAIT` 语法,遇到锁时不会阻塞等锁,而是返回兼容 MySQL 的错误码 `3572`。 +- TiDB 支持在同一集群中同时使用乐观事务模式和悲观事务模式。你可以为事务执行指定任一模式。 -- 如果 `Point Get` 和 `Batch Point Get` 算子没有读到数据,依然会对给定的主键或者唯一键加锁,阻塞其他事务对相同主键唯一键加锁或者进行写入操作。 +- TiDB 支持 `FOR UPDATE NOWAIT` 语法,不会阻塞等待锁释放。相反,会返回 MySQL 兼容的错误代码 `3572`。 -- 支持 `FOR UPDATE OF TABLES` 语法,对于存在多表 join 的语句,只对 `OF TABLES` 中包含的表关联的行进行悲观锁加锁操作。 +- 如果 `Point Get` 和 `Batch Point Get` 算子不读取数据,它们仍会锁定给定的主键或唯一键,这会阻止其他事务锁定或写入相同的主键或唯一键。 -## 和 MySQL InnoDB 的差异 +- TiDB 支持 `FOR UPDATE OF TABLES` 语法。对于连接多个表的语句,TiDB 只对 `OF TABLES` 中的表的相关行应用悲观锁。 -1. 有些 `WHERE` 子句中使用了 range,TiDB 在执行这类 DML 语句和 `SELECT FOR UPDATE` 语句时,不会阻塞 range 内并发的 DML 语句的执行。 +## 与 MySQL InnoDB 的差异 - 举例: +1. 当 TiDB 执行 WHERE 子句中使用范围的 DML 或 `SELECT FOR UPDATE` 语句时,范围内的并发 DML 语句不会被阻塞。 + + 例如: ```sql CREATE TABLE t1 ( @@ -98,80 +102,82 @@ BEGIN /*T! PESSIMISTIC */; ```sql BEGIN /*T! PESSIMISTIC */; - INSERT INTO t1 (id) VALUES (6); -- 仅 MySQL 中出现阻塞。 - UPDATE t1 SET pad1='new value' WHERE id = 5; -- MySQL 和 TiDB 处于等待阻塞状态。 + INSERT INTO t1 (id) VALUES (6); -- 仅在 MySQL 中阻塞 + UPDATE t1 SET pad1='new value' WHERE id = 5; -- 在 MySQL 和 TiDB 中都等待阻塞 ``` - 产生这一行为是因为 TiDB 当前不支持 _gap locking_(间隙锁)。 + 这种行为是因为 TiDB 目前不支持**间隙锁定**。 2. TiDB 不支持 `SELECT LOCK IN SHARE MODE`。 - 使用这个语句执行的时候,效果和没有加锁是一样的,不会阻塞其他事务的读写。 + 当执行 `SELECT LOCK IN SHARE MODE` 时,其效果与不带锁的效果相同,因此不会阻塞其他事务的读取或写入操作。 + +3. DDL 可能导致悲观事务提交失败。 -3. DDL 可能会导致悲观事务提交失败。 + 在 MySQL 中执行 DDL 时,可能会被正在执行的事务阻塞。然而,在 TiDB 中,DDL 操作不会被阻塞,这会导致悲观事务提交失败:`ERROR 1105 (HY000): Information schema is changed. [try again later]`。TiDB 在事务执行期间执行 `TRUNCATE TABLE` 语句可能会导致 `table doesn't exist` 错误。 - MySQL 在执行 DDL 语句时,会被正在执行的事务阻塞住,而在 TiDB 中 DDL 操作会成功,造成悲观事务提交失败:`ERROR 1105 (HY000): Information schema is changed. [try again later]`。TiDB 事务执行过程中并发执行 `TRUNCATE TABLE` 语句,可能会导致事务报错 `table doesn't exist`。 +4. 执行 `START TRANSACTION WITH CONSISTENT SNAPSHOT` 后,MySQL 仍然可以读取其他事务中后来创建的表,而 TiDB 不能。 -4. `START TRANSACTION WITH CONSISTENT SNAPSHOT` 之后,MySQL 仍然可以读取到之后在其他事务创建的表,而 TiDB 不能。 +5. 自动提交事务倾向于使用乐观锁定。 -5. autocommit 事务优先采用乐观事务提交。 - - 使用悲观事务模式时,autocommit 事务首先尝试使用开销更小的乐观事务模式提交。如果发生了写冲突,重试时才会使用悲观事务提交。所以 `tidb_retry_limit = 0` 时,autocommit 事务遇到写冲突仍会报 `Write Conflict` 错误。 + 在使用悲观模式时,自动提交事务首先尝试使用开销较小的乐观模式提交语句。如果发生写冲突,则使用悲观模式重试事务。因此,如果将 `tidb_retry_limit` 设置为 `0`,当发生写冲突时,自动提交事务仍会报告 `Write Conflict` 错误。 - 自动提交的 `SELECT FOR UPDATE` 语句不会等锁。 + 自动提交的 `SELECT FOR UPDATE` 语句不会等待锁。 -6. 对语句中 `EMBEDDED SELECT` 读到的相关数据不会加锁。 +6. 语句中 `EMBEDDED SELECT` 读取的数据不会被锁定。 -7. 垃圾回收 (GC) 不会影响到正在执行的事务,但悲观事务的执行时间仍有上限,默认为 1 小时,可通过 TiDB 配置文件 `[performance]` 类别下的 `max-txn-ttl` 修改。 +7. TiDB 中的打开事务不会阻止垃圾回收(GC)。默认情况下,这将悲观事务的最大执行时间限制为 1 小时。你可以通过编辑 TiDB 配置文件中 `[performance]` 下的 `max-txn-ttl` 来修改此限制。 ## 隔离级别 -TiDB 在悲观事务模式下支持了 2 种隔离级别: +TiDB 在悲观事务模式下支持以下两种隔离级别: -1. 默认使用与 MySQL 行为相同的[可重复读隔离级别 (Repeatable Read)](/transaction-isolation-levels.md#可重复读隔离级别-repeatable-read)。 +- 默认为[可重复读](/transaction-isolation-levels.md#可重复读隔离级别),与 MySQL 相同。 > **注意:** > - > 在这种隔离级别下,DML 操作会基于已提交的最新数据来执行,行为与 MySQL 相同,但与 TiDB 乐观事务不同,请参考[与 MySQL 可重复读隔离级别的区别](/transaction-isolation-levels.md#与-mysql-可重复读隔离级别的区别)。 + > 在此隔离级别下,DML 操作基于最新已提交的数据执行。这种行为与 MySQL 相同,但与 TiDB 的乐观事务模式不同。请参见 [TiDB 与 MySQL 可重复读的区别](/transaction-isolation-levels.md#tidb-与-mysql-可重复读的区别)。 -2. 使用 [`SET TRANSACTION`](/sql-statements/sql-statement-set-transaction.md) 语句可将隔离级别设置为[读已提交隔离级别 (Read Committed)](/transaction-isolation-levels.md#读已提交隔离级别-read-committed)。 +- [读已提交](/transaction-isolation-levels.md#读已提交隔离级别)。你可以使用 [`SET TRANSACTION`](/sql-statements/sql-statement-set-transaction.md) 语句设置此隔离级别。 ## 悲观事务提交流程 -TiDB 悲观锁复用了乐观锁的两阶段提交逻辑,重点在 DML 执行时做了改造。 +在事务提交流程中,悲观事务和乐观事务具有相同的逻辑。两种事务都采用两阶段提交(2PC)模式。悲观事务的重要改动是 DML 执行。 -![TiDB 悲观事务的提交流程](/media/pessimistic-transaction-commit.png) +![TiDB 悲观事务提交流程](/media/pessimistic-transaction-commit.png) -在两阶段提交之前增加了 Acquire Pessimistic Lock 阶段,简要步骤如下。 +悲观事务在 2PC 之前添加了一个 `获取悲观锁` 阶段。此阶段包括以下步骤: -1. (同乐观锁)TiDB 收到来自客户端的 begin 请求,获取当前时间戳作为本事务的 StartTS。 -2. TiDB 收到来自客户端的更新数据的请求:TiDB 向 TiKV 发起加悲观锁请求,该锁持久化到 TiKV。 -3. (同乐观锁)客户端发起 commit,TiDB 开始执行与乐观锁一样的两阶段提交。 +1. (与乐观事务模式相同)TiDB 接收来自客户端的 `begin` 请求,当前时间戳是此事务的 start_ts。 +2. 当 TiDB 服务器接收到来自客户端的写入请求时,TiDB 服务器向 TiKV 服务器发起悲观锁请求,并将锁持久化到 TiKV 服务器。 +3. (与乐观事务模式相同)当客户端发送提交请求时,TiDB 开始执行类似于乐观事务模式的两阶段提交。 ![TiDB 中的悲观事务](/media/pessimistic-transaction-in-tidb.png) -相关细节本节不再赘述,详情可阅读 [TiDB 悲观锁实现原理](https://tidb.net/blog/7730ed79)。 +## 流水线锁定流程 -## Pipelined 加锁流程 +添加悲观锁需要向 TiKV 写入数据。只有在通过 Raft 提交和应用后,才能将成功添加锁的响应返回给 TiDB。因此,与乐观事务相比,悲观事务模式不可避免地具有更高的延迟。 -加悲观锁需要向 TiKV 写入数据,要经过 Raft 提交并 apply 后才能返回,相比于乐观事务,不可避免的会增加部分延迟。为了降低加锁的开销,TiKV 实现了 pipelined 加锁流程:当数据满足加锁要求时,TiKV 立刻通知 TiDB 执行后面的请求,并异步写入悲观锁,从而降低大部分延迟,显著提升悲观事务的性能。但当 TiKV 出现网络隔离或者节点宕机时,悲观锁异步写入有可能失败,从而产生以下影响: +为了减少锁定的开销,TiKV 实现了流水线锁定流程:当数据满足锁定要求时,TiKV 立即通知 TiDB 执行后续请求,并异步写入悲观锁。这个过程减少了大部分延迟,显著提高了悲观事务的性能。但是,当 TiKV 发生网络分区或 TiKV 节点宕机时,异步写入悲观锁可能会失败,并影响以下方面: -* 无法阻塞修改相同数据的其他事务。如果业务逻辑依赖加锁或等锁机制,业务逻辑的正确性将受到影响。 +* 其他修改相同数据的事务无法被阻塞。如果应用逻辑依赖于锁定或锁等待机制,则会影响应用逻辑的正确性。 -* 有较低概率导致事务提交失败,但不会影响事务正确性。 +* 事务提交有较低概率失败,但不影响事务的正确性。 -如果业务逻辑依赖加锁或等锁机制,或者即使在集群异常情况下也要尽可能保证事务提交的成功率,应关闭 pipelined 加锁功能。 + -![Pipelined pessimistic lock](/media/pessimistic-transaction-pipelining.png) +如果应用逻辑依赖于锁定或锁等待机制,或者你希望即使在 TiKV 集群异常的情况下也尽可能保证事务提交的成功率,你应该禁用流水线锁定功能。 -该功能默认开启,可修改 TiKV 配置关闭: +![流水线悲观锁](/media/pessimistic-transaction-pipelining.png) + +此功能默认启用。要禁用它,请修改 TiKV 配置: ```toml [pessimistic-txn] pipelined = false ``` -若集群是 v4.0.9 及以上版本,也可通过[在线修改 TiKV 配置](/dynamic-config.md#在线修改-tikv-配置)功能动态关闭该功能: +如果 TiKV 集群是 v4.0.9 或更高版本,你也可以通过[动态修改 TiKV 配置](/dynamic-config.md#动态修改-tikv-配置)来动态禁用此功能: {{< copyable "sql" >}} @@ -179,24 +185,32 @@ pipelined = false set config tikv pessimistic-txn.pipelined='false'; ``` + + + + +如果应用逻辑依赖于锁定或锁等待机制,或者你希望即使在 TiKV 集群异常的情况下也尽可能保证事务提交的成功率,你可以[联系 TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)来禁用流水线锁定功能。 + + + ## 内存悲观锁 -TiKV 在 v6.0.0 中引入了内存悲观锁功能。开启内存悲观锁功能后,悲观锁通常只会被存储在 Region leader 的内存中,而不会将锁持久化到磁盘,也不会通过 Raft 协议将锁同步到其他副本,因此可以大大降低悲观事务加锁的开销,提升悲观事务的吞吐并降低延迟。 +在 v6.0.0 中,TiKV 引入了内存悲观锁功能。启用此功能后,悲观锁通常只存储在 Region leader 的内存中,不会持久化到磁盘或通过 Raft 复制到其他副本。此功能可以大大减少获取悲观锁的开销,提高悲观事务的吞吐量。 -当内存悲观锁占用的内存达到 Region 或节点的阈值时,加悲观锁会回退为使用 [pipelined 加锁流程](#pipelined-加锁流程)。当 Region 发生合并或 leader 迁移时,为避免悲观锁丢失,TiKV 会将内存悲观锁写入磁盘并同步到其他副本。 +当内存悲观锁的内存使用超过 Region 或 TiKV 节点的内存阈值时,获取悲观锁会转为[流水线锁定流程](#流水线锁定流程)。当 Region 合并或 leader 转移时,为避免悲观锁丢失,TiKV 会将内存悲观锁写入磁盘并复制到其他副本。 -内存悲观锁实现了和 [pipelined 加锁](#pipelined-加锁流程)类似的表现,即集群无异常时不影响加锁表现,但当 TiKV 出现网络隔离或者节点宕机时,事务加的悲观锁可能丢失。 +内存悲观锁的表现与流水线锁定流程类似,在集群健康时不影响锁的获取。但是,当 TiKV 发生网络隔离或 TiKV 节点宕机时,已获取的悲观锁可能会丢失。 -如果业务逻辑依赖加锁或等锁机制,或者即使在集群异常情况下也要尽可能保证事务提交的成功率,应**关闭**内存悲观锁功能。 +如果应用逻辑依赖于锁获取或锁等待机制,或者你希望即使在集群异常状态下也尽可能保证事务提交的成功率,你需要**禁用**内存悲观锁功能。 -该功能默认开启。如要关闭,可修改 TiKV 配置: +此功能默认启用。要禁用它,请修改 TiKV 配置: ```toml [pessimistic-txn] in-memory = false ``` -也可通过[在线修改 TiKV 配置](/dynamic-config.md#在线修改-tikv-配置)功能动态关闭该功能: +要动态禁用此功能,请动态修改 TiKV 配置: {{< copyable "sql" >}} diff --git a/placement-rules-in-sql.md b/placement-rules-in-sql.md index 041263bbee65..dc6db67e6734 100644 --- a/placement-rules-in-sql.md +++ b/placement-rules-in-sql.md @@ -1,58 +1,76 @@ --- -title: Placement Rules in SQL -summary: 了解如何通过 SQL 接口调度表和分区的放置位置。 +title: SQL 中的放置规则 +summary: 了解如何使用 SQL 语句调度表和分区的数据放置。 --- -# Placement Rules in SQL +# SQL 中的放置规则 -Placement Rules in SQL 特性用于通过 SQL 语句配置数据在 TiKV 集群中的放置位置。通过该功能,你可以将集群、数据库、表、或分区的数据部署到不同的地域、机房、机柜、主机。 +SQL 中的放置规则是一项功能,可让你使用 SQL 语句指定数据在 TiKV 集群中的存储位置。通过此功能,你可以将集群、数据库、表或分区的数据调度到特定的区域、数据中心、机架或主机。 -该功能可以实现以下业务场景: +此功能可以满足以下使用场景: -- 多数据中心部署,配置规则优化数据高可用策略 -- 合并多个不同业务的数据库,物理隔离不同用户的数据,满足实例内部不同用户的隔离需求 -- 增加重要数据的副本数,提高业务可用性和数据可靠性 +- 跨多个数据中心部署数据,并配置规则以优化高可用性策略。 +- 合并来自不同应用程序的多个数据库,并在物理上隔离不同用户的数据,满足实例内不同用户的隔离要求。 +- 增加重要数据的副本数量,以提高应用程序可用性和数据可靠性。 -## 功能概述 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 -通过 Placement Rules in SQL 功能, 你可以[创建放置策略 (placement policy)](#创建并绑定放置策略),并为不同的数据级别配置所需的放置策略,粒度从粗到细为: +## 概述 -| 级别 | 描述 | -|----------------------------|------------------------------------------------------------------------------------------------| -| 集群 | TiDB 默认为集群配置 3 副本的策略。你可以为集群配置全局放置策略,参考[集群配置](#为集群指定全局的副本数)。 | -| 数据库 | 你可以为指定的 Database 配置放置策略,参考[为数据库指定默认的放置策略](#为数据库指定默认的放置策略)。 | -| 表 | 你可以为指定的 Table 配置放置策略,参考[为表指定放置策略](#为表指定放置策略)。 | -| 分区 | 你可以为表中不同的 Row 创建分区,并单独对分区配置放置策略,参考[为分区表指定放置策略](#为分区表指定放置策略)。 | +通过 SQL 中的放置规则功能,你可以[创建放置策略](#创建和附加放置策略)并为不同级别的数据配置所需的放置策略,粒度从粗到细如下: + +| 级别 | 描述 | +|------------------|--------------------------------------------------------------------------------------| +| 集群 | 默认情况下,TiDB 为集群配置 3 个副本的策略。你可以为集群配置全局放置策略。更多信息,请参见[为集群全局指定副本数量](#为集群全局指定副本数量)。 | +| 数据库 | 你可以为特定数据库配置放置策略。更多信息,请参见[为数据库指定默认放置策略](#为数据库指定默认放置策略)。 | +| 表 | 你可以为特定表配置放置策略。更多信息,请参见[为表指定放置策略](#为表指定放置策略)。 | +| 分区 | 你可以为表中的不同行创建分区,并为分区单独配置放置策略。更多信息,请参见[为分区表指定放置策略](#为分区表指定放置策略)。 | -> **建议:** +> **提示:** > -> Placement Rules in SQL 底层的实现依赖 PD 提供的放置规则 (placement rules) 功能,参考 [Placement Rules 使用文档](/configure-placement-rules.md)。在 Placement Rules in SQL 语境下,放置规则既可以代指绑定对象的放置策略 (placement policy),也可以代指 TiDB 发给 PD 的放置规则。 +> *SQL 中的放置规则*的实现依赖于 PD 的*放置规则功能*。详情请参考[配置放置规则](https://docs.pingcap.com/tidb/stable/configure-placement-rules)。在 SQL 中的放置规则上下文中,*放置规则*可能指附加到其他对象的*放置策略*,或从 TiDB 发送到 PD 的规则。 -## 使用限制 +## 限制 -- 为了降低运维难度,建议将一个集群的 placement policy 数量限制在 10 个以内。 -- 建议将绑定了 placement policy 的表和分区数的总数限制在 10000 以内。为过多的表和分区绑定 policy,会增加 PD 上规则计算的负担,从而影响服务性能。 -- 建议按照本文中提到的示例场景使用 Placement Rules in SQL 功能,不建议使用复杂的放置策略。 +- 为简化维护,建议将集群内的放置策略数量限制在 10 个或更少。 +- 建议将附加了放置策略的表和分区的总数限制在 10,000 个或更少。为太多表和分区附加策略会增加 PD 的计算工作负载,从而影响服务性能。 +- 建议按照本文档提供的示例使用 SQL 中的放置规则功能,而不是使用其他复杂的放置策略。 ## 前提条件 -放置策略依赖于 TiKV 节点标签 (label) 的配置。例如,放置选项 `PRIMARY_REGION` 依赖 TiKV 中的 `region` 标签。 +放置策略依赖于 TiKV 节点上的标签配置。例如,`PRIMARY_REGION` 放置选项依赖于 TiKV 中的 `region` 标签。 -创建放置策略时,TiDB 不会检查标签是否存在,而是在绑定放置策略的时候进行检查。因此,在绑定放置策略前,请确保各个 TiKV 节点已配置正确的标签。配置方法为: + + +当你创建放置策略时,TiDB 不会检查策略中指定的标签是否存在。相反,TiDB 会在你附加策略时执行检查。因此,在附加放置策略之前,请确保每个 TiKV 节点都配置了正确的标签。TiDB Self-Managed 集群的配置方法如下: ``` tikv-server --labels region=,zone=,host= ``` -详细配置方法可参考以下示例: +有关详细配置方法,请参见以下示例: -| 方式 | 示例 | +| 部署方法 | 示例 | | --- | --- | -| 手动部署 | [通过拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md) | -| TiUP 部署 | [跨机房部署拓扑结构](/geo-distributed-deployment-topology.md) | -| Operator 部署| [在 Kubernetes 中配置 TiDB 集群](https://docs.pingcap.com/zh/tidb-in-kubernetes/stable/configure-a-tidb-cluster#高数据的高可用) | +| 手动部署 | [使用拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md) | +| 使用 TiUP 部署 | [跨地域部署拓扑](/geo-distributed-deployment-topology.md) | +| 使用 TiDB Operator 部署 | [在 Kubernetes 中配置 TiDB 集群](https://docs.pingcap.com/tidb-in-kubernetes/stable/configure-a-tidb-cluster#high-data-high-availability) | + +> **注意:** +> +> 对于 TiDB Cloud Dedicated 集群,你可以跳过这些标签配置步骤,因为 TiDB Cloud Dedicated 集群中的 TiKV 节点上的标签是自动配置的。 -如需查看当前 TiKV 集群中所有可用的标签,可以使用 [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md) 语句: + + + + +对于 TiDB Cloud Dedicated 集群,TiKV 节点上的标签是自动配置的。 + + + +要查看当前 TiKV 集群中的所有可用标签,你可以使用 [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md) 语句: ```sql SHOW PLACEMENT LABELS; @@ -68,24 +86,24 @@ SHOW PLACEMENT LABELS; ## 使用方法 -本节介绍如何通过 SQL 语句创建、绑定、查看、修改、删除放置策略。 +本节介绍如何使用 SQL 语句创建、附加、查看、修改和删除放置策略。 -### 创建并绑定放置策略 +### 创建和附加放置策略 -1. 使用 [`CREATE PLACEMENT POLICY`](/sql-statements/sql-statement-create-placement-policy.md) 语句创建放置策略: +1. 要创建放置策略,使用 [`CREATE PLACEMENT POLICY`](/sql-statements/sql-statement-create-placement-policy.md) 语句: ```sql CREATE PLACEMENT POLICY myplacementpolicy PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-west-1"; ``` - 在该语句中: + 在此语句中: - - `PRIMARY_REGION="us-east-1"` 选项代表 Raft leader 被放置在 `region` 标签为 `us-east-1` 的节点上。 - - `REGIONS="us-east-1,us-west-1"` 选项代表 Raft followers 被放置在 `region` 标签为 `us-east-1` 和 `region` 标签为 `us-west-1` 的节点上。 + - `PRIMARY_REGION="us-east-1"` 选项表示将 Raft Leaders 放置在 `region` 标签为 `us-east-1` 的节点上。 + - `REGIONS="us-east-1,us-west-1"` 选项表示将 Raft Followers 放置在 `region` 标签为 `us-east-1` 和 `region` 标签为 `us-west-1` 的节点上。 - 更多可配置的放置选项和对应的含义,请参考[放置选项](#放置选项参考)。 + 有关可配置的放置选项及其含义,请参见[放置选项参考](#放置选项参考)。 -2. 使用 `CREATE TABLE` 或者 `ALTER TABLE` 将放置策略绑定至表或分区表,这样就在表或分区上指定了放置策略: +2. 要将放置策略附加到表或分区表,使用 `CREATE TABLE` 或 `ALTER TABLE` 语句为该表或分区表指定放置策略: ```sql CREATE TABLE t1 (a INT) PLACEMENT POLICY=myplacementpolicy; @@ -93,11 +111,11 @@ SHOW PLACEMENT LABELS; ALTER TABLE t2 PLACEMENT POLICY=myplacementpolicy; ``` - `PLACEMENT POLICY` 为全局作用域,不与任何数据库表结构相关联。因此,通过 `CREATE TABLE` 指定放置策略时,无需任何额外的权限。 + `PLACEMENT POLICY` 不与任何数据库架构关联,可以在全局范围内附加。因此,使用 `CREATE TABLE` 指定放置策略不需要任何额外的权限。 ### 查看放置策略 -- 要查看某条已创建的放置策略,可以使用 [`SHOW CREATE PLACEMENT POLICY`](/sql-statements/sql-statement-show-create-placement-policy.md) 语句: +- 要查看现有的放置策略,你可以使用 [`SHOW CREATE PLACEMENT POLICY`](/sql-statements/sql-statement-show-create-placement-policy.md) 语句: ```sql SHOW CREATE PLACEMENT POLICY myplacementpolicy\G @@ -107,7 +125,7 @@ SHOW PLACEMENT LABELS; 1 row in set (0.00 sec) ``` -- 要查看某张表绑定的放置策略,可以使用 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 语句: +- 要查看附加到特定表的放置策略,你可以使用 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 语句: ```sql SHOW CREATE TABLE t1\G @@ -119,7 +137,7 @@ SHOW PLACEMENT LABELS; 1 row in set (0.00 sec) ``` -- 要查看集群中所有放置策略的定义,可以查询 [`INFORMATION_SCHEMA.PLACEMENT_POLICIES`](/information-schema/information-schema-placement-policies.md) 系统表: +- 要查看集群中放置策略的定义,你可以查询 [`INFORMATION_SCHEMA.PLACEMENT_POLICIES`](/information-schema/information-schema-placement-policies.md) 系统表: ```sql SELECT * FROM information_schema.placement_policies\G @@ -133,25 +151,25 @@ SHOW PLACEMENT LABELS; LEADER_CONSTRAINTS | FOLLOWER_CONSTRAINTS | LEARNER_CONSTRAINTS | - SCHEDULE | + SCHEDULE | FOLLOWERS | 4 LEARNERS | 0 1 row in set ``` -- 要查看集群中所有绑定了放置策略的表,可以查询 `information_schema.tables` 系统表的 `tidb_placement_policy_name` 列: +- 要查看集群中所有附加了放置策略的表,你可以查询 `information_schema.tables` 系统表的 `tidb_placement_policy_name` 列: ```sql SELECT * FROM information_schema.tables WHERE tidb_placement_policy_name IS NOT NULL; ``` -- 要查看集群中所有绑定了放置策略的分区,可以查询 `information_schema.partitions` 系统表的 `tidb_placement_policy_name` 列: +- 要查看集群中所有附加了放置策略的分区,你可以查询 `information_schema.partitions` 系统表的 `tidb_placement_policy_name` 列: ```sql SELECT * FROM information_schema.partitions WHERE tidb_placement_policy_name IS NOT NULL; ``` -- 所有绑定放置策略的对象都是异步调度的。要查看放置策略的调度进度,可以使用 [`SHOW PLACEMENT`](/sql-statements/sql-statement-show-placement.md) 语句。 +- 附加到所有对象的放置策略都是*异步*应用的。要检查放置策略的调度进度,你可以使用 [`SHOW PLACEMENT`](/sql-statements/sql-statement-show-placement.md) 语句: ```sql SHOW PLACEMENT; @@ -159,17 +177,17 @@ SHOW PLACEMENT LABELS; ### 修改放置策略 -要修改放置策略,可以使用 [`ALTER PLACEMENT POLICY`](/sql-statements/sql-statement-alter-placement-policy.md) 语句。该修改将应用于所有绑定了此放置策略的对象。 +要修改放置策略,你可以使用 [`ALTER PLACEMENT POLICY`](/sql-statements/sql-statement-alter-placement-policy.md) 语句。修改将应用于附加了相应策略的所有对象。 ```sql ALTER PLACEMENT POLICY myplacementpolicy FOLLOWERS=4; ``` -在该语句中,`FOLLOWERS=4` 选项代表数据有 5 个副本,包括 4 个 follower 和 1 个 leader。更多可配置的放置选项和对应的含义,请参考[放置选项](#放置选项参考)。 +在此语句中,`FOLLOWERS=4` 选项表示为数据配置 5 个副本,包括 4 个 Followers 和 1 个 Leader。有关可配置的放置选项及其含义,请参见[放置选项参考](#放置选项参考)。 ### 删除放置策略 -要删除没有绑定任何表或分区的放置策略,可以使用 [`DROP PLACEMENT POLICY`](/sql-statements/sql-statement-drop-placement-policy.md) 语句: +要删除未附加到任何表或分区的策略,你可以使用 [`DROP PLACEMENT POLICY`](/sql-statements/sql-statement-drop-placement-policy.md) 语句: ```sql DROP PLACEMENT POLICY myplacementpolicy; @@ -177,67 +195,65 @@ DROP PLACEMENT POLICY myplacementpolicy; ## 放置选项参考 -在创建和修改放置策略时,你可以按需配置放置选项。 +创建或修改放置策略时,你可以根据需要配置放置选项。 > **注意:** > -> `PRIMARY_REGION`、`REGIONS` 和 `SCHEDULE` 选项不可与 `CONSTRAINTS` 选项同时指定,否则会报错。 +> `PRIMARY_REGION`、`REGIONS` 和 `SCHEDULE` 选项不能与 `CONSTRAINTS` 选项一起指定,否则会出错。 ### 常规放置选项 -常规放置选项可以满足数据放置的基本需求。 +常规放置选项可以满足数据放置的基本要求。 -| 选项名 | 描述 | +| 选项名称 | 描述 | |----------------------------|------------------------------------------------------------------------------------------------| -| `PRIMARY_REGION` | Raft leader 被放置在有 `region` 标签的节点上,且这些 `region` 标签匹配本选项的值。 | -| `REGIONS` | Raft followers 被放置在有 `region` 标签的节点上,且这些 `region` 标签匹配本选项的值。 | -| `SCHEDULE` | 用于调度 follower 放置位置的策略。可选值为 `EVEN`(默认值)或 `MAJORITY_IN_PRIMARY`。 | -| `FOLLOWERS` | Follower 的数量。例如 `FOLLOWERS=2` 表示数据有 3 个副本(2 个 follower 和 1 个 leader)。 | +| `PRIMARY_REGION` | 指定将 Raft Leaders 放置在 `region` 标签与此选项值匹配的节点上。 | +| `REGIONS` | 指定将 Raft Followers 放置在 `region` 标签与此选项值匹配的节点上。 | +| `SCHEDULE` | 指定调度 Followers 放置的策略。值选项为 `EVEN`(默认)或 `MAJORITY_IN_PRIMARY`。 | +| `FOLLOWERS` | 指定 Followers 的数量。例如,`FOLLOWERS=2` 表示数据将有 3 个副本(2 个 Followers 和 1 个 Leader)。 | ### 高级放置选项 -高级配置选项可以更灵活地放置数据,满足复杂的场景需求,但其配置方法相对常规配置选项更复杂一些,需要你对集群拓扑和 TiDB 数据分片有深入的了解。 +高级配置选项为数据放置提供了更大的灵活性,以满足复杂场景的要求。但是,配置高级选项比常规选项更复杂,需要你对集群拓扑和 TiDB 数据分片有深入的了解。 -| 选项名 | 描述 | -|----------------------------|------------------------------------------------------------------------------------------------| -| `CONSTRAINTS` | 适用于所有角色 (role) 的约束列表。例如,`CONSTRAINTS="[+disk=ssd]"`。| -| `LEADER_CONSTRAINTS` | 仅适用于 leader 的约束列表。 | -| `FOLLOWER_CONSTRAINTS` | 仅适用于 follower 的约束列表。 | -| `LEARNER_CONSTRAINTS` | 仅适用于 learner 的约束列表。 | -| `LEARNERS` | 指定 learner 的数量。 | -| `SURVIVAL_PREFERENCE` | 指定按 label 容灾等级的优先级放置副本。例如 `SURVIVAL_PREFERENCE="[region, zone, host]"`。 | +| 选项名称 | 描述 | +| --------------| ------------ | +| `CONSTRAINTS` | 适用于所有角色的约束列表。例如,`CONSTRAINTS="[+disk=ssd]"`。 | +| `LEADER_CONSTRAINTS` | 仅适用于 Leader 的约束列表。 | +| `FOLLOWER_CONSTRAINTS` | 仅适用于 Followers 的约束列表。 | +| `LEARNER_CONSTRAINTS` | 仅适用于 learners 的约束列表。 | +| `LEARNERS` | learners 的数量。 | +| `SURVIVAL_PREFERENCE` | 根据标签的灾难容忍级别的副本放置优先级。例如,`SURVIVAL_PREFERENCE="[region, zone, host]"`。 | ### CONSTRAINTS 格式 -`CONSTRAINTS`、`FOLLOWER_CONSTRAINTS`、`LEARNER_CONSTRAINTS` 放置选项支持以下两种配置格式: +你可以使用以下任一格式配置 `CONSTRAINTS`、`FOLLOWER_CONSTRAINTS` 和 `LEARNER_CONSTRAINTS` 放置选项: | CONSTRAINTS 格式 | 描述 | |----------------------------|-----------------------------------------------------------------------------------------------------------| -| 列表格式 | 如果指定的约束适用于所有副本,可以使用键值对列表格式。键以 `+` 或 `-` 开头。例如:
  • `[+region=us-east-1]` 表示放置数据在 `region` 标签为 `us-east-1` 的节点上。
  • `[+region=us-east-1,-type=fault]` 表示放置数据在 `region` 标签为 `us-east-1` 且 `type` 标签不为 `fault` 的节点上。

| -| 字典格式 | 如果需要为不同的约束指定不同数量的副本,可以使用字典格式。例如:
  • `FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,+region=us-east-2: 1,+region=us-west-1: 1}";` 表示 1 个 follower 位于 `us-east-1`,1 个 follower 位于 `us-east-2`,1 个 follower 位于 `us-west-1`。
  • `FOLLOWER_CONSTRAINTS='{"+region=us-east-1,+type=scale-node": 1,"+region=us-west-1": 1}';` 表示 1 个 follower 位于 `us-east-1` 区域中有标签 `type` 为 `scale-node` 的节点上,1 个 follower 位于 `us-west-1`。
字典格式支持以 `+` 或 `-` 开头的键,并支持配置特殊的 `#evict-leader` 属性。例如,`FOLLOWER_CONSTRAINTS='{"+region=us-east-1":1, "+region=us-east-2": 2, "+region=us-west-1,#evict-leader": 1}'` 表示当进行容灾时,`us-west-1` 上尽可能驱逐当选的 leader。| +| 列表格式 | 如果要指定的约束适用于所有副本,你可以使用键值列表格式。每个键以 `+` 或 `-` 开头。例如:
  • `[+region=us-east-1]` 表示将数据放置在具有 `region` 标签为 `us-east-1` 的节点上。
  • `[+region=us-east-1,-type=fault]` 表示将数据放置在具有 `region` 标签为 `us-east-1` 但不具有 `type` 标签为 `fault` 的节点上。

| +| 字典格式 | 如果需要为不同的约束指定不同数量的副本,你可以使用字典格式。例如:
  • `FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,+region=us-east-2: 1,+region=us-west-1: 1}";` 表示在 `us-east-1` 中放置一个 Follower,在 `us-east-2` 中放置一个 Follower,在 `us-west-1` 中放置一个 Follower。
  • `FOLLOWER_CONSTRAINTS='{"+region=us-east-1,+type=scale-node": 1,"+region=us-west-1": 1}';` 表示在位于 `us-east-1` 区域且具有 `type` 标签为 `scale-node` 的节点上放置一个 Follower,在 `us-west-1` 中放置一个 Follower。
字典格式支持每个键以 `+` 或 `-` 开头,并允许你配置特殊的 `#evict-leader` 属性。例如,`FOLLOWER_CONSTRAINTS='{"+region=us-east-1":1, "+region=us-east-2": 2, "+region=us-west-1,#evict-leader": 1}'` 表示在灾难恢复期间,将尽可能驱逐 `us-west-1` 中的 Leaders。| > **注意:** > -> - `LEADER_CONSTRAINTS` 放置选项只支持列表格式。 -> - 字典和列表格式都基于 YAML 解析,但 YAML 语法有时不能被正常解析。例如 YAML 会把 `"{+region=east:1,+region=west:2}"`(`:` 后无空格)错误地解析成 `'{"+region=east:1": null, "+region=west:2": null}'`,不符合预期。但 `"{+region=east: 1,+region=west: 2}"`(`:` 后有空格)能被正确解析成 `'{"+region=east": 1, "+region=west": 2}'`。因此建议 `:` 后加上空格。 -> +> - `LEADER_CONSTRAINTS` 放置选项仅支持列表格式。 +> - 列表和字典格式都基于 YAML 解析器,但在某些情况下可能会错误解析 YAML 语法。例如,`"{+region=east:1,+region=west:2}"` (`:` 后没有空格)可能会被错误解析为 `'{"+region=east:1": null, "+region=west:2": null}'`,这是意外的。但是,`"{+region=east: 1,+region=west: 2}"` (`:` 后有空格)可以被正确解析为 `'{"+region=east": 1, "+region=west": 2}'`。因此,建议在 `:` 后添加空格。 +## 基本示例 -## 基础示例 +### 为集群全局指定副本数量 -### 为集群指定全局的副本数 - -集群初始化后,副本数默认值为 `3`。集群如需更多的副本数,可使用配置策略调大该值,应用到集群级别,可以使用 [`ALTER RANGE`](/sql-statements/sql-statement-alter-range.md)。示例如下: +集群初始化后,默认副本数为 `3`。如果集群需要更多副本,你可以通过配置放置策略来增加这个数量,然后使用 [`ALTER RANGE`](/sql-statements/sql-statement-alter-range.md) 在集群级别应用该策略。例如: ```sql CREATE PLACEMENT POLICY five_replicas FOLLOWERS=4; ALTER RANGE global PLACEMENT POLICY five_replicas; ``` -注意,TiDB 默认 leader 个数是 1。因此,5 个副本为 4 个 follower 和 1 个 leader。 +注意,由于 TiDB 默认 Leaders 数量为 `1`,`five replicas` 表示 `4` 个 Followers 和 `1` 个 Leader。 -### 为数据库指定默认的放置策略 +### 为数据库指定默认放置策略 -你可以为某个数据库指定默认的放置策略,类似于为数据库设置默认字符集或排序规则。如果数据库中的表或分区没有单独指定其他放置策略,就会使用数据库上指定的放置策略。示例如下: +你可以为数据库指定默认放置策略。这类似于为数据库设置默认字符集或排序规则。如果数据库中的表或分区没有指定其他放置策略,则数据库的放置策略将应用于该表和分区。例如: ```sql CREATE PLACEMENT POLICY p1 PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2"; -- 创建放置策略 @@ -246,38 +262,38 @@ CREATE PLACEMENT POLICY p2 FOLLOWERS=4; CREATE PLACEMENT POLICY p3 FOLLOWERS=2; -CREATE TABLE t1 (a INT); -- 创建表 t1,且未指定放置策略。 +CREATE TABLE t1 (a INT); -- 创建表 t1,未指定任何放置策略。 -ALTER DATABASE test PLACEMENT POLICY=p2; -- 更改数据库默认的放置策略为 p2,但更改不影响已有的表 t1。 +ALTER DATABASE test PLACEMENT POLICY=p2; -- 更改数据库的默认放置策略为 p2,不会应用于现有表 t1。 -CREATE TABLE t2 (a INT); -- 创建表 t2,默认的放置策略 p2 在 t2 上生效。 +CREATE TABLE t2 (a INT); -- 创建表 t2。默认放置策略 p2 应用于 t2。 -CREATE TABLE t3 (a INT) PLACEMENT POLICY=p1; -- 创建表 t3。因为语句中已经指定了其他放置策略,默认的 p2 策略在 t3 上不生效。 +CREATE TABLE t3 (a INT) PLACEMENT POLICY=p1; -- 创建表 t3。因为此语句指定了另一个放置规则,默认放置策略 p2 不会应用于表 t3。 -ALTER DATABASE test PLACEMENT POLICY=p3; -- 再次更改数据库默认的放置策略,此更改不影响已有的表。 +ALTER DATABASE test PLACEMENT POLICY=p3; -- 再次更改数据库的默认策略,不会应用于现有表。 -CREATE TABLE t4 (a INT); -- 创建表 t4,默认的放置策略 p3 在 t4 生效。 +CREATE TABLE t4 (a INT); -- 创建表 t4。默认放置策略 p3 应用于 t4。 -ALTER PLACEMENT POLICY p3 FOLLOWERS=3; -- 绑定策略 p3 的表,也就是 t4,会采用 FOLLOWERS=3。 +ALTER PLACEMENT POLICY p3 FOLLOWERS=3; -- `FOLLOWERS=3` 应用于附加了策略 p3 的表(即表 t4)。 ``` -注意分区与表之间的继承和这里的继承不同。改变表的默认放置策略,也会让分区应用新的策略。但是只有建表时没有指定放置策略,表才会从数据库继承放置策略,且之后再改变数据库的默认放置策略也不影响已经继承的表。 +注意,表到其分区的策略继承与上述示例中的策略继承不同。当你更改表的默认策略时,新策略也会应用于该表中的分区。但是,只有在创建表时未指定任何策略时,表才会从数据库继承策略。一旦表从数据库继承了策略,修改数据库的默认策略不会应用于该表。 ### 为表指定放置策略 -你可以为某个表指定默认的放置策略。示例如下: +你可以为表指定默认放置策略。例如: ```sql CREATE PLACEMENT POLICY five_replicas FOLLOWERS=4; -CREATE TABLE t (a INT) PLACEMENT POLICY=five_replicas; -- 创建表 t。绑定放置策略为 five_replicas。 +CREATE TABLE t (a INT) PLACEMENT POLICY=five_replicas; -- 创建表 t 并将 'five_replicas' 放置策略附加到它。 -ALTER TABLE t PLACEMENT POLICY=default; -- 删除表 t 已绑定的放置策略 five_replicas,重置为默认的放置策略。 +ALTER TABLE t PLACEMENT POLICY=default; -- 从表 t 移除 'five_replicas' 放置策略,并重置为默认放置策略。 ``` ### 为分区表指定放置策略 -你还可以给表分区指定放置策略。示例如下: +你也可以为分区表或分区指定放置策略。例如: ```sql CREATE PLACEMENT POLICY storageforhisotrydata CONSTRAINTS="[+node=history]"; @@ -295,22 +311,21 @@ PARTITION BY RANGE( YEAR(purchased) ) ( ); ``` -如果没有为表中的某个分区指定任何放置策略,该分区将尝试继承表上可能存在的策略。在上面示例中: +如果表中的分区没有指定放置策略,该分区会尝试从表继承策略(如果有)。在上述示例中: -- `p0` 分区将会应用 `storageforhisotrydata` 策略 -- `p4` 分区将会应用 `storagefornewdata` 策略 -- `p1`、`p2`、`p3` 分区将会应用表 `t1` 的放置策略 `companystandardpolicy` -- 如果 `t1` 没有绑定任何策略,`p1`、`p2`、`p3` 会继承数据库或全局的默认策略 +- `p0` 分区将应用 `storageforhisotrydata` 策略。 +- `p4` 分区将应用 `storagefornewdata` 策略。 +- `p1`、`p2` 和 `p3` 分区将应用从表 `t1` 继承的 `companystandardpolicy` 放置策略。 +- 如果没有为表 `t1` 指定放置策略,`p1`、`p2` 和 `p3` 分区将继承数据库默认策略或全局默认策略。 -给分区绑定放置策略后,你可以更改指定分区的放置策略。示例如下: +在这些分区附加了放置策略后,你可以像下面的示例一样更改特定分区的放置策略: ```sql ALTER TABLE t1 PARTITION p1 PLACEMENT POLICY=storageforhisotrydata; ``` +## 高可用性示例 -## 高可用场景示例 - -假设集群的拓扑结构如下,集群的 TiKV 节点分布在 3 个 `region`(区域),每个 `region` 有 3 个可用的 `zone` (可用区): +假设有一个集群具有以下拓扑结构,其中 TiKV 节点分布在 3 个区域,每个区域包含 3 个可用区: ```sql SELECT store_id,address,label from INFORMATION_SCHEMA.TIKV_STORE_STATUS; @@ -327,32 +342,43 @@ SELECT store_id,address,label from INFORMATION_SCHEMA.TIKV_STORE_STATUS; | 8 | 127.0.0.1:20167 | [{"key": "region", "value": "us-west-1"}, {"key": "zone", "value": "us-west-1b"}, {"key": "host", "value": "host8"}] | | 9 | 127.0.0.1:20168 | [{"key": "region", "value": "us-west-1"}, {"key": "zone", "value": "us-west-1c"}, {"key": "host", "value": "host9"}] | +----------+-----------------+--------------------------------------------------------------------------------------------------------------------------+ - ``` ### 指定生存偏好 -如果你不特别在意数据的具体分布,只希望能满足容灾生存要求,可以使用 `SURVIVAL_PREFERENCES` 选项设置数据的生存能力偏好。 +如果你不特别关心具体的数据分布,但优先考虑满足灾难恢复要求,你可以使用 `SURVIVAL_PREFERENCES` 选项来指定数据生存偏好。 -在上面的例子中,TiDB 集群分布在 3 个 `region`,且每个区域有 3 个 `zone`。在为该集群创建放置策略时,假设 `SURVIVAL_PREFERENCES` 的设置如下: +如上例所示,TiDB 集群分布在 3 个区域,每个区域包含 3 个可用区。在为此集群创建放置策略时,假设你按如下方式配置 `SURVIVAL_PREFERENCES`: -``` sql +```sql CREATE PLACEMENT POLICY multiaz SURVIVAL_PREFERENCES="[region, zone, host]"; CREATE PLACEMENT POLICY singleaz CONSTRAINTS="[+region=us-east-1]" SURVIVAL_PREFERENCES="[zone]"; ``` -创建好放置策略后,你可以按需将放置策略绑定到对应的表上: +创建放置策略后,你可以根据需要将它们附加到相应的表: + +- 对于附加了 `multiaz` 放置策略的表,数据将放置在不同区域的 3 个副本中,优先满足跨区域的数据隔离生存目标,其次是跨可用区的生存目标,最后是跨主机的生存目标。 +- 对于附加了 `singleaz` 放置策略的表,数据将首先放置在 `us-east-1` 区域的 3 个副本中,然后满足跨可用区的数据隔离生存目标。 + + + +> **注意:** +> +> `SURVIVAL_PREFERENCES` 等同于 PD 中的 `location-labels`。更多信息,请参见[使用拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md)。 + + -- 对于绑定了 `multiaz` 放置策略的表,数据将以 3 副本的形式放置在不同的 `region` 里,优先满足跨 `region` 级别的生存目标,再满足跨 `zone` 级别的生存目标,最后再满足跨 `host` 级别的生存目标。 -- 对于绑定了 `singleaz` 放置策略的表,数据会优先以 3 副本的形式全部放置在 `us-east-1` 这个 `region` 里,再满足跨 `zone` 级别的数据隔离的生存目标。 + > **注意:** > -> `SURVIVAL_PREFERENCES` 和 PD 中的 `location-labels` 是等价的,更多信息可以参考[通过拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md)。 +> `SURVIVAL_PREFERENCES` 等同于 PD 中的 `location-labels`。更多信息,请参见[使用拓扑 label 进行副本调度](https://docs.pingcap.com/tidb/stable/schedule-replicas-by-topology-labels)。 -### 指定集群多数据中心 5 副本 2:2:1 分布 + -如需特定的数据分布(如 5 副本 2:2:1 分布),可以配置[字典格式](#constraints-格式)的 `CONSTRAINTS` 为不同的约束指定不同数量的副本: +### 指定跨多个数据中心按 2:2:1 分布的 5 副本集群 + +如果你需要特定的数据分布,例如按 2:2:1 的比例分布的 5 个副本,你可以通过使用[字典格式](#constraints-格式)配置这些 `CONSTRAINTS` 来为不同的约束指定不同数量的副本: ```sql CREATE PLACEMENT POLICY `deploy221` CONSTRAINTS='{"+region=us-east-1":2, "+region=us-east-2": 2, "+region=us-west-1": 1}'; @@ -368,45 +394,44 @@ SHOW PLACEMENT; +-------------------+---------------------------------------------------------------------------------------------+------------------+ ``` -通过为集群全局设置 `deploy221` 放置策略后,TiDB 会根据该策略来分布数据:`us-east-1` 区域放置两个副本,`us-east-2` 区域放置两个副本,`us-west-1` 区域放置一个副本。 +在为集群设置全局 `deploy221` 放置策略后,TiDB 会按照此策略分布数据:在 `us-east-1` 区域放置两个副本,在 `us-east-2` 区域放置两个副本,在 `us-west-1` 区域放置一个副本。 -### 指定 Leader/Follower 分布 +### 指定 Leaders 和 Followers 的分布 -你可以通过 Constraints 或 PRIMARY_REGION 指定特殊的 Leader/Follower 的分布。 +你可以使用约束或 `PRIMARY_REGION` 指定 Leaders 和 Followers 的特定分布。 -#### 使用 Constraints 指定 +#### 使用约束 -如果你对 Raft Leader 的分布节点有要求,可以使用如下语句指定: +如果你对 Raft Leaders 在节点间的分布有特定要求,可以使用以下语句指定放置策略: ```sql CREATE PLACEMENT POLICY deploy221_primary_east1 LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS='{"+region=us-east-1": 1, "+region=us-east-2": 2, "+region=us-west-1: 1}'; ``` -该放置策略创建好并绑定到所需的数据后,这些数据的 Raft Leader 副本将会放置在 `LEADER_CONSTRAINTS` 选项指定的 `us-east-1` 区域中,其他副本将会放置在`FOLLOWER_CONSTRAINTS` 选项指定的区域。需要注意的是,如果集群发生故障,比如 Leader 所在区域 `us-east-1` 的节点宕机,这时候即使其他区域设置的都是 `FOLLOWER_CONSTRAINTS`, 也会从中选举出一个新的 Leader,也就是说保证服务可用的优先级是最高的。 +创建此放置策略并附加到所需数据后,数据的 Raft Leader 副本将放置在 `LEADER_CONSTRAINTS` 选项指定的 `us-east-1` 区域,而其他副本将放置在 `FOLLOWER_CONSTRAINTS` 选项指定的区域。注意,如果集群发生故障,例如 `us-east-1` 区域的节点宕机,仍然会从其他区域选举新的 Leader,即使这些区域在 `FOLLOWER_CONSTRAINTS` 中指定。换句话说,确保服务可用性具有最高优先级。 -在 `us-east-1` 区域故障发生时,如果希望新的 Leader 不要放置在 `us-west-1`,可以配置特殊的 `evict-leader` 属性,驱逐上面新的 Leader: +如果在 `us-east-1` 区域发生故障时,你不希望在 `us-west-1` 放置新的 Leaders,你可以配置特殊的 `evict-leader` 属性来驱逐该区域中新选举的 Leaders: ```sql CREATE PLACEMENT POLICY deploy221_primary_east1 LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS='{"+region=us-east-1": 1, "+region=us-east-2": 2, "+region=us-west-1,#evict-leader": 1}'; ``` -#### 使用 PRIMARY_REGION 指定 +#### 使用 `PRIMARY_REGION` -如果你的集群拓扑配置了 `region` label,你还可以使用 `PRIMARY_REGION` 和 `REGIONS` 选项来指定 follower 的放置策略: +如果在集群拓扑中配置了 `region` 标签,你也可以使用 `PRIMARY_REGION` 和 `REGIONS` 选项为 Followers 指定放置策略: ```sql CREATE PLACEMENT POLICY eastandwest PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2,us-west-1" SCHEDULE="MAJORITY_IN_PRIMARY" FOLLOWERS=4; CREATE TABLE t1 (a INT) PLACEMENT POLICY=eastandwest; ``` -- `PRIMARY_REGION` 为 Leader 分布的区域,只能指定一个。 -- `SCHEDULE` 选项指定 TiDB 如何平衡 follower 的分布。 - - 该选项默认的 `EVEN` 调度规则确保 follower 在所有区域内分布平衡。 - - 如需保证在 `PRIMARY_REGION`(即 `us-east-1`)内放置足够多的 follower 副本,你可以使用 `MAJORITY_IN_PRIMARY` 调度规则来使该区域的 follower 达到指定数量。该调度牺牲一些可用性来换取更低的事务延迟。如果主区域宕机,`MAJORITY_IN_PRIMARY` 无法提供自动故障转移。 - -## 数据隔离场景示例 +- `PRIMARY_REGION` 指定 Leaders 的分布区域。你只能在此选项中指定一个区域。 +- `SCHEDULE` 选项指定 TiDB 如何平衡 Followers 的分布。 + - 默认的 `EVEN` 调度规则确保 Followers 在所有区域中均匀分布。 + - 如果你想确保在 `PRIMARY_REGION`(即 `us-east-1`)中放置足够数量的 Follower 副本,你可以使用 `MAJORITY_IN_PRIMARY` 调度规则。此调度规则以牺牲一些可用性为代价提供较低延迟的事务。如果主要区域发生故障,`MAJORITY_IN_PRIMARY` 不提供自动故障转移。 +## 数据隔离示例 -以下示例在创建放置策略时,设置了一个约束,要求数据必须放置在配置了指定的 `app` 标签的 TiKV 节点: +如下例所示,在创建放置策略时,你可以为每个策略配置一个约束,要求将数据放置在具有指定 `app` 标签的 TiKV 节点上。 ```sql CREATE PLACEMENT POLICY app_order CONSTRAINTS="[+app=order]"; @@ -417,24 +442,37 @@ CREATE TABLE list (id INT, name VARCHAR(50), purchased DATE) PLACEMENT POLICY=app_list ``` -在该示例中,约束是通过列表格式 (`[+app=order]`) 指定的。你也可以使用字典格式指定,例如 (`{+app=order: 3}`)。 +在此示例中,约束使用列表格式指定,如 `[+app=order]`。你也可以使用字典格式指定它们,如 `{+app=order: 3}`。 -执行示例中的语句后,TiDB 会将 `app_order` 的数据放置在配置了 `app` 标签为 `order` 的 TiKV 节点上,将 `app_list` 的数据放置在配置了 `app` 标签为 `list_collection` 的 TiKV 节点上,从而在存储上达到了物理隔离的效果。 +执行示例中的语句后,TiDB 将把 `app_order` 数据放置在 `app` 标签为 `order` 的 TiKV 节点上,把 `app_list` 数据放置在 `app` 标签为 `list_collection` 的 TiKV 节点上,从而在存储中实现物理数据隔离。 -## 兼容性说明 +## 兼容性 -### 功能兼容性 +## 与其他功能的兼容性 - 临时表不支持放置策略。 -- 放置策略仅保证静态数据被放置在正确的 TiKV 节点上。该策略不保证传输中的数据(通过用户查询或内部操作)只出现在特定区域内。 -- 设置数据的 TiFlash 副本需要通过[构建 TiFlash 副本](/tiflash/create-tiflash-replicas.md)的方式创建,不能使用该特性。 -- 设置 `PRIMARY_REGION` 和 `REGIONS` 时允许存在语法糖。但在未来版本中,我们计划为 `PRIMARY_RACK`、`PRIMARY_ZONE` 和 `PRIMARY_HOST` 添加变体支持,见 [issue #18030](https://github.com/pingcap/tidb/issues/18030)。 +- 放置策略仅确保静态数据位于正确的 TiKV 节点上,但不保证传输中的数据(通过用户查询或内部操作)仅在特定区域中发生。 +- 要为数据配置 TiFlash 副本,你需要[创建 TiFlash 副本](/tiflash/create-tiflash-replicas.md)而不是使用放置策略。 +- 允许为设置 `PRIMARY_REGION` 和 `REGIONS` 使用语法糖规则。未来,我们计划为 `PRIMARY_RACK`、`PRIMARY_ZONE` 和 `PRIMARY_HOST` 添加变体。参见 [issue #18030](https://github.com/pingcap/tidb/issues/18030)。 + +## 与工具的兼容性 + + -### 工具兼容性 +| 工具名称 | 最低支持版本 | 描述 | +| --- | --- | --- | +| Backup & Restore (BR) | 6.0 | 6.0 版本之前,BR 不支持备份和恢复放置策略。更多信息,请参见[为什么在恢复放置规则到集群时出错](/faq/backup-and-restore-faq.md#why-does-an-error-occur-when-i-restore-placement-rules-to-a-cluster)。 | +| TiDB Lightning | 尚未兼容 | 当 TiDB Lightning 导入包含放置策略的备份数据时会报错 | +| TiCDC | 6.0 | 忽略放置策略,不会将策略复制到下游 | +| TiDB Binlog | 6.0 | 忽略放置策略,不会将策略复制到下游 | + + -| 工具名称 | 最低兼容版本 | 说明 | + + +| 工具名称 | 最低支持版本 | 描述 | | --- | --- | --- | -| Backup & Restore (BR) | 6.0 | BR 在 v6.0 之前不支持放置策略的备份与恢复,请参见[恢复 Placement Rule 到集群时为什么会报错?](/faq/backup-and-restore-faq.md#恢复-placement-rule-到集群时为什么会报错) | -| TiDB Lightning | 暂时不兼容 | 导入包含放置策略的数据时会报错 | -| TiCDC | 6.0 | 忽略放置策略,不同步策略到下游集群 | -| TiDB Binlog | 6.0 | 忽略放置策略,不同步策略到下游集群 | +| TiDB Lightning | 尚未兼容 | 当 TiDB Lightning 导入包含放置策略的备份数据时会报错 | +| TiCDC | 6.0 | 忽略放置策略,不会将策略复制到下游 | + + diff --git a/predicate-push-down.md b/predicate-push-down.md index a8cc56046674..60f04d9d743e 100644 --- a/predicate-push-down.md +++ b/predicate-push-down.md @@ -1,19 +1,19 @@ --- title: 谓词下推 -summary: TiDB 逻辑优化规则中的谓词下推旨在尽早完成数据过滤,减少数据传输或计算的开销。谓词下推适用于将过滤表达式计算下推到数据源,如示例 1、2、3。但对于存储层不支持的谓词、外连接中的谓词和包含用户变量的谓词则不能下推。 +summary: 介绍 TiDB 的一个逻辑优化规则——谓词下推(Predicate Push Down,PPD)。 --- -# 谓词下推 +# 谓词下推(PPD) -本文档介绍 TiDB 逻辑优化规则中的谓词下推规则,旨在让读者对谓词下推形成理解,并了解常见的谓词下推适用及不适用的场景。 +本文介绍 TiDB 的一个逻辑优化规则——谓词下推(Predicate Push Down,PPD)。本文旨在帮助你理解谓词下推以及了解其适用和不适用的场景。 -谓词下推将查询语句中的过滤表达式计算尽可能下推到距离数据源最近的地方,以尽早完成数据的过滤,进而显著地减少数据传输或计算的开销。 +PPD 将选择算子尽可能下推到数据源,以尽早完成数据过滤,这可以显著降低数据传输或计算的成本。 ## 示例 -以下通过一些例子对谓词下推优化进行说明,其中示例 1、2、3 为谓词下推适用的案例,示例 4、5、6 为谓词下推不适用的案例。 +以下案例描述了 PPD 的优化。案例 1、2 和 3 是 PPD 适用的场景,案例 4、5 和 6 是 PPD 不适用的场景。 -### 示例 1: 谓词下推到存储层 +### 案例 1:将谓词下推到存储层 ```sql create table t(id int primary key, a int); @@ -28,9 +28,9 @@ explain select * from t where a < 1; 3 rows in set (0.00 sec) ``` -在该查询中,将谓词 `a < 1` 下推到 TiKV 上对数据进行过滤,可以减少由于网络传输带来的开销。 +在这个查询中,将谓词 `a < 1` 下推到 TiKV 层进行数据过滤可以减少网络传输的开销。 -### 示例 2: 谓词下推到存储层 +### 案例 2:将谓词下推到存储层 ```sql create table t(id int primary key, a int not null); @@ -44,9 +44,9 @@ explain select * from t where a < substring('123', 1, 1); +-------------------------+----------+-----------+---------------+--------------------------------+ ``` -该查询与示例 1 中的查询生成了完全一样的执行计划,这是因为谓词 `a < substring('123', 1, 1)` 的 `substring` 的入参均为常量,因此可以提前计算,进而简化得到等价的谓词 `a < 1`。进一步的,可以将 `a < 1` 下推至 TiKV 上。 +这个查询与案例 1 的执行计划相同,因为谓词 `a < substring('123', 1, 1)` 中 `substring` 的输入参数都是常量,所以可以提前计算。然后谓词被简化为等价的谓词 `a < 1`。之后,TiDB 可以将 `a < 1` 下推到 TiKV。 -### 示例 3: 谓词下推到 join 下方 +### 案例 3:将谓词下推到连接算子之下 ```sql create table t(id int primary key, a int not null); @@ -66,11 +66,11 @@ explain select * from t join s on t.a = s.a where t.a < 1; 7 rows in set (0.00 sec) ``` -在该查询中,将谓词 `t.a < 1` 下推到 join 前进行过滤,可以减少 join 时的计算开销。 +在这个查询中,谓词 `t.a < 1` 被下推到连接之下以提前过滤,这可以减少连接的计算开销。 -此外,这条 SQL 执行的是内连接,且 `ON` 条件是 `t.a = s.a`,可以由 `t.a < 1` 推导出谓词 `s.a < 1`,并将其下推至 join 运算前对 `s` 表进行过滤,可以进一步减少 join 时的计算开销。 +此外,这条 SQL 语句执行了一个内连接,`ON` 条件是 `t.a = s.a`。可以从 `t.a < 1` 推导出谓词 `s.a < 1` 并将其下推到连接算子之下的 `s` 表。过滤 `s` 表可以进一步减少连接的计算开销。 -### 示例 4: 存储层不支持的谓词无法下推 +### 案例 4:存储层不支持的谓词无法下推 ```sql create table t(id int primary key, a varchar(10) not null); @@ -84,11 +84,11 @@ desc select * from t where truncate(a, " ") = '1'; +-------------------------+----------+-----------+---------------+---------------------------------------------------+ ``` -在该查询中,存在谓词 `truncate(a, " ") = '1'`。 +在这个查询中,有一个谓词 `truncate(a, " ") = '1'`。 -从 explain 结果中可以看到,该谓词没有被下推到 TiKV 上进行计算,这是因为 TiKV coprocessor 中没有对 `truncate` 内置函数进行支持,因此无法将其下推到 TiKV 上。 +从 `explain` 结果可以看出,该谓词没有被下推到 TiKV 进行计算。这是因为 TiKV 协处理器不支持内置函数 `truncate`。 -### 示例 5: 外连接中内表上的谓词不能下推 +### 案例 5:外连接内表上的谓词不能下推 ```sql create table t(id int primary key, a int not null); @@ -107,11 +107,11 @@ explain select * from t left join s on t.a = s.a where s.a is null; 6 rows in set (0.00 sec) ``` -在该查询中,内表 s 上存在谓词 `s.a is null`。 +在这个查询中,内表 `s` 上有一个谓词 `s.a is null`。 -从 explain 中可以看到,该谓词没有被下推到 join 前进行计算,这是因为外连接在不满足 on 条件时会对内表填充 NULL,而在该查询中 `s.a is null` 用来对 join 后的结果进行过滤,如果将其下推到 join 前在内表上进行过滤,则下推前后不等价,因此不可进行下推。 +从 `explain` 结果可以看出,该谓词没有被下推到连接算子之下。这是因为当 `on` 条件不满足时,外连接会用 `NULL` 值填充内表,而谓词 `s.a is null` 用于在连接之后过滤结果。如果将其下推到连接之下的内表,执行计划就不等价于原始计划了。 -### 示例 6: 谓词中包含用户变量时不能下推 +### 案例 6:包含用户变量的谓词不能下推 ```sql create table t(id int primary key, a char); @@ -127,11 +127,11 @@ explain select * from t where a < @a; 3 rows in set (0.00 sec) ``` -在该查询中,表 t 上存在谓词 `a < @a`,其中 `@a` 为值为 1 的用户变量。 +在这个查询中,表 `t` 上有一个谓词 `a < @a`。谓词中的 `@a` 是一个用户变量。 -从 explain 中可以看到,该谓词没有像示例 2 中一样,将谓词简化为 `a < 1` 并下推到 TiKV 上进行计算。这是因为,用户变量 `@a` 的值可能会某些场景下在查询过程中发生改变,且 TiKV 对于用户变量 `@a` 的值不可知,因此 TiDB 不会将 `@a` 替换为 1,且不会下推至 TiKV 上进行计算。 +从 `explain` 结果可以看出,该谓词不像案例 2 那样被简化为 `a < 1` 并下推到 TiKV。这是因为用户变量 `@a` 的值可能在计算过程中发生变化,而 TiKV 无法感知这些变化。所以 TiDB 不会将 `@a` 替换为 `1`,也不会将其下推到 TiKV。 -一个帮助理解的例子如下: +下面是一个帮助理解的示例: ```sql create table t(id int primary key, a int); @@ -147,4 +147,4 @@ select id, a, @a:=@a+1 from t where a = @a; 2 rows in set (0.00 sec) ``` -可以从在该查询中看到,`@a` 的值会在查询过程中发生改变,因此如果将 `a = @a` 替换为 `a = 1` 并下推至 TiKV,则优化前后不等价。 +从这个查询可以看出,`@a` 的值会在查询过程中发生变化。所以如果将 `a = @a` 替换为 `a = 1` 并下推到 TiKV,就不是一个等价的执行计划了。 diff --git a/read-historical-data.md b/read-historical-data.md index 9cef3820b5e6..c8e44285b95a 100644 --- a/read-historical-data.md +++ b/read-historical-data.md @@ -1,83 +1,68 @@ --- -title: 通过系统变量 tidb_snapshot 读取历史数据 -summary: 本文介绍了通过系统变量 `tidb_snapshot` 读取历史数据的操作流程和历史数据的保留策略。TiDB 实现了通过标准 SQL 接口读取历史数据功能,无需特殊的 client 或者 driver。当数据被更新、删除后,依然可以通过 SQL 接口将更新 / 删除前的数据读取出来。历史数据保留策略使用 MVCC 管理版本,超过一定时间的历史数据会被彻底删除,以减小空间占用以及避免历史版本过多引入的性能开销。 +title: 使用系统变量 `tidb_snapshot` 读取历史数据 +summary: 了解如何使用系统变量 `tidb_snapshot` 从历史版本读取数据。 --- -# 通过系统变量 tidb_snapshot 读取历史数据 +# 使用系统变量 `tidb_snapshot` 读取历史数据 -本文档介绍如何通过系统变量 `tidb_snapshot` 读取历史数据,包括具体的操作流程以及历史数据的保存策略。 +本文档介绍如何使用系统变量 `tidb_snapshot` 从历史版本读取数据,包括具体的使用示例和保存历史数据的策略。 > **注意:** > -> 你还可以使用 [Stale Read](/stale-read.md) 功能读取历史数据。更推荐使用 Stale Read 读取历史数据。 +> 您也可以使用 [Stale Read](/stale-read.md) 功能来读取历史数据,这是更推荐的方式。 ## 功能说明 -TiDB 实现了通过标准 SQL 接口读取历史数据功能,无需特殊的 client 或者 driver。当数据被更新、删除后,依然可以通过 SQL 接口将更新/删除前的数据读取出来。 +TiDB 实现了通过标准 SQL 接口直接读取历史数据的功能,无需特殊的客户端或驱动程序。 > **注意:** > -> 读取历史数据时,即使当前数据的表结构相较于历史数据的表结构已经发生改变,历史数据也会使用当时的表结构来返回数据。 +> - 即使数据被更新或删除,也可以通过 SQL 接口读取其历史版本。 +> - 在读取历史数据时,即使当前表结构已经改变,TiDB 也会返回带有旧表结构的数据。 -## 操作流程 +## TiDB 如何读取历史版本数据 -为支持读取历史版本数据,TiDB 引入了一个新的系统变量 [`tidb_snapshot`](/system-variables.md#tidb_snapshot): +TiDB 引入了 [`tidb_snapshot`](/system-variables.md#tidb_snapshot) 系统变量来支持读取历史数据。关于 `tidb_snapshot` 变量: -- 这个变量的作用域为 `SESSION`。 -- 你可以通过标准的 `SET` 语句修改这个变量的值。 -- 这个变量的数据类型为文本类型,能够存储 TSO 和日期时间。TSO 是从 PD 端获取的全局授时的时间戳,日期时间的格式为:"2016-10-08 16:45:26.999",一般来说可以只写到秒,比如”2016-10-08 16:45:26”。 -- 当这个变量被设置时,TiDB 会按照设置的时间戳建立 Snapshot(没有开销,只是创建数据结构),随后所有的 `SELECT` 操作都会从这个 Snapshot 上读取数据。 +- 该变量在 `SESSION` 作用域内有效。 +- 可以使用 `SET` 语句修改其值。 +- 变量的数据类型为文本。 +- 变量接受 TSO(时间戳预言机)和日期时间格式。TSO 是从 PD 获取的全局唯一时间服务。可接受的日期时间格式为 "2016-10-08 16:45:26.999"。通常,日期时间可以使用秒级精度设置,例如 "2016-10-08 16:45:26"。 +- 当设置该变量时,TiDB 会使用其值作为时间戳创建一个快照,这只涉及数据结构且没有任何开销。之后,所有的 `SELECT` 操作都将从该快照中读取数据。 > **注意:** > -> TiDB 的事务是通过 PD 进行全局授时,所以存储的数据版本也是以 PD 所授时间戳作为版本号。在生成 Snapshot 时,是以 tidb_snapshot 变量的值作为版本号,如果 TiDB Server 所在机器和 PD Server 所在机器的本地时间相差较大,需要以 PD 的时间为准。 +> 由于 TiDB 事务中的时间戳是由 Placement Driver (PD) 分配的,存储的数据版本也是基于 PD 分配的时间戳进行标记的。当创建快照时,版本号是基于 `tidb_snapshot` 变量的值。如果 TiDB 服务器的本地时间与 PD 服务器时间存在较大差异,请使用 PD 服务器的时间。 -当读取历史版本操作结束后,可以结束当前 Session 或者是通过 `SET` 语句将 tidb_snapshot 变量的值设为 "",即可读取最新版本的数据。 +从历史版本读取数据后,您可以通过结束当前会话或使用 `SET` 语句将 `tidb_snapshot` 变量的值设置为 ""(空字符串)来读取最新版本的数据。 -## 历史数据保留策略 +## TiDB 如何管理数据版本 -TiDB 使用 MVCC 管理版本,当更新/删除数据时,不会做真正的数据删除,只会添加一个新版本数据,所以可以保留历史数据。历史数据不会全部保留,超过一定时间的历史数据会被彻底删除,以减小空间占用以及避免历史版本过多引入的性能开销。 +TiDB 实现了多版本并发控制(MVCC)来管理数据版本。之所以保留数据的历史版本,是因为每次更新/删除都会创建数据对象的新版本,而不是直接在原地更新/删除数据对象。但并非所有版本都会被保留。如果版本早于特定时间,它们将被完全删除,以减少存储占用和过多历史版本导致的性能开销。 -TiDB 使用周期性运行的 GC(Garbage Collection,垃圾回收)来进行清理,关于 GC 的详细介绍参见 [TiDB 垃圾回收 (GC)](/garbage-collection-overview.md)。 +在 TiDB 中,垃圾回收(GC)会定期运行以删除过时的数据版本。有关 GC 的详细信息,请参见 [TiDB 垃圾回收(GC)](/garbage-collection-overview.md) -这里需要重点关注的是: +请特别注意以下几点: -- 使用系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入) 可以配置历史版本的保留时间(默认值是 `10m0s`)。 -- 使用 SQL 语句 `SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'` 可以查询当前的 safePoint,即当前可以读的最旧的快照。在每次 GC 开始运行时,safePoint 将自动更新。 +- [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-new-in-v50):此系统变量用于配置早期修改的保留时间(默认值:`10m0s`)。 +- `SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'` 的输出。这是当前可以读取历史数据的 `safePoint`。每次运行垃圾回收进程时都会更新此值。 ## 示例 -1. 初始化阶段,创建一个表,并插入几行数据: - - {{< copyable "sql" >}} +1. 在初始阶段,创建一个表并插入几行数据: ```sql - create table t (c int); - ``` - - ``` + mysql> create table t (c int); Query OK, 0 rows affected (0.01 sec) - ``` - - {{< copyable "sql" >}} - ```sql - insert into t values (1), (2), (3); - ``` - - ``` + mysql> insert into t values (1), (2), (3); Query OK, 3 rows affected (0.00 sec) ``` 2. 查看表中的数据: - {{< copyable "sql" >}} - ```sql - select * from t; - ``` - - ``` + mysql> select * from t; +------+ | c | +------+ @@ -88,15 +73,10 @@ TiDB 使用周期性运行的 GC(Garbage Collection,垃圾回收)来进行 3 rows in set (0.00 sec) ``` -3. 查看当前时间: - - {{< copyable "sql" >}} +3. 查看表的时间戳: ```sql - select now(); - ``` - - ``` + mysql> select now(); +---------------------+ | now() | +---------------------+ @@ -105,27 +85,17 @@ TiDB 使用周期性运行的 GC(Garbage Collection,垃圾回收)来进行 1 row in set (0.00 sec) ``` -4. 更新某一行数据: - - {{< copyable "sql" >}} +4. 更新其中一行的数据: ```sql - update t set c=22 where c=2; - ``` - - ``` + mysql> update t set c=22 where c=2; Query OK, 1 row affected (0.00 sec) ``` -5. 确认数据已经被更新: - - {{< copyable "sql" >}} +5. 确认数据已更新: ```sql - select * from t; - ``` - - ``` + mysql> select * from t; +------+ | c | +------+ @@ -136,32 +106,25 @@ TiDB 使用周期性运行的 GC(Garbage Collection,垃圾回收)来进行 3 rows in set (0.00 sec) ``` -6. 设置一个特殊的环境变量,这个是一个 session scope 的变量,其意义为读取这个时间之前的最新的一个版本。 +6. 设置作用域为 Session 的 `tidb_snapshot` 变量。设置该变量后,可以读取该值之前的最新版本。 - {{< copyable "sql" >}} + > **注意:** + > + > 在本例中,该值被设置为更新操作之前的时间。 ```sql - set @@tidb_snapshot="2016-10-08 16:45:26"; - ``` - - ``` + mysql> set @@tidb_snapshot="2016-10-08 16:45:26"; Query OK, 0 rows affected (0.00 sec) ``` > **注意:** > - > - 这里的时间设置的是 update 语句之前的那个时间。 - > - 在 `tidb_snapshot` 前须使用 `@@` 而非 `@`,因为 `@@` 表示系统变量,`@` 表示用户变量。 + > 您应该在 `tidb_snapshot` 前使用 `@@` 而不是 `@`,因为 `@@` 用于表示系统变量,而 `@` 用于表示用户变量。 - 这里读取到的内容即为 update 之前的内容,也就是历史版本: - - {{< copyable "sql" >}} + **结果:** 以下语句读取的是更新操作之前的数据,即历史数据。 ```sql - select * from t; - ``` - - ``` + mysql> select * from t; +------+ | c | +------+ @@ -172,25 +135,15 @@ TiDB 使用周期性运行的 GC(Garbage Collection,垃圾回收)来进行 3 rows in set (0.00 sec) ``` -7. 清空这个变量后,即可读取最新版本数据: - - {{< copyable "sql" >}} +7. 将 `tidb_snapshot` 变量设置为 ""(空字符串),您就可以读取最新版本的数据: ```sql - set @@tidb_snapshot=""; - ``` - - ``` + mysql> set @@tidb_snapshot=""; Query OK, 0 rows affected (0.00 sec) ``` - {{< copyable "sql" >}} - ```sql - select * from t; - ``` - - ``` + mysql> select * from t; +------+ | c | +------+ @@ -203,11 +156,11 @@ TiDB 使用周期性运行的 GC(Garbage Collection,垃圾回收)来进行 > **注意:** > - > 在 `tidb_snapshot` 前须使用 `@@` 而非 `@`,因为 `@@` 表示系统变量,`@` 表示用户变量。 + > 您应该在 `tidb_snapshot` 前使用 `@@` 而不是 `@`,因为 `@@` 用于表示系统变量,而 `@` 用于表示用户变量。 -## 历史数据恢复策略 +## 如何恢复历史数据 -在恢复历史版本的数据之前,需要确保在对数据进行操作时,垃圾回收机制 (GC) 不会清除历史数据。如下所示,可以通过设置 `tidb_gc_life_time` 变量来调整 GC 清理的周期。不要忘记在恢复历史数据后将该变量设置回之前的值。 +在从旧版本恢复数据之前,请确保在您处理数据时垃圾回收(GC)不会清除历史数据。这可以通过设置 `tidb_gc_life_time` 变量来实现,如下例所示。恢复完成后,不要忘记将变量设置回之前的值。 ```sql SET GLOBAL tidb_gc_life_time="60m"; @@ -215,10 +168,10 @@ SET GLOBAL tidb_gc_life_time="60m"; > **注意:** > -> 将 GC life time 从默认的 10 分钟增加到半小时及以上,会导致同一行保留有多个版本并占用更多的磁盘空间,也可能会影响某些操作的性能,例如扫描。进行扫描操作时,TiDB 读取数据需要跳过这些有多个版本的同一行,从而影响到扫描性能。 +> 将 GC 生命周期从默认的 10 分钟增加到半小时或更长时间将导致保留更多的行版本,这可能需要更多的磁盘空间。这也可能影响某些操作的性能,例如在数据读取过程中,TiDB 需要跳过同一行的这些额外版本时的扫描操作。 -如果想要恢复历史版本的数据,可以使用以下任意一种方法进行设置: +要从旧版本恢复数据,您可以使用以下方法之一: -- 对于简单场景,在设置 `tidb_snapshot` 变量后使用 [`SELECT`](/sql-statements/sql-statement-select.md) 语句并复制粘贴输出结果,或者使用 `SELECT ... INTO OUTFILE` 语句并使用 [`LOAD DATA`](/sql-statements/sql-statement-load-data.md) 语句来导入数据。 +- 对于简单的情况,在设置 `tidb_snapshot` 变量后使用 [`SELECT`](/sql-statements/sql-statement-select.md) 并复制粘贴输出,或使用 `SELECT ... INTO OUTFILE` 然后使用 [`LOAD DATA`](/sql-statements/sql-statement-load-data.md) 稍后导入数据。 -- 使用 [Dumpling](/dumpling-overview.md#导出-tidb-的历史数据快照) 导出 TiDB 的历史数据快照。Dumpling 在导出较大的数据集时有较好的性能。 +- 使用 [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview#export-historical-data-snapshots-of-tidb) 导出历史快照。Dumpling 在导出较大数据集时表现良好。 diff --git a/runtime-filter.md b/runtime-filter.md index f311ee47c404..e4c162d85dee 100644 --- a/runtime-filter.md +++ b/runtime-filter.md @@ -1,36 +1,36 @@ --- -title: Runtime Filter -summary: 介绍 Runtime Filter 的原理及使用方式。 +title: 运行时过滤器 +summary: 了解运行时过滤器的工作原理及其使用方法。 --- -# Runtime Filter +# 运行时过滤器 -Runtime Filter 是 TiDB v7.3 引入的新功能,旨在提升 MPP 场景下 Hash Join 的性能。它通过动态生成 Filter 来提前过滤 Hash Join 的数据,从而减少运行时的数据扫描量以及 Hash Join 的计算量,最终提升查询性能。 +运行时过滤器(Runtime Filter)是 TiDB v7.3 中引入的新特性,旨在提高 MPP 场景下哈希连接的性能。通过动态生成过滤器来预先过滤哈希连接的数据,TiDB 可以减少运行时的数据扫描量和哈希连接的计算量,最终提升查询性能。 -## 名词解释 +## 概念 -- Hash Join:一种实现 Join 关系代数的方式。它通过在 Join 的一侧构建 Hash Table 并在另一侧不断匹配 Hash Table 来得到 Join 的结果。 -- Build Side:Hash Join 中用于构建 Hash Table 的一侧,称为 Build Side。本文默认以 Join 的右表作为 Build Side。 -- Probe Side:Hash Join 中用于不断匹配 Hash Table 的一侧,称为 Probe Side。本文默认以 Join 的左表作为 Probe Side。 -- Filter:也称谓词,在本文中指过滤条件。 +- 哈希连接(Hash join):实现连接关系代数的一种方式。通过在一侧建立哈希表,另一侧持续匹配哈希表来获得连接结果。 +- 构建侧(Build side):哈希连接中用于构建哈希表的一侧。在本文档中,默认哈希连接的右表称为构建侧。 +- 探测侧(Probe side):哈希连接中用于持续匹配哈希表的一侧。在本文档中,默认哈希连接的左表称为探测侧。 +- 过滤器(Filter):也称为谓词(predicate),在本文档中指过滤条件。 -## Runtime Filter 的原理 +## 运行时过滤器的工作原理 -Hash Join 通过将右表的数据构建为 Hash Table,并将左表的数据不断匹配 Hash Table 来完成 Join。如果在匹配过程中,发现一部分 Join Key 值无法命中 Hash Table,则说明这部分数据不存在于右表,也不会出现在最终的 Join 结果中。因此,如果能够在扫描时**提前过滤掉这部分 Join Key 的数据**,将减少扫描时间和网络开销,从而大幅提升 Join 效率。 +哈希连接通过基于右表构建哈希表并使用左表持续探测哈希表来执行连接操作。如果在探测过程中某些连接键值无法命中哈希表,这意味着该数据在右表中不存在,也不会出现在最终的连接结果中。因此,如果 TiDB 能够在扫描过程中**预先过滤掉连接键数据**,就会减少扫描时间和网络开销,从而大大提高连接效率。 -Runtime Filter 是在查询规划阶段生成的一种**动态取值谓词**。该谓词与 TiDB Selection 中的其他谓词具有相同作用,都应用于 Table Scan 操作上,用于筛选不满足谓词条件的行为。唯一的区别在于,Runtime Filter 中的参数取值来自于 Hash Join 构建过程中产生的结果。 +运行时过滤器是在查询规划阶段生成的**动态谓词**。这个谓词与 TiDB Selection 算子中的其他谓词具有相同的功能。这些谓词都应用于 Table Scan 操作以过滤掉不符合谓词的行。唯一的区别是运行时过滤器中的参数值来自哈希连接构建过程中生成的结果。 ### 示例 -假设当前存在 `store_sales` 表与 `date_dim` 表的 Join 查询,它的 Join 方式为 Hash Join。`store_sales` 是一张事实表,主要存储门店销售数据,行数为 100 万。`date_dim` 是一张时间维度表,主要存储日期信息。当前想要查询 2001 年的销售数据,则 `date_dim` 表参与 Join 的数据量为 365 行。 +假设在 `store_sales` 表和 `date_dim` 表之间有一个连接查询,连接方式是哈希连接。`store_sales` 是一个事实表,主要存储商店的销售数据,行数为 100 万。`date_dim` 是一个时间维度表,主要存储日期信息。你想查询 2001 年的销售数据,因此 `date_dim` 表中有 365 行参与连接操作。 ```sql SELECT * FROM store_sales, date_dim WHERE ss_date_sk = d_date_sk - AND d_year = 2001; + AND d_year = 2001; ``` -Hash Join 通常情况下的执行方式为: +哈希连接的执行计划通常如下: ``` +-------------------+ @@ -48,14 +48,14 @@ Hash Join 通常情况下的执行方式为: +---------------+ +----------------+ ``` -*(上图为示意图,省略了 exchange 等节点)* +*(上图省略了 exchange 节点和其他节点。)* -Runtime Filter 的执行方式如下: +运行时过滤器的执行过程如下: -1. 扫描 `date_dim` 的数据。 -2. PhysicalHashJoin 根据 Build Side 数据计算出一个过滤条件,比如 `date_dim in (2001/01/01~2001/12/31)`。 -3. 将该过滤条件发送给等待扫描 `store_sales` 的 TableFullScan。 -4. `store_sales` 应用该过滤条件,并将过滤后的数据传递给 PhysicalHashJoin,从而减少 Probe Side 的扫表数据量以及匹配 Hash Table 的计算量。 +1. 扫描 `date_dim` 表的数据。 +2. `PhysicalHashJoin` 根据构建侧的数据计算出一个过滤条件,如 `date_dim in (2001/01/01~2001/12/31)`。 +3. 将过滤条件发送给正在等待扫描 `store_sales` 的 `TableFullScan` 算子。 +4. 过滤条件应用于 `store_sales`,过滤后的数据传递给 `PhysicalHashJoin`,从而减少探测侧扫描的数据量和匹配哈希表的计算量。 ``` 2. Build RF values @@ -72,26 +72,25 @@ Runtime Filter 的执行方式如下: +-----------------+ +----------------+ ``` -* (上图中的 RF 是 Runtime Filter 的缩写) * +*(RF 是 Runtime Filter 的缩写)* -对比以上两个图可以看出,`store_sales` 的扫描量从 100 万减少到了 5000。通过减少 Table Full Scan 扫描的数据量,Runtime Filter 可以减少匹配 Hash Table 的次数,避免不必要的 I/O 和网络传输,从而显著提升了 Join 操作的效率。 +从上面两个图中可以看到,`store_sales` 扫描的数据量从 100 万减少到了 5000。通过减少 `TableFullScan` 扫描的数据量,运行时过滤器可以减少匹配哈希表的次数,避免不必要的 I/O 和网络传输,从而显著提高连接操作的效率。 +## 使用运行时过滤器 -## 使用 Runtime Filter +要使用运行时过滤器,你需要创建带有 TiFlash 副本的表,并将 [`tidb_runtime_filter_mode`](/system-variables.md#tidb_runtime_filter_mode-new-in-v720) 设置为 `LOCAL`。 -要使用 Runtime Filter,只需创建带 TiFlash 副本的表,并将 [`tidb_runtime_filter_mode`](/system-variables.md#tidb_runtime_filter_mode-从-v720-版本开始引入) 设置为 `LOCAL`。 +以 TPC-DS 数据集为例,本节使用 `catalog_sales` 表和 `date_dim` 表进行连接操作,说明运行时过滤器如何提高查询效率。 -本小节以 TPC-DS 的数据集为例,使用 `catalog_sales` 表和 `date_dim` 表进行 Join 操作,说明如何使用 Runtime Filter 提升查询效率。 +### 步骤 1. 为要连接的表创建 TiFlash 副本 -### 第 1 步:创建表的 TiFlash 副本 - -给 `catalog_sales` 表和 `date_dim` 表分别增加一个 TiFlash 副本。 +为 `catalog_sales` 表和 `date_dim` 表各添加一个 TiFlash 副本。 ```sql ALTER TABLE catalog_sales SET tiflash REPLICA 1; ALTER TABLE date_dim SET tiflash REPLICA 1; ``` -等待一段时间,并检查两个表的 TiFlash 副本已准备就绪,即副本的 `AVAILABLE` 字段和 `PROGRESS` 字段均为 `1`。 +等待两个表的 TiFlash 副本就绪,即副本的 `AVAILABLE` 和 `PROGRESS` 字段都为 `1`。 ```sql SELECT * FROM INFORMATION_SCHEMA.TIFLASH_REPLICA WHERE TABLE_NAME='catalog_sales'; @@ -101,7 +100,7 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_REPLICA WHERE TABLE_NAME='catalog_sales | tpcds50 | catalog_sales | 1055 | 1 | | 1 | 1 | +--------------+---------------+----------+---------------+-----------------+-----------+----------+ -mysql> SELECT * FROM INFORMATION_SCHEMA.TIFLASH_REPLICA WHERE TABLE_NAME='date_dim'; +SELECT * FROM INFORMATION_SCHEMA.TIFLASH_REPLICA WHERE TABLE_NAME='date_dim'; +--------------+------------+----------+---------------+-----------------+-----------+----------+ | TABLE_SCHEMA | TABLE_NAME | TABLE_ID | REPLICA_COUNT | LOCATION_LABELS | AVAILABLE | PROGRESS | +--------------+------------+----------+---------------+-----------------+-----------+----------+ @@ -109,15 +108,15 @@ mysql> SELECT * FROM INFORMATION_SCHEMA.TIFLASH_REPLICA WHERE TABLE_NAME='date_d +--------------+------------+----------+---------------+-----------------+-----------+----------+ ``` -### 第 2 步:开启 Runtime Filter +### 步骤 2. 启用运行时过滤器 -将系统变量 [`tidb_runtime_filter_mode`](/system-variables.md#tidb_runtime_filter_mode-从-v720-版本开始引入) 的值设置为 `LOCAL`,即开启 Runtime Filter。 +要启用运行时过滤器,需要将系统变量 [`tidb_runtime_filter_mode`](/system-variables.md#tidb_runtime_filter_mode-new-in-v720) 的值设置为 `LOCAL`。 ```sql SET tidb_runtime_filter_mode="LOCAL"; ``` -查看是否更改成功: +检查更改是否成功: ```sql SHOW VARIABLES LIKE "tidb_runtime_filter_mode"; @@ -128,11 +127,10 @@ SHOW VARIABLES LIKE "tidb_runtime_filter_mode"; +--------------------------+-------+ ``` -系统变量的值显示为 `LOCAL`,则表示已成功开启 Runtime Filter。 - -### 第 3 步:执行查询 +如果系统变量的值为 `LOCAL`,则运行时过滤器已启用。 +### 步骤 3. 执行查询 -在进行查询之前,先查看一下查询计划。使用 [`EXPLAIN` 语句](/sql-statements/sql-statement-explain.md)来检查 Runtime Filter 是否已正确生效。 +在执行查询之前,使用 [`EXPLAIN` 语句](/sql-statements/sql-statement-explain.md)显示执行计划并检查运行时过滤器是否已生效。 ```sql EXPLAIN SELECT cs_ship_date_sk FROM catalog_sales, date_dim @@ -140,15 +138,14 @@ WHERE d_date = '2002-2-01' AND cs_ship_date_sk = d_date_sk; ``` -当 Runtime Filter 启用时,可以看到 HashJoin 节点和 TableScan 节点上分别挂载了对应的 Runtime Filter,表示 Runtime Filter 规划成功。 +当运行时过滤器生效时,相应的运行时过滤器会挂载在 `HashJoin` 节点和 `TableScan` 节点上,表示运行时过滤器已成功应用。 ``` TableFullScan: runtime filter:0[IN] -> tpcds50.catalog_sales.cs_ship_date_sk - HashJoin: runtime filter:0[IN] <- tpcds50.date_dim.d_date_sk | ``` -完整的查询规划如下: +完整的查询执行计划如下: ``` +----------------------------------------+-------------+--------------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ @@ -167,19 +164,18 @@ HashJoin: runtime filter:0[IN] <- tpcds50.date_dim.d_date_sk | 9 rows in set (0.01 sec) ``` -此时执行 SQL 查询,即可应用 Runtime Filter。 +现在,执行 SQL 查询,运行时过滤器将被应用。 ```sql SELECT cs_ship_date_sk FROM catalog_sales, date_dim WHERE d_date = '2002-2-01' AND cs_ship_date_sk = d_date_sk; ``` +### 步骤 4. 性能对比 -### 第 4 步:性能对比 +本示例使用 50 GB 的 TPC-DS 数据。启用运行时过滤器后,查询时间从 0.38 秒减少到 0.17 秒,效率提升了 50%。你可以使用 `ANALYZE` 语句查看运行时过滤器生效后各个算子的执行时间。 -以 TPC-DS 的 50 GB 数据量为例,开启 Runtime Filter 后,查询时间从 0.38 秒减少到 0.17 秒,效率提升 50%。通过 `ANALYZE` 语句可以查看 Runtime Filter 生效后各个算子的执行时间。 - -以下为未开启 Runtime Filter 时查询的执行信息: +以下是未启用运行时过滤器时查询的执行信息: ```sql EXPLAIN ANALYZE SELECT cs_ship_date_sk FROM catalog_sales, date_dim WHERE d_date = '2002-2-01' AND cs_ship_date_sk = d_date_sk; @@ -199,7 +195,7 @@ EXPLAIN ANALYZE SELECT cs_ship_date_sk FROM catalog_sales, date_dim WHERE d_date 9 rows in set (0.38 sec) ``` -以下为开启 Runtime Filter 后的查询 Summary: +以下是启用运行时过滤器时查询的执行信息: ```sql EXPLAIN ANALYZE SELECT cs_ship_date_sk FROM catalog_sales, date_dim @@ -221,39 +217,38 @@ EXPLAIN ANALYZE SELECT cs_ship_date_sk FROM catalog_sales, date_dim 9 rows in set (0.17 sec) ``` -对比两个查询的执行信息,可发现以下改进: +通过比较两个查询的执行信息,你可以发现以下改进: -* IO 减少:对比 TableFullScan 算子的 `total_scanned_rows` 可知,开启 Runtime Filter 后 TableFullScan 的扫描量减少了 2/3 。 -* Hash Join 性能提升:HashJoin 算子的执行耗时从 376.1ms 减少至 157.6ms。 +* IO 减少:通过比较 TableFullScan 算子的 `total_scanned_rows`,可以看到启用运行时过滤器后 `TableFullScan` 的扫描量减少了 2/3。 +* 哈希连接性能提升:`HashJoin` 算子的执行时长从 376.1 ms 减少到 157.6 ms。 ### 最佳实践 -Runtime Filter 适用于大表和小表进行 Join 的情况,比如事实表和维度表的关联查询。当维度表的命中的数据量较少时,意味着 Filter 的取值较少,事实表能更多地过滤掉不满足条件的数据。与默认情况下扫描整个事实表相比,这将显著提高查询性能。 - -例如,在 TPC-DS 中,泛 `Sales` 表和 `date_dim` 表的 Join 就是一个典型例子。 +运行时过滤器适用于大表和小表连接的场景,例如事实表和维度表的连接查询。当维度表的命中数据量较小时,意味着过滤器的值较少,因此可以更有效地过滤掉事实表中不满足条件的数据。与默认扫描整个事实表的场景相比,这显著提高了查询性能。 -## 配置 Runtime Filter +TPC-DS 中 `Sales` 表和 `date_dim` 表的连接操作就是一个典型的例子。 +## 配置运行时过滤器 -在使用 Runtime Filter 时,你可以配置 Runtime Filter 的模式和谓词的类型。 +在使用运行时过滤器时,你可以配置运行时过滤器的模式和谓词类型。 -### Runtime Filter Mode +### 运行时过滤器模式 -Runtime Filter Mode 指的是 Runtime Filter 的模式,即 **生成 Filter 算子** 和 **接收 Filter 算子**之间的关系。共有三种模式:`OFF`、`LOCAL`、`GLOBAL`。在 v7.3.0 中仅支持 `OFF` 和 `LOCAL` 模式,通过系统变量 [`tidb_runtime_filter_mode`](/system-variables.md#tidb_runtime_filter_mode-从-v720-版本开始引入) 控制。 +运行时过滤器的模式是**过滤器发送算子**和**过滤器接收算子**之间的关系。有三种模式:`OFF`、`LOCAL` 和 `GLOBAL`。在 v7.3.0 中,仅支持 `OFF` 和 `LOCAL` 模式。运行时过滤器模式由系统变量 [`tidb_runtime_filter_mode`](/system-variables.md#tidb_runtime_filter_mode-new-in-v720) 控制。 -+ `OFF`:代表关闭 Runtime Filter。关闭后,查询行为和过去完全一致。 -+ `LOCAL`:开启 LOCAL 模式的 Runtime Filter。LOCAL 模式指的是**生成 Filter 的算子**和**接收 Filter 的算子**在同一个 MPP Task 中。简单来说,Runtime Filter 可应用于 HashJoin 算子和 TableScan 算子在同一个 Task 中的情况。目前 Runtime Filter 仅支持 LOCAL 模式,要开启该模式,设置为 `LOCAL` 即可。 -+ `GLOBAL`:目前不支持 GLOBAL 模式,不可设置为该模式。 +- `OFF`:运行时过滤器被禁用。禁用后,查询行为与之前版本相同。 +- `LOCAL`:运行时过滤器以本地模式启用。在本地模式下,**过滤器发送算子**和**过滤器接收算子**在同一个 MPP 任务中。换句话说,运行时过滤器可以应用于 HashJoin 算子和 TableScan 算子在同一任务中的场景。目前,运行时过滤器仅支持本地模式。要启用此模式,请将其设置为 `LOCAL`。 +- `GLOBAL`:目前不支持全局模式。你不能将运行时过滤器设置为此模式。 -### Runtime Filter Type +### 运行时过滤器类型 -Runtime Filter Type 指的是 Runtime Filter 谓词的类型,即生成的 Filter 算子使用的谓词类型。目前只支持一种类型:`IN`,即生成的谓词类似于 `k1 in (xxx)`。通过系统变量 [`tidb_runtime_filter_type`](/system-variables.md#tidb_runtime_filter_type-从-v720-版本开始引入) 控制。 +运行时过滤器的类型是生成的过滤器算子使用的谓词类型。目前仅支持一种类型:`IN`,这意味着生成的谓词类似于 `k1 in (xxx)`。运行时过滤器类型由系统变量 [`tidb_runtime_filter_type`](/system-variables.md#tidb_runtime_filter_type-new-in-v720) 控制。 -+ `IN`:默认为 `IN` 类型。即生成的 Runtime Filter 使用 `IN` 类型的谓词。 +- `IN`:默认类型。表示生成的运行时过滤器使用 `IN` 类型谓词。 ## 限制 -+ Runtime Filter 是 MPP 架构下的优化,仅可应用于下推到 TiFlash 的查询。 -+ Join 类型:Left outer、Full outer、Anti join(当左表为 Probe Side 时)均不支持生成 Runtime Filter。由于 Runtime Filter 会提前过滤参与 Join 的数据,这些类型的 Join 不会丢弃未匹配上的数据,所以无法使用该优化。 -+ Equal Join expression:当等值 Join 表达式中的 Probe 列为复杂表达式,或者其类型为 JSON、Blob、Array 等复合类型时,也不会生成 Runtime Filter。主要原因是这类 Column 很少作为 Equal Join 的关联列,并且即使生成了 Filter,过滤率通常很低。 +- 运行时过滤器是 MPP 架构中的优化,只能应用于下推到 TiFlash 的查询。 +- 连接类型:Left outer、Full outer 和 Anti join(当左表是探测侧时)不支持运行时过滤器。因为运行时过滤器会预先过滤参与连接的数据,而上述连接类型不会丢弃不匹配的数据,所以不能使用运行时过滤器。 +- 等值连接表达式:当等值连接表达式中的探测列是复杂表达式时,或者当探测列类型是 JSON、Blob、Array 或其他复杂数据类型时,不会生成运行时过滤器。主要原因是上述类型的列很少用作连接列。即使生成了过滤器,过滤率通常也很低。 -对于以上限制,如果你需要确认是否正确生成了 Runtime Filter,可以通过 [`EXPLAIN` 语句](/sql-statements/sql-statement-explain.md) 来验证。 +对于上述限制,如果你需要确认运行时过滤器是否正确生成,可以使用 [`EXPLAIN` 语句](/sql-statements/sql-statement-explain.md)验证执行计划。 diff --git a/schema-object-names.md b/schema-object-names.md index 293fb7903e27..b4de4e240d2f 100644 --- a/schema-object-names.md +++ b/schema-object-names.md @@ -1,17 +1,17 @@ --- -title: Schema 对象名 -summary: 本文介绍 TiDB SQL 语句中的模式对象名。 +title: Schema 对象名称 +summary: 了解 TiDB SQL 语句中的 schema 对象名称。 --- -# Schema 对象名 +# Schema 对象名称 -本文介绍 TiDB SQL 语句中的模式对象名。 +本文档介绍 TiDB SQL 语句中的 schema 对象名称。 -模式对象名用于命名 TiDB 中所有的模式对象,包括 database、table、index、column、alias 等等。在 SQL 语句中,可以通过标识符 (identifier) 来引用这些对象。 +Schema 对象名称用于命名 TiDB 中的所有 schema 对象,包括数据库、表、索引、列和别名。你可以在 SQL 语句中使用标识符来引用这些对象。 -标识符可以被反引号包裹,即 `SELECT * FROM t` 也可以写成 `` SELECT * FROM `t` ``。但如果标识符中存在至少一个特殊符号,或者它是一个保留关键字,那就必须使用反引号包裹来引用它所代表的模式对象。 +你可以使用反引号来包围标识符。例如,`SELECT * FROM t` 也可以写作 `` SELECT * FROM `t` ``。但是,如果标识符包含一个或多个特殊字符或是保留关键字,则必须用反引号包围以引用它所代表的 schema 对象。 {{< copyable "sql" >}} @@ -19,20 +19,39 @@ summary: 本文介绍 TiDB SQL 语句中的模式对象名。 SELECT * FROM `table` WHERE `table`.id = 20; ``` -如果 SQL MODE 中设置了 `ANSI_QUOTES`,那么 TiDB 会将被双引号 `"` 包裹的字符串识别为 identifier。 +如果你在 SQL MODE 中设置了 `ANSI_QUOTES`,TiDB 将识别用双引号 `"` 包围的字符串作为标识符。 + +{{< copyable "sql" >}} + +```sql +CREATE TABLE "test" (a varchar(10)); +``` ```sql -MySQL [test]> CREATE TABLE "test" (a varchar(10)); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 19 near ""test" (a varchar(10))" +``` + +{{< copyable "sql" >}} + +```sql +SET SESSION sql_mode='ANSI_QUOTES'; +``` -MySQL [test]> SET SESSION sql_mode='ANSI_QUOTES'; +```sql Query OK, 0 rows affected (0.000 sec) +``` -MySQL [test]> CREATE TABLE "test" (a varchar(10)); +{{< copyable "sql" >}} + +```sql +CREATE TABLE "test" (a varchar(10)); +``` + +```sql Query OK, 0 rows affected (0.012 sec) ``` -如果要在被引用的标识符中使用反引号这个字符,则需要重复两次反引号,例如创建一个表 a`b: +如果你想在引用的标识符中使用反引号字符,请重复反引号两次。例如,要创建一个名为 a`b 的表: {{< copyable "sql" >}} @@ -40,7 +59,7 @@ Query OK, 0 rows affected (0.012 sec) CREATE TABLE `a``b` (a int); ``` -在 select 语句中,alias 部分可以用标识符或者字符串: +在 `SELECT` 语句中,你可以使用标识符或字符串来指定别名: {{< copyable "sql" >}} @@ -48,7 +67,7 @@ CREATE TABLE `a``b` (a int); SELECT 1 AS `identifier`, 2 AS 'string'; ``` -``` +```sql +------------+--------+ | identifier | string | +------------+--------+ @@ -57,11 +76,11 @@ SELECT 1 AS `identifier`, 2 AS 'string'; 1 row in set (0.00 sec) ``` -更多细节,请参考 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/identifiers.html)。 +更多信息,请参见 [MySQL Schema Object Names](https://dev.mysql.com/doc/refman/8.0/en/identifiers.html)。 -## Identifier Qualifiers +## 标识符限定符 -Object Names(对象名字)有时可以被限定或者省略。例如在创建表的时候可以省略数据库限定名: +对象名称可以是非限定的或限定的。例如,以下语句创建一个没有限定名称的表: {{< copyable "sql" >}} @@ -69,7 +88,7 @@ Object Names(对象名字)有时可以被限定或者省略。例如在创 CREATE TABLE t (i int); ``` -如果之前没有使用 `USE` 或者连接参数来设定数据库,会报 `ERROR 1046 (3D000): No database selected` 错误。此时可以指定数据库限定名: +如果你没有使用 `USE` 语句或连接参数来配置数据库,将显示 `ERROR 1046 (3D000): No database selected` 错误。此时,你可以指定数据库限定名称: {{< copyable "sql" >}} @@ -77,18 +96,20 @@ CREATE TABLE t (i int); CREATE TABLE test.t (i int); ``` -`.` 的左右两端可以出现空格,`table_name.col_name` 等于 `table_name . col_name`。 +`.` 周围可以存在空格。`table_name.col_name` 和 `table_name . col_name` 是等价的。 -如果要引用这个模式对象,那么请使用: +要引用此标识符,请使用: -``` +{{< copyable "sql" >}} + +```sql `table_name`.`col_name` ``` 而不是: -``` +```sql `table_name.col_name` ``` -更多细节,请参考 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/identifier-qualifiers.html)。 +更多信息,请参见 [MySQL Identifier Qualifiers](https://dev.mysql.com/doc/refman/8.0/en/identifier-qualifiers.html)。 diff --git a/shard-row-id-bits.md b/shard-row-id-bits.md index 5357605065b4..6bb608645c66 100644 --- a/shard-row-id-bits.md +++ b/shard-row-id-bits.md @@ -1,25 +1,35 @@ --- title: SHARD_ROW_ID_BITS -summary: 介绍 TiDB 的 `SHARD_ROW_ID_BITS` 表属性。 +summary: 了解 SHARD_ROW_ID_BITS 属性。 --- # SHARD_ROW_ID_BITS -本文介绍表属性 `SHARD_ROW_ID_BITS`,它用来设置隐式 `_tidb_rowid` 分片数量的 bit 位数。 +本文档介绍 `SHARD_ROW_ID_BITS` 表属性,该属性用于设置隐式 `_tidb_rowid` 分片后的分片位数。 -## 基本概念 +## 概念 -对于非[聚簇索引](/clustered-indexes.md)主键或没有主键的表,TiDB 会使用一个隐式的自增 rowid。大量执行 `INSERT` 插入语句时会把数据集中写入单个 Region,造成写入热点。 +对于非聚簇主键或没有主键的表,TiDB 使用隐式自增行 ID。当执行大量 `INSERT` 操作时,数据会写入单个 Region,导致写入热点。 -通过设置 `SHARD_ROW_ID_BITS`,可以把 rowid 打散写入多个不同的 Region,缓解写入热点问题。 +为了缓解热点问题,您可以配置 `SHARD_ROW_ID_BITS`。行 ID 会被打散,数据会写入多个不同的 Region。 - `SHARD_ROW_ID_BITS = 4` 表示 16 个分片 - `SHARD_ROW_ID_BITS = 6` 表示 64 个分片 -- `SHARD_ROW_ID_BITS = 0` 表示默认值 1 个分片 +- `SHARD_ROW_ID_BITS = 0` 表示默认 1 个分片 -关于 `SHARD_ROW_ID_BITS` 的更多使用信息,可参考[使用 SHARD_ROW_ID_BITS 处理热点表](/troubleshoot-hot-spot-issues.md#使用-shard_row_id_bits-处理热点表)。 + -## 语句示例 +有关使用详情,请参阅[热点问题处理指南](/troubleshoot-hot-spot-issues.md#use-shard_row_id_bits-to-process-hotspots)。 + + + + + +有关使用详情,请参阅[热点问题处理指南](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues#use-shard_row_id_bits-to-process-hotspots)。 + + + +## 示例 ```sql CREATE TABLE t ( diff --git a/sql-logical-optimization.md b/sql-logical-optimization.md index fc3e656ed62d..ffbb3770e480 100644 --- a/sql-logical-optimization.md +++ b/sql-logical-optimization.md @@ -1,20 +1,20 @@ --- -title: 逻辑优化 -summary: 本章节介绍了 TiDB 查询计划的关键逻辑改写,包括子查询优化、列裁剪、关联子查询去关联、Max/Min 消除、谓词下推、分区裁剪、TopN 和 Limit 下推以及 Join 重排序。这些改写帮助 TiDB 生成最终的查询计划,提高查询效率。 +title: SQL 逻辑优化 +summary: SQL 逻辑优化章节解释了 TiDB 查询计划生成中的关键逻辑重写。例如,由于 TiDB 的重写,`IN` 子查询 `t.a in (select t1.a from t1 where t1.b=t.b)` 不会存在。关键重写包括子查询相关优化、列裁剪、相关子查询去关联化、消除 Max/Min、谓词下推、分区裁剪、TopN 和 Limit 算子下推以及连接重排序。 --- -# 逻辑优化 +# SQL 逻辑优化 -本章节将对一些比较关键的逻辑改写进行说明,帮助大家理解 TiDB 如何生成最终的查询计划。比如在 TiDB 输入 `select * from t where t.a in (select t1.a from t1 where t1.b=t.b)` 这个查询时,在最终的执行计划中将看不到这个 `t.a in (select t1.a from t1 where t1.b=t.b)` 这个 `IN` 子查询的存在,这便是因为 TiDB 对这里进行了一些改写。 +本章节解释了一些关键的逻辑重写,帮助您理解 TiDB 如何生成最终的查询计划。例如,当您在 TiDB 中执行 `select * from t where t.a in (select t1.a from t1 where t1.b=t.b)` 查询时,您会发现 `IN` 子查询 `t.a in (select t1.a from t1 where t1.b=t.b)` 不存在,这是因为 TiDB 在这里进行了一些重写。 -本章节会介绍如下几个关键改写: +本章节介绍以下关键重写: -- [子查询相关的优化](/subquery-optimization.md) +- [子查询相关优化](/subquery-optimization.md) - [列裁剪](/column-pruning.md) -- [关联子查询去关联](/correlated-subquery-optimization.md) -- [Max/Min 消除](/max-min-eliminate.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) +- [TopN 和 Limit 算子下推](/topn-limit-push-down.md) +- [连接重排序](/join-reorder.md) - [从窗口函数中推导 TopN 或 Limit](/derive-topn-from-window.md) diff --git a/sql-mode.md b/sql-mode.md index fef7404db0ac..b25094a1b41e 100644 --- a/sql-mode.md +++ b/sql-mode.md @@ -1,55 +1,56 @@ --- title: SQL 模式 -summary: TiDB 服务器采用不同 SQL 模式来操作,可以使用 `SET [SESSION | GLOBAL] sql_mode='modes'` 语句设置 SQL 模式。`GLOBAL` 级别的 SQL 模式需要 `SUPER` 权限,影响新连接;`SESSION` 级别的 SQL 模式只影响当前客户端。重要的 sql_mode 值包括 `ANSI`、`STRICT_TRANS_TABLES` 和 `TRADITIONAL`。SQL mode 列表包括 `PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`、`ONLY_FULL_GROUP_BY` 等。 +summary: 了解 SQL 模式。 --- # SQL 模式 -TiDB 服务器采用不同 SQL 模式来操作,且不同客户端可以应用不同模式。SQL 模式定义 TiDB 支持哪些 SQL 语法及执行哪种数据验证检查。 - -TiDB 启动之后,你可以使用 `SET [ SESSION | GLOBAL ] sql_mode='modes'` 语句设置 SQL 模式。 - -- 设置 `GLOBAL` 级别的 SQL 模式时用户需要有 `SUPER` 权限,并且只会影响到从设置 SQL 模式开始后续新建立的连接(注:老连接不受影响)。 -- `SESSION` 级别的 SQL 模式的变化只会影响当前的客户端。 - -在该语句中,`modes` 是用逗号 (`,`) 间隔开的一系列不同的模式。使用 `SELECT @@sql_mode` 语句查询当前 SQL 模式,SQL 模式默认值:`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`。 - -## 重要的 sql_mode 值 - -* `ANSI`:符合标准 SQL,对数据进行校验,如果不符合定义类型或长度,对数据类型调整或截断保存,且返回 `warning` 警告。 -* `STRICT_TRANS_TABLES`:严格模式,对数据进行严格校验,当数据出现错误时,无法被插入到表中,并且返回错误。 -* `TRADITIONAL`:采用此模式使 TiDB 的行为像“传统” SQL 数据库系统,当在列中插入不正确的值时“给出错误而不是警告”,一旦发现错误立即放弃 `INSERT` 或 `UPDATE`。 - -## SQL mode 列表,如下 - -| 名称 | 含义 | -| --- | --- | -| `PIPES_AS_CONCAT` | 将 "\|\|" 视为字符串连接操作符 (`+`)(同 `CONCAT()`),而不视为 `OR`(支持)| -| `ANSI_QUOTES` | 将 `"` 视为识别符,如果启用 `ANSI_QUOTES`,只单引号内的会被认为是 String Literals,双引号被解释为识别符,因此不能用双引号来引用字符串(支持)| -| `IGNORE_SPACE` | 若开启该模式,系统忽略空格。例如:“user” 和 “user “ 是相同的(支持)| -| `ONLY_FULL_GROUP_BY` | 如果未被聚合函数处理或未被 `GROUP BY` 的列出现在 `SELECT`、`HAVING`、`ORDER BY` 中,此 SQL 不合法,因为这种列被查询展示出来不合常规。该设置受系统变量 [`tidb_enable_new_only_full_group_by_check`](/system-variables.md#tidb_enable_new_only_full_group_by_check-从-v610-版本开始引入) 影响。(支持)| -| `NO_UNSIGNED_SUBTRACTION` | 在减运算中,如果某个操作数没有符号,不要将结果标记为 `UNSIGNED`(支持)| -| `NO_DIR_IN_CREATE` | 创建表时,忽视所有 `INDEX DIRECTORY` 和 `DATA DIRECTORY` 指令,该选项仅对从复制服务器有用 (仅语法支持)| -| `NO_KEY_OPTIONS` | 使用 `SHOW CREATE TABLE` 时不会输出 MySQL 特有的语法部分,如 `ENGINE`,使用 mysqldump 跨 DB 种类迁移的时需要考虑此选项(仅语法支持)| -| `NO_FIELD_OPTIONS` | 使用 `SHOW CREATE TABLE` 时不会输出 MySQL 特有的语法部分,如 `ENGINE`,使用 mysqldump 跨 DB 种类迁移的时需要考虑此选项(仅语法支持)| -| `NO_TABLE_OPTIONS` | 使用 `SHOW CREATE TABLE` 时不会输出 MySQL 特有的语法部分,如 `ENGINE`,使用 mysqldump 跨 DB 种类迁移的时需要考虑此选项(仅语法支持)| -| `NO_AUTO_VALUE_ON_ZERO` | 若启用该模式,在 [`AUTO_INCREMENT`](/auto-increment.md) 列传入的值是 `0` 或者具体数值时系统直接将该值写入此列,传入 `NULL` 时系统自动生成下一个序列号(支持)| -| `NO_BACKSLASH_ESCAPES` | 若启用该模式,`\` 反斜杠符号仅代表它自己(支持)| -| `STRICT_TRANS_TABLES` | 对于事务存储引擎启用严格模式,insert非法值之后,回滚整条语句(支持)| -| `STRICT_ALL_TABLES` | 对于事务型表,写入非法值之后,回滚整个事务语句(支持)| -| `NO_ZERO_IN_DATE` | 在严格模式,不接受月或日部分为0的日期。如果使用IGNORE选项,我们为类似的日期插入'0000-00-00'。在非严格模式,可以接受该日期,但会生成警告(支持) -| `NO_ZERO_DATE` | 在严格模式,不要将 '0000-00-00'做为合法日期。你仍然可以用 `IGNORE` 选项插入零日期。在非严格模式,可以接受该日期,但会生成警告(支持)| -| `ALLOW_INVALID_DATES` | 不检查全部日期的合法性,仅检查月份值在 1 到 12 及日期值在 1 到 31 之间,仅适用于 `DATE` 和 `DATATIME` 列,`TIMESTAMP` 列需要全部检查其合法性(支持)| -| `ERROR_FOR_DIVISION_BY_ZERO` | 若启用该模式,在 `INSERT` 或 `UPDATE` 过程中,被除数为 `0` 值时,系统产生错误
若未启用该模式,被除数为 0 值时,系统产生警告,并用 `NULL` 代替(支持) | -| `NO_AUTO_CREATE_USER` | 防止 `GRANT` 自动创建新用户,但指定密码除外(支持)| -| `HIGH_NOT_PRECEDENCE` | NOT 操作符的优先级是表达式。例如:`NOT a BETWEEN b AND c` 被解释为 `NOT (a BETWEEN b AND c)`。在部份旧版本 MySQL 中,表达式被解释为 `(NOT a) BETWEEN b AND c`(支持) | -| `NO_ENGINE_SUBSTITUTION` | 如果需要的存储引擎被禁用或未编译,可以防止自动替换存储引擎(仅语法支持)| -| `PAD_CHAR_TO_FULL_LENGTH` | 若启用该模式,系统对于 `CHAR` 类型不会截断尾部空格(仅语法支持。该模式[在 MySQL 8.0 中已废弃](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length)。)| -| `REAL_AS_FLOAT` | 将 `REAL` 视为 `FLOAT` 的同义词,而不是 `DOUBLE` 的同义词(支持)| +TiDB 服务器在不同的 SQL 模式下运行,并针对不同的客户端应用这些模式。SQL 模式定义了 TiDB 支持的 SQL 语法以及要执行的数据验证检查类型,具体说明如下: + +TiDB 启动后,你可以使用 `SET [ SESSION | GLOBAL ] sql_mode='modes'` 语句来设置 SQL 模式。 + +- 在 `GLOBAL` 级别设置 SQL 模式时,确保你具有 `SUPER` 权限,并且此级别的设置仅影响之后建立的连接。 + +- 在 `SESSION` 级别更改 SQL 模式仅影响当前客户端。 + +在此语句中,`modes` 是由逗号(',')分隔的一组模式。你可以使用 `SELECT @@sql_mode` 语句检查当前的 SQL 模式。SQL 模式的默认值为:`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`。 + +## 重要的 `sql_mode` 值 + +* `ANSI`:此模式符合标准 SQL。在此模式下,会检查数据。如果数据不符合定义的类型或长度,则会调整或截断数据类型,并返回 `warning`。 +* `STRICT_TRANS_TABLES`:严格模式,严格检查数据。如果任何数据不正确,则无法插入表中,并返回错误。 +* `TRADITIONAL`:在此模式下,TiDB 的行为类似于"传统的" SQL 数据库系统。当向列中插入任何不正确的值时,会返回错误而不是警告。然后,`INSERT` 或 `UPDATE` 语句会立即停止。 + +## SQL 模式表 + +| 名称 | 描述 | +| :--- | :--- | +| `PIPES_AS_CONCAT` | 将 "\|\|" 视为字符串连接运算符(`+`)(与 `CONCAT()` 相同),而不是 `OR`(完全支持)| +| `ANSI_QUOTES` | 将 `"` 视为标识符。如果启用 `ANSI_QUOTES`,则只有单引号被视为字符串字面量,双引号被视为标识符。因此,双引号不能用于引用字符串。(完全支持)| +| `IGNORE_SPACE` | 如果启用此模式,系统会忽略空格。例如:"user" 和 "user " 是相同的。(完全支持)| +| `ONLY_FULL_GROUP_BY` | 如果 SQL 语句在 `SELECT`、`HAVING` 或 `ORDER BY` 中引用的列既不是聚合列也不包含在 `GROUP BY` 子句中,则该语句无效。这是因为在查询结果中显示此类列是异常的。此设置受系统变量 [`tidb_enable_new_only_full_group_by_check`](/system-variables.md#tidb_enable_new_only_full_group_by_check-new-in-v610) 的影响。(完全支持)| +| `NO_UNSIGNED_SUBTRACTION` | 如果在减法中某个操作数没有符号,则不将结果标记为 `UNSIGNED`。(完全支持)| +| `NO_DIR_IN_CREATE` | 创建表时忽略所有 `INDEX DIRECTORY` 和 `DATA DIRECTORY` 指令。此选项仅对二级复制服务器有用(仅语法支持)| +| `NO_KEY_OPTIONS` | 使用 `SHOW CREATE TABLE` 语句时,不导出 MySQL 特定的语法,如 `ENGINE`。在使用 mysqldump 跨数据库类型迁移时考虑此选项。(仅语法支持)| +| `NO_FIELD_OPTIONS` | 使用 `SHOW CREATE TABLE` 语句时,不导出 MySQL 特定的语法,如 `ENGINE`。在使用 mysqldump 跨数据库类型迁移时考虑此选项。(仅语法支持)| +| `NO_TABLE_OPTIONS` | 使用 `SHOW CREATE TABLE` 语句时,不导出 MySQL 特定的语法,如 `ENGINE`。在使用 mysqldump 跨数据库类型迁移时考虑此选项。(仅语法支持)| +| `NO_AUTO_VALUE_ON_ZERO` | 如果启用此模式,当传入 [`AUTO_INCREMENT`](/auto-increment.md) 列的值为 `0` 或特定值时,系统直接将此值写入该列。当传入 `NULL` 时,系统自动生成下一个序列号。(完全支持)| +| `NO_BACKSLASH_ESCAPES` | 如果启用此模式,`\` 反斜杠符号仅代表其本身。(完全支持)| +| `STRICT_TRANS_TABLES` | 为事务存储引擎启用严格模式,在插入非法值后回滚整个语句。(完全支持)| +| `STRICT_ALL_TABLES` | 对于事务表,在插入非法值后回滚整个事务语句。(完全支持)| +| `NO_ZERO_IN_DATE` | 严格模式,不接受月份或日期部分为 `0` 的日期。如果使用 `IGNORE` 选项,TiDB 会为类似日期插入 '0000-00-00'。在非严格模式下,接受此日期但返回警告。(完全支持)| +| `NO_ZERO_DATE` | 在严格模式下不使用 '0000-00-00' 作为合法日期。你仍可以使用 `IGNORE` 选项插入零日期。在非严格模式下,接受此日期但返回警告。(完全支持)| +| `ALLOW_INVALID_DATES` | 在此模式下,系统不检查所有日期的有效性。它只检查月份值是否在 `1` 到 `12` 范围内,以及日期值是否在 `1` 到 `31` 范围内。该模式仅适用于 `DATE` 和 `DATETIME` 列。所有 `TIMESTAMP` 列都需要完整的有效性检查。(完全支持)| +| `ERROR_FOR_DIVISION_BY_ZERO` | 如果启用此模式,在处理数据更改操作(`INSERT` 或 `UPDATE`)中的除以 `0` 时,系统返回错误。
如果未启用此模式,系统返回警告并使用 `NULL` 代替。(完全支持)| +| `NO_AUTO_CREATE_USER` | 防止 `GRANT` 自动创建新用户,除非指定了密码(完全支持)| +| `HIGH_NOT_PRECEDENCE` | NOT 运算符的优先级使得诸如 `NOT a BETWEEN b AND c` 之类的表达式被解析为 `NOT (a BETWEEN b AND c)`。在某些较旧版本的 MySQL 中,此表达式被解析为 `(NOT a) BETWEEN b AND c`。(完全支持)| +| `NO_ENGINE_SUBSTITUTION` | 如果所需的存储引擎被禁用或未编译,则防止自动替换存储引擎。(仅语法支持)| +| `PAD_CHAR_TO_FULL_LENGTH` | 如果启用此模式,系统不会修剪 `CHAR` 类型的尾随空格。(仅语法支持。此模式在 [MySQL 8.0 中已弃用](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length)。)| +| `REAL_AS_FLOAT` | 将 `REAL` 视为 `FLOAT` 的同义词,而不是 `DOUBLE` 的同义词(完全支持)| | `POSTGRESQL` | 等同于 `PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`、`NO_KEY_OPTIONS`、`NO_TABLE_OPTIONS`、`NO_FIELD_OPTIONS`(仅语法支持)| -| `MSSQL` | 等同于 `PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`、`NO_KEY_OPTIONS`、`NO_TABLE_OPTIONS`、 `NO_FIELD_OPTIONS`(仅语法支持)| +| `MSSQL` | 等同于 `PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`、`NO_KEY_OPTIONS`、`NO_TABLE_OPTIONS`、`NO_FIELD_OPTIONS`(仅语法支持)| | `DB2` | 等同于 `PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`、`NO_KEY_OPTIONS`、`NO_TABLE_OPTIONS`、`NO_FIELD_OPTIONS`(仅语法支持)| -| `MAXDB` | 等同于 `PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`、`NO_KEY_OPTIONS`、`NO_TABLE_OPTIONS`、`NO_FIELD_OPTIONS`、`NO_AUTO_CREATE_USER`(支持)| +| `MAXDB` | 等同于 `PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`、`NO_KEY_OPTIONS`、`NO_TABLE_OPTIONS`、`NO_FIELD_OPTIONS`、`NO_AUTO_CREATE_USER`(完全支持)| | `MySQL323` | 等同于 `NO_FIELD_OPTIONS`、`HIGH_NOT_PRECEDENCE`(仅语法支持)| | `MYSQL40` | 等同于 `NO_FIELD_OPTIONS`、`HIGH_NOT_PRECEDENCE`(仅语法支持)| | `ANSI` | 等同于 `REAL_AS_FLOAT`、`PIPES_AS_CONCAT`、`ANSI_QUOTES`、`IGNORE_SPACE`(仅语法支持)| diff --git a/sql-non-prepared-plan-cache.md b/sql-non-prepared-plan-cache.md index 2f17763f0ff3..fe8dda9204b3 100644 --- a/sql-non-prepared-plan-cache.md +++ b/sql-non-prepared-plan-cache.md @@ -1,63 +1,63 @@ --- -title: 非 Prepare 语句执行计划缓存 -summary: 介绍 TiDB 中非 Prepare 语句执行计划缓存的原理、使用方法及示例。 +title: SQL 非预处理执行计划缓存 +summary: 了解 TiDB 中 SQL 非预处理执行计划缓存的原理、用法和示例。 --- -# 非 Prepare 语句执行计划缓存 +# SQL 非预处理执行计划缓存 -对于某些非 `PREPARE` 语句,TiDB 可以像 [`Prepare`/`Execute` 语句](/sql-prepared-plan-cache.md)一样支持执行计划缓存。这可以让这些语句跳过优化器阶段,以提升性能。 +TiDB 支持对某些非 `PREPARE` 语句进行执行计划缓存,类似于 [`Prepare`/`Execute` 语句](/sql-prepared-plan-cache.md)。此功能允许这些语句跳过优化阶段并提高性能。 -开启非 Prepare 语句执行计划缓存可能会带来额外的内存和 CPU 开销,并不一定适用于所有场景。建议参考[性能收益](#性能收益)和[内存监控](#监控)章节,根据具体的使用情况决定是否开启该功能。 +启用非预处理计划缓存可能会带来额外的内存和 CPU 开销,可能并不适合所有情况。要确定是否在您的场景中启用此功能,请参考[性能优势](#性能优势)和[内存监控](#监控)部分。 ## 原理 -Non-Prepared Plan Cache 为会话级别,并且与 [Prepared Plan Cache](/sql-prepared-plan-cache.md) 共用一个缓存。Non-Prepared Plan Cache 功能的基本原理如下: +非预处理计划缓存是一个会话级别的功能,与[预处理计划缓存](/sql-prepared-plan-cache.md)共享一个缓存。非预处理计划缓存的基本原理如下: -1. 开启 Non-Prepared Plan Cache 后,TiDB 首先根据 AST(抽象语法树)对查询进行参数化。例如,将 `SELECT * FROM t WHERE b < 10 AND a = 1` 参数化为 `SELECT * FROM t WHERE b < ? and a = ?`。 -2. 然后,使用参数化后的查询在 Plan Cache 中查找。 -3. 如果能找到可以直接复用的计划,则直接使用,并跳过整个优化过程。 -4. 否则,继续进行查询优化,并在最后将生成的计划放回到缓存中,以便下次复用。 +1. 启用非预处理计划缓存后,TiDB 首先基于抽象语法树(AST)对查询进行参数化。例如,`SELECT * FROM t WHERE b < 10 AND a = 1` 被参数化为 `SELECT * FROM t WHERE b < ? and a = ?`。 +2. 然后,TiDB 使用参数化的查询在计划缓存中搜索。 +3. 如果找到可重用的计划,则直接使用它并跳过优化阶段。 +4. 否则,优化器生成一个新计划并将其添加回缓存中,以供后续查询重用。 -## 使用方法 +## 用法 -目前,你可以通过 [`tidb_enable_non_prepared_plan_cache`](/system-variables.md#tidb_enable_non_prepared_plan_cache) 开启或关闭 Non-Prepared Plan Cache。同时,你还可以通过 [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-从-v710-版本开始引入) 来控制 Plan Cache 的大小。当缓存的计划数超过 `tidb_session_plan_cache_size` 时,TiDB 会使用 LRU (Least Recently Used) 策略进行逐出。 +要启用或禁用非预处理计划缓存,您可以设置 [`tidb_enable_non_prepared_plan_cache`](/system-variables.md#tidb_enable_non_prepared_plan_cache) 系统变量。您还可以使用 [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-new-in-v710) 系统变量控制非预处理计划缓存的大小。当缓存的计划数量超过 `tidb_session_plan_cache_size` 时,TiDB 使用最近最少使用(LRU)策略淘汰计划。 -从 v7.1.0 开始,你可以通过变量 [`tidb_plan_cache_max_plan_size`](/system-variables.md#tidb_plan_cache_max_plan_size-从-v710-版本开始引入) 来设置可以缓存的计划的最大大小,默认为 2 MB。超过该值的执行计划将不会被缓存到 Plan Cache 中。 +从 v7.1.0 开始,您可以使用系统变量 [`tidb_plan_cache_max_plan_size`](/system-variables.md#tidb_plan_cache_max_plan_size-new-in-v710) 控制可以缓存的计划的最大大小。默认值为 2 MB。如果计划的大小超过此值,则不会缓存该计划。 > **注意:** > -> `tidb_session_plan_cache_size` 定义的内存会被 Prepared 和 Non-Prepared Plan Cache 共享。如果集群已经开启 Prepared Plan Cache,那么开启 Non-Prepared Plan Cache 可能降低原先 Prepared Plan Cache 的命中率。 +> `tidb_session_plan_cache_size` 指定的内存在预处理和非预处理计划缓存之间共享。如果您已经为当前集群启用了预处理计划缓存,启用非预处理计划缓存可能会降低原有预处理计划缓存的命中率。 ## 示例 -下面是一个使用示例: +以下示例展示如何使用非预处理计划缓存: -1. 创建用于测试的表 `t`: +1. 创建一个测试表 `t`: ```sql CREATE TABLE t (a INT, b INT, KEY(b)); ``` -2. 开启 Non-Prepared Plan Cache: +2. 启用非预处理计划缓存: ```sql SET tidb_enable_non_prepared_plan_cache = ON; ``` -3. 依次执行以下查询: +3. 执行以下两个查询: ```sql SELECT * FROM t WHERE b < 10 AND a = 1; SELECT * FROM t WHERE b < 5 AND a = 2; ``` -4. 查看第二个查询语句是否命中缓存: +4. 检查第二个查询是否命中缓存: ```sql SELECT @@last_plan_from_cache; ``` - 输出结果中 `last_plan_from_cache` 的值为 `1`,表示第二次执行的查询计划来自于缓存: + 如果输出中 `last_plan_from_cache` 的值为 `1`,表示第二个查询的执行计划来自缓存: ```sql +------------------------+ @@ -70,64 +70,64 @@ Non-Prepared Plan Cache 为会话级别,并且与 [Prepared Plan Cache](/sql-p ## 限制 -### 缓存限制 +### 缓存次优计划 -TiDB 对参数化后形式相同的查询,只能缓存一个计划。例如,对于 `SELECT * FROM t WHERE a < 1` 和 `SELECT * FROM t WHERE a < 100000` 这两个查询语句,由于参数化后的形式相同,均为 `SELECT * FROM t WHERE a < ?`,因此它们会共用一个计划。 +TiDB 对于一个参数化查询只缓存一个计划。例如,查询 `SELECT * FROM t WHERE a < 1` 和 `SELECT * FROM t WHERE a < 100000` 共享相同的参数化形式 `SELECT * FROM t WHERE a < ?`,因此共享相同的计划。 -如果由此产生性能问题,可以使用 `ignore_plan_cache()` Hint 忽略计划缓存中的计划,让优化器每次重新为 SQL 生成执行计划。如果无法修改 SQL,可以通过创建 binding 来解决,例如 `CREATE BINDING FOR SELECT ... USING SELECT /*+ ignore_plan_cache() */ ...`。 +如果这导致性能问题,您可以使用 `ignore_plan_cache()` 提示来忽略缓存中的计划,这样优化器每次都会为该 SQL 生成新的执行计划。如果无法修改 SQL,您可以创建绑定来解决问题。例如,`CREATE BINDING FOR SELECT ... USING SELECT /*+ ignore_plan_cache() */ ...`。 ### 使用限制 -由于上述风险以及执行计划缓存只在简单查询上有明显收益(如果查询较为复杂,查询本身执行时间较长,使用执行计划缓存收益不大),TiDB 目前对 Non-Prepared Plan Cache 的生效范围有严格的限制。具体限制如下: +由于上述风险,以及执行计划缓存仅对简单查询提供显著优势(如果查询复杂且执行时间较长,使用执行计划缓存可能帮助不大),TiDB 对非预处理计划缓存的范围有严格限制。限制如下: -- [Prepared Plan Cache](/sql-prepared-plan-cache.md) 不支持的查询或者计划,Non-Prepared Plan Cache 也不支持。 -- 不支持包含 `Window` 或 `Having` 的查询。 -- 不支持包含三张表及以上 `Join` 或子查询的查询。 -- 不支持 `ORDER BY` 或者 `GROUP BY` 后直接带数字或者表达式的查询,如 `ORDER BY 1`、`GROUP BY a+1`。仅支持 `ORDER BY column_name` 和 `GROUP BY column_name`。 -- 不支持过滤条件中包含 `JSON`、`ENUM`、`SET` 或 `BIT` 类型的列的查询,例如 `SELECT * FROM t WHERE json_col = '{}'`。 -- 不支持过滤条件中出现 `NULL` 值的查询,例如 `SELECT * FROM t WHERE a is NULL`。 -- 默认不支持参数化后参数个数超过 200 个的查询,例如 `SELECT * FROM t WHERE a in (1, 2, 3, ... 201)`。从 v7.3.0 开始,你可以通过在 [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-从-v653-和-v710-版本开始引入) 系统变量中设置 [`44823`](/optimizer-fix-controls.md#44823-从-v730-版本开始引入) 这个 Fix 来调整该限制。 -- 不支持访问虚拟列、临时表、视图、或内存表的查询,例如 `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`,其中 `COLUMNS` 为 TiDB 内存表。 -- 不支持带有 Hint 或有 Binding 的查询。 -- 默认不支持 DML 语句或包含 `FOR UPDATE` 的查询语句。若要启用支持,你可以执行 `SET tidb_enable_non_prepared_plan_cache_for_dml = ON`。 +- [预处理计划缓存](/sql-prepared-plan-cache.md)不支持的查询或计划,非预处理计划缓存也不支持。 +- 不支持包含 `Window` 或 `Having` 等复杂运算符的查询。 +- 不支持包含三个或更多 `Join` 表或子查询的查询。 +- 不支持在 `ORDER BY` 或 `GROUP BY` 后直接包含数字或表达式的查询,如 `ORDER BY 1` 和 `GROUP BY a+1`。仅支持 `ORDER BY column_name` 和 `GROUP BY column_name`。 +- 不支持对 `JSON`、`ENUM`、`SET` 或 `BIT` 类型列进行过滤的查询,如 `SELECT * FROM t WHERE json_col = '{}'`。 +- 不支持对 `NULL` 值进行过滤的查询,如 `SELECT * FROM t WHERE a is NULL`。 +- 默认不支持参数化后参数超过 200 个的查询,如 `SELECT * FROM t WHERE a in (1, 2, 3, ... 201)`。从 v7.3.0 开始,您可以通过在 [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710) 系统变量中设置 [`44823`](/optimizer-fix-controls.md#44823-new-in-v730) 修复来修改此限制。 +- 不支持访问虚拟列、临时表、视图或内存表的查询,如 `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`,其中 `COLUMNS` 是 TiDB 内存表。 +- 不支持带有提示或绑定的查询。 +- 默认不支持 DML 语句或带有 `FOR UPDATE` 子句的 `SELECT` 语句。要移除此限制,您可以执行 `SET tidb_enable_non_prepared_plan_cache_for_dml = ON`。 -开启此功能后,优化器会对查询进行快速判断,如果不满足 Non-Prepared Plan Cache 的支持条件,则会走正常的优化流程。 +启用此功能后,优化器会快速评估查询。如果不满足非预处理计划缓存的支持条件,查询会回退到常规优化过程。 -## 性能收益 +## 性能优势 -在内部测试中,开启 Non-Prepared Plan Cache 功能在大多数 TP 场景下可以获得显著的性能收益。例如:TPCC 测试中性能提升约 4%,一些 Bank 负载上提升超过 10%,在 Sysbench RangeScan 上提升达到 15%。 +在内部测试中,启用非预处理计划缓存功能在大多数 TP 场景下都能获得显著的性能优势。例如,在 TPC-C 测试中性能提升约 4%,在某些银行工作负载中提升超过 10%,在 Sysbench RangeScan 中提升 15%。 -但是这个功能本身也会带来额外的 CPU 和内存开销,包括判断查询是否支持、对查询进行参数化、在 Plan Cache 中进行搜索等。如果负载中的多数查询无法被 Cache 命中,开启此功能反而可能影响性能。 +然而,此功能也会带来一些额外的内存和 CPU 开销,包括确定查询是否受支持、参数化查询和在缓存中搜索计划。如果缓存无法命中您工作负载中的大多数查询,启用它可能实际上会对性能产生不利影响。 -此时,你需要观察 Grafana 监控中的 **Queries Using Plan Cache OPS** 面板中的 `non-prepared` 指标和 **Plan Cache Miss OPS** 面板中的 `non-prepared-unsupported` 指标。如果大多数查询都无法被支持,只有少部分查询能命中 Plan Cache,此时你可以关闭此功能。 +在这种情况下,您需要观察 Grafana 上 **Queries Using Plan Cache OPS** 面板中的 `non-prepared` 指标和 **Plan Cache Miss OPS** 面板中的 `non-prepared-unsupported` 指标。如果大多数查询不受支持,只有少数能命中计划缓存,您可以禁用此功能。 ![non-prepared-unsupported](/media/non-prepapred-plan-cache-unsupprot.png) ## 诊断 -开启 Non-Prepared Plan Cache 后,可以使用 `EXPLAIN FORMAT='plan_cache' SELECT ...` 语句验证查询是否能够命中缓存。对于无法命中缓存的查询,系统会通过 warning 的方式返回无法命中的原因。 +启用非预处理计划缓存后,您可以执行 `EXPLAIN FORMAT='plan_cache' SELECT ...` 语句来验证查询是否能命中缓存。对于无法命中缓存的查询,系统会在警告中返回原因。 -需要注意的是,如果不加 `FORMAT='plan_cache'`,则 `EXPLAIN` 语句永远不会命中缓存。 +请注意,如果您不添加 `FORMAT='plan_cache'`,`EXPLAIN` 语句将永远不会命中缓存。 -执行下面 `EXPLAIN FORMAT='plan_cache'` 语句,查看查询是否能够命中: +要验证查询是否命中缓存,执行以下 `EXPLAIN FORMAT='plan_cache'` 语句: ```sql EXPLAIN FORMAT='plan_cache' SELECT * FROM (SELECT a+1 FROM t) t; ``` -输出结果示例如下: +输出如下: ```sql 3 rows in set, 1 warning (0.00 sec) ``` -通过 `SHOW warnings;` 查看无法命中缓存的查询信息: +要查看无法命中缓存的查询,执行 `SHOW warnings;`: ```sql SHOW warnings; ``` -输出结果示例如下: +输出如下: ```sql +---------+------+-------------------------------------------------------------------------------+ @@ -138,15 +138,15 @@ SHOW warnings; 1 row in set (0.00 sec) ``` -可以看到在上述例子中,由于 Non-Prepared Plan Cache 不支持 `+` 操作,所以无法命中缓存。 +在上述示例中,由于非预处理计划缓存不支持 `+` 操作,查询无法命中缓存。 ## 监控 -开启 Non-Prepared Plan Cache 后,可以在以下几个面板中查看缓存的内存使用情况、缓存中计划的个数、缓存命中的情况等信息。 +启用非预处理计划缓存后,您可以在以下面板中监控内存使用情况、缓存中的计划数量和缓存命中率: -![non-prepared-plan-cache](/media/tidb-non-prepared-plan-cache-metrics.png) +![non-prepare-plan-cache](/media/tidb-non-prepared-plan-cache-metrics.png) -`statements_summary` 表和慢查询日志也会体现缓存的命中情况。下面是查看 `statements_summary` 表中缓存命中情况的例子: +您还可以在 `statements_summary` 表和慢查询日志中监控缓存命中率。以下展示如何在 `statements_summary` 表中查看缓存命中率: 1. 创建表 `t`: @@ -154,13 +154,13 @@ SHOW warnings; CREATE TABLE t (a int); ``` -2. 打开 Non-Prepared Plan Cache 开关: +2. 启用非预处理计划缓存: ```sql - SET @@tidb_enable_non_prepared_plan_cache = ON; + SET @@tidb_enable_non_prepared_plan_cache=ON; ``` -3. 依次执行以下三个查询: +3. 执行以下三个查询: ```sql SELECT * FROM t WHERE a<1; @@ -168,13 +168,13 @@ SHOW warnings; SELECT * FROM t WHERE a<3; ``` -4. 查询 `statements_summary` 表查看查询命中缓存的情况: +4. 查询 `statements_summary` 表以查看缓存命中率: ```sql SELECT digest_text, query_sample_text, exec_count, plan_in_cache, plan_cache_hits FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY WHERE query_sample_text LIKE '%SELECT * FROM %'; ``` - 输出结果如下: + 输出如下: ```sql +---------------------------------+------------------------------------------+------------+---------------+-----------------+ @@ -185,4 +185,4 @@ SHOW warnings; 1 row in set (0.01 sec) ``` - 可以看到,查询执行了三次且命中缓存两次。 \ No newline at end of file + 从输出中可以看到,查询执行了三次,命中缓存两次。 diff --git a/sql-optimization-concepts.md b/sql-optimization-concepts.md index 226102b82e65..182657c22a7c 100644 --- a/sql-optimization-concepts.md +++ b/sql-optimization-concepts.md @@ -1,16 +1,16 @@ --- -title: SQL 优化流程简介 -summary: TiDB 中的 SQL 优化流程包括查询文本解析、逻辑等价变化和最终执行计划生成。经过 parser 解析和合法性验证后,TiDB 会对查询进行逻辑上的等价变化,使得查询在逻辑执行计划上更易处理。之后根据数据分布和执行开销生成最终执行计划。同时,TiDB 在执行 PREPARE 语句时可以选择开启缓存来降低执行计划生成的开销。 +title: SQL 优化过程 +summary: 了解 TiDB 中 SQL 的逻辑优化和物理优化。 --- -# SQL 优化流程简介 +# SQL 优化过程 -在 TiDB 中,从输入的查询文本到最终的执行计划执行结果的过程可以见下图。 +在 TiDB 中,从输入查询到根据最终执行计划获得执行结果的过程如下图所示: -![SQL Optimization](/media/sql-optimization.png) +![SQL 优化过程](/media/sql-optimization.png) -在经过了 `parser` 对原始查询文本的解析以及一些简单的合法性验证后,TiDB 首先会对查询做一些逻辑上的等价变化,详细的变化可以查询[逻辑优化](/sql-logical-optimization.md)章节。 +在通过 `parser` 解析原始查询文本并进行一些简单的有效性检查后,TiDB 首先对查询进行一些逻辑等价的变换。有关详细变换,请参见 [SQL 逻辑优化](/sql-logical-optimization.md)。 -通过这些等价变化,使得这个查询在逻辑执行计划上可以变得更易于处理。在等价变化结束之后,TiDB 会得到一个与原始查询等价的查询计划结构,之后根据数据分布、以及一个算子具体的执行开销,来获得一个最终的执行计划,这部分内容可以查询[物理优化](/sql-physical-optimization.md)章节。 +通过这些等价变换,该查询在逻辑执行计划中变得更容易处理。完成等价变换后,TiDB 获得一个与原始查询等价的查询计划结构,然后基于数据分布和操作符的具体执行成本获得最终的执行计划。有关详细信息,请参见 [SQL 物理优化](/sql-physical-optimization.md)。 -同时,TiDB 在执行 [`PREPARE`](/sql-statements/sql-statement-prepare.md) 语句时,可以选择开启缓存来降低 TiDB 生成执行计划的开销,这部分内容会在[执行计划缓存](/sql-prepared-plan-cache.md)一节中介绍。 \ No newline at end of file +同时,当 TiDB 执行 [`PREPARE`](/sql-statements/sql-statement-prepare.md) 语句时,您可以选择启用缓存以减少在 TiDB 中生成执行计划的成本。有关详细信息,请参见[执行计划缓存](/sql-prepared-plan-cache.md)。 diff --git a/sql-physical-optimization.md b/sql-physical-optimization.md index 8c07f623c065..2d00f86a1c0f 100644 --- a/sql-physical-optimization.md +++ b/sql-physical-optimization.md @@ -1,18 +1,16 @@ --- -title: 物理优化 -summary: 物理优化是基于代价的优化,为逻辑执行计划制定物理执行计划。优化器根据数据统计信息选择时间复杂度、资源消耗和物理属性最小的物理执行计划。TiDB 执行计划文档介绍了索引选择、统计信息、错误索引解决方案、Distinct 优化和代价模型。 +title: SQL 物理优化 +summary: 物理优化是一个基于成本的过程,用于为逻辑执行计划创建物理执行计划。优化器根据数据统计信息、时间复杂度和资源消耗为每个算子选择最佳的物理实现。这包括索引选择、统计信息收集、使用正确的索引、distinct 关键字优化,以及用于选择最优执行计划的成本模型。 --- -# 物理优化 +# SQL 物理优化 -物理优化是基于代价的优化,为上一阶段产生的逻辑执行计划制定物理执行计划。这一阶段中,优化器会为逻辑执行计划中的每个算子选择具体的物理实现。逻辑算子的不同物理实现有着不同的时间复杂度、资源消耗和物理属性等。在这个过程中,优化器会根据数据的统计信息来确定不同物理实现的代价,并选择整体代价最小的物理执行计划。 +物理优化是基于成本的优化,它为上一阶段生成的逻辑执行计划制定物理执行计划。在这个阶段,优化器为逻辑执行计划中的每个算子选择特定的物理实现。逻辑算子的不同物理实现具有不同的时间复杂度、资源消耗和物理属性。在这个过程中,优化器根据数据的统计信息确定不同物理实现的成本,并选择总体成本最小的物理执行计划。 -[理解 TiDB 执行计划](/explain-overview.md)文档中对每个物理算子进行了一些介绍,本章节重点介绍以下方面: +[理解查询执行计划](/explain-overview.md)已经介绍了一些物理算子。本章重点关注以下几个方面: -- [索引的选择](/choose-index.md):介绍在一张表有多个索引时,TiDB 如何选择最优的索引来访问表。 -- [常规统计信息](/statistics.md):介绍 TiDB 收集了哪些常规统计信息来获得表的数据分布情况。 -- [扩展统计信息](/extended-statistics.md):介绍如何使用扩展统计信息指导优化器。 -- [错误索引的解决方案](/wrong-index-solution.md):介绍当发现 TiDB 索引选错时,你应该使用哪些手段使其使用正确的索引。 -- [Distinct 优化](/agg-distinct-optimization.md):介绍有关 `DISTINCT` 关键字的优化,包括其优缺点以及如何使用它。 -- [代价模型](/cost-model.md):介绍在物理优化时,TiDB 怎么通过代价模型来选择一个最优的执行计划。 -- [Runtime Filter](/runtime-filter.md):介绍如何通过动态生成 Filter 提升 MPP 场景下 Hash Join 的性能。 \ No newline at end of file +- 在[索引选择](/choose-index.md)中,你将了解当 TiDB 在表上有多个索引时,如何选择最优索引来访问表。 +- 在[统计信息简介](/statistics.md)中,你将了解 TiDB 收集哪些统计信息来获取表的数据分布。 +- [错误索引解决方案](/wrong-index-solution.md)介绍了当发现索引选择错误时如何使用正确的索引。 +- [Distinct 优化](/agg-distinct-optimization.md)介绍了物理优化过程中与 `DISTINCT` 关键字相关的优化。在这一节中,你将了解它的优缺点以及如何使用它。 +- [成本模型](/cost-model.md)介绍了在物理优化过程中如何基于成本模型选择最优执行计划。 diff --git a/sql-plan-management.md b/sql-plan-management.md index 346f6f8a8349..24818ea15136 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -1,25 +1,37 @@ --- -title: 执行计划管理 (SPM) -summary: 介绍 TiDB 的执行计划管理 (SQL Plan Management) 功能。 +title: SQL 执行计划管理 (SPM) +summary: 了解 TiDB 中的 SQL 执行计划管理。 --- -# 执行计划管理 (SPM) +# SQL 执行计划管理 (SPM) -执行计划管理,又称 SPM (SQL Plan Management),是通过执行计划绑定,对执行计划进行人为干预的一系列功能,包括执行计划绑定、自动捕获绑定、自动演进绑定等。 +SQL 执行计划管理是一组用于手动干预 SQL 执行计划的功能。这些功能包括 SQL 绑定、基线捕获和基线演进。 -## 执行计划绑定 (SQL Binding) +## SQL 绑定 -执行计划绑定是 SPM 的基础。在[优化器 Hints](/optimizer-hints.md) 中介绍了可以通过 Hint 的方式选择指定的执行计划,但有时需要在不修改 SQL 语句的情况下干预执行计划的选择。执行计划绑定功能使得可以在不修改 SQL 语句的情况下选择指定的执行计划。 +SQL 绑定是 SPM 的基础。[优化器提示](/optimizer-hints.md)文档介绍了如何使用提示选择特定的执行计划。但是,有时您需要在不修改 SQL 语句的情况下干预执行计划的选择。通过 SQL 绑定,您可以在不修改 SQL 语句的情况下选择指定的执行计划。 + + + +> **注意:** +> +> 要使用 SQL 绑定,您需要具有 `SUPER` 权限。如果 TiDB 提示您没有足够的权限,请参见[权限管理](/privilege-management.md)添加所需的权限。 + + + + > **注意:** > -> 要使用执行计划绑定,你需要拥有 `SUPER` 权限。如果在使用过程中系统提示权限不足,可参考[权限管理](/privilege-management.md)补充所需权限。 +> 要使用 SQL 绑定,您需要具有 `SUPER` 权限。如果 TiDB 提示您没有足够的权限,请参见[权限管理](https://docs.pingcap.com/tidb/stable/privilege-management)添加所需的权限。 + + ### 创建绑定 -你可以根据 SQL 或者历史执行计划为指定的 SQL 语句创建绑定。 +您可以根据 SQL 语句或历史执行计划为 SQL 语句创建绑定。 -#### 根据 SQL 创建绑定 +#### 根据 SQL 语句创建绑定 {{< copyable "sql" >}} @@ -27,7 +39,7 @@ summary: 介绍 TiDB 的执行计划管理 (SQL Plan Management) 功能。 CREATE [GLOBAL | SESSION] BINDING [FOR BindableStmt] USING BindableStmt; ``` -该语句可以在 GLOBAL 或者 SESSION 作用域内为 SQL 绑定执行计划。目前,可创建执行计划绑定的 SQL 语句类型 (BindableStmt) 包括:`SELECT`、`DELETE`、`UPDATE` 和带有 `SELECT` 子查询的 `INSERT`/`REPLACE`。使用示例如下: +此语句在 GLOBAL 或 SESSION 级别绑定 SQL 执行计划。目前,TiDB 支持的可绑定 SQL 语句(BindableStmt)包括 `SELECT`、`DELETE`、`UPDATE` 和带有 `SELECT` 子查询的 `INSERT` / `REPLACE`。以下是一个示例: ```sql CREATE GLOBAL BINDING USING SELECT /*+ use_index(orders, orders_book_id_idx) */ * FROM orders; @@ -36,35 +48,34 @@ CREATE GLOBAL BINDING FOR SELECT * FROM orders USING SELECT /*+ use_index(orders > **注意:** > -> 绑定的优先级高于手工添加的 Hint,即在有绑定的时候执行带有 Hint 的语句时,该语句中控制优化器行为的 Hint 不会生效,但是其他类别的 Hint 仍然能够生效。 +> 绑定的优先级高于手动添加的提示。因此,当您执行包含提示的语句而存在相应绑定时,控制优化器行为的提示不会生效。但是,其他类型的提示仍然有效。 -其中,有两类特定的语法由于语法冲突不能创建执行计划绑定,创建时会报语法错误,例如: +具体来说,由于语法冲突,以下两类语句无法绑定执行计划。在创建绑定时会报语法错误。请参见以下示例: ```sql --- 类型一:使用 `JOIN` 关键字但不通过 `USING` 关键字指定关联列的笛卡尔积 +-- 第一类:使用 `JOIN` 关键字且不使用 `USING` 关键字指定关联列获取笛卡尔积的语句。 CREATE GLOBAL BINDING for SELECT * FROM orders o1 JOIN orders o2 USING SELECT * FROM orders o1 JOIN orders o2; --- 类型二:包含了 `USING` 关键字的 `delete` 语句 +-- 第二类:包含 `USING` 关键字的 `DELETE` 语句。 CREATE GLOBAL BINDING for DELETE FROM users USING users JOIN orders ON users.id = orders.user_id USING DELETE FROM users USING users JOIN orders ON users.id = orders.user_id; ``` -可以通过等价的 SQL 改写绕过这个语法冲突的问题。例如,上述两个例子可以改写为: +您可以通过使用等效语句来绕过语法冲突。例如,您可以按以下方式重写上述语句: ```sql - --- 类型一的改写:去掉 `JOIN` 关键字,用逗号代替 +-- 第一类语句的重写:删除 `JOIN` 关键字,用逗号替代。 CREATE GLOBAL BINDING for SELECT * FROM orders o1, orders o2 USING SELECT * FROM orders o1, orders o2; --- 类型二的改写:去掉 `DELETE` 语句中的 `USING` 关键字 +-- 第二类语句的重写:从 `DELETE` 语句中删除 `USING` 关键字。 CREATE GLOBAL BINDING for DELETE users FROM users JOIN orders ON users.id = orders.user_id USING @@ -73,49 +84,49 @@ USING > **注意:** > -> 在对带 `SELECT` 子查询的 `INSERT`/`REPLACE` 语句创建执行计划绑定时,需要将想要绑定的优化器 Hints 指定在 `SELECT` 子查询中,而不是 `INSERT`/`REPLACE` 关键字后,不然优化器 Hints 不会生效。 +> 为带有 `SELECT` 子查询的 `INSERT` / `REPLACE` 语句创建执行计划绑定时,需要在 `SELECT` 子查询中指定要绑定的优化器提示,而不是在 `INSERT` / `REPLACE` 关键字后指定。否则,优化器提示不会按预期生效。 -例如: +以下是两个示例: ```sql --- Hint 能生效的用法 +-- 以下语句中的提示会生效。 CREATE GLOBAL BINDING for INSERT INTO orders SELECT * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR) USING INSERT INTO orders SELECT /*+ use_index(@sel_1 pre_orders, idx_created) */ * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR); --- Hint 不能生效的用法 +-- 以下语句中的提示不会生效。 CREATE GLOBAL BINDING for INSERT INTO orders SELECT * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR) USING INSERT /*+ use_index(@sel_1 pre_orders, idx_created) */ INTO orders SELECT * FROM pre_orders WHERE status = 'VALID' AND created <= (NOW() - INTERVAL 1 HOUR); ``` -如果在创建执行计划绑定时不指定作用域,隐式作用域 SESSION 会被使用。TiDB 优化器会将被绑定的 SQL 进行“标准化”处理,然后存储到系统表中。在处理 SQL 查询时,只要“标准化”后的 SQL 和系统表中某个被绑定的 SQL 语句一致,并且系统变量 [`tidb_use_plan_baselines`](/system-variables.md#tidb_use_plan_baselines-从-v40-版本开始引入) 的值为 `on`(其默认值为 `on`),即可使用相应的优化器 Hint。如果存在多个可匹配的执行计划,优化器会从中选择代价最小的一个进行绑定。 +如果在创建执行计划绑定时未指定作用域,默认作用域为 SESSION。TiDB 优化器会对绑定的 SQL 语句进行规范化处理,并将其存储在系统表中。在处理 SQL 查询时,如果规范化后的语句与系统表中的某个绑定 SQL 语句匹配,并且系统变量 `tidb_use_plan_baselines` 设置为 `on`(默认值为 `on`),TiDB 就会为该语句使用相应的优化器提示。如果有多个可匹配的执行计划,优化器会选择成本最低的一个进行绑定。 -`标准化`:把 SQL 中的常量变成变量参数,对空格和换行符等做标准化处理,并对查询引用到的表显式指定数据库。例如: +`规范化`是一个将 SQL 语句中的常量转换为变量参数,并显式指定查询中引用的表的数据库,同时对 SQL 语句中的空格和换行进行标准化处理的过程。请参见以下示例: ```sql SELECT * FROM users WHERE balance > 100 --- 以上语句标准化后如下: +-- 规范化后的语句如下: SELECT * FROM bookshop . users WHERE balance > ? ``` > **注意:** > -> 在进行标准化的时候,`IN` 表达式中的 `?` 会被标准化为 `...`。 +> 在规范化过程中,`IN` 谓词中的 `?` 被规范化为 `...`。 > > 例如: > > ```sql > SELECT * FROM books WHERE type IN ('Novel') > SELECT * FROM books WHERE type IN ('Novel','Life','Education') -> -- 以上语句标准化后如下: +> -- 规范化后的语句如下: > SELECT * FROM bookshop . books WHERE type IN ( ... ) > SELECT * FROM bookshop . books WHERE type IN ( ... ) > ``` > -> 不同长度的 `IN` 表达式被标准化后,会被识别为同一条语句,因此只需要创建一条绑定,对这些表达式同时生效。 +> 规范化后,不同长度的 `IN` 谓词被识别为相同的语句,因此您只需要创建一个适用于所有这些谓词的绑定。 > > 例如: > @@ -139,13 +150,13 @@ SELECT * FROM bookshop . users WHERE balance > ? > | 1 | > +--------------------------+ > ``` -> -> 在 v7.4.0 之前版本的 TiDB 集群中创建的绑定可能会包含 `IN (?)`,在升级到 v7.4.0 或更高版本后,这些绑定会被统一修改为 `IN (...)`。 -> +> +> 在 v7.4.0 之前版本的 TiDB 集群中创建的绑定可能包含 `IN (?)`。升级到 v7.4.0 或更高版本后,这些绑定将被修改为 `IN (...)`。 +> > 例如: > > ```sql -> -- 在 v7.3.0 集群上创建绑定 +> -- 在 v7.3.0 上创建绑定 > mysql> CREATE GLOBAL BINDING FOR SELECT * FROM t WHERE a IN (1) USING SELECT /*+ use_index(t, idx_a) */ * FROM t WHERE a IN (1); > mysql> SHOW GLOBAL BINDINGS; > +-----------------------------------------------+------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ @@ -153,8 +164,8 @@ SELECT * FROM bookshop . users WHERE balance > ? > +-----------------------------------------------+------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ > | select * from `test` . `t` where `a` in ( ? ) | SELECT /*+ use_index(`t` `idx_a`)*/ * FROM `test`.`t` WHERE `a` IN (1) | test | enabled | 2024-09-03 15:39:02.695 | 2024-09-03 15:39:02.695 | utf8mb4 | utf8mb4_general_ci | manual | 8b9c4e6ab8fad5ba29b034311dcbfc8a8ce57dde2e2d5d5b65313b90ebcdebf7 | | > +-----------------------------------------------+------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ -> -> -- 升级到 v7.4.0 或更高的版本后 +> +> -- 升级到 v7.4.0 或更高版本后 > mysql> SHOW GLOBAL BINDINGS; > +-------------------------------------------------+------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ > | Original_sql | Bind_sql | Default_db | Status | Create_time | Update_time | Charset | Collation | Source | Sql_digest | Plan_digest | @@ -163,694 +174,50 @@ SELECT * FROM bookshop . users WHERE balance > ? > +-------------------------------------------------+------------------------------------------------------------------------+------------+---------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ > ``` -值得注意的是,如果一条 SQL 语句在 GLOBAL 和 SESSION 作用域内都有与之绑定的执行计划,因为优化器在遇到 SESSION 绑定时会忽略 GLOBAL 绑定的执行计划,该语句在 SESSION 作用域内绑定的执行计划会屏蔽掉语句在 GLOBAL 作用域内绑定的执行计划。 +当一个 SQL 语句在 GLOBAL 和 SESSION 作用域都有绑定的执行计划时,由于优化器在遇到 SESSION 绑定时会忽略 GLOBAL 作用域中的绑定执行计划,因此该语句在 SESSION 作用域中的绑定执行计划会屏蔽 GLOBAL 作用域中的执行计划。 例如: ```sql --- 创建一个 global binding,指定其使用 sort merge join +-- 创建一个 GLOBAL 绑定,并在此绑定中指定使用 `sort merge join`。 CREATE GLOBAL BINDING for SELECT * FROM t1, t2 WHERE t1.id = t2.id USING SELECT /*+ merge_join(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; --- 从该 SQL 的执行计划中可以看到其使用了 global binding 中指定的 sort merge join +-- 此 SQL 语句的执行计划使用 GLOBAL 绑定中指定的 `sort merge join`。 explain SELECT * FROM t1, t2 WHERE t1.id = t2.id; --- 创建另一个 session binding,指定其使用 hash join +-- 创建另一个 SESSION 绑定,并在此绑定中指定使用 `hash join`。 CREATE BINDING for SELECT * FROM t1, t2 WHERE t1.id = t2.id USING SELECT /*+ hash_join(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; --- 从该 SQL 的执行计划中可以看到其使用了 session binding 中指定的 hash join,而不是 global binding 中指定的 sort merge join +-- 在此语句的执行计划中,使用的是 SESSION 绑定中指定的 `hash join`,而不是 GLOBAL 绑定中指定的 `sort merge join`。 explain SELECT * FROM t1, t2 WHERE t1.id = t2.id; ``` -第一个 `SELECT` 语句在执行时优化器会通过 GLOBAL 作用域内的绑定为其加上 `sm_join(t1, t2)` hint,`explain` 出的执行计划中最上层的节点为 MergeJoin。而第二个 `SELECT` 语句在执行时优化器则会忽视 GLOBAL 作用域内的绑定而使用 SESSION 作用域内的绑定为该语句加上 `hash_join(t1, t2)` hint,`explain` 出的执行计划中最上层的节点为 HashJoin。 - -每个标准化的 SQL 只能同时有一个通过 `CREATE BINDING` 创建的绑定。对相同的标准化 SQL 创建多个绑定时,会保留最后一个创建的绑定,之前的所有绑定(创建的和演进出来的)都会被删除。但 session 绑定和 global 绑定仍然允许共存,不受这个逻辑影响。 - -另外,创建绑定时,TiDB 要求 session 处于某个数据库上下文中,也就是执行过 `use ${database}` 或者客户端连接时指定了数据库。 - -需要注意的是原始 SQL 和绑定 SQL 在参数化以及去掉 Hint 后文本必须相同,否则创建会失败,例如: - -{{< copyable "sql" >}} - -```sql -CREATE BINDING FOR SELECT * FROM t WHERE a > 1 USING SELECT * FROM t use index(idx) WHERE a > 2; -``` - -可以创建成功,因为原始 SQL 和绑定 SQL 在参数化以及去掉 Hint 后文本都是 `SELECT * FROM test . t WHERE a > ?`,而 - -{{< copyable "sql" >}} - -```sql -CREATE BINDING FOR SELECT * FROM t WHERE a > 1 USING SELECT * FROM t use index(idx) WHERE b > 2; -``` - -则不可以创建成功,因为原始 SQL 在经过处理后是 `SELECT * FROM test . t WHERE a > ?`,而绑定 SQL 在经过处理后是 `SELECT * FROM test . t WHERE b > ?`。 - -> **注意:** -> -> 对于 `PREPARE`/`EXECUTE` 语句组,或者用二进制协议执行的查询,创建执行计划绑定的对象应当是查询语句本身,而不是 `PREPARE`/`EXECUTE` 语句。 - -#### 根据历史执行计划创建绑定 - -如需将 SQL 语句的执行计划固定为之前使用过的执行计划,可以使用 `plan_digest` 为该 SQL 语句绑定一个历史的执行计划。相比于使用 SQL 创建绑定的方式,此方式更加简便。 - -以下为根据历史执行计划创建绑定的注意事项: - -- 该功能是根据历史的执行计划生成 hint 而实现的绑定,历史的执行计划来源是 [Statement Summary Tables](/statement-summary-tables.md),因此在使用此功能之前需开启系统变量 [`tidb_enable_stmt_summary`](/system-variables.md#tidb_enable_stmt_summary-从-v304-版本开始引入)。 -- 对于包含子查询的查询、访问 TiFlash 的查询、3 张表或更多表进行 Join 的查询,自动生成的 hint 不够完备,可能导致无法完全固定住计划,对于这类情况在创建时会产生告警。 -- 原执行计划对应 SQL 语句中的 hint 也会被应用在创建的绑定中,如执行 `SELECT /*+ max_execution_time(1000) */ * FROM t` 后,使用其 `plan_digest` 创建的绑定中会带上 `max_execution_time(1000)`。 - -使用方式: - -```sql -CREATE [GLOBAL | SESSION] BINDING FROM HISTORY USING PLAN DIGEST 'plan_digest'; -``` - -该语句使用 `plan_digest` 为 SQL 语句绑定执行计划,在不指定作用域时默认作用域为 SESSION。所创建绑定的适用 SQL、优先级、作用域、生效条件等与[根据 SQL 创建绑定](#根据-sql-创建绑定)相同。 - -使用此绑定方式时,你需要先从 `statements_summary` 中找到需要绑定的执行计划对应的 `plan_digest`,再通过 `plan_digest` 创建绑定。具体步骤如下: - -1. 从 `Statement Summary Tables` 的记录中查找执行计划对应的 `plan_digest`。 - - 例如: - - ```sql - CREATE TABLE t(id INT PRIMARY KEY , a INT, KEY idx_a(a)); - SELECT /*+ IGNORE_INDEX(t, idx_a) */ * FROM t WHERE a = 1; - SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY WHERE QUERY_SAMPLE_TEXT = 'SELECT /*+ IGNORE_INDEX(t, idx_a) */ * FROM t WHERE a = 1'\G - ``` - - 以下为 `statements_summary` 部分查询结果: - - ``` - SUMMARY_BEGIN_TIME: 2022-12-01 19:00:00 - ........... - DIGEST_TEXT: select * from `t` where `a` = ? - ........... - PLAN_DIGEST: 4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb - PLAN: id task estRows operator info actRows execution info memory disk - TableReader_7 root 10 data:Selection_6 0 time:4.05ms, loops:1, cop_task: {num: 1, max: 598.6µs, proc_keys: 0, rpc_num: 2, rpc_time: 609.8µs, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15} 176 Bytes N/A - └─Selection_6 cop[tikv] 10 eq(test.t.a, 1) 0 tikv_task:{time:560.8µs, loops:0} N/A N/A - └─TableFullScan_5 cop[tikv] 10000 table:t, keep order:false, stats:pseudo 0 tikv_task:{time:560.8µs, loops:0} N/A N/A - BINARY_PLAN: 6QOYCuQDCg1UYWJsZVJlYWRlcl83Ev8BCgtTZWxlY3Rpb25fNhKOAQoPBSJQRnVsbFNjYW5fNSEBAAAAOA0/QSkAAQHwW4jDQDgCQAJKCwoJCgR0ZXN0EgF0Uh5rZWVwIG9yZGVyOmZhbHNlLCBzdGF0czpwc2V1ZG9qInRpa3ZfdGFzazp7dGltZTo1NjAuOMK1cywgbG9vcHM6MH1w////CQMEAXgJCBD///8BIQFzCDhVQw19BAAkBX0QUg9lcSgBfCAudC5hLCAxKWrmYQAYHOi0gc6hBB1hJAFAAVIQZGF0YTo9GgRaFAW4HDQuMDVtcywgCbYcMWKEAWNvcF8F2agge251bTogMSwgbWF4OiA1OTguNsK1cywgcHJvY19rZXlzOiAwLCBycGNfBSkAMgkMBVcQIDYwOS4pEPBDY29wcl9jYWNoZV9oaXRfcmF0aW86IDAuMDAsIGRpc3RzcWxfY29uY3VycmVuY3k6IDE1fXCwAXj///////////8BGAE= - ``` - - 可以看到执行计划对应的 `plan_digest` 为 `4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb`。 - -2. 使用 `plan_digest` 创建绑定。 - - ```sql - CREATE BINDING FROM HISTORY USING PLAN DIGEST '4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb'; - ``` - -创建完毕后可以[查看绑定](#查看绑定),验证绑定是否生效。 - -```sql -SHOW BINDINGS\G -``` - -``` -*************************** 1. row *************************** -Original_sql: select * from `test` . `t` where `a` = ? - Bind_sql: SELECT /*+ use_index(@`sel_1` `test`.`t` ) ignore_index(`t` `idx_a`)*/ * FROM `test`.`t` WHERE `a` = 1 - ........... - Sql_digest: 6909a1bbce5f64ade0a532d7058dd77b6ad5d5068aee22a531304280de48349f - Plan_digest: -1 row in set (0.01 sec) - -ERROR: -No query specified -``` - -```sql -SELECT * FROM t WHERE a = 1; -SELECT @@LAST_PLAN_FROM_BINDING; -``` - -``` -+--------------------------+ -| @@LAST_PLAN_FROM_BINDING | -+--------------------------+ -| 1 | -+--------------------------+ -1 row in set (0.00 sec) -``` - -### 删除绑定 - -你可以根据 SQL 语句或者 `sql_digest` 删除绑定。 - -#### 根据 SQL 语句删除绑定 - -{{< copyable "sql" >}} - -```sql -DROP [GLOBAL | SESSION] BINDING FOR BindableStmt; -``` - -该语句可以在 GLOBAL 或者 SESSION 作用域内删除指定的执行计划绑定,在不指定作用域时默认作用域为 SESSION。 - -一般来说,SESSION 作用域的绑定主要用于测试或在某些特殊情况下使用。若需要集群中所有的 TiDB 进程都生效,则需要使用 GLOBAL 作用域的绑定。SESSION 作用域对 GLOBAL 作用域绑定的屏蔽效果会持续到该 SESSION 结束。 - -承接上面关于 SESSION 绑定屏蔽 GLOBAL 绑定的例子,继续执行: - -```sql --- 删除 session 中创建的 binding -DROP session binding for SELECT * FROM t1, t2 WHERE t1.id = t2.id; - --- 重新查看该 SQL 的执行计划 -explain SELECT * FROM t1,t2 WHERE t1.id = t2.id; -``` - -在这里 SESSION 作用域内被删除掉的绑定会屏蔽 GLOBAL 作用域内相应的绑定,优化器不会为 `SELECT` 语句添加 `sm_join(t1, t2)` hint,`explain` 给出的执行计划中最上层节点并不被 hint 固定为 MergeJoin,而是由优化器经过代价估算后自主进行选择。 - -#### 根据 `sql_digest` 删除绑定 - -除了可以根据 SQL 语句删除对应的绑定以外,也可以根据 `sql_digest` 删除绑定: - -```sql -DROP [GLOBAL | SESSION] BINDING FOR SQL DIGEST 'sql_digest'; -``` - -该语句用于在 GLOBAL 或者 SESSION 作用域内删除 `sql_digest` 对应的的执行计划绑定,在不指定作用域时默认作用域为 SESSION。你可以通过[查看绑定](#查看绑定)语句获取 `sql_digest`。 - -> **注意:** -> -> 执行 `DROP GLOBAL BINDING` 会删除当前 tidb-server 实例缓存中的绑定,并将系统表中对应行的状态修改为 'deleted'。该语句不会直接删除系统表中的记录,因为其他 tidb-server 实例需要读取系统表中的 'deleted' 状态来删除其缓存中对应的绑定。对于这些系统表中状态为 'deleted' 的记录,后台线程每隔 100 个 `bind-info-lease`(默认值为 `3s`,合计 `300s`)会触发一次对 `update_time` 在 10 个 `bind-info-lease` 以前的绑定(确保所有 tidb-server 实例已经读取过这个 'deleted' 状态并更新完缓存)的回收清除操作。 - -### 变更绑定状态 - -#### 根据 SQL 语句变更绑定状态 - -{{< copyable "sql" >}} - -```sql -SET BINDING [ENABLED | DISABLED] FOR BindableStmt; -``` - -该语句可以在 GLOBAL 作用域内变更指定执行计划的绑定状态,默认作用域为 GLOBAL,该作用域不可更改。 - -使用时,只能将 `Disabled` 的绑定改为 `Enabled` 状态,或将 `Enabled` 的绑定改为 `Disabled` 状态。如果没有可以改变状态的绑定,则会输出一条内容为 `There are no bindings can be set the status. Please check the SQL text` 的警告。需要注意的是,当绑定被设置成 `Disabled` 状态时,查询语句不会使用该绑定。 - -#### 根据 `sql_digest` 变更绑定状态 - -除了可以根据 SQL 语句变更对应的绑定状态以外,也可以根据 `sql_digest` 变更绑定状态: - -```sql -SET BINDING [ENABLED | DISABLED] FOR SQL DIGEST 'sql_digest'; -``` - -使用 `sql_digest` 所能变更的绑定状态和生效情况与[根据 SQL 语句变更绑定状态](#根据-sql-语句变更绑定状态)相同。如果没有可以改变状态的绑定,则会输出一条内容为 `can't find any binding for 'sql_digest'` 的警告。 - -### 查看绑定 - -{{< copyable "sql" >}} - -```sql -SHOW [GLOBAL | SESSION] BINDINGS [ShowLikeOrWhere]; -``` - -该语句会按照绑定更新时间由新到旧的顺序输出 GLOBAL 或者 SESSION 作用域内的执行计划绑定,在不指定作用域时默认作用域为 SESSION。目前 `SHOW BINDINGS` 会输出 11 列,具体如下: - -| 列名 | 说明 | -| -------- | ------------- | -| original_sql | 参数化后的原始 SQL | -| bind_sql | 带 Hint 的绑定 SQL | -| default_db | 默认数据库名 | -| status | 状态,包括 enabled(可用,从 v6.0 开始取代之前版本的 using 状态)、disabled(不可用)、deleted(已删除)、 invalid(无效)、rejected(演进时被拒绝)和 pending verify(等待演进验证) | -| create_time | 创建时间 | -| update_time | 更新时间 | -| charset | 字符集 | -| collation | 排序规则 | -| source | 创建方式,包括 manual(根据 SQL 创建绑定生成)、history(根据历史执行计划创建绑定生成)、capture(由 TiDB 自动创建生成)和 evolve (由 TiDB 自动演进生成) | -| sql_digest | 归一化后的 SQL 的 digest | -| plan_digest | 执行计划的 digest | - -### 排查绑定 - -绑定的排查通常有两种方式: - -- 使用系统变量 [`last_plan_from_binding`](/system-variables.md#last_plan_from_binding-从-v40-版本开始引入) 显示上一条执行语句是否采用 binding 的执行计划。 - - {{< copyable "sql" >}} - - ```sql - -- 创建一个 global binding - - CREATE GLOBAL BINDING for - SELECT * FROM t - USING - SELECT /*+ USE_INDEX(t, idx_a) */ * FROM t; - - SELECT * FROM t; - SELECT @@[SESSION.]last_plan_from_binding; - ``` - - ```sql - +--------------------------+ - | @@last_plan_from_binding | - +--------------------------+ - | 1 | - +--------------------------+ - 1 row in set (0.00 sec) - ``` - -- 使用 `explain format = 'verbose'` 语句查看 SQL 语句的查询计划。如果 SQL 语句使用了 binding,可以接着执行 `show warnings` 了解该 SQL 语句使用了哪一条 binding。 - - ```sql - -- 创建一个 global binding - - CREATE GLOBAL BINDING for - SELECT * FROM t - USING - SELECT /*+ USE_INDEX(t, idx_a) */ * FROM t; - - -- 使用 explain format = 'verbose' 语句查看 SQL 的执行计划 - - explain format = 'verbose' SELECT * FROM t; - - -- 通过执行 `show warnings` 了解该 SQL 语句使用了哪一条 binding - - show warnings; - ``` - - ```sql - +-------+------+--------------------------------------------------------------------------+ - | Level | Code | Message | - +-------+------+--------------------------------------------------------------------------+ - | Note | 1105 | Using the bindSQL: SELECT /*+ USE_INDEX(`t` `idx_a`)*/ * FROM `test`.`t` | - +-------+------+--------------------------------------------------------------------------+ - 1 row in set (0.01 sec) - - ``` - -### 对绑定进行缓存 - -每个 TiDB 实例都有一个 LRU (Least Recently Used) Cache 对绑定进行缓存,缓存的容量由系统变量 [`tidb_mem_quota_binding_cache`](/system-variables.md#tidb_mem_quota_binding_cache-从-v600-版本开始引入) 进行控制。缓存会影响绑定的使用和查看,因此你只能使用和查看存在于缓存中的绑定。 - -如需查看绑定的使用情况,可以执行 `SHOW binding_cache status` 语句。该语句无法指定作用域,默认作用域为 GLOBAL。该语句可查看缓存中可用绑定的数量、系统中所有可用绑定的数量、缓存中所有绑定的内存使用量及缓存的内存容量。 - -{{< copyable "sql" >}} - -```sql - -SHOW binding_cache status; -``` - -```sql -+-------------------+-------------------+--------------+--------------+ -| bindings_in_cache | bindings_in_table | memory_usage | memory_quota | -+-------------------+-------------------+--------------+--------------+ -| 1 | 1 | 159 Bytes | 64 MB | -+-------------------+-------------------+--------------+--------------+ -1 row in set (0.00 sec) -``` - -## 利用 Statement Summary 表获取需要绑定的查询 - -[Statement Summary](/statement-summary-tables.md) 的表中存放了近期的 SQL 相关的执行信息,如延迟、执行次数、对应计划等。你可以通过查询 Statement Summary 表得到符合条件查询的 `plan_digest`,然后[根据历史执行计划创建绑定](/sql-plan-management.md#根据历史执行计划创建绑定)。 - -以下示例查找过去两周执行次数超过 10 次、执行计划不稳定且未被绑定的 `SELECT` 语句,并按照执行次数排序,将执行次数前 100 的查询绑定到对应的查询延迟最低的计划上。 - -```sql -WITH stmts AS ( -- Gets all information - SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY - UNION ALL - SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY -), -best_plans AS ( - SELECT plan_digest, `digest`, avg_latency, - CONCAT('create global binding from history using plan digest "', plan_digest, '"') as binding_stmt - FROM stmts t1 - WHERE avg_latency = (SELECT min(avg_latency) FROM stmts t2 -- The plan with the lowest query latency - WHERE t2.`digest` = t1.`digest`) -) - -SELECT any_value(digest_text) as query, - SUM(exec_count) as exec_count, - plan_hint, binding_stmt -FROM stmts, best_plans -WHERE stmts.`digest` = best_plans.`digest` - AND summary_begin_time > DATE_SUB(NOW(), interval 14 day) -- Executed in the past 2 weeks - AND stmt_type = 'Select' -- Only consider select statements - AND schema_name NOT IN ('INFORMATION_SCHEMA', 'mysql') -- Not an internal query - AND plan_in_binding = 0 -- No binding yet -GROUP BY stmts.`digest` - HAVING COUNT(DISTINCT(stmts.plan_digest)) > 1 -- This query is unstable. It has more than 1 plan. - AND SUM(exec_count) > 10 -- High-frequency, and has been executed more than 10 times. -ORDER BY SUM(exec_count) DESC LIMIT 100; -- Top 100 high-frequency queries. -``` - -通过一些过滤条件得到满足条件的查询,然后直接运行 `binding_stmt` 列对应的语句即可创建相应的绑定。 - -``` -+---------------------------------------------+------------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| query | exec_count | plan_hint | binding_stmt | -+---------------------------------------------+------------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| select * from `t` where `a` = ? and `b` = ? | 401 | use_index(@`sel_1` `test`.`t` `a`), no_order_index(@`sel_1` `test`.`t` `a`) | create global binding from history using plan digest "0d6e97fb1191bbd08dddefa7bd007ec0c422b1416b152662768f43e64a9958a6" | -| select * from `t` where `b` = ? and `c` = ? | 104 | use_index(@`sel_1` `test`.`t` `b`), no_order_index(@`sel_1` `test`.`t` `b`) | create global binding from history using plan digest "80c2aa0aa7e6d3205755823aa8c6165092c8521fb74c06a9204b8d35fc037dd9" | -+---------------------------------------------+------------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -``` - -## 跨数据库绑定执行计划 (Cross-DB Binding) - -在创建绑定的 SQL 语句中,TiDB 支持使用通配符 `*` 表示数据库,实现跨数据库绑定。该功能自 v7.6.0 开始引入。要使用跨数据库绑定,首先需要开启 [`tidb_opt_enable_fuzzy_binding`](/system-variables.md#tidb_opt_enable_fuzzy_binding-从-v760-版本开始引入) 系统变量。 - -当数据按数据库 (schema/db) 分类存储,同时各数据库具有相同的对象定义并且运行相似的业务逻辑时,跨数据库执行计划绑定能显著简化执行计划的固定过程。以下是一些常见的使用场景: - -* 用户在 TiDB 上运行 SaaS 或 PaaS 类服务,每个租户的数据存储于独立的数据库中,以便数据维护和管理。 -* 用户在单一实例中进行分库操作,并在迁移到 TiDB 后保留了原有的数据库结构,即将原实例中的数据按数据库分类存储。 - -在这些场景中,跨数据库绑定能有效缓解由于用户数据和负载的不均衡及其快速变化所引发的 SQL 性能问题。SaaS 服务商可以通过跨数据库绑定,固定大数据量用户业务已验证的执行计划,从而避免因小数据量用户业务快速增长引起的潜在性能问题。 - -使用跨数据库绑定,只需要在创建绑定的 SQL 语句中将数据库名用 `*` 表示,例如: - -```sql -CREATE GLOBAL BINDING USING SELECT /*+ use_index(t, idx_a) */ * FROM t; -- 创建 GLOBAL 作用域的普通绑定 -CREATE GLOBAL BINDING USING SELECT /*+ use_index(t, idx_a) */ * FROM *.t; -- 创建 GLOBAL 作用域的跨数据库绑定 -SHOW GLOBAL BINDINGS; -``` - -输出结果示例如下: - -```sql -+----------------------------+---------------------------------------------------+------------+---------+-------------------------+-------------------------+--------------+-----------------+--------+------------------------------------------------------------------+-------------+ -| Original_sql | Bind_sql | Default_db | Status | Create_time | Update_time | Charset | Collation | Source | Sql_digest | Plan_digest | -+----------------------------+---------------------------------------------------+------------+---------+-------------------------+-------------------------+--------------+-----------------+--------+------------------------------------------------------------------+-------------+ -| select * from `test` . `t` | SELECT /*+ use_index(`t` `idx_a`)*/ * FROM `test`.`t` | test | enabled | 2023-12-29 14:19:01.332 | 2023-12-29 14:19:01.332 | utf8 | utf8_general_ci | manual | 8b193b00413fdb910d39073e0d494c96ebf24d1e30b131ecdd553883d0e29b42 | | -| select * from `*` . `t` | SELECT /*+ use_index(`t` `idx_a`)*/ * FROM `*`.`t` | | enabled | 2023-12-29 14:19:02.232 | 2023-12-29 14:19:02.232 | utf8 | utf8_general_ci | manual | 8b193b00413fdb910d39073e0d494c96ebf24d1e30b131ecdd553883d0e29b42 | | -+----------------------------+---------------------------------------------------+------------+---------+-------------------------+-------------------------+--------------+-----------------+--------+------------------------------------------------------------------+-------------+ -``` - -在 `SHOW GLOBAL BINDINGS` 的输出结果中,跨数据库绑定的 `Default_db` 为空,且 `Original_sql` 和 `Bind_sql` 字段中的数据库名通过 `*` 表示。这条绑定会对所有 `select * from t` 查询生效,而不限于特定数据库。 - -对于相同的查询,跨数据绑定与普通绑定可以同时存在,TiDB 匹配的优先级从高到低依次为:SESSION 级别的普通绑定 > SESSION 级别的跨数据库绑定 > GLOBAL 级别的普通绑定 > GLOBAL 级别的跨数据库绑定。 - -除了创建绑定的 SQL 语句不同,跨数据库绑定的删除和状态变更语句与普通绑定相同。下面是一个详细的使用示例。 - -1. 创建数据库 `db1` 和 `db2`,并在每个数据库中创建两张表: - - ```sql - CREATE DATABASE db1; - CREATE TABLE db1.t1 (a INT, KEY(a)); - CREATE TABLE db1.t2 (a INT, KEY(a)); - CREATE DATABASE db2; - CREATE TABLE db2.t1 (a INT, KEY(a)); - CREATE TABLE db2.t2 (a INT, KEY(a)); - ``` - -2. 开启跨数据库绑定功能: - - ```sql - SET tidb_opt_enable_fuzzy_binding=1; - ``` - -3. 创建跨数据库绑定: +当第一个 `SELECT` 语句被执行时,优化器通过 GLOBAL 作用域中的绑定为语句添加 `sm_join(t1, t2)` 提示。`explain` 结果中的执行计划顶部节点是 MergeJoin。当第二个 `SELECT` 语句被执行时,优化器使用 SESSION 作用域中的绑定而不是 GLOBAL 作用域中的绑定,并为语句添加 `hash_join(t1, t2)` 提示。`explain` 结果中的执行计划顶部节点是 HashJoin。 - ```sql - CREATE GLOBAL BINDING USING SELECT /*+ use_index(t1, idx_a), use_index(t2, idx_a) */ * FROM *.t1, *.t2; - ``` +每个规范化的 SQL 语句在同一时间只能有一个使用 `CREATE BINDING` 创建的绑定。当为同一个规范化的 SQL 语句创建多个绑定时,保留最后创建的绑定,所有之前的绑定(创建的和演进的)都被标记为已删除。但是会话绑定和全局绑定可以共存,不受此逻辑影响。 -4. 执行查询并查看是否使用了绑定: +此外,在创建绑定时,TiDB 要求会话处于数据库上下文中,这意味着在客户端连接时指定了数据库或执行了 `use ${database}`。 - ```sql - SELECT * FROM db1.t1, db1.t2; - SELECT @@LAST_PLAN_FROM_BINDING; - +--------------------------+ - | @@LAST_PLAN_FROM_BINDING | - +--------------------------+ - | 1 | - +--------------------------+ - - SELECT * FROM db2.t1, db2.t2; - SELECT @@LAST_PLAN_FROM_BINDING; - +--------------------------+ - | @@LAST_PLAN_FROM_BINDING | - +--------------------------+ - | 1 | - +--------------------------+ - - SELECT * FROM db1.t1, db2.t2; - SELECT @@LAST_PLAN_FROM_BINDING; - +--------------------------+ - | @@LAST_PLAN_FROM_BINDING | - +--------------------------+ - | 1 | - +--------------------------+ - - USE db1; - SELECT * FROM t1, db2.t2; - SELECT @@LAST_PLAN_FROM_BINDING; - +--------------------------+ - | @@LAST_PLAN_FROM_BINDING | - +--------------------------+ - | 1 | - +--------------------------+ - ``` +原始 SQL 语句和绑定语句在规范化和移除提示后必须具有相同的文本,否则绑定将失败。请参见以下示例: -5. 查看绑定: +- 此绑定可以成功创建,因为参数化和移除提示后的文本相同:`SELECT * FROM test . t WHERE a > ?` ```sql - SHOW GLOBAL BINDINGS; - +----------------------------------------------+------------------------------------------------------------------------------------------+------------+-----------------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ - | Original_sql | Bind_sql | Default_db | Status | Create_time | Update_time | Charset | Collation | Source | Sql_digest | Plan_digest | - +----------------------------------------------+------------------------------------------------------------------------------------------+------------+-----------------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ - | select * from ( `*` . `t1` ) join `*` . `t2` | SELECT /*+ use_index(`t1` `idx_a`) use_index(`t2` `idx_a`)*/ * FROM (`*` . `t1`) JOIN `*` . `t2` | | enabled | 2023-12-29 14:22:28.144 | 2023-12-29 14:22:28.144 | utf8 | utf8_general_ci | manual | ea8720583e80644b58877663eafb3579700e5f918a748be222c5b741a696daf4 | | - +----------------------------------------------+------------------------------------------------------------------------------------------+------------+-----------------+-------------------------+-------------------------+---------+--------------------+--------+------------------------------------------------------------------+-------------+ + CREATE BINDING FOR SELECT * FROM t WHERE a > 1 USING SELECT * FROM t use index (idx) WHERE a > 2 ``` -6. 删除绑定: +- 此绑定将失败,因为原始 SQL 语句处理为 `SELECT * FROM test . t WHERE a > ?`,而绑定 SQL 语句处理为 `SELECT * FROM test . t WHERE b > ?`。 ```sql - DROP GLOBAL BINDING FOR SQL DIGEST 'ea8720583e80644b58877663eafb3579700e5f918a748be222c5b741a696daf4'; - SHOW GLOBAL BINDINGS; - Empty set (0.00 sec) + CREATE BINDING FOR SELECT * FROM t WHERE a > 1 USING SELECT * FROM t use index(idx) WHERE b > 2 ``` -## 自动捕获绑定 (Baseline Capturing) - -自动绑定会对符合捕获条件的查询进行捕获,为符合条件的查询生成相应的绑定。通常用于[升级时的计划回退防护](#升级时的计划回退防护)。 - -Plan Baseline 是一组被允许用于 SQL 语句优化器的可接受计划。在典型的应用场景中,TiDB 仅在验证计划性能良好后才将其添加到 Baseline 中。这些计划包含优化器重新生成执行计划所需的所有信息(例如,SQL 计划标识符、提示集、绑定值、优化器环境)。 - -### 使用方式 - -通过将 `tidb_capture_plan_baselines` 的值设置为 `on`(其默认值为 `off`)可以打开自动捕获绑定功能。 - -> **注意:** -> -> 自动绑定功能依赖于 [Statement Summary](/statement-summary-tables.md),因此在使用自动绑定之前需打开 Statement Summary 开关。 - -开启自动绑定功能后,每隔 `bind-info-lease`(默认值为 `3s`)会遍历一次 Statement Summary 中的历史 SQL 语句,并为至少出现两次的 SQL 语句自动捕获绑定。绑定的执行计划为 Statement Summary 中记录执行这条语句时使用的执行计划。 - -对于以下几种 SQL 语句,TiDB 不会自动捕获绑定: - -- EXPLAIN 和 EXPLAIN ANALYZE 语句; -- TiDB 内部执行的 SQL 语句,比如统计信息自动加载使用的 SELECT 查询; -- 存在 `Enabled` 或 `Disabled` 状态绑定的语句; -- 满足捕获绑定黑名单过滤条件的语句。 - -> **注意:** -> -> 当前,绑定通过生成一组 Hints 来固定查询语句生成的执行计划,从而确保执行计划不发生变化。对于大多数 OLTP 查询,TiDB 能够保证计划前后一致,如使用相同的索引、相同的 Join 方式(如 HashJoin、IndexJoin)等。但是,受限于当前 Hints 的完善程度,对于一些较为复杂的查询,如两个表以上的 Join 和复杂的 OLAP、MPP 类查询,TiDB 无法保证计划在绑定前后完全一致。 - -对于 `PREPARE`/`EXECUTE` 语句组,或通过二进制协议执行的查询,TiDB 会为真正的查询(而不是 `PREPARE`/`EXECUTE` 语句)自动捕获绑定。 - > **注意:** > -> 由于 TiDB 存在一些内嵌 SQL 保证一些功能的正确性,所以自动捕获绑定时会默认屏蔽内嵌 SQL。 - -### 过滤捕获绑定 - -使用本功能,你可以设置黑名单,将满足黑名单规则的查询排除在捕获范围之外。黑名单支持的过滤维度包括表名、频率和用户名。 - -#### 使用方式 - -将过滤规则插入到系统表 `mysql.capture_plan_baselines_blacklist` 中,该过滤规则即刻起会在整个集群范围内生效。 - -{{< copyable "sql" >}} - -```sql --- 按照表名进行过滤 -INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('table', 'test.t'); - --- 通过通配符来实现按照数据库名和表名进行过滤 -INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('table', 'test.table_*'); -INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('table', 'db_*.table_*'); - --- 按照执行频率进行过滤 -INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('frequency', '2'); - --- 按照用户名进行过滤 -INSERT INTO mysql.capture_plan_baselines_blacklist(filter_type, filter_value) VALUES('user', 'user1'); -``` - -| **维度名称** | **说明** | 注意事项 | -| :----------- | :----------------------------------------------------------- | ------------------------------------------------------------ | -| table | 按照表名进行过滤,每个过滤规则均采用 `db.table` 形式,支持通配符。详细规则可以参考[直接使用表名](/table-filter.md#直接使用表名)和[使用通配符](/table-filter.md#使用通配符)。 | 字母大小写不敏感,如果包含非法内容,日志会输出 `[sql-bind] failed to load mysql.capture_plan_baselines_blacklist` 警告。 | -| frequency | 按照频率进行过滤,默认捕获执行超过一次的语句。可以设置较大值来捕获执行频繁的语句。 | 插入的值小于 1 会被认为是非法值,同时,日志会输出 `[sql-bind] frequency threshold is less than 1, ignore it` 警告。如果插入了多条频率过滤规则,频率最大的值会被用作过滤条件。 | -| user | 按照用户名进行过滤,黑名单用户名执行的语句不会被捕获。 | 如果多个用户执行同一条语句,只有当他们的用户名都在黑名单的时候,该语句才不会被捕获。 | - -> **注意:** -> -> - 修改黑名单需要数据库的 super privilege 权限。 -> -> - 如果黑名单包含了非法的过滤内容时,TiDB 会在日志中输出 `[sql-bind] unknown capture filter type, ignore it` 进行提示。 - -### 升级时的计划回退防护 - -当需要升级 TiDB 集群时,你可以利用自动捕获绑定对潜在的计划回退风险进行一定程度的防护,具体流程为: - -1. 升级前打开自动捕获。 - - > **注意:** - > - > 经测试,长期打开自动捕获对集群负载的性能影响很小。尽量长期打开自动捕获,以确保重要的查询(出现过两次及以上)都能被捕获到。 - -2. 进行 TiDB 集群的升级。在升级完成后,这些通过捕获的绑定会发挥作用,确保在升级后,查询的计划不会改变。 -3. 升级完成后,根据情况手动删除绑定。 - - - 通过[`SHOW GLOBAL BINDINGS`](#查看绑定)语句检查绑定来源: - - 根据输出中的 `Source` 字段对绑定的来源进行区分,确认是通过捕获 (`capture`) 生成还是通过手动创建 (`manual`) 生成。 - - - 确定 `capture` 的绑定是否需要保留: - - ``` - -- 查看绑定生效时的计划 - SET @@SESSION.TIDB_USE_PLAN_BASELINES = true; - EXPLAIN FORMAT='VERBOSE' SELECT * FROM t1 WHERE ...; - - -- 查看绑定不生效时的计划 - SET @@SESSION.TIDB_USE_PLAN_BASELINES = false; - EXPLAIN FORMAT='VERBOSE' SELECT * FROM t1 WHERE ...; - ``` - - - 如果屏蔽绑定前后,查询得到的计划一致,则可以安全删除此绑定。 - - - 如果计划不一样,则可能需要对此计划变化的原因进行排查,如检查统计信息等操作。在这种情况下需要保留此绑定,确保计划不发生变化。 - -## 自动演进绑定 (Baseline Evolution) - -自动演进绑定,在 TiDB 4.0 版本引入,是执行计划管理的重要功能之一。 - -由于某些数据变更后,原先绑定的执行计划可能是一个不优的计划。为了解决该问题,引入自动演进绑定功能来自动优化已经绑定的执行计划。 - -另外自动演进绑定还可以一定程度上避免统计信息改动后,对执行计划带来的抖动。 - -### 使用方式 - -通过以下语句可以开启自动演进绑定功能: - -{{< copyable "sql" >}} - -```sql -SET GLOBAL tidb_evolve_plan_baselines = ON; -``` - -`tidb_evolve_plan_baselines` 的默认值为 `off`。 - -> **警告:** -> -> - 自动演进功能目前为实验特性,存在未知风险,不建议在生产环境中使用。 -> -> - 此变量开关已强制关闭,直到自动演进成为正式功能 GA (Generally Available)。如果你尝试打开开关,会产生报错。如果你已经在生产环境中使用了此功能,请尽快将它禁用。如发现 binding 状态不如预期,请从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。 - -在打开自动演进功能后,如果优化器选出的最优执行计划不在之前绑定的执行计划之中,会将其记录为待验证的执行计划。每隔 `bind-info-lease`(默认值为 `3s`),会选出一个待验证的执行计划,将其和已经绑定的执行计划中代价最小的比较实际运行时间。如果待验证的运行时间更优的话(目前判断标准是运行时间小于等于已绑定执行计划运行时间的 2/3),会将其标记为可使用的绑定。以下示例描述上述过程。 - -假如有表 `t` 定义如下: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE t(a INT, b INT, KEY(a), KEY(b)); -``` - -在表 `t` 上进行如下查询: - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t WHERE a < 100 AND b < 100; -``` - -表上满足条件 `a < 100` 的行很少。但由于某些原因,优化器没能选中使用索引 `a` 这个最优执行计划,而是误选了速度慢的全表扫,那么用户首先可以通过如下语句创建一个绑定: - -{{< copyable "sql" >}} - -```sql -CREATE GLOBAL BINDING for SELECT * FROM t WHERE a < 100 AND b < 100 USING SELECT * FROM t use index(a) WHERE a < 100 AND b < 100; -``` - -当以上查询语句再次执行时,优化器会在刚创建绑定的干预下选择使用索引 `a`,进而降低查询时间。 - -假如随着在表中进行插入和修改,表中满足条件 `a < 100` 的行变得越来越多,而满足条件 `b < 100` 的行变得越来越少,这时再在绑定的干预下使用索引 `a` 可能就不是最优了。 - -绑定的演进可以解决这类问题。当优化器感知到表数据变化后,会对这条查询生成使用索引 `b` 的执行计划。但由于绑定的存在,这个执行计划不会被采纳和执行,不过它会被存在后台的演进列表里。在演进过程中,如果它被验证为执行时间明显低于使用索引 `a` 的执行时间(即当前绑定的执行计划),那么索引 `b` 会被加入到可用的绑定列表中。在此之后,当这条查询再次被执行时,优化器首先生成使用索引 `b` 的执行计划,并确认它在绑定列表中,所以会采纳它并执行,进而可以在数据变化后降低这条查询的执行时间。 - -为了减少自动演进对集群的影响,可以通过设置 `tidb_evolve_plan_task_max_time` 来限制每个执行计划运行的最长时间,其默认值为 `600s`。实际在验证执行计划时,计划的最长运行时间还会被限制为不超过已验证执行计划的运行时间的两倍;通过 `tidb_evolve_plan_task_start_time` 和 `tidb_evolve_plan_task_end_time` 可以限制运行演进任务的时间窗口,默认值分别为 `00:00 +0000` 和 `23:59 +0000`。 - -### 注意事项 - -由于自动演进绑定会自动地创建新的绑定,当查询的环境发生变动时,自动创建的绑定可能会有多种行为的选择。这里列出一些注意事项: - -+ 自动演进只会对存在至少一个 global 绑定的标准化 SQL 进行演进。 - -+ 由于创建新的绑定会删除之前所有绑定(对于一条标准化 SQL),自动演进的绑定也会在手动重新创建绑定后被删除。 - -+ 所有和计算过程相关的 hint,在演进时都会被保留。计算过程相关的 hint 有如下几种: - - | Hint | 说明 | - | :-------- | :------------- | - | memory_quota | 查询过程最多可以使用多少内存 | - | use_toja | 优化器是否考虑把子查询转化为 join | - | use_cascades | 是否使用 cascades 优化器 | - | no_index_merge | 优化器是否考虑将 index merge 作为一个读表选项 | - | read_consistent_replica | 是否强制读表时使用 follower read | - | max_execution_time | 查询过程最多消耗多少时间 | - -+ `read_from_storage` 是一个非常特别的 hint,因为它指定了读表时选择从 TiKV 读还是从 TiFlash 读。由于 TiDB 提供隔离读的功能,当隔离条件变化时,这个 hint 对演进出来的执行计划影响很大,所以当最初创建的绑定中存在这个 hint,TiDB 会无视其所有演进的绑定。 - -## 升级检查 (Upgrade Checklist) - -执行计划管理功能 (SPM) 在版本升级过程中可能会出现一些兼容性问题导致升级失败,你需要在版本升级前做一些检查,确保版本顺利升级。 - -* 当你尝试从 v5.2 以前的版本(即 v4.0、v5.0、v5.1)升级到当前版本,需要注意在升级前检查自动演进的开关 `tidb_evolve_plan_baselines` 是否已经关闭。如果尚未关闭,则需要将其关闭后再进行升级。具体操作如下所示: - - {{< copyable "sql" >}} - - ```sql - -- 在待升级的版本上检查自动演进的开关 `tidb_evolve_plan_baselines` 是否关闭。 - - SELECT @@global.tidb_evolve_plan_baselines; - - -- 如果演进的开关 `tidb_evolve_plan_baselines` 尚未关闭,则需要将其关闭。 - - set global tidb_evolve_plan_baselines = off; - ``` - -* 当你尝试从 v4.0 版本升级到当前版本,需要注意在升级前检查所有可用绑定对应的查询语句在新版本中是否存在语法错误。如果存在语法错误,则需要删除对应的绑定。 - - 具体操作如下所示: - - {{< copyable "sql" >}} - - ```sql - -- 在待升级的版本上检查现有可用绑定对应的查询语句。 - - SELECT bind_sql FROM mysql.bind_info WHERE status = 'using'; - - -- 将上一条查询得到的结果,在新版本的测试环境中进行验证。 - - bind_sql_0; - bind_sql_1; - ... - - -- 如果报错信息是语法错误(ERROR 1064 (42000): You have an error in your SQL syntax),则需要删除对应的绑定。 - -- 如果是其他错误,如未找到表,则表示语法兼容,不需要进行额外的处理。 - ``` +> 对于 `PREPARE` / `EXECUTE` 语句和使用二进制协议执行的查询,您需要为实际的查询语句创建执行计划绑定,而不是为 `PREPARE` / `EXECUTE` 语句创建绑定。 diff --git a/sql-prepared-plan-cache.md b/sql-prepared-plan-cache.md index 2637e7e7e4e3..ebd5990d348c 100644 --- a/sql-prepared-plan-cache.md +++ b/sql-prepared-plan-cache.md @@ -1,88 +1,84 @@ --- -title: Prepare 语句执行计划缓存 -summary: Prepare 语句执行计划缓存功能默认打开,可通过变量启用或关闭。缓存功能仅针对 Prepare/Execute 请求,对普通查询无效。缓存功能会有一定内存开销,可通过监控查看内存使用情况。可手动清空计划缓存,但不支持一次性清空整个集群的计划缓存。忽略 COM_STMT_CLOSE 指令和 DEALLOCATE PREPARE 语句,可解决计划被立即清理的问题。监控 Queries Using Plan Cache OPS 和 Plan Cache Miss OPS,以确保 SQL 执行计划缓存正常工作。Prepared Statement Count 图表显示非零值,表示应用使用了预处理语句。 +title: SQL Prepared 执行计划缓存 +summary: 了解 TiDB 中的 SQL Prepared 执行计划缓存。 --- -# Prepare 语句执行计划缓存 +# SQL Prepared 执行计划缓存 -TiDB 支持对 `Prepare`/`Execute` 请求的执行计划缓存。其中包括以下两种形式的预处理语句: +TiDB 支持对 `Prepare` 和 `Execute` 查询的执行计划缓存。这包括两种形式的预处理语句: -- 使用 `COM_STMT_PREPARE` 和 `COM_STMT_EXECUTE` 的协议功能; -- 执行 `Prepare`/`Execute` SQL 语句查询; +- 使用 `COM_STMT_PREPARE` 和 `COM_STMT_EXECUTE` 协议特性。 +- 使用 SQL 语句 `PREPARE` 和 `EXECUTE`。 -TiDB 优化器对这两类查询的处理是一样的:`Prepare` 时将参数化的 SQL 查询解析成 AST(抽象语法树),每次 `Execute` 时根据保存的 AST 和具体的参数值生成执行计划。 +TiDB 优化器以相同的方式处理这两种类型的查询:在准备阶段,将参数化查询解析为 AST(抽象语法树)并缓存;在后续执行时,基于存储的 AST 和具体参数值生成执行计划。 -当开启执行计划缓存后,每条 `Prepare` 语句的第一次 `Execute` 会检查当前查询是否可以使用执行计划缓存,如果可以则将生成的执行计划放进一个由 LRU 链表构成的缓存中;在后续的 `Execute` 中,会先从缓存中获取执行计划,并检查是否可用,如果获取和检查成功则跳过生成执行计划这一步,否则重新生成执行计划并放入缓存中。 +当启用执行计划缓存时,每个 `Prepare` 语句在首次执行时会检查当前查询是否可以使用执行计划缓存,如果可以使用,则将生成的执行计划放入由 LRU(最近最少使用)链表实现的缓存中。在后续的 `Execute` 查询中,从缓存中获取执行计划并检查其可用性。如果检查成功,则跳过生成执行计划的步骤。否则,重新生成执行计划并保存在缓存中。 -对于某些非 `PREPARE` 语句,TiDB 可以像 `Prepare`/`Execute` 语句一样支持执行计划缓存,详情请参考[非 Prepare 语句执行计划缓存](/sql-non-prepared-plan-cache.md)。 +TiDB 还支持对某些非 `PREPARE` 语句的执行计划缓存,类似于 `Prepare`/`Execute` 语句。更多详情,请参考[非预处理执行计划缓存](/sql-non-prepared-plan-cache.md)。 -在当前版本中,当 `Prepare` 语句符合以下条件任何一条,查询或者计划不会被缓存: +在当前版本的 TiDB 中,如果 `Prepare` 语句满足以下任一条件,则不会缓存查询或计划: -- `SELECT`、`UPDATE`、`INSERT`、`DELETE`、`Union`、`Intersect`、`Except` 以外的 SQL 语句; -- 访问临时表、包含生成列的表的查询,或使用静态模式(即 [`tidb_partition_prune_mode`](/system-variables.md#tidb_partition_prune_mode-从-v51-版本开始引入) 设置为 `static`)访问分区表的查询; -- 查询中包含非关联子查询,例如 `SELECT * FROM t1 WHERE t1.a > (SELECT 1 FROM t2 WHERE t2.b < 1)`; -- 执行计划中带有 `PhysicalApply` 算子的关联子查询,例如 `SELECT * FROM t1 WHERE t1.a > (SELECT a FROM t2 WHERE t1.b > t2.b)`; -- 包含 `ignore_plan_cache` 或 `set_var` 这两个 Hint 的查询,例如 `SELECT /*+ ignore_plan_cache() */ * FROM t` 或 `SELECT /*+ set_var(max_execution_time=1) */ * FROM t`; -- 包含除 `?` 外其他变量(即系统变量或用户自定义变量)的查询,例如 `select * from t where a>? and b>@x`; -- 查询包含无法被缓存函数。目前不能被缓存的函数有:`database()`、`current_user`、`current_role`、`user`、`connection_id`、`last_insert_id`、`row_count`、`version`、`like`; -- `LIMIT` 后面带有变量(例如 `LIMIT ?` 或 `LIMIT 10, ?`)且变量值大于 10000 的执行计划不缓存; -- `?` 直接在 `Order By` 后的查询,如 `Order By ?`,此时 `?` 表示根据 `Order By` 后第几列排序,排序列不同的查询使用同一个计划可能导致错误结果,故不缓存;如果是普通表达式,如 `Order By a+?` 则会缓存; -- `?` 紧跟在 `Group by` 后的查询,如 `Group By ?`,此时 `?` 表示根据 `Group By` 后第几列聚合,聚合列不同的查询使用同一个计划可能导致错误结果,故不缓存;如果是普通表达式,如 `Group By a+?` 则会缓存; -- `?` 出现在窗口函数 `Window Frame` 定义中的查询,如 `(partition by year order by sale rows ? preceding)`;如果 `?` 出现在窗口函数的其他位置,则会缓存; -- 用参数进行 `int` 和 `string` 比较的查询,如 `c_int >= ?` 或者 `c_int in (?, ?)`等,其中 `?` 为字符串类型,如 `set @x='123'`;此时为了保证结果和 MySQL 兼容性,需要每次对参数进行调整,故不会缓存; -- 会访问 `TiFlash` 的计划不会被缓存; -- 大部分情况下计划中含有 `TableDual` 的计划将将不会被缓存,除非当前执行的 `Prepare` 语句不含参数,则对应的 `TableDual` 计划可以被缓存。 -- 访问 TiDB 系统视图的查询,如 `information_schema.columns`。不建议使用 `Prepare`/`Execute` 语句访问系统视图。 +- 查询包含除 `SELECT`、`UPDATE`、`INSERT`、`DELETE`、`Union`、`Intersect` 和 `Except` 之外的 SQL 语句。 +- 查询访问临时表,或包含生成列的表,或使用静态模式(即 [`tidb_partition_prune_mode`](/system-variables.md#tidb_partition_prune_mode-new-in-v51) 设置为 `static`)访问分区表。 +- 查询包含非相关子查询,如 `SELECT * FROM t1 WHERE t1.a > (SELECT 1 FROM t2 WHERE t2.b < 1)`。 +- 查询包含在执行计划中带有 `PhysicalApply` 算子的相关子查询,如 `SELECT * FROM t1 WHERE t1.a > (SELECT a FROM t2 WHERE t1.b > t2.b)`。 +- 查询包含 `ignore_plan_cache` 或 `set_var` 提示,如 `SELECT /*+ ignore_plan_cache() */ * FROM t` 或 `SELECT /*+ set_var(max_execution_time=1) */ * FROM t`。 +- 查询包含除 `?` 之外的变量(包括系统变量或用户定义变量),如 `select * from t where a>? and b>@x`。 +- 查询包含无法缓存的函数:`database()`、`current_user`、`current_role`、`user`、`connection_id`、`last_insert_id`、`row_count`、`version` 和 `like`。 +- 查询使用变量作为 `LIMIT` 参数(如 `LIMIT ?` 和 `LIMIT 10, ?`)且变量值大于 10000。 +- 查询在 `Order By` 后包含 `?`,如 `Order By ?`。这类查询基于 `?` 指定的列进行排序。如果针对不同列的查询使用相同的执行计划,结果将会错误。因此,这类查询不会被缓存。但是,如果查询是常见的,如 `Order By a+?`,则会被缓存。 +- 查询在 `Group By` 后包含 `?`,如 `Group By?`。这类查询基于 `?` 指定的列进行分组。如果针对不同列的查询使用相同的执行计划,结果将会错误。因此,这类查询不会被缓存。但是,如果查询是常见的,如 `Group By a+?`,则会被缓存。 +- 查询在窗口函数的 `Window Frame` 定义中包含 `?`,如 `(partition by year order by sale rows ? preceding)`。如果 `?` 出现在窗口函数的其他位置,则查询会被缓存。 +- 查询包含用于比较 `int` 和 `string` 的参数,如 `c_int >= ?` 或 `c_int in (?, ?)`,其中 `?` 表示字符串类型,如 `set @x='123'`。为确保查询结果与 MySQL 兼容,需要在每次查询时调整参数,因此这类查询不会被缓存。 +- 计划尝试访问 `TiFlash`。 +- 在大多数情况下,包含 `TableDual` 的计划不会被缓存,除非当前 `Prepare` 语句没有参数。 +- 查询访问 TiDB 系统视图,如 `information_schema.columns`。不建议使用 `Prepare` 和 `Execute` 语句访问系统视图。 -TiDB 对 `?` 的个数有限制,如果超过了 65535 个,则会报错 `Prepared statement contains too many placeholders`。 +TiDB 对查询中的 `?` 数量有限制。如果查询包含超过 65535 个 `?`,将报错 `Prepared statement contains too many placeholders`。 -LRU 链表是设计成 session 级别的缓存,因为 `Prepare`/`Execute` 不能跨 session 执行。LRU 链表的每个元素是一个 key-value 对,value 是执行计划,key 由如下几部分组成: +LRU 链表被设计为会话级缓存,因为 `Prepare`/`Execute` 不能跨会话执行。LRU 列表的每个元素都是一个键值对。值是执行计划,键由以下部分组成: -- 执行 `Execute` 时所在数据库的名字; -- `Prepare` 语句的标识符,即紧跟在 `PREPARE` 关键字后的名字; -- 当前的 schema 版本,每条执行成功的 DDL 语句会修改 schema 版本; -- 执行 `Execute` 时的 SQL Mode; -- 当前设置的时区,即系统变量 `time_zone` 的值; -- 系统变量 `sql_select_limit` 的值; +- 执行 `Execute` 的数据库名称 +- `Prepare` 语句的标识符,即 `PREPARE` 关键字后的名称 +- 当前的 schema 版本,每次成功执行 DDL 语句后都会更新 +- 执行 `Execute` 时的 SQL 模式 +- 当前时区,即 `time_zone` 系统变量的值 +- `sql_select_limit` 系统变量的值 -key 中任何一项变动(如切换数据库、重命名 `Prepare` 语句、执行 DDL、修改 SQL Mode/`time_zone` 的值)、或 LRU 淘汰机制触发都会导致 `Execute` 时无法命中执行计划缓存。 +上述信息的任何变化(例如,切换数据库、重命名 `Prepare` 语句、执行 DDL 语句或修改 SQL 模式/`time_zone` 的值),或 LRU 缓存淘汰机制都会导致执行时执行计划缓存未命中。 -成功从缓存中获取到执行计划后,TiDB 会先检查执行计划是否依然合法,如果当前 `Execute` 在显式事务里执行,并且引用的表在事务前序语句中被修改,而缓存的执行计划对该表访问不包含 `UnionScan` 算子,则它不能被执行。 +从缓存中获取执行计划后,TiDB 首先检查执行计划是否仍然有效。如果当前 `Execute` 语句在显式事务中执行,并且在事务前序语句中修改了引用的表,则访问该表的缓存执行计划不包含 `UnionScan` 算子,因此无法执行。 -在通过合法性检测后,会根据当前最新参数值,对执行计划的扫描范围做相应调整,再用它执行获取数据。 +通过验证测试后,根据当前参数值调整执行计划的扫描范围,然后用于执行数据查询。 -关于执行计划缓存和查询性能有几点值得注意: +关于执行计划缓存和查询性能,有几点值得注意: -- 不管计划是否已经被缓存,都会受到 SQL Binding 的影响。对于没有被缓存的计划,即在第一次执行 `Execute` 时,会受到已有 SQL Binding 的影响;而对于已经缓存的计划,如果有新的 SQL Binding 被创建产生,则原有已经被缓存的计划会失效。 -- 已经被缓存的计划不会受到统计信息更新、优化规则和表达式下推黑名单更新的影响,仍然会使用已经保存在缓存中的计划。 -- 重启 TiDB 实例时(如不停机滚动升级 TiDB 集群),`Prepare` 信息会丢失,此时执行 `execute stmt ...` 可能会遇到 `Prepared Statement not found` 的错误,此时需要再执行一次 `prepare stmt ...`。 -- 考虑到不同 `Execute` 的参数会不同,执行计划缓存为了保证适配性会禁止一些和具体参数值密切相关的激进查询优化手段,导致对特定的一些参数值,查询计划可能不是最优。比如查询的过滤条件为 `where a > ? and a < ?`,第一次 `Execute` 时参数分别为 2 和 1,考虑到这两个参数下次执行时可能会是 1 和 2,优化器不会生成对当前参数最优的 `TableDual` 执行计划。 -- 如果不考虑缓存失效和淘汰,一份执行计划缓存会对应各种不同的参数取值,理论上也会导致某些取值下执行计划非最优。比如查询过滤条件为 `where a < ?`,假如第一次执行 `Execute` 时用的参数值为 1,此时优化器生成最优的 `IndexScan` 执行计划放入缓存,在后续执行 `Execute` 时参数变为 10000,此时 `TableScan` 可能才是更优执行计划,但由于执行计划缓存,执行时还是会使用先前生成的 `IndexScan`。因此执行计划缓存更适用于查询较为简单(查询编译耗时占比较高)且执行计划较为固定的业务场景。 +- 无论执行计划是否被缓存,它都会受到 SQL 绑定的影响。对于未缓存的执行计划(第一次 `Execute`),这些计划受现有 SQL 绑定的影响。对于已缓存的执行计划,如果创建了新的 SQL 绑定,这些计划将变为无效。 +- 缓存的计划不受统计信息、优化规则和表达式下推黑名单变化的影响。 +- 考虑到 `Execute` 的参数不同,执行计划缓存禁止了一些与特定参数值密切相关的激进查询优化方法,以确保适应性。这导致查询计划可能对某些参数值不是最优的。例如,查询的过滤条件是 `where a > ? And a < ?`,第一次 `Execute` 语句的参数分别是 `2` 和 `1`。考虑到这两个参数在下次执行时可能是 `1` 和 `2`,优化器不会生成针对当前参数值的最优 `TableDual` 执行计划; +- 如果不考虑缓存失效和淘汰,执行计划缓存适用于各种参数值,这在理论上也会导致某些值的执行计划不是最优的。例如,如果过滤条件是 `where a < ?` 且第一次执行使用的参数值是 `1`,那么优化器会生成最优的 `IndexScan` 执行计划并将其放入缓存。在后续执行中,如果值变为 `10000`,`TableScan` 计划可能是更好的选择。但由于执行计划缓存,会使用之前生成的 `IndexScan` 进行执行。因此,执行计划缓存更适合于查询简单(编译比例高)且执行计划相对固定的应用场景。 -自 v6.1.0 起,执行计划缓存功能默认打开,可以通过变量 [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-从-v610-版本开始引入) 启用或关闭这项功能。 +从 v6.1.0 开始,执行计划缓存默认启用。你可以通过系统变量 [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610) 控制预处理计划缓存。 > **注意:** > -> 系统变量 [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-从-v610-版本开始引入) 控制的执行计划缓存仅针对 `Prepare`/`Execute` 请求,对普通查询无效。普通查询的执行计划缓存参见[非 Prepare 语句执行计划缓存](/sql-non-prepared-plan-cache.md)。 +> [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610) 系统变量仅控制 `Prepare`/`Execute` 查询的执行计划缓存,不控制普通查询的执行计划缓存。关于普通查询的执行计划缓存,请参见[SQL 非预处理执行计划缓存](/sql-non-prepared-plan-cache.md)。 -在开启了执行计划缓存功能后,可以通过 SESSION 级别的系统变量 [`last_plan_from_cache`](/system-variables.md#last_plan_from_cache-从-v40-版本开始引入) 查看上一条 `Execute` 语句是否使用了缓存的执行计划,例如: +启用执行计划缓存功能后,你可以使用会话级系统变量 [`last_plan_from_cache`](/system-variables.md#last_plan_from_cache-new-in-v40) 查看上一个 `Execute` 语句是否使用了缓存的执行计划,例如: {{< copyable "sql" >}} ```sql MySQL [test]> create table t(a int); Query OK, 0 rows affected (0.00 sec) - MySQL [test]> prepare stmt from 'select * from t where a = ?'; Query OK, 0 rows affected (0.00 sec) - MySQL [test]> set @a = 1; Query OK, 0 rows affected (0.00 sec) --- 第一次 execute 生成执行计划放入缓存 +-- 第一次执行生成执行计划并保存在缓存中。 MySQL [test]> execute stmt using @a; Empty set (0.00 sec) - MySQL [test]> select @@last_plan_from_cache; +------------------------+ | @@last_plan_from_cache | @@ -91,10 +87,9 @@ MySQL [test]> select @@last_plan_from_cache; +------------------------+ 1 row in set (0.00 sec) --- 第二次 execute 命中缓存 +-- 第二次执行命中缓存。 MySQL [test]> execute stmt using @a; Empty set (0.00 sec) - MySQL [test]> select @@last_plan_from_cache; +------------------------+ | @@last_plan_from_cache | @@ -104,20 +99,17 @@ MySQL [test]> select @@last_plan_from_cache; 1 row in set (0.00 sec) ``` -如果发现某一组 `Prepare`/`Execute` 由于执行计划缓存导致了非预期行为,可以通过 SQL Hint `ignore_plan_cache()` 让该组语句不使用缓存。还是用上述的 `stmt` 为例: +如果你发现某个 `Prepare`/`Execute` 由于执行计划缓存而出现意外行为,可以使用 `ignore_plan_cache()` SQL 提示跳过当前语句的执行计划缓存。仍以上述语句为例: {{< copyable "sql" >}} ```sql MySQL [test]> prepare stmt from 'select /*+ ignore_plan_cache() */ * from t where a = ?'; Query OK, 0 rows affected (0.00 sec) - MySQL [test]> set @a = 1; Query OK, 0 rows affected (0.00 sec) - MySQL [test]> execute stmt using @a; Empty set (0.00 sec) - MySQL [test]> select @@last_plan_from_cache; +------------------------+ | @@last_plan_from_cache | @@ -125,10 +117,8 @@ MySQL [test]> select @@last_plan_from_cache; | 0 | +------------------------+ 1 row in set (0.00 sec) - MySQL [test]> execute stmt using @a; Empty set (0.00 sec) - MySQL [test]> select @@last_plan_from_cache; +------------------------+ | @@last_plan_from_cache | @@ -138,15 +128,17 @@ MySQL [test]> select @@last_plan_from_cache; 1 row in set (0.00 sec) ``` -## 诊断 Prepared Plan Cache +## 预处理计划缓存的诊断 -对于无法进行缓存的查询或计划,可通过 `SHOW WARNINGS` 语句查看查询或计划是否被缓存。如果未被缓存,则可在结果中查看无法被缓存的原因。示例如下: +某些查询或计划无法被缓存。你可以使用 `SHOW WARNINGS` 语句检查查询或计划是否被缓存。如果未被缓存,你可以在结果中查看失败的原因。例如: ```sql -mysql> PREPARE st FROM 'SELECT * FROM t WHERE a > (SELECT MAX(a) FROM t)'; -- 该查询包含子查询,因此无法被缓存 +mysql> PREPARE st FROM 'SELECT * FROM t WHERE a > (SELECT MAX(a) FROM t)'; -- 查询包含子查询,无法缓存。 + Query OK, 0 rows affected, 1 warning (0.01 sec) -mysql> SHOW WARNINGS; -- 查看查询计划无法被缓存的原因 +mysql> show warnings; -- 检查查询计划无法缓存的原因。 + +---------+------+-----------------------------------------------+ | Level | Code | Message | +---------+------+-----------------------------------------------+ @@ -154,16 +146,20 @@ mysql> SHOW WARNINGS; -- 查看查询计划无法被缓存的原因 +---------+------+-----------------------------------------------+ 1 row in set (0.00 sec) -mysql> PREPARE st FROM 'SELECT * FROM t WHERE a prepare st from 'select * from t where a SET @a='1'; +mysql> set @a='1'; + Query OK, 0 rows affected (0.00 sec) -mysql> EXECUTE st USING @a; -- 该优化中进行了非 INT 类型到 INT 类型的转换,产生的执行计划可能随着参数变化而存在风险,因此 TiDB 不缓存该计划 +mysql> execute st using @a; -- 优化将非 INT 类型转换为 INT 类型,执行计划可能随参数变化而变化,所以 TiDB 不缓存该计划。 + Empty set, 1 warning (0.01 sec) -mysql> SHOW WARNINGS; +mysql> show warnings; + +---------+------+----------------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------------+ @@ -172,40 +168,64 @@ mysql> SHOW WARNINGS; 1 row in set (0.00 sec) ``` -## Prepared Plan Cache 的内存管理 +## 预处理计划缓存的内存管理 + + -使用 Prepared Plan Cache 会有一定的内存开销,可以通过 Grafana 中的 [`Plan Cache Memory Usage` 监控](/grafana-tidb-dashboard.md)查看每台 TiDB 实例上所有 `SESSION` 所缓存的计划占用的总内存。 +使用预处理计划缓存会产生内存开销。要查看每个 TiDB 实例中所有会话的缓存执行计划的总内存消耗,你可以使用 Grafana 中的 [**Plan Cache Memory Usage** 监控面板](/grafana-tidb-dashboard.md)。 > **注意:** > -> 考虑到 Golang 的内存回收机制以及部分未统计的内存结构,Grafana 中显示的内存与实际的堆内存使用量并不相等。经过实验验证存在约 ±20% 的误差。 +> 由于 Golang 的内存回收机制和一些未计数的内存结构,Grafana 中显示的内存不等于实际的堆内存使用量。经测试,Grafana 中显示的内存与实际堆内存使用量之间存在约 ±20% 的偏差。 -对于每台 TiDB 实例上所缓存的执行计划总数量,可以通过 Grafana 中的 [`Plan Cache Plan Num` 监控](/grafana-tidb-dashboard.md)查看。 +要查看每个 TiDB 实例中缓存的执行计划总数,你可以使用 Grafana 中的 [**Plan Cache Plan Num** 面板](/grafana-tidb-dashboard.md)。 -Grafana 中 `Plan Cache Memory Usage` 和 `Plan Cache Plan Num` 监控如下图所示: +以下是 Grafana 中 **Plan Cache Memory Usage** 和 **Plan Cache Plan Num** 面板的示例: ![grafana_panels](/media/planCache-memoryUsage-planNum-panels.png) -从 v7.1.0 开始,你可以通过变量 [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-从-v710-版本开始引入) 来设置每个 `SESSION` 最多缓存的计划数量。针对不同的环境,推荐的设置如下,你可以结合监控进行调整: +从 v7.1.0 开始,你可以通过配置系统变量 [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-new-in-v710) 来控制每个会话中可以缓存的计划的最大数量。对于不同的环境,建议值如下,你可以根据监控面板进行调整: -- TiDB Server 实例内存阈值 <= 64 GiB 时,`tidb_session_plan_cache_size = 50` -- TiDB Server 实例内存阈值 > 64 GiB 时,`tidb_session_plan_cache_size = 100` + -从 v7.1.0 开始,你可以通过变量 [`tidb_plan_cache_max_plan_size`](/system-variables.md#tidb_plan_cache_max_plan_size-从-v710-版本开始引入) 来设置可以缓存的计划的最大大小,默认为 2 MB。超过该值的执行计划将不会被缓存到 Plan Cache 中。 + -当 TiDB Server 的内存余量小于一定阈值时,会触发 Plan Cache 的内存保护机制,此时会对一些缓存的计划进行逐出。 +使用预处理计划缓存会产生一些内存开销。在内部测试中,每个缓存的计划平均消耗 100 KiB 内存。由于计划缓存目前是在 `SESSION` 级别,总内存消耗大约是 `会话数 * 每个会话中缓存的平均计划数 * 100 KiB`。 -目前该阈值由变量 `tidb_prepared_plan_cache_memory_guard_ratio` 控制,默认为 0.1,即 10%,也就是当剩余内存不足 10%(使用内存超过 90%)时,会触发此机制。 +例如,当前 TiDB 实例有 50 个并发会话,每个会话大约有 100 个缓存的计划。总内存消耗大约是 `50 * 100 * 100 KiB` = `512 MB`。 -由于内存限制,Plan Cache 可能出现 Cache Miss 的情况,可以通过 Grafana 中的 [`Plan Cache Miss OPS` 监控](/grafana-tidb-dashboard.md)查看。 +你可以通过配置系统变量 [`tidb_session_plan_cache_size`](/system-variables.md#tidb_session_plan_cache_size-new-in-v710) 来控制每个会话中可以缓存的计划的最大数量。对于不同的环境,建议值如下: -## 手动清空计划缓存 + -通过执行 `ADMIN FLUSH [SESSION | INSTANCE] PLAN_CACHE` 语句,你可以手动清空计划缓存。 +- 当 TiDB 服务器实例的内存阈值 <= 64 GiB 时,将 `tidb_session_plan_cache_size` 设置为 `50`。 +- 当 TiDB 服务器实例的内存阈值 > 64 GiB 时,将 `tidb_session_plan_cache_size` 设置为 `100`。 -该语句中的作用域 `[SESSION | INSTANCE]` 用于指定需要清空的缓存级别,可以为 `SESSION` 或 `INSTANCE`。如果不指定作用域,该语句默认清空 `SESSION` 级别的缓存。 +从 v7.1.0 开始,你可以使用系统变量 [`tidb_plan_cache_max_plan_size`](/system-variables.md#tidb_plan_cache_max_plan_size-new-in-v710) 控制可以缓存的计划的最大大小。默认值为 2 MB。如果计划的大小超过此值,则不会缓存该计划。 -下面是一个清空计划缓存的例子: +当 TiDB 服务器的未使用内存小于某个阈值时,会触发计划缓存的内存保护机制,通过该机制将驱逐一些缓存的计划。 + +你可以通过配置系统变量 `tidb_prepared_plan_cache_memory_guard_ratio` 来控制阈值。阈值默认为 0.1,这意味着当 TiDB 服务器的未使用内存小于总内存的 10%(90% 的内存已使用)时,将触发内存保护机制。 + + + +由于内存限制,计划缓存有时可能会未命中。你可以通过查看 Grafana 仪表板中的 [`Plan Cache Miss OPS` 指标](/grafana-tidb-dashboard.md)来检查状态。 + + + + + +由于内存限制,计划缓存有时可能会未命中。 + + + +## 清除执行计划缓存 + +你可以通过执行 `ADMIN FLUSH [SESSION | INSTANCE] PLAN_CACHE` 语句来清除执行计划缓存。 + +在此语句中,`[SESSION | INSTANCE]` 指定是清除当前会话还是整个 TiDB 实例的计划缓存。如果未指定范围,则上述语句默认应用于 `SESSION` 缓存。 + +以下是清除 `SESSION` 执行计划缓存的示例: {{< copyable "sql" >}} @@ -222,7 +242,7 @@ Empty set (0.00 sec) MySQL [test]> execute stmt; Empty set (0.00 sec) -MySQL [test]> select @@last_plan_from_cache; -- 选择计划缓存 +MySQL [test]> select @@last_plan_from_cache; -- 选择缓存的计划 +------------------------+ | @@last_plan_from_cache | +------------------------+ @@ -230,13 +250,13 @@ MySQL [test]> select @@last_plan_from_cache; -- 选择计划缓存 +------------------------+ 1 row in set (0.00 sec) -MySQL [test]> admin flush session plan_cache; -- 清空当前 session 的计划缓存 +MySQL [test]> admin flush session plan_cache; -- 清除当前会话的缓存计划 Query OK, 0 rows affected (0.00 sec) MySQL [test]> execute stmt; Empty set (0.00 sec) -MySQL [test]> select @@last_plan_from_cache; -- 由于缓存被清空,此时无法再次选中 +MySQL [test]> select @@last_plan_from_cache; -- 无法再次选择缓存的计划,因为它已被清除 +------------------------+ | @@last_plan_from_cache | +------------------------+ @@ -245,7 +265,7 @@ MySQL [test]> select @@last_plan_from_cache; -- 由于缓存被清空,此时 1 row in set (0.00 sec) ``` -TiDB 暂不支持清空 `GLOBAL` 级别的计划缓存,即不支持一次性清空整个集群的计划缓存,使用时会报错: +目前,TiDB 不支持清除 `GLOBAL` 执行计划缓存。这意味着你无法清除整个 TiDB 集群的缓存计划。如果你尝试清除 `GLOBAL` 执行计划缓存,将报告以下错误: {{< copyable "sql" >}} @@ -254,59 +274,59 @@ MySQL [test]> admin flush global plan_cache; ERROR 1105 (HY000): Do not support the 'admin flush global scope.' ``` -## 忽略 `COM_STMT_CLOSE` 指令和 `DEALLOCATE PREPARE` 语句 +## 忽略 `COM_STMT_CLOSE` 命令和 `DEALLOCATE PREPARE` 语句 -为了减少每次执行 SQL 语句的语法分析,Prepared Statement 推荐的使用方式是,prepare 一次,然后 execute 多次,最后 deallocate prepare。例如: +为了减少 SQL 语句的语法解析成本,建议你运行一次 `prepare stmt`,然后多次运行 `execute stmt`,最后运行 `deallocate prepare`: {{< copyable "sql" >}} ```sql -MySQL [test]> prepare stmt from '...'; -- prepare 一次 -MySQL [test]> execute stmt using ...; -- execute 一次 +MySQL [test]> prepare stmt from '...'; -- 准备一次 +MySQL [test]> execute stmt using ...; -- 执行一次 MySQL [test]> ... -MySQL [test]> execute stmt using ...; -- execute 多次 -MySQL [test]> deallocate prepare stmt; -- 使用完成后释放 +MySQL [test]> execute stmt using ...; -- 执行多次 +MySQL [test]> deallocate prepare stmt; -- 释放预处理语句 ``` -如果你习惯于在每次 execute 后都立即执行 deallocate prepare,如: +在实际操作中,你可能习惯于每次运行 `execute stmt` 后都运行 `deallocate prepare`,如下所示: {{< copyable "sql" >}} ```sql -MySQL [test]> prepare stmt from '...'; -- 第一次 prepare +MySQL [test]> prepare stmt from '...'; -- 准备一次 MySQL [test]> execute stmt using ...; -MySQL [test]> deallocate prepare stmt; -- 一次使用后立即释放 -MySQL [test]> prepare stmt from '...'; -- 第二次 prepare +MySQL [test]> deallocate prepare stmt; -- 释放预处理语句 +MySQL [test]> prepare stmt from '...'; -- 准备两次 MySQL [test]> execute stmt using ...; -MySQL [test]> deallocate prepare stmt; -- 再次释放 +MySQL [test]> deallocate prepare stmt; -- 释放预处理语句 ``` -这样的使用方式会让第一次执行得到的计划被立即清理,不能在第二次被复用。 +在这种情况下,第一个执行语句获得的计划无法被第二个执行语句重用。 -为了兼容这样的使用方式,从 v6.0 起,TiDB 支持 [`tidb_ignore_prepared_cache_close_stmt`](/system-variables.md#tidb_ignore_prepared_cache_close_stmt-从-v600-版本开始引入) 变量。打开该变量后,TiDB 会忽略关闭 Prepare Statement 的信号,解决上述问题,如: +为了解决这个问题,你可以将系统变量 [`tidb_ignore_prepared_cache_close_stmt`](/system-variables.md#tidb_ignore_prepared_cache_close_stmt-new-in-v600) 设置为 `ON`,这样 TiDB 就会忽略关闭 `prepare stmt` 的命令: {{< copyable "sql" >}} ```sql -mysql> set @@tidb_ignore_prepared_cache_close_stmt=1; -- 打开开关 +mysql> set @@tidb_ignore_prepared_cache_close_stmt=1; -- 启用变量 Query OK, 0 rows affected (0.00 sec) -mysql> prepare stmt from 'select * from t'; -- 第一次 prepare +mysql> prepare stmt from 'select * from t'; -- 准备一次 Query OK, 0 rows affected (0.00 sec) -mysql> execute stmt; -- 第一次 execute +mysql> execute stmt; -- 执行一次 Empty set (0.00 sec) -mysql> deallocate prepare stmt; -- 第一次 execute 后立即释放 +mysql> deallocate prepare stmt; -- 第一次执行后释放 Query OK, 0 rows affected (0.00 sec) -mysql> prepare stmt from 'select * from t'; -- 第二次 prepare +mysql> prepare stmt from 'select * from t'; -- 准备两次 Query OK, 0 rows affected (0.00 sec) -mysql> execute stmt; -- 第二次 execute +mysql> execute stmt; -- 执行两次 Empty set (0.00 sec) -mysql> select @@last_plan_from_cache; -- 因为开关打开,第二次依旧能复用上一次的计划 +mysql> select @@last_plan_from_cache; -- 重用上一个计划 +------------------------+ | @@last_plan_from_cache | +------------------------+ @@ -317,6 +337,16 @@ mysql> select @@last_plan_from_cache; -- 因为开关打开,第二次依 ### 监控 -在 [Grafana 面板](/grafana-tidb-dashboard.md)的 TiDB 页面,**Executor** 部分包含“Queries Using Plan Cache OPS”和“Plan Cache Miss OPS”两个图表,用以检查 TiDB 和应用是否正确配置,以便 SQL 执行计划缓存能正常工作。TiDB 页面的 **Server** 部分还提供了“Prepared Statement Count”图表,如果应用使用了预处理语句,这个图表会显示非零值。通过数值变化,可以判断 SQL 执行计划缓存是否正常工作。 + + +在 TiDB 页面的 **Executor** 部分的 [Grafana 仪表板](/grafana-tidb-dashboard.md)中,有 "Queries Using Plan Cache OPS" 和 "Plan Cache Miss OPS" 图表。这些图表可用于检查 TiDB 和应用程序是否都正确配置以允许 SQL 计划缓存正常工作。同一页面的 **Server** 部分提供了 "Prepared Statement Count" 图表。如果应用程序使用预处理语句(这是 SQL 计划缓存正常工作所必需的),此图表会显示非零值。 ![`sql_plan_cache`](/media/performance/sql_plan_cache.png) + + + + + +在 [TiDB Cloud 控制台](https://tidbcloud.com/) 的[**监控**](/tidb-cloud/built-in-monitoring.md)页面上,你可以查看 `Queries Using Plan Cache OPS` 指标,以获取所有 TiDB 实例中每秒使用或未命中计划缓存的查询数。 + + diff --git a/sql-statements/sql-statement-add-column.md b/sql-statements/sql-statement-add-column.md index af37824d783d..a8886ab21161 100644 --- a/sql-statements/sql-statement-add-column.md +++ b/sql-statements/sql-statement-add-column.md @@ -1,13 +1,13 @@ --- -title: ADD COLUMN -summary: TiDB 数据库中 ADD COLUMN 的使用概况。 +title: ADD COLUMN | TiDB SQL 语句参考 +summary: TiDB 数据库中 ADD COLUMN 的使用概述。 --- # ADD COLUMN -`ALTER TABLE.. ADD COLUMN` 语句用于在已有表中添加列。在 TiDB 中,`ADD COLUMN` 为在线操作,不会阻塞表中的数据读写。 +`ALTER TABLE.. ADD COLUMN` 语句用于向现有表添加列。在 TiDB 中,这是一个在线操作,这意味着添加列时不会阻塞对表的读取或写入操作。 -## 语法图 +## 语法 ```ebnf+diagram AlterTableStmt @@ -45,83 +45,36 @@ ColumnOption ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT); Query OK, 0 rows affected (0.11 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (NULL); -``` - -``` +mysql> INSERT INTO t1 VALUES (NULL); Query OK, 1 row affected (0.02 sec) -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -ALTER TABLE t1 ADD COLUMN c1 INT NOT NULL; -``` -``` +mysql> ALTER TABLE t1 ADD COLUMN c1 INT NOT NULL; Query OK, 0 rows affected (0.28 sec) -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ | 1 | 0 | +----+----+ 1 row in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -ALTER TABLE t1 ADD c2 INT NOT NULL AFTER c1; -``` - -``` +mysql> ALTER TABLE t1 ADD c2 INT NOT NULL AFTER c1; Query OK, 0 rows affected (0.28 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+----+----+ | id | c1 | c2 | +----+----+----+ @@ -132,9 +85,9 @@ SELECT * FROM t1; ## MySQL 兼容性 -* 不支持将新添加的列设为 `PRIMARY KEY`。 -* 不支持将新添加的列设为 `AUTO_INCREMENT`。 -* 对添加生成列有局限性,具体可参考:[生成列局限性](/generated-columns.md#生成列的局限性)。 +* 不支持添加新列并将其设置为 `PRIMARY KEY`。 +* 不支持添加新列并将其设置为 `AUTO_INCREMENT`。 +* 添加生成列有一些限制,请参考:[生成列的限制](/generated-columns.md#limitations)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-add-index.md b/sql-statements/sql-statement-add-index.md index d5fd1e830dca..ce1fb09c38d0 100644 --- a/sql-statements/sql-statement-add-index.md +++ b/sql-statements/sql-statement-add-index.md @@ -1,24 +1,29 @@ --- -title: ADD INDEX -summary: TiDB 数据库中 ADD INDEX 的使用概况。 +title: ADD INDEX | TiDB SQL 语句参考 +summary: TiDB 数据库中 ADD INDEX 的使用概述。 --- # ADD INDEX -`ALTER TABLE.. ADD INDEX` 语句用于在已有表中添加一个索引。在 TiDB 中,`ADD INDEX` 为在线操作,不会阻塞表中的数据读写。 +`ALTER TABLE.. ADD INDEX` 语句用于向现有表添加索引。在 TiDB 中,这是一个在线操作,这意味着添加索引时不会阻塞对表的读取或写入操作。 -> **Tip:** +> **提示:** > -> 你可以使用 [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md)加速该语句的执行。 +> 可以使用 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) 来加速此语句的执行。 + + > **警告:** > -> - 在升级 TiDB 集群的过程中,**请勿执行** DDL 语句,否则可能会出现行为未定义的问题。 -> - 集群中有 DDL 语句正在被执行时(通常为 `ADD INDEX` 和列类型变更等耗时较久的 DDL 语句),**请勿进行**升级操作。在升级前,建议使用 [`ADMIN SHOW DDL`](/sql-statements/sql-statement-admin-show-ddl.md) 命令查看集群中是否有正在进行的 DDL Job。如需升级,请等待 DDL 执行完成或使用 [`ADMIN CANCEL DDL`](/sql-statements/sql-statement-admin-cancel-ddl.md) 命令取消该 DDL Job 后再进行升级。 -> -> 从 TiDB v7.1 版本升级至更高的版本时,可以不遵循以上限制,建议参考[平滑升级 TiDB 的限制](/smooth-upgrade-tidb.md#使用限制)。 +> - 在集群中执行 DDL 语句时(通常是耗时的 DDL 语句,如 `ADD INDEX` 和列类型更改),**不要**升级 TiDB 集群。 +> - 在升级之前,建议使用 [`ADMIN SHOW DDL`](/sql-statements/sql-statement-admin-show-ddl.md) 命令检查 TiDB 集群是否有正在进行的 DDL 任务。如果集群有 DDL 任务,要升级集群,请等待 DDL 执行完成,或使用 [`ADMIN CANCEL DDL`](/sql-statements/sql-statement-admin-cancel-ddl.md) 命令取消 DDL 任务后再升级集群。 +> - 此外,在集群升级期间,**不要**执行任何 DDL 语句。否则,可能会出现未定义行为的问题。 +> +> 当你将 TiDB 从 v7.1.0 升级到更高版本时,可以忽略上述限制。详情请参见 [TiDB 平滑升级的限制](/smooth-upgrade-tidb.md)。 -## 语法图 + + +## 语法 ```ebnf+diagram AlterTableStmt @@ -46,34 +51,15 @@ IndexType ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` - -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` -{{< copyable "sql" >}} - -```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` - -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +-------------------------+----------+-----------+---------------+--------------------------------+ | id | estRows | task | access object | operator info | +-------------------------+----------+-----------+---------------+--------------------------------+ @@ -82,25 +68,11 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; | └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +-------------------------+----------+-----------+---------------+--------------------------------+ 3 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -ALTER TABLE t1 ADD INDEX (c1); -``` -``` +mysql> ALTER TABLE t1 ADD INDEX (c1); Query OK, 0 rows affected (0.30 sec) -``` -{{< copyable "sql" >}} - -```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` - -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +------------------------+---------+-----------+------------------------+---------------------------------------------+ | id | estRows | task | access object | operator info | +------------------------+---------+-----------+------------------------+---------------------------------------------+ @@ -112,16 +84,16 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; ## MySQL 兼容性 -* 为了兼容 MySQL,TiDB 在语法上支持 `HASH`、`BTREE` 和 `RTREE` 等索引类型,但会忽略它们。 +* TiDB 在语法上接受 `HASH`、`BTREE` 和 `RTREE` 等索引类型以与 MySQL 兼容,但会忽略这些类型。 * 不支持 `SPATIAL` 索引。 -* TiDB 支持解析 `FULLTEXT` 语法,但不支持使用 `FULLTEXT` 索引。 +* TiDB 支持解析 `FULLTEXT` 语法但不支持使用 `FULLTEXT` 索引。 * 不支持降序索引(类似于 MySQL 5.7)。 -* 无法向表中添加 `CLUSTERED` 类型的 `PRIMARY KEY`。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 +* 不支持向表添加 `CLUSTERED` 类型的主键。关于 `CLUSTERED` 类型的主键的更多详情,请参考[聚簇索引](/clustered-indexes.md)。 ## 另请参阅 -* [索引的选择](/choose-index.md) -* [错误索引的解决方案](/wrong-index-solution.md) +* [索引选择](/choose-index.md) +* [错误索引解决方案](/wrong-index-solution.md) * [CREATE INDEX](/sql-statements/sql-statement-create-index.md) * [DROP INDEX](/sql-statements/sql-statement-drop-index.md) * [RENAME INDEX](/sql-statements/sql-statement-rename-index.md) @@ -129,4 +101,4 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; * [ADD COLUMN](/sql-statements/sql-statement-add-column.md) * [CREATE TABLE](/sql-statements/sql-statement-create-table.md) * [EXPLAIN](/sql-statements/sql-statement-explain.md) -* [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md) +* [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) diff --git a/sql-statements/sql-statement-admin-cancel-ddl.md b/sql-statements/sql-statement-admin-cancel-ddl.md index 5e3b26170132..69c9219b4aef 100644 --- a/sql-statements/sql-statement-admin-cancel-ddl.md +++ b/sql-statements/sql-statement-admin-cancel-ddl.md @@ -1,19 +1,20 @@ --- -title: ADMIN CANCEL DDL -summary: TiDB 数据库中 ADMIN CANCEL DDL 的使用概况。 +title: ADMIN CANCEL DDL | TiDB SQL 语句参考 +summary: TiDB 数据库中 ADMIN CANCEL DDL 的使用概览。 +category: reference --- # ADMIN CANCEL DDL -`ADMIN CANCEL DDL` 语句用于取消当前正在运行的 DDL 作业。可以通过 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 作业的 `job_id`。 +`ADMIN CANCEL DDL` 语句允许您取消正在运行的 DDL 作业。可以通过运行 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 找到 `job_id`。 -用于取消已经提交但未执行完成的 DDL 任务。取消完成后,执行 DDL 任务的 SQL 语句会返回 `ERROR 8214 (HY000): Cancelled DDL job` 的错误。取消一个已经执行完成的 DDL 任务会在 RESULT 列看到 `DDL Job:90 not found` 的错误,表示该任务已从 DDL 等待队列中被移除。 +`ADMIN CANCEL DDL` 语句还允许您取消已提交但尚未完成执行的 DDL 作业。取消后,执行 DDL 作业的 SQL 语句将返回 `ERROR 8214 (HY000): Cancelled DDL job` 错误。如果您取消一个已经完成的 DDL 作业,您将在 `RESULT` 列中看到 `DDL Job:90 not found` 错误,这表示该作业已从 DDL 等待队列中移除。 -## 语法图 +## 语法 ```ebnf+diagram AdminCancelDDLStmt ::= - 'ADMIN' 'CANCEL' 'DDL' 'JOBS' NumList + 'ADMIN' 'CANCEL' 'DDL' 'JOBS' NumList NumList ::= Int64Num ( ',' Int64Num )* @@ -21,24 +22,24 @@ NumList ::= ## 示例 -可以通过 `ADMIN CANCEL DDL JOBS` 语句取消当前正在运行的 DDL 作业,并返回对应作业是否取消成功: +要取消当前正在运行的 DDL 作业并返回相应作业是否成功取消,使用 `ADMIN CANCEL DDL JOBS`: ```sql ADMIN CANCEL DDL JOBS job_id [, job_id] ...; ``` -如果取消失败,会显示失败的具体原因。 +如果操作未能取消作业,将显示具体原因。 > **注意:** > -> + 在 v6.2.0 之前,只有该操作可以取消 DDL 作业,其他所有的操作和环境变更(例如机器重启、集群重启)都不会取消 DDL 作业。从 v6.2.0 开始,使用 [`KILL`](/sql-statements/sql-statement-kill.md) 语句终止作业的方式也可以取消正在执行中的 DDL 作业。 -> + 该操作可以同时取消多个 DDL 作业,可以通过 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句来获取 DDL 作业的 `job_id`。 -> + 如果希望取消的作业已经执行完毕,取消操作将失败。 +> - 在 v6.2.0 之前,只有此操作可以取消 DDL 作业,所有其他操作和环境变化(如机器重启和集群重启)都不能取消这些作业。从 v6.2.0 开始,[`KILL`](/sql-statements/sql-statement-kill.md) 语句也可以通过终止正在进行的 DDL 作业来取消它们。 +> - 此操作可以同时取消多个 DDL 作业。您可以使用 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 作业的 ID。 +> - 如果您要取消的作业已经完成,取消操作将失败。 ## MySQL 兼容性 -`ADMIN CANCEL DDL` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 -## 另请参阅 +## 另请参见 -* [`ADMIN SHOW DDL [JOBS|QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) +* [`ADMIN SHOW DDL [JOBS|JOB QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) diff --git a/sql-statements/sql-statement-admin-check-table-index.md b/sql-statements/sql-statement-admin-check-table-index.md index e6c2868a4f4d..f41c37bd1ba5 100644 --- a/sql-statements/sql-statement-admin-check-table-index.md +++ b/sql-statements/sql-statement-admin-check-table-index.md @@ -1,33 +1,35 @@ --- -title: ADMIN CHECK [TABLE|INDEX] -summary: TiDB 数据库中 ADMIN CHECK [TABLE|INDEX] 的使用概况。 +title: ADMIN CHECK [TABLE|INDEX] | TiDB SQL 语句参考 +summary: TiDB 数据库中 ADMIN 使用概览。 +category: reference --- # ADMIN CHECK [TABLE|INDEX] -`ADMIN CHECK [TABLE|INDEX]` 语句用于校验表中数据和对应索引的一致性。 +`ADMIN CHECK [TABLE|INDEX]` 语句用于检查表和索引的数据一致性。 -该语句不支持: +它不支持以下功能: -- 校验[外键约束](/foreign-key.md)。 -- 当使用[聚簇索引](/clustered-indexes.md)时,校验主键索引。 +- 检查 [FOREIGN KEY 约束](/foreign-key.md)。 +- 如果使用了[聚簇主键](/clustered-indexes.md),则不支持检查 PRIMARY KEY 索引。 -如果执行 `ADMIN CHECK [TABLE|INDEX]` 发现任何问题,你可以删除并重新创建索引来解决。如果问题仍未解决,你可以尝试 [TiDB 支持资源](/support.md)。 +如果 `ADMIN CHECK [TABLE|INDEX]` 发现任何问题,你可以通过删除并重新创建索引来解决这些问题。如果问题仍未解决,你可以[报告 bug](https://docs.pingcap.com/tidb/stable/support)。 ## 原理 -`ADMIN CHECK TABLE` 语句执行以下步骤来校验表: +`ADMIN CHECK TABLE` 语句通过以下步骤检查表: -1. 对每个索引,检查索引中的记录数是否与表中的记录数一致。 -2. 对每个索引,遍历每行的值,并将其与表中的值进行比较。 +1. 对于每个索引,它检查索引中的记录数是否与表中的记录数相同。 -如果使用 `ADMIN CHECK INDEX` 语句,它只会校验指定的索引。 +2. 对于每个索引,它遍历每行中的值并将这些值与表中的值进行比较。 + +如果你使用 `ADMIN CHECK INDEX` 语句,它只检查指定的索引。 ## 语法图 ```ebnf+diagram AdminCheckStmt ::= - 'ADMIN' 'CHECK' ( 'TABLE' TableNameList | 'INDEX' TableName Identifier ( HandleRange ( ',' HandleRange )* )? ) + 'ADMIN' 'CHECK' ( 'TABLE' TableNameList | 'INDEX' TableName Identifier ( HandleRange ( ',' HandleRange )* )? ) TableNameList ::= TableName ( ',' TableName )* @@ -37,30 +39,30 @@ HandleRange ::= '(' Int64Num ',' Int64Num ')' ## 示例 -可以通过 `ADMIN CHECK TABLE` 语句校验 `tbl_name` 表中所有数据和对应索引的一致性: +要检查 `tbl_name` 表中所有数据及其对应索引的一致性,使用 `ADMIN CHECK TABLE`: ```sql ADMIN CHECK TABLE tbl_name [, tbl_name] ...; ``` -若通过一致性校验,则返回空的查询结果;否则返回数据不一致的错误信息。 +如果一致性检查通过,则返回空结果。否则,返回错误消息指示数据不一致。 ```sql ADMIN CHECK INDEX tbl_name idx_name; ``` -以上语句用于对 `tbl_name` 表中 `idx_name` 索引对应列数据和索引数据进行一致性校验。若通过校验,则返回空的查询结果;否则返回数据不一致的错误信息。 +上述语句用于检查 `tbl_name` 表中对应于 `idx_name` 索引的列数据和索引数据的一致性。如果一致性检查通过,则返回空结果;否则,返回错误消息指示数据不一致。 ```sql ADMIN CHECK INDEX tbl_name idx_name (lower_val, upper_val) [, (lower_val, upper_val)] ...; ``` -以上语句用于对 `tbl_name` 表中 `idx_name` 索引对应列数据和索引数据进行一致性校验,并且指定了需要检查的数据范围。若通过校验,则返回空的查询结果;否则返回数据不一致的错误信息。 +上述语句用于检查 `tbl_name` 表中对应于 `idx_name` 索引的列数据和索引数据的一致性,并指定要检查的数据范围。如果一致性检查通过,则返回空结果。否则,返回错误消息指示数据不一致。 ## MySQL 兼容性 -`ADMIN CHECK [TABLE|INDEX]` 语句是 TiDB 对 MySQL 语法的扩展。 +该语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [`ADMIN REPAIR`](/sql-statements/sql-statement-admin.md#admin-repair-table-语句) \ No newline at end of file +* [`ADMIN REPAIR`](/sql-statements/sql-statement-admin.md#admin-repair-statement) diff --git a/sql-statements/sql-statement-admin-checksum-table.md b/sql-statements/sql-statement-admin-checksum-table.md index 20a0f3e2ecbe..65b09939daf1 100644 --- a/sql-statements/sql-statement-admin-checksum-table.md +++ b/sql-statements/sql-statement-admin-checksum-table.md @@ -1,17 +1,30 @@ --- -title: ADMIN CHECKSUM TABLE -summary: TiDB 数据库中 ADMIN CHECKSUM TABLE 的使用概况。 +title: ADMIN CHECKSUM TABLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 ADMIN 的使用概览。 +category: reference --- # ADMIN CHECKSUM TABLE -`ADMIN CHECKSUM TABLE` 语句用于计算表中所有数据和索引的 CRC64 校验和。 +`ADMIN CHECKSUM TABLE` 语句用于计算表的数据和索引的 CRC64 校验和。 -[校验和](/tidb-lightning/tidb-lightning-glossary.md#checksum)是通过表数据和 `table_id` 等属性进行计算得出的。这意味着两张 `table_id` 不同的表即使数据相同,校验和也不相同。 + -当使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 物理模式、[TiDB Data Migration](/dm/dm-overview.md) 或 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 导入完成一张表后,`ADMIN CHECKSUM TABLE
` 语句会默认执行以验证数据完整性。 +[校验和](/tidb-lightning/tidb-lightning-glossary.md#checksum)是基于表数据和属性(如 `table_id`)计算的。这意味着具有相同数据但 `table_id` 值不同的两个表将得到不同的校验和。 -## 语法图 +使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md)、[TiDB Data Migration](/dm/dm-overview.md) 或 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 导入表后,默认会执行 `ADMIN CHECKSUM TABLE
` 来验证数据完整性。 + + + + + +[校验和](https://docs.pingcap.com/tidb/stable/tidb-lightning-glossary#checksum)是基于表数据和属性(如 `table_id`)计算的。这意味着具有相同数据但 `table_id` 值不同的两个表将得到不同的校验和。 + +使用 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 导入表后,默认会执行 `ADMIN CHECKSUM TABLE
` 来验证数据完整性。 + + + +## 语法 ```ebnf+diagram AdminChecksumTableStmt ::= @@ -29,21 +42,21 @@ TableNameList ::= CREATE TABLE t1(id INT PRIMARY KEY); ``` -插入一些数据: +向 `t1` 插入一些数据: ```sql INSERT INTO t1 VALUES (1),(2),(3); ``` -计算表 `t1` 的校验和: +计算 `t1` 的校验和: ```sql ADMIN CHECKSUM TABLE t1; ``` -输出结果示例如下: +输出结果如下: -``` +```sql +---------+------------+----------------------+-----------+-------------+ | Db_name | Table_name | Checksum_crc64_xor | Total_kvs | Total_bytes | +---------+------------+----------------------+-----------+-------------+ @@ -54,4 +67,4 @@ ADMIN CHECKSUM TABLE t1; ## MySQL 兼容性 -`ADMIN CHECKSUM TABLE` 语句是 TiDB 对 MySQL 语法的扩展。 +该语句是 TiDB 对 MySQL 语法的扩展。 diff --git a/sql-statements/sql-statement-admin-cleanup.md b/sql-statements/sql-statement-admin-cleanup.md index c9a3d7a6645f..3e0fca746ff7 100644 --- a/sql-statements/sql-statement-admin-cleanup.md +++ b/sql-statements/sql-statement-admin-cleanup.md @@ -1,13 +1,13 @@ --- title: ADMIN CLEANUP INDEX -summary: TiDB 数据库中 ADMIN CLEANUP 的使用概况。 +summary: TiDB 数据库中 ADMIN CLEANUP 的使用概览。 --- # ADMIN CLEANUP INDEX -`ADMIN CLEANUP INDEX` 语句用于在表发生行数据和索引的一致性故障时,删除表中多余的索引,使表的行数据和索引恢复一致状态。注意,该语法尚不支持[外键约束](/foreign-key.md)。 +`ADMIN CLEANUP INDEX` 语句用于在表的数据和索引不一致时删除表中的冗余索引。请注意,此语法目前还不支持[外键约束](/foreign-key.md)。 -## 语法图 +## 语法 ```ebnf+diagram AdminCleanupStmt ::= @@ -19,7 +19,7 @@ TableNameList ::= ## 示例 -假设由于一些原因(例如灾难恢复场景,集群中丢失了部分行数据),数据库中的 `tbl` 表出现数据和索引不一致现象: +假设数据库中的 `tbl` 表由于某些原因(例如,在灾难恢复场景中集群中丢失了一些行数据)导致数据和索引不一致: ```sql SELECT * FROM tbl; @@ -29,13 +29,13 @@ ADMIN CHECK INDEX tbl idx ; ERROR 1105 (HY000): handle &kv.CommonHandle{encoded:[]uint8{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8}, colEndOffsets:[]uint16{0xa}}, index:types.Datum{k:0x5, decimal:0x0, length:0x0, i:0, collation:"utf8mb4_bin", b:[]uint8{0x0}, x:interface {}(nil)} != record: ``` -从 `SELECT` 查询的错误信息可以看到,`tbl` 表中包含 2 条行数据和 3 条索引数据,这意味着行数据与索引数据出现了不一致故障,同时至少有 1 条索引处于悬空状态。此时可以使用 `ADMIN CLEANUP INDEX` 语句删除悬空的索引: +从 `SELECT` 查询的错误消息可以看出,`tbl` 表包含两行数据和三行索引数据,这意味着行数据和索引数据不一致。同时,至少有一个索引处于悬空状态。在这种情况下,您可以使用 `ADMIN CLEANUP INDEX` 语句删除悬空索引: ```sql ADMIN CLEANUP INDEX tbl idx; ``` -执行结果示例如下: +执行结果如下: ```sql ADMIN CLEANUP INDEX tbl idx; @@ -46,29 +46,48 @@ ADMIN CLEANUP INDEX tbl idx; +---------------+ ``` -此时,可以重新使用 `ADMIN CHECK INDEX` 语句检查数据索引的一致性,验证数据是否恢复到正常状态: +您可以再次执行 `ADMIN CHECK INDEX` 语句来检查数据和索引的一致性,并验证数据是否已恢复到正常状态: ```sql ADMIN CHECK INDEX tbl idx; Query OK, 0 rows affected (0.01 sec) ``` + + > **注意:** > -> 当由于副本丢失导致数据索引出现不一致时: +> 当由于副本丢失导致数据和索引不一致时: > -> - 通常行数据与索引数据都有丢失,此时需要同时使用 `ADMIN CLEANUP INDEX` 与 [`ADMIN RECOVER INDEX`](/sql-statements/sql-statement-admin-recover.md) 语句保证行数据与索引数据的一致性。 -> - `ADMIN CLEANUP INDEX` 总是单并发执行。在表数据量大时,建议通过重建索引的方式进行索引数据的恢复。 -> - `ADMIN CLEANUP INDEX` 在执行期间,不会为对应的表或索引记录加锁,TiDB 允许其他的会话同时对表记录进行更新或修改。然而,在此情况下,`ADMIN CLEANUP INDEX` 可能无法正确处理所有表记录。因此,在执行 `ADMIN CLEANUP INDEX` 时,请避免同时修改表数据。 -> - 若你使用 TiDB 企业版,此时建议[提交工单](https://support.pingcap.cn/)联系 PingCAP 支持工程师进行处理。 +> - 可能会同时丢失行数据和索引数据。要恢复一致性,需要同时使用 `ADMIN CLEANUP INDEX` 和 [`ADMIN RECOVER INDEX`](/sql-statements/sql-statement-admin-recover.md) 语句。 +> - `ADMIN CLEANUP INDEX` 语句始终以单线程执行。当表数据较大时,建议通过重建索引来恢复索引数据。 +> - 执行 `ADMIN CLEANUP INDEX` 语句时,相应的表或索引不会被锁定,TiDB 允许其他会话同时修改表记录。但是,在这种情况下,`ADMIN CLEANUP INDEX` 可能无法正确处理所有表记录。因此,执行 `ADMIN CLEANUP INDEX` 时,应避免同时修改表数据。 +> - 如果您使用 TiDB 企业版,可以[提交请求](/support.md)联系支持工程师寻求帮助。 > -> `ADMIN CLEANUP INDEX` 命令不具有原子性:若该命令在执行期间中断,建议重新执行直到成功。 +> `ADMIN CLEANUP INDEX` 语句不是原子性的:如果语句在执行过程中被中断,建议重新执行直到成功。 + + + + + +> **注意:** +> +> 当由于副本丢失导致数据和索引不一致时: +> +> - 可能会同时丢失行数据和索引数据。要恢复一致性,需要同时使用 `ADMIN CLEANUP INDEX` 和 [`ADMIN RECOVER INDEX`](/sql-statements/sql-statement-admin-recover.md) 语句。 +> - `ADMIN CLEANUP INDEX` 语句始终以单线程执行。当表数据较大时,建议通过重建索引来恢复索引数据。 +> - 执行 `ADMIN CLEANUP INDEX` 语句时,相应的表或索引不会被锁定,TiDB 允许其他会话同时修改表记录。但是,在这种情况下,`ADMIN CLEANUP INDEX` 可能无法正确处理所有表记录。因此,执行 `ADMIN CLEANUP INDEX` 时,应避免同时修改表数据。 +> - 如果您使用 TiDB 企业版,可以[提交请求](https://tidb.support.pingcap.com/)联系支持工程师寻求帮助。 +> +> `ADMIN CLEANUP INDEX` 语句不是原子性的:如果语句在执行过程中被中断,建议重新执行直到成功。 + + ## MySQL 兼容性 -`ADMIN CLEANUP INDEX` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 -## 另请参阅 +## 另请参见 * [`ADMIN CHECK TABLE/INDEX`](/sql-statements/sql-statement-admin-check-table-index.md) * [`ADMIN RECOVER INDEX`](/sql-statements/sql-statement-admin-recover.md) diff --git a/sql-statements/sql-statement-admin-pause-ddl.md b/sql-statements/sql-statement-admin-pause-ddl.md index 2e775465c96b..6f8624aaa7c7 100644 --- a/sql-statements/sql-statement-admin-pause-ddl.md +++ b/sql-statements/sql-statement-admin-pause-ddl.md @@ -1,25 +1,19 @@ --- title: ADMIN PAUSE DDL JOBS -summary: TiDB 数据库中 ADMIN PAUSE DDL JOBS 的使用概况。 +summary: TiDB 数据库中 ADMIN PAUSE DDL JOBS 的使用概述。 --- # ADMIN PAUSE DDL JOBS -`ADMIN PAUSE DDL` 语句用于暂停当前正在运行的 DDL 作业。可以通过 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 作业的 `job_id`。 +`ADMIN PAUSE DDL` 允许你暂停正在运行的 DDL 作业。可以通过运行 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 找到 `job_id`。 -该语句可用于暂停已经发起但未执行完成的 DDL 任务。成功暂停后,执行 DDL 任务的 SQL 语句不会立即返回,表现为正在执行。如果尝试暂停一个已经完成的 DDL 任务,会在 `RESULT` 列看到 `DDL Job:90 not found` 的错误,表示该任务已从 DDL 等待队列中被移除。 - -> **注意:** -> -> + 该操作可以暂停 DDL 作业,但除版本升级外,其他操作和环境变更(例如机器重启、集群重启)不会暂停 DDL 作业。 -> + 版本升级时,正在运行的 DDL 作业将被暂停,同时在升级过程中发起的 DDL 作业也将被暂停。升级结束后,所有已暂停的 DDL 作业将恢复执行。升级过程中的操作为自动进行,详情查阅 [TiDB 平滑升级](/smooth-upgrade-tidb.md)。 -> + 该操作可以同时暂停多个 DDL 作业,可以通过 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句来获取 DDL 作业的 `job_id`。 +你可以使用此语句暂停已发出但尚未完成执行的 DDL 作业。暂停后,执行 DDL 作业的 SQL 语句不会立即返回,而是看起来仍在运行。如果你尝试暂停已完成的 DDL 作业,你会在 `RESULT` 列中看到 `DDL Job:90 not found` 错误,这表示该作业已从 DDL 等待队列中移除。 ## 语法图 ```ebnf+diagram AdminPauseDDLStmt ::= - 'ADMIN' 'PAUSE' 'DDL' 'JOBS' NumList + 'ADMIN' 'PAUSE' 'DDL' 'JOBS' NumList NumList ::= Int64Num ( ',' Int64Num )* @@ -27,19 +21,38 @@ NumList ::= ## 示例 -可以通过 `ADMIN PAUSE DDL JOBS` 语句暂停当前正在运行的 DDL 作业,并返回对应作业是否暂停成功,直到被 `ADMIN RESUME DDL JOBS` 恢复: +`ADMIN PAUSE DDL JOBS` 暂停当前正在运行的 DDL 作业,并返回作业是否成功暂停。可以通过 `ADMIN RESUME DDL JOBS` 恢复作业。 ```sql ADMIN PAUSE DDL JOBS job_id [, job_id] ...; ``` -如果暂停失败,会显示失败的具体原因。 +如果暂停失败,会显示具体的失败原因。 + + + +> **注意:** +> +> + 此语句可以暂停 DDL 作业,但除了集群升级外,其他操作和环境变化(如机器重启和集群重启)不会暂停 DDL 作业。 +> + 在集群升级期间,正在进行的 DDL 作业会被暂停,升级期间发起的 DDL 作业也会被暂停。升级完成后,所有暂停的 DDL 作业将恢复。升级期间的暂停和恢复操作是自动进行的。详情请参见 [TiDB 平滑升级](/smooth-upgrade-tidb.md)。 +> + 此语句可以暂停多个 DDL 作业。你可以使用 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 作业的 `job_id`。 + + + + +> **注意:** +> +> + 此语句可以暂停 DDL 作业,但除了集群升级外,其他操作和环境变化(如机器重启和集群重启)不会暂停 DDL 作业。 +> + 在集群升级期间,正在进行的 DDL 作业会被暂停,升级期间发起的 DDL 作业也会被暂停。升级完成后,所有暂停的 DDL 作业将恢复。升级期间的暂停和恢复操作是自动进行的。详情请参见 [TiDB 平滑升级](https://docs.pingcap.com/tidb/stable/smooth-upgrade-tidb)。 +> + 此语句可以暂停多个 DDL 作业。你可以使用 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 作业的 `job_id`。 + + ## MySQL 兼容性 -`ADMIN PAUSE DDL JOBS` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 -## 另请参阅 +## 另请参见 * [`ADMIN SHOW DDL [JOBS|QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) * [`ADMIN CANCEL DDL`](/sql-statements/sql-statement-admin-cancel-ddl.md) diff --git a/sql-statements/sql-statement-admin-recover.md b/sql-statements/sql-statement-admin-recover.md index 358eba3a9f35..39a4f78ae116 100644 --- a/sql-statements/sql-statement-admin-recover.md +++ b/sql-statements/sql-statement-admin-recover.md @@ -1,11 +1,11 @@ --- title: ADMIN RECOVER INDEX -summary: TiDB 数据库中 ADMIN RECOVER INDEX 的使用概况。 +summary: TiDB 数据库中 ADMIN RECOVER INDEX 的使用概览。 --- # ADMIN RECOVER INDEX -`ADMIN RECOVER INDEX` 语句用于在表发生行数据和索引的一致性故障时,根据表中多余的索引,使表的行数据和索引重新恢复到一致状态。注意,该语法尚不支持[外键约束](/foreign-key.md)。 +当行数据和索引数据不一致时,你可以使用 `ADMIN RECOVER INDEX` 语句基于冗余索引恢复一致性。注意,此语法目前还不支持[外键约束](/foreign-key.md)。 ## 语法图 @@ -16,7 +16,7 @@ AdminRecoverStmt ::= ## 示例 -假设由于一些原因(例如灾难恢复场景,集群中丢失了部分索引数据),数据库中的 `tbl` 表出现行数据和索引不一致现象: +假设数据库中的 `tbl` 表由于某些原因(例如,在灾难恢复场景中集群中的某些行数据丢失)导致行数据和索引不一致: ```sql SELECT * FROM tbl; @@ -26,13 +26,13 @@ ADMIN CHECK INDEX tbl idx ; ERROR 1105 (HY000): handle &kv.CommonHandle{encoded:[]uint8{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8}, colEndOffsets:[]uint16{0xa}}, index:types.Datum{k:0x5, decimal:0x0, length:0x0, i:0, collation:"utf8mb4_bin", b:[]uint8{0x0}, x:interface {}(nil)} != record: ``` -从 `SELECT` 查询的错误信息可以看到,`tbl` 表中包含 3 条行数据和 2 条索引数据,这意味着行数据与索引数据出现了不一致故障,同时至少有 1 条行数据缺少了对应的索引。此时可以使用 `ADMIN RECOVER INDEX` 语句补充缺少的索引: +从 `SELECT` 查询的错误消息可以看出,`tbl` 表包含三行数据和两行索引数据,这意味着行数据和索引数据不一致。同时,至少有一行数据没有对应的索引。在这种情况下,你可以使用 `ADMIN RECOVER INDEX` 语句来补充缺失的索引: ```sql ADMIN RECOVER INDEX tbl idx; ``` -执行结果示例如下: +执行结果如下: ```sql ADMIN RECOVER INDEX tbl idx; @@ -44,27 +44,46 @@ ADMIN RECOVER INDEX tbl idx; 1 row in set (0.00 sec) ``` -此时,可以重新使用 `ADMIN CHECK INDEX` 语句对数据索引的一致性进行检查,验证数据恢复到正常状态: +你可以再次执行 `ADMIN CHECK INDEX` 语句来检查数据和索引的一致性,并验证数据是否已恢复正常: ```sql ADMIN CHECK INDEX tbl idx; Query OK, 0 rows affected (0.01 sec) ``` + + > **注意:** > -> 当由于副本丢失导致数据索引出现不一致时: +> 当由于副本丢失导致数据和索引不一致时: > -> - 通常行数据与索引数据都有丢失,此时需要同时使用 [`ADMIN CLEANUP INDEX`](/sql-statements/sql-statement-admin-cleanup.md) 与 `ADMIN RECOVER INDEX` 语句保证行数据与索引数据的一致性。 -> - `ADMIN RECOVER INDEX` 总是单并发执行。在表数据量大时,建议通过重建索引的方式进行索引数据的恢复。 -> - `ADMIN RECOVER INDEX` 在执行期间,不会为对应的表或索引记录加锁,这意味着 TiDB 允许同时有其他的会话对表记录进行更新或修改。然而,在此情况下 `ADMIN RECOVER INDEX` 可能无法正确处理所有数据。因此,在执行 `ADMIN RECOVER INDEX` 时,请避免同时修改表数据。 -> - 若你使用 TiDB 企业版,此时建议[提交工单](https://support.pingcap.cn/)联系 PingCAP 支持工程师进行处理。 +> - 可能同时存在行数据和索引数据的丢失。要解决此问题,请同时使用 [`ADMIN CLEANUP INDEX`](/sql-statements/sql-statement-admin-cleanup.md) 和 `ADMIN RECOVER INDEX` 语句来恢复行数据和索引数据的一致性。 +> - `ADMIN RECOVER INDEX` 语句始终以单线程执行。当表数据较大时,建议通过重建索引来恢复索引数据。 +> - 执行 `ADMIN RECOVER INDEX` 语句时,相应的表或索引不会被锁定,TiDB 允许其他会话同时修改表记录。但是,在这种情况下,`ADMIN RECOVER INDEX` 可能无法正确处理所有表记录。因此,执行 `ADMIN RECOVER INDEX` 时,应避免同时修改表数据。 +> - 如果你使用 TiDB 企业版,可以[提交请求](/support.md)联系支持工程师寻求帮助。 > -> `ADMIN RECOVER INDEX` 命令不具有原子性:若该命令在执行期间中断,建议重新执行直到成功。 +> `ADMIN RECOVER INDEX` 语句不是原子性的:如果语句在执行过程中被中断,建议重新执行直到成功。 + + + + + +> **注意:** +> +> 当由于副本丢失导致数据和索引不一致时: +> +> - 可能同时存在行数据和索引数据的丢失。要解决此问题,请同时使用 [`ADMIN CLEANUP INDEX`](/sql-statements/sql-statement-admin-cleanup.md) 和 `ADMIN RECOVER INDEX` 语句来恢复行数据和索引数据的一致性。 +> - `ADMIN RECOVER INDEX` 语句始终以单线程执行。当表数据较大时,建议通过重建索引来恢复索引数据。 +> - 执行 `ADMIN RECOVER INDEX` 语句时,相应的表或索引不会被锁定,TiDB 允许其他会话同时修改表记录。但是,在这种情况下,`ADMIN RECOVER INDEX` 可能无法正确处理所有表记录。因此,执行 `ADMIN RECOVER INDEX` 时,应避免同时修改表数据。 +> - 如果你使用 TiDB 企业版,可以[提交请求](https://tidb.support.pingcap.com/)联系支持工程师寻求帮助。 +> +> `ADMIN RECOVER INDEX` 语句不是原子性的:如果语句在执行过程中被中断,建议重新执行直到成功。 + + ## MySQL 兼容性 -`ADMIN RECOVER INDEX` 语句是 TiDB 对 MySQL 语法的扩展。 +该语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 diff --git a/sql-statements/sql-statement-admin-resume-ddl.md b/sql-statements/sql-statement-admin-resume-ddl.md index 57dc2b65b1f5..6c9a78795dfb 100644 --- a/sql-statements/sql-statement-admin-resume-ddl.md +++ b/sql-statements/sql-statement-admin-resume-ddl.md @@ -1,27 +1,19 @@ --- title: ADMIN RESUME DDL JOBS -summary: TiDB 数据库中 ADMIN RESUME DDL 的使用概况。 +summary: TiDB 数据库中 ADMIN RESUME DDL 的使用概览。 --- # ADMIN RESUME DDL JOBS -`ADMIN RESUME DDL` 语句用于恢复当前处于暂停中的 DDL 作业。可以通过 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 作业的 `job_id`。 +`ADMIN RESUME DDL` 允许你恢复已暂停的 DDL 任务。你可以通过运行 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 找到 `job_id`。 -该语句可用于恢复处于暂停中的 DDL 任务。成功恢复后,执行 DDL 任务的 SQL 语句会一直表现为正在执行。如果尝试恢复已经完成的 DDL 任务,会在 `RESULT` 列看到 `DDL Job:90 not found` 的错误,表示该任务已从 DDL 等待队列中被移除。 +你可以使用此语句恢复已暂停的 DDL 任务。恢复完成后,执行 DDL 任务的 SQL 语句继续显示为正在执行。如果你尝试恢复已完成的 DDL 任务,你将在 `RESULT` 列中看到 `DDL Job:90 not found` 错误,这表示该任务已从 DDL 等待队列中移除。 -> **注意:** -> -> + 该操作可以恢复已被暂停的 DDL 作业。 -> + 版本升级时,正在运行的 DDL 作业将被暂停,同时在升级过程中发起的 DDL 作业也将被暂停。升级结束后,所有已暂停的 DDL 作业将恢复执行。升级过程中的操作为自动进行,详情查阅 [TiDB 平滑升级](/smooth-upgrade-tidb.md)。 -> + 该操作可以同时恢复多个 DDL 作业,可以通过 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句来获取 DDL 作业的 `job_id`。 -> + 处于非暂停状态中的作业无法被恢复,操作将失败。 -> + 如果重复恢复同一个 DDL 作业,会报错 `Error Number: 8261`。 - -## 语法图 +## 语法 ```ebnf+diagram AdminResumeDDLStmt ::= - 'ADMIN' 'RESUME' 'DDL' 'JOBS' NumList + 'ADMIN' 'RESUME' 'DDL' 'JOBS' NumList NumList ::= Int64Num ( ',' Int64Num )* @@ -29,17 +21,38 @@ NumList ::= ## 示例 -可以通过 `ADMIN RESUME DDL JOBS` 语句恢复当前处于暂停中的 DDL 作业,并返回对应作业是否恢复执行: +`ADMIN RESUME DDL JOBS` 恢复当前暂停的 DDL 任务,并返回任务是否恢复成功。 ```sql ADMIN RESUME DDL JOBS job_id [, job_id] ...; ``` -如果恢复失败,会显示失败的具体原因。 +如果恢复失败,将显示具体的失败原因。 + + + +> **注意:** +> +> + 在集群升级期间,正在进行的 DDL 任务会被暂停,升级期间发起的 DDL 任务也会被暂停。升级完成后,所有暂停的 DDL 任务将恢复。升级期间的暂停和恢复操作是自动进行的。详情请参阅 [TiDB 平滑升级](/smooth-upgrade-tidb.md)。 +> + 此语句可以恢复多个 DDL 任务。你可以使用 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 任务的 `job_id`。 +> + 处于其他状态(非 `paused`)的 DDL 任务无法恢复,恢复操作将失败。 +> + 如果你多次尝试恢复同一个任务,TiDB 会报错 `Error Number: 8261`。 + + + + +> **注意:** +> +> + 在集群升级期间,正在进行的 DDL 任务会被暂停,升级期间发起的 DDL 任务也会被暂停。升级完成后,所有暂停的 DDL 任务将恢复。升级期间的暂停和恢复操作是自动进行的。详情请参阅 [TiDB 平滑升级](https://docs.pingcap.com/tidb/stable/smooth-upgrade-tidb)。 +> + 此语句可以恢复多个 DDL 任务。你可以使用 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md) 语句获取 DDL 任务的 `job_id`。 +> + 处于其他状态(非 `paused`)的 DDL 任务无法恢复,恢复操作将失败。 +> + 如果你多次尝试恢复同一个任务,TiDB 会报错 `Error Number: 8261`。 + + ## MySQL 兼容性 -`ADMIN RESUME DDL` 语句是 TiDB 对 MySQL 语法的扩展。 +该语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 diff --git a/sql-statements/sql-statement-admin-show-ddl.md b/sql-statements/sql-statement-admin-show-ddl.md index 83c1fcdca0f5..69d5af951227 100644 --- a/sql-statements/sql-statement-admin-show-ddl.md +++ b/sql-statements/sql-statement-admin-show-ddl.md @@ -1,11 +1,11 @@ --- -title: ADMIN SHOW DDL [JOBS|JOB QUERIES] -summary: TiDB 数据库中 ADMIN SHOW DDL [JOBS|JOB QUERIES] 的使用概况。 +title: ADMIN SHOW DDL [JOBS|JOB QUERIES] | TiDB SQL 语句参考 +summary: TiDB 数据库中 ADMIN 使用概览。 --- # ADMIN SHOW DDL [JOBS|JOB QUERIES] -`ADMIN SHOW DDL [JOBS|JOB QUERIES]` 语句显示了正在运行和最近完成的 DDL 作业的信息。 +`ADMIN SHOW DDL [JOBS|JOB QUERIES]` 语句显示正在运行和最近完成的 DDL 作业的信息。 ## 语法图 @@ -29,14 +29,14 @@ WhereClauseOptional ::= ### `ADMIN SHOW DDL` -可以通过 `ADMIN SHOW DDL` 语句查看当前正在运行的 DDL 作业状态,包括当前 schema 版本号、Owner 的 DDL ID 和地址、正在执行的 DDL 任务和 SQL、当前 TiDB 实例的 DDL ID。该语句返回的结果字段描述如下: +要查看当前正在运行的 DDL 作业的状态,使用 `ADMIN SHOW DDL`。输出包括当前的 schema 版本、owner 的 DDL ID 和地址、正在运行的 DDL 作业和 SQL 语句,以及当前 TiDB 实例的 DDL ID。返回结果字段说明如下: -- `SCHEMA_VER`:schema 版本号。 -- `OWNER_ID`:DDL Owner 的 UUID。参见 [`TIDB_IS_DDL_OWNER()`](/functions-and-operators/tidb-functions.md)。 -- `OWNER_ADDRESS`:DDL Owner 的 IP 地址。 +- `SCHEMA_VER`:表示 schema 的版本号。 +- `OWNER_ID`:DDL owner 的 UUID。另请参阅 [`TIDB_IS_DDL_OWNER()`](/functions-and-operators/tidb-functions.md)。 +- `OWNER_ADDRESS`:DDL owner 的 IP 地址。 - `RUNNING_JOBS`:正在运行的 DDL 作业的详细信息。 -- `SELF_ID`:当前连接的 TiDB 节点的 UUID。如果 `SELF_ID` 与 `OWNER_ID` 相同,这意味着你当前连接的是 DDL Owner。 -- `QUERY`:查询语句。 +- `SELF_ID`:当前连接的 TiDB 节点的 UUID。如果 `SELF_ID` 与 `OWNER_ID` 相同,表示你当前连接的是 DDL owner。 +- `QUERY`:查询的语句。 ```sql ADMIN SHOW DDL\G; @@ -55,48 +55,49 @@ OWNER_ADDRESS: 0.0.0.0:4000 ### `ADMIN SHOW DDL JOBS` -`ADMIN SHOW DDL JOBS` 语句用于查看当前 DDL 作业队列中的所有结果(包括正在运行以及等待运行的任务)以及已执行完成的 DDL 作业队列中的最近十条结果。该语句的返回结果字段描述如下: - -- `JOB_ID`:每个 DDL 操作对应一个 DDL 任务,`JOB_ID` 全局唯一。 -- `DB_NAME`:执行 DDL 操作的数据库的名称。 -- `TABLE_NAME`:执行 DDL 操作的表的名称。 -- `JOB_TYPE`:DDL 任务的类型。常见的任务类型包括: - - `create schema`:[`CREATE SCHEMA`](/sql-statements/sql-statement-create-database.md) 操作。 - - `create table`:[`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 操作。 - - `create view`:[`CREATE VIEW`](/sql-statements/sql-statement-create-view.md) 操作。 - - `ingest`:通过 [`tidb_ddl_enable_fast_reorg`](/system-variables.md#tidb_ddl_enable_fast_reorg-从-v630-版本开始引入) 配置的加速索引回填的 ingest 任务。 - - `txn`:基本的事务性回填。 - - `add index /* txn-merge */`:在回填完成时,将临时索引与原始索引合并的事务性回填。 -- `SCHEMA_STATE`:DDL 所操作的 schema 对象的当前状态。如果 `JOB_TYPE` 是 `ADD INDEX`,则为索引的状态;如果是 `ADD COLUMN`,则为列的状态;如果是 `CREATE TABLE`,则为表的状态。常见的状态有以下几种: - - `none`:表示不存在。一般 `DROP` 操作或者 `CREATE` 操作失败回滚后,会变为 `none` 状态。 - - `delete only`、`write only`、`delete reorganization`、`write reorganization`:这四种状态是中间状态,具体含义请参考 [TiDB 中在线 DDL 异步变更的原理](/ddl-introduction.md#tidb-在线-ddl-异步变更的原理)。由于中间状态转换很快,一般操作中看不到这几种状态,只有执行 `ADD INDEX` 操作时能看到处于 `write reorganization` 状态,表示正在添加索引数据。 - - `public`:表示存在且对用户可用。一般 `CREATE TABLE` 和 `ADD INDEX`(或 `ADD COLUMN`)等操作完成后,会变为 `public` 状态,表示新建的表、列、索引可以正常读写了。 +`ADMIN SHOW DDL JOBS` 语句用于查看当前 DDL 作业队列中的所有结果,包括正在运行和排队的任务,以及已完成的 DDL 作业队列中的最新十个结果。返回结果字段说明如下: + +- `JOB_ID`:每个 DDL 操作对应一个 DDL 作业。`JOB_ID` 是全局唯一的。 +- `DB_NAME`:执行 DDL 操作的数据库名称。 +- `TABLE_NAME`:执行 DDL 操作的表名。 +- `JOB_TYPE`:DDL 操作的类型。常见的作业类型包括: + - `create schema`:用于 [`CREATE SCHEMA`](/sql-statements/sql-statement-create-database.md) 操作。 + - `create table`:用于 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 操作。 + - `create view`:用于 [`CREATE VIEW`](/sql-statements/sql-statement-create-view.md) 操作。 + - `ingest`:使用由 [`tidb_ddl_enable_fast_reorg`](/system-variables.md#tidb_ddl_enable_fast_reorg-new-in-v630) 配置的加速索引回填。 + - `txn`:基本事务回填。 + - `add index /* txn-merge */`:使用临时索引的事务回填,该索引在回填完成后与原始索引合并。 +- `SCHEMA_STATE`:DDL 操作的 schema 对象的当前状态。如果 `JOB_TYPE` 是 `ADD INDEX`,则是索引的状态;如果是 `ADD COLUMN`,则是列的状态;如果是 `CREATE TABLE`,则是表的状态。常见状态包括: + - `none`:表示不存在。通常在 `DROP` 操作之后或 `CREATE` 操作失败并回滚后,会变成 `none` 状态。 + - `delete only`、`write only`、`delete reorganization`、`write reorganization`:这四个状态是中间状态。有关它们的具体含义,请参阅[TiDB 中在线 DDL 异步变更的工作原理](/ddl-introduction.md#tidb-中在线-ddl-异步变更的工作原理)。由于中间状态转换很快,这些状态在操作过程中通常不可见。只有在执行 `ADD INDEX` 操作时才能看到 `write reorganization` 状态,表示正在添加索引数据。 + - `public`:表示存在且可供用户使用。通常在 `CREATE TABLE` 和 `ADD INDEX`(或 `ADD COLUMN`)操作完成后,会变成 `public` 状态,表示新创建的表、列和索引可以正常读写。 - `SCHEMA_ID`:执行 DDL 操作的数据库的 ID。 - `TABLE_ID`:执行 DDL 操作的表的 ID。 -- `ROW_COUNT`:执行 `ADD INDEX` 操作时,当前已经添加完成的数据行数。 +- `ROW_COUNT`:执行 `ADD INDEX` 操作时,表示已添加的数据行数。 - `CREATE_TIME`:DDL 操作的创建时间。 - `START_TIME`:DDL 操作的开始时间。 - `END_TIME`:DDL 操作的结束时间。 -- `STATE`:DDL 操作的状态。常见的状态有以下几种: - - `none`:表示该操作尚未开始。 - - `queueing`:表示该操作任务已经进入 DDL 任务队列中,但尚未执行,因为还在排队等待前面的 DDL 任务完成。另一种原因可能是执行 `DROP` 操作后,`queueing` 状态会变为 `done` 状态,但是很快会更新为 `synced` 状态,表示所有 TiDB 实例都已经同步到该状态。 - - `running`:表示该操作正在执行。 - - `synced`:表示该操作已经执行成功,且所有 TiDB 实例都已经同步该状态。 - - `rollback done`:表示该操作执行失败,回滚完成。 - - `rollingback`:表示该操作执行失败,正在回滚。 - - `cancelling`:表示正在取消该操作。这个状态只有在用 [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) 命令取消 DDL 任务时才会出现。 - - `cancelled`:表示该操作已经取消。 - - `pausing`:表示正在暂停该操作。 - - `paused`:表示 DDL 已被暂停运行。这个状态只有在用 [`ADMIN PAUSED DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md) 命令暂停 DDL 任务时才会出现。可以通过 [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md) 命令进行恢复运行。 - - `done`:表示该操作在 TiDB owner 节点已经执行成功,但其他 TiDB 节点还没有同步该 DDL 任务所执行的变更。 - -示例如下: +- `STATE`:DDL 操作的状态。常见状态包括: + - `none`:表示操作尚未开始。 + - `queueing`:表示操作作业已进入 DDL 作业队列但尚未执行,因为它仍在等待早期的 DDL 作业完成。另一个原因可能是执行 `DROP` 操作后,`queueing` 状态会变成 `done` 状态,但很快会更新为 `synced` 状态,表示所有 TiDB 实例都已同步到该状态。 + - `running`:表示正在执行操作。 + - `synced`:表示操作已成功执行,所有 TiDB 实例都已同步到此状态。 + - `rollback done`:表示操作失败且回滚已完成。 + - `rollingback`:表示操作失败且正在回滚。 + - `cancelling`:表示正在取消操作。此状态仅在使用 [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) 命令取消 DDL 作业时出现。 + - `cancelled`:表示操作已被取消。 + - `pausing`:表示正在暂停操作。 + - `paused`:表示操作已暂停。此状态仅在使用 [`ADMIN PAUSED DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md) 命令暂停 DDL 作业时出现。你可以使用 [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md) 命令恢复 DDL 作业。 + - `done`:表示操作已在 TiDB owner 节点上成功执行,但其他 TiDB 节点尚未同步此 DDL 作业执行的更改。 + +以下示例显示 `ADMIN SHOW DDL JOBS` 的结果: ```sql ADMIN SHOW DDL JOBS; ``` ```sql +mysql> ADMIN SHOW DDL JOBS; +--------+---------+--------------------+--------------+----------------------+-----------+----------+-----------+-----------------------------------------------------------------+---------+ | JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | CREATE_TIME | START_TIME | END_TIME | STATE | +--------+---------+--------------------+--------------+----------------------+-----------+----------+-----------+---------------------+-------------------------------------------+---------+ @@ -116,26 +117,26 @@ ADMIN SHOW DDL JOBS; 12 rows in set (0.00 sec) ``` -由上述 `ADMIN` 查询结果可知: +从上面的输出可以看出: -- `job_id` 为 59 的 DDL 作业当前正在进行中(`STATE` 列显示为 `running`)。`SCHEMA_STATE` 列显示了表当前处于 `write reorganization` 状态,一旦任务完成,将更改为 `public`,以便用户会话可以公开观察到状态变更。`end_time` 列显示为 `NULL`,表明当前作业的完成时间未知。 +- 作业 59 当前正在进行中(`STATE` 为 `running`)。schema 状态当前为 `write reorganization`,但一旦任务完成,将切换到 `public` 以表示用户会话可以公开观察到此更改。`end_time` 列也是 `NULL`,表示当前不知道作业的完成时间。 -- `job_id` 为 60 的 `JOB_TYPE` 显示为 `add index`,表明正在排队等待 `job_id` 为 59 的作业完成。当作业 59 完成时,作业 60 的 `STATE` 将更改为 `running`。 +- 作业 60 是一个 `add index` 作业,当前正在排队等待作业 59 完成。当作业 59 完成时,作业 60 的 `STATE` 将切换为 `running`。 -- 对于破坏性的更改(例如删除索引或删除表),当作业完成时,`SCHEMA_STATE` 将变为 `none`。对于附加更改,`SCHEMA_STATE` 将变为 `public`。 +- 对于删除索引或删除表等破坏性更改,作业完成时 `SCHEMA_STATE` 将变为 `none`。对于添加性更改,`SCHEMA_STATE` 将变为 `public`。 -若要限制表中显示的行数,可以指定 `NUM` 和 `WHERE` 条件: +要限制显示的行数,可以指定数字和 where 条件: ```sql ADMIN SHOW DDL JOBS [NUM] [WHERE where_condition]; ``` -* `NUM`:用于查看已经执行完成的 DDL 作业队列中最近 `NUM` 条结果;未指定时,默认值为 10。 -* `WHERE`:`WHERE` 子句,用于添加过滤条件。 +* `NUM`:查看已完成的 DDL 作业队列中的最后 `NUM` 个结果。如果未指定,`NUM` 默认为 10。 +* `WHERE`:添加过滤条件。 ### `ADMIN SHOW DDL JOB QUERIES` -`ADMIN SHOW DDL JOB QUERIES` 语句用于查看 `job_id` 对应的 DDL 任务的原始 SQL 语句: +要查看与 `job_id` 对应的 DDL 作业的原始 SQL 语句,使用 `ADMIN SHOW DDL JOB QUERIES`: ```sql ADMIN SHOW DDL JOBS; @@ -143,7 +144,7 @@ ADMIN SHOW DDL JOB QUERIES 51; ``` ```sql -ADMIN SHOW DDL JOB QUERIES 51; +mysql> ADMIN SHOW DDL JOB QUERIES 51; +--------------------------------------------------------------+ | QUERY | +--------------------------------------------------------------+ @@ -152,64 +153,64 @@ ADMIN SHOW DDL JOB QUERIES 51; 1 row in set (0.02 sec) ``` -只能在 DDL 历史作业队列中最近十条结果中搜索与 `job_id` 对应的正在运行中的 DDL 作业。 +你只能在 DDL 历史作业队列的最后十个结果中搜索与 `job_id` 对应的正在运行的 DDL 作业。 ### `ADMIN SHOW DDL JOB QUERIES LIMIT m OFFSET n` -`ADMIN SHOW DDL JOB QUERIES LIMIT m OFFSET n` 语句用于查看指定范围 `[n+1, n+m]` 的 `job_id` 对应的 DDL 任务的原始 SQL 语句: +要查看与 `job_id` 对应的指定范围 `[n+1, n+m]` 内的 DDL 作业的原始 SQL 语句,使用 `ADMIN SHOW DDL JOB QUERIES LIMIT m OFFSET n`: ```sql -ADMIN SHOW DDL JOB QUERIES LIMIT m; # -- 取出前 m 行 -ADMIN SHOW DDL JOB QUERIES LIMIT n, m; # -- 取出第 n+1 到 n+m 行 -ADMIN SHOW DDL JOB QUERIES LIMIT m OFFSET n; # -- 取出第 n+1 到 n+m 行 +ADMIN SHOW DDL JOB QUERIES LIMIT m; # 检索前 m 行 +ADMIN SHOW DDL JOB QUERIES LIMIT n, m; # 检索第 [n+1, n+m] 行 +ADMIN SHOW DDL JOB QUERIES LIMIT m OFFSET n; # 检索第 [n+1, n+m] 行 ``` -以上语法中 `n` 和 `m` 都是非负整数。语法的具体示例如下: +其中 `n` 和 `m` 是大于等于 0 的整数。 ```sql -ADMIN SHOW DDL JOB QUERIES LIMIT 3; # Retrieve first 3 rows +ADMIN SHOW DDL JOB QUERIES LIMIT 3; # 检索前 3 行 +--------+--------------------------------------------------------------+ -| JOB_ID | QUERY | +| JOB_ID | QUERY | +--------+--------------------------------------------------------------+ -| 59 | ALTER TABLE t1 ADD INDEX index2 (col2) | -| 60 | ALTER TABLE t2 ADD INDEX index1 (col1) | -| 58 | CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY auto_increment) | +| 59 | ALTER TABLE t1 ADD INDEX index2 (col2) | +| 60 | ALTER TABLE t2 ADD INDEX index1 (col1) | +| 58 | CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY auto_increment) | +--------+--------------------------------------------------------------+ 3 rows in set (0.00 sec) ``` ```sql -ADMIN SHOW DDL JOB QUERIES LIMIT 6, 2; # Retrieve rows 7-8 +ADMIN SHOW DDL JOB QUERIES LIMIT 6, 2; # 检索第 7-8 行 +--------+----------------------------------------------------------------------------+ -| JOB_ID | QUERY | +| JOB_ID | QUERY | +--------+----------------------------------------------------------------------------+ -| 52 | ALTER TABLE t1 ADD INDEX index1 (col1) | -| 51 | CREATE TABLE IF NOT EXISTS t1 (id INT NOT NULL PRIMARY KEY auto_increment) | +| 52 | ALTER TABLE t1 ADD INDEX index1 (col1) | +| 51 | CREATE TABLE IF NOT EXISTS t1 (id INT NOT NULL PRIMARY KEY auto_increment) | +--------+----------------------------------------------------------------------------+ 3 rows in set (0.00 sec) ``` ```sql -ADMIN SHOW DDL JOB QUERIES LIMIT 3 OFFSET 4; # Retrieve rows 5-7 +ADMIN SHOW DDL JOB QUERIES LIMIT 3 OFFSET 4; # 检索第 5-7 行 +--------+----------------------------------------+ -| JOB_ID | QUERY | +| JOB_ID | QUERY | +--------+----------------------------------------+ | 54 | DROP TABLE IF EXISTS t3 | | 53 | ALTER TABLE t1 DROP INDEX index1 | -| 52 | ALTER TABLE t1 ADD INDEX index1 (col1) | +| 52 | ALTER TABLE t1 ADD INDEX index1 (col1) | +--------+----------------------------------------+ 3 rows in set (0.00 sec) ``` -该语句可以在 DDL 历史作业队列任意指定范围中搜索与 `job_id` 对应的正在运行中的 DDL 作业,没有 `ADMIN SHOW DDL JOB QUERIES` 语句的最近 10 条结果的限制。 +你可以在 DDL 历史作业队列中任意指定范围内搜索与 `job_id` 对应的正在运行的 DDL 作业。此语法没有 `ADMIN SHOW DDL JOB QUERIES` 最后十个结果的限制。 ## MySQL 兼容性 -`ADMIN SHOW DDL [JOBS|JOB QUERIES]` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [DDL 语句的执行原理及最佳实践](/ddl-introduction.md) +* [DDL 简介](/ddl-introduction.md) * [ADMIN CANCEL DDL](/sql-statements/sql-statement-admin-cancel-ddl.md) * [ADMIN PAUSE DDL](/sql-statements/sql-statement-admin-pause-ddl.md) * [ADMIN RESUME DDL](/sql-statements/sql-statement-admin-resume-ddl.md) diff --git a/sql-statements/sql-statement-admin.md b/sql-statements/sql-statement-admin.md index 59116123e153..434d863037ee 100644 --- a/sql-statements/sql-statement-admin.md +++ b/sql-statements/sql-statement-admin.md @@ -1,29 +1,44 @@ --- -title: ADMIN -summary: TiDB的 `ADMIN` 语句是用于查看TiDB状态和对表数据进行校验的扩展语法。其中包括 `ADMIN RELOAD`、`ADMIN PLUGIN`、`ADMIN ... BINDINGS`、`ADMIN REPAIR TABLE` 和 `ADMIN SHOW NEXT_ROW_ID` 等扩展语句。这些语句可以用于重新加载表达式下推的黑名单、启用或禁用插件、持久化 SQL Plan 绑定信息、修复表的元信息以及查看表中特殊列的详情。这些功能对于管理和维护 TiDB 数据库非常有用。 +title: ADMIN | TiDB SQL 语句参考 +summary: TiDB 数据库中 ADMIN 的使用概述。 --- # ADMIN -`ADMIN` 语句是 TiDB 扩展语法,用于查看 TiDB 自身的状态,并对 TiDB 中的表数据进行校验。本文介绍了下列与 ADMIN 相关的扩展语句: +该语句是 TiDB 扩展语法,用于查看 TiDB 的状态和检查 TiDB 中表的数据。本文档介绍以下 `ADMIN` 相关语句: - [`ADMIN RELOAD`](#admin-reload-语句) -- [`ADMIN PLUGIN`](#admin-plugin-语句) -- [`ADMIN ... BINDINGS`](#admin--bindings-语句) -- [`ADMIN REPAIR TABLE`](#admin-repair-table-语句) +- [`ADMIN PLUGINS`](#admin-plugins-相关语句) +- [`ADMIN ... BINDINGS`](#admin-bindings-相关语句) +- [`ADMIN REPAIR`](#admin-repair-语句) - [`ADMIN SHOW NEXT_ROW_ID`](#admin-show-next_row_id-语句) - [`ADMIN SHOW SLOW`](#admin-show-slow-语句) -## ADMIN 与 DDL 相关的扩展语句 +## DDL 相关语句 -| 语句 | 功能描述 | + + +| 语句 | 描述 | +|------------------------------------------------------------------------------------------|-----------------------------| +| [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消当前正在运行的 DDL 作业。 | +| [`ADMIN PAUSE DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md) | 暂停当前正在运行的 DDL 作业。 | +| [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md) | 恢复已暂停的 DDL 作业。 | +| [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表中所有行和索引的 CRC64。 | +| [ADMIN CHECK [TABLE\|INDEX]](/sql-statements/sql-statement-admin-check-table-index.md) | 检查表或索引的一致性。 | +| [ADMIN SHOW DDL [JOBS\|QUERIES]](/sql-statements/sql-statement-admin-show-ddl.md) | 显示当前正在运行或最近完成的 DDL 作业的详细信息。 | + + + + + +| 语句 | 描述 | |------------------------------------------------------------------------------------------|-----------------------------| -| [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消当前正在运行的 DDL 作业 | -| [`ADMIN PAUSE DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md) | 暂停当前正在运行的 DDL 作业 | -| [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md) | 恢复当前处于暂停中的 DDL 作业 | -| [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表中所有行和索引的 CRC64 校验和 | -| [ADMIN CHECK [TABLE\|INDEX]](/sql-statements/sql-statement-admin-check-table-index.md) | 校验表中数据和对应索引的一致性 | -| [ADMIN SHOW DDL [JOBS\|QUERIES]](/sql-statements/sql-statement-admin-show-ddl.md) | 显示有关当前正在运行或最近完成的 DDL 作业的详细信息| +| [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消当前正在运行的 DDL 作业。 | +| [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表中所有行和索引的 CRC64。 | +| [ADMIN CHECK [TABLE\|INDEX]](/sql-statements/sql-statement-admin-check-table-index.md) | 检查表或索引的一致性。 | +| [ADMIN SHOW DDL [JOBS\|QUERIES]](/sql-statements/sql-statement-admin-show-ddl.md) | 显示当前正在运行或最近完成的 DDL 作业的详细信息。 | + + ## `ADMIN RELOAD` 语句 @@ -31,61 +46,79 @@ summary: TiDB的 `ADMIN` 语句是用于查看TiDB状态和对表数据进行校 ADMIN RELOAD expr_pushdown_blacklist; ``` -以上语句用于重新加载表达式下推的黑名单。 +上述语句用于重新加载表达式下推的黑名单。 ```sql ADMIN RELOAD opt_rule_blacklist; ``` -以上语句用于重新加载逻辑优化规则的黑名单。 +上述语句用于重新加载逻辑优化规则的黑名单。 -## `ADMIN PLUGIN` 语句 +## `ADMIN PLUGINS` 相关语句 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ```sql ADMIN PLUGINS ENABLE plugin_name [, plugin_name] ...; ``` -以上语句用于启用 `plugin_name` 插件。 +上述语句用于启用 `plugin_name` 插件。 ```sql ADMIN PLUGINS DISABLE plugin_name [, plugin_name] ...; ``` -以上语句用于禁用 `plugin_name` 插件。 +上述语句用于禁用 `plugin_name` 插件。 -## `ADMIN ... BINDINGS` 语句 +## `ADMIN BINDINGS` 相关语句 ```sql -ADMIN FLUSH bindings; +ADMIN FLUSH BINDINGS; ``` -以上语句用于持久化 SQL Plan 绑定的信息。 +上述语句用于持久化 SQL Plan 绑定信息。 ```sql -ADMIN CAPTURE bindings; +ADMIN CAPTURE BINDINGS; ``` -以上语句可以将出现超过一次的 `select`execution-plan 语句生成 SQL Plan 的绑定。 +上述语句可以为出现多次的 `SELECT` 语句生成 SQL Plan 绑定。 ```sql -ADMIN EVOLVE bindings; +ADMIN EVOLVE BINDINGS; ``` -开启自动绑定功能后,每隔 `bind-info-lease`(默认值为 `3s`)触发一次 SQL Plan 绑定信息的演进。以上语句用于主动触发此演进,SQL Plan 绑定详情可参考:[执行计划管理](/sql-plan-management.md)。 +启用自动绑定功能后,每隔 `bind-info-leave`(默认值为 `3s`)会触发 SQL Plan 绑定信息的演进。上述语句用于主动触发此演进。 ```sql -ADMIN RELOAD bindings; +ADMIN RELOAD BINDINGS; ``` -以上语句用于重新加载 SQL Plan 绑定的信息。 +上述语句用于重新加载 SQL Plan 绑定信息。 + +## `ADMIN REPAIR` 语句 + + + +> **注意:** +> +> 此 TiDB 语句不适用于 TiDB Cloud。 + + -## `ADMIN REPAIR TABLE` 语句 +在极端情况下,要以不可信的方式覆盖存储表的元数据,使用 `ADMIN REPAIR TABLE`: ```sql ADMIN REPAIR TABLE tbl_name CREATE TABLE STATEMENT; ``` -`ADMIN REPAIR TABLE tbl_name CREATE TABLE STATEMENT` 用于在极端情况下,对存储层中的表的元信息进行非可信的覆盖。“非可信”是指需要人为保证原表的元信息可以完全由 `CREATE TABLE STATEMENT` 提供。该语句需要打开配置文件项中的 [`repair-mode`](/tidb-configuration-file.md#repair-mode) 开关,并且需要确保所修复的表名在 [`repair-table-list`](/tidb-configuration-file.md#repair-table-list) 名单中。 + + +这里的"不可信"意味着你需要手动确保原始表的元数据可以被 `CREATE TABLE STATEMENT` 操作覆盖。要使用此 `REPAIR` 语句,需要启用 [`repair-mode`](/tidb-configuration-file.md#repair-mode) 配置项,并确保要修复的表列在 [`repair-table-list`](/tidb-configuration-file.md#repair-table-list) 中。 + + ## `ADMIN SHOW NEXT_ROW_ID` 语句 @@ -93,10 +126,14 @@ ADMIN REPAIR TABLE tbl_name CREATE TABLE STATEMENT; ADMIN SHOW t NEXT_ROW_ID; ``` -以上语句可以查看表中某些特殊列的详情。输出结果与 [SHOW TABLE NEXT_ROW_ID](/sql-statements/sql-statement-show-table-next-rowid.md) 相同。 +上述语句用于查看表的某些特殊列的详细信息。输出与 [SHOW TABLE NEXT_ROW_ID](/sql-statements/sql-statement-show-table-next-rowid.md) 相同。 ## `ADMIN SHOW SLOW` 语句 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + ```sql ADMIN SHOW SLOW RECENT N; ``` @@ -105,9 +142,13 @@ ADMIN SHOW SLOW RECENT N; ADMIN SHOW SLOW TOP [INTERNAL | ALL] N; ``` -这两种语句的具体操作详情可参考:[admin show slow 语句](/identify-slow-queries.md#admin-show-slow-命令)。 + -## 语句概览 +详情请参考 [`ADMIN SHOW SLOW` 命令](/identify-slow-queries.md#admin-show-slow-command)。 + + + +## 语法图 ```ebnf+diagram AdminStmt ::= @@ -158,18 +199,18 @@ TableNameList ::= TableName ( ',' TableName )* ``` -## 使用示例 +## 示例 -执行以下命令,可查看正在执行的 DDL 任务中最近 10 条已经完成的 DDL 任务。未指定 `NUM` 时,默认只显示最近 10 条已经执行完的 DDL 任务。 +运行以下命令查看当前正在运行的 DDL 作业队列中最后 10 个已完成的 DDL 作业。当未指定 `NUM` 时,默认只显示最后 10 个已完成的 DDL 作业。 ```sql -ADMIN SHOW DDL jobs; +ADMIN SHOW DDL JOBS; ``` ``` -+--------+---------+------------+---------------+----------------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ -| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME | END_TIME | STATE | -+--------+---------+------------+---------------+----------------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ ++--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ +| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME | END_TIME | STATE | ++--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ | 45 | test | t1 | add index | write reorganization | 32 | 37 | 0 | 2019-01-10 12:38:36.501 +0800 CST | | running | | 44 | test | t1 | add index | none | 32 | 37 | 0 | 2019-01-10 12:36:55.18 +0800 CST | 2019-01-10 12:36:55.852 +0800 CST | rollback done | | 43 | test | t1 | add index | public | 32 | 37 | 6 | 2019-01-10 12:35:13.66 +0800 CST | 2019-01-10 12:35:14.925 +0800 CST | synced | @@ -184,16 +225,16 @@ ADMIN SHOW DDL jobs; +--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ ``` -执行以下命令,可查看正在执行的 DDL 任务中最近 5 条已经执行完的 DDL 任务: +运行以下命令查看当前正在运行的 DDL 作业队列中最后 5 个已完成的 DDL 作业: ```sql ADMIN SHOW DDL JOBS 5; ``` ``` -+--------+---------+------------+---------------+----------------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ -| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME | END_TIME | STATE | -+--------+---------+------------+---------------+----------------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ ++--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ +| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME | END_TIME | STATE | ++--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ | 45 | test | t1 | add index | write reorganization | 32 | 37 | 0 | 2019-01-10 12:38:36.501 +0800 CST | | running | | 44 | test | t1 | add index | none | 32 | 37 | 0 | 2019-01-10 12:36:55.18 +0800 CST | 2019-01-10 12:36:55.852 +0800 CST | rollback done | | 43 | test | t1 | add index | public | 32 | 37 | 6 | 2019-01-10 12:35:13.66 +0800 CST | 2019-01-10 12:35:14.925 +0800 CST | synced | @@ -203,7 +244,7 @@ ADMIN SHOW DDL JOBS 5; +--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ ``` -执行以下命令,查看表中某些特殊列的详情。输出结果与 [SHOW TABLE NEXT_ROW_ID](/sql-statements/sql-statement-show-table-next-rowid.md) 相同。 +运行以下命令查看表的某些特殊列的详细信息。输出与 [SHOW TABLE NEXT_ROW_ID](/sql-statements/sql-statement-show-table-next-rowid.md) 相同。 ```sql ADMIN SHOW t NEXT_ROW_ID; @@ -219,43 +260,43 @@ ADMIN SHOW t NEXT_ROW_ID; 2 rows in set (0.01 sec) ``` -执行以下命令,可查看 test 数据库中未执行完成的 DDL 任务,包括正在执行中以及最近 5 条已经执行完但是执行失败的 DDL 任务。 +运行以下命令查看 test 数据库中未完成的 DDL 作业。结果包括正在运行的 DDL 作业和最后 5 个已完成但失败的 DDL 作业。 ```sql ADMIN SHOW DDL JOBS 5 WHERE state != 'synced' AND db_name = 'test'; ``` ``` -+--------+---------+------------+---------------+----------------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ -| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME | END_TIME | STATE | -+--------+---------+------------+---------------+----------------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ ++--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ +| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME | END_TIME | STATE | ++--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ | 45 | test | t1 | add index | write reorganization | 32 | 37 | 0 | 2019-01-10 12:38:36.501 +0800 CST | | running | | 44 | test | t1 | add index | none | 32 | 37 | 0 | 2019-01-10 12:36:55.18 +0800 CST | 2019-01-10 12:36:55.852 +0800 CST | rollback done | +--------+---------+------------+---------------------+----------------+-----------+----------+-----------+-----------------------------------+-----------------------------------+---------------+ ``` -* `JOB_ID`:每个 DDL 操作对应一个 DDL 作业,`JOB_ID` 全局唯一。 -* `DB_NAME`:执行 DDL 操作的数据库的名称。 -* `TABLE_NAME`:执行 DDL 操作的表的名称。 +* `JOB_ID`:每个 DDL 操作对应一个 DDL 作业。`JOB_ID` 全局唯一。 +* `DB_NAME`:执行 DDL 操作的数据库名称。 +* `TABLE_NAME`:执行 DDL 操作的表名。 * `JOB_TYPE`:DDL 操作的类型。 -* `SCHEMA_STATE`:schema 的当前状态。如果 `JOB_TYPE` 是 `add index`,则为 index 的状态;如果是 `add column`,则为 column 的状态,如果是 `create table`,则为 table 的状态。常见的状态有以下几种: - * `none`:表示不存在。一般 `drop` 操作或者 `create` 操作失败回滚后,会变为 `none` 状态。 - * `delete only`、`write only`、`delete reorganization`、`write reorganization`:这四种状态是中间状态。由于中间状态转换很快,一般操作中看不到这几种状态,只有执行 `add index` 操作时能看到处于 `write reorganization` 状态,表示正在添加索引数据。 - * `public`:表示存在且可用。一般 `create table` 和 `add index/column` 等操作完成后,会变为 `public` 状态,表示新建的 table/column/index 可以正常读写了。 +* `SCHEMA_STATE`:架构的当前状态。如果 `JOB_TYPE` 是 `add index`,则是索引的状态;如果 `JOB_TYPE` 是 `add column`,则是列的状态;如果 `JOB_TYPE` 是 `create table`,则是表的状态。常见状态包括: + * `none`:表示不存在。当 `drop` 或 `create` 操作失败并回滚时,通常会变成 `none` 状态。 + * `delete only`、`write only`、`delete reorganization`、`write reorganization`:这四个状态是中间状态。这些状态在普通操作中不可见,因为中间状态的转换非常快。你只能在 `add index` 操作中看到 `write reorganization` 状态,这表示正在添加索引数据。 + * `public`:表示存在且可用。当 `create table` 和 `add index/column` 等操作完成时,通常会变成 `public` 状态,这意味着创建的表/列/索引现在可以正常读写了。 * `SCHEMA_ID`:执行 DDL 操作的数据库的 ID。 * `TABLE_ID`:执行 DDL 操作的表的 ID。 -* `ROW_COUNT`:执行 `add index` 操作时,当前已经添加完成的数据行数。 +* `ROW_COUNT`:运行 `add index` 操作时已添加的数据行数。 * `START_TIME`:DDL 操作的开始时间。 * `END_TIME`:DDL 操作的结束时间。 -* `STATE`:DDL 操作的状态。常见的状态有以下几种: - * `none`:表示该操作任务已经进入 DDL 作业队列中,但尚未执行,因为还在排队等待前面的 DDL 作业完成。另一种原因可能是执行 `drop` 操作后,会变为 `none` 状态,但是很快会更新为 `synced` 状态,表示所有 TiDB 实例都已经同步到该状态。 - * `running`:表示该操作正在执行。 - * `synced`:表示该操作已经执行成功,且所有 TiDB 实例都已经同步该状态。 - * `rollback done`:表示该操作执行失败,回滚完成。 - * `rollingback`:表示该操作执行失败,正在回滚。 - * `cancelling`:表示正在取消该操作。这个状态只有在用 [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) 命令取消 DDL 作业时才会出现。 - * `paused`:表示 DDL 已被暂停运行。这个状态只有在用 [`ADMIN PAUSED DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md) 命令暂停 DDL 任务时才会出现。可以通过 [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md) 命令进行恢复运行。 +* `STATE`:DDL 操作的状态。常见状态包括: + * `none`:表示操作任务已被放入 DDL 作业队列但尚未执行,因为它在等待前面的任务完成。另一个原因可能是它在运行 drop 操作后变成 `none` 状态,但很快会更新为 `synced` 状态,这意味着所有 TiDB 实例都已同步到这个状态。 + * `running`:表示正在执行操作。 + * `synced`:表示操作已成功执行,并且所有 TiDB 实例都已同步到这个状态。 + * `rollback done`:表示操作已失败并已完成回滚。 + * `rollingback`:表示操作已失败并正在回滚。 + * `cancelling`:表示正在取消操作。此状态仅在使用 [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) 命令取消 DDL 作业时出现。 + * `paused`:表示操作已暂停。此状态仅在使用 [`ADMIN PAUSED DDL JOBS`](/sql-statements/sql-statement-admin-pause-ddl.md) 命令暂停 DDL 作业时出现。你可以使用 [`ADMIN RESUME DDL JOBS`](/sql-statements/sql-statement-admin-resume-ddl.md) 命令恢复 DDL 作业。 ## MySQL 兼容性 -`ADMIN` 语句是 TiDB 对于 MySQL 语法的扩展。 +该语句是 TiDB 对 MySQL 语法的扩展。 diff --git a/sql-statements/sql-statement-alter-database.md b/sql-statements/sql-statement-alter-database.md index 65349150d358..eb3e323593ca 100644 --- a/sql-statements/sql-statement-alter-database.md +++ b/sql-statements/sql-statement-alter-database.md @@ -1,13 +1,13 @@ --- -title: ALTER DATABASE -summary: TiDB 数据库中 ALTER DATABASE 的使用概况。 +title: ALTER DATABASE | TiDB SQL 语句参考 +summary: TiDB 数据库中 ALTER DATABASE 的使用概览。 --- # ALTER DATABASE -`ALTER DATABASE` 用于修改指定或当前数据库的默认字符集和排序规则。`ALTER SCHEMA` 跟 `ALTER DATABASE` 操作效果一样。 +`ALTER DATABASE` 用于指定或修改当前数据库的默认字符集和排序规则。`ALTER SCHEMA` 与 `ALTER DATABASE` 具有相同的效果。 -## 语法图 +## 语法 ```ebnf+diagram AlterDatabaseStmt ::= @@ -19,7 +19,7 @@ DatabaseOption ::= ## 示例 -修改数据库 `test` 的字符集为 `utf8mb4`: +修改 test 数据库架构以使用 utf8mb4 字符集: {{< copyable "sql" >}} @@ -31,13 +31,13 @@ ALTER DATABASE test DEFAULT CHARACTER SET = utf8mb4; Query OK, 0 rows affected (0.00 sec) ``` -目前 TiDB 只支持部分的字符集和排序规则,详情参阅[字符集支持](/character-set-and-collation.md)。 +目前,TiDB 仅支持部分字符集和排序规则。详情请参见[字符集和排序规则支持](/character-set-and-collation.md)。 ## MySQL 兼容性 -`ALTER DATABASE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `ALTER DATABASE` 语句与 MySQL 完全兼容。如果您发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 -## 另请参阅 +## 另请参见 * [CREATE DATABASE](/sql-statements/sql-statement-create-database.md) * [SHOW DATABASES](/sql-statements/sql-statement-show-databases.md) diff --git a/sql-statements/sql-statement-alter-index.md b/sql-statements/sql-statement-alter-index.md index 766c946422db..7fab7d0ad31e 100644 --- a/sql-statements/sql-statement-alter-index.md +++ b/sql-statements/sql-statement-alter-index.md @@ -1,11 +1,11 @@ --- title: ALTER INDEX -summary: TiDB 数据库中 ALTER INDEX 的使用概况。 +summary: TiDB 数据库中 ALTER INDEX 的使用概览。 --- # ALTER INDEX -`ALTER INDEX` 语句用于修改索引的可见性,可以将索引设置为 `Visible` 或者 `Invisible`。设置为 `Invisible` 的索引即不可见索引 (Invisible Index) 由 DML 语句维护,不会被查询优化器使用。从 TiDB v8.0.0 开始,你可以通过修改系统变量 [`tidb_opt_use_invisible_indexes`](/system-variables.md#tidb_opt_use_invisible_indexes-从-v800-版本开始引入),允许优化器选择不可见索引。 +`ALTER INDEX` 语句用于修改索引的可见性为 `Visible` 或 `Invisible`。不可见索引会被 DML 语句维护,但查询优化器不会使用它们。这在你想要在永久删除索引之前进行双重检查的场景中很有用。从 TiDB v8.0.0 开始,你可以通过修改系统变量 [`tidb_opt_use_invisible_indexes`](/system-variables.md#tidb_opt_use_invisible_indexes-new-in-v800) 来让优化器选择不可见索引。 ## 语法图 @@ -19,7 +19,7 @@ AlterIndexSpec ## 示例 -可以通过 `ALTER TABLE ... ALTER INDEX ...` 语句,修改索引的可见性: +你可以使用 `ALTER TABLE ... ALTER INDEX ...` 语句修改索引的可见性。 {{< copyable "sql" >}} @@ -51,7 +51,7 @@ SHOW CREATE TABLE t1; 1 row in set (0.00 sec) ``` -优化器将无法使用 `c1` 这个**不可见的索引**: +优化器无法使用 `c1` 的**不可见索引**。 {{< copyable "sql" >}} @@ -70,7 +70,7 @@ EXPLAIN SELECT c1 FROM t1 ORDER BY c1; 3 rows in set (0.00 sec) ``` -作为对比,c2 是**可见的索引**,优化器将可以使用索引: +相比之下,`c2` 是**可见索引**,可以被优化器使用。 {{< copyable "sql" >}} @@ -88,7 +88,7 @@ EXPLAIN SELECT c2 FROM t1 ORDER BY c2; 2 rows in set (0.00 sec) ``` -即使用 SQL Hint `USE INDEX` 强制使用索引,优化器也无法使用不可见索引,否则 SQL 语句会报错: +即使使用 `USE INDEX` SQL 提示强制使用索引,优化器仍然无法使用不可见索引;否则,会返回错误。 {{< copyable "sql" >}} @@ -102,7 +102,7 @@ ERROR 1176 (42000): Key 'c1' doesn't exist in table 't1' > **注意:** > -> “不可见”是仅仅对优化器而言的,不可见索引仍然可以被修改或删除。 +> 这里的"不可见"仅对优化器不可见。你仍然可以修改或删除不可见索引。 {{< copyable "sql" >}} @@ -116,8 +116,8 @@ Query OK, 0 rows affected (0.02 sec) ## MySQL 兼容性 -* TiDB 中的不可见索引是基于 MySQL 8.0 中的同等特性构建的。 -* 与 MySQL 类似,TiDB 不允许将主键索引设为不可见。 +* TiDB 中的不可见索引是基于 MySQL 8.0 中的相同功能建模的。 +* 与 MySQL 类似,TiDB 不允许将 `PRIMARY KEY` 索引设置为不可见。 ## 另请参阅 diff --git a/sql-statements/sql-statement-alter-instance.md b/sql-statements/sql-statement-alter-instance.md index cffd90a72bf9..9b997c5a63c0 100644 --- a/sql-statements/sql-statement-alter-instance.md +++ b/sql-statements/sql-statement-alter-instance.md @@ -1,22 +1,38 @@ --- title: ALTER INSTANCE -summary: TiDB 数据库中 ALTER INSTANCE 的使用概况。 +summary: 了解 TiDB 中 `ALTER INSTANCE` 的使用概述。 --- # ALTER INSTANCE -`ALTER INSTANCE` 语句用于对单个 TiDB 实例进行变更操作。目前 TiDB 仅支持 `RELOAD TLS` 子句。 +`ALTER INSTANCE` 语句用于对单个 TiDB 实例进行更改。目前,TiDB 仅支持 `RELOAD TLS` 子句。 + +> **注意:** +> +> [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 可以自动刷新 TLS 证书,因此此功能不适用于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群。 ## RELOAD TLS -`ALTER INSTANCE RELOAD TLS` 语句用于从原配置的证书 ([`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。 + + +你可以执行 `ALTER INSTANCE RELOAD TLS` 语句来从原始配置路径重新加载证书([`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))。 + + + + + +你可以执行 `ALTER INSTANCE RELOAD TLS` 语句来从原始配置路径重新加载证书([`ssl-cert`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#ssl-cert))、密钥([`ssl-key`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#ssl-key))和 CA([`ssl-ca`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#ssl-ca))。 + + -新加载的证书密钥和 CA 将在语句执行成功后对新建立的连接生效,不会影响语句执行前已建立的连接。 +新加载的证书、密钥和 CA 在语句成功执行后建立的连接上生效。在执行此语句之前建立的连接不受影响。 -在重加载遇到错误时默认会报错返回且继续使用变更前的密钥和证书,但在添加可选的 `NO ROLLBACK ON ERROR` 后遇到错误将不报错并以关闭 TLS 安全连接功能的方式处理后续请求。 +当重新加载过程中发生错误时,默认情况下会返回错误消息,并继续使用之前的密钥和证书。但是,如果你添加了可选的 `NO ROLLBACK ON ERROR`,当重新加载过程中发生错误时,不会返回错误,而是在禁用 TLS 安全连接的情况下处理后续请求。 ## 语法图 +**AlterInstanceStmt:** + ```ebnf+diagram AlterInstanceStmt ::= 'ALTER' 'INSTANCE' InstanceOption @@ -35,8 +51,18 @@ ALTER INSTANCE RELOAD TLS; ## MySQL 兼容性 -仅支持从原配置路径重加载,不支持动态修改加载路径,也不支持动态启用启动 TiDB 时未开启的 TLS 加密连接功能。 +`ALTER INSTANCE RELOAD TLS` 语句仅支持从原始配置路径重新加载。它不支持动态修改加载路径或在 TiDB 启动时动态启用 TLS 加密连接功能。重启 TiDB 时,此功能默认是禁用的。 ## 另请参阅 -[为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md) + + +[启用 TiDB 客户端与服务端之间的 TLS](/enable-tls-between-clients-and-servers.md)。 + + + + + +[启用 TiDB 客户端与服务端之间的 TLS](https://docs.pingcap.com/tidb/stable/enable-tls-between-clients-and-servers)。 + + diff --git a/sql-statements/sql-statement-alter-placement-policy.md b/sql-statements/sql-statement-alter-placement-policy.md index 561eaa819fb0..6a5317248492 100644 --- a/sql-statements/sql-statement-alter-placement-policy.md +++ b/sql-statements/sql-statement-alter-placement-policy.md @@ -1,20 +1,24 @@ --- title: ALTER PLACEMENT POLICY -summary: TiDB 数据库中 ALTER PLACEMENT POLICY 的使用概况。 +summary: TiDB 中 ALTER PLACEMENT POLICY 的使用方法。 --- # ALTER PLACEMENT POLICY -`ALTER PLACEMENT POLICY` 用于修改已创建的放置策略。此修改会自动更新至所有使用这些放置策略的表和分区。 +`ALTER PLACEMENT POLICY` 用于修改先前创建的放置策略。使用该放置策略的所有表和分区都将自动更新。 -`ALTER PLACEMENT POLICY` 会完全替换之前定义的规则,而不会和之前的规则合并,比如在下面的例子中,`FOLLOWERS=4` 就被 `ALTER PLACEMENT POLICY` 语句覆盖了: +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +`ALTER PLACEMENT POLICY` 用新定义_替换_之前的策略。它不会将旧策略与新策略_合并_。在以下示例中,执行 `ALTER PLACEMENT POLICY` 时,`FOLLOWERS=4` 会丢失: ```sql CREATE PLACEMENT POLICY p1 FOLLOWERS=4; ALTER PLACEMENT POLICY p1 PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-west-1"; ``` -## 语法图 +## 语法 ```ebnf+diagram AlterPolicyStmt ::= @@ -54,14 +58,16 @@ AdvancedPlacementOption ::= > **注意:** > -> 如要查看所在集群中可用的区域,见 [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md)。如果未看到任何可用的区域,此 TiKV 集群在部署时可能未正确设置标签 (label)。 +> 要了解集群中有哪些可用区域,请参见 [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md)。 +> +> 如果你没有看到任何可用区域,你的 TiKV 安装可能没有正确设置标签。 {{< copyable "sql" >}} ```sql CREATE PLACEMENT POLICY p1 PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-west-1"; -CREATE TABLE t1 (i INT) PLACEMENT POLICY=p1; -- 绑定放置策略 p1 到表 t1。 -ALTER PLACEMENT POLICY p1 PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-west-1,us-west-2" FOLLOWERS=4; -- t1 上的放置规则会自动更新。 +CREATE TABLE t1 (i INT) PLACEMENT POLICY=p1; -- 将策略 p1 分配给表 t1 +ALTER PLACEMENT POLICY p1 PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-west-1,us-west-2" FOLLOWERS=4; -- t1 的规则将自动更新。 SHOW CREATE PLACEMENT POLICY p1\G ``` @@ -82,7 +88,7 @@ Create Policy | CREATE PLACEMENT POLICY `p1` PRIMARY_REGION="us-east-1" REGIONS= ## 另请参阅 -* [Placement Rules in SQL](/placement-rules-in-sql.md) +* [SQL 中的放置规则](/placement-rules-in-sql.md) * [SHOW PLACEMENT](/sql-statements/sql-statement-show-placement.md) * [CREATE PLACEMENT POLICY](/sql-statements/sql-statement-create-placement-policy.md) * [DROP PLACEMENT POLICY](/sql-statements/sql-statement-drop-placement-policy.md) diff --git a/sql-statements/sql-statement-alter-range.md b/sql-statements/sql-statement-alter-range.md index 740895b75f04..3ef5e1cf95d7 100644 --- a/sql-statements/sql-statement-alter-range.md +++ b/sql-statements/sql-statement-alter-range.md @@ -1,11 +1,15 @@ --- title: ALTER RANGE -summary: TiDB 数据库中 ALTER RANGE 的使用概况。 +summary: TiDB 中 ALTER RANGE 的使用概述。 --- # ALTER RANGE -`ALTER RANGE` 语句目前仅用于修改 TiDB 数据库中指定范围的放置策略。 +目前,`ALTER RANGE` 语句只能用于修改 TiDB 中特定放置策略的范围。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ## 语法图 @@ -14,10 +18,10 @@ AlterRangeStmt ::= 'ALTER' 'RANGE' Identifier PlacementPolicyOption ``` -目前 `ALTER RANGE` 能起作用的有 `global` 和 `meta` 两个参数: +`ALTER RANGE` 支持以下两个参数: -- `global`:表示集群内全域数据的范围 -- `meta`:表示 TiDB 内部存储的元信息的数据范围 +- `global`:表示集群中所有数据的范围。 +- `meta`:表示存储在 TiDB 中的内部元数据的范围。 ## 示例 @@ -29,4 +33,4 @@ ALTER RANGE global PLACEMENT POLICY = "deploy111"; ALTER RANGE meta PLACEMENT POLICY = "five_replicas"; ``` -上述示例创建了一个名为 `deploy111` 和 `five_replicas` 的放置策略,为不同的区域指定了约束条件。然后将 `deploy111` 放置策略应用到了整个集群范围内的数据,将 `five_replicas` 放置策略应用到元数据范围内。 \ No newline at end of file +上述示例创建了两个放置策略(`deploy111` 和 `five_replicas`),为不同区域指定了约束条件,然后将 `deploy111` 放置策略应用于集群范围内的所有数据,将 `five_replicas` 放置策略应用于元数据范围。 diff --git a/sql-statements/sql-statement-alter-resource-group.md b/sql-statements/sql-statement-alter-resource-group.md index 2da24b024e11..2447435f8935 100644 --- a/sql-statements/sql-statement-alter-resource-group.md +++ b/sql-statements/sql-statement-alter-resource-group.md @@ -1,13 +1,17 @@ --- title: ALTER RESOURCE GROUP -summary: TiDB 数据库中 ALTER RESOURCE GROUP 的使用概况。 +summary: 了解 TiDB 中 ALTER RESOURCE GROUP 的用法。 --- # ALTER RESOURCE GROUP -`ALTER RESOURCE GROUP` 语句用于在当前所选数据库中修改资源组。 +`ALTER RESOURCE GROUP` 语句用于修改数据库中的资源组。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法 ```ebnf+diagram AlterResourceGroupStmt ::= @@ -42,7 +46,7 @@ ResourceGroupPriorityOption ::= | MEDIUM | HIGH -ResourceGroupRunawayOptionList ::= +ResourceGroupRunawayOptionList ::= DirectResourceGroupRunawayOption | ResourceGroupRunawayOptionList DirectResourceGroupRunawayOption | ResourceGroupRunawayOptionList ',' DirectResourceGroupRunawayOption @@ -61,40 +65,40 @@ ResourceGroupRunawayActionOption ::= | COOLDOWN | KILL -BackgroundOptionList ::= +BackgroundOptionList ::= DirectBackgroundOption | BackgroundOptionList DirectBackgroundOption | BackgroundOptionList ',' DirectBackgroundOption -DirectBackgroundOption ::= +DirectBackgroundOption ::= "TASK_TYPES" EqOpt stringLit ``` -TiDB 支持以下 `DirectResourceGroupOption`, 其中 [Request Unit (RU)](/tidb-resource-control.md#什么是-request-unit-ru) 是 TiDB 对 CPU、IO 等系统资源统一抽象的单位。 +TiDB 支持以下 `DirectResourceGroupOption`,其中[请求单元 (RU)](/tidb-resource-control.md#what-is-request-unit-ru) 是 TiDB 中 CPU、IO 和其他系统资源的统一抽象单位。 -| 参数 | 含义 | 举例 | -|---------------|--------------|--------------------------------------| -| `RU_PER_SEC` | 每秒 RU 填充的速度 | `RU_PER_SEC = 500` 表示此资源组每秒回填 500 个 RU。 | -| `PRIORITY` | 任务在 TiKV 上处理的绝对优先级 | `PRIORITY = HIGH` 表示优先级高。若未指定则默认为 `MEDIUM`。 | -| `BURSTABLE` | 允许对应的资源组超出配额后使用空余的系统资源。 | -| `QUERY_LIMIT` | 当查询执行满足该条件时,识别该查询为 Runaway Query 并执行相应的操作 | `QUERY_LIMIT=(EXEC_ELAPSED='60s', ACTION=KILL, WATCH=EXACT DURATION='10m')` 表示当执行时间超过 60 秒后识别为 Runaway Query,对该查询执行终止操作,并在 10 分钟内对同样的 SQL 直接执行终止操作。`QUERY_LIMIT=()` 或 `QUERY_LIMIT=NULL` 则表示不进行 Runaway 控制。具体参数介绍参见[管理资源消耗超出预期的查询 (Runaway Queries)](/tidb-resource-control.md#管理资源消耗超出预期的查询-runaway-queries)。 | -| `BACKGROUND` | 后台任务相关的设置。具体参数介绍参见[管理后台任务](/tidb-resource-control.md#管理后台任务) | `BACKGROUND=(TASK_TYPES="br,stats")` 表示将备份恢复和收集统计信息相关的任务作为后台任务调度。 | +| 选项 | 描述 | 示例 | +|---------------|-------------------------------------|------------------------| +| `RU_PER_SEC` | 每秒 RU 补充率 | `RU_PER_SEC = 500` 表示此资源组每秒补充 500 个 RU | +| `PRIORITY` | 在 TiKV 上处理任务的绝对优先级 | `PRIORITY = HIGH` 表示优先级高。如果未指定,默认值为 `MEDIUM`。 | +| `BURSTABLE` | 如果设置了 `BURSTABLE` 属性,TiDB 允许相应的资源组在超出配额时使用可用的系统资源。 | +| `QUERY_LIMIT` | 当查询执行满足此条件时,该查询被识别为失控查询并执行相应的操作。 | `QUERY_LIMIT=(EXEC_ELAPSED='60s', ACTION=KILL, WATCH=EXACT DURATION='10m')` 表示当执行时间超过 60 秒时,该查询被识别为失控查询。查询被终止。在接下来的 10 分钟内,所有具有相同 SQL 文本的 SQL 语句都将立即被终止。`QUERY_LIMIT=()` 或 `QUERY_LIMIT=NULL` 表示未启用失控控制。参见[失控查询](/tidb-resource-control.md#manage-queries-that-consume-more-resources-than-expected-runaway-queries)。 | +| `BACKGROUND` | 配置后台任务。更多详情,请参见[管理后台任务](/tidb-resource-control.md#manage-background-tasks)。 | `BACKGROUND=(TASK_TYPES="br,stats")` 表示备份恢复和统计信息收集相关的任务被安排为后台任务。 | > **注意:** > -> - `ALTER RESOURCE GROUP` 语句只能在全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-从-v660-版本开始引入) 参数设置为 `ON` 时才能执行。 -> - `ALTER RESOURCE GROUP` 语句支持以增量方式修改,未指定的参数保持不变。但其中 `QUERY_LIMIT` 和 `BACKGROUND` 各自作为一个整体,无法部分修改其中的参数。 -> - 目前仅 `default` 资源组支持修改 `BACKGROUND` 相关设置。 +> - `ALTER RESOURCE GROUP` 语句只能在全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-new-in-v660) 设置为 `ON` 时执行。 +> - `ALTER RESOURCE GROUP` 语句支持增量更改,未指定的参数保持不变。但是,`QUERY_LIMIT` 和 `BACKGROUND` 都是作为一个整体使用,不能部分修改。 +> - 目前,只有 `default` 资源组支持修改 `BACKGROUND` 配置。 ## 示例 -创建一个名为 `rg1` 的资源组,并修改它的属性。 +创建名为 `rg1` 的资源组并修改其属性。 ```sql DROP RESOURCE GROUP IF EXISTS rg1; ``` -```sql +``` Query OK, 0 rows affected (0.22 sec) ``` @@ -145,7 +149,7 @@ SELECT * FROM information_schema.resource_groups WHERE NAME ='rg1'; 1 rows in set (1.30 sec) ``` -修改 `default` 资源组的后台任务 `BACKGROUND` 相关设置。 +修改 `default` 资源组的 `BACKGROUND` 选项。 ```sql ALTER RESOURCE GROUP default BACKGROUND = (TASK_TYPES = "br,ddl"); @@ -170,10 +174,10 @@ SELECT * FROM information_schema.resource_groups WHERE NAME ='default'; ## MySQL 兼容性 -MySQL 也支持 [ALTER RESOURCE GROUP](https://dev.mysql.com/doc/refman/8.0/en/alter-resource-group.html),但是接受的参数和 TiDB 不同,两者并不兼容。 +MySQL 也支持 [ALTER RESOURCE GROUP](https://dev.mysql.com/doc/refman/8.0/en/alter-resource-group.html)。但是,可接受的参数与 TiDB 的不同,因此它们不兼容。 ## 另请参阅 * [DROP RESOURCE GROUP](/sql-statements/sql-statement-drop-resource-group.md) * [CREATE RESOURCE GROUP](/sql-statements/sql-statement-create-resource-group.md) -* [RU](/tidb-resource-control.md#什么是-request-unit-ru) +* [请求单元 (RU)](/tidb-resource-control.md#what-is-request-unit-ru) diff --git a/sql-statements/sql-statement-alter-sequence.md b/sql-statements/sql-statement-alter-sequence.md index cd030e1d9296..13d803f35039 100644 --- a/sql-statements/sql-statement-alter-sequence.md +++ b/sql-statements/sql-statement-alter-sequence.md @@ -1,13 +1,13 @@ --- title: ALTER SEQUENCE -summary: 介绍 ALTER SEQUENCE 在 TiDB 中的使用概况。 +summary: TiDB 数据库中 ALTER SEQUENCE 的使用概述。 --- # ALTER SEQUENCE -`ALTER SEQUENCE` 语句用于在 TiDB 中修改序列对象。序列是一种与 `Table` 和 `View` 对象平级的数据库对象,用于生成自定义的序列化 ID。 +`ALTER SEQUENCE` 语句用于修改 TiDB 中的序列对象。序列是与 `Table` 和 `View` 对象同级的数据库对象。序列用于以自定义方式生成序列化的 ID。 -## 语法图 +## 语法概要 ```ebnf+diagram CreateSequenceStmt ::= @@ -34,7 +34,7 @@ SequenceOption ::= | 'RESTART' ( ( '='? | 'WITH' ) SignedNum )? ``` -## 语法说明 +## 语法 ```sql ALTER SEQUENCE sequence_name @@ -47,40 +47,40 @@ ALTER SEQUENCE sequence_name [table_options] ``` -## 参数说明 +## 参数 |参数 | 默认值 | 描述 | | :-- | :-- | :--| -| `INCREMENT` | `1` | 指定序列的步长。其正负值可以控制序列的增长方向。| -| `MINVALUE` | `1` 或 `-9223372036854775807` | 指定序列的最小值。当 `INCREMENT` > `0` 时,默认值为 `1`;当 `INCREMENT` < `0` 时,默认值为 `-9223372036854775807`。| -| `MAXVALUE` | `9223372036854775806` 或 `-1` | 指定序列的最大值。当 `INCREMENT` > `0` 时,默认值为 `9223372036854775806`;当 `INCREMENT` < `0` 时,默认值为 `-1`。| -| `START` | `MINVALUE` 或 `MAXVALUE` | 指定序列的初始值。当 `INCREMENT` > `0` 时,默认值为 `MINVALUE`; 当 `INCREMENT` < `0` 时,默认值为 `MAXVALUE`。 | -| `CACHE` | `1000` | 指定每个 TiDB 本地缓存序列的大小。| -| `CYCLE` | `NO CYCLE` | 指定序列用完之后是否要循环使用。在 `CYCLE` 的情况下,当 `INCREMENT` > `0` 时,序列用完后的后续起始值为 `MINVALUE`;当 `INCREMENT` < `0` 时,序列用完后的后续起始值为 `MAXVALUE`。| +| `INCREMENT` | `1` | 指定序列的增量。其正值或负值可以控制序列的增长方向。 | +| `MINVALUE` | `1` 或 `-9223372036854775807` | 指定序列的最小值。当 `INCREMENT` > `0` 时,默认值为 `1`。当 `INCREMENT` < `0` 时,默认值为 `-9223372036854775807`。 | +| `MAXVALUE` | `9223372036854775806` 或 `-1` | 指定序列的最大值。当 `INCREMENT` > `0` 时,默认值为 `9223372036854775806`。当 `INCREMENT` < `0` 时,默认值为 `-1`。 | +| `START` | `MINVALUE` 或 `MAXVALUE` | 指定序列的初始值。当 `INCREMENT` > `0` 时,默认值为 `MINVALUE`。当 `INCREMENT` < `0` 时,默认值为 `MAXVALUE`。 | +| `CACHE` | `1000` | 指定 TiDB 中序列的本地缓存大小。 | +| `CYCLE` | `NO CYCLE` | 指定序列是否从最小值重新开始(或降序序列的最大值)。当 `INCREMENT` > `0` 时,默认值为 `MINVALUE`。当 `INCREMENT` < `0` 时,默认值为 `MAXVALUE`。 | > **注意:** > -> 在执行 `ALTER SEQUENCE ... RESTART` 之前,更改 `START` 值不会影响生成的值。 +> 更改 `START` 值不会影响生成的值,直到你执行 `ALTER SEQUENCE ... RESTART`。 ## `SEQUENCE` 函数 -主要通过表达式函数来操纵序列的使用。 +你可以通过以下表达式函数控制序列: + `NEXTVAL` 或 `NEXT VALUE FOR` - 本质上都是 `NEXTVAL()` 函数,获取序列对象的下一个有效值,其参数为序列的 `identifier`。 + 本质上,两者都是 `NEXTVAL()` 函数,用于获取序列对象的下一个有效值。`NEXTVAL()` 函数的参数是序列的 `identifier`。 + `LASTVAL` - `LASTVAL()` 函数,用于获取本会话上一个使用过的值。如果没有值,则为 `NULL`,其参数为序列的 `identifier`。 + 此函数获取此会话的最后使用值。如果该值不存在,则使用 `NULL`。此函数的参数是序列的 `identifier`。 + `SETVAL` - `SETVAL()` 函数,用于设置序列的增长。其第一参数为序列的 `identifier`,第二个参数为 `num`。 + 此函数设置序列当前值的进程。此函数的第一个参数是序列的 `identifier`;第二个参数是 `num`。 > **注意:** > -> 在 TiDB 序列的实现中,`SETVAL` 函数并不能改变序列增长的初始步调或循环步调。在 `SETVAL` 之后只会返回符合步调规律的下一个有效的序列值。 +> 在 TiDB 的序列实现中,`SETVAL` 函数不能更改此序列的初始进程或循环进程。此函数仅根据此进程返回下一个有效值。 ## 示例 @@ -94,7 +94,7 @@ CREATE SEQUENCE s1; Query OK, 0 rows affected (0.15 sec) ``` -执行以下 SQL 语句两次,获取该序列接下来的两个值: +通过执行以下 SQL 语句两次从序列中获取接下来的两个值: ```sql SELECT NEXTVAL(s1); @@ -122,7 +122,7 @@ SELECT NEXTVAL(s1); 1 row in set (0.00 sec) ``` -将该序列的步长更改为 `2`: +将序列的增量更改为 `2`: ```sql ALTER SEQUENCE s1 INCREMENT=2; @@ -132,7 +132,7 @@ ALTER SEQUENCE s1 INCREMENT=2; Query OK, 0 rows affected (0.18 sec) ``` -此时,再次获取该序列接下来的两个值: +现在,再次从序列中获取接下来的两个值: ```sql SELECT NEXTVAL(s1); @@ -160,9 +160,9 @@ SELECT NEXTVAL(s1); 1 row in set (0.00 sec) ``` -从以上输出中可以看到,在执行了 `ALTER SEQUENCE` 语句后,数值的增幅为 `2`。 +从输出可以看出,在执行 `ALTER SEQUENCE` 语句后,值现在每次增加 2。 -你还可以更改序列的其他参数。例如,可以按照以下方式更改序列的 `MAXVALUE`: +你还可以更改序列的其他参数。例如,你可以按如下方式更改序列的 `MAXVALUE`: ```sql CREATE SEQUENCE s2 MAXVALUE=10; @@ -193,23 +193,23 @@ Create Sequence: CREATE SEQUENCE `s2` start with 1 minvalue 1 maxvalue 100 incre ## MySQL 兼容性 -该语句是 TiDB 的扩展,序列的实现借鉴自 MariaDB。 +此语句是 TiDB 扩展。其实现是基于 MariaDB 中可用的序列。 -除了 `SETVAL` 函数外,其他函数的“步调 (progressions)” 与 MariaDB 一致。这里的步调是指,序列中的数在定义之后会产生一定的等差关系。`SETVAL` 虽然可以将序列的当前值进行移动设置,但是后续出现的值仍会遵循原有的等差关系。 +除了 `SETVAL` 函数外,所有其他函数都具有与 MariaDB 相同的_进程_。这里的"进程"意味着序列中的数字遵循由序列定义的某个算术进程规则。虽然你可以使用 `SETVAL` 设置序列的当前值,但序列的后续值仍然遵循原始进程规则。 -示例如下: +例如: ``` -1, 3, 5, ... // 序列遵循起始为 1、步长为 2 的等差关系。 -SELECT SETVAL(seq, 6) // 设置序列的当前值为 6。 -7, 9, 11, ... // 后续产生值仍会遵循这个等差关系。 +1, 3, 5, ... // 序列从 1 开始,每次增加 2。 +SELECT SETVAL(seq, 6) // 将序列的当前值设置为 6。 +7, 9, 11, ... // 后续值仍然遵循进程规则。 ``` -在 `CYCLE` 模式下,序列的起始值第一轮为 `START`,后续轮次将会是 `MinValue` (INCREMENT > 0) 或 `MaxValue` (INCREMENT < 0)。 +在 `CYCLE` 模式下,序列在第一轮中的初始值是 `START` 参数的值,在后续轮次中的初始值是 `MinValue`(`INCREMENT` > 0)或 `MaxValue`(`INCREMENT` < 0)的值。 ## 另请参阅 * [CREATE SEQUENCE](/sql-statements/sql-statement-create-sequence.md) * [DROP SEQUENCE](/sql-statements/sql-statement-drop-sequence.md) * [SHOW CREATE SEQUENCE](/sql-statements/sql-statement-show-create-sequence.md) -* [Sequence Functions](/functions-and-operators/sequence-functions.md) +* [序列函数](/functions-and-operators/sequence-functions.md) diff --git a/sql-statements/sql-statement-alter-table-compact.md b/sql-statements/sql-statement-alter-table-compact.md index 815746a9d86a..2c014f528faf 100644 --- a/sql-statements/sql-statement-alter-table-compact.md +++ b/sql-statements/sql-statement-alter-table-compact.md @@ -1,32 +1,32 @@ --- title: ALTER TABLE ... COMPACT -summary: TiDB 数据库中 ALTER TABLE ... COMPACT 语句的使用概况。 +summary: TiDB 数据库中 ALTER TABLE ... COMPACT 的使用概述。 --- # ALTER TABLE ... COMPACT -TiDB 存储节点在后台会自动发起数据整理(Compaction)。数据整理时,表中的物理数据会被重写,如清理已删除的数据、合并多版本数据等,从而可以获得更高的访问性能,并减少磁盘空间占用。使用 `ALTER TABLE ... COMPACT` 语句可以立即对指定的表进行数据整理,而无需等待后台触发。 +为了提高读取性能并减少磁盘使用,TiDB 会在后台自动调度存储节点上的数据压缩。在压缩过程中,存储节点会重写物理数据,包括清理已删除的行和合并由更新引起的多个数据版本。`ALTER TABLE ... COMPACT` 语句允许你立即对特定表启动压缩,而无需等待后台触发压缩。 -该语句执行时不会阻塞现有 SQL 语句的执行或 TiDB 功能的使用,包括事务、DDL、GC 等,也不会改变通过 SQL 语句访问获得的数据内容。该语句执行时会消耗一定量的 IO 及 CPU 资源,请注意选择合适的时机执行,如资源空闲时段,避免对业务造成负面影响。 +执行此语句不会阻塞现有的 SQL 语句或影响任何 TiDB 功能,如事务、DDL 和 GC。通过 SQL 语句可以选择的数据也不会改变。执行此语句会消耗一些 IO 和 CPU 资源。请注意选择合适的执行时机,例如在资源充足时执行,以避免对业务产生负面影响。 -该语句会等待表中所有副本都数据整理完毕后才结束运行并返回。在执行过程中,你可以通过 [`KILL`](/sql-statements/sql-statement-kill.md) 语句安全地中断本张表的数据整理过程。中断不会破坏数据一致性或丢失数据,也不会影响后续重新发起或自动触发后台数据整理。 +当表的所有副本都压缩完成时,压缩语句将完成并返回。在执行过程中,你可以通过执行 [`KILL`](/sql-statements/sql-statement-kill.md) 语句安全地中断压缩。中断压缩不会破坏数据一致性或导致数据丢失,也不会影响后续的手动或后台压缩。 -目前该语句仅支持对 TiFlash 进行数据整理,不支持对 TiKV 进行数据整理。 +此数据压缩语句目前仅支持 TiFlash 副本,不支持 TiKV 副本。 -## 语法图 +## 语法概要 ```ebnf+diagram AlterTableCompactStmt ::= 'ALTER' 'TABLE' TableName 'COMPACT' ( 'PARTITION' PartitionNameList )? ( 'TIFLASH' 'REPLICA' )? ``` -自 v6.2.0 起,语法中 `TIFLASH REPLICA` 部分可以被省略。省略后语句含义不变,同样只对 TiFlash 列存有效。 +从 v6.2.0 开始,语法中的 `TIFLASH REPLICA` 部分可以省略。省略时,语句的语义保持不变,仅对 TiFlash 生效。 ## 示例 -### 对表中 TiFlash 副本进行数据整理 +### 压缩表中的 TiFlash 副本 -假设目前有一张 `employees` 表具有 4 个分区,且具有 2 个 TiFlash 副本: +以下以一个具有 4 个分区和 2 个 TiFlash 副本的 `employees` 表为例: ```sql CREATE TABLE employees ( @@ -40,11 +40,10 @@ PARTITION BY LIST (store_id) ( PARTITION pWest VALUES IN (11, 12, 13, 14, 15), PARTITION pCentral VALUES IN (16, 17, 18, 19, 20) ); - ALTER TABLE employees SET TIFLASH REPLICA 2; ``` -执行以下语句可对 `employees` 表上所有分区的 2 个 TiFlash 副本立即进行数据整理: +你可以执行以下语句立即对 `employees` 表中所有分区的 2 个 TiFlash 副本启动压缩: {{< copyable "sql" >}} @@ -52,9 +51,9 @@ ALTER TABLE employees SET TIFLASH REPLICA 2; ALTER TABLE employees COMPACT TIFLASH REPLICA; ``` -### 对分区表中指定分区的 TiFlash 副本进行数据整理 +### 压缩表中指定分区的 TiFlash 副本 -假设目前有一张 `employees` 表具有 4 个分区,且具有 2 个 TiFlash 副本: +以下以一个具有 4 个分区和 2 个 TiFlash 副本的 `employees` 表为例: ```sql CREATE TABLE employees ( @@ -72,26 +71,30 @@ PARTITION BY LIST (store_id) ( ALTER TABLE employees SET TIFLASH REPLICA 2; ``` -执行以下语句可对 `employees` 表上 `pNorth`、`pEast` 这两个分区的 2 个 TiFlash 副本立即进行数据整理: +你可以执行以下语句立即对 `employees` 表中 `pNorth` 和 `pEast` 分区的 2 个 TiFlash 副本启动压缩: ```sql ALTER TABLE employees COMPACT PARTITION pNorth, pEast TIFLASH REPLICA; ``` -## 并发度 +## 并发性 + +`ALTER TABLE ... COMPACT` 语句同时压缩表中的所有副本。 + +为了避免对在线业务产生重大影响,默认情况下每个 TiFlash 实例一次只压缩一个表的数据(后台触发的压缩除外)。这意味着如果你同时对多个表执行 `ALTER TABLE ... COMPACT` 语句,它们的执行将在同一个 TiFlash 实例上排队,而不是同时执行。 -`ALTER TABLE ... COMPACT` 语句会同时对表中所有副本发起数据整理操作。 + -为了避免数据整理操作对在线业务造成显著影响,在同一时间,每个 TiFlash 实例默认只会处理一张表的数据整理操作(后台自动触发的数据整理除外)。这意味着,若你同时对多张表执行 `ALTER TABLE ... COMPACT` 语句,则它们在同一个 TiFlash 实例上会排队依次执行,而非同时执行。 +要获得更高的表级并发性和更高的资源使用率,你可以修改 TiFlash 配置 [`manual_compact_pool_size`](/tiflash/tiflash-configuration.md)。例如,当 `manual_compact_pool_size` 设置为 2 时,可以同时处理 2 个表的压缩。 -你可以修改 TiFlash 配置文件参数 [`manual_compact_pool_size`](/tiflash/tiflash-configuration.md),以更大资源占用为代价、获得更大的表级别并发度。例如,参数指定为 2 时,可以同时对 2 张表进行数据整理。 + -## 观测数据整理进度 +## 观察数据压缩进度 -你可以通过 `INFORMATION_SCHEMA.TIFLASH_TABLES` 表中 `TOTAL_DELTA_ROWS` 列来观测 TiFlash 存储引擎上数据整理的进度,或判断是否有必要对某张表发起数据整理。`TOTAL_DELTA_ROWS` 的值越大,说明还能被整理的数据越多;若 `TOTAL_DELTA_ROWS` 为 `0`,说明表中所有数据都处于最佳状态,无需整理。 +你可以通过检查 `INFORMATION_SCHEMA.TIFLASH_TABLES` 表中的 `TOTAL_DELTA_ROWS` 列来观察数据压缩的进度或确定是否需要对表启动压缩。`TOTAL_DELTA_ROWS` 的值越大,可以压缩的数据就越多。如果 `TOTAL_DELTA_ROWS` 为 `0`,则表中的所有数据都处于最佳状态,不需要压缩。
- 示例:查询普通表的数据整理状态 + 示例:检查非分区表的压缩状态 ```sql USE test; @@ -119,7 +122,7 @@ SELECT TOTAL_DELTA_ROWS, TOTAL_STABLE_ROWS FROM INFORMATION_SCHEMA.TIFLASH_TABLE +------------------+-------------------+ | 3 | 0 | +------------------+-------------------+ --- 新写入的数据可被整理 +-- 新写入的数据可以压缩 ALTER TABLE foo COMPACT TIFLASH REPLICA; @@ -131,13 +134,13 @@ SELECT TOTAL_DELTA_ROWS, TOTAL_STABLE_ROWS FROM INFORMATION_SCHEMA.TIFLASH_TABLE +------------------+-------------------+ | 0 | 3 | +------------------+-------------------+ --- 所有数据都处于最佳整理状态 +-- 所有数据都处于最佳状态,不需要压缩 ```
- 示例:查询分区表的数据整理状态 + 示例:检查分区表的压缩状态 ```sql USE test; @@ -167,7 +170,7 @@ SELECT PARTITION_NAME, TOTAL_DELTA_ROWS, TOTAL_STABLE_ROWS | pWest | 0 | 0 | | pCentral | 0 | 0 | +----------------+------------------+-------------------+ --- 一些分区上有数据可被整理 +-- 某些分区可以压缩 ALTER TABLE employees COMPACT TIFLASH REPLICA; @@ -183,28 +186,28 @@ SELECT PARTITION_NAME, TOTAL_DELTA_ROWS, TOTAL_STABLE_ROWS | pWest | 0 | 0 | | pCentral | 0 | 0 | +----------------+------------------+-------------------+ --- 所有分区上的数据都处于最佳整理状态 +-- 所有分区中的数据都处于最佳状态,不需要压缩 ```
> **注意:** > -> - 若数据整理的过程中发生了数据更新,你可能观察到数据整理完毕后 `TOTAL_DELTA_ROWS` 仍为非零值。这是正常现象,表明这些更新部分没有被整理到。若你想对这部分更新数据也进行整理,可再次执行 `ALTER TABLE ... COMPACT` 语句。 +> - 如果在压缩过程中更新了数据,压缩完成后 `TOTAL_DELTA_ROWS` 可能仍然是非零值。这是正常的,表示这些更新尚未被压缩。要压缩这些更新,请再次执行 `ALTER TABLE ... COMPACT` 语句。 > -> - `TOTAL_DELTA_ROWS` 的单位是数据版本数,而非数据行数。例如,插入一行记录再删除该行后,`TOTAL_DELTA_ROWS` 会增加 2。 +> - `TOTAL_DELTA_ROWS` 表示数据版本,而不是行数。例如,如果你插入一行然后删除它,`TOTAL_DELTA_ROWS` 将增加 2。 ## 兼容性 ### MySQL 兼容性 -`ALTER TABLE ... COMPACT` 语法是 TiDB 引入的对标准 SQL 语法的扩展。尽管没有对应的 MySQL 语法,但你仍然可通过 MySQL 各版本客户端,或各个遵循 MySQL 协议的数据库驱动执行该语句。 +`ALTER TABLE ... COMPACT` 语法是 TiDB 特有的,是对标准 SQL 语法的扩展。虽然没有等效的 MySQL 语法,但你仍然可以使用符合 MySQL 协议的 MySQL 客户端或各种数据库驱动程序执行此语句。 -### TiDB Binlog 及 TiCDC 兼容性 +### TiDB Binlog 和 TiCDC 兼容性 -`ALTER TABLE ... COMPACT` 语句不会导致逻辑数据变化,因而不会被 TiDB Binlog 及 TiCDC 同步到下游。 +`ALTER TABLE ... COMPACT` 语句不会导致逻辑数据更改,因此不会被 TiDB Binlog 或 TiCDC 复制到下游。 ## 另请参阅 - [ALTER TABLE](/sql-statements/sql-statement-alter-table.md) -- [KILL](/sql-statements/sql-statement-kill.md) +- [KILL TIDB](/sql-statements/sql-statement-kill.md) diff --git a/sql-statements/sql-statement-alter-table.md b/sql-statements/sql-statement-alter-table.md index 26c4a7e068cc..25eaec0fcfa6 100644 --- a/sql-statements/sql-statement-alter-table.md +++ b/sql-statements/sql-statement-alter-table.md @@ -1,17 +1,17 @@ --- -title: ALTER TABLE -summary: TiDB 数据库中 ALTER TABLE 的使用概况。 +title: ALTER TABLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 ALTER TABLE 的使用概览。 --- # ALTER TABLE -`ALTER TABLE` 语句用于对已有表进行修改,以符合新表结构。`ALTER TABLE` 语句可用于: +此语句修改现有表以符合新的表结构。`ALTER TABLE` 语句可用于: -- [`ADD`](/sql-statements/sql-statement-add-index.md),[`DROP`](/sql-statements/sql-statement-drop-index.md),或 [`RENAME`](/sql-statements/sql-statement-rename-index.md) 索引 -- [`ADD`](/sql-statements/sql-statement-add-column.md),[`DROP`](/sql-statements/sql-statement-drop-column.md),[`MODIFY`](/sql-statements/sql-statement-modify-column.md) 或 [`CHANGE`](/sql-statements/sql-statement-change-column.md) 列 +- [`ADD`](/sql-statements/sql-statement-add-index.md)、[`DROP`](/sql-statements/sql-statement-drop-index.md) 或 [`RENAME`](/sql-statements/sql-statement-rename-index.md) 索引 +- [`ADD`](/sql-statements/sql-statement-add-column.md)、[`DROP`](/sql-statements/sql-statement-drop-column.md)、[`MODIFY`](/sql-statements/sql-statement-modify-column.md) 或 [`CHANGE`](/sql-statements/sql-statement-change-column.md) 列 - [`COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) 表数据 -## 语法图 +## 语法 ```ebnf+diagram AlterTableStmt ::= @@ -63,7 +63,7 @@ PlacementPolicyOption ::= ## 示例 -创建一张表,并插入初始数据: +创建一个包含一些初始数据的表: {{< copyable "sql" >}} @@ -74,11 +74,12 @@ INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); ```sql Query OK, 0 rows affected (0.11 sec) + Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 ``` -执行以下查询需要扫描全表,因为 `c1` 列未被索引: +由于列 c1 没有索引,以下查询需要进行全表扫描: {{< copyable "sql" >}} @@ -97,7 +98,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; 3 rows in set (0.00 sec) ``` -你可以使用 [`ALTER TABLE .. ADD INDEX`](/sql-statements/sql-statement-add-index.md) 语句在 `t1` 表上添加索引。添加后,`EXPLAIN` 的分析结果显示 `SELECT * FROM t1 WHERE c1 = 3;` 查询已使用效率更高的索引范围扫描: +可以使用 [`ALTER TABLE .. ADD INDEX`](/sql-statements/sql-statement-add-index.md) 语句在表 t1 上添加索引。`EXPLAIN` 确认原始查询现在使用索引范围扫描,这更有效率: {{< copyable "sql" >}} @@ -108,6 +109,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; ```sql Query OK, 0 rows affected (0.30 sec) + +------------------------+---------+-----------+------------------------+---------------------------------------------+ | id | estRows | task | access object | operator info | +------------------------+---------+-----------+------------------------+---------------------------------------------+ @@ -117,7 +119,7 @@ Query OK, 0 rows affected (0.30 sec) 2 rows in set (0.00 sec) ``` -TiDB 允许用户为 DDL 操作指定使用某一种 `ALTER` 算法。注意这仅为一种指定,并不改变实际的用于更改表的算法: +TiDB 支持断言 DDL 更改使用特定的 `ALTER` 算法。请注意,这只是一个断言,不会改变实际用于修改表的算法: {{< copyable "sql" >}} @@ -129,7 +131,7 @@ ALTER TABLE t1 DROP INDEX c1, ALGORITHM=INSTANT; Query OK, 0 rows affected (0.24 sec) ``` -如果某一 DDL 操作要求使用 `INPLACE` 算法,而用户指定 `ALGORITHM=INSTANT`,会导致报错: +在需要 `INPLACE` 算法的操作上使用 `ALGORITHM=INSTANT` 断言会导致语句错误: {{< copyable "sql" >}} @@ -141,7 +143,7 @@ ALTER TABLE t1 ADD INDEX (c1), ALGORITHM=INSTANT; ERROR 1846 (0A000): ALGORITHM=INSTANT is not supported. Reason: Cannot alter table by INSTANT. Try ALGORITHM=INPLACE. ``` -但如果为 `INPLACE` 操作指定 `ALGORITHM=COPY`,会产生警告而非错误,这是因为 TiDB 将该指定解读为*该算法或更好的算法*。由于 TiDB 使用的算法可能不同于 MySQL,所以这一行为可用于 MySQL 兼容性。 +但是,对于 `INPLACE` 操作使用 `ALGORITHM=COPY` 断言会生成警告而不是错误。这是因为 TiDB 将断言解释为_此算法或更好的算法_。这种行为差异对于 MySQL 兼容性很有用,因为 TiDB 使用的算法可能与 MySQL 不同: {{< copyable "sql" >}} @@ -152,6 +154,7 @@ SHOW WARNINGS; ```sql Query OK, 0 rows affected, 1 warning (0.25 sec) + +-------+------+---------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+---------------------------------------------------------------------------------------------+ @@ -162,25 +165,31 @@ Query OK, 0 rows affected, 1 warning (0.25 sec) ## MySQL 兼容性 -TiDB 中的 `ALTER TABLE` 语法主要存在以下限制: +TiDB 中的 `ALTER TABLE` 有以下主要限制: + +- 在单个 `ALTER TABLE` 语句中修改多个 schema 对象时: + + - 不支持在多个更改中修改同一对象。 + - TiDB 在**执行前**根据表 schema 验证语句。例如,执行 `ALTER TABLE t ADD COLUMN c1 INT, ADD COLUMN c2 INT AFTER c1;` 时会返回错误,因为表中不存在列 `c1`。 + - 对于 `ALTER TABLE` 语句,TiDB 的执行顺序是从左到右一个接一个地执行更改,这在某些情况下与 MySQL 不兼容。 + +- 不支持对主键列进行 [Reorg-Data](/sql-statements/sql-statement-modify-column.md#reorg-data-change) 类型的更改。 + +- 不支持对分区表进行列类型更改。 + +- 不支持对生成列进行列类型更改。 + +- 由于 TiDB 和 MySQL 之间 `CAST` 函数行为的兼容性问题,不支持某些数据类型的更改(例如,某些 TIME、Bit、Set、Enum 和 JSON 类型)。 -- 使用 `ALTER TABLE` 语句修改一个表的多个模式对象(如列、索引)时: - - 不允许在多个更改中指定同一个模式对象。 - - TiDB 根据**执行前**的表结构检查合法性。例如 `ALTER TABLE t ADD COLUMN c1 INT, ADD COLUMN c2 INT AFTER c1;` 会报错,因为表结构中不存在名字为 `c1` 的列。 - - TiDB 的执行顺序是从左往右逐个执行更改,该行为在个别场景下和 MySQL 不兼容。 -- 不支持主键列上 [Reorg-Data](/sql-statements/sql-statement-modify-column.md#reorg-data-change) 类型的变更。 -- 不支持分区表上的列类型变更。 -- 不支持生成列上的列类型变更。 -- 不支持部分数据类型(例如,部分时间类型、Bit、Set、Enum、JSON 等)的变更,因为 TiDB 中的 `CAST` 函数与 MySQL 的行为存在兼容性问题。 - 不支持空间数据类型。 -- `ALTER TABLE t CACHE | NOCACHE` 不是 MySQL 标准语法,而是 TiDB 扩展功能,参见[缓存表](/cached-tables.md)。 -其它限制可参考:[TiDB 中 DDL 语句与 MySQL 的兼容性情况](/mysql-compatibility.md#ddl-的限制)。 +- `ALTER TABLE t CACHE | NOCACHE` 是 TiDB 对 MySQL 语法的扩展。详情请参见[缓存表](/cached-tables.md)。 + +有关更多限制,请参见 [MySQL 兼容性](/mysql-compatibility.md#ddl-operations)。 ## 另请参阅 -- [与 MySQL 兼容性对比](/mysql-compatibility.md#ddl-的限制) -- [ALTER TABLE ... COMPACT](/sql-statements/sql-statement-alter-table-compact.md) +- [MySQL 兼容性](/mysql-compatibility.md#ddl-operations) - [ADD COLUMN](/sql-statements/sql-statement-add-column.md) - [DROP COLUMN](/sql-statements/sql-statement-drop-column.md) - [ADD INDEX](/sql-statements/sql-statement-add-index.md) diff --git a/sql-statements/sql-statement-alter-user.md b/sql-statements/sql-statement-alter-user.md index c86d081d4405..a31da31ac33e 100644 --- a/sql-statements/sql-statement-alter-user.md +++ b/sql-statements/sql-statement-alter-user.md @@ -1,13 +1,13 @@ --- -title: ALTER USER -summary: TiDB 数据库中 ALTER USER 的使用概况。 +title: ALTER USER | TiDB SQL 语句参考 +summary: TiDB 数据库中 ALTER USER 的使用概述。 --- # ALTER USER -`ALTER USER` 语句用于更改 TiDB 权限系统内的已有用户。和 MySQL 一样,在 TiDB 权限系统中,用户是用户名和用户名所连接主机的组合。因此,可创建一个用户 `'newuser2'@'192.168.1.1'`,使其只能通过 IP 地址 `192.168.1.1` 进行连接。相同的用户名从不同主机登录时可能会拥有不同的权限。 +此语句用于在 TiDB 权限系统中修改现有用户。在 MySQL 权限系统中,用户是用户名和连接来源主机的组合。因此,可以创建一个只能从 IP 地址 `192.168.1.1` 连接的用户 `'newuser2'@'192.168.1.1'`。同时也可以让两个用户具有相同的用户部分,但由于从不同主机登录而具有不同的权限。 -## 语法图 +## 语法概要 ```ebnf+diagram AlterUserStmt ::= @@ -46,23 +46,11 @@ RequireListElement ::= 'ISSUER' Issuer | 'SUBJECT' Subject | 'CIPHER' Cipher | ' ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE USER 'newuser' IDENTIFIED BY 'newuserpassword'; -``` - -``` +mysql> CREATE USER 'newuser' IDENTIFIED BY 'newuserpassword'; Query OK, 1 row affected (0.01 sec) -``` - -{{< copyable "sql" >}} -```sql -SHOW CREATE USER 'newuser'; -``` - -``` +mysql> SHOW CREATE USER 'newuser'; +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE USER for newuser@% | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -71,25 +59,15 @@ SHOW CREATE USER 'newuser'; 1 row in set (0.00 sec) ``` -### 修改用户基本信息 +### 修改基本用户信息 -修改用户 `newuser` 的密码: +更改用户 `newuser` 的密码: ```sql -ALTER USER 'newuser' IDENTIFIED BY 'newnewpassword'; -``` - -``` +mysql> ALTER USER 'newuser' IDENTIFIED BY 'newnewpassword'; Query OK, 0 rows affected (0.02 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW CREATE USER 'newuser'; -``` - -``` +mysql> SHOW CREATE USER 'newuser'; +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE USER for newuser@% | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -124,7 +102,7 @@ SELECT * FROM information_schema.user_attributes; 1 rows in set (0.00 sec) ``` -通过 `ALTER USER ... COMMENT` 修改用户 `newuser` 的注释: +使用 `ALTER USER ... COMMENT` 修改 `newuser` 的注释: ```sql ALTER USER 'newuser' COMMENT 'Here is the comment'; @@ -140,7 +118,7 @@ SELECT * FROM information_schema.user_attributes; 1 rows in set (0.00 sec) ``` -通过 `ALTER USER ... ATTRIBUTE` 删除用户 `newuser` 的注释: +使用 `ALTER USER ... ATTRIBUTE` 删除 `newuser` 的注释: ```sql ALTER USER 'newuser' ATTRIBUTE '{"comment": null}'; @@ -156,7 +134,7 @@ SELECT * FROM information_schema.user_attributes; 1 rows in set (0.00 sec) ``` -通过 `ALTER USER ... PASSWORD EXPIRE NEVER` 修改用户 `newuser` 的自动密码过期策略为永不过期: +通过 `ALTER USER ... PASSWORD EXPIRE NEVER` 将 `newuser` 的自动密码过期策略更改为永不过期: ```sql ALTER USER 'newuser' PASSWORD EXPIRE NEVER; @@ -166,7 +144,7 @@ ALTER USER 'newuser' PASSWORD EXPIRE NEVER; Query OK, 0 rows affected (0.02 sec) ``` -通过 `ALTER USER ... PASSWORD REUSE INTERVAL ... DAY` 修改用户 `newuser` 的密码重用策略为不允许重复使用最近 90 天内使用过的密码: +使用 `ALTER USER ... PASSWORD REUSE INTERVAL ... DAY` 修改 `newuser` 的密码重用策略,禁止重用最近 90 天内使用过的任何密码: ```sql ALTER USER 'newuser' PASSWORD REUSE INTERVAL 90 DAY; @@ -178,7 +156,7 @@ Query OK, 0 rows affected (0.02 sec) ### 修改用户绑定的资源组 -通过 `ALTER USER ... RESOURCE GROUP` 修改用户 `newuser` 的资源组到 `rg1`: +使用 `ALTER USER ... RESOURCE GROUP` 将用户 `newuser` 的资源组修改为 `rg1`。 ```sql ALTER USER 'newuser' RESOURCE GROUP rg1; @@ -203,7 +181,7 @@ SELECT USER, JSON_EXTRACT(User_attributes, "$.resource_group") FROM mysql.user W 1 row in set (0.02 sec) ``` -取消用户绑定的资源组,即将用户绑定到 `default` 资源组。 +解除用户与资源组的绑定,即绑定用户到 `default` 资源组。 ```sql ALTER USER 'newuser' RESOURCE GROUP `default`; @@ -221,7 +199,12 @@ SELECT USER, JSON_EXTRACT(User_attributes, "$.resource_group") FROM mysql.user W ## 另请参阅 -* [Security Compatibility with MySQL](/security-compatibility-with-mysql.md) + + +* [与 MySQL 的安全特性兼容性](/security-compatibility-with-mysql.md) + + + * [CREATE USER](/sql-statements/sql-statement-create-user.md) * [DROP USER](/sql-statements/sql-statement-drop-user.md) * [SHOW CREATE USER](/sql-statements/sql-statement-show-create-user.md) diff --git a/sql-statements/sql-statement-analyze-table.md b/sql-statements/sql-statement-analyze-table.md index f46cf33cee7e..ba4239fd687c 100644 --- a/sql-statements/sql-statement-analyze-table.md +++ b/sql-statements/sql-statement-analyze-table.md @@ -1,15 +1,15 @@ --- -title: ANALYZE -summary: TiDB 数据库中 ANALYZE 的使用概况。 +title: ANALYZE | TiDB SQL 语句参考 +summary: TiDB 数据库中 ANALYZE 的使用概览。 --- # ANALYZE -`ANALYZE` 语句用于更新 TiDB 在表和索引上留下的统计信息。执行大批量更新或导入记录后,或查询执行计划不是最佳时,建议运行 `ANALYZE`。 +该语句用于更新 TiDB 在表和索引上建立的统计信息。建议在执行大批量更新或导入记录后,或者当你发现查询执行计划不理想时运行 `ANALYZE`。 -当 TiDB 逐渐发现这些统计数据与预估不一致时,也会自动更新其统计数据。 +当 TiDB 发现统计信息与其自身估计不一致时,也会随着时间自动更新其统计信息。 -目前 TiDB 收集统计信息为全量收集,通过 `ANALYZE TABLE` 语句来实现。关于该语句的详细使用方式,可参考[常规统计信息](/statistics.md)。 +目前,TiDB 通过使用 `ANALYZE TABLE` 语句进行完整收集来收集统计信息。有关更多信息,请参阅[统计信息简介](/statistics.md)。 ## 语法图 @@ -47,44 +47,24 @@ PartitionNameList ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) ``` -{{< copyable "sql" >}} - ```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` - -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 ``` -{{< copyable "sql" >}} - ```sql -ALTER TABLE t1 ADD INDEX (c1); -``` - -``` +mysql> ALTER TABLE t1 ADD INDEX (c1); Query OK, 0 rows affected (0.30 sec) ``` -{{< copyable "sql" >}} - ```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` - -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +------------------------+---------+-----------+------------------------+---------------------------------------------+ | id | estRows | task | access object | operator info | +------------------------+---------+-----------+------------------------+---------------------------------------------+ @@ -94,25 +74,13 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; 2 rows in set (0.00 sec) ``` -当前的统计信息状态为 `pseudo`,表示统计信息不准确。 - -{{< copyable "sql" >}} +当前统计信息的状态是 `pseudo`,这意味着统计信息不准确。 ```sql -ANALYZE TABLE t1; -``` - -``` +mysql> ANALYZE TABLE t1; Query OK, 0 rows affected (0.13 sec) -``` -{{< copyable "sql" >}} - -```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` - -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +------------------------+---------+-----------+------------------------+-------------------------------+ | id | estRows | task | access object | operator info | +------------------------+---------+-----------+------------------------+-------------------------------+ @@ -122,16 +90,14 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; 2 rows in set (0.00 sec) ``` -统计信息已经正确地更新和加载。 +统计信息现在已正确更新并加载。 ## MySQL 兼容性 -`ANALYZE TABLE` 在语法上与 MySQL 类似。但 `ANALYZE TABLE` 在 TiDB 上的执行时间可能长得多,因为它的内部运行方式不同。 - -TiDB 与 MySQL 在以下方面存在区别:所收集的统计信息,以及查询执行过程中统计信息是如何被使用的。虽然 TiDB 中的 `ANALYZE` 语句在语法上与 MySQL 类似,但存在以下差异: +TiDB 在收集的统计信息和在查询执行期间如何使用统计信息方面**都**与 MySQL 不同。虽然此语句在语法上与 MySQL 类似,但以下差异适用: -+ 执行 `ANALYZE TABLE` 时,TiDB 可能不包含最近提交的更改。若对行进行了批量更改,在执行 `ANALYZE TABLE` 之前,你可能需要先执行 `sleep(1)`,这样统计信息更新才能反映这些更改。参见 [#16570](https://github.com/pingcap/tidb/issues/16570)。 -+ `ANALYZE TABLE` 在 TiDB 中的执行时间比在 MySQL 中的执行时间要长得多。 ++ 运行 `ANALYZE TABLE` 时,TiDB 可能不会包含最近提交的更改。在批量更新行后,你可能需要在执行 `ANALYZE TABLE` 之前执行 `sleep(1)`,以便统计信息更新能反映这些更改。参见 [#16570](https://github.com/pingcap/tidb/issues/16570)。 ++ `ANALYZE TABLE` 在 TiDB 中的执行时间明显长于 MySQL。 ## 另请参阅 diff --git a/sql-statements/sql-statement-backup.md b/sql-statements/sql-statement-backup.md index abf3f6099617..bfedd4a9c985 100644 --- a/sql-statements/sql-statement-backup.md +++ b/sql-statements/sql-statement-backup.md @@ -1,25 +1,28 @@ --- -title: BACKUP -summary: TiDB 数据库中 BACKUP 的使用概况。 +title: BACKUP | TiDB SQL 语句参考 +summary: TiDB 数据库中 BACKUP 的使用概述。 --- # BACKUP +此语句用于执行 TiDB 集群的分布式备份。 + > **警告:** > -> `BACKUP` 语句目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> - 此功能为实验特性。不建议在生产环境中使用。此功能可能会在没有预先通知的情况下发生变更或移除。如果发现 bug,可以在 GitHub 上提交[议题](https://github.com/pingcap/tidb/issues)。 +> - 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 -`BACKUP` 语句用于对 TiDB 集群执行分布式备份操作。 +`BACKUP` 语句使用与 [BR 工具](https://docs.pingcap.com/tidb/stable/backup-and-restore-overview)相同的引擎,不同之处在于备份过程由 TiDB 本身驱动,而不是由独立的 BR 工具驱动。BR 的所有优点和警告也适用于此语句。 -`BACKUP` 语句使用的引擎与 [BR](/br/backup-and-restore-overview.md) 相同,但备份过程是由 TiDB 本身驱动,而非单独的 BR 工具。BR 工具的优势和警告也适用于 `BACKUP` 语句。 +执行 `BACKUP` 需要 `BACKUP_ADMIN` 或 `SUPER` 权限。此外,执行备份的 TiDB 节点和集群中的所有 TiKV 节点都必须对目标位置具有读写权限。当启用[安全增强模式](/system-variables.md#tidb_enable_enhanced_security)时,不允许使用本地存储(以 `local://` 开头的存储路径)。 -执行 `BACKUP` 需要 `BACKUP_ADMIN` 或 `SUPER` 权限。此外,执行备份的 TiDB 节点和集群中的所有 TiKV 节点都必须有对目标存储的读或写权限。 +`BACKUP` 语句会阻塞直到整个备份任务完成、失败或被取消。执行 `BACKUP` 需要准备一个长期连接。可以使用 [`KILL TIDB QUERY`](/sql-statements/sql-statement-kill.md) 语句取消任务。 -`BACKUP` 语句开始执行后将会被阻塞,直到整个备份任务完成、失败或取消。因此,执行 `BACKUP` 时需要准备一个持久的连接。如需取消任务,可执行 [`KILL TIDB QUERY`](/sql-statements/sql-statement-kill.md) 语句。 +同一时间只能执行一个 `BACKUP` 和 [`RESTORE`](/sql-statements/sql-statement-restore.md) 任务。如果在同一 TiDB 服务器上已经在执行 `BACKUP` 或 `RESTORE` 语句,新的 `BACKUP` 执行将等待所有先前的任务完成。 -一次只能执行一个 `BACKUP` 和 [`RESTORE`](/sql-statements/sql-statement-restore.md) 任务。如果 TiDB server 上已经在执行一个 `BACKUP` 或 `RESTORE` 语句,新的 `BACKUP` 将等待前面所有的任务完成后再执行。 +`BACKUP` 只能与 "tikv" 存储引擎一起使用。使用 "unistore" 引擎的 `BACKUP` 将失败。 -## 语法图 +## 语法概要 ```ebnf+diagram BackupStmt ::= @@ -63,16 +66,16 @@ BACKUP DATABASE `test` TO 'local:///mnt/backup/2020/04/'; 1 row in set (58.453 sec) ``` -上述示例中,`test` 数据库被备份到本地,数据以 SST 文件的形式存储在分布于所有 TiDB 和 TiKV 节点的 `/mnt/backup/2020/04/` 目录中。 +在上面的示例中,`test` 数据库被备份到本地文件系统。数据以 SST 文件的形式保存在所有 TiDB 和 TiKV 节点的 `/mnt/backup/2020/04/` 目录中。 -输出结果的第一行描述如下: +上面结果的第一行描述如下: -| 列名 | 描述 | +| 列 | 描述 | | :-------- | :--------- | -| `Destination` | 目标存储的 URL | -| `Size` | 备份文件的总大小,单位为字节 | -| `BackupTS` | 创建备份时的快照 TSO(用于[增量备份](#增量备份)) | -| `Queue Time` | `BACKUP` 任务开始排队的时间戳(当前时区) | +| `Destination` | 目标 URL | +| `Size` | 备份存档的总大小,以字节为单位 | +| `BackupTS` | 创建备份时快照的 TSO(对[增量备份](#增量备份)有用) | +| `Queue Time` | `BACKUP` 任务排队的时间戳(当前时区) | | `Execution Time` | `BACKUP` 任务开始执行的时间戳(当前时区) | ### 备份表 @@ -89,7 +92,7 @@ BACKUP TABLE `test`.`sbtest01` TO 'local:///mnt/backup/sbtest01/'; BACKUP TABLE sbtest02, sbtest03, sbtest04 TO 'local:///mnt/backup/sbtest/'; ``` -### 备份集群 +### 备份整个集群 {{< copyable "sql" >}} @@ -97,11 +100,11 @@ BACKUP TABLE sbtest02, sbtest03, sbtest04 TO 'local:///mnt/backup/sbtest/'; BACKUP DATABASE * TO 'local:///mnt/backup/full/'; ``` -注意,备份中不包含系统表(`mysql.*`、`INFORMATION_SCHEMA.*`、`PERFORMANCE_SCHEMA.*` 等)。 +注意,系统表(`mysql.*`、`INFORMATION_SCHEMA.*`、`PERFORMANCE_SCHEMA.*` 等)不会包含在备份中。 ### 外部存储 -BR 支持备份数据到 Amazon S3 或 Google Cloud Storage (GCS): +BR 支持将数据备份到 S3 或 GCS: {{< copyable "sql" >}} @@ -109,9 +112,9 @@ BR 支持备份数据到 Amazon S3 或 Google Cloud Storage (GCS): BACKUP DATABASE `test` TO 's3://example-bucket-2020/backup-05/?access-key={YOUR_ACCESS_KEY}&secret-access-key={YOUR_SECRET_KEY}'; ``` -有关详细的 URL 语法,见[外部存储服务的 URI 格式](/external-storage-uri.md)。 +URL 语法在[外部存储服务的 URI 格式](/external-storage-uri.md)中有进一步说明。 -当运行在云环境中时,不能分发凭证,可设置 `SEND_CREDENTIALS_TO_TIKV` 选项为 `FALSE`: +在不应分发凭证的云环境中运行时,将 `SEND_CREDENTIALS_TO_TIKV` 选项设置为 `FALSE`: {{< copyable "sql" >}} @@ -122,11 +125,13 @@ BACKUP DATABASE `test` TO 's3://example-bucket-2020/backup-05/' ### 性能调优 -如果你需要减少网络带宽占用,可以通过 `RATE_LIMIT` 来限制每个 TiKV 节点的平均上传速度。 +使用 `RATE_LIMIT` 限制每个 TiKV 节点的平均上传速度以减少网络带宽。 + +在备份完成之前,`BACKUP` 会对集群上的数据执行校验和以验证正确性。如果你确信这种验证是不必要的,可以通过将 `CHECKSUM` 参数设置为 `FALSE` 来禁用检查。 -在备份完成之前,`BACKUP` 将对集群上的数据执行校验和以验证数据正确性。如果你确定无需进行校验,可以通过将 `CHECKSUM` 参数设置为 `FALSE` 来禁用该检查。 +要指定 BR 可以执行备份表和索引的并发任务数,请使用 `CONCURRENCY` 参数。此参数控制 BR 内的线程池大小,优化备份操作的性能和效率。 -要指定 BR 可以同时执行的备份表和索引的任务数量,可使用 `CONCURRENCY`。该参数控制 BR 的线程池大小,可以优化备份操作的性能和效率。根据备份类型不同,一个任务代表一个表范围或一个索引范围。如果有一个表带有一个索引,则会有两个任务来备份这个表。参数 `CONCURRENCY` 的默认值为 `4`,如果你要备份许多表或索引,需调大该参数的值。 +一个任务代表一个表范围或一个索引范围,具体取决于备份架构。对于一个有一个索引的表,使用两个任务来备份这个表。`CONCURRENCY` 的默认值是 `4`。如果需要备份大量的表或索引,请增加其值。 {{< copyable "sql" >}} @@ -139,7 +144,7 @@ BACKUP DATABASE `test` TO 's3://example-bucket-2020/backup-06/' ### 快照 -可以指定一个时间戳、TSO 或相对时间,来备份历史数据。 +指定时间戳、TSO 或相对时间来备份历史数据。 {{< copyable "sql" >}} @@ -147,28 +152,30 @@ BACKUP DATABASE `test` TO 's3://example-bucket-2020/backup-06/' -- 相对时间 BACKUP DATABASE `test` TO 'local:///mnt/backup/hist01' SNAPSHOT = 36 HOUR AGO; + -- 时间戳(当前时区) BACKUP DATABASE `test` TO 'local:///mnt/backup/hist02' SNAPSHOT = '2020-04-01 12:00:00'; --- TSO + +-- 时间戳 oracle BACKUP DATABASE `test` TO 'local:///mnt/backup/hist03' SNAPSHOT = 415685305958400; ``` -对于相对时间,支持以下时间单位: +相对时间支持的单位有: -* MICROSECOND(微秒) -* SECOND(秒) -* MINUTE(分钟) -* HOUR(小时) -* DAY(天) -* WEEK(周) +* MICROSECOND +* SECOND +* MINUTE +* HOUR +* DAY +* WEEK -注意,相对时间的单位遵循 SQL 标准,永远使用单数。 +注意,按照 SQL 标准,单位始终是单数形式。 ### 增量备份 -提供 `LAST_BACKUP` 选项,只备份从上一次备份到当前快照之间的增量数据。 +提供 `LAST_BACKUP` 选项仅备份从上次备份到当前快照之间的更改。 {{< copyable "sql" >}} @@ -177,14 +184,14 @@ BACKUP DATABASE `test` TO 'local:///mnt/backup/hist03' BACKUP DATABASE `test` TO 'local:///mnt/backup/hist02' LAST_BACKUP = '2020-04-01 12:00:00'; --- TSO +-- 时间戳 oracle BACKUP DATABASE `test` TO 'local:///mnt/backup/hist03' LAST_BACKUP = 415685305958400; ``` ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 diff --git a/sql-statements/sql-statement-batch.md b/sql-statements/sql-statement-batch.md index 704834bd7641..fc48adfd33e0 100644 --- a/sql-statements/sql-statement-batch.md +++ b/sql-statements/sql-statement-batch.md @@ -1,25 +1,25 @@ --- title: BATCH -summary: TiDB 数据库中 BATCH 的使用概况。 +summary: TiDB 数据库中 BATCH 的使用概述。 --- # BATCH -BATCH 语句将一个 DML 语句拆成多个语句在内部执行,因此**不保证**事务的原子性和隔离性,是一个“非事务”语句。 +`BATCH` 语法在 TiDB 中将一个 DML 语句拆分为多个语句执行。这意味着**不保证**事务的原子性和隔离性。因此,它是一个"非事务性"语句。 -目前 BATCH 语句支持 `INSERT`、`REPLACE`、`UPDATE`、`DELETE`。 +目前,`BATCH` 支持 `INSERT`、`REPLACE`、`UPDATE` 和 `DELETE` 操作。 -BATCH 语句在某一列将 DML 语句涉及的范围划分为多个区间,在每个区间执行一条 SQL。 +基于一个列,`BATCH` 语法将 DML 语句划分为多个范围作用域来执行。在每个范围内,执行一个单独的 SQL 语句。 -详细的说明和使用限制见[非事务语句](/non-transactional-dml.md)。 +有关使用方法和限制的详细信息,请参见[非事务性 DML 语句](/non-transactional-dml.md)。 -在涉及多表 join 时,`BATCH` 语法中指定拆分列时需要指明完整的路径以避免歧义,如: +当你在 `BATCH` 语句中使用多表连接时,需要指定列的完整路径以避免歧义: ```sql BATCH ON test.t2.id LIMIT 1 INSERT INTO t SELECT t2.id, t2.v, t3.v FROM t2 JOIN t3 ON t2.k = t3.k; ``` -上面这条语句的拆分列用 `test.t2.id` 指明,不具有歧义。如果写成如下 `id` 的形式,则会报错: +上述语句将要拆分的列指定为 `test.t2.id`,这是没有歧义的。如果你像下面这样使用 `id`,将会报错: ```sql BATCH ON id LIMIT 1 INSERT INTO t SELECT t2.id, t2.v, t3.v FROM t2 JOIN t3 ON t2.k = t3.k; @@ -27,7 +27,7 @@ BATCH ON id LIMIT 1 INSERT INTO t SELECT t2.id, t2.v, t3.v FROM t2 JOIN t3 ON t2 Non-transactional DML, shard column must be fully specified ``` -## 语法图 +## 语法 ```ebnf+diagram NonTransactionalDMLStmt ::= @@ -45,8 +45,8 @@ ShardableStmt ::= ## MySQL 兼容性 -BATCH 语句是 TiDB 独有的语句,与 MySQL 不兼容。 +`BATCH` 语法是 TiDB 特有的,与 MySQL 不兼容。 ## 另请参阅 -* [非事务语句](/non-transactional-dml.md) +* [非事务性 DML 语句](/non-transactional-dml.md) diff --git a/sql-statements/sql-statement-begin.md b/sql-statements/sql-statement-begin.md index a0cc3881963f..4d054db543ad 100644 --- a/sql-statements/sql-statement-begin.md +++ b/sql-statements/sql-statement-begin.md @@ -1,15 +1,15 @@ --- -title: BEGIN -summary: TiDB 数据库中 BEGIN 的使用概况。 +title: BEGIN | TiDB SQL 语句参考 +summary: TiDB 数据库中 BEGIN 的使用概览。 --- # BEGIN -`BEGIN` 语句用于在 TiDB 内启动一个新事务,类似于 `START TRANSACTION` 和 `SET autocommit=0` 语句。 +此语句在 TiDB 中开启一个新的事务。它类似于 `START TRANSACTION` 和 `SET autocommit=0` 语句。 -在没有 `BEGIN` 语句的情况下,每个语句默认在各自的事务中自动提交,从而确保 MySQL 兼容性。 +在没有 `BEGIN` 语句的情况下,每个语句默认会在自己的事务中自动提交。这种行为确保了与 MySQL 的兼容性。 -## 语法图 +## 语法 ```ebnf+diagram BeginTransactionStmt ::= @@ -19,49 +19,23 @@ BeginTransactionStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a int NOT NULL PRIMARY KEY); -``` - -``` +mysql> CREATE TABLE t1 (a int NOT NULL PRIMARY KEY); Query OK, 0 rows affected (0.12 sec) -``` - -{{< copyable "sql" >}} -```sql -BEGIN; -``` - -``` +mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (1); -``` - -``` +mysql> INSERT INTO t1 VALUES (1); Query OK, 1 row affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -COMMIT; -``` - -``` +mysql> COMMIT; Query OK, 0 rows affected (0.01 sec) ``` ## MySQL 兼容性 -TiDB 支持 `BEGIN PESSIMISTIC` 或 `BEGIN OPTIMISTIC` 的语法扩展,用户可以为某一个事务覆盖默认的事务模型。 +TiDB 支持 `BEGIN PESSIMISTIC` 或 `BEGIN OPTIMISTIC` 的语法扩展。这使你可以为你的事务覆盖默认的事务模型。 ## 另请参阅 diff --git a/sql-statements/sql-statement-cancel-import-job.md b/sql-statements/sql-statement-cancel-import-job.md index c92efcad38a4..942c4e427ab3 100644 --- a/sql-statements/sql-statement-cancel-import-job.md +++ b/sql-statements/sql-statement-cancel-import-job.md @@ -1,17 +1,17 @@ --- title: CANCEL IMPORT -summary: TiDB 数据库中 CANCEL IMPORT 的使用概况。 +summary: TiDB 中 CANCEL IMPORT 的使用概述。 --- # CANCEL IMPORT -`CANCEL IMPORT` 语句用于取消 TiDB 中创建的数据导入任务。 +`CANCEL IMPORT` 语句用于取消在 TiDB 中创建的数据导入任务。 ## 所需权限 -只有导入任务的创建者或拥有 `SUPER` 权限的用户才能够取消任务。 +要取消数据导入任务,你需要是导入任务的创建者或具有 `SUPER` 权限。 -## 语法图 +## 语法 ```ebnf+diagram CancelImportJobsStmt ::= @@ -20,13 +20,13 @@ CancelImportJobsStmt ::= ## 示例 -下面示例取消 ID 为 1 的导入任务: +要取消 ID 为 `1` 的导入任务,执行以下语句: ```sql CANCEL IMPORT JOB 1; ``` -输出结果如下: +输出如下: ``` Query OK, 0 rows affected (0.01 sec) diff --git a/sql-statements/sql-statement-change-column.md b/sql-statements/sql-statement-change-column.md index 0d8aef0d590e..e67478d589be 100644 --- a/sql-statements/sql-statement-change-column.md +++ b/sql-statements/sql-statement-change-column.md @@ -1,19 +1,19 @@ --- -title: CHANGE COLUMN -summary: TiDB 数据库中 CHANGE COLUMN 的使用概况。 +title: CHANGE COLUMN | TiDB SQL 语句参考 +summary: TiDB 数据库中 CHANGE COLUMN 的使用概述。 --- # CHANGE COLUMN -`ALTER TABLE.. CHANGE COLUMN` 语句用于在已有表上更改列,包括对列进行重命名,和将数据改为兼容类型。 +`ALTER TABLE.. CHANGE COLUMN` 语句用于修改现有表中的列。修改可以包括重命名列和将数据类型更改为兼容类型。 -从 v5.1.0 版本起,TiDB 开始支持 Reorg 数据的类型变更,包括但不限于: +从 v5.1.0 开始,TiDB 支持更改 Reorg 数据类型,包括但不限于: -- 从 varchar 转换为 bigint -- decimal 精度修改 -- 从 varchar(10) 到 varchar(5) 的长度压缩 +- 将 `VARCHAR` 更改为 `BIGINT` +- 修改 `DECIMAL` 精度 +- 将 `VARCHAR(10)` 的长度压缩为 `VARCHAR(5)` -## 语法图 +## 语法 ```ebnf+diagram AlterTableStmt @@ -148,10 +148,10 @@ ERROR 8200 (HY000): Unsupported modify column: change from original type decimal ## MySQL 兼容性 -* 不支持主键列上 [Reorg-Data](/sql-statements/sql-statement-modify-column.md#reorg-data-change) 类型的变更。 -* 不支持分区表上的列类型变更。 -* 不支持生成列上的列类型变更。 -* 不支持部分数据类型(例如,部分 TIME 类型、BIT、SET、ENUM、JSON 等)向某些类型的变更,因为 TiDB 的 `CAST` 函数与 MySQL 的行为存在兼容性问题。 +* 不支持对主键列进行 [Reorg-Data](/sql-statements/sql-statement-modify-column.md#reorg-data-change) 类型的更改。 +* 不支持对分区表进行列类型更改。 +* 不支持对生成列进行列类型更改。 +* 由于 TiDB 和 MySQL 之间 `CAST` 函数行为的兼容性问题,不支持将某些数据类型(例如 TIME、BIT、SET、ENUM 和 JSON 类型)更改为其他类型。 ## 另请参阅 diff --git a/sql-statements/sql-statement-commit.md b/sql-statements/sql-statement-commit.md index 8a64c8e9ab82..9fb53985ea0e 100644 --- a/sql-statements/sql-statement-commit.md +++ b/sql-statements/sql-statement-commit.md @@ -1,15 +1,15 @@ --- -title: COMMIT -summary: TiDB 数据库中 COMMIT 的使用概况。 +title: COMMIT | TiDB SQL 语句参考 +summary: TiDB 数据库中 COMMIT 的使用概述。 --- # COMMIT -`COMMIT` 语句用于在 TiDB 服务器内部提交事务。 +此语句用于在 TiDB 服务器中提交事务。 -在不使用 `BEGIN` 或 `START TRANSACTION` 语句的情况下,TiDB 中每一个查询语句本身也会默认作为事务处理,自动提交,确保了与 MySQL 的兼容。 +在没有 `BEGIN` 或 `START TRANSACTION` 语句的情况下,TiDB 的默认行为是每个语句都将是其自己的事务并自动提交。这种行为确保了与 MySQL 的兼容性。 -## 语法图 +## 语法 ```ebnf+diagram CommitStmt ::= @@ -22,57 +22,31 @@ CompletionTypeWithinTransaction ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a int NOT NULL PRIMARY KEY); -``` - -``` +mysql> CREATE TABLE t1 (a int NOT NULL PRIMARY KEY); Query OK, 0 rows affected (0.12 sec) -``` - -{{< copyable "sql" >}} -```sql -START TRANSACTION; -``` - -``` +mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (1); -``` - -``` +mysql> INSERT INTO t1 VALUES (1); Query OK, 1 row affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -COMMIT; -``` - -``` +mysql> COMMIT; Query OK, 0 rows affected (0.01 sec) ``` ## MySQL 兼容性 -* 目前,默认情况下 TiDB 使用元数据锁 (MDL) 来防止 DDL 语句修改事务使用的表,这与 MySQL 中的元数据锁在行为上有一些差别,具体可以参考[元数据锁](/metadata-lock.md)。 -* TiDB 3.0.8 及更新版本默认使用[悲观事务模式](/pessimistic-transaction.md)。在[乐观事务模型](/optimistic-transaction.md)下,需要考虑到修改的行已被另一个事务修改,导致 `COMMIT` 语句可能执行失败的情况。 -* 启用乐观事务模型后,`UNIQUE` 和 `PRIMARY KEY` 约束检查将延迟直至语句提交。当 `COMMIT` 语句失败时,这可能导致其他问题。可通过设置 `tidb_constraint_check_in_place=ON` 来改变该行为。 -* TiDB 解析但忽略 `ROLLBACK AND [NO] RELEASE` 语法。在 MySQL 中,使用该语法可在提交事务后立即断开客户端会话。在 TiDB 中,建议使用客户端程序的 `mysql_close()` 来实现该功能。 -* TiDB 解析但忽略 `ROLLBACK AND [NO] CHAIN` 语法。在 MySQL 中,使用该语法可在提交当前事务时立即以相同的隔离级别开启新事务。在 TiDB 中,推荐直接开启新事务。 +* 目前,TiDB 默认使用元数据锁(MDL)来防止 DDL 语句修改事务中使用的表。TiDB 和 MySQL 之间的元数据锁行为有所不同。更多详情,请参见[元数据锁](/metadata-lock.md)。 +* 默认情况下,TiDB 3.0.8 及更高版本使用[悲观锁定](/pessimistic-transaction.md)。在使用[乐观锁定](/optimistic-transaction.md)时,需要注意 `COMMIT` 语句可能会因为行被其他事务修改而失败。 +* 当启用乐观锁定时,`UNIQUE` 和 `PRIMARY KEY` 约束检查会延迟到语句提交时进行。这会导致 `COMMIT` 语句可能失败的额外情况。可以通过设置 `tidb_constraint_check_in_place=ON` 来改变这种行为。 +* TiDB 解析但忽略 `ROLLBACK AND [NO] RELEASE` 语法。在 MySQL 中,此功能用于在提交事务后立即断开客户端会话。在 TiDB 中,建议改用客户端驱动程序的 `mysql_close()` 功能。 +* TiDB 解析但忽略 `ROLLBACK AND [NO] CHAIN` 语法。在 MySQL 中,此功能用于在当前事务提交时立即以相同的隔离级别启动新事务。在 TiDB 中,建议直接启动新事务。 ## 另请参阅 * [START TRANSACTION](/sql-statements/sql-statement-start-transaction.md) * [ROLLBACK](/sql-statements/sql-statement-rollback.md) * [BEGIN](/sql-statements/sql-statement-begin.md) -* [事务的惰性检查](/transaction-overview.md#惰性检查) +* [约束的延迟检查](/transaction-overview.md#lazy-check-of-constraints) diff --git a/sql-statements/sql-statement-create-binding.md b/sql-statements/sql-statement-create-binding.md index 2ca1ad473118..f81fabb08d9c 100644 --- a/sql-statements/sql-statement-create-binding.md +++ b/sql-statements/sql-statement-create-binding.md @@ -1,17 +1,17 @@ --- title: CREATE [GLOBAL|SESSION] BINDING -summary: TiDB 数据库中 CREATE [GLOBAL|SESSION] BINDING 的使用概况。 +summary: TiDB 数据库中 CREATE BINDING 的使用。 --- # CREATE [GLOBAL|SESSION] BINDING -`CREATE [GLOBAL|SESSION] BINDING` 语句用于在 TiDB 中创建新的执行计划绑定。绑定可用于将优化器 Hint 插入语句中,而无需更改底层查询。 +此语句在 TiDB 中创建一个新的执行计划绑定。绑定可用于在不需要更改底层查询的情况下注入提示(hint)。 -`BINDING` 语句可以在 `GLOBAL` 或者 `SESSION` 作用域内创建执行计划绑定。在不指定作用域时,默认的作用域为 `SESSION`。 +`BINDING` 可以是 `GLOBAL` 或 `SESSION` 级别。默认为 `SESSION`。 -被绑定的 SQL 语句会被参数化后存储到系统表中。在处理 SQL 查询时,只要参数化后的 SQL 语句和系统表中某个被绑定的 SQL 语句一致,并且系统变量 `tidb_use_plan_baselines` 的值为 `ON`(其默认值为 `ON`),即可使用相应的优化器 Hint。如果存在多个可匹配的执行计划,优化器会从中选择代价最小的一个进行绑定。更多信息,请参考[创建绑定](/sql-plan-management.md#创建绑定)。 +绑定的 SQL 语句会被参数化并存储在系统表中。当处理 SQL 查询时,只要参数化的 SQL 语句与系统表中的绑定语句一致,且系统变量 `tidb_use_plan_baselines` 设置为 `ON`(默认值),相应的优化器提示就可用。如果有多个可用的执行计划,优化器会选择成本最低的计划进行绑定。更多信息,请参见[创建绑定](/sql-plan-management.md#create-a-binding)。 -## 语法图 +## 语法 ```ebnf+diagram CreateBindingStmt ::= @@ -29,50 +29,50 @@ BindableStmt ::= ## 示例 -你可以根据 SQL 或历史执行计划创建绑定。 +你可以根据 SQL 语句或历史执行计划创建绑定。 -下面的示例演示如何根据 SQL 创建绑定。 +以下示例展示如何根据 SQL 语句创建绑定。 {{< copyable "sql" >}} ```sql -CREATE TABLE t1 ( - id INT NOT NULL PRIMARY KEY auto_increment, - b INT NOT NULL, - pad VARBINARY(255), - INDEX(b) - ); +mysql> CREATE TABLE t1 ( + id INT NOT NULL PRIMARY KEY auto_increment, + b INT NOT NULL, + pad VARBINARY(255), + INDEX(b) + ); Query OK, 0 rows affected (0.07 sec) -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM dual; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM dual; Query OK, 1 row affected (0.01 sec) Records: 1 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 8 rows affected (0.00 sec) Records: 8 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 1000 rows affected (0.04 sec) Records: 1000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (1.74 sec) Records: 100000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (2.15 sec) Records: 100000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (2.64 sec) Records: 100000 Duplicates: 0 Warnings: 0 -SELECT SLEEP(1); +mysql> SELECT SLEEP(1); +----------+ | SLEEP(1) | +----------+ @@ -80,10 +80,10 @@ SELECT SLEEP(1); +----------+ 1 row in set (1.00 sec) -ANALYZE TABLE t1; +mysql> ANALYZE TABLE t1; Query OK, 0 rows affected (1.33 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ @@ -93,13 +93,13 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ 3 rows in set (0.02 sec) -CREATE SESSION BINDING FOR - SELECT * FROM t1 WHERE b = 123 - USING - SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123; +mysql> CREATE SESSION BINDING FOR + SELECT * FROM t1 WHERE b = 123 + USING + SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123; Query OK, 0 rows affected (0.00 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ @@ -109,7 +109,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ 3 rows in set (0.22 sec) -SHOW SESSION BINDINGS\G +mysql> SHOW SESSION BINDINGS\G *************************** 1. row *************************** Original_sql: select * from t1 where b = ? Bind_sql: SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123 @@ -121,10 +121,10 @@ Original_sql: select * from t1 where b = ? Collation: utf8mb4_0900_ai_ci 1 row in set (0.00 sec) -DROP SESSION BINDING FOR SELECT * FROM t1 WHERE b = 123; +mysql> DROP SESSION BINDING FOR SELECT * FROM t1 WHERE b = 123; Query OK, 0 rows affected (0.00 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+-------------------------------------------------------------------------+-----------------------------------+----------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------------+---------+---------+-----------+----------------------+-------------------------------------------------------------------------+-----------------------------------+----------------+------+ @@ -135,7 +135,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; 3 rows in set (0.01 sec) ``` -下面的示例演示如何根据历史执行计划创建绑定。 +以下示例展示如何根据历史执行计划创建绑定。 ```sql mysql> CREATE TABLE t(id INT PRIMARY KEY , a INT, KEY(a)); @@ -165,17 +165,16 @@ mysql> SELECT @@LAST_PLAN_FROM_BINDING; | 1 | +--------------------------+ 1 row in set (0.01 sec) - ``` ## MySQL 兼容性 -`CREATE [GLOBAL|SESSION] BINDING` 语句是 TiDB 对 MySQL 语法的扩展。 +该语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 * [DROP [GLOBAL|SESSION] BINDING](/sql-statements/sql-statement-drop-binding.md) * [SHOW [GLOBAL|SESSION] BINDINGS](/sql-statements/sql-statement-show-bindings.md) -* [ANALYZE](/sql-statements/sql-statement-analyze-table.md) -* [Optimizer Hints](/optimizer-hints.md) -* [执行计划管理 (SPM)](/sql-plan-management.md) +* [ANALYZE TABLE](/sql-statements/sql-statement-analyze-table.md) +* [优化器提示](/optimizer-hints.md) +* [SQL 计划管理](/sql-plan-management.md) diff --git a/sql-statements/sql-statement-create-database.md b/sql-statements/sql-statement-create-database.md index 10655d6fc7f9..c756aa06b2f3 100644 --- a/sql-statements/sql-statement-create-database.md +++ b/sql-statements/sql-statement-create-database.md @@ -1,11 +1,11 @@ --- -title: CREATE DATABASE -summary: TiDB 数据库中 CREATE DATABASE 的使用概况。 +title: CREATE DATABASE | TiDB SQL 语句参考 +summary: TiDB 数据库中 CREATE DATABASE 的使用概览。 --- # CREATE DATABASE -`CREATE DATABASE` 语句用于在 TiDB 上创建新数据库。按照 SQL 标准,“数据库”一词在 MySQL 术语中最接近 “schema”。 +此语句在 TiDB 中创建一个新的数据库。MySQL 中的"数据库"术语最接近于 SQL 标准中的 schema。 ## 语法图 @@ -36,9 +36,7 @@ PlacementPolicyOption ::= ## 语法说明 -`CREATE DATABASE` 用于创建数据库,并可以指定数据库的默认属性(如数据库默认字符集、排序规则)。`CREATE SCHEMA` 跟 `CREATE DATABASE` 操作效果一样。 - -{{< copyable "sql" >}} +`CREATE DATABASE` 语句用于创建数据库,并指定数据库的默认属性,如默认字符集和排序规则。`CREATE SCHEMA` 是 `CREATE DATABASE` 的同义词。 ```sql CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name @@ -49,49 +47,22 @@ create_specification: | [DEFAULT] COLLATE [=] collation_name ``` -当创建已存在的数据库且不指定使用 `IF NOT EXISTS` 时会报错。 +如果你创建一个已存在的数据库且未指定 `IF NOT EXISTS`,将显示错误。 -`create_specification` 选项用于指定数据库具体的 `CHARACTER SET` 和 `COLLATE`。目前 TiDB 只支持部分的字符集和排序规则,请参照[字符集支持](/character-set-and-collation.md)。 +`create_specification` 选项用于指定数据库中的特定 `CHARACTER SET` 和 `COLLATE`。目前,TiDB 仅支持部分字符集和排序规则。详情请参见[字符集和排序规则支持](/character-set-and-collation.md)。 ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE DATABASE mynewdatabase; -``` - -``` +mysql> CREATE DATABASE mynewdatabase; Query OK, 0 rows affected (0.09 sec) -``` -{{< copyable "sql" >}} - -```sql -USE mynewdatabase; -``` - -``` +mysql> USE mynewdatabase; Database changed -``` - -{{< copyable "sql" >}} - -```sql -CREATE TABLE t1 (a int); -``` - -``` +mysql> CREATE TABLE t1 (a int); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - -```sql -SHOW TABLES; -``` -``` +mysql> SHOW TABLES; +-------------------------+ | Tables_in_mynewdatabase | +-------------------------+ @@ -102,7 +73,7 @@ SHOW TABLES; ## MySQL 兼容性 -`CREATE DATABASE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `CREATE DATABASE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-create-index.md b/sql-statements/sql-statement-create-index.md index 8ced66162f8f..a388d37a2f10 100644 --- a/sql-statements/sql-statement-create-index.md +++ b/sql-statements/sql-statement-create-index.md @@ -1,11 +1,11 @@ --- -title: CREATE INDEX -summary: CREATE INDEX 在 TiDB 中的使用概况 +title: CREATE INDEX | TiDB SQL 语句参考 +summary: TiDB 数据库中 CREATE INDEX 的使用概览。 --- # CREATE INDEX -`CREATE INDEX` 语句用于在已有表中添加新索引,功能等同于 [`ALTER TABLE .. ADD INDEX`](/sql-statements/sql-statement-alter-table.md),提供了 MySQL 兼容性。 +该语句用于为现有表添加新索引。它是 [`ALTER TABLE .. ADD INDEX`](/sql-statements/sql-statement-alter-table.md) 的替代语法,包含此语法是为了与 MySQL 兼容。 ## 语法图 @@ -65,27 +65,14 @@ KeyOrIndex ::= ## 示例 ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.10 sec) -``` - -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` -```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` - -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +-------------------------+----------+-----------+---------------+--------------------------------+ | id | estRows | task | access object | operator info | +-------------------------+----------+-----------+---------------+--------------------------------+ @@ -94,21 +81,11 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; | └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +-------------------------+----------+-----------+---------------+--------------------------------+ 3 rows in set (0.00 sec) -``` -```sql -CREATE INDEX c1 ON t1 (c1); -``` - -``` +mysql> CREATE INDEX c1 ON t1 (c1); Query OK, 0 rows affected (0.30 sec) -``` -```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` - -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +------------------------+---------+-----------+------------------------+---------------------------------------------+ | id | estRows | task | access object | operator info | +------------------------+---------+-----------+------------------------+---------------------------------------------+ @@ -116,45 +93,35 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; | └─IndexRangeScan_5 | 10.00 | cop[tikv] | table:t1, index:c1(c1) | range:[3,3], keep order:false, stats:pseudo | +------------------------+---------+-----------+------------------------+---------------------------------------------+ 2 rows in set (0.00 sec) -``` -```sql -ALTER TABLE t1 DROP INDEX c1; -``` - -``` +mysql> ALTER TABLE t1 DROP INDEX c1; Query OK, 0 rows affected (0.30 sec) -``` -```sql -CREATE UNIQUE INDEX c1 ON t1 (c1); -``` - -``` +mysql> CREATE UNIQUE INDEX c1 ON t1 (c1); Query OK, 0 rows affected (0.31 sec) ``` ## 表达式索引 -在一些场景中,查询的条件往往是基于某个表达式进行过滤。在这些场景中,一般的索引不能生效,执行查询只能遍历整个表,导致查询性能较差。表达式索引是一种特殊的索引,能将索引建立于表达式上。在创建了表达式索引后,基于表达式的查询便可以使用上索引,极大提升查询的性能。 +在某些场景中,查询的过滤条件是基于某个表达式的。在这些场景中,由于普通索引无法生效,查询只能通过全表扫描执行,查询性能较差。表达式索引是一种可以在表达式上创建的特殊索引。创建表达式索引后,TiDB 可以在基于表达式的查询中使用该索引,从而显著提高查询性能。 -假设要基于 `LOWER(col1)` 这个表达式建立索引,示例的 SQL 语句如下: +例如,如果你想基于 `LOWER(col1)` 创建索引,执行以下 SQL 语句: ```sql CREATE INDEX idx1 ON t1 ((LOWER(col1))); ``` -或者等价的语句: +或者你可以执行以下等效语句: ```sql ALTER TABLE t1 ADD INDEX idx1((LOWER(col1))); ``` -还可以在建表的同时指定表达式索引: +你也可以在创建表时指定表达式索引: ```sql CREATE TABLE t1 ( - col1 CHAR(10), + col1 CHAR(10), col2 CHAR(10), INDEX ((LOWER(col1))) ); @@ -162,15 +129,15 @@ CREATE TABLE t1 ( > **注意:** > -> 表达式索引中的表达式需要用 `(` 和 `)` 包围起来,否则会报语法错误。 +> 表达式索引中的表达式必须用 `(` 和 `)` 括起来。否则,会报语法错误。 -删除表达式索引与删除普通索引的方法一致: +你可以像删除普通索引一样删除表达式索引: ```sql DROP INDEX idx1 ON t1; ``` -表达式索引涉及众多表达式。为了确保正确性,当前仅允许经充分测试的一部分函数用于创建表达式索引,即生产环境中仅允许表达式中包含这些函数。这些函数可以通过查询变量 [`tidb_allow_function_for_expression_index`](/system-variables.md#tidb_allow_function_for_expression_index-从-v520-版本开始引入) 得到。在后续版本中,这些函数会持续增加。目前允许的函数如下: +表达式索引涉及各种类型的表达式。为确保正确性,只有一些经过充分测试的函数才允许用于创建表达式索引。这意味着在生产环境中只允许使用这些函数。你可以通过查询 [`tidb_allow_function_for_expression_index`](/system-variables.md#tidb_allow_function_for_expression_index-new-in-v520) 变量获取这些函数。目前,允许的函数如下: - [`JSON_ARRAY()`](/functions-and-operators/json-functions.md) - [`JSON_ARRAY_APPEND()`](/functions-and-operators/json-functions.md) @@ -202,43 +169,49 @@ DROP INDEX idx1 ON t1; - [`UPPER()`](/functions-and-operators/string-functions.md#upper) - [`VITESS_HASH()`](/functions-and-operators/tidb-functions.md) -对于以上列表之外的函数,由于未完成充分测试,当前仍为实验特性,不建议在生产环境中使用。其他的表达式例如运算符、`CAST` 和 `CASE WHEN` 也同样为实验特性,不建议在生产环境中使用。如果仍然希望使用,可以在 [TiDB 配置文件](/tidb-configuration-file.md#allow-expression-index-从-v400-版本开始引入)中进行以下设置: +对于不在上述列表中的函数,这些函数未经过充分测试,不建议在生产环境中使用,可以视为实验性功能。其他表达式(如运算符、`CAST` 和 `CASE WHEN`)也被视为实验性功能,不建议在生产环境中使用。 + + + +如果你仍然想使用这些表达式,可以在 [TiDB 配置文件](/tidb-configuration-file.md#allow-expression-index-new-in-v400)中进行以下配置: ```sql allow-expression-index = true ``` + + > **注意:** > -> 表达式索引不能为主键。 +> 不能在主键上创建表达式索引。 > > 表达式索引中的表达式不能包含以下内容: > -> - 易变函数,例如 `RAND()` 和 `NOW()` 等。 -> - [系统变量](/system-variables.md)以及[用户变量](/user-defined-variables.md)。 +> - 易变函数,如 `RAND()` 和 `NOW()`。 +> - [系统变量](/system-variables.md)和[用户变量](/user-defined-variables.md)。 > - 子查询。 -> - [`AUTO_INCREMENT`](/auto-increment.md) 属性的列。一个例外是设置系统变量 [`tidb_enable_auto_increment_in_generated`](/system-variables.md#tidb_enable_auto_increment_in_generated) 为 `true` 后,可以去掉该限制。 +> - [`AUTO_INCREMENT`](/auto-increment.md) 列。你可以通过将 [`tidb_enable_auto_increment_in_generated`](/system-variables.md#tidb_enable_auto_increment_in_generated)(系统变量)的值设置为 `true` 来移除此限制。 > - [窗口函数](/functions-and-operators/window-functions.md)。 -> - ROW 函数。例如 `CREATE TABLE t (j JSON, INDEX k (((j,j))));`。 +> - ROW 函数,如 `CREATE TABLE t (j JSON, INDEX k (((j,j))));`。 > - [聚合函数](/functions-and-operators/aggregate-group-by-functions.md)。 > -> 表达式索引将隐式占用名字,`_V$_{index_name}_{index_offset}`,如果已有相同名字的列存在,创建表达式索引将报错。如果后续新增相同名字的列,也会报错。 +> 表达式索引隐式占用一个名称(例如,`_V$_{index_name}_{index_offset}`)。如果你尝试使用列已经使用的名称创建新的表达式索引,会发生错误。此外,如果你添加一个同名的新列,也会发生错误。 > -> 在表达式索引中,表达式的函数参数个数必须正确。 +> 确保表达式索引中函数参数的数量正确。 > -> 当索引的表达式使用了字符串相关的函数时,受返回类型以及其长度的影响,创建表达式索引可能会失败。这时可以使用 `CAST()` 函数显式指定返回的类型以及长度。例如表达式 `REPEAT(a, 3)`,为了能根据该表达式建立表达式索引,需要将表达式改写为 `CAST(REPEAT(a, 3) AS CHAR(20))` 这样的形式。 +> 当索引的表达式包含字符串相关函数时,受返回类型和长度的影响,可能会创建表达式索引失败。在这种情况下,你可以使用 `CAST()` 函数显式指定返回类型和长度。例如,要基于 `REPEAT(a, 3)` 表达式创建表达式索引,你需要将此表达式修改为 `CAST(REPEAT(a, 3) AS CHAR(20))`。 -当查询语句中的表达式与表达式索引中的表达式一致时,优化器可以为该查询选择使用表达式索引。依赖于统计信息,某些情况下优化器不一定选择表达式索引。这时可以通过 hint 指定强制使用表达式索引。 +当查询语句中的表达式与表达式索引中的表达式匹配时,优化器可以选择使用表达式索引进行查询。在某些情况下,优化器可能会根据统计信息选择不使用表达式索引。在这种情况下,你可以通过使用优化器提示强制优化器选择表达式索引。 -在以下示例中,假设建立在 `LOWER(col1)` 表达式上的索引为 `idx`。 +在以下示例中,假设你在表达式 `LOWER(col1)` 上创建了表达式索引 `idx`: -当读取的结果为相同的表达式时,可以使用表达式索引。例如: +如果查询语句的结果是相同的表达式,则表达式索引适用。以下语句为例: ```sql SELECT LOWER(col1) FROM t; ``` -当过滤的条件中有相同的表达式时,可以使用表达式索引。例如: +如果过滤条件中包含相同的表达式,则表达式索引适用。以下语句为例: ```sql SELECT * FROM t WHERE LOWER(col1) = "a"; @@ -249,28 +222,30 @@ SELECT * FROM t WHERE LOWER(col1) > "a" AND LOWER(col1) < "b"; SELECT * FROM t WHERE LOWER(col1) > "b" OR LOWER(col1) < "a"; ``` -当查询按照相同的表达式进行排序时,可以使用表达式索引。例如: +当查询按相同表达式排序时,表达式索引适用。以下语句为例: ```sql SELECT * FROM t ORDER BY LOWER(col1); ``` -当聚合函数或者 `GROUP BY` 中包含相同的表达式时,可以使用表达式索引。例如: +如果聚合(`GROUP BY`)函数中包含相同的表达式,则表达式索引适用。以下语句为例: ```sql SELECT MAX(LOWER(col1)) FROM t; SELECT MIN(col1) FROM t GROUP BY LOWER(col1); ``` -要查看表达式索引对应的表达式,可执行 [`SHOW INDEX`](/sql-statements/sql-statement-show-indexes.md) 或查看系统表 [`information_schema.tidb_indexes`](/information-schema/information-schema-tidb-indexes.md) 以及 [`information_schema.STATISTICS`](/information-schema/information-schema-statistics.md) 表,输出中 `Expression` 这一列显示对应的表达式。对于非表达式索引,该列的值为 `NULL`。 +要查看表达式索引对应的表达式,执行 [`SHOW INDEX`](/sql-statements/sql-statement-show-indexes.md),或查看系统表 [`information_schema.tidb_indexes`](/information-schema/information-schema-tidb-indexes.md) 和表 [`information_schema.STATISTICS`](/information-schema/information-schema-statistics.md)。输出中的 `Expression` 列表示对应的表达式。对于非表达式索引,该列显示 `NULL`。 + +维护表达式索引的成本高于维护其他索引,因为在插入或更新行时需要计算表达式的值。表达式的值已存储在索引中,因此当优化器选择表达式索引时,不需要重新计算该值。 -维护表达式索引的代价比一般的索引更高,因为在插入或者更新每一行时都需要计算出表达式的值。因为表达式的值已经存储在索引中,所以当优化器选择表达式索引时,表达式的值就不需要再计算。因此,当查询速度比插入速度和更新速度更重要时,可以考虑建立表达式索引。 +因此,当查询性能超过插入和更新性能时,可以考虑对表达式建立索引。 -表达式索引的语法和限制与 MySQL 相同,是通过将索引建立在隐藏的虚拟生成列 (generated virtual column) 上来实现的。因此所支持的表达式继承了虚拟生成列的所有[限制](/generated-columns.md#生成列的局限性)。 +表达式索引具有与 MySQL 相同的语法和限制。它们是通过在不可见的虚拟生成列上创建索引来实现的,因此支持的表达式继承了[虚拟生成列的所有限制](/generated-columns.md#限制)。 ## 多值索引 -多值索引是一种定义在数组列上的二级索引。在普通索引中,一条索引记录对应一条数据记录 (1:1)。而在多值索引中,存在多条索引记录对应一条数据记录 (N:1)。多值索引用于索引 JSON 数组。例如,一个定义在 `zipcode` 字段上的多值索引会对每一个 `zipcode` 中的记录产生一条索引记录。 +多值索引是一种定义在数组列上的二级索引。在普通索引中,一个索引记录对应一个数据记录(1:1)。在多值索引中,多个索引记录对应一个数据记录(N:1)。多值索引用于索引 JSON 数组。例如,在 `zipcode` 字段上定义的多值索引将为 `zipcode` 数组中的每个元素生成一个索引记录。 ```json { @@ -282,7 +257,7 @@ SELECT MIN(col1) FROM t GROUP BY LOWER(col1); ### 创建多值索引 -创建多值索引与创建表达式索引的方法一致。在索引定义中使用 [`CAST(... AS ... ARRAY)`](/functions-and-operators/cast-functions-and-operators.md#cast) 函数来创建一个多值索引。 +你可以通过在索引定义中使用 [`CAST(... AS ... ARRAY)`](/functions-and-operators/cast-functions-and-operators.md#cast) 函数来创建多值索引,就像创建表达式索引一样。 ```sql mysql> CREATE TABLE customers ( @@ -293,7 +268,7 @@ mysql> CREATE TABLE customers ( ); ``` -多值索引可以被定义为唯一索引: +你可以将多值索引定义为唯一索引。 ```sql mysql> CREATE TABLE customers ( @@ -304,7 +279,7 @@ mysql> CREATE TABLE customers ( ); ``` -当被定义为唯一索引时,试图插入重复数据将会报错: +当多值索引被定义为唯一索引时,如果尝试插入重复数据,会报错。 ```sql mysql> INSERT INTO customers VALUES (1, 'pingcap', '{"zipcode": [1,2]}'); @@ -314,7 +289,7 @@ mysql> INSERT INTO customers VALUES (1, 'pingcap', '{"zipcode": [2,3]}'); ERROR 1062 (23000): Duplicate entry '2' for key 'customers.zips' ``` -允许同一条记录存在重复的值,不同记录出现重复值时将报错: +同一条记录可以有重复值,但当不同记录有重复值时,会报错。 ```sql -- 插入成功 @@ -326,7 +301,7 @@ mysql> INSERT INTO t1 VALUES('[1,2]'); mysql> INSERT INTO t1 VALUES('[2,3]'); ``` -多值索引也可以被定义为复合索引: +你也可以将多值索引定义为复合索引: ```sql mysql> CREATE TABLE customers ( @@ -337,7 +312,7 @@ mysql> CREATE TABLE customers ( ); ``` -当被定义为复合索引时,多值部分可以出现在任意位置,但是只能出现一次。 +当多值索引被定义为复合索引时,多值部分可以出现在任何位置,但只能出现一次。 ```sql mysql> CREATE TABLE customers ( @@ -349,10 +324,10 @@ mysql> CREATE TABLE customers ( ERROR 1235 (42000): This version of TiDB doesn't yet support 'more than one multi-valued key part per index'. ``` -写入的数据必须与多值索引的定义类型完全匹配,否则数据写入失败: +写入的数据必须与多值索引定义的类型完全匹配,否则数据写入失败: ```sql --- zipcode 字段中的所有元素必须为 UNSIGNED 类型 +-- zipcode 字段中的所有元素必须是 UNSIGNED 类型。 mysql> INSERT INTO customers VALUES (1, 'pingcap', '{"zipcode": [-1]}'); ERROR 3752 (HY000): Value is out of range for expression index 'zips' at row 1 @@ -365,52 +340,52 @@ Query OK, 1 row affected (0.00 sec) ### 使用多值索引 -请参考[索引的选择](/choose-index.md#使用多值索引)。 +有关更多详细信息,请参见[索引选择 - 使用多值索引](/choose-index.md#使用多值索引)。 -### 特性与限制 +### 限制 -- 如果是空 JSON 数组,则不会有对应的索引记录。 -- `CAST(... AS ... ARRAY)` 中的目标类型不能是 `BINARY`、`JSON`、`YEAR`、`FLOAT`、`DECIMAL`。其中源类型必须是 JSON。 -- 无法使用多值索引进行排序。 -- 只允许在 JSON 数组上建立多值索引。 -- 多值索引不可以作为主键或外键。 -- 多值索引使用额外的存储空间为:平均每行数组元素个数 * 普通二级索引使用空间。 -- 相比于普通索引,DML 会对多值索引产生更多的索引记录的修改,因此多值索引会带来比普通索引更大的性能影响。 -- 由于多值索引是一种特殊的表达式索引,因此具有表达式索引的限制。 -- 使用备份恢复工具 (BR)、同步工具 (TiCDC)、导入工具 (TiDB Lightning) 无法将定义了多值索引的表备份、同步、导入到低于 v6.6.0 版本的 TiDB。 -- 条件复杂的查询有可能无法选择到多值索引,多值索引支持的条件模式请参考[使用多值索引](/choose-index.md#使用多值索引)。 +- 对于空 JSON 数组,不会生成相应的索引记录。 +- `CAST(... AS ... ARRAY)` 中的目标类型不能是 `BINARY`、`JSON`、`YEAR`、`FLOAT` 和 `DECIMAL`。源类型必须是 JSON。 +- 不能使用多值索引进行排序。 +- 只能在 JSON 数组上创建多值索引。 +- 多值索引不能是主键或外键。 +- 多值索引使用的额外存储空间 = 每行数组元素的平均数量 * 普通二级索引使用的空间。 +- 与普通索引相比,DML 操作会修改多值索引的更多索引记录,因此多值索引对性能的影响比普通索引更大。 +- 因为多值索引是一种特殊的表达式索引,所以多值索引具有与表达式索引相同的限制。 +- 如果表使用多值索引,则不能使用 BR、TiCDC 或 TiDB Lightning 将表备份、复制或导入到早于 v6.6.0 的 TiDB 集群。 +- 对于具有复杂条件的查询,TiDB 可能无法选择多值索引。有关多值索引支持的条件模式的信息,请参考[使用多值索引](/choose-index.md#使用多值索引)。 ## 不可见索引 -默认情况下,不可见索引 (Invisible Indexes) 不会被查询优化器使用: +默认情况下,不可见索引是被查询优化器忽略的索引: ```sql CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE(c2)); CREATE UNIQUE INDEX c1 ON t1 (c1) INVISIBLE; ``` -从 TiDB v8.0.0 开始,你可以通过修改系统变量 [`tidb_opt_use_invisible_indexes`](/system-variables.md#tidb_opt_use_invisible_indexes-从-v800-版本开始引入),允许优化器选择不可见索引。 +从 TiDB v8.0.0 开始,你可以通过修改系统变量 [`tidb_opt_use_invisible_indexes`](/system-variables.md#tidb_opt_use_invisible_indexes-new-in-v800) 来让优化器选择不可见索引。 -具体可以参考 [`ALTER INDEX`](/sql-statements/sql-statement-alter-index.md)。 +详情请参见 [`ALTER INDEX`](/sql-statements/sql-statement-alter-index.md)。 ## 相关系统变量 -和 `CREATE INDEX` 语句相关的系统变量有 `tidb_ddl_enable_fast_reorg`、`tidb_ddl_reorg_worker_cnt` 、`tidb_ddl_reorg_batch_size` 、`tidb_ddl_reorg_priority` 和 `tidb_enable_auto_increment_in_generated`,具体可以参考[系统变量](/system-variables.md#tidb_ddl_reorg_worker_cnt)。 +与 `CREATE INDEX` 语句相关的系统变量有 `tidb_ddl_enable_fast_reorg`、`tidb_ddl_reorg_worker_cnt`、`tidb_ddl_reorg_batch_size`、`tidb_enable_auto_increment_in_generated` 和 `tidb_ddl_reorg_priority`。详情请参见[系统变量](/system-variables.md#tidb_ddl_reorg_worker_cnt)。 ## MySQL 兼容性 -* TiDB 支持解析 `FULLTEXT` 语法,但尚不支持使用 `FULLTEXT`、`HASH` 和 `SPATIAL` 索引。 -* 为了兼容 MySQL,TiDB 在语法上支持 `HASH`、`BTREE` 和 `RTREE` 等索引类型,但会忽略它们。 -* 不支持降序索引 (类似于 MySQL 5.7)。 -* 无法向表中添加 `CLUSTERED` 类型的 `PRIMARY KEY`。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 -* 表达式索引与视图存在兼容性问题。通过视图进行查询时,无法使用上表达式索引。 -* 表达式索引与 Binding 存在兼容性问题。当表达式索引中的表达式存在常量时,对应查询所建的 Binding 会扩大范围。假设表达式索引中的表达式为 `a+1`,对应的查询条件为 `a+1 > 2`。则建立的 Binding 为 `a+? > ?`,这会导致像 `a+2 > 2` 这样的查询也会强制使用表达式索引,得到一个较差的执行计划。这同样影响 SQL Plan Management (SPM) 中的捕获和演进功能。 -* 多值索引写入的数据必须与定义类型完全匹配,否则数据写入失败。详见[创建多值索引](/sql-statements/sql-statement-create-index.md#创建多值索引)。 +* TiDB 支持解析 `FULLTEXT` 语法,但不支持使用 `FULLTEXT`、`HASH` 和 `SPATIAL` 索引。 +* TiDB 接受 `HASH`、`BTREE` 和 `RTREE` 等索引类型的语法以与 MySQL 兼容,但会忽略它们。 +* 不支持降序索引(类似于 MySQL 5.7)。 +* 不支持向表添加 `CLUSTERED` 类型的主键。有关 `CLUSTERED` 类型主键的更多详细信息,请参考[聚簇索引](/clustered-indexes.md)。 +* 表达式索引与视图不兼容。当使用视图执行查询时,不能同时使用表达式索引。 +* 表达式索引与绑定有兼容性问题。当表达式索引的表达式有常量时,为相应查询创建的绑定会扩大其范围。例如,假设表达式索引中的表达式是 `a+1`,相应的查询条件是 `a+1 > 2`。在这种情况下,创建的绑定是 `a+? > ?`,这意味着具有条件如 `a+2 > 2` 的查询也被强制使用表达式索引,导致执行计划不佳。此外,这也会影响 SQL Plan Management (SPM) 中的基线捕获和基线演进。 +* 使用多值索引写入的数据必须与定义的数据类型完全匹配。否则,数据写入失败。详情请参见[创建多值索引](/sql-statements/sql-statement-create-index.md#创建多值索引)。 ## 另请参阅 -* [索引的选择](/choose-index.md) -* [错误索引的解决方案](/wrong-index-solution.md) +* [索引选择](/choose-index.md) +* [错误索引解决方案](/wrong-index-solution.md) * [ADD INDEX](/sql-statements/sql-statement-add-index.md) * [DROP INDEX](/sql-statements/sql-statement-drop-index.md) * [RENAME INDEX](/sql-statements/sql-statement-rename-index.md) diff --git a/sql-statements/sql-statement-create-placement-policy.md b/sql-statements/sql-statement-create-placement-policy.md index 83d6971959e7..aac250ed05d7 100644 --- a/sql-statements/sql-statement-create-placement-policy.md +++ b/sql-statements/sql-statement-create-placement-policy.md @@ -1,13 +1,17 @@ --- title: CREATE PLACEMENT POLICY -summary: TiDB 数据库中 CREATE PLACEMENT POLICY 的使用概况。 +summary: TiDB 中 CREATE PLACEMENT POLICY 的使用方法。 --- # CREATE PLACEMENT POLICY -`CREATE PLACEMENT POLICY` 用于创建命名的放置策略,随后可以将该策略分配给表、分区或数据库。 +`CREATE PLACEMENT POLICY` 用于创建命名放置策略,该策略可以稍后分配给表、分区或数据库架构。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法 ```ebnf+diagram CreatePolicyStmt ::= @@ -47,7 +51,9 @@ AdvancedPlacementOption ::= > **注意:** > -> 如要查看所在集群中可用的区域,见 [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md)。如果未看到任何可用的区域,此 TiKV 集群在部署时可能未正确设置标签 (label)。 +> 要了解集群中有哪些可用区域,请参见 [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md)。 +> +> 如果你没有看到任何可用区域,你的 TiKV 安装可能没有正确设置标签。 {{< copyable "sql" >}} @@ -76,7 +82,7 @@ Query OK, 0 rows affected (0.10 sec) ## 另请参阅 -* [Placement Rules in SQL](/placement-rules-in-sql.md) +* [SQL 中的放置规则](/placement-rules-in-sql.md) * [SHOW PLACEMENT](/sql-statements/sql-statement-show-placement.md) * [ALTER PLACEMENT POLICY](/sql-statements/sql-statement-alter-placement-policy.md) * [DROP PLACEMENT POLICY](/sql-statements/sql-statement-drop-placement-policy.md) diff --git a/sql-statements/sql-statement-create-resource-group.md b/sql-statements/sql-statement-create-resource-group.md index 6d61e5742478..26c399aa2851 100644 --- a/sql-statements/sql-statement-create-resource-group.md +++ b/sql-statements/sql-statement-create-resource-group.md @@ -1,13 +1,17 @@ --- title: CREATE RESOURCE GROUP -summary: TiDB 数据库中 CREATE RESOURCE GROUP 的使用概况。 +summary: 了解 TiDB 中 CREATE RESOURCE GROUP 的使用方法。 --- # CREATE RESOURCE GROUP -`CREATE RESOURCE GROUP` 语句用于在当前所选数据库中创建资源组。 +你可以使用 `CREATE RESOURCE GROUP` 语句创建资源组。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法 ```ebnf+diagram CreateResourceGroupStmt ::= @@ -42,7 +46,7 @@ ResourceGroupPriorityOption ::= | MEDIUM | HIGH -ResourceGroupRunawayOptionList ::= +ResourceGroupRunawayOptionList ::= DirectResourceGroupRunawayOption | ResourceGroupRunawayOptionList DirectResourceGroupRunawayOption | ResourceGroupRunawayOptionList ',' DirectResourceGroupRunawayOption @@ -66,26 +70,26 @@ ResourceGroupRunawayActionOption ::= | KILL ``` -资源组的 `ResourceGroupName` 是全局唯一的,不允许重复。 +资源组名称参数(`ResourceGroupName`)必须全局唯一。 -TiDB 支持以下 `DirectResourceGroupOption`, 其中 [Request Unit (RU)](/tidb-resource-control.md#什么是-request-unit-ru) 是 TiDB 对 CPU、IO 等系统资源统一抽象的单位。 +TiDB 支持以下 `DirectResourceGroupOption`,其中[请求单元 (RU)](/tidb-resource-control.md#what-is-request-unit-ru) 是 TiDB 中 CPU、IO 和其他系统资源的统一抽象单位。 -| 参数 | 含义 | 举例 | -|---------------|--------------|--------------------------------------| -| `RU_PER_SEC` | 每秒 RU 填充的速度 | `RU_PER_SEC = 500` 表示此资源组每秒回填 500 个 RU。 | -| `PRIORITY` | 任务在 TiKV 上处理的绝对优先级 | `PRIORITY = HIGH` 表示优先级高。若未指定,则默认为 `MEDIUM`。 | -| `BURSTABLE` | 允许对应的资源组超出配额后使用空余的系统资源。 | -| `QUERY_LIMIT` | 当查询执行满足该条件时,识别该查询为 Runaway Query 并进行相应的控制 | `QUERY_LIMIT=(EXEC_ELAPSED='60s', ACTION=KILL, WATCH=EXACT DURATION='10m')` 表示当执行时间超过 60 秒后识别为 Runaway Query,对该查询执行终止操作,并在 10 分钟内对同样的 SQL 直接执行终止操作。`QUERY_LIMIT=()` 或 `QUERY_LIMIT=NULL` 则表示不进行 Runaway 控制。具体参数介绍详见[管理资源消耗超出预期的查询 (Runaway Queries)](/tidb-resource-control.md#管理资源消耗超出预期的查询-runaway-queries)。 | +| 选项 | 描述 | 示例 | +|---------------|-------------------------------------|------------------------| +| `RU_PER_SEC` | 每秒 RU 补充速率 | `RU_PER_SEC = 500` 表示该资源组每秒补充 500 个 RU | +| `PRIORITY` | 在 TiKV 上处理任务的绝对优先级 | `PRIORITY = HIGH` 表示优先级高。如果未指定,默认值为 `MEDIUM`。 | +| `BURSTABLE` | 如果设置了 `BURSTABLE` 属性,TiDB 允许相应的资源组在超出配额时使用可用的系统资源。 | +| `QUERY_LIMIT` | 当查询执行满足此条件时,该查询被识别为失控查询并执行相应的操作。 | `QUERY_LIMIT=(EXEC_ELAPSED='60s', ACTION=KILL, WATCH=EXACT DURATION='10m')` 表示当执行时间超过 60 秒时,该查询被识别为失控查询。查询被终止。在接下来的 10 分钟内,所有具有相同 SQL 文本的 SQL 语句都将立即被终止。`QUERY_LIMIT=()` 或 `QUERY_LIMIT=NULL` 表示不启用失控控制。参见[失控查询](/tidb-resource-control.md#manage-queries-that-consume-more-resources-than-expected-runaway-queries)。 | > **注意:** > -> - `CREATE RESOURCE GROUP` 语句只能在全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-从-v660-版本开始引入) 设置为 `ON` 时才能执行。 -> - TiDB 集群在初始化时会自动创建 `default` 资源组,其 `RU_PER_SEC` 的默认值为 `UNLIMITED` (等同于 `INT` 类型最大值,即 `2147483647`),且为 `BURSTABLE` 模式。所有未绑定资源组的请求都将自动绑定至此资源组。在新建配置其他资源组时,建议根据实际情况修改 `default` 资源组的配置。 -> - 目前仅 `default` 资源组支持修改 `BACKGROUND` 相关设置。 +> - `CREATE RESOURCE GROUP` 语句只能在全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-new-in-v660) 设置为 `ON` 时执行。 +> TiDB 在集群初始化期间自动创建一个 `default` 资源组。对于此资源组,`RU_PER_SEC` 的默认值为 `UNLIMITED`(相当于 `INT` 类型的最大值,即 `2147483647`),并且处于 `BURSTABLE` 模式。所有未绑定到任何资源组的请求都会自动绑定到这个 `default` 资源组。当你为其他资源组创建新配置时,建议根据需要修改 `default` 资源组配置。 +> - 目前,只有 `default` 资源组支持修改 `BACKGROUND` 配置。 ## 示例 -创建 `rg1` 和 `rg2` 两个资源组。 +创建两个资源组 `rg1` 和 `rg2`。 ```sql DROP RESOURCE GROUP IF EXISTS rg1; @@ -131,11 +135,11 @@ SELECT * FROM information_schema.resource_groups WHERE NAME ='rg1' or NAME = 'rg ## MySQL 兼容性 -MySQL 也支持 [CREATE RESOURCE GROUP](https://dev.mysql.com/doc/refman/8.0/en/create-resource-group.html),但是接受的参数和 TiDB 不同,两者并不兼容。 +MySQL 也支持 [CREATE RESOURCE GROUP](https://dev.mysql.com/doc/refman/8.0/en/create-resource-group.html)。但是,可接受的参数与 TiDB 的不同,因此它们不兼容。 ## 另请参阅 * [DROP RESOURCE GROUP](/sql-statements/sql-statement-drop-resource-group.md) * [ALTER RESOURCE GROUP](/sql-statements/sql-statement-alter-resource-group.md) -* [ALTER USER RESOURCE GROUP](/sql-statements/sql-statement-alter-user.md#修改用户绑定的资源组) -* [RU](/tidb-resource-control.md#什么是-request-unit-ru) +* [ALTER USER RESOURCE GROUP](/sql-statements/sql-statement-alter-user.md#modify-the-resource-group-bound-to-the-user) +* [请求单元 (RU)](/tidb-resource-control.md#what-is-request-unit-ru) diff --git a/sql-statements/sql-statement-create-role.md b/sql-statements/sql-statement-create-role.md index 2c943b24284d..1f8557a92ada 100644 --- a/sql-statements/sql-statement-create-role.md +++ b/sql-statements/sql-statement-create-role.md @@ -1,13 +1,13 @@ --- -title: CREATE ROLE -summary: TiDB 数据库中 CREATE ROLE 的使用概况。 +title: CREATE ROLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 CREATE ROLE 的使用概述。 --- # CREATE ROLE -`CREATE ROLE` 语句是基于角色的访问控制 (RBAC) 操作的一部分,用于创建新角色并将新角色分配给用户。 +此语句创建一个新角色,该角色可以作为基于角色的访问控制的一部分分配给用户。 -## 语法图 +## 语法概要 ```ebnf+diagram CreateRoleStmt ::= @@ -22,13 +22,13 @@ RoleSpec ::= ## 示例 -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -创建新角色 `analyticsteam` 和新用户 `jennifer`: +创建一个新角色 `analyticsteam` 和一个新用户 `jennifer`: ```sql CREATE ROLE analyticsteam; @@ -44,13 +44,13 @@ GRANT analyticsteam TO jennifer; Query OK, 0 rows affected (0.01 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -需要注意的是,默认情况下,用户 `jennifer` 需要执行 `SET ROLE analyticsteam` 语句才能使用与 `analyticsteam` 角色相关联的权限: +注意,默认情况下,`jennifer` 需要执行 `SET ROLE analyticsteam` 才能使用与 `analyticsteam` 角色相关的权限: ```sql SHOW GRANTS; @@ -86,26 +86,26 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -执行 `SET DEFAULT ROLE` 语句将用户 `jennifer` 与 `analyticsteam` 角色相关联: +可以使用 `SET DEFAULT ROLE` 语句将角色 `analyticsteam` 关联到 `jennifer`: ```sql SET DEFAULT ROLE analyticsteam TO jennifer; Query OK, 0 rows affected (0.02 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -此时 `jennifer` 用户无需执行 `SET ROLE` 语句就能拥有 `analyticsteam` 角色相关联的权限: +此后,用户 `jennifer` 拥有与角色 `analyticsteam` 相关的权限,且 `jennifer` 不需要执行 `SET ROLE` 语句: ```sql SHOW GRANTS; @@ -129,7 +129,7 @@ SHOW TABLES IN test; ## MySQL 兼容性 -`CREATE ROLE` 语句与 MySQL 8.0 的“角色”功能完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `CREATE ROLE` 语句与 MySQL 8.0 的角色功能完全兼容。如果发现任何兼容性差异,请[报告 bug](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 @@ -138,4 +138,9 @@ SHOW TABLES IN test; * [`REVOKE `](/sql-statements/sql-statement-revoke-role.md) * [`SET ROLE`](/sql-statements/sql-statement-set-role.md) * [`SET DEFAULT ROLE`](/sql-statements/sql-statement-set-default-role.md) + + + * [基于角色的访问控制](/role-based-access-control.md) + + diff --git a/sql-statements/sql-statement-create-sequence.md b/sql-statements/sql-statement-create-sequence.md index fa20fefe0a3a..483f9ccca5a5 100644 --- a/sql-statements/sql-statement-create-sequence.md +++ b/sql-statements/sql-statement-create-sequence.md @@ -1,11 +1,11 @@ --- title: CREATE SEQUENCE -summary: CREATE SEQUENCE 在 TiDB 中的使用概况 +summary: TiDB 数据库中 CREATE SEQUENCE 的使用概述。 --- # CREATE SEQUENCE -`CREATE SEQUENCE` 语句用于在 TiDB 中创建序列对象。序列是一种与表、视图对象平级的数据库对象,用于生成自定义的序列化 ID。 +`CREATE SEQUENCE` 语句在 TiDB 中创建序列对象。序列是与表和 `View` 对象同级的数据库对象。序列用于以自定义方式生成序列化的 ID。 ## 语法图 @@ -36,11 +36,11 @@ SequenceOption ::= | 'NOCYCLE' ``` -## 语法说明 +## 语法 {{< copyable "sql" >}} -``` +```sql CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name [ INCREMENT [ BY | = ] increment ] [ MINVALUE [=] minvalue | NO MINVALUE | NOMINVALUE ] @@ -51,41 +51,41 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name [table_options] ``` -## 参数说明 +## 参数 |参数 | 默认值 | 描述 | | :-- | :-- | :--| -| `TEMPORARY` | `false` | TiDB 暂时不支持 `TEMPORARY` 选项,仅在语法上做兼容。| -| `INCREMENT` | `1` | 指定序列的步长。其正负值可以控制序列的增长方向。| -| `MINVALUE` | `1` 或 `-9223372036854775807` | 指定序列的最小值。当 `INCREMENT` > `0` 时,默认值为 `1`;当 `INCREMENT` < `0` 时,默认值为 `-9223372036854775807`。| -| `MAXVALUE` | `9223372036854775806` 或 `-1` | 指定序列的最大值。当 `INCREMENT` > `0` 时,默认值为 `9223372036854775806`;当 `INCREMENT` < `0` 时,默认值为 `-1`。| -| `START` | `MINVALUE` 或 `MAXVALUE` | 指定序列的初始值。当 `INCREMENT` > `0` 时,默认值为 `MINVALUE`; 当 `INCREMENT` < `0` 时,默认值为 `MAXVALUE`。 | -| `CACHE` | `1000` | 指定每个 TiDB 本地缓存序列的大小。| -| `CYCLE` | `NO CYCLE` | 指定序列用完之后是否要循环使用。在 `CYCLE` 的情况下,当 `INCREMENT` > `0` 时,序列用完后的后续起始值为 `MINVALUE`;当 `INCREMENT` < `0` 时,序列用完后的后续起始值为 `MAXVALUE`。| +| `TEMPORARY` | `false` | TiDB 目前不支持 `TEMPORARY` 选项,仅提供语法兼容。 | +| `INCREMENT` | `1` | 指定序列的增量。其正值或负值可以控制序列的增长方向。 | +| `MINVALUE` | `1` 或 `-9223372036854775807` | 指定序列的最小值。当 `INCREMENT` > `0` 时,默认值为 `1`。当 `INCREMENT` < `0` 时,默认值为 `-9223372036854775807`。 | +| `MAXVALUE` | `9223372036854775806` 或 `-1` | 指定序列的最大值。当 `INCREMENT` > `0` 时,默认值为 `9223372036854775806`。当 `INCREMENT` < `0` 时,默认值为 `-1`。 | +| `START` | `MINVALUE` 或 `MAXVALUE`| 指定序列的初始值。当 `INCREMENT` > `0` 时,默认值为 `MINVALUE`。当 `INCREMENT` < `0` 时,默认值为 `MAXVALUE`。 | +| `CACHE` | `1000` | 指定序列在 TiDB 中的本地缓存大小。 | +| `CYCLE` | `NO CYCLE` | 指定序列是否从最小值重新开始(或递减序列的最大值)。当 `INCREMENT` > `0` 时,默认值为 `MINVALUE`。当 `INCREMENT` < `0` 时,默认值为 `MAXVALUE`。 | ## `SEQUENCE` 函数 -主要通过表达式函数来操纵序列的使用。 +你可以通过以下表达式函数控制序列: + `NEXTVAL` 或 `NEXT VALUE FOR` - 本质上都是 `NEXTVAL()` 函数,获取序列对象的下一个有效值,其参数为序列的 `identifier`。 + 本质上,两者都是 `NEXTVAL()` 函数,用于获取序列对象的下一个有效值。`NEXTVAL()` 函数的参数是序列的 `identifier`。 + `LASTVAL` - `LASTVAL()` 函数,用于获取本会话上一个使用过的值。如果没有值,则为 `NULL`,其参数为序列的 `identifier`。 + 此函数获取此会话中最后使用的值。如果该值不存在,则使用 `NULL`。此函数的参数是序列的 `identifier`。 + `SETVAL` - `SETVAL()` 函数,用于设置序列的增长。其第一参数为序列的 `identifier`,第二个参数为 `num`。 + 此函数设置序列当前值的进程。此函数的第一个参数是序列的 `identifier`;第二个参数是 `num`。 > **注意:** > -> 在 TiDB 序列的实现中,`SETVAL` 函数并不能改变序列增长的初始步调或循环步调。在 `SETVAL` 之后只会返回符合步调规律的下一个有效的序列值。 +> 在 TiDB 的序列实现中,`SETVAL` 函数不能更改此序列的初始进程或循环进程。此函数仅根据此进程返回下一个有效值。 ## 示例 -+ 创建一个默认参数的序列对象。 ++ 使用默认参数创建序列对象: {{< copyable "sql" >}} @@ -97,7 +97,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name Query OK, 0 rows affected (0.06 sec) ``` -+ 使用 `NEXTVAL()` 函数获取序列对象的下一个值。 ++ 使用 `NEXTVAL()` 函数获取序列对象的下一个值: {{< copyable "sql" >}} @@ -114,7 +114,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.02 sec) ``` -+ 使用 `LASTVAL()` 函数获取本会话上一次调用序列对象所产生的值。 ++ 使用 `LASTVAL()` 函数获取此会话中序列对象最后一次调用生成的值: {{< copyable "sql" >}} @@ -131,7 +131,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.02 sec) ``` -+ 使用 `SETVAL()` 函数设置序列对象当前值的位置。 ++ 使用 `SETVAL()` 函数设置序列对象的当前值(或当前位置): {{< copyable "sql" >}} @@ -148,7 +148,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.01 sec) ``` -+ 也可使用 `next value for` 语法获取序列的下一个值。 ++ 你也可以使用 `next value for` 语法获取序列的下一个值: {{< copyable "sql" >}} @@ -165,7 +165,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.00 sec) ``` -+ 创建一个默认自定义参数的序列对象。 ++ 使用自定义默认参数创建序列对象: {{< copyable "sql" >}} @@ -177,7 +177,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name Query OK, 0 rows affected (0.01 sec) ``` -+ 当本会话还未使用过序列对象时,`LASTVAL()` 函数返回 NULL 值。 ++ 当序列对象在此会话中未被使用时,`LASTVAL()` 函数返回 `NULL` 值。 {{< copyable "sql" >}} @@ -194,7 +194,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.01 sec) ``` -+ 序列对象 `NEXTVAL()` 的第一个有效值为 `start` 值。 ++ 序列对象的 `NEXTVAL()` 函数的第一个有效值是 `START` 参数的值。 {{< copyable "sql" >}} @@ -211,7 +211,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.00 sec) ``` -+ 使用 `SETVAL()` 虽然可以改变序列对象当前值的位置,但是无法改变下一个值的等差规律。 ++ 虽然 `SETVAL()` 函数可以更改序列对象的当前值,但它不能更改下一个值的算术进程规则。 {{< copyable "sql" >}} @@ -228,7 +228,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.00 sec) ``` -+ 使用 `NEXTVAL()` 下一个值获取时,会遵循序列定义的等差规律。 ++ 当你使用 `NEXTVAL()` 获取下一个值时,下一个值将遵循序列定义的算术进程规则。 {{< copyable "sql" >}} @@ -245,19 +245,19 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.00 sec) ``` -+ 可以将序列的下一个值作为列的默认值来使用。 ++ 你可以使用序列的下一个值作为列的默认值,如下例所示。 {{< copyable "sql" >}} ```sql - CREATE TABLE t(a int default next value for seq2); + CREATE table t(a int default next value for seq2); ``` ``` Query OK, 0 rows affected (0.02 sec) ``` -+ 下列示例中,因为没有指定值,会直接获取 `seq2` 的默认值来使用。 ++ 在下面的示例中,未指定值,因此使用 `seq2` 的默认值。 {{< copyable "sql" >}} @@ -284,7 +284,7 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name 1 row in set (0.00 sec) ``` -+ 下列示例中,因为没有指定值,会直接获取 `seq2` 的默认值来使用。由于 `seq2` 的下一个值超过了上述示例 (`CREATE SEQUENCE seq2 start 3 increment 2 minvalue 1 maxvalue 10 cache 3;`) 的定义范围,所以会显示报错。 ++ 在下面的示例中,未指定值,因此使用 `seq2` 的默认值。但是 `seq2` 的下一个值不在上面示例中定义的范围内(`CREATE SEQUENCE seq2 start 3 increment 2 minvalue 1 maxvalue 10 cache 3;`),因此返回错误。 {{< copyable "sql" >}} @@ -298,23 +298,23 @@ CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name ## MySQL 兼容性 -该语句是 TiDB 的扩展,序列的实现借鉴自 MariaDB。 +此语句是 TiDB 对 MySQL 语法的扩展。其实现参考了 MariaDB 中可用的序列。 -除了 `SETVAL` 函数外,其他函数的“步调 (progressions)” 与 MariaDB 一致。这里的步调是指,序列中的数在定义之后会产生一定的等差关系。`SETVAL` 虽然可以将序列的当前值进行移动设置,但是后续出现的值仍会遵循原有的等差关系。 +除了 `SETVAL` 函数外,所有其他函数都具有与 MariaDB 相同的_进程_。这里的"进程"意味着序列中的数字遵循序列定义的某个算术进程规则。虽然你可以使用 `SETVAL` 设置序列的当前值,但序列的后续值仍然遵循原始进程规则。 -示例如下: +例如: ``` -1, 3, 5, ... // 序列遵循起始为 1、步长为 2 的等差关系。 -select SETVAL(seq, 6) // 设置序列的当前值为 6。 -7, 9, 11, ... // 后续产生值仍会遵循这个等差关系。 +1, 3, 5, ... // 序列从 1 开始,每次增加 2。 +select SETVAL(seq, 6) // 将序列的当前值设置为 6。 +7, 9, 11, ... // 后续值仍然遵循进程规则。 ``` -在 `CYCLE` 模式下,序列的起始值第一轮为 `START`,后续轮次将会是 `MinValue` (INCREMENT > 0) 或 `MaxValue` (INCREMENT < 0)。 +在 `CYCLE` 模式下,序列在第一轮中的初始值是 `START` 参数的值,在后续轮次中的初始值是 `MinValue`(`INCREMENT` > 0)或 `MaxValue`(`INCREMENT` < 0)的值。 ## 另请参阅 * [ALTER SEQUENCE](/sql-statements/sql-statement-alter-sequence.md) * [DROP SEQUENCE](/sql-statements/sql-statement-drop-sequence.md) * [SHOW CREATE SEQUENCE](/sql-statements/sql-statement-show-create-sequence.md) -* [Sequence 函数](/functions-and-operators/sequence-functions.md) +* [序列函数](/functions-and-operators/sequence-functions.md) diff --git a/sql-statements/sql-statement-create-table-like.md b/sql-statements/sql-statement-create-table-like.md index c014fd911ed1..12a10241ce95 100644 --- a/sql-statements/sql-statement-create-table-like.md +++ b/sql-statements/sql-statement-create-table-like.md @@ -1,13 +1,13 @@ --- -title: CREATE TABLE LIKE -summary: TiDB 数据库中 CREATE TABLE LIKE 的使用概况。 +title: CREATE TABLE LIKE | TiDB SQL 语句参考 +summary: TiDB 数据库中 CREATE TABLE LIKE 的使用概述。 --- # CREATE TABLE LIKE -`CREATE TABLE LIKE` 语句用于复制已有表的定义,但不复制任何数据。 +此语句用于复制现有表的定义,但不复制任何数据。 -## 语法图 +## 语法 ```ebnf+diagram CreateTableLikeStmt ::= @@ -26,34 +26,15 @@ OnCommitOpt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (a INT NOT NULL); Query OK, 0 rows affected (0.13 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (1),(2),(3),(4),(5); -``` -``` +mysql> INSERT INTO t1 VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +---+ | a | +---+ @@ -64,35 +45,21 @@ SELECT * FROM t1; | 5 | +---+ 5 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -CREATE TABLE t2 LIKE t1; -``` -``` +mysql> CREATE TABLE t2 LIKE t1; Query OK, 0 rows affected (0.10 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t2; -``` - -``` +mysql> SELECT * FROM t2; Empty set (0.00 sec) ``` -## Region 的预切分 +## 预切分 Region -如果被复制的表定义了 `PRE_SPLIT_REGIONS` 属性,则通过 `CREATE TABLE LIKE` 语句复制的表,会继承该属性并在建表时预切分 Region。关于 `PRE_SPLIT_REGIONS` 属性的说明,参见 [`CREATE TABLE` 语句](/sql-statements/sql-statement-create-table.md)。 +如果要复制的表定义了 `PRE_SPLIT_REGIONS` 属性,使用 `CREATE TABLE LIKE` 语句创建的表会继承这个属性,并且新表上的 Region 会被切分。关于 `PRE_SPLIT_REGIONS` 的详细信息,请参见 [`CREATE TABLE` 语句](/sql-statements/sql-statement-create-table.md)。 ## MySQL 兼容性 -`CREATE TABLE LIKE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `CREATE TABLE LIKE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-create-table.md b/sql-statements/sql-statement-create-table.md index b1e03b98e37c..c1381b051bdd 100644 --- a/sql-statements/sql-statement-create-table.md +++ b/sql-statements/sql-statement-create-table.md @@ -1,13 +1,13 @@ --- -title: CREATE TABLE -summary: TiDB 数据库中 CREATE TABLE 的使用概况 +title: CREATE TABLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 CREATE TABLE 的使用概览。 --- # CREATE TABLE -`CREATE TABLE` 语句用于在当前所选数据库中创建新表,与 MySQL 中 `CREATE TABLE` 语句的行为类似。另可参阅单独的 `CREATE TABLE LIKE` 文档。 +此语句在当前选择的数据库中创建一个新表。它的行为类似于 MySQL 中的 `CREATE TABLE` 语句。 -## 语法图 +## 语法 ```ebnf+diagram CreateTableStmt ::= @@ -157,26 +157,37 @@ NextValueForSequence ::= | "NEXTVAL" '(' TableName ')' ``` -TiDB 支持以下 `table_option`。TiDB 会解析并忽略其他 `table_option` 参数,例如 `AVG_ROW_LENGTH`、`CHECKSUM`、`COMPRESSION`、`CONNECTION`、`DELAY_KEY_WRITE`、`ENGINE`、`KEY_BLOCK_SIZE`、`MAX_ROWS`、`MIN_ROWS`、`ROW_FORMAT` 和 `STATS_PERSISTENT`。 +支持以下 *table_options*。其他选项如 `AVG_ROW_LENGTH`、`CHECKSUM`、`COMPRESSION`、`CONNECTION`、`DELAY_KEY_WRITE`、`ENGINE`、`KEY_BLOCK_SIZE`、`MAX_ROWS`、`MIN_ROWS`、`ROW_FORMAT` 和 `STATS_PERSISTENT` 会被解析但忽略。 -| 参数 |含义 |举例 | -|----------------|--------------------------------------|----------------------------| -|`AUTO_INCREMENT`|自增字段初始值 |`AUTO_INCREMENT` = 5| -| [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md) |用来设置隐式 _tidb_rowid 的分片数量的 bit 位数 |`SHARD_ROW_ID_BITS` = 4| -|`PRE_SPLIT_REGIONS`|用来在建表时预先均匀切分 `2^(PRE_SPLIT_REGIONS)` 个 Region |`PRE_SPLIT_REGIONS` = 4| -|`AUTO_ID_CACHE`|用来指定 Auto ID 在 TiDB 实例中 Cache 的大小,默认情况下 TiDB 会根据 Auto ID 分配速度自动调整 |`AUTO_ID_CACHE` = 200| -|`AUTO_RANDOM_BASE`|用来指定 AutoRandom 自增部分的初始值,该参数可以被认为属于内部接口的一部分,对于用户而言请忽略 |`AUTO_RANDOM_BASE` = 0| -|`CHARACTER SET` |指定该表所使用的[字符集](/character-set-and-collation.md) | `CHARACTER SET` = 'utf8mb4'| -|`COLLATE` |指定该表所使用的字符集排序规则 | `COLLATE` = 'utf8mb4_bin'| -|`COMMENT` |注释信息 | `COMMENT` = 'comment info'| +| 选项 | 描述 | 示例 | +| ---------- | ---------- | ------- | +| `AUTO_INCREMENT` | 自增字段的初始值 | `AUTO_INCREMENT` = 5 | +| [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md)| 设置隐式 `_tidb_rowid` 分片的位数 |`SHARD_ROW_ID_BITS` = 4| +|`PRE_SPLIT_REGIONS`| 在创建表时预先切分 `2^(PRE_SPLIT_REGIONS)` 个 Region |`PRE_SPLIT_REGIONS` = 4| +|`AUTO_ID_CACHE`| 设置 TiDB 实例中的自动 ID 缓存大小。默认情况下,TiDB 会根据自动 ID 的分配速度自动调整此大小 |`AUTO_ID_CACHE` = 200 | +|`AUTO_RANDOM_BASE`| 设置 auto_random 的初始增量部分值。此选项可以被视为内部接口的一部分。用户可以忽略此参数 |`AUTO_RANDOM_BASE` = 0| +| `CHARACTER SET` | 指定表的[字符集](/character-set-and-collation.md) | `CHARACTER SET` = 'utf8mb4' | +| `COMMENT` | 注释信息 | `COMMENT` = 'comment info' | + + > **注意:** > -> 在 TiDB 配置文件中,`split-table` 默认开启。当该配置项开启时,建表操作会为每个表建立单独的 Region,详情参见 [TiDB 配置文件描述](/tidb-configuration-file.md)。 +> `split-table` 配置选项默认启用。启用时,为每个新创建的表创建单独的 Region。详情请参见 [TiDB 配置文件](/tidb-configuration-file.md)。 + + + + + +> **注意:** +> +> TiDB 为每个新创建的表创建单独的 Region。 + + ## 示例 -创建一张简单表并插入一行数据: +创建一个简单的表并插入一行: {{< copyable "sql" >}} @@ -188,7 +199,7 @@ INSERT INTO t1 (a) VALUES (1); SELECT * FROM t1; ``` -```sql +``` mysql> drop table if exists t1; Query OK, 0 rows affected (0.23 sec) @@ -223,7 +234,7 @@ mysql> SELECT * FROM t1; 1 row in set (0.00 sec) ``` -删除一张表。如果该表不存在,就建一张表: +如果表存在则删除,如果表不存在则有条件地创建表: {{< copyable "sql" >}} @@ -239,11 +250,13 @@ DESC t1; ```sql mysql> DROP TABLE IF EXISTS t1; Query OK, 0 rows affected (0.22 sec) + mysql> CREATE TABLE IF NOT EXISTS t1 ( - id BIGINT NOT NULL PRIMARY KEY auto_increment, - b VARCHAR(200) NOT NULL - ); + id BIGINT NOT NULL PRIMARY KEY auto_increment, + b VARCHAR(200) NOT NULL + ); Query OK, 0 rows affected (0.08 sec) + mysql> DESC t1; +-------+--------------+------+------+---------+----------------+ | Field | Type | Null | Key | Default | Extra | @@ -256,14 +269,26 @@ mysql> DESC t1; ## MySQL 兼容性 -* 支持除空间类型以外的所有数据类型。 -* 为了兼容 MySQL,TiDB 在语法上支持 `HASH`、`BTREE` 和 `RTREE` 等索引类型,但会忽略它们。 +* 支持除空间类型外的所有数据类型。 +* TiDB 在语法上接受 `HASH`、`BTREE` 和 `RTREE` 等索引类型以与 MySQL 兼容,但会忽略它们。 * TiDB 支持解析 `FULLTEXT` 语法,但不支持使用 `FULLTEXT` 索引。 -* 为了与 MySQL 兼容,`index_col_name` 属性支持 length 选项,最大长度默认限制为 3072 字节。此长度限制可以通过配置项 `max-index-length` 更改,具体请参阅 [TiDB 配置文件描述](/tidb-configuration-file.md#max-index-length)。 -* 为了与 MySQL 兼容,TiDB 会解析但忽略 `index_col_name` 属性的 `[ASC | DESC]` 索引排序选项。 + + + +* 为了兼容性,`index_col_name` 属性支持长度选项,默认最大长度限制为 3072 字节。可以通过 `max-index-length` 配置选项更改长度限制。详情请参见 [TiDB 配置文件](/tidb-configuration-file.md#max-index-length)。 + + + + + +* 为了兼容性,`index_col_name` 属性支持长度选项,最大长度限制为 3072 字节。 + + + +* `index_col_name` 中的 `[ASC | DESC]` 目前会被解析但忽略(与 MySQL 5.7 兼容的行为)。 * `COMMENT` 属性不支持 `WITH PARSER` 选项。 -* TiDB 在单个表中默认支持 1017 列,最大可支持 4096 列。InnoDB 中相应的数量限制为 1017 列,MySQL 中的硬限制为 4096 列。详情参阅 [TiDB 使用限制](/tidb-limitations.md)。 -* 分区表支持 `HASH`、`RANGE`、`LIST` 和 `KEY` [分区类型](/partitioned-table.md#分区类型)。对于不支持的分区类型,TiDB 会报 `Warning: Unsupported partition type %s, treat as normal table` 错误,其中 `%s` 为不支持的具体分区类型。 +* TiDB 默认支持单个表中的 1017 列,最多支持 4096 列。InnoDB 中对应的限制是 1017 列,MySQL 的硬限制是 4096 列。详情请参见 [TiDB 限制](/tidb-limitations.md)。 +* TiDB 支持 `HASH`、`RANGE`、`LIST` 和 `KEY` [分区类型](/partitioned-table.md#分区类型)。对于不支持的分区类型,TiDB 返回 `Warning: Unsupported partition type %s, treat as normal table`,其中 `%s` 是具体的不支持的分区类型。 ## 另请参阅 diff --git a/sql-statements/sql-statement-create-user.md b/sql-statements/sql-statement-create-user.md index 1a3f2002216d..67ddedaba6f1 100644 --- a/sql-statements/sql-statement-create-user.md +++ b/sql-statements/sql-statement-create-user.md @@ -1,13 +1,13 @@ --- -title: CREATE USER -summary: TiDB 数据库中 CREATE USER 的使用概况。 +title: CREATE USER | TiDB SQL 语句参考 +summary: TiDB 数据库中 CREATE USER 的使用概述。 --- # CREATE USER -`CREATE USER` 语句用于创建带有指定密码的新用户。和 MySQL 一样,在 TiDB 权限系统中,用户是用户名和用户名所连接主机的组合。因此,可创建一个用户 `'newuser2'@'192.168.1.1'`,使其只能通过 IP 地址 `192.168.1.1` 进行连接。相同的用户名从不同主机登录时可能会拥有不同的权限。 +此语句用于创建一个新用户,并指定密码。在 MySQL 权限系统中,用户是用户名和其连接来源主机的组合。因此,可以创建一个只能从 IP 地址 `192.168.1.1` 连接的用户 `'newuser2'@'192.168.1.1'`。同时也可以让两个用户具有相同的用户名部分,但因为从不同的主机登录而具有不同的权限。 -## 语法图 +## 语法 ```ebnf+diagram CreateUserStmt ::= @@ -50,57 +50,35 @@ RequireListElement ::= 'ISSUER' Issuer | 'SUBJECT' Subject | 'CIPHER' Cipher | ' ## 示例 -创建一个密码为 `newuserpassword` 的用户。 - -{{< copyable "sql" >}} +创建一个密码为 `newuserpassword` 的用户: ```sql -CREATE USER 'newuser' IDENTIFIED BY 'newuserpassword'; -``` - -``` +mysql> CREATE USER 'newuser' IDENTIFIED BY 'newuserpassword'; Query OK, 1 row affected (0.04 sec) ``` -创建一个只能在 `192.168.1.1` 登录的用户,密码为 `newuserpassword`。 - -{{< copyable "sql" >}} +创建一个只能从 `192.168.1.1` 登录的用户: ```sql -CREATE USER 'newuser2'@'192.168.1.1' IDENTIFIED BY 'newuserpassword'; -``` - -``` +mysql> CREATE USER 'newuser2'@'192.168.1.1' IDENTIFIED BY 'newuserpassword'; Query OK, 1 row affected (0.02 sec) ``` -创建一个要求在登录时使用 TLS 连接的用户。 - -{{< copyable "sql" >}} +创建一个必须使用 TLS 连接登录的用户: ```sql CREATE USER 'newuser3'@'%' IDENTIFIED BY 'newuserpassword' REQUIRE SSL; -``` - -``` Query OK, 1 row affected (0.02 sec) ``` -创建一个要求在登录时提供指定客户端证书的用户。 - -{{< copyable "sql" >}} +创建一个登录时需要使用 X.509 证书的用户: ```sql CREATE USER 'newuser4'@'%' IDENTIFIED BY 'newuserpassword' REQUIRE ISSUER '/C=US/ST=California/L=San Francisco/O=PingCAP'; -``` - -``` Query OK, 1 row affected (0.02 sec) ``` -创建一个初始状态下被锁住的用户。 - -{{< copyable "sql" >}} +创建一个创建时就被锁定的用户: ```sql CREATE USER 'newuser5'@'%' ACCOUNT LOCK; @@ -110,7 +88,7 @@ CREATE USER 'newuser5'@'%' ACCOUNT LOCK; Query OK, 1 row affected (0.02 sec) ``` -创建一个带注释的用户。 +创建一个带有注释的用户: ```sql CREATE USER 'newuser6'@'%' COMMENT 'This user is created only for test'; @@ -126,7 +104,7 @@ SELECT * FROM information_schema.user_attributes; 1 rows in set (0.00 sec) ``` -创建一个具有邮箱 (`email`) 属性的用户。 +创建一个带有 `email` 属性的用户: ```sql CREATE USER 'newuser7'@'%' ATTRIBUTE '{"email": "user@pingcap.com"}'; @@ -142,7 +120,7 @@ SELECT * FROM information_schema.user_attributes; 1 rows in set (0.00 sec) ``` -创建一个禁止重复使用最近 5 次密码的用户。 +创建一个不允许重复使用最近 5 个密码的用户: ```sql CREATE USER 'newuser8'@'%' PASSWORD HISTORY 5; @@ -152,7 +130,7 @@ CREATE USER 'newuser8'@'%' PASSWORD HISTORY 5; Query OK, 1 row affected (0.02 sec) ``` -创建一个密码已经手动过期的用户。 +创建一个密码已手动过期的用户: ```sql CREATE USER 'newuser9'@'%' PASSWORD EXPIRE; @@ -170,24 +148,30 @@ SELECT USER, HOST, USER_ATTRIBUTES FROM MYSQL.USER WHERE USER='newuser7'; ``` ```sql -+-----------+------+---------------------------------------------------+ -| USER | HOST | USER_ATTRIBUTES | -+-----------+------+---------------------------------------------------+ -| newuser7 | % | {"resource_group": "rg1"} | -+-----------+------+---------------------------------------------------+ ++----------+------+---------------------------+ +| USER | HOST | USER_ATTRIBUTES | ++----------+------+---------------------------+ +| newuser7 | % | {"resource_group": "rg1"} | ++----------+------+---------------------------+ 1 rows in set (0.00 sec) ``` ## MySQL 兼容性 -* TiDB 不支持 `WITH MAX_QUERIES_PER_HOUR`、`WITH MAX_UPDATES_PER_HOUR`、`WITH MAX_USER_CONNECTIONS` 等 `CREATE` 选项。 +以下 `CREATE USER` 选项尚未被 TiDB 支持,将被解析但会被忽略: + +* TiDB 不支持 `WITH MAX_QUERIES_PER_HOUR`、`WITH MAX_UPDATES_PER_HOUR` 和 `WITH MAX_USER_CONNECTIONS` 选项。 * TiDB 不支持 `DEFAULT ROLE` 选项。 -* 对于 TiDB 尚不支持的 `CREATE` 选项。这些选项可被解析,但会被忽略。 ## 另请参阅 -* [Security Compatibility with MySQL](/security-compatibility-with-mysql.md) + + +* [与 MySQL 的安全兼容性](/security-compatibility-with-mysql.md) +* [权限管理](/privilege-management.md) + + + * [DROP USER](/sql-statements/sql-statement-drop-user.md) * [SHOW CREATE USER](/sql-statements/sql-statement-show-create-user.md) * [ALTER USER](/sql-statements/sql-statement-alter-user.md) -* [Privilege Management](/privilege-management.md) diff --git a/sql-statements/sql-statement-create-view.md b/sql-statements/sql-statement-create-view.md index 077e4d08a77f..1c1550ba8a13 100644 --- a/sql-statements/sql-statement-create-view.md +++ b/sql-statements/sql-statement-create-view.md @@ -1,13 +1,13 @@ --- -title: CREATE VIEW -summary: TiDB 数据库中 CREATE VIEW 的使用概况。 +title: CREATE VIEW | TiDB SQL 语句参考 +summary: TiDB 数据库中 CREATE VIEW 的使用概述。 --- # CREATE VIEW -使用 `CREATE VIEW` 语句将 `SELECT` 语句保存为类似于表的可查询对象。TiDB 中的视图是非物化的,这意味着在查询视图时,TiDB 将在内部重写查询,以将视图定义与 SQL 查询结合起来。 +`CREATE VIEW` 语句将 `SELECT` 语句保存为可查询对象,类似于表。TiDB 中的视图是非物化的。这意味着在查询视图时,TiDB 会在内部重写查询,将视图定义与 SQL 查询组合在一起。 -## 语法图 +## 语法概要 ```ebnf+diagram CreateViewStmt ::= @@ -36,44 +36,18 @@ ViewCheckOption ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` - -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} -```sql -CREATE VIEW v1 AS SELECT * FROM t1 WHERE c1 > 2; -``` - -``` +mysql> CREATE VIEW v1 AS SELECT * FROM t1 WHERE c1 > 2; Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -84,15 +58,8 @@ SELECT * FROM t1; | 5 | 5 | +----+----+ 5 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM v1; -``` - -``` +mysql> SELECT * FROM v1; +----+----+ | id | c1 | +----+----+ @@ -101,25 +68,11 @@ SELECT * FROM v1; | 5 | 5 | +----+----+ 3 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (c1) VALUES (6); -``` - -``` +mysql> INSERT INTO t1 (c1) VALUES (6); Query OK, 1 row affected (0.01 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM v1; -``` - -``` +mysql> SELECT * FROM v1; +----+----+ | id | c1 | +----+----+ @@ -129,23 +82,16 @@ SELECT * FROM v1; | 6 | 6 | +----+----+ 4 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO v1 (c1) VALUES (7); -``` - -``` +mysql> INSERT INTO v1 (c1) VALUES (7); ERROR 1105 (HY000): insert into view v1 is not supported now. ``` ## MySQL 兼容性 -* 目前 TiDB 中的任何视图都不可被插入,也不可被更新(即不支持 INSERT VIEW,也不支持 UPDATE VIEW)。`WITH CHECK OPTION` 只做了语法兼容但不生效。 -* 目前 TiDB 中的视图不支持 `ALTER VIEW`,但可以使用 `CREATE OR REPLACE` 替代。 -* 目前 `ALGORITHM` 字段在 TiDB 中只做了语法兼容但不生效,TiDB 目前只支持 MERGE 算法。 +* 目前,TiDB 中的任何视图都不能进行插入或更新操作(即不支持 `INSERT VIEW` 和 `UPDATE VIEW`)。`WITH CHECK OPTION` 仅在语法上兼容但不生效。 +* 目前,TiDB 中的视图不支持 `ALTER VIEW`,但你可以使用 `CREATE OR REPLACE` 代替。 +* 目前,`ALGORITHM` 字段在 TiDB 中仅在语法上兼容但不生效。TiDB 目前仅支持 MERGE 算法。 ## 另请参阅 diff --git a/sql-statements/sql-statement-deallocate.md b/sql-statements/sql-statement-deallocate.md index 7df78128ac6a..8effa3d10491 100644 --- a/sql-statements/sql-statement-deallocate.md +++ b/sql-statements/sql-statement-deallocate.md @@ -1,11 +1,11 @@ --- -title: DEALLOCATE -summary: TiDB 数据库中 DEALLOCATE 的使用概况。 +title: DEALLOCATE | TiDB SQL 语句参考 +summary: TiDB 数据库中 DEALLOCATE 的使用概览。 --- # DEALLOCATE -`DEALLOCATE` 语句用于为服务器端预处理语句提供 SQL 接口。 +`DEALLOCATE` 语句为服务器端预处理语句提供了 SQL 接口。 ## 语法图 @@ -26,54 +26,28 @@ Identifier ::= ## 示例 -{{< copyable "sql" >}} - ```sql -PREPARE mystmt FROM 'SELECT ? as num FROM DUAL'; -``` - -``` +mysql> PREPARE mystmt FROM 'SELECT ? as num FROM DUAL'; Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -SET @number = 5; -``` - -``` +mysql> SET @number = 5; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -EXECUTE mystmt USING @number; -``` - -``` +mysql> EXECUTE mystmt USING @number; +------+ | num | +------+ | 5 | +------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -DEALLOCATE PREPARE mystmt; -``` - -``` +mysql> DEALLOCATE PREPARE mystmt; Query OK, 0 rows affected (0.00 sec) ``` ## MySQL 兼容性 -`DEALLOCATE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `DEALLOCATE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-delete.md b/sql-statements/sql-statement-delete.md index 77f987d0063a..2379ea5db58d 100644 --- a/sql-statements/sql-statement-delete.md +++ b/sql-statements/sql-statement-delete.md @@ -1,11 +1,11 @@ --- -title: DELETE -summary: TiDB 数据库中 DELETE 的使用概况。 +title: DELETE | TiDB SQL 语句参考 +summary: TiDB 数据库中 DELETE 的使用概述。 --- # DELETE -`DELETE` 语句用于从指定的表中删除行。 +`DELETE` 语句用于从指定表中删除行。 ## 语法图 @@ -16,34 +16,15 @@ DeleteFromStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -54,25 +35,11 @@ SELECT * FROM t1; | 5 | 5 | +----+----+ 5 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -DELETE FROM t1 WHERE id = 4; -``` -``` +mysql> DELETE FROM t1 WHERE id = 4; Query OK, 1 row affected (0.02 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -86,7 +53,7 @@ SELECT * FROM t1; ## MySQL 兼容性 -`DELETE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `DELETE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-desc.md b/sql-statements/sql-statement-desc.md index c834a0fc0e4f..96f934362ff3 100644 --- a/sql-statements/sql-statement-desc.md +++ b/sql-statements/sql-statement-desc.md @@ -1,8 +1,8 @@ --- -title: DESC -summary: TiDB 数据库中 DESC 的使用概况。 +title: DESC | TiDB SQL 语句参考 +summary: TiDB 数据库中 `DESC` 的使用概览。 --- # DESC -`DESC` 语句是 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 的别名。包含该语句提供了 MySQL 兼容性。 +该语句是 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 的别名。包含此语句是为了与 MySQL 兼容。 diff --git a/sql-statements/sql-statement-describe.md b/sql-statements/sql-statement-describe.md index d4ca641ba603..1f9cc479c8d1 100644 --- a/sql-statements/sql-statement-describe.md +++ b/sql-statements/sql-statement-describe.md @@ -1,8 +1,8 @@ --- -title: DESCRIBE -summary: TiDB 数据库中 DESCRIBE 的使用概况。 +title: DESCRIBE | TiDB SQL 语句参考 +summary: TiDB 数据库中 DESCRIBE 的使用概述。 --- # DESCRIBE -`DESCRIBE` 语句为 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 的别名。包含该语句提供了 MySQL 兼容性。 +此语句是 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 的别名。它是为了与 MySQL 保持兼容而包含的。 diff --git a/sql-statements/sql-statement-do.md b/sql-statements/sql-statement-do.md index 6a1d526bcbb0..49e1d4f45ffe 100644 --- a/sql-statements/sql-statement-do.md +++ b/sql-statements/sql-statement-do.md @@ -1,17 +1,17 @@ --- -title: DO | TiDB SQL Statement Reference -summary: TiDB 数据库中 DO 的使用概况。 +title: DO | TiDB SQL 语句参考 +summary: TiDB 数据库中 DO 的使用概述。 --- # DO -`DO` 语句用于执行表达式,但不返回任何结果。大部分情况下,`DO` 相当于不返回结果的 `SELECT expr, ...,`。 +`DO` 执行表达式但不返回任何结果。在大多数情况下,`DO` 等同于不返回结果的 `SELECT expr, ...`。 > **注意:** > -> `DO` 只能执行表达式,所以不是所有能够用 `SELECT` 的地方都能用 `DO` 替换。例如 `DO id FROM t1` 就是不是合法的 SQL 语句,因为它引用了一张表。 +> `DO` 只执行表达式。它不能在所有可以使用 `SELECT` 的场合使用。例如,`DO id FROM t1` 是无效的,因为它引用了一个表。 -`DO` 在 MySQL 中的一个主要应用场景是存储过程或者触发器。因为 TiDB 当前不支持存储过程和触发器,所以 `DO` 的实际使用场景较少。 +在 MySQL 中,一个常见的用例是执行存储过程或触发器。由于 TiDB 不提供存储过程或触发器,此功能的使用有限。 ## 语法图 @@ -29,15 +29,10 @@ Expression ::= ## 示例 -这条 `SELECT` 语句会暂停执行,但同时也会返回一个结果集。 - -{{< copyable "sql" >}} +这个 SELECT 语句会暂停,但同时也会产生一个结果集。 ```sql -SELECT SLEEP(5); -``` - -``` +mysql> SELECT SLEEP(5); +----------+ | SLEEP(5) | +----------+ @@ -46,31 +41,19 @@ SELECT SLEEP(5); 1 row in set (5.00 sec) ``` -如果使用 `DO` 的话,语句同样会暂停,但不会返回结果集。 - -{{< copyable "sql" >}} +相比之下,DO 会暂停但不产生结果集。 ```sql -DO SLEEP(5); -``` - -``` +mysql> DO SLEEP(5); Query OK, 0 rows affected (5.00 sec) -``` -{{< copyable "sql" >}} - -```sql -DO SLEEP(1), SLEEP(1.5); -``` - -``` +mysql> DO SLEEP(1), SLEEP(1.5); Query OK, 0 rows affected (2.50 sec) ``` ## MySQL 兼容性 -`DO` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `DO` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-drop-binding.md b/sql-statements/sql-statement-drop-binding.md index c58c26e78b8c..7b33f198fa45 100644 --- a/sql-statements/sql-statement-drop-binding.md +++ b/sql-statements/sql-statement-drop-binding.md @@ -1,15 +1,15 @@ --- title: DROP [GLOBAL|SESSION] BINDING -summary: TiDB 数据库中 DROP [GLOBAL|SESSION] BINDING 的使用概况。 +summary: TiDB 数据库中 DROP BINDING 的使用方法。 --- # DROP [GLOBAL|SESSION] BINDING -`DROP BINDING` 语句用于删除指定的 SQL 绑定。绑定可用于将优化器 Hint 插入语句中,而无需更改底层查询。 +此语句从特定的 SQL 语句中删除绑定。绑定可用于在不需要更改底层查询的情况下向语句注入提示。 -`BINDING` 语句可以在 `GLOBAL` 或者 `SESSION` 作用域内删除执行计划绑定。在不指定作用域时,默认的作用域为 `SESSION`。 +`BINDING` 可以是 `GLOBAL` 或 `SESSION` 级别。默认为 `SESSION`。 -## 语法图 +## 语法 ```ebnf+diagram DropBindingStmt ::= @@ -27,48 +27,48 @@ BindableStmt ::= 你可以根据 SQL 语句或 `sql_digest` 删除绑定。 -下面的示例演示如何根据 SQL 语句删除绑定。 +以下示例展示如何根据 SQL 语句删除绑定。 {{< copyable "sql" >}} ```sql -CREATE TABLE t1 ( - id INT NOT NULL PRIMARY KEY auto_increment, - b INT NOT NULL, - pad VARBINARY(255), - INDEX(b) - ); +mysql> CREATE TABLE t1 ( + id INT NOT NULL PRIMARY KEY auto_increment, + b INT NOT NULL, + pad VARBINARY(255), + INDEX(b) + ); Query OK, 0 rows affected (0.07 sec) -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM dual; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM dual; Query OK, 1 row affected (0.01 sec) Records: 1 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 8 rows affected (0.00 sec) Records: 8 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 1000 rows affected (0.04 sec) Records: 1000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (1.74 sec) Records: 100000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (2.15 sec) Records: 100000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (2.64 sec) Records: 100000 Duplicates: 0 Warnings: 0 -SELECT SLEEP(1); +mysql> SELECT SLEEP(1); +----------+ | SLEEP(1) | +----------+ @@ -76,10 +76,10 @@ SELECT SLEEP(1); +----------+ 1 row in set (1.00 sec) -ANALYZE TABLE t1; +mysql> ANALYZE TABLE t1; Query OK, 0 rows affected (1.33 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ @@ -89,13 +89,13 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ 3 rows in set (0.02 sec) -CREATE SESSION BINDING FOR - SELECT * FROM t1 WHERE b = 123 - USING - SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123; +mysql> CREATE SESSION BINDING FOR + SELECT * FROM t1 WHERE b = 123 + USING + SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123; Query OK, 0 rows affected (0.00 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ @@ -105,7 +105,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ 3 rows in set (0.22 sec) -SHOW SESSION BINDINGS\G +mysql> SHOW SESSION BINDINGS\G *************************** 1. row *************************** Original_sql: select * from t1 where b = ? Bind_sql: SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123 @@ -117,10 +117,10 @@ Original_sql: select * from t1 where b = ? Collation: utf8mb4_0900_ai_ci 1 row in set (0.00 sec) -DROP SESSION BINDING FOR SELECT * FROM t1 WHERE b = 123; +mysql> DROP SESSION BINDING FOR SELECT * FROM t1 WHERE b = 123; Query OK, 0 rows affected (0.00 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+-------------------------------------------------------------------------+-----------------------------------+----------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------------+---------+---------+-----------+----------------------+-------------------------------------------------------------------------+-----------------------------------+----------------+------+ @@ -130,11 +130,11 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+-------------------------------------------------------------------------+-----------------------------------+----------------+------+ 3 rows in set (0.01 sec) -SHOW SESSION BINDINGS\G +mysql> SHOW SESSION BINDINGS\G Empty set (0.00 sec) ``` -下面的示例演示如何根据 `sql_digest` 删除绑定。 +以下示例展示如何根据 `sql_digest` 删除绑定。 ```sql mysql> CREATE TABLE t(id INT PRIMARY KEY , a INT, KEY(a)); @@ -195,12 +195,12 @@ No query specified ## MySQL 兼容性 -`DROP [GLOBAL|SESSION] BINDING` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 * [CREATE [GLOBAL|SESSION] BINDING](/sql-statements/sql-statement-create-binding.md) * [SHOW [GLOBAL|SESSION] BINDINGS](/sql-statements/sql-statement-show-bindings.md) -* [ANALYZE](/sql-statements/sql-statement-analyze-table.md) -* [Optimizer Hints](/optimizer-hints.md) -* [执行计划管理 (SPM)](/sql-plan-management.md) +* [ANALYZE TABLE](/sql-statements/sql-statement-analyze-table.md) +* [优化器提示](/optimizer-hints.md) +* [SQL 执行计划管理](/sql-plan-management.md) diff --git a/sql-statements/sql-statement-drop-column.md b/sql-statements/sql-statement-drop-column.md index ea185b631d7f..c2d3b939da5c 100644 --- a/sql-statements/sql-statement-drop-column.md +++ b/sql-statements/sql-statement-drop-column.md @@ -1,13 +1,13 @@ --- -title: DROP COLUMN -summary: TiDB 数据库中 DROP COLUMN 的使用概况。 +title: DROP COLUMN | TiDB SQL 语句参考 +summary: TiDB 数据库中 DROP COLUMN 的使用概览。 --- # DROP COLUMN -`DROP COLUMN` 语句用于从指定的表中删除列。在 TiDB 中,`DROP COLUMN` 为在线操作,不会阻塞表中的数据读写。 +此语句从指定的表中删除一列。在 TiDB 中,`DROP COLUMN` 是在线操作,这意味着它不会阻塞读取或写入操作。 -## 语法图 +## 语法 ```ebnf+diagram AlterTableStmt @@ -22,34 +22,15 @@ ColumnName ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, col1 INT NOT NULL, col2 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, col1 INT NOT NULL, col2 INT NOT NULL); Query OK, 0 rows affected (0.12 sec) -``` - -{{< copyable "sql" >}} -```sql -INSERT INTO t1 (col1,col2) VALUES (1,1),(2,2),(3,3),(4,4),(5,5); -``` - -``` +mysql> INSERT INTO t1 (col1,col2) VALUES (1,1),(2,2),(3,3),(4,4),(5,5); Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+------+------+ | id | col1 | col2 | +----+------+------+ @@ -60,25 +41,10 @@ SELECT * FROM t1; | 5 | 5 | 5 | +----+------+------+ 5 rows in set (0.01 sec) -``` - -{{< copyable "sql" >}} - -```sql -ALTER TABLE t1 DROP COLUMN col1, DROP COLUMN col2; -``` -``` +mysql> ALTER TABLE t1 DROP COLUMN col1, DROP COLUMN col2; ERROR 1105 (HY000): can't run multi schema change -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+------+------+ | id | col1 | col2 | +----+------+------+ @@ -89,25 +55,11 @@ SELECT * FROM t1; | 5 | 5 | 5 | +----+------+------+ 5 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -ALTER TABLE t1 DROP COLUMN col1; -``` - -``` +mysql> ALTER TABLE t1 DROP COLUMN col1; Query OK, 0 rows affected (0.27 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+------+ | id | col2 | +----+------+ @@ -122,7 +74,7 @@ SELECT * FROM t1; ## MySQL 兼容性 -* 目前不支持删除主键列或组合索引相关列。 +* 不支持删除主键列或被组合索引覆盖的列。 ## 另请参阅 diff --git a/sql-statements/sql-statement-drop-database.md b/sql-statements/sql-statement-drop-database.md index b3ae199e6f3f..87d9d6a16d72 100644 --- a/sql-statements/sql-statement-drop-database.md +++ b/sql-statements/sql-statement-drop-database.md @@ -1,13 +1,13 @@ --- -title: DROP DATABASE -summary: TiDB 数据库中 DROP DATABASE 的使用概况。 +title: DROP DATABASE | TiDB SQL 语句参考 +summary: TiDB 数据库中 DROP DATABASE 的使用概述。 --- # DROP DATABASE -`DROP DATABASE` 语句用于永久删除指定的数据库,以及删除所有在 schema 中创建的表和视图。与被删数据库相关联的用户权限不受影响。 +`DROP DATABASE` 语句永久删除指定的数据库架构,以及其中创建的所有表和视图。与被删除数据库相关联的用户权限不受影响。 -## 语法图 +## 语法概要 ```ebnf+diagram DropDatabaseStmt ::= @@ -18,13 +18,8 @@ IfExists ::= ( 'IF' 'EXISTS' )? ## 示例 -{{< copyable "sql" >}} - ```sql -SHOW DATABASES; -``` - -``` +mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ @@ -34,25 +29,11 @@ SHOW DATABASES; | test | +--------------------+ 4 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -DROP DATABASE test; -``` -``` +mysql> DROP DATABASE test; Query OK, 0 rows affected (0.25 sec) -``` - -{{< copyable "sql" >}} -```sql -SHOW DATABASES; -``` - -``` +mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ @@ -65,7 +46,7 @@ SHOW DATABASES; ## MySQL 兼容性 -`DROP DATABASE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `DROP DATABASE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告 bug](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-drop-index.md b/sql-statements/sql-statement-drop-index.md index 6823bc20f748..87988fb4d79b 100644 --- a/sql-statements/sql-statement-drop-index.md +++ b/sql-statements/sql-statement-drop-index.md @@ -1,13 +1,13 @@ --- -title: DROP INDEX -summary: TiDB 数据库中 DROP INDEX 的使用概况。 +title: DROP INDEX | TiDB SQL 语句参考 +summary: TiDB 数据库中 DROP INDEX 的使用概述。 --- # DROP INDEX -`DROP INDEX` 语句用于从指定的表中删除索引,并在 TiKV 中将空间标记为释放。 +此语句用于从指定表中删除索引,并在 TiKV 中将相应空间标记为可用。 -## 语法图 +## 语法 ```ebnf+diagram DropIndexStmt ::= @@ -22,34 +22,15 @@ IndexLockAndAlgorithmOpt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.10 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +-------------------------+----------+-----------+---------------+--------------------------------+ | id | estRows | task | access object | operator info | +-------------------------+----------+-----------+---------------+--------------------------------+ @@ -58,25 +39,11 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; | └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +-------------------------+----------+-----------+---------------+--------------------------------+ 3 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -CREATE INDEX c1 ON t1 (c1); -``` - -``` +mysql> CREATE INDEX c1 ON t1 (c1); Query OK, 0 rows affected (0.30 sec) -``` - -{{< copyable "sql" >}} -```sql -EXPLAIN SELECT * FROM t1 WHERE c1 = 3; -``` - -``` +mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3; +------------------------+---------+-----------+------------------------+---------------------------------------------+ | id | estRows | task | access object | operator info | +------------------------+---------+-----------+------------------------+---------------------------------------------+ @@ -84,21 +51,14 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3; | └─IndexRangeScan_5 | 0.01 | cop[tikv] | table:t1, index:c1(c1) | range:[3,3], keep order:false, stats:pseudo | +------------------------+---------+-----------+------------------------+---------------------------------------------+ 2 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -DROP INDEX c1 ON t1; -``` - -``` +mysql> DROP INDEX c1 ON t1; Query OK, 0 rows affected (0.30 sec) ``` ## MySQL 兼容性 -* 不支持删除 `CLUSTERED` 类型的 `PRIMARY KEY`。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 +* 不支持删除 `CLUSTERED` 类型的主键。关于 `CLUSTERED` 类型的主键的更多详情,请参考[聚簇索引](/clustered-indexes.md)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-drop-placement-policy.md b/sql-statements/sql-statement-drop-placement-policy.md index 8e441e6976d1..91e136ed1a5f 100644 --- a/sql-statements/sql-statement-drop-placement-policy.md +++ b/sql-statements/sql-statement-drop-placement-policy.md @@ -1,11 +1,15 @@ --- title: DROP PLACEMENT POLICY -summary: TiDB 数据库中 ALTER PLACEMENT POLICY 的使用概况。 +summary: TiDB 中 ALTER PLACEMENT POLICY 的使用方法。 --- # DROP PLACEMENT POLICY -`DROP PLACEMENT POLICY` 用于删除已创建的放置策略。 +`DROP PLACEMENT POLICY` 用于删除先前创建的放置策略。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ## 语法图 @@ -19,21 +23,21 @@ PolicyName ::= ## 示例 -删除放置规则时,确保该策略未被任何表或分区引用,否则会删除失败。 +只有当放置策略没有被任何表或分区引用时,才能删除它。 {{< copyable "sql" >}} ```sql CREATE PLACEMENT POLICY p1 FOLLOWERS=4; CREATE TABLE t1 (a INT PRIMARY KEY) PLACEMENT POLICY=p1; -DROP PLACEMENT POLICY p1; -- 该语句执行失败,因为放置规则 p1 被引用。 +DROP PLACEMENT POLICY p1; -- 此语句失败,因为放置策略 p1 正在被引用。 --- 查看引用放置规则的表和分区。 +-- 查找哪些表和分区引用了该放置策略。 SELECT table_schema, table_name FROM information_schema.tables WHERE tidb_placement_policy_name='p1'; SELECT table_schema, table_name FROM information_schema.partitions WHERE tidb_placement_policy_name='p1'; -ALTER TABLE t1 PLACEMENT POLICY=default; -- 移除表 t1 上的默认放置规则。 -DROP PLACEMENT POLICY p1; -- 执行成功。 +ALTER TABLE t1 PLACEMENT POLICY=default; -- 从 t1 中移除放置策略。 +DROP PLACEMENT POLICY p1; -- 成功。 ``` ```sql @@ -63,7 +67,7 @@ Query OK, 0 rows affected (0.21 sec) ## 另请参阅 -* [Placement Rules in SQL](/placement-rules-in-sql.md) +* [SQL 中的放置规则](/placement-rules-in-sql.md) * [SHOW PLACEMENT](/sql-statements/sql-statement-show-placement.md) * [CREATE PLACEMENT POLICY](/sql-statements/sql-statement-create-placement-policy.md) * [ALTER PLACEMENT POLICY](/sql-statements/sql-statement-alter-placement-policy.md) diff --git a/sql-statements/sql-statement-drop-resource-group.md b/sql-statements/sql-statement-drop-resource-group.md index 96f4cbb4c5e3..0668b3a20308 100644 --- a/sql-statements/sql-statement-drop-resource-group.md +++ b/sql-statements/sql-statement-drop-resource-group.md @@ -1,13 +1,17 @@ --- title: DROP RESOURCE GROUP -summary: TiDB 数据库中 DROP RESOURCE GROUP 的使用概况。 +summary: 了解在 TiDB 中 DROP RESOURCE GROUP 的用法。 --- # DROP RESOURCE GROUP -`DROP RESOURCE GROUP` 语句用于在当前所选数据库中删除资源组。 +你可以使用 `DROP RESOURCE GROUP` 语句删除资源组。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法概要 ```ebnf+diagram DropResourceGroupStmt ::= @@ -23,12 +27,12 @@ ResourceGroupName ::= > **注意:** > -> - `DROP RESOURCE GROUP` 语句只能在全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-从-v660-版本开始引入) 设置为 `ON` 时才能执行。 -> - `default` 资源组为系统保留的资源组,不支持删除。 +> - 只有当全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-new-in-v660) 设置为 `ON` 时,才能执行 `DROP RESOURCE GROUP` 语句。 +> - `default` 资源组是保留的,不能被删除。 ## 示例 -删除名为 `rg1` 的资源组: +删除名为 `rg1` 的资源组。 ```sql DROP RESOURCE GROUP IF EXISTS rg1; @@ -83,4 +87,4 @@ MySQL 也支持 [DROP RESOURCE GROUP](https://dev.mysql.com/doc/refman/8.0/en/dr * [ALTER RESOURCE GROUP](/sql-statements/sql-statement-alter-resource-group.md) * [CREATE RESOURCE GROUP](/sql-statements/sql-statement-create-resource-group.md) -* [RU](/tidb-resource-control.md#什么是-request-unit-ru) +* [请求单元 (RU)](/tidb-resource-control.md#what-is-request-unit-ru) diff --git a/sql-statements/sql-statement-drop-role.md b/sql-statements/sql-statement-drop-role.md index 38c3bd7d4327..9b65f73f9313 100644 --- a/sql-statements/sql-statement-drop-role.md +++ b/sql-statements/sql-statement-drop-role.md @@ -1,13 +1,13 @@ --- -title: DROP ROLE -summary: TiDB 数据库中 DROP ROLE 的使用概况。 +title: DROP ROLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 DROP ROLE 的使用概述。 --- # DROP ROLE -使用 `DROP ROLE` 语句可删除已用 `CREATE ROLE` 语句创建的角色。 +此语句用于删除之前通过 `CREATE ROLE` 创建的角色。 -## 语法图 +## 语法 ```ebnf+diagram DropRoleStmt ::= @@ -19,13 +19,13 @@ RolenameList ::= ## 示例 -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -创建新角色 `analyticsteam` 和新用户 `jennifer`: +创建一个新角色 `analyticsteam` 和一个新用户 `jennifer`: ```sql CREATE ROLE analyticsteam; @@ -41,13 +41,13 @@ GRANT analyticsteam TO jennifer; Query OK, 0 rows affected (0.01 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -需要注意的是,默认情况下,用户 `jennifer` 需要执行 `SET ROLE analyticsteam` 语句才能使用与角色相关联的权限: +注意,默认情况下,`jennifer` 需要执行 `SET ROLE analyticsteam` 才能使用与 `analyticsteam` 角色相关的权限: ```sql SHOW GRANTS; @@ -83,26 +83,26 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -执行 `SET DEFAULT ROLE` 语句将用户 `jennifer` 与 `analyticsteam` 角色相关联: +可以使用 `SET DEFAULT ROLE` 语句将角色 `analyticsteam` 关联到 `jennifer`: ```sql SET DEFAULT ROLE analyticsteam TO jennifer; Query OK, 0 rows affected (0.02 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -此时 `jennifer` 用户无需执行 `SET ROLE` 语句就能拥有 `analyticsteam` 角色相关联的权限: +此后,用户 `jennifer` 拥有与角色 `analyticsteam` 相关的权限,且 `jennifer` 不需要执行 `SET ROLE` 语句: ```sql SHOW GRANTS; @@ -124,28 +124,28 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -删除角色 `analyticsteam`: +删除 `analyticsteam` 角色: ```sql DROP ROLE analyticsteam; Query OK, 0 rows affected (0.02 sec) ``` -`jennifer` 用户不再具有与 `analyticsteam` 关联的默认角色,或不能再将 `analyticsteam` 设为启用角色: +`jennifer` 不再具有默认角色 `analyticsteam`,也无法将角色设置为 `analyticsteam`。 -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -查看 `jennifer` 用户的权限: +显示 `jennifer` 的权限: ```sql SHOW GRANTS; @@ -162,7 +162,7 @@ ERROR 3530 (HY000): `analyticsteam`@`%` is is not granted to jennifer@% ## MySQL 兼容性 -`DROP ROLE` 语句与 MySQL 8.0 的角色功能完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `DROP ROLE` 语句与 MySQL 8.0 的角色功能完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 @@ -171,4 +171,9 @@ ERROR 3530 (HY000): `analyticsteam`@`%` is is not granted to jennifer@% * [`REVOKE `](/sql-statements/sql-statement-revoke-role.md) * [`SET ROLE`](/sql-statements/sql-statement-set-role.md) * [`SET DEFAULT ROLE`](/sql-statements/sql-statement-set-default-role.md) + + + * [基于角色的访问控制](/role-based-access-control.md) + + diff --git a/sql-statements/sql-statement-drop-sequence.md b/sql-statements/sql-statement-drop-sequence.md index 76163a1ca24e..69a94264181f 100644 --- a/sql-statements/sql-statement-drop-sequence.md +++ b/sql-statements/sql-statement-drop-sequence.md @@ -1,11 +1,11 @@ --- title: DROP SEQUENCE -summary: TiDB 数据库中 DROP SEQUENCE 的使用概况。 +summary: TiDB 数据库中 DROP SEQUENCE 的使用概述。 --- # DROP SEQUENCE -`DROP SEQUENCE` 语句用于删除序列对象。 +`DROP SEQUENCE` 语句用于在 TiDB 中删除序列对象。 ## 语法图 @@ -46,7 +46,7 @@ Query OK, 0 rows affected (0.03 sec) ## MySQL 兼容性 -该语句是 TiDB 的扩展,序列的实现借鉴自 MariaDB。 +该语句是 TiDB 对 MySQL 语法的扩展。其实现参考了 MariaDB 中可用的序列。 ## 另请参阅 diff --git a/sql-statements/sql-statement-drop-stats.md b/sql-statements/sql-statement-drop-stats.md index 90527b3652d4..7ca9259d1cdd 100644 --- a/sql-statements/sql-statement-drop-stats.md +++ b/sql-statements/sql-statement-drop-stats.md @@ -1,13 +1,13 @@ --- title: DROP STATS -summary: TiDB 数据库中 DROP STATS 的使用概况。 +summary: TiDB 数据库中 DROP STATS 的使用概述。 --- # DROP STATS -`DROP STATS` 语句用于从当前所选定的数据库中删除选定表的统计信息。 +`DROP STATS` 语句用于从选定数据库中删除选定表的统计信息。 -## 语法图 +## 语法概要 ```ebnf+diagram DropStatsStmt ::= @@ -17,9 +17,9 @@ TableName ::= Identifier ('.' Identifier)? ``` -## 使用 +## 使用说明 -以下语句用于删除 `TableName` 的所有统计信息。如果指定了分区表,则此语句还会删除该表中所有分区的统计信息以及[动态裁剪模式下的分区表统计信息](/statistics.md#收集动态裁剪模式下的分区表统计信息)。 +以下语句删除 `TableName` 的所有统计信息。如果指定了分区表,此语句会删除该表所有分区的统计信息以及[动态裁剪模式下生成的全局统计信息](/statistics.md#collect-statistics-of-partitioned-tables-in-dynamic-pruning-mode)。 ```sql DROP STATS TableName @@ -29,7 +29,7 @@ DROP STATS TableName Query OK, 0 rows affected (0.00 sec) ``` -以下语句只删除 `PartitionNameList` 中指定分区的统计信息: +以下语句仅删除 `PartitionNameList` 中指定分区的统计信息。 ```sql DROP STATS TableName PARTITION PartitionNameList; @@ -39,7 +39,7 @@ DROP STATS TableName PARTITION PartitionNameList; Query OK, 0 rows affected (0.00 sec) ``` -以下语句只删除指定表在动态裁剪模式下生成的 GlobalStats 统计信息: +以下语句仅删除指定表在动态裁剪模式下生成的全局统计信息。 ```sql DROP STATS TableName GLOBAL; @@ -90,8 +90,8 @@ Empty set (0.00 sec) ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [常规统计信息](/statistics.md) +* [统计信息简介](/statistics.md) diff --git a/sql-statements/sql-statement-drop-table.md b/sql-statements/sql-statement-drop-table.md index 67b063f2f678..aee57b2d12ca 100644 --- a/sql-statements/sql-statement-drop-table.md +++ b/sql-statements/sql-statement-drop-table.md @@ -1,13 +1,13 @@ --- -title: DROP TABLE -summary: TiDB 数据库中 DROP TABLE 的使用概况。 +title: DROP TABLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 DROP TABLE 的使用概览。 --- # DROP TABLE -`DROP TABLE` 语句用于从当前所选的数据库中删除表。如果表不存在则会报错,除非使用 `IF EXISTS` 修饰符。 +此语句从当前选择的数据库中删除一个表。如果表不存在,将返回错误,除非使用 `IF EXISTS` 修饰符。 -## 语法图 +## 语法 ```ebnf+diagram DropTableStmt ::= @@ -26,90 +26,45 @@ TableNameList ::= ## 删除临时表 -删除普通表和临时表的用法如下: +你可以使用以下语法来删除普通表和临时表: -- `DROP TEMPORARY TABLE` 只能删除本地临时表 -- `DROP GLOBAL TEMPORARY TABLE` 只能删除全局临时表 -- `DROP TABLE` 可以删除普通表或临时表 +- 使用 `DROP TEMPORARY TABLE` 删除本地临时表。 +- 使用 `DROP GLOBAL TEMPORARY TABLE` 删除全局临时表。 +- 使用 `DROP TABLE` 删除普通表或临时表。 ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a INT); -``` - -``` +mysql> CREATE TABLE t1 (a INT); Query OK, 0 rows affected (0.11 sec) -``` -{{< copyable "sql" >}} - -```sql -DROP TABLE t1; -``` - -``` +mysql> DROP TABLE t1; Query OK, 0 rows affected (0.22 sec) -``` - -{{< copyable "sql" >}} - -```sql -DROP TABLE table_not_exists; -``` -``` +mysql> DROP TABLE table_not_exists; ERROR 1051 (42S02): Unknown table 'test.table_not_exists' -``` - -{{< copyable "sql" >}} -```sql -DROP TABLE IF EXISTS table_not_exists; -``` - -``` +mysql> DROP TABLE IF EXISTS table_not_exists; Query OK, 0 rows affected, 1 warning (0.01 sec) -``` - -```sql -SHOW WARNINGS; -``` -``` +mysql> SHOW WARNINGS; +-------+------+---------------------------------------+ | Level | Code | Message | +-------+------+---------------------------------------+ | Note | 1051 | Unknown table 'test.table_not_exists' | +-------+------+---------------------------------------+ 1 row in set (0.01 sec) -``` -{{< copyable "sql" >}} - -```sql -CREATE VIEW v1 AS SELECT 1; -``` - -``` +mysql> CREATE VIEW v1 AS SELECT 1; Query OK, 0 rows affected (0.10 sec) -``` - -{{< copyable "sql" >}} -```sql -DROP TABLE v1; -``` - -``` +mysql> DROP TABLE v1; Query OK, 0 rows affected (0.23 sec) ``` ## MySQL 兼容性 -* 目前 `RESTRICT` 和 `CASCADE` 仅在语法上支持。 +目前,`RESTRICT` 和 `CASCADE` 仅在语法上支持。 ## 另请参阅 diff --git a/sql-statements/sql-statement-drop-user.md b/sql-statements/sql-statement-drop-user.md index a5e707251f4f..4520f7ba0426 100644 --- a/sql-statements/sql-statement-drop-user.md +++ b/sql-statements/sql-statement-drop-user.md @@ -1,11 +1,11 @@ --- -title: DROP USER -summary: TiDB 数据库中 DROP USER 的使用概况。 +title: DROP USER | TiDB SQL 语句参考 +summary: TiDB 数据库中 DROP USER 的使用概览。 --- # DROP USER -`DROP USER` 语句用于从 TiDB 系统数据库中删除用户。如果用户不存在,使用关键词 `IF EXISTS` 可避免出现警告。执行 `DROP USER` 语句需要拥有 `CREATE USER` 权限。 +该语句从 TiDB 系统数据库中删除用户。可以使用可选关键字 `IF EXISTS` 来在用户不存在时静默错误。该语句需要 `CREATE USER` 权限。 ## 语法图 @@ -19,53 +19,20 @@ Username ::= ## 示例 -{{< copyable "sql" >}} - ```sql -DROP USER 'idontexist'; -``` - -``` +mysql> DROP USER idontexist; ERROR 1396 (HY000): Operation DROP USER failed for idontexist@% -``` - -{{< copyable "sql" >}} - -```sql -DROP USER IF EXISTS 'idontexist'; -``` -``` +mysql> DROP USER IF EXISTS 'idontexist'; Query OK, 0 rows affected (0.01 sec) -``` - -{{< copyable "sql" >}} - -```sql -CREATE USER 'newuser' IDENTIFIED BY 'mypassword'; -``` -``` +mysql> CREATE USER 'newuser' IDENTIFIED BY 'mypassword'; Query OK, 1 row affected (0.02 sec) -``` - -{{< copyable "sql" >}} - -```sql -GRANT ALL ON test.* TO 'newuser'; -``` -``` +mysql> GRANT ALL ON test.* TO 'newuser'; Query OK, 0 rows affected (0.03 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW GRANTS FOR 'newuser'; -``` - -``` +mysql> SHOW GRANTS FOR 'newuser'; +-------------------------------------------------+ | Grants for newuser@% | +-------------------------------------------------+ @@ -73,60 +40,37 @@ SHOW GRANTS FOR 'newuser'; | GRANT ALL PRIVILEGES ON test.* TO 'newuser'@'%' | +-------------------------------------------------+ 2 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -REVOKE ALL ON test.* FROM 'newuser'; -``` - -``` +mysql> REVOKE ALL ON test.* FROM 'newuser'; Query OK, 0 rows affected (0.03 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW GRANTS FOR 'newuser'; -``` - -``` +mysql> SHOW GRANTS FOR 'newuser'; +-------------------------------------+ | Grants for newuser@% | +-------------------------------------+ | GRANT USAGE ON *.* TO 'newuser'@'%' | +-------------------------------------+ 1 row in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -DROP USER 'newuser'; -``` - -``` +mysql> DROP USER 'newuser'; Query OK, 0 rows affected (0.14 sec) -``` - -{{< copyable "sql" >}} -```sql -SHOW GRANTS FOR 'newuser'; -``` - -``` +mysql> SHOW GRANTS FOR 'newuser'; ERROR 1141 (42000): There is no such grant defined for user 'newuser' on host '%' ``` ## MySQL 兼容性 -* 在 TiDB 中删除不存在的用户时,使用 `IF EXISTS` 可避免出现警告。[Issue #10196](https://github.com/pingcap/tidb/issues/10196) +* 在 TiDB 中,使用 `IF EXISTS` 删除不存在的用户不会产生警告。[问题 #10196](https://github.com/pingcap/tidb/issues/10196)。 ## 另请参阅 * [CREATE USER](/sql-statements/sql-statement-create-user.md) * [ALTER USER](/sql-statements/sql-statement-alter-user.md) * [SHOW CREATE USER](/sql-statements/sql-statement-show-create-user.md) -* [Privilege Management](/privilege-management.md) + + + +* [权限管理](/privilege-management.md) + + diff --git a/sql-statements/sql-statement-drop-view.md b/sql-statements/sql-statement-drop-view.md index ec298327e38c..20f28e501c69 100644 --- a/sql-statements/sql-statement-drop-view.md +++ b/sql-statements/sql-statement-drop-view.md @@ -1,13 +1,13 @@ --- -title: DROP VIEW -summary: TiDB 数据库中 DROP VIEW 的使用概况。 +title: DROP VIEW | TiDB SQL 语句参考 +summary: TiDB 数据库中 DROP VIEW 的使用概述。 --- # DROP VIEW -`DROP VIEW` 语句用于从当前所选定的数据库中删除视图对象。视图所引用的基表不受影响。 +此语句从当前选择的数据库中删除视图对象。它不会影响视图引用的任何基表。 -## 语法图 +## 语法 ```ebnf+diagram DropViewStmt ::= @@ -22,44 +22,18 @@ TableName ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` - -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -CREATE VIEW v1 AS SELECT * FROM t1 WHERE c1 > 2; -``` -``` +mysql> CREATE VIEW v1 AS SELECT * FROM t1 WHERE c1 > 2; Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -70,15 +44,8 @@ SELECT * FROM t1; | 5 | 5 | +----+----+ 5 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM v1; -``` -``` +mysql> SELECT * FROM v1; +----+----+ | id | c1 | +----+----+ @@ -87,25 +54,11 @@ SELECT * FROM v1; | 5 | 5 | +----+----+ 3 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -DROP VIEW v1; -``` - -``` +mysql> DROP VIEW v1; Query OK, 0 rows affected (0.23 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -120,9 +73,9 @@ SELECT * FROM t1; ## MySQL 兼容性 -`DROP VIEW` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `DROP VIEW` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 -## See also +## 另请参阅 * [CREATE VIEW](/sql-statements/sql-statement-create-view.md) * [DROP TABLE](/sql-statements/sql-statement-drop-table.md) diff --git a/sql-statements/sql-statement-execute.md b/sql-statements/sql-statement-execute.md index e7efabf4a087..72c51fc75c54 100644 --- a/sql-statements/sql-statement-execute.md +++ b/sql-statements/sql-statement-execute.md @@ -1,6 +1,6 @@ --- -title: EXECUTE -summary: TiDB 数据库中 EXECUTE 的使用概况。 +title: EXECUTE | TiDB SQL 语句参考 +summary: TiDB 数据库中 EXECUTE 的使用概述。 --- # EXECUTE @@ -16,54 +16,28 @@ ExecuteStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -PREPARE mystmt FROM 'SELECT ? as num FROM DUAL'; -``` - -``` +mysql> PREPARE mystmt FROM 'SELECT ? as num FROM DUAL'; Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -SET @number = 5; -``` - -``` +mysql> SET @number = 5; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -EXECUTE mystmt USING @number; -``` - -``` +mysql> EXECUTE mystmt USING @number; +------+ | num | +------+ | 5 | +------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -DEALLOCATE PREPARE mystmt; -``` - -``` +mysql> DEALLOCATE PREPARE mystmt; Query OK, 0 rows affected (0.00 sec) ``` ## MySQL 兼容性 -`EXECUTE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `EXECUTE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-explain-analyze.md b/sql-statements/sql-statement-explain-analyze.md index 3d999425eeda..bb74ab9c62ba 100644 --- a/sql-statements/sql-statement-explain-analyze.md +++ b/sql-statements/sql-statement-explain-analyze.md @@ -1,17 +1,17 @@ --- -title: EXPLAIN ANALYZE -summary: TiDB 数据库中 EXPLAIN ANALYZE 的使用概况。 +title: EXPLAIN ANALYZE | TiDB SQL 语句参考 +summary: TiDB 数据库中 EXPLAIN ANALYZE 的使用概述。 --- # EXPLAIN ANALYZE -`EXPLAIN ANALYZE` 语句的工作方式类似于 `EXPLAIN`,主要区别在于前者实际上会执行语句。这样可以将查询计划中的估计值与执行时所遇到的实际值进行比较。如果估计值与实际值显著不同,那么应考虑在受影响的表上运行 `ANALYZE TABLE`。 +`EXPLAIN ANALYZE` 语句的工作方式类似于 `EXPLAIN`,主要区别在于它会实际执行该语句。这使你可以比较查询规划中使用的估计值与执行期间遇到的实际值。如果估计值与实际值有显著差异,你应该考虑对受影响的表运行 `ANALYZE TABLE`。 > **注意:** > -> 在使用 `EXPLAIN ANALYZE` 执行 DML 语句时,数据的修改操作会被正常执行。但目前 DML 语句还无法展示执行计划。 +> 当你使用 `EXPLAIN ANALYZE` 执行 DML 语句时,数据修改通常会被执行。目前,DML 语句的执行计划**尚不能**显示。 -## 语法图 +## 语法 ```ebnf+diagram ExplainSym ::= @@ -33,14 +33,14 @@ ExplainableStmt ::= ## EXPLAIN ANALYZE 输出格式 -和 `EXPLAIN` 不同,`EXPLAIN ANALYZE` 会执行对应的 SQL 语句,记录其运行时信息,和执行计划一并返回出来。因此,可以将 `EXPLAIN ANALYZE` 视为 `EXPLAIN` 语句的扩展。`EXPLAIN ANALYZE` 语句的返回结果相比 `EXPLAIN`,增加了 `actRows`,`execution info`,`memory`,`disk` 这几列信息: +与 `EXPLAIN` 不同,`EXPLAIN ANALYZE` 执行相应的 SQL 语句,记录其运行时信息,并将这些信息与执行计划一起返回。因此,你可以将 `EXPLAIN ANALYZE` 视为 `EXPLAIN` 语句的扩展。与 `EXPLAIN`(用于调试查询执行)相比,`EXPLAIN ANALYZE` 的返回结果还包括 `actRows`、`execution info`、`memory` 和 `disk` 等信息列。这些列的详细信息如下: -| 属性名 | 含义 | +| 属性名 | 描述 | |:----------------|:---------------------------------| -| actRows | 算子实际输出的数据条数。 | -| execution info | 算子的实际执行信息。time 表示从进入算子到离开算子的全部 wall time,包括所有子算子操作的全部执行时间。如果该算子被父算子多次调用 (loops),这个时间就是累积的时间。loops 是当前算子被父算子调用的次数。 | -| memory | 算子占用内存空间的大小。 | -| disk | 算子占用磁盘空间的大小。 | +| actRows | 算子输出的行数。 | +| execution info | 算子的执行信息。`time` 表示从进入算子到离开算子的总 `wall time`,包括所有子算子的总执行时间。如果该算子被父算子多次调用(在循环中),则时间指累积时间。`loops` 是当前算子被父算子调用的次数。 | +| memory | 算子占用的内存空间。 | +| disk | 算子占用的磁盘空间。 | ## 示例 @@ -50,7 +50,7 @@ ExplainableStmt ::= CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); ``` -``` +```sql Query OK, 0 rows affected (0.12 sec) ``` @@ -60,7 +60,7 @@ Query OK, 0 rows affected (0.12 sec) INSERT INTO t1 (c1) VALUES (1), (2), (3); ``` -``` +```sql Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 ``` @@ -71,7 +71,7 @@ Records: 3 Duplicates: 0 Warnings: 0 EXPLAIN ANALYZE SELECT * FROM t1 WHERE id = 1; ``` -``` +```sql +-------------+---------+---------+------+---------------+----------------------------------------------------------------+---------------+--------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------+---------+---------+------+---------------+----------------------------------------------------------------+---------------+--------+------+ @@ -86,7 +86,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE id = 1; EXPLAIN ANALYZE SELECT * FROM t1; ``` -``` +```sql +-------------------+----------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+-----------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------+----------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+-----------+------+ @@ -96,66 +96,66 @@ EXPLAIN ANALYZE SELECT * FROM t1; 2 rows in set (0.00 sec) ``` -## 算子执行信息介绍 +## 算子的执行信息 -`execution info` 信息除了基本的 `time` 和 `loop` 信息外,还包含算子特有的执行信息,主要包含了该算子发送 RPC 请求的耗时信息以及其他步骤的耗时。 +除了基本的 `time` 和 `loop` 执行信息外,`execution info` 还包含算子特定的执行信息,主要包括算子发送 RPC 请求所消耗的时间以及其他步骤的持续时间。 ### Point_Get -`Point_Get` 算子可能包含以下执行信息: +`Point_Get` 算子的执行信息通常包含以下信息: -- `Get:{num_rpc:1, total_time:697.051µs}`:向 TiKV 发送 `Get` 类型的 RPC 请求的数量 (`num_rpc`) 和所有 RPC 请求的总耗时 (`total_time`)。 -- `ResolveLock:{num_rpc:1, total_time:12.117495ms}`:读数据遇到锁后,进行 resolve lock 的时间。一般在读写冲突的场景下会出现。 -- `regionMiss_backoff:{num:11, total_time:2010 ms},tikvRPC_backoff:{num:11, total_time:10691 ms}`:RPC 请求失败后,会在等待 backoff 的时间后重试,包括了 backoff 的类型(如 regionMiss,tikvRPC),backoff 等待的总时间 (total_time) 和 backoff 的总次数 (num)。 +- `Get:{num_rpc:1, total_time:697.051µs}`:发送到 TiKV 的 `Get` RPC 请求数量(`num_rpc`)和所有 RPC 请求的总持续时间(`total_time`)。 +- `ResolveLock:{num_rpc:1, total_time:12.117495ms}`:如果 TiDB 在读取数据时遇到锁,它必须先解决锁,这通常发生在读写冲突的场景中。此信息表示解决锁的持续时间。 +- `regionMiss_backoff:{num:11, total_time:2010 ms},tikvRPC_backoff:{num:11, total_time:10691 ms}`:当 RPC 请求失败时,TiDB 会等待回退时间后重试请求。回退统计信息包括回退类型(如 `regionMiss` 和 `tikvRPC`)、总等待时间(`total_time`)和总回退次数(`num`)。 ### Batch_Point_Get -`Batch_Point_get` 算子的执行信息和 `Point_Get` 算子类似,不过 `Batch_Point_Get` 一般向 TiKV 发送 `BatchGet` 类型的 RPC 请求来读取数据。 +`Batch_Point_Get` 算子的执行信息与 `Point_Get` 算子类似,但 `Batch_Point_Get` 通常会发送 `BatchGet` RPC 请求到 TiKV 来读取数据。 -`BatchGet:{num_rpc:2, total_time:83.13µs}`:向 TiKV 发送 `BatchGet` 类型的 RPC 请求的数量 (`num_rpc`) 和所有 RPC 请求的总耗时 (`total_time`)。 +`BatchGet:{num_rpc:2, total_time:83.13µs}`:发送到 TiKV 的 `BatchGet` 类型 RPC 请求数量(`num_rpc`)和所有 RPC 请求消耗的总时间(`total_time`)。 ### TableReader -`TableReader` 算子可能包含以下执行信息: +`TableReader` 算子的执行信息通常如下: ``` cop_task: {num: 6, max: 1.07587ms, min: 844.312µs, avg: 919.601µs, p95: 1.07587ms, max_proc_keys: 16, p95_proc_keys: 16, tot_proc: 1ms, tot_wait: 1ms, copr_cache_hit_ratio: 0.00}, rpc_info:{Cop:{num_rpc:6, total_time:5.313996ms}} ``` -- `cop_task`:包含 cop task 的相关信息,如: - - `num`:cop task 的数量 - - `max`,`min`,`avg`,`p95`:所有 cop task 中执行时间的最大值,最小值,平均值和 P95 值。 - - `max_proc_keys`, `p95_proc_keys`:所有 cop task 中 tikv 扫描 kv 数据的最大值,P95 值,如果 max 和 p95 的值差距很大,说明数据分布不太均匀。 - - `copr_cache_hit_ratio`:cop task 请求的 Coprocessor Cache 缓存命中率。[Coprocessor Cache 配置](/tidb-configuration-file.md)。 -- `rpc_info`:按照向 TiKV 发送 RPC 请求的类型统计总数量和总时间。 -- `backoff`:包含不同类型的 backoff 以及等待总耗时。 +- `cop_task`:包含 `cop` 任务的执行信息。例如: + - `num`:cop 任务的数量。 + - `max`、`min`、`avg`、`p95`:执行 cop 任务消耗的执行时间的最大值、最小值、平均值和 P95 值。 + - `max_proc_keys` 和 `p95_proc_keys`:所有 cop 任务中 TiKV 扫描的最大和 P95 键值数。如果最大值和 P95 值之间的差异很大,数据分布可能不均衡。 + - `copr_cache_hit_ratio`:`cop` 任务请求的 Coprocessor Cache 命中率。 +- `rpc_info`:按请求类型聚合的发送到 TiKV 的 RPC 请求总数和总时间。 +- `backoff`:包含不同类型的回退和回退的总等待时间。 ### Insert -`Insert` 算子可能包含以下执行信息: +`Insert` 算子的执行信息通常如下: ``` -prepare:109.616µs, check_insert:{total_time:1.431678ms, mem_insert_time:667.878µs, prefetch:763.8µs, rpc:{BatchGet:{num_rpc:1, total_time:699.166µs},Get:{num_rpc:1, total_time:378.276µs}}} +prepare:109.616µs, check_insert:{total_time:1.431678ms, mem_insert_time:667.878µs, prefetch:763.8µs, rpc:{BatchGet:{num_rpc:1, total_time:699.166µs},Get:{num_rpc:1, total_time:378.276µs }}} ``` -- `prepare`:准备写入前的耗时,包括表达式,默认值相关的计算等。 -- `check_insert`:这个信息一般出现在 `insert ignore` 和 `insert on duplicate` 语句中,包含冲突检查和写入 TiDB 事务缓存的耗时。注意,这个耗时不包含事务提交的耗时。具体包含以下信息: - - `total_time`:`check_insert` 步骤的总耗时。 - - `mem_insert_time`:将数据写入 TiDB 事务缓存的耗时。 - - `prefetch`:从 TiKV 中获取需要检查冲突的数据的耗时,该步骤主要是向 TiKV 发送 `BatchGet` 类型的 RPC 请求的获取数据。 - - `rpc`:向 TiKV 发送 RPC 请求的总耗时,一般包含 `BatchGet` 和 `Get` 两种类型的 RPC 耗时,其中: - - `BatchGet` 请求是 `prefetch` 步骤发送的 RPC 请求。 - - `Get` 请求是 `insert on duplicate` 语句在执行 `duplicate update` 时发送的 RPC 请求。 -- `backoff`:包含不同类型的 backoff 以及等待总耗时。 +- `prepare`:准备写入的时间消耗,包括表达式、默认值和自增值的计算。 +- `check_insert`:此信息通常出现在 `insert ignore` 和 `insert on duplicate` 语句中,包括冲突检查和将数据写入 TiDB 事务缓存的时间消耗。注意,这个时间消耗不包括事务提交的时间消耗。它包含以下信息: + - `total_time`:`check_insert` 步骤花费的总时间。 + - `mem_insert_time`:将数据写入 TiDB 事务缓存的时间消耗。 + - `prefetch`:从 TiKV 获取需要检查冲突的数据的持续时间。此步骤向 TiKV 发送 `Batch_Get` RPC 请求以获取数据。 + - `rpc`:发送 RPC 请求到 TiKV 消耗的总时间,通常包括两种类型的 RPC 时间,`BatchGet` 和 `Get`,其中: + - `BatchGet` RPC 请求在 `prefetch` 步骤中发送。 + - `Get` RPC 请求在 `insert on duplicate` 语句执行 `duplicate update` 时发送。 +- `backoff`:包含不同类型的回退和回退的总等待时间。 ### IndexJoin -`IndexJoin` 算子有 1 个 outer worker 和 N 个 inner worker 并行执行,其 join 结果的顺序和 outer table 的顺序一致,具体执行流程如下: +`IndexJoin` 算子有 1 个外部工作线程和 N 个内部工作线程用于并发执行。连接结果保持外表的顺序。详细的执行过程如下: -1. Outer worker 读取 N 行 outer table 的数据,然后包装成一个 task 发送给 result channel 和 inner worker channel。 -2. Inner worker 从 inner worker channel 里面接收 task,然后根据 task 生成需要读取 inner table 的 key ranges 范围,然后读取相应范围的 inner table 行数据,并生成一个 inner table row 的 hash table。 -3. `IndexJoin` 的主线程从 result channel 中接收 task,然后等待 inner worker 执行完这个 task。 -4. `IndexJoin` 的主线程用 outer table rows 和 inner table rows 的 hash table 做 join。 +1. 外部工作线程读取 N 个外部行,然后将其包装成任务,并发送到结果通道和内部工作线程通道。 +2. 内部工作线程接收任务,从任务构建键范围,并根据键范围获取内部行。然后构建内部行哈希表。 +3. 主 `IndexJoin` 线程从结果通道接收任务,并等待内部工作线程完成处理任务。 +4. 主 `IndexJoin` 线程通过查找内部行哈希表来连接每个外部行。 `IndexJoin` 算子包含以下执行信息: @@ -163,25 +163,25 @@ prepare:109.616µs, check_insert:{total_time:1.431678ms, mem_insert_time:667.878 inner:{total:4.297515932s, concurrency:5, task:17, construct:97.96291ms, fetch:4.164310088s, build:35.219574ms}, probe:53.574945ms ``` -- `inner`:inner worker 的执行信息,具体如下: - - `total`:inner worker 的总耗时。 - - `concurrency`:inner worker 的数量。 - - `task`:inner worker 处理 task 的总数量。 - - `construct`:inner worker 读取 task 对应的 inner table rows 之前的准备时间。 - - `fetch`:inner worker 读取 inner table rows 的总耗时。 - - `build`: inner worker 构造 inner table rows 对应的 hash table 的总耗时。 -- `probe`:`IndexJoin` 主线程用 outer table rows 和 inner table rows 的 hash table 做 join 的总耗时。 +- `Inner`:内部工作线程的执行信息: + - `total`:内部工作线程消耗的总时间。 + - `concurrency`:并发内部工作线程的数量。 + - `task`:内部工作线程处理的任务总数。 + - `construct`:内部工作线程在读取任务对应的内部表行之前的准备时间。 + - `fetch`:内部工作线程读取内部表行消耗的总时间。 + - `Build`:内部工作线程构建对应内部表行哈希表消耗的总时间。 +- `probe`:主 `IndexJoin` 线程执行外表行与内部表行哈希表连接操作消耗的总时间。 ### IndexHashJoin -`IndexHashJoin` 算子和 `IndexJoin` 算子执行流程类似,也有 1 个 outer worker 和 N 个 inner worker 并行执行,但是其 join 结果的顺序是不和 outer table 一致。具体执行流程如下: +`IndexHashJoin` 算子的执行过程类似于 `IndexJoin` 算子。`IndexHashJoin` 算子也有 1 个外部工作线程和 N 个内部工作线程并行执行,但输出顺序不保证与外表一致。详细的执行过程如下: -1. Outer worker 读取 N 行 out table 的数据,然后包装成一个 task 发送给 inner worker channel。 -2. Inner worker 从 inner worker channel 里面接收 task,然后做以下三件事情,其中步骤 a 和 b 是并行执行。 - a. 用 outer table rows 生成一个 hash table。 - b. 根据 task 生成 key 的范围后,读取 inner table 相应范围的行数据。 - c. 用 inner table rows 和 outer table rows 的 hash table 做 join,然后把 join 结果发送给 result channel。 -3. `IndexHashJoin` 的主线程从 result channel 中接收 join 结果。 +1. 外部工作线程读取 N 个外部行,构建任务,并发送到内部工作线程通道。 +2. 内部工作线程从内部工作线程通道接收任务,并对每个任务按顺序执行以下三个操作: + a. 从外部行构建哈希表 + b. 从外部行构建键范围并获取内部行 + c. 探测哈希表并将连接结果发送到结果通道。注意:步骤 a 和步骤 b 并行运行。 +3. `IndexHashJoin` 的主线程从结果通道接收连接结果。 `IndexHashJoin` 算子包含以下执行信息: @@ -189,24 +189,24 @@ inner:{total:4.297515932s, concurrency:5, task:17, construct:97.96291ms, fetch:4 inner:{total:4.429220003s, concurrency:5, task:17, construct:96.207725ms, fetch:4.239324006s, build:24.567801ms, join:93.607362ms} ``` -- `inner`:inner worker 的执行信息,具体如下: - - `total`:inner worker 的总耗时。 - - `concurrency`:inner worker 的数量。 - - `task`:inner worker 处理 task 的总数量。 - - `construct`:inner worker 读取 task 对应的 inner table rows 之前的准备时间。 - - `fetch`:inner worker 读取 inner table rows 的总耗时。 - - `build`: inner worker 构造 outer table rows 对应的 hash table 的总耗时。 - - `join`: inner worker 用 inner table rows 和 outer table rows 的 hash table 做 join 的总耗时。 +- `Inner`:内部工作线程的执行信息: + - `total`:内部工作线程消耗的总时间。 + - `concurrency`:内部工作线程的数量。 + - `task`:内部工作线程处理的任务总数。 + - `construct`:内部工作线程在读取内部表行之前的准备时间。 + - `fetch`:内部工作线程读取内部表行消耗的总时间。 + - `Build`:内部工作线程构建外表行哈希表消耗的总时间。 + - `join`:内部工作线程执行内部表行与外表行哈希表连接操作消耗的总时间。 ### HashJoin -`HashJoin` 算子有一个 inner worker,一个 outer worker 和 N 个 join worker,其具体执行逻辑如下: +`HashJoin` 算子有一个内部工作线程、一个外部工作线程和 N 个连接工作线程。详细的执行过程如下: -1. inner worker 读取 inner table rows 并构造 hash table。 -2. outer worker 读取 outer table rows,然后包装成 task 发送给 join worker。 -3. 等待第 1 步的 hash table 构造完成。 -4. join worker 用 task 里面的 outer table rows 和 hash table 做 join,然后把 join 结果发送给 result channel。 -5. `HashJoin` 的主线程从 result channel 中接收 join 结果。 +1. 内部工作线程读取内部表行并构建哈希表。 +2. 外部工作线程读取外部表行,然后将其包装成任务并发送给连接工作线程。 +3. 连接工作线程等待步骤 1 中的哈希表构建完成。 +4. 连接工作线程使用任务中的外部表行和哈希表执行连接操作,然后将连接结果发送到结果通道。 +5. `HashJoin` 的主线程从结果通道接收连接结果。 `HashJoin` 算子包含以下执行信息: @@ -214,16 +214,16 @@ inner:{total:4.429220003s, concurrency:5, task:17, construct:96.207725ms, fetch: build_hash_table:{total:146.071334ms, fetch:110.338509ms, build:35.732825ms}, probe:{concurrency:5, total:857.162518ms, max:171.48271ms, probe:125.341665ms, fetch:731.820853ms} ``` -- `build_hash_table`: 读取 inner table 的数据并构造 hash table 的执行信息: - - `total`:总耗时。 - - `fetch`:读取 inner table 数据的总耗时。 - - `build`:构造 hash table 的总耗时。 -- `probe`: join worker 的执行信息: - - `concurrency`:join worker 的数量。 - - `total`:所有 join worker 执行的总耗时。 - - `max`:单个 join worker 执行的最大耗时。 - - `probe`: 用 outer table rows 和 hash table 做 join 的总耗时。 - - `fetch`:join worker 等待读取 outer table rows 数据的总耗时。 +- `build_hash_table`:读取内部表数据并构建哈希表的执行信息: + - `total`:总时间消耗。 + - `fetch`:读取内部表数据消耗的总时间。 + - `build`:构建哈希表消耗的总时间。 +- `probe`:连接工作线程的执行信息: + - `concurrency`:连接工作线程的数量。 + - `total`:所有连接工作线程消耗的总时间。 + - `max`:单个连接工作线程执行的最长时间。 + - `probe`:与外部表行和哈希表连接消耗的总时间。 + - `fetch`:连接工作线程等待读取外部表行数据消耗的总时间。 ### TableFullScan (TiFlash) @@ -243,47 +243,47 @@ tiflash_scan: { } ``` -+ `dtfile`:扫表过程中与 DTFile (即 DeltaTree File)相关的信息;这基本反映了 TiFlash 在 Stable 层数据的读取情况。 - - `total_scanned_packs`:DTFile 内累计读取的 Pack 的数量;Pack 是 TiFlash DTFile 读取的最小粒度,默认情况下每 8192 行构成一个 Pack。 - - `total_skipped_packs`:DTFile 内累计跳过的 Pack 的数量;Pack 会由于 `WHERE` 条件命中粗糙索引或主键范围过滤而被跳过。 - - `total_scanned_rows`:DTFile 内累计读取的行数;若存在 MVCC 带来的多版本更新或删除,则每个版本独立计数。 - - `total_skipped_rows`:DTFile 内累计跳过的行数。 - - `total_rs_index_load_time`:读取 DTFile 粗糙索引的累计耗时。 - - `total_read_time`:读取 DTFile 数据的累计耗时。 -+ `total_create_snapshot_time`:扫表过程中创建快照的总耗时。 ++ `dtfile`:表扫描期间的 DTFile(DeltaTree File)相关信息,反映了 TiFlash Stable 层的数据扫描状态。 + - `total_scanned_packs`:DTFile 中已扫描的 pack 总数。pack 是 TiFlash DTFile 中可以读取的最小单位。默认情况下,每 8192 行构成一个 pack。 + - `total_skipped_packs`:DTFile 中扫描时跳过的 pack 总数。当 `WHERE` 子句命中粗糙集索引或匹配主键的范围过滤时,会跳过不相关的 pack。 + - `total_scanned_rows`:DTFile 中已扫描的行总数。如果由于 MVCC 存在多个版本的更新或删除,每个版本都会被独立计数。 + - `total_skipped_rows`:DTFile 中扫描时跳过的行总数。 + - `total_rs_index_load_time`:读取 DTFile 粗糙集索引使用的总时间。 + - `total_read_time`:读取 DTFile 数据使用的总时间。 ++ `total_create_snapshot_time`:表扫描期间创建快照使用的总时间。 ### lock_keys 执行信息 -在悲观事务中执行 DML 语句时,算子的执行信息还可能包含 `lock_keys` 的执行信息,示例如下: +当在悲观事务中执行 DML 语句时,算子的执行信息可能还包括 `lock_keys` 的执行信息。例如: ``` lock_keys: {time:94.096168ms, region:6, keys:8, lock_rpc:274.503214ms, rpc_count:6} ``` -- `time`:执行 `lock_keys` 操作的总耗时。 +- `time`:执行 `lock_keys` 操作的总持续时间。 - `region`:执行 `lock_keys` 操作涉及的 Region 数量。 -- `keys`:需要 `Lock` 的 `Key` 的数量。 -- `lock_rpc`:向 TiKV 发送 `Lock` 类型的 RPC 总耗时。因为可以并行发送多个 RPC 请求,所以总 RPC 耗时可能比 `lock_keys` 操作总耗时大。 -- `rpc_count`:向 TiKV 发送 `Lock` 类型的 RPC 总数量。 +- `keys`:需要 `Lock` 的 `Key` 数量。 +- `lock_rpc`:向 TiKV 发送 `Lock` 类型 RPC 请求消耗的总时间。因为多个 RPC 请求可以并行发送,所以总 RPC 时间消耗可能大于 `lock_keys` 操作的总时间消耗。 +- `rpc_count`:向 TiKV 发送的 `Lock` 类型 RPC 请求总数。 ### commit_txn 执行信息 -在 `autocommit=1` 的事务中执行写入类型的 DML 语句时,算子的执行信息还会包括事务提交的耗时信息,示例如下: +当在 `autocommit=1` 的事务中执行写类型的 DML 语句时,写算子的执行信息还将包括事务提交的持续时间信息。例如: ``` commit_txn: {prewrite:48.564544ms, wait_prewrite_binlog:47.821579, get_commit_ts:4.277455ms, commit:50.431774ms, region_num:7, write_keys:16, write_byte:536} ``` -- `prewrite`:事务 2PC 提交阶段中 `prewrite` 阶段的耗时。 -- `wait_prewrite_binlog:`:等待写 prewrite Binlog 的耗时。 -- `get_commit_ts`:获取事务提交时间戳的耗时。 -- `commit`:事务 2PC 提交阶段中,`commit` 阶段的耗时。 -- `write_keys`:事务中写入 `key` 的数量。 -- `write_byte`:事务中写入 `key-value` 的总字节数量,单位是 byte。 +- `prewrite`:事务 2PC 提交的 `prewrite` 阶段消耗的时间。 +- `wait_prewrite_binlog`:等待写入 prewrite Binlog 消耗的时间。 +- `get_commit_ts`:获取事务提交时间戳消耗的时间。 +- `commit`:事务 2PC 提交的 `commit` 阶段消耗的时间。 +- `write_keys`:事务中写入的总 `keys`。 +- `write_byte`:事务中写入的 `key-value` 总字节数,单位为字节。 -### RU (Request Unit) 消耗 +### RU(请求单元)消耗 -[Request Unit (RU)](/tidb-resource-control.md#什么是-request-unit-ru) 是资源管控对系统资源统一抽象的计量单位。执行计划顶层算子的 `execution info` 会显示 SQL 整体的 RU 消耗。 +[请求单元(Request Unit,RU)](/tidb-resource-control.md#什么是请求单元-ru)是系统资源的统一抽象单位,在 TiDB 资源控制中定义。顶层算子的 `execution info` 显示了这个特定 SQL 语句的总体 RU 消耗。 ``` RU:273.842670 @@ -291,64 +291,64 @@ RU:273.842670 > **注意:** > -> 该值仅表示本次执行的实际 RU 消耗。由于受缓存的影响(比如[下推计算结果缓存](/coprocessor-cache.md)),同一个 SQL 在每次执行时消耗的 RU 可能会不同。 - -RU 计数可以通过 `EXPLAIN ANALYZE` 中的其他值计算得出,特别是 `execution info` 列。例如: - -``` - 'executeInfo': - time:2.55ms, - loops:2, - RU:0.329460, - Get:{ - num_rpc:1, - total_time:2.13ms - }, - total_process_time: 231.5µs, - total_wait_time: 732.9µs, - tikv_wall_time: 995.8µs, - scan_detail: { - total_process_keys: 1, - total_process_keys_size: 150, - total_keys: 1, - get_snapshot_time: 691.7µs, - rocksdb: { - block: { - cache_hit_count: 2, - read_count: 1, - read_byte: 8.19 KB, - read_time: 10.3µs - } - } - }, -``` - -关于基础成本信息,请参考 [`tikv/pd` 源码](https://github.com/tikv/pd/blob/aeb259335644d65a97285d7e62b38e7e43c6ddca/client/resource_group/controller/config.go#L58C19-L67)。相关计算是通过 [`model.go`](https://github.com/tikv/pd/blob/54219d649fb4c8834cd94362a63988f3c074d33e/client/resource_group/controller/model.go#L107) 完成的。 - -如果你使用的是 TiDB v7.1,计算方法是 `pd/pd-client/model.go` 中的 `BeforeKVRequest() + AfterKVRequest()`,即总和: - -``` -before key/value request is processed: +> 这个值显示了此次执行实际消耗的 RU。由于缓存的影响(例如[协处理器缓存](/coprocessor-cache.md)),同一条 SQL 语句每次执行可能会消耗不同数量的 RU。 + +你可以从 `EXPLAIN ANALYZE` 中的其他值计算 RU,特别是 `execution info` 列。例如: + +```json +'executeInfo': + time:2.55ms, + loops:2, + RU:0.329460, + Get:{ + num_rpc:1, + total_time:2.13ms + }, + total_process_time: 231.5µs, + total_wait_time: 732.9µs, + tikv_wall_time: 995.8µs, + scan_detail: { + total_process_keys: 1, + total_process_keys_size: 150, + total_keys: 1, + get_snapshot_time: 691.7µs, + rocksdb: { + block: { + cache_hit_count: 2, + read_count: 1, + read_byte: 8.19 KB, + read_time: 10.3µs + } + } + }, +``` + +基本成本在 [`tikv/pd` 源代码](https://github.com/tikv/pd/blob/aeb259335644d65a97285d7e62b38e7e43c6ddca/client/resource_group/controller/config.go#L58C19-L67)中定义,计算在 [`model.go`](https://github.com/tikv/pd/blob/54219d649fb4c8834cd94362a63988f3c074d33e/client/resource_group/controller/model.go#L107) 文件中执行。 + +如果你使用的是 TiDB v7.1,计算是 `pd/pd-client/model.go` 中 `BeforeKVRequest()` 和 `AfterKVRequest()` 的总和,即: + +``` +在处理键/值请求之前: consumption.RRU += float64(kc.ReadBaseCost) -> kv.ReadBaseCost * rpc_nums -after key/value request is processed: +在处理键/值请求之后: consumption.RRU += float64(kc.ReadBytesCost) * readBytes -> kc.ReadBytesCost * total_process_keys_size consumption.RRU += float64(kc.CPUMsCost) * kvCPUMs -> kc.CPUMsCost * total_process_time ``` -对于 writes 和 batch gets,计算方法相似,只是基础成本不同。 +对于写入和批量获取,计算方式类似,但基本成本不同。 -### 其它常见执行信息 +### 其他常见执行信息 -Coprocessor 算子通常包含 `cop_task` 和 `tikv_task` 两部分执行时间信息。前者是 TiDB 端记录的时间,从发出请求到接收回复;后者是 TiKV Coprocessor 算子自己记录的时间。两者相差较大可能说明在等待、gRPC 或网络上耗时较长。 +Coprocessor 算子通常包含两部分执行时间信息:`cop_task` 和 `tikv_task`。`cop_task` 是 TiDB 记录的时间,从发送请求到服务器到接收响应的时刻。`tikv_task` 是 TiKV Coprocessor 自身记录的时间。如果两者之间存在较大差异,可能表明等待响应的时间太长,或者 gRPC 或网络消耗的时间太长。 ## MySQL 兼容性 -`EXPLAIN ANALYZE` 是 MySQL 8.0 的功能,但该语句在 MySQL 中的输出格式和可能的执行计划都与 TiDB 有较大差异。 +`EXPLAIN ANALYZE` 是 MySQL 8.0 的特性,但 TiDB 中的输出格式和潜在的执行计划与 MySQL 有很大不同。 ## 另请参阅 -* [Understanding the Query Execution Plan](/explain-overview.md) +* [理解查询执行计划](/explain-overview.md) * [EXPLAIN](/sql-statements/sql-statement-explain.md) * [ANALYZE TABLE](/sql-statements/sql-statement-analyze-table.md) * [TRACE](/sql-statements/sql-statement-trace.md) diff --git a/sql-statements/sql-statement-explain.md b/sql-statements/sql-statement-explain.md index 8a3eb50322dc..e679f263d594 100644 --- a/sql-statements/sql-statement-explain.md +++ b/sql-statements/sql-statement-explain.md @@ -1,21 +1,21 @@ --- -title: EXPLAIN -summary: TiDB 数据库中 EXPLAIN 的使用概况。 +title: EXPLAIN | TiDB SQL 语句参考 +summary: TiDB 数据库中 EXPLAIN 的使用概览。 --- -# EXPLAIN +# `EXPLAIN` -`EXPLAIN` 语句仅用于显示查询的执行计划,而不执行查询。该语句为 `EXPLAIN ANALYZE` 语句的补充,后者会执行查询。如果 `EXPLAIN` 的输出与预期结果不匹配,可考虑在查询的每个表上执行 `ANALYZE TABLE`,以确保表统计信息是最新的。 +`EXPLAIN` 语句显示查询的执行计划,但不执行查询。它是 `EXPLAIN ANALYZE` 语句的补充,后者会执行查询。如果 `EXPLAIN` 的输出与预期结果不符,请考虑对查询中的每个表执行 `ANALYZE TABLE` 以确保表统计信息是最新的。 > **注意:** > -> 某些子查询会在优化阶段被提前执行以生成可能更优的执行计划,即使是在 `EXPLAIN` 语句中。更详细的说明以及禁用此行为的方法请参见 [`tidb_opt_enable_non_eval_scalar_subquery`](/system-variables.md#tidb_opt_enable_non_eval_scalar_subquery-从-v730-版本开始引入) 和[禁止子查询提前展开](/explain-walkthrough.md#禁止子查询提前执行)。 +> 某些子查询在优化阶段会被预执行以生成最优执行计划,即使在 `EXPLAIN` 语句中也是如此。有关此行为的更多信息以及如何禁用它,请参见 [`tidb_opt_enable_non_eval_scalar_subquery`](/system-variables.md#tidb_opt_enable_non_eval_scalar_subquery-new-in-v730) 和[禁用子查询的提前执行](/explain-walkthrough.md#disable-the-early-execution-of-subqueries)。 -语句 `DESC` 和 `DESCRIBE` 是 `EXPLAIN` 的别名。`EXPLAIN ` 的替代用法记录在 [`SHOW [FULL] COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) 下。 +`DESC` 和 `DESCRIBE` 语句是 `EXPLAIN` 语句的别名。`EXPLAIN ` 的替代用法在 [`SHOW [FULL] COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) 中有文档说明。 -TiDB 支持 `EXPLAIN [options] FOR CONNECTION connection_id`,但与 MySQL 的 `EXPLAIN FOR` 有一些区别,请参见 [`EXPLAIN FOR CONNECTION`](#explain-for-connection)。 +TiDB 支持 `EXPLAIN [options] FOR CONNECTION connection_id` 语句。但是,此语句与 MySQL 中的 `EXPLAIN FOR` 语句不同。更多详情,请参见 [`EXPLAIN FOR CONNECTION`](#explain-for-connection)。 -## 语法图 +## 语法 ```ebnf+diagram ExplainSym ::= @@ -35,25 +35,25 @@ ExplainableStmt ::= | UnionStmt ``` -## EXPLAIN 输出格式 +## `EXPLAIN` 输出格式 > **注意:** > -> 使用 MySQL 客户端连接到 TiDB 时,为避免输出结果在终端中换行,可先执行 `pager less -S` 命令。执行命令后,新的 `EXPLAIN` 的输出结果不再换行,可按右箭头 键水平滚动阅读输出结果。 +> 当你使用 MySQL 客户端连接 TiDB 时,为了以更清晰的方式阅读输出结果而不换行,你可以使用 `pager less -S` 命令。然后,在输出 `EXPLAIN` 结果后,你可以按键盘上的右箭头键 来水平滚动输出。 > **注意:** > -> 在执行计划返回结果中,自 v6.4.0 版本起,特定算子(即 `IndexJoin` 和 `Apply` 算子的 Probe 端所有子节点)的 `estRows` 字段意义与 v6.4.0 之前的有所不同。细节请参考 [TiDB 执行计划概览](/explain-overview.md#解读-explain-的返回结果)。 +> 在返回的执行计划中,对于 `IndexJoin` 和 `Apply` 算子的所有探测端子节点,从 v6.4.0 开始,`estRows` 的含义与 v6.4.0 之前不同。你可以在 [TiDB 执行计划概览](/explain-overview.md#understand-explain-output)中找到详细信息。 -目前 TiDB 的 `EXPLAIN` 会输出 5 列,分别是:`id`,`estRows`,`task`,`access object`,`operator info`。执行计划中每个算子都由这 5 列属性来描述,`EXPLAIN` 结果中每一行描述一个算子。每个属性的具体含义如下: +目前,TiDB 中的 `EXPLAIN` 输出包含 5 列:`id`、`estRows`、`task`、`access object`、`operator info`。执行计划中的每个算子都由这些属性描述,`EXPLAIN` 输出中的每一行描述一个算子。每个属性的描述如下: -| 属性名 | 含义 | +| 属性名 | 描述 | |:----------------|:----------------------------------------------------------------------------------------------------------| -| id | 算子的 ID,是算子在整个执行计划中唯一的标识。在 TiDB 2.1 中,ID 会格式化地显示算子的树状结构。数据从孩子结点流向父亲结点,每个算子的父亲结点有且仅有一个。| -| estRows | 算子预计将会输出的数据条数,基于统计信息以及算子的执行逻辑估算而来。在 4.0 之前叫 count。 | -| task | 算子属于的 task 种类。目前的执行计划分成为两种 task,一种叫 **root** task,在 tidb-server 上执行,一种叫 **cop** task,在 TiKV 或者 TiFlash 上并行执行。当前的执行计划在 task 级别的拓扑关系是一个 root task 后面可以跟许多 cop task,root task 使用 cop task 的输出结果作为输入。cop task 中执行的也即是 TiDB 下推到 TiKV 或者 TiFlash 上的任务,每个 cop task 分散在 TiKV 或者 TiFlash 集群中,由多个进程共同执行。 | -| access object | 算子所访问的数据项信息。包括表 `table`,表分区 `partition` 以及使用的索引 `index`(如果有)。只有直接访问数据的算子才拥有这些信息。 | -| operator info | 算子的其它信息。各个算子的 operator info 各有不同,可参考下面的示例解读。 | +| id | 算子的 ID 是整个执行计划中算子的唯一标识符。在 TiDB 2.1 中,ID 的格式经过调整以显示算子的树状结构。数据从子节点流向父节点。每个算子有且仅有一个父节点。 | +| estRows | 算子预计输出的行数。这个数字根据统计信息和算子的逻辑进行估算。在 TiDB 4.0 的早期版本中,`estRows` 被称为 `count`。 | +| task | 算子属于的任务类型。目前,执行计划被分为两种任务:**root** 任务在 tidb-server 上执行,**cop** 任务在 TiKV 或 TiFlash 上并行执行。执行计划在任务级别的拓扑结构是一个 root 任务后跟多个 cop 任务。root 任务使用 cop 任务的输出作为输入。cop 任务指的是 TiDB 下推到 TiKV 或 TiFlash 的任务。每个 cop 任务分布在 TiKV 集群或 TiFlash 集群中,由多个进程执行。 | +| access object | 算子访问的数据项信息。信息包括 `table`、`partition` 和 `index`(如果有)。只有直接访问数据的算子才有这些信息。 | +| operator info | 算子的其他信息。每个算子的 `operator info` 都不同。你可以参考以下示例。 | ## 示例 @@ -63,7 +63,7 @@ ExplainableStmt ::= EXPLAIN SELECT 1; ``` -``` +```sql +-------------------+---------+------+---------------+---------------+ | id | estRows | task | access object | operator info | +-------------------+---------+------+---------------+---------------+ @@ -79,7 +79,7 @@ EXPLAIN SELECT 1; CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); ``` -``` +```sql Query OK, 0 rows affected (0.10 sec) ``` @@ -89,7 +89,7 @@ Query OK, 0 rows affected (0.10 sec) INSERT INTO t1 (c1) VALUES (1), (2), (3); ``` -``` +```sql Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 ``` @@ -100,7 +100,7 @@ Records: 3 Duplicates: 0 Warnings: 0 EXPLAIN SELECT * FROM t1 WHERE id = 1; ``` -``` +```sql +-------------+---------+------+---------------+---------------+ | id | estRows | task | access object | operator info | +-------------+---------+------+---------------+---------------+ @@ -115,7 +115,7 @@ EXPLAIN SELECT * FROM t1 WHERE id = 1; DESC SELECT * FROM t1 WHERE id = 1; ``` -``` +```sql +-------------+---------+------+---------------+---------------+ | id | estRows | task | access object | operator info | +-------------+---------+------+---------------+---------------+ @@ -130,7 +130,7 @@ DESC SELECT * FROM t1 WHERE id = 1; DESCRIBE SELECT * FROM t1 WHERE id = 1; ``` -``` +```sql +-------------+---------+------+---------------+---------------+ | id | estRows | task | access object | operator info | +-------------+---------+------+---------------+---------------+ @@ -145,7 +145,7 @@ DESCRIBE SELECT * FROM t1 WHERE id = 1; EXPLAIN INSERT INTO t1 (c1) VALUES (4); ``` -``` +```sql +----------+---------+------+---------------+---------------+ | id | estRows | task | access object | operator info | +----------+---------+------+---------------+---------------+ @@ -160,7 +160,7 @@ EXPLAIN INSERT INTO t1 (c1) VALUES (4); EXPLAIN UPDATE t1 SET c1=5 WHERE c1=3; ``` -``` +```sql +---------------------------+---------+-----------+---------------+--------------------------------+ | id | estRows | task | access object | operator info | +---------------------------+---------+-----------+---------------+--------------------------------+ @@ -178,7 +178,7 @@ EXPLAIN UPDATE t1 SET c1=5 WHERE c1=3; EXPLAIN DELETE FROM t1 WHERE c1=3; ``` -``` +```sql +---------------------------+---------+-----------+---------------+--------------------------------+ | id | estRows | task | access object | operator info | +---------------------------+---------+-----------+---------------+--------------------------------+ @@ -190,31 +190,31 @@ EXPLAIN DELETE FROM t1 WHERE c1=3; 4 rows in set (0.01 sec) ``` -在 `EXPLAIN` 语句中,你可以使用 `FORMAT = "xxx"` 语法指定输出内容的格式。目前支持的输出格式如下: +要指定 `EXPLAIN` 输出的格式,你可以使用 `FORMAT = xxx` 语法。目前,TiDB 支持以下格式: -| FORMAT | 作用 | -|-------------|-------------------------------------------------------------------| -| 未指定 | 未指定 `FORMAT` 时,默认输出格式为 `row` | -| `brief` | `EXPLAIN` 语句输出结果中的算子 ID 将被简化,较之未指定 `FORMAT` 时输出结果的算子 ID 更为简化 | -| `dot` | `EXPLAIN` 语句将输出 DOT 格式的执行计划,可以通过 `dot` 程序(在 `graphviz` 包中)生成 PNG 文件 | -| `row` | `EXPLAIN` 语句将以表格格式输出结果。更多信息,可参阅 [TiDB 执行计划概览](/explain-overview.md) | -| `tidb_json` | `EXPLAIN` 语句将输出 JSON 格式的执行计划,算子信息存放在一个 JSON 数组中 | -| `verbose` | `EXPLAIN` 语句将以 `row` 格式输出结果,并在结果中额外包含一个 `estCost` 列,表示查询的代价估算。关于如何使用这种格式的更多信息,请参阅[执行计划管理 (SPM)](/sql-plan-management.md)。| -| `plan_cache` | `EXPLAIN` 语句将以 `row` 格式输出结果,[执行计划缓存](/sql-non-prepared-plan-cache.md#诊断)信息将作为 warning 显示。 +| FORMAT | 描述 | +| ------ | ------ | +| 未指定 | 如果未指定格式,`EXPLAIN` 使用默认格式 `row`。 | +| `brief` | 与未指定 `FORMAT` 时相比,`EXPLAIN` 语句输出中的算子 ID 被简化。 | +| `dot` | `EXPLAIN` 语句输出 DOT 执行计划,可以通过 `dot` 程序(在 `graphviz` 包中)生成 PNG 文件。 | +| `row` | `EXPLAIN` 语句以表格格式输出结果。更多信息,请参见[理解查询执行计划](/explain-overview.md)。 | +| `tidb_json` | `EXPLAIN` 语句以 JSON 格式输出执行计划,并将算子信息存储在 JSON 数组中。 | +| `verbose` | `EXPLAIN` 语句以 `row` 格式输出结果,结果中额外包含一个 `estCost` 列,显示查询的估计成本。有关如何使用此格式的更多信息,请参见 [SQL 执行计划管理](/sql-plan-management.md)。 | +| `plan_cache` | `EXPLAIN` 语句以 `row` 格式输出结果,并以警告形式显示[执行计划缓存](/sql-non-prepared-plan-cache.md#diagnostics)信息。 |
-在 `EXPLAIN` 中指定 `FORMAT = "brief"` 时,示例如下: +以下是 `EXPLAIN` 中 `FORMAT` 为 `"brief"` 时的示例: {{< copyable "sql" >}} ```sql -EXPLAIN FORMAT = "brief" DELETE FROM t1 WHERE c1=3; +EXPLAIN FORMAT = "brief" DELETE FROM t1 WHERE c1 = 3; ``` -``` +```sql +-------------------------+---------+-----------+---------------+--------------------------------+ | id | estRows | task | access object | operator info | +-------------------------+---------+-----------+---------------+--------------------------------+ @@ -227,18 +227,19 @@ EXPLAIN FORMAT = "brief" DELETE FROM t1 WHERE c1=3; ```
+
-除 MySQL 标准结果格式外,TiDB 还支持 DotGraph,需要在 `EXPLAIN` 中指定 `FORMAT = "dot"`,示例如下: +除了 MySQL 标准结果格式外,TiDB 还支持 DotGraph,你需要指定 `FORMAT = "dot"`,如以下示例所示: {{< copyable "sql" >}} ```sql -create table t(a bigint, b bigint); -explain format = "dot" select A.a, B.b from t A join t B on A.a > B.b where A.a < 10; +CREATE TABLE t(a bigint, b bigint); +EXPLAIN format = "dot" SELECT A.a, B.b FROM t A JOIN t B ON A.a > B.b WHERE A.a < 10; ``` -``` +```sql +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | dot contents | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -273,17 +274,15 @@ label = "cop" 1 row in set (0.00 sec) ``` -如果你的计算机上安装了 `dot` 程序,可使用以下方法生成 PNG 文件: - -{{< copyable "shell-regular" >}} +如果你的计算机上有 `dot` 程序,可以使用以下方法生成 PNG 文件: ```bash dot xx.dot -T png -O -``` -The `xx.dot` is the result returned by the above statement. +xx.dot 是上述语句返回的结果。 +``` -如果你的计算机上未安装 `dot` 程序,可将结果复制到[本网站](http://www.webgraphviz.com/)以获取树形图: +如果你的计算机上没有 `dot` 程序,可以将结果复制到[此网站](http://www.webgraphviz.com/)以获取树形图: ![Explain Dot](/media/explain_dot.png) @@ -291,7 +290,7 @@ The `xx.dot` is the result returned by the above statement.
-在 `EXPLAIN` 中指定 `FORMAT = "tidb_json"` 时,示例如下: +要获取 JSON 格式的输出,在 `EXPLAIN` 语句中指定 `FORMAT = "tidb_json"`。以下是一个示例: ```sql CREATE TABLE t(id int primary key, a int, b int, key(a)); @@ -332,7 +331,7 @@ EXPLAIN FORMAT = "tidb_json" SELECT id FROM t WHERE a = 1; 1 row in set (0.01 sec) ``` -在输出结果中,`id`、`estRows`、`taskType`、`accessObject`、`operatorInfo` 与默认格式输出的列含义相同。`subOperators` 是存放子节点的数组,子节点的字段及含义与父节点均相同。若某字段缺失,则说明该字段为空。 +在输出中,`id`、`estRows`、`taskType`、`accessObject` 和 `operatorInfo` 与默认格式中的列具有相同的含义。`subOperators` 是一个存储子节点的数组。子节点的字段和含义与父节点相同。如果某个字段缺失,表示该字段为空。
@@ -340,21 +339,21 @@ EXPLAIN FORMAT = "tidb_json" SELECT id FROM t WHERE a = 1; ## MySQL 兼容性 -* `EXPLAIN` 的格式和 TiDB 中潜在的执行计划都与 MySQL 有很大不同。 +* TiDB 中的 `EXPLAIN` 格式和潜在的执行计划与 MySQL 有很大的不同。 * TiDB 不支持 `FORMAT=JSON` 或 `FORMAT=TREE` 选项。 -* TiDB 支持的 `FORMAT=tidb_json` 是对当前默认 `EXPLAIN` 格式的 JSON 编码,与 MySQL 的 `FORMAT=JSON` 结果的格式、字段信息都不同。 +* TiDB 中的 `FORMAT=tidb_json` 是默认 `EXPLAIN` 结果的 JSON 格式输出。其格式和字段与 MySQL 中的 `FORMAT=JSON` 输出不同。 -## `EXPLAIN FOR CONNECTION` +### `EXPLAIN FOR CONNECTION` -`EXPLAIN FOR CONNECTION` 用于获得一个连接中当前正在执行 SQL 的执行计划或者是最后执行 SQL 的执行计划,其输出格式与 `EXPLAIN` 完全一致。但 TiDB 中的实现与 MySQL 不同,除了输出格式之外,还有以下区别: +`EXPLAIN FOR CONNECTION` 用于获取当前正在执行的 SQL 查询或连接中最后执行的 SQL 查询的执行计划。输出格式与 `EXPLAIN` 相同。但是,TiDB 中 `EXPLAIN FOR CONNECTION` 的实现与 MySQL 中的不同。它们的差异(除了输出格式外)如下: -- 如果连接处于睡眠状态,MySQL 返回为空,而 TiDB 返回的是最后执行的查询计划。 -- 如果获取当前会话连接的执行计划,MySQL 会报错,而 TiDB 会正常返回。 -- MySQL 的文档中指出,MySQL 要求登录用户与被查询的连接相同,或者拥有 `PROCESS` 权限,而 TiDB 则要求登录用户与被查询的连接相同,或者拥有 `SUPER` 权限。 +- 如果连接处于睡眠状态,MySQL 返回空结果,而 TiDB 返回最后执行的查询计划。 +- 如果你尝试获取当前会话的执行计划,MySQL 返回错误,而 TiDB 正常返回结果。 +- MySQL 要求登录用户与被查询的连接相同,或登录用户具有 **`PROCESS`** 权限;而 TiDB 要求登录用户与被查询的连接相同,或登录用户具有 **`SUPER`** 权限。 ## 另请参阅 -* [理解 TiDB 执行计划](/explain-overview.md) +* [理解查询执行计划](/explain-overview.md) * [EXPLAIN ANALYZE](/sql-statements/sql-statement-explain-analyze.md) * [ANALYZE TABLE](/sql-statements/sql-statement-analyze-table.md) * [TRACE](/sql-statements/sql-statement-trace.md) diff --git a/sql-statements/sql-statement-flashback-cluster.md b/sql-statements/sql-statement-flashback-cluster.md index 10c588037cd9..f094849022f4 100644 --- a/sql-statements/sql-statement-flashback-cluster.md +++ b/sql-statements/sql-statement-flashback-cluster.md @@ -1,28 +1,36 @@ --- title: FLASHBACK CLUSTER -summary: TiDB 数据库中 FLASHBACK CLUSTER 的使用概况。 +summary: 了解在 TiDB 数据库中 FLASHBACK CLUSTER 的用法。 --- # FLASHBACK CLUSTER -TiDB v6.4.0 引入了 `FLASHBACK CLUSTER TO TIMESTAMP` 语法,其功能是将集群的数据恢复到过去指定的时间点。指定时间点时,你可以使用日期时间和时间函数,日期时间的格式为:'2016-10-08 16:45:26.999',最小时间精度范围为毫秒,通常可只写到秒,例如 '2016-10-08 16:45:26'。 +TiDB v6.4.0 引入了 `FLASHBACK CLUSTER TO TIMESTAMP` 语法。你可以使用它将集群恢复到特定时间点。在指定时间戳时,你可以设置一个日期时间值或使用时间函数。日期时间的格式类似于 '2016-10-08 16:45:26.999',最小时间单位为毫秒。但在大多数情况下,以秒为时间单位指定时间戳就足够了,例如 '2016-10-08 16:45:26'。 -TiDB v6.5.6、v7.1.3、v7.5.1、v7.6.0 开始引入了 `FLASHBACK CLUSTER TO TSO` 的语法,支持使用时间戳 [TSO](/tso.md) 更加精确地指定恢复时间点,实现更加灵活的数据恢复。 +从 v6.5.6、v7.1.3、v7.5.1 和 v7.6.0 开始,TiDB 引入了 `FLASHBACK CLUSTER TO TSO` 语法。此语法允许你使用 [TSO](/tso.md) 来指定更精确的恢复时间点,从而提高数据恢复的灵活性。 > **警告:** > -> - 在指定恢复时间点时,请务必检查 TIMESTAMP 或 TSO 的有效性,避免指定可能超过 PD 当前分配的最大 TSO(参考 Grafana PD 面板上 `Current TSO`)的未来时间。否则,可能破坏并发处理线性一致性以及事务隔离级别,导致严重的数据正确性的问题。 -> - 在 `FLASHBACK CLUSTER` 执行期间,数据清理过程不能保证事务的一致性。在 `FLASHBACK CLUSTER` 执行完成后,如需使用 TiDB 的任何历史版本读取功能(如 [Stale Read](/stale-read.md) 或 [`tidb_snapshot`](/read-historical-data.md)),请确保所选择的历史时间点不在 FLASHBACK 运行的时间范围内。如果读取的历史版本包含未 FLASHBACK 完成的数据,可能会破坏并发处理的线性一致性以及事务隔离级别,导致严重的数据正确性问题。 +> `FLASHBACK CLUSTER TO [TIMESTAMP|TSO]` 语法不适用于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群。为避免意外结果,请勿在 TiDB Cloud Serverless 集群上执行此语句。 > **警告:** > -> 在 TiDB v7.1.0 中使用该功能可能会出现 FLASHBACK 完成后部分 Region 仍处于 FLASHBACK 过程中的问题。请尽量避免在 v7.1.0 中使用该功能。详情可见 [#44292](https://github.com/pingcap/tidb/issues/44292)。 +> - 在指定恢复时间点时,请确保检查目标时间戳或 TSO 的有效性,避免指定超过 PD 当前分配的最大 TSO 的未来时间(参见 Grafana PD 面板上的 `Current TSO`)。否则,可能会违反并发处理线性一致性和事务隔离级别,导致严重的数据正确性问题。 +> - 在执行 `FLASHBACK CLUSTER` 期间,数据清理过程不保证事务一致性。在 `FLASHBACK CLUSTER` 完成后,如果你打算使用 TiDB 中的任何历史版本读取功能(如 [Stale Read](/stale-read.md) 或 [`tidb_snapshot`](/read-historical-data.md)),请确保指定的历史时间戳不在 `FLASHBACK CLUSTER` 执行期间。读取包含 FLASHBACK 未完全恢复数据的历史版本可能会违反并发处理线性一致性和事务隔离级别,导致严重的数据正确性问题。 + + + +> **警告:** > -> 如果已经出现该问题,可以使用 [TiDB 快照备份与恢复](/br/br-snapshot-guide.md)功能进行数据恢复。 +> 当你在 TiDB v7.1.0 中使用此功能时,即使在 FLASHBACK 操作完成后,某些 Region 可能仍处于 FLASHBACK 过程中。建议避免在 v7.1.0 中使用此功能。更多信息,请参见 issue [#44292](https://github.com/pingcap/tidb/issues/44292)。 +> +> 如果你遇到此问题,可以使用 [TiDB 快照备份和恢复](/br/br-snapshot-guide.md)功能来恢复数据。 + + > **注意:** > -> `FLASHBACK CLUSTER TO [TIMESTAMP|TSO]` 是用最新的时间戳写入特定时间点的旧数据,但不会删除当前数据,所以在使用前请确保集群有足够的存储空间来同时容纳旧数据和当前数据。 +> `FLASHBACK CLUSTER TO [TIMESTAMP|TSO]` 的工作原理是用最新的时间戳写入特定时间点的旧数据,不会删除当前数据。因此在使用此功能之前,你需要确保有足够的存储空间来存放旧数据和当前数据。 ## 语法 @@ -40,23 +48,38 @@ FlashbackToTimestampStmt ## 注意事项 -* `FLASHBACK` 指定的时间点需要在 Garbage Collection (GC) life time 时间内。你可以使用系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入) 配置数据的历史版本的保留时间(默认值是 `10m0s`)。可以使用以下 SQL 语句查询当前的 `safePoint`,即 GC 已经清理到的时间点: +* `FLASHBACK` 语句中指定的时间必须在垃圾回收(GC)生命周期内。系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-new-in-v50)(默认值:`10m0s`)定义了行的早期版本的保留时间。可以通过以下查询获取垃圾回收已执行到的当前 `safePoint`: ```sql SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'; ``` -* 执行 `FLASHBACK CLUSTER` SQL 语句的用户需要有 `SUPER` 权限。 -* `FLASHBACK CLUSTER` 不支持回退修改 PD 相关信息的 DDL,如 `ALTER TABLE ATTRIBUTE`、`ALTER TABLE REPLICA`、`CREATE PLACEMENT POLICY` 等。 -* `FLASHBACK CLUSTER` 指定的时间点不能存在未执行完成的 DDL 记录。若存在,TiDB 会拒绝该 DDL 操作。 -* 在执行 `FLASHBACK CLUSTER` 前,TiDB 会主动断开所有相关表上的连接,并禁止对这些表进行读写操作,直到 `FLASHBACK CLUSTER` 完成。 -* `FLASHBACK CLUSTER` 命令不能取消,一旦开始执行 TiDB 会一直重试,直到成功。 -* 在 `FLASHBACK CLUSTER` 执行期间,若有数据备份需求,只支持使用 [BR 命令行工具进行快照备份](/br/br-snapshot-guide.md),并需要指定早于 `FLASHBACK CLUSTER` 开始时间的 `BackupTS`。同时,在执行 `FLASHBACK CLUSTER` 期间,[开启日志备份](/br/br-pitr-guide.md)的操作会失败,请等待 `FLASHBACK CLUSTER` 结束后再尝试开启日志备份。 -* 若 `FLASHBACK CLUSTER` 导致了元信息(表结构、库结构)的回滚,则相关的修改**不会**被 TiCDC 同步。因此,用户需主动暂停任务,待 `FLASHBACK CLUSTER` 完成后将上下游的 schema 定义手动同步一致,然后重新创建 TiCDC changefeed。 + + +* 只有具有 `SUPER` 权限的用户才能执行 `FLASHBACK CLUSTER` SQL 语句。 +* `FLASHBACK CLUSTER` 不支持回滚修改 PD 相关信息的 DDL 语句,如 `ALTER TABLE ATTRIBUTE`、`ALTER TABLE REPLICA` 和 `CREATE PLACEMENT POLICY`。 +* 在 `FLASHBACK` 语句指定的时间点,不能存在未完全执行的 DDL 语句。如果存在这样的 DDL,TiDB 将拒绝执行。 +* 在执行 `FLASHBACK CLUSTER` 之前,TiDB 会断开所有相关连接,并禁止对这些表进行读写操作,直到 `FLASHBACK CLUSTER` 语句完成。 +* `FLASHBACK CLUSTER` 语句执行后不能取消。TiDB 将持续重试直到成功。 +* 在执行 `FLASHBACK CLUSTER` 期间,如果需要备份数据,只能使用[备份与恢复](/br/br-snapshot-guide.md)并指定早于 `FLASHBACK CLUSTER` 开始时间的 `BackupTS`。此外,在执行 `FLASHBACK CLUSTER` 期间,启用[日志备份](/br/br-pitr-guide.md)将失败。因此,请在 `FLASHBACK CLUSTER` 完成后尝试启用日志备份。 +* 如果 `FLASHBACK CLUSTER` 语句导致元数据(表结构、数据库结构)回滚,相关修改将**不会**被 TiCDC 复制。因此,你需要手动暂停任务,等待 `FLASHBACK CLUSTER` 完成,并手动复制上下游的架构定义以确保它们一致。之后,你需要重新创建 TiCDC changefeed。 + + + + + +* 只有具有 `SUPER` 权限的用户才能执行 `FLASHBACK CLUSTER` SQL 语句。 +* `FLASHBACK CLUSTER` 不支持回滚修改 PD 相关信息的 DDL 语句,如 `ALTER TABLE ATTRIBUTE`、`ALTER TABLE REPLICA` 和 `CREATE PLACEMENT POLICY`。 +* 在 `FLASHBACK` 语句指定的时间点,不能存在未完全执行的 DDL 语句。如果存在这样的 DDL,TiDB 将拒绝执行。 +* 在执行 `FLASHBACK CLUSTER` 之前,TiDB 会断开所有相关连接,并禁止对这些表进行读写操作,直到 `FLASHBACK CLUSTER` 语句完成。 +* `FLASHBACK CLUSTER` 语句执行后不能取消。TiDB 将持续重试直到成功。 +* 如果 `FLASHBACK CLUSTER` 语句导致元数据(表结构、数据库结构)回滚,相关修改将**不会**被 TiCDC 复制。因此,你需要手动暂停任务,等待 `FLASHBACK CLUSTER` 完成,并手动复制上下游的架构定义以确保它们一致。之后,你需要重新创建 TiCDC changefeed。 + + ## 示例 -闪回到指定的 TIMESTAMP 来恢复新写入的数据: +以下示例展示如何将集群闪回到特定时间戳以恢复新插入的数据: ```sql mysql> CREATE TABLE t(a INT); @@ -91,7 +114,7 @@ mysql> SELECT * FROM t; Empty set (0.00 sec) ``` -闪回到指定的 TSO 来精确恢复误删除的数据: +以下示例展示如何将集群闪回到特定 TSO 以精确恢复误删的数据: ```sql mysql> INSERT INTO t VALUES (1); @@ -109,7 +132,7 @@ mysql> SELECT * FROM t; mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) -mysql> SELECT @@tidb_current_ts; -- 获取当前 TSO +mysql> SELECT @@tidb_current_ts; -- 获取当前 TSO +--------------------+ | @@tidb_current_ts | +--------------------+ @@ -137,7 +160,7 @@ mysql> SELECT * FROM t; 1 row in set (0.01 sec) ``` -如果 `FLASHBACK CLUSTER` 指定的时间点有未完成的 DDL 记录,那么 `FLASHBACK CLUSTER` 将执行失败: +如果在 `FLASHBACK` 语句指定的时间点存在未完全执行的 DDL 语句,`FLASHBACK` 语句将失败: ```sql mysql> ALTER TABLE t ADD INDEX k(a); @@ -155,7 +178,7 @@ mysql> FLASHBACK CLUSTER TO TIMESTAMP '2023-01-29 14:33:12'; ERROR 1105 (HY000): Detected another DDL job at 2023-01-29 14:33:12 +0800 CST, can't do flashback ``` -可以通过日志查看 `FLASHBACK` 执行进度,具体的日志如下所示: +通过日志,你可以获取 `FLASHBACK` 的执行进度。以下是一个示例: ``` [2022/10/09 17:25:59.316 +08:00] [INFO] [cluster.go:463] ["flashback cluster stats"] ["complete regions"=9] ["total regions"=10] [] diff --git a/sql-statements/sql-statement-flashback-database.md b/sql-statements/sql-statement-flashback-database.md index 4c403b7100da..32a637d074c4 100644 --- a/sql-statements/sql-statement-flashback-database.md +++ b/sql-statements/sql-statement-flashback-database.md @@ -1,19 +1,19 @@ --- title: FLASHBACK DATABASE -summary: TiDB 数据库中 FLASHBACK DATABASE 的使用概况。 +summary: 了解在 TiDB 数据库中 FLASHBACK DATABASE 的用法。 --- # FLASHBACK DATABASE -TiDB v6.4.0 引入了 `FLASHBACK DATABASE` 语法,其功能是在 Garbage Collection (GC) life time 时间内,可以用 `FLASHBACK DATABASE` 语句来恢复被 `DROP` 删除的数据库以及数据。 +TiDB v6.4.0 引入了 `FLASHBACK DATABASE` 语法。你可以使用 `FLASHBACK DATABASE` 来恢复在垃圾回收(GC)生命周期内被 `DROP` 语句删除的数据库及其数据。 -可以使用系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入) 配置数据的历史版本的保留时间(默认值是 `10m0s`)。可以使用以下 SQL 语句查询当前的 `safePoint`,即 GC 已经清理到的时间点: +你可以通过配置 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-new-in-v50) 系统变量来设置历史数据的保留时间。默认值为 `10m0s`。你可以使用以下 SQL 语句查询当前的 `safePoint`(即 GC 已执行到的时间点): ```sql SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'; ``` -只要一个数据库是在 `tikv_gc_safe_point` 时间之后被 `DROP`,即可以用 `FLASHBACK DATABASE` 语法来恢复。 +只要数据库是在 `tikv_gc_safe_point` 时间之后被 `DROP` 删除的,你就可以使用 `FLASHBACK DATABASE` 来恢复该数据库。 ## 语法 @@ -21,27 +21,26 @@ SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'; FLASHBACK DATABASE DBName [TO newDBName] ``` -### 语法图 +### 语法概要 ```ebnf+diagram FlashbackDatabaseStmt ::= 'FLASHBACK' DatabaseSym DBName FlashbackToNewName - FlashbackToNewName ::= ( 'TO' Identifier )? ``` ## 注意事项 -- 如果数据库被删除的时间超过了 GC life time (`tikv_gc_safe_point`),就无法使用 `FLASHBACK DATABASE` 语句来恢复被删除的数据了,否则会返回错误。错误类似于 `ERROR 1105 (HY000): Can't find dropped database 'test' in GC safe point 2022-11-06 16:10:10 +0800 CST`。 +* 如果数据库是在 `tikv_gc_safe_point` 时间之前删除的,你将无法使用 `FLASHBACK DATABASE` 语句恢复数据。`FLASHBACK DATABASE` 语句会返回类似 `ERROR 1105 (HY000): Can't find dropped database 'test' in GC safe point 2022-11-06 16:10:10 +0800 CST` 的错误。 -- 不能用 `FLASHBACK DATABASE` 多次恢复同一个被删除的数据库,因为 `FLASHBACK DATABASE` 所恢复数据库的 schema ID 和原被删除数据库的 schema ID 一致,多次恢复同一数据库会导致重复的 schema ID。在 TiDB 中,所有数据库的 schema ID 必须全局唯一。 +* 你不能使用 `FLASHBACK DATABASE` 语句多次恢复同一个数据库。因为通过 `FLASHBACK DATABASE` 恢复的数据库与原始数据库具有相同的 schema ID,多次恢复同一个数据库会导致 schema ID 重复。在 TiDB 中,数据库 schema ID 必须全局唯一。 -- 在开启 TiDB Binlog 时,使用 `FLASHBACK DATABASE` 需要注意以下情况: +* 当启用 TiDB Binlog 时,使用 `FLASHBACK DATABASE` 时需要注意以下几点: - * 下游从集群也需要支持 `FLASHBACK DATABASE`。 - * 从集群的 GC life time 一定要长于主集群的 GC life time。否则上下游同步存在的延迟可能也会造成下游恢复数据失败。 - * 如果 TiDB Binlog 同步出错,则需要在 TiDB Binlog 中过滤掉该数据库,同时手动全量重新导入该数据库的数据。 + * 下游从库必须支持 `FLASHBACK DATABASE`。 + * 从库的 GC 生命周期必须长于主库。否则,上下游之间的延迟可能会导致下游数据恢复失败。 + * 如果 TiDB Binlog 复制遇到错误,你需要在 TiDB Binlog 中过滤掉该数据库,然后手动为该数据库导入完整数据。 ## 示例 @@ -55,7 +54,7 @@ FlashbackToNewName ::= FLASHBACK DATABASE test; ``` -- 恢复被 `DROP` 删除的 `test` 数据库并重命名为 `test1`: +- 恢复被 `DROP` 删除的 `test` 数据库,并将其重命名为 `test1`: ```sql DROP DATABASE test; @@ -67,4 +66,4 @@ FlashbackToNewName ::= ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 diff --git a/sql-statements/sql-statement-flashback-table.md b/sql-statements/sql-statement-flashback-table.md index ca8b9071c01c..e4eac152341c 100644 --- a/sql-statements/sql-statement-flashback-table.md +++ b/sql-statements/sql-statement-flashback-table.md @@ -1,21 +1,21 @@ --- title: FLASHBACK TABLE -summary: TiDB 4.0 引入了 `FLASHBACK TABLE` 语法,可在 GC 生命周期内恢复被 `DROP` 或 `TRUNCATE` 删除的表和数据。使用系统变量 `tidb_gc_life_time` 配置历史版本保留时间,默认为 `10m0s`。查询当前`safePoint`:`SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'`。注意,过了 GC 生命周期就无法恢复被删除的数据。 +summary: 了解如何使用 `FLASHBACK TABLE` 语句恢复表。 --- # FLASHBACK TABLE -在 TiDB 4.0 中,引入了 `FLASHBACK TABLE` 语法,其功能是在 Garbage Collection (GC) life time 时间内,可以用 `FLASHBACK TABLE` 语句来恢复被 `DROP` 或 `TRUNCATE` 删除的表以及数据。 +`FLASHBACK TABLE` 语法自 TiDB 4.0 引入。你可以使用 `FLASHBACK TABLE` 语句在垃圾回收(GC)生命周期内恢复被 `DROP` 或 `TRUNCATE` 操作删除的表和数据。 -可以使用系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入) 配置数据的历史版本的保留时间(默认值是 `10m0s`)。可以使用以下 SQL 语句查询当前的 `safePoint`,即 GC 已经清理到的时间点: +系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-new-in-v50)(默认值:`10m0s`)定义了行的早期版本的保留时间。可以通过以下查询获取垃圾回收已执行到的当前 `safePoint`: {{< copyable "sql" >}} - ```sql - SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'; - ``` +```sql +SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point'; +``` -只要被 `DROP` 或 `TRUNCATE` 删除的表是在 `tikv_gc_safe_point` 时间之后,都能用 `FLASHBACK TABLE` 语法来恢复。 +只要表是在 `tikv_gc_safe_point` 时间之后被 `DROP` 或 `TRUNCATE` 语句删除的,你就可以使用 `FLASHBACK TABLE` 语句恢复该表。 ## 语法 @@ -25,7 +25,7 @@ summary: TiDB 4.0 引入了 `FLASHBACK TABLE` 语法,可在 GC 生命周期内 FLASHBACK TABLE table_name [TO other_table_name] ``` -### 语法图 +## 语法图 ```ebnf+diagram FlashbackTableStmt ::= @@ -40,18 +40,18 @@ FlashbackToNewName ::= ## 注意事项 -如果删除了一张表并过了 GC lifetime,就不能再用 `FLASHBACK TABLE` 语句来恢复被删除的数据了,否则会返回错误,错误类似于 `Can't find dropped/truncated table 't' in GC safe point 2020-03-16 16:34:52 +0800 CST`。 - -在开启 TiDB Binlog 时使用 `FLASHBACK TABLE` 需要注意以下情况: +如果表被删除且 GC 生命周期已过,则无法再使用 `FLASHBACK TABLE` 语句恢复已删除的数据。否则,将返回类似 `Can't find dropped / truncated table 't' in GC safe point 2020-03-16 16:34:52 +0800 CST` 的错误。 -* 下游从集群也支持 `FLASHBACK TABLE` -* 从集群的 GC lifetime 一定要长于主集群的 GC lifetime。上下游同步存在的延迟可能也会造成下游恢复数据失败。 +当启用 TiDB Binlog 并使用 `FLASHBACK TABLE` 语句时,请注意以下条件和要求: -如果 Binlog 同步出错,则需要在 Binlog 过滤掉该表,同时手动全量重新导入该表的数据。 +* 下游从集群也必须支持 `FLASHBACK TABLE`。 +* 从集群的 GC 生命周期必须长于主集群。 +* 上下游之间的复制延迟也可能导致无法将数据恢复到下游。 +* 如果 TiDB Binlog 在复制表时发生错误,你需要在 TiDB Binlog 中过滤该表,并手动导入该表的所有数据。 ## 示例 -- 恢复被 `DROP` 删除的表数据: +- 恢复被 `DROP` 操作删除的表数据: {{< copyable "sql" >}} @@ -65,7 +65,9 @@ FlashbackToNewName ::= FLASHBACK TABLE t; ``` -- 恢复被 `TRUNCATE` 的表数据,由于被 `TRUNCATE` 的表还存在,所以需要重命名被恢复的表,否则会报错表 t 已存在。 +- 恢复被 `TRUNCATE` 操作删除的表数据。由于被截断的表 `t` 仍然存在,你需要将要恢复的表 `t` 重命名。否则,由于表 `t` 已存在,将返回错误。 + + {{< copyable "sql" >}} ```sql TRUNCATE TABLE t; @@ -77,25 +79,27 @@ FlashbackToNewName ::= FLASHBACK TABLE t TO t1; ``` -## 工作原理 +## 实现原理 + +删除表时,TiDB 只删除表元数据,并将要删除的表数据(行数据和索引数据)写入 `mysql.gc_delete_range` 表。TiDB 后台的 GC Worker 会定期从 `mysql.gc_delete_range` 表中删除超过 GC 生命周期的键。 -TiDB 在删除表时,实际上只删除了表的元信息,并将需要删除的表数据(行数据和索引数据)写一条数据到 `mysql.gc_delete_range` 表。TiDB 后台的 GC Worker 会定期从 `mysql.gc_delete_range` 表中取出超过 GC lifetime 相关范围的 key 进行删除。 +因此,要恢复表,你只需要在 GC Worker 删除表数据之前恢复表元数据并删除 `mysql.gc_delete_range` 表中的相应行记录。你可以使用 TiDB 的快照读取来恢复表元数据。有关快照读取的详细信息,请参阅[读取历史数据](/read-historical-data.md)。 -所以,`FLASHBACK TABLE` 只需要在 GC Worker 还没删除表数据前,恢复表的元信息并删除 `mysql.gc_delete_range` 表中相应的行记录即可。恢复表的元信息可以用 TiDB 的快照读实现。具体的快照读内容可以参考[读取历史数据](/read-historical-data.md)文档。下面是 `FLASHBACK TABLE t TO t1` 的工作流程: +以下是 `FLASHBACK TABLE t TO t1` 的工作过程: -1. 从 DDL History job 中查找 `drop table` 或者 `truncate table` 类型的操作,且操作的表名是 `t` 的第一个 DDL job,若没找到,则返回错误。 -2. 检查 DDL job 的开始时间,是否在 `tikv_gc_safe_point` 之前。如果是`tikv_gc_safe_point` 之前,说明被 `DROP` 或 `TRUNCATE` 删除的表已经被 GC 清理掉,返回错误。 -3. 用 DDL job 的开始时间作为 snapshot 读取历史数据,读取表的元信息。 -4. 删除 `mysql.gc_delete_range` 中和表 `t` 相关的 GC 任务。 -5. 将表的元信息中的 `name` 修改成 `t1`,并用该元信息新建一个表。注意:这里只是修改了表名,但是 table ID 不变,依旧是之前被删除的表 `t` 的 table ID。 +1. TiDB 搜索最近的 DDL 历史作业,并定位表 `t` 上第一个 `DROP TABLE` 或 `truncate table` 类型的 DDL 操作。如果 TiDB 无法定位到一个,则返回错误。 +2. TiDB 检查 DDL 作业的开始时间是否在 `tikv_gc_safe_point` 之前。如果在 `tikv_gc_safe_point` 之前,则表示被 `DROP` 或 `TRUNCATE` 操作删除的表已被 GC 清理,并返回错误。 +3. TiDB 使用 DDL 作业的开始时间作为快照来读取历史数据和读取表元数据。 +4. TiDB 删除 `mysql.gc_delete_range` 中与表 `t` 相关的 GC 任务。 +5. TiDB 将表元数据中的 `name` 更改为 `t1`,并使用此元数据创建新表。请注意,只更改表名而不更改表 ID。表 ID 与之前删除的表 `t` 的 ID 相同。 -可以发现,从表 `t` 被删除,到表 `t` 被 `FLASHBACK` 恢复到 `t1`,一直都是对表的元信息进行操作,而表的用户数据一直未被修改过。被恢复的表 `t1` 和之前被删除的表 `t` 的 table ID 相同,所以表 `t1` 才能读取表`t` 的用户数据。 +从上述过程可以看出,TiDB 始终对表的元数据进行操作,而表的用户数据从未被修改。恢复的表 `t1` 与之前删除的表 `t` 具有相同的 ID,因此 `t1` 可以读取 `t` 的用户数据。 > **注意:** > -> 不能用 `FLASHBACK` 多次恢复同一个被删除的表,因为 `FLASHBACK` 所恢复表的 table ID 还是被删除表的 table ID,而 TiDB 要求所有还存在的表 table ID 必须全局唯一。 +> 你不能使用 `FLASHBACK` 语句多次恢复同一个已删除的表,因为恢复的表的 ID 与已删除表的 ID 相同,而 TiDB 要求所有现有表必须具有全局唯一的表 ID。 - `FLASHBACK TABLE` 是通过快照读获取表的元信息后,再走一次类似于 `CREATE TABLE` 的建表流程,所以 `FLASHBACK TABLE` 实际上也是一种 DDL 操作。 +`FLASHBACK TABLE` 操作是通过 TiDB 通过快照读取获取表元数据,然后经过类似于 `CREATE TABLE` 的表创建过程来完成的。因此,`FLASHBACK TABLE` 本质上是一种 DDL 操作。 ## MySQL 兼容性 diff --git a/sql-statements/sql-statement-flush-privileges.md b/sql-statements/sql-statement-flush-privileges.md index efab2fc26ee2..70ebab75e841 100644 --- a/sql-statements/sql-statement-flush-privileges.md +++ b/sql-statements/sql-statement-flush-privileges.md @@ -1,11 +1,11 @@ --- -title: FLUSH PRIVILEGES -summary: TiDB 数据库中 FLUSH PRIVILEGES 的使用概况。 +title: FLUSH PRIVILEGES | TiDB SQL 语句参考 +summary: TiDB 数据库中 FLUSH PRIVILEGES 的使用概述。 --- # FLUSH PRIVILEGES -`FLUSH PRIVILEGES` 语句可触发 TiDB 从权限表中重新加载权限的内存副本。在对如 `mysql.user` 一类的表进行手动编辑后,应当执行 `FLUSH PRIVILEGES`。使用如 `GRANT` 或 `REVOKE` 一类的权限语句后,不需要执行 `FLUSH PRIVILEGES` 语句。执行 `FLUSH PRIVILEGES` 语句的用户需要拥有 `RELOAD` 权限。 +`FLUSH PRIVILEGES` 语句指示 TiDB 从权限表重新加载内存中的权限副本。在手动编辑如 `mysql.user` 等表后,你必须执行此语句。但是,在使用 `GRANT` 或 `REVOKE` 等权限语句后,不需要执行此语句。执行此语句需要 `RELOAD` 权限。 ## 语法图 @@ -27,22 +27,21 @@ FlushOption ::= ## 示例 -{{< copyable "sql" >}} - ```sql -FLUSH PRIVILEGES; -``` - -``` +mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.01 sec) ``` ## MySQL 兼容性 -`FLUSH PRIVILEGES` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `FLUSH PRIVILEGES` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 -* [`GRANT `](/sql-statements/sql-statement-grant-privileges.md) -* [`REVOKE `](/sql-statements/sql-statement-revoke-privileges.md) -* [Privilege Management](/privilege-management.md) +* [SHOW GRANTS](/sql-statements/sql-statement-show-grants.md) + + + +* [权限管理](/privilege-management.md) + + diff --git a/sql-statements/sql-statement-flush-status.md b/sql-statements/sql-statement-flush-status.md index 316a6fa35a8f..93f39726aa75 100644 --- a/sql-statements/sql-statement-flush-status.md +++ b/sql-statements/sql-statement-flush-status.md @@ -1,13 +1,13 @@ --- -title: FLUSH STATUS -summary: TiDB 数据库中 FLUSH STATUS 的使用概况。 +title: FLUSH STATUS | TiDB SQL 语句参考 +summary: TiDB 数据库中 FLUSH STATUS 的使用概述。 --- # FLUSH STATUS -`FLUSH STATUS` 语句用于提供 MySQL 兼容性,但在 TiDB 上并无作用。因为 TiDB 使用 Prometheus 和 Grafana 而非 `SHOW STATUS` 来进行集中度量收集。 +此语句是为了与 MySQL 兼容而包含的。它对 TiDB 没有任何影响,因为 TiDB 使用 Prometheus 和 Grafana 进行集中式指标收集,而不是使用 `SHOW STATUS`。 -## 语法图 +## 语法概要 ```ebnf+diagram FlushStmt ::= @@ -27,13 +27,8 @@ FlushOption ::= ## 示例 -{{< copyable "sql" >}} - ```sql -show status; -``` - -``` +mysql> show status; +--------------------+--------------------------------------+ | Variable_name | Value | +--------------------+--------------------------------------+ @@ -45,15 +40,8 @@ show status; | Ssl_cipher | | +--------------------+--------------------------------------+ 6 rows in set (0.01 sec) -``` - -{{< copyable "sql" >}} -```sql -show global status; -``` - -``` +mysql> show global status; +--------------------+--------------------------------------+ | Variable_name | Value | +--------------------+--------------------------------------+ @@ -65,25 +53,11 @@ show global status; | ddl_schema_version | 141 | +--------------------+--------------------------------------+ 6 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -flush status; -``` - -``` +mysql> flush status; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -show status; -``` - -``` +mysql> show status; +--------------------+--------------------------------------+ | Variable_name | Value | +--------------------+--------------------------------------+ @@ -99,7 +73,7 @@ show status; ## MySQL 兼容性 -* `FLUSH STATUS` 语句与 MySQL 兼容。 +* 此语句与 MySQL 兼容。 ## 另请参阅 diff --git a/sql-statements/sql-statement-flush-tables.md b/sql-statements/sql-statement-flush-tables.md index c9f2096af9a2..942d63a9ba6f 100644 --- a/sql-statements/sql-statement-flush-tables.md +++ b/sql-statements/sql-statement-flush-tables.md @@ -1,11 +1,11 @@ --- -title: FLUSH TABLES -summary: TiDB 数据库中 FLUSH TABLES 的使用概况。 +title: FLUSH TABLES | TiDB SQL 语句参考 +summary: TiDB 数据库中 FLUSH TABLES 的使用概览。 --- # FLUSH TABLES -`FLUSH TABLES` 语句用于提供 MySQL 兼容性,但在 TiDB 中并无有效用途。 +该语句是为了与 MySQL 兼容而包含的。在 TiDB 中没有实际用途。 ## 语法图 @@ -40,31 +40,19 @@ WithReadLockOpt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -FLUSH TABLES; -``` - -``` +mysql> FLUSH TABLES; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -FLUSH TABLES WITH READ LOCK; -``` - -``` +mysql> FLUSH TABLES WITH READ LOCK; ERROR 1105 (HY000): FLUSH TABLES WITH READ LOCK is not supported. Please use @@tidb_snapshot ``` ## MySQL 兼容性 -* TiDB 没有 MySQL 中的表缓存这一概念。所以,`FLUSH TABLES` 因 MySQL 兼容性会在 TiDB 中解析出但会被忽略掉。 -* 因为 TiDB 目前不支持锁表,所以`FLUSH TABLES WITH READ LOCK` 语句会产生错误。建议使用 [Historical reads](/read-historical-data.md) 来实现锁表。 +* TiDB 没有 MySQL 中表缓存的概念。因此,为了兼容性,TiDB 会解析但忽略 `FLUSH TABLES`。 +* 语句 `FLUSH TABLES WITH READ LOCK` 会产生错误,因为 TiDB 目前不支持锁定表。建议使用[历史读取](/read-historical-data.md)来代替。 ## 另请参阅 -* [Read historical data](/read-historical-data.md) +* [读取历史数据](/read-historical-data.md) diff --git a/sql-statements/sql-statement-grant-privileges.md b/sql-statements/sql-statement-grant-privileges.md index 8d8d160e0b15..5729e8da4800 100644 --- a/sql-statements/sql-statement-grant-privileges.md +++ b/sql-statements/sql-statement-grant-privileges.md @@ -1,13 +1,13 @@ --- -title: GRANT -summary: TiDB 数据库中 GRANT 的使用概况。 +title: GRANT | TiDB SQL 语句参考 +summary: TiDB 数据库中 GRANT 的使用概览。 --- # `GRANT ` -`GRANT ` 语句用于为 TiDB 中已存在的用户分配权限。TiDB 中的权限系统同 MySQL 一样,都基于数据库/表模式来分配凭据。执行 `GRANT ` 语句需要拥有分配的权限,并且拥有 `GRANT OPTION` 权限。 +此语句为 TiDB 中的已存在用户分配权限。TiDB 中的权限系统遵循 MySQL,其中凭据是基于数据库/表模式分配的。执行此语句需要 `GRANT OPTION` 权限和你分配的所有权限。 -## 语法图 +## 语法 ```ebnf+diagram GrantStmt ::= @@ -62,33 +62,14 @@ RequireListElement ::= 'ISSUER' Issuer | 'SUBJECT' Subject | 'CIPHER' Cipher | ' ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE USER 'newuser' IDENTIFIED BY 'mypassword'; -``` - -``` +mysql> CREATE USER 'newuser' IDENTIFIED BY 'mypassword'; Query OK, 1 row affected (0.02 sec) -``` -{{< copyable "sql" >}} - -```sql -GRANT ALL ON test.* TO 'newuser'; -``` - -``` +mysql> GRANT ALL ON test.* TO 'newuser'; Query OK, 0 rows affected (0.03 sec) -``` - -{{< copyable "sql" >}} - -```sql -SHOW GRANTS FOR 'newuser'; -``` -``` +mysql> SHOW GRANTS FOR 'newuser'; +-------------------------------------------------+ | Grants for newuser@% | +-------------------------------------------------+ @@ -102,12 +83,17 @@ SHOW GRANTS FOR 'newuser'; * 与 MySQL 类似,`USAGE` 权限表示登录 TiDB 服务器的能力。 * 目前不支持列级权限。 -* 与 MySQL 类似,不存在 `NO_AUTO_CREATE_USER` sql 模式时,`GRANT` 语句将在用户不存在时自动创建一个空密码的新用户。删除此 sql-mode(默认情况下已启用)会带来安全风险。 -* `GRANT ` 语句执行成功后,在 TiDB 中语句执行的结果会在当前连接立即生效,而 [MySQL 中部分权限的结果需要等到之后的连接才生效](https://dev.mysql.com/doc/refman/8.0/en/privilege-changes.html)。见 [TiDB #39356](https://github.com/pingcap/tidb/issues/39356)。 +* 与 MySQL 类似,当不存在 `NO_AUTO_CREATE_USER` SQL 模式时,如果用户不存在,`GRANT` 语句将自动创建一个空密码的新用户。移除此 SQL 模式(默认启用)会带来安全风险。 +* 在 TiDB 中,`GRANT ` 语句成功执行后,执行结果会立即在当前连接上生效。而[在 MySQL 中,对于某些权限,执行结果仅在后续连接中生效](https://dev.mysql.com/doc/refman/8.0/en/privilege-changes.html)。详情请参见 [TiDB #39356](https://github.com/pingcap/tidb/issues/39356)。 ## 另请参阅 * [`GRANT `](/sql-statements/sql-statement-grant-role.md) * [`REVOKE `](/sql-statements/sql-statement-revoke-privileges.md) -* [`SHOW GRANTS`](/sql-statements/sql-statement-show-grants.md) +* [SHOW GRANTS](/sql-statements/sql-statement-show-grants.md) + + + * [权限管理](/privilege-management.md) + + diff --git a/sql-statements/sql-statement-grant-role.md b/sql-statements/sql-statement-grant-role.md index b527af25246d..bc9e17a6d315 100644 --- a/sql-statements/sql-statement-grant-role.md +++ b/sql-statements/sql-statement-grant-role.md @@ -1,11 +1,11 @@ --- -title: GRANT -summary: TiDB 数据库中 GRANT 的使用概况。 +title: GRANT | TiDB SQL 语句参考 +summary: TiDB 数据库中 GRANT 的使用概览。 --- # `GRANT ` -`GRANT ` 语句用于将之前创建的角色授予给现有用户。用户可以通过 `SET ROLE ` 语句拥有角色权限,或者通过 `SET ROLE ALL` 语句拥有被授予的所有角色。 +将先前创建的角色分配给现有用户。用户随后可以使用语句 `SET ROLE ` 来获取该角色的权限,或使用 `SET ROLE ALL` 来获取已分配的所有角色的权限。 ## 语法图 @@ -22,7 +22,7 @@ UsernameList ::= ## 示例 -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root @@ -44,13 +44,13 @@ GRANT analyticsteam TO jennifer; Query OK, 0 rows affected (0.01 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -需要注意的是,默认情况下,用户 `jennifer` 需要执行 `SET ROLE analyticsteam` 语句才能使用与 `analyticsteam` 角色相关联的权限: +注意,默认情况下,`jennifer` 需要执行 `SET ROLE analyticsteam` 才能使用与 `analyticsteam` 角色相关的权限: ```sql SHOW GRANTS; @@ -86,26 +86,26 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -执行 `SET DEFAULT ROLE` 语句将用户 `jennifer` 与 `analyticsteam` 角色相关联: +可以使用 `SET DEFAULT ROLE` 语句将角色 `analyticsteam` 关联到 `jennifer`: ```sql SET DEFAULT ROLE analyticsteam TO jennifer; Query OK, 0 rows affected (0.02 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -此时 `jennifer` 用户无需执行 `SET ROLE` 语句就能拥有 `analyticsteam` 角色相关联的权限: +此后,用户 `jennifer` 拥有与角色 `analyticsteam` 相关的权限,且 `jennifer` 不需要执行 `SET ROLE` 语句: ```sql SHOW GRANTS; @@ -129,7 +129,7 @@ SHOW TABLES IN test; ## MySQL 兼容性 -`GRANT ` 语句与 MySQL 8.0 的角色功能完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `GRANT ` 语句与 MySQL 8.0 的角色功能完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 @@ -139,4 +139,9 @@ SHOW TABLES IN test; * [`REVOKE `](/sql-statements/sql-statement-revoke-role.md) * [`SET ROLE`](/sql-statements/sql-statement-set-role.md) * [`SET DEFAULT ROLE`](/sql-statements/sql-statement-set-default-role.md) + + + * [基于角色的访问控制](/role-based-access-control.md) + + diff --git a/sql-statements/sql-statement-import-into.md b/sql-statements/sql-statement-import-into.md index e783697ce9dc..f3ffb62ff7ac 100644 --- a/sql-statements/sql-statement-import-into.md +++ b/sql-statements/sql-statement-import-into.md @@ -1,65 +1,68 @@ --- title: IMPORT INTO -summary: TiDB 数据库中 IMPORT INTO 的使用概况。 +summary: TiDB 中 IMPORT INTO 的使用概述。 --- # IMPORT INTO -`IMPORT INTO` 语句使用 TiDB Lightning 的[物理导入模式](/tidb-lightning/tidb-lightning-physical-import-mode.md)导入数据,提供以下两种用法: +`IMPORT INTO` 语句允许你通过 TiDB Lightning 的[物理导入模式](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode)将数据导入到 TiDB。你可以通过以下两种方式使用 `IMPORT INTO`: -- `IMPORT INTO ... FROM FILE` 用于将 `CSV`、`SQL`、`PARQUET` 等格式的数据文件导入到 TiDB 的一张空表中。 -- `IMPORT INTO ... FROM SELECT` 用于将 `SELECT` 语句的查询结果导入到 TiDB 的一张空表中,也支持导入使用 [`AS OF TIMESTAMP`](/as-of-timestamp.md) 查询的历史数据。 +- `IMPORT INTO ... FROM FILE`:将 `CSV`、`SQL` 和 `PARQUET` 等格式的数据文件导入到 TiDB 的空表中。 +- `IMPORT INTO ... FROM SELECT`:将 `SELECT` 语句的查询结果导入到 TiDB 的空表中。你还可以使用它导入通过 [`AS OF TIMESTAMP`](/as-of-timestamp.md) 查询的历史数据。 + + > **注意:** > -> 与 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 相比,`IMPORT INTO` 语句可以直接在 TiDB 节点上执行,支持自动化分布式任务调度和 [TiDB 全局排序](/tidb-global-sort.md),在部署、资源利用率、任务配置便捷性、调用集成便捷性、高可用性和可扩展性等方面都有很大提升。建议在合适的场景下,使用 `IMPORT INTO` 代替 TiDB Lightning。 - -## 使用限制 - -- 只支持导入数据到数据库中已有的空表。 -- 如果表中其他分区已包含数据,不支持将数据导入到该表的空分区中。目标表必须完全为空才能执行导入操作。 -- 不支持导入到[临时表](/temporary-tables.md)或者[缓存表](/cached-tables.md)。 -- 不支持事务,也无法回滚。在显式事务 (`BEGIN`/`END`) 中执行会报错。 -- 不支持和 [Backup & Restore](/br/backup-and-restore-overview.md)、[`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md)、[创建索引加速](/system-variables.md#tidb_ddl_enable_fast_reorg-从-v630-版本开始引入)、TiDB Lightning 导入、TiCDC 数据同步、[Point-in-time recovery (PITR)](/br/br-log-architecture.md) 等功能同时工作。相关兼容性介绍,请参见 [`IMPORT INTO` 和 TiDB Lightning 与日志备份和 TiCDC 的兼容性](/tidb-lightning/tidb-lightning-compatibility-and-scenarios.md)。 -- 导入数据的过程中,请勿在目标表上执行 DDL 和 DML 操作,也不要在目标数据库上执行 [`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.md),否则会导致导入失败或数据不一致。导入期间也不建议进行读操作,因为读取的数据可能不一致。请在导入完成后再进行读写操作。 -- 导入期间会占用大量系统资源,建议 TiDB 节点使用 32 核以上的 CPU 和 64 GiB 以上内存以获得更好的性能。导入期间会将排序好的数据写入到 TiDB [临时目录](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入)下,建议优先考虑配置闪存等高性能存储介质。详情请参考[物理导入使用限制](/tidb-lightning/tidb-lightning-physical-import-mode.md#必要条件及限制)。 -- TiDB [临时目录](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入)至少需要有 90 GiB 的可用空间。建议预留大于等于所需导入数据的存储空间,以保证最佳导入性能。 -- 一个导入任务只支持导入数据到一张目标表中。 -- TiDB 集群升级期间不支持使用该语句。 -- 所需导入的数据不能存在主键或非空唯一索引冲突的记录,否则会导致任务失败。 -- 已知问题:在 TiDB 节点配置文件中的 PD 地址与当前集群 PD 拓扑不一致时(如曾经缩容过 PD,但没有对应更新 TiDB 配置文件或者更新该文件后未重启 TiDB 节点),执行 `IMPORT INTO` 会失败。 - -### `IMPORT INTO ... FROM FILE` 使用限制 - -- 目前单个 `IMPORT INTO` 任务支持导入 10 TiB 以内的数据。启用[全局排序](/tidb-global-sort.md)后,单个 `IMPORT INTO` 任务支持导入 40 TiB 以内的数据。 -- 在导入完成前会阻塞当前连接,如果需要异步执行,可以添加 `DETACHED` 选项。 -- 每个集群上最多同时有 16 个 `IMPORT INTO` 任务(参考 [TiDB 分布式执行框架使用限制](/tidb-distributed-execution-framework.md#使用限制))在运行,当集群没有足够资源或者达到任务数量上限时,新提交的导入任务会排队等待执行。 -- 当使用[全局排序](/tidb-global-sort.md)导入数据时,`THREAD` 选项值需要大于或等于 `8`。 -- 当使用[全局排序](/tidb-global-sort.md)导入数据时,单行数据的总长度不能超过 32 MiB。 -- 未开启 [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md)时创建的所有 `IMPORT INTO` 任务会直接在提交任务的节点上运行,后续即使开启了分布式执行框架,这些任务也不会被调度到其它 TiDB 节点上执行。开启分布式执行框架后,新创建的 `IMPORT INTO` 任务如果导入的是 S3 或 GCS 中的数据,则会自动调度或者 failover 到其它 TiDB 节点执行。 - -### `IMPORT INTO ... FROM SELECT` 使用限制 - -- `IMPORT INTO ... FROM SELECT` 仅能在当前用户连接的 TiDB 节点执行,在导入完成前会阻塞当前连接。 -- `IMPORT INTO ... FROM SELECT` 仅支持配置 `THREAD` 和 `DISABLE_PRECHECK` 这两个[导入选项](#withoptions)。 -- `IMPORT INTO ... FROM SELECT` 不支持使用 `SHOW IMPORT JOB(s)` 和 `CANCEL IMPORT JOB ` 等任务管理语句。 -- TiDB [临时目录](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入)需要有足够的空间来存储整个 `SELECT` 语句查询结果(暂不支持设置 `DISK_QUOTA` 选项)。 +> 与 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 相比,`IMPORT INTO` 可以直接在 TiDB 节点上执行,支持自动分布式任务调度和 [TiDB 全局排序](/tidb-global-sort.md),在部署、资源利用、任务配置便利性、调用和集成便利性、高可用性和可扩展性等方面都有显著改进。建议你在适当的场景下考虑使用 `IMPORT INTO` 替代 TiDB Lightning。 + + + +## 限制 + +- `IMPORT INTO` 只支持将数据导入到数据库中已存在的空表中。 +- `IMPORT INTO` 不支持在表的其他分区已包含数据的情况下将数据导入到空分区。目标表必须完全为空才能进行导入操作。 +- `IMPORT INTO` 不支持将数据导入到[临时表](/temporary-tables.md)或[缓存表](/cached-tables.md)中。 +- `IMPORT INTO` 不支持事务或回滚。在显式事务(`BEGIN`/`END`)中执行 `IMPORT INTO` 将返回错误。 +- `IMPORT INTO` 不支持与[备份恢复](https://docs.pingcap.com/tidb/stable/backup-and-restore-overview)、[`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md)、[加速添加索引](/system-variables.md#tidb_ddl_enable_fast_reorg-new-in-v630)、使用 TiDB Lightning 导入数据、使用 TiCDC 复制数据或[时间点恢复 (PITR)](https://docs.pingcap.com/tidb/stable/br-log-architecture) 等功能同时工作。有关更多兼容性信息,请参见 [TiDB Lightning 和 `IMPORT INTO` 与 TiCDC 和日志备份的兼容性](https://docs.pingcap.com/tidb/stable/tidb-lightning-compatibility-and-scenarios)。 +- 在数据导入过程中,不要对目标表执行 DDL 或 DML 操作,也不要对目标数据库执行 [`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.md)。这些操作可能导致导入失败或数据不一致。此外,**不建议**在导入过程中执行读取操作,因为读取的数据可能不一致。只有在导入完成后才执行读写操作。 +- 导入过程会显著消耗系统资源。对于 TiDB Self-Managed,为获得更好的性能,建议使用至少 32 核和 64 GiB 内存的 TiDB 节点。TiDB 在导入期间会将排序后的数据写入 TiDB [临时目录](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630),因此建议为 TiDB Self-Managed 配置高性能存储介质,如闪存。更多信息,请参见[物理导入模式限制](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode#requirements-and-restrictions)。 +- 对于 TiDB Self-Managed,TiDB [临时目录](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630)预期至少有 90 GiB 的可用空间。建议分配等于或大于要导入的数据量的存储空间。 +- 一个导入任务只支持导入数据到一个目标表。 +- 在 TiDB 集群升级期间不支持 `IMPORT INTO`。 +- 确保要导入的数据不包含主键或非空唯一索引冲突的记录。否则,冲突可能导致导入任务失败。 +- 已知问题:如果 TiDB 节点配置文件中的 PD 地址与集群当前的 PD 拓扑不一致,`IMPORT INTO` 任务可能会失败。这种不一致可能出现在以下情况:例如之前进行了 PD 缩容,但 TiDB 配置文件未相应更新,或者在配置文件更新后 TiDB 节点未重启。 +### `IMPORT INTO ... FROM FILE` 限制 + +- 对于 TiDB Self-Managed,每个 `IMPORT INTO` 任务支持导入 10 TiB 以内的数据。如果启用[全局排序](/tidb-global-sort.md)功能,每个 `IMPORT INTO` 任务支持导入 40 TiB 以内的数据。 +- 对于 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated),如果要导入的数据超过 500 GiB,建议使用至少 16 核的 TiDB 节点并启用[全局排序](/tidb-global-sort.md)功能,此时每个 `IMPORT INTO` 任务支持导入 40 TiB 以内的数据。如果要导入的数据在 500 GiB 以内,或者 TiDB 节点的核数少于 16,则不建议启用[全局排序](/tidb-global-sort.md)功能。 +- `IMPORT INTO ... FROM FILE` 的执行会阻塞当前连接,直到导入完成。要异步执行该语句,可以添加 `DETACHED` 选项。 +- 每个集群最多可以同时运行 16 个 `IMPORT INTO` 任务(参见 [TiDB 分布式执行框架 (DXF) 使用限制](/tidb-distributed-execution-framework.md#limitation))。当集群资源不足或达到最大任务数时,新提交的导入任务将排队等待执行。 +- 当使用[全局排序](/tidb-global-sort.md)功能进行数据导入时,`THREAD` 选项的值必须至少为 `8`。 +- 当使用[全局排序](/tidb-global-sort.md)功能进行数据导入时,单行数据编码后的大小不能超过 32 MiB。 +- 所有在未启用 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) 时创建的 `IMPORT INTO` 任务都直接在提交任务的节点上运行,即使后来启用了 DXF,这些任务也不会被调度到其他 TiDB 节点执行。启用 DXF 后,只有新创建的从 S3 或 GCS 导入数据的 `IMPORT INTO` 任务才会自动调度或故障转移到其他 TiDB 节点执行。 + +### `IMPORT INTO ... FROM SELECT` 限制 + +- `IMPORT INTO ... FROM SELECT` 只能在当前用户连接的 TiDB 节点上执行,并且会阻塞当前连接直到导入完成。 +- `IMPORT INTO ... FROM SELECT` 只支持两个[导入选项](#withoptions):`THREAD` 和 `DISABLE_PRECHECK`。 +- `IMPORT INTO ... FROM SELECT` 不支持任务管理语句,如 `SHOW IMPORT JOB(s)` 和 `CANCEL IMPORT JOB `。 +- TiDB 的[临时目录](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630)需要足够的空间来存储 `SELECT` 语句的整个查询结果(目前不支持配置 `DISK_QUOTA` 选项)。 - 不支持使用 [`tidb_snapshot`](/read-historical-data.md) 导入历史数据。 -- 由于 `SELECT` 子句的语法较为复杂,`IMPORT INTO` 的 `WITH` 参数可能会与其冲突,导致解析时报错,例如 `GROUP BY ... [WITH ROLLUP]`。建议先对复杂的 `SELECT` 语句创建视图,然后使用 `IMPORT INTO ... FROM SELECT * FROM view_name` 进行导入。或者,可以通过括号明确 `SELECT` 子句的范围,例如 `IMPORT INTO ... FROM (SELECT ...) WITH ...`。 - -## 导入前准备 +- 由于 `SELECT` 子句的语法复杂,`IMPORT INTO` 中的 `WITH` 参数可能与之冲突并导致解析错误,例如 `GROUP BY ... [WITH ROLLUP]`。建议为复杂的 `SELECT` 语句创建视图,然后使用 `IMPORT INTO ... FROM SELECT * FROM view_name` 进行导入。或者,可以用括号明确 `SELECT` 子句的范围,例如 `IMPORT INTO ... FROM (SELECT ...) WITH ...`。 -在使用 `IMPORT INTO` 开始导入数据前,请确保: +## 导入前提条件 -- 要导入的目标表在 TiDB 中已经创建,并且是空表。 -- 当前集群有足够的剩余空间能容纳要导入的数据。 -- 当前连接的 TiDB 节点的[临时目录](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入)至少有 90 GiB 的磁盘空间。如果导入存储在 S3 或 GCS 的数据文件且开启了 [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-从-v710-版本开始引入),需要确保集群中所有 TiDB 节点的临时目录都有足够的磁盘空间。 +在使用 `IMPORT INTO` 导入数据之前,请确保满足以下要求: -## 需要的权限 +- 要导入的目标表已在 TiDB 中创建,且为空表。 +- 目标集群有足够的空间存储要导入的数据。 +- 对于 TiDB Self-Managed,当前会话连接的 TiDB 节点的[临时目录](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630)至少有 90 GiB 的可用空间。如果启用了 [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-new-in-v710) 且导入数据来自 S3 或 GCS,还要确保集群中每个 TiDB 节点的临时目录都有足够的磁盘空间。 -执行 `IMPORT INTO` 的用户需要有目标表的 `SELECT`、`UPDATE`、`INSERT`、`DELETE` 和 `ALTER` 权限。如果是导入存储在 TiDB 本地的文件,还需要有 `FILE` 权限。 +## 所需权限 -## 语法图 +执行 `IMPORT INTO` 需要目标表的 `SELECT`、`UPDATE`、`INSERT`、`DELETE` 和 `ALTER` 权限。要导入 TiDB 本地存储中的文件,还需要 `FILE` 权限。 +## 语法 ```ebnf+diagram ImportIntoStmt ::= @@ -93,83 +96,81 @@ OptionItem ::= ### ColumnNameOrUserVarList -用于指定数据文件中每行的各个字段如何对应到目标表列,也可以将字段对应到某个变量,用来跳过导入某些字段或者在 `SetClause` 中使用。 +指定数据文件中的每个字段如何对应目标表中的列。你还可以使用它将字段映射到变量以跳过某些字段的导入,或在 `SetClause` 中使用它。 -- 当不指定该参数时,数据文件中每行的字段数需要和目标表的列数一致,且各个字段会按顺序导入到对应的列。 -- 当指定该参数时,指定的列或变量个数需要和数据文件中每行的字段数一致。 +- 如果未指定此参数,数据文件中每行的字段数必须与目标表的列数匹配,并且字段将按顺序导入到对应的列中。 +- 如果指定了此参数,指定的列或变量数必须与数据文件中每行的字段数匹配。 ### SetClause -用于指定目标列值的计算方式。在 SET 表达式的右侧,可以引用在 `ColumnNameOrUserVarList` 中指定的变量。 +指定如何计算目标列的值。在 `SET` 表达式的右侧,你可以引用在 `ColumnNameOrUserVarList` 中指定的变量。 -SET 表达式左侧只能引用 `ColumnNameOrUserVarList` 中没有的列名。如果目标列名已经在 `ColumnNameOrUserVarList` 中,则该 SET 表达式无效。 +在 `SET` 表达式的左侧,你只能引用不包含在 `ColumnNameOrUserVarList` 中的列名。如果目标列名已存在于 `ColumnNameOrUserVarList` 中,则 `SET` 表达式无效。 ### fileLocation -用于指定数据文件的存储位置,该位置可以是 S3 或 GCS URI 路径,也可以是 TiDB 本地文件路径。 +指定数据文件的存储位置,可以是 Amazon S3 或 GCS 的 URI 路径,或者是 TiDB 本地文件路径。 -- S3 或 GCS URI 路径:配置详见[外部存储服务的 URI 格式](/external-storage-uri.md)。 +- Amazon S3 或 GCS URI 路径:有关 URI 配置详情,请参见[外部存储服务的 URI 格式](/external-storage-uri.md)。 -- TiDB 本地文件路径:必须为绝对路径,数据文件后缀必须为 `.csv`、`.sql` 或 `.parquet`。确保该路径对应的文件存储在当前用户连接的 TiDB 节点上,且当前连接的用户有 `FILE` 权限。 +- TiDB 本地文件路径:必须是绝对路径,且文件扩展名必须是 `.csv`、`.sql` 或 `.parquet`。确保此路径对应的文件存储在当前用户连接的 TiDB 节点上,且用户具有 `FILE` 权限。 > **注意:** > -> 如果目标集群开启了 [SEM](/system-variables.md#tidb_enable_enhanced_security),则 fileLocation 不能指定为本地文件路径。 +> 如果目标集群启用了 [SEM](/system-variables.md#tidb_enable_enhanced_security),则 `fileLocation` 不能指定为本地文件路径。 -使用 fileLocation 可以指定单个文件,也可使用通配符 `*` 和 `[]` 来匹配需要导入的多个文件。注意通配符只能用在文件名部分,不会匹配目录,也不会递归处理子目录下相关的文件。下面以数据存储在 S3 为例: +在 `fileLocation` 参数中,你可以指定单个文件,或使用 `*` 和 `[]` 通配符匹配多个文件进行导入。注意,通配符只能用于文件名,因为它不匹配目录或递归匹配子目录中的文件。以存储在 Amazon S3 上的文件为例,你可以按以下方式配置参数: - 导入单个文件:`s3:///path/to/data/foo.csv` -- 导入指定路径下的所有文件:`s3:///path/to/data/*` -- 导入指定路径下的所有以 `.csv` 结尾的文件:`s3:///path/to/data/*.csv` -- 导入指定路径下所有以 `foo` 为前缀的文件:`s3:///path/to/data/foo*` -- 导入指定路径下以 `foo` 为前缀、以 `.csv` 结尾的文件:`s3:///path/to/data/foo*.csv` -- 导入指定路径下的 `1.csv` 和 `2.csv`:`s3:///path/to/data/[12].csv` - +- 导入指定路径中的所有文件:`s3:///path/to/data/*` +- 导入指定路径中所有扩展名为 `.csv` 的文件:`s3:///path/to/data/*.csv` +- 导入指定路径中所有以 `foo` 为前缀的文件:`s3:///path/to/data/foo*` +- 导入指定路径中所有以 `foo` 为前缀且扩展名为 `.csv` 的文件:`s3:///path/to/data/foo*.csv` +- 导入指定路径中的 `1.csv` 和 `2.csv`:`s3:///path/to/data/[12].csv` ### Format -`IMPORT INTO` 支持 3 种数据文件格式,包括 `CSV`、`SQL` 和 `PARQUET`。当不指定该参数时,默认格式为 `CSV`。 +`IMPORT INTO` 语句支持三种数据文件格式:`CSV`、`SQL` 和 `PARQUET`。如果未指定,默认格式为 `CSV`。 ### WithOptions -你可以通过 WithOptions 来指定导入选项,控制数据导入过程。例如,如需使导入数据文件的任务在后台异步执行,你可以通过在 `IMPORT INTO` 语句中添加 `WITH DETACHED` 选项来开启导入任务的 `DETACHED` 模式。 +你可以使用 `WithOptions` 指定导入选项并控制数据导入过程。例如,要在后台异步执行数据文件的导入,可以通过在 `IMPORT INTO` 语句中添加 `WITH DETACHED` 选项来启用导入的 `DETACHED` 模式。 -目前支持的选项包括: +支持的选项如下: -| 选项名 | 支持的数据源以及格式 | 描述 | +| 选项名称 | 支持的数据源和格式 | 描述 | |:---|:---|:---| -| `CHARACTER_SET=''` | CSV | 指定数据文件的字符集,默认为 `utf8mb4`。目前支持的字符集包括 `binary`、`utf8`、`utf8mb4`、`gb18030`、`gbk`、`latin1` 和 `ascii`。 | -| `FIELDS_TERMINATED_BY=''` | CSV | 指定字段分隔符,默认为 `,`。 | -| `FIELDS_ENCLOSED_BY=''` | CSV | 指定字段的定界符,默认为 `"`。 | -| `FIELDS_ESCAPED_BY=''` | CSV | 指定字段的转义符,默认为 `\`。 | -| `FIELDS_DEFINED_NULL_BY=''` | CSV | 指定字段为何值时将会被解析为 NULL,默认为 `\N`。 | -| `LINES_TERMINATED_BY=''` | CSV | 指定行分隔符,默认 `IMPORT INTO` 会自动识别分隔符为 `\n`、`\r` 或 `\r\n`,如果行分隔符为以上三种,无须显式指定该选项。 | -| `SKIP_ROWS=` | CSV | 指定需要跳过的行数,默认为 `0`。可通过该参数跳过 CSV 中的 header,如果是通过通配符来指定所需导入的源文件,该参数会对 fileLocation 中通配符匹配的所有源文件生效。 | -| `SPLIT_FILE` | CSV | 将单个 CSV 文件拆分为多个 256 MiB 左右的小文件块进行并行处理,以提高导入效率。该参数仅对**非**压缩的 CSV 文件生效,且该参数和 TiDB Lightning 的 [`strict-format`](/tidb-lightning/tidb-lightning-data-source.md#启用严格格式) 有相同的使用限制。注意,你需要为该选项显式指定 `LINES_TERMINATED_BY`。| -| `DISK_QUOTA=''` | 所有文件格式 | 指定数据排序期间可使用的磁盘空间阈值。默认值为 TiDB [临时目录](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入)所在磁盘空间的 80%。如果无法获取磁盘总大小,默认值为 50 GiB。当显式指定 `DISK_QUOTA` 时,该值同样不能超过 TiDB [临时目录](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入)所在磁盘空间的 80%。 | -| `DISABLE_TIKV_IMPORT_MODE` | 所有文件格式 | 指定是否禁止导入期间将 TiKV 切换到导入模式。默认不禁止。如果当前集群存在正在运行的读写业务,为避免导入过程对这部分业务造成影响,可开启该参数。 | -| `THREAD=` | 所有文件格式、`SELECT` 语句的查询结果 | 指定导入的并发度。对于 `IMPORT INTO ... FROM FILE`,`THREAD` 默认值为 TiDB 节点的 CPU 核数的 50%,最小值为 `1`,最大值为 CPU 核数;对于 `IMPORT INTO ... FROM SELECT`,`THREAD` 默认值为 `2`,最小值为 `1`,最大值为 TiDB 节点的 CPU 核数的 2 倍。如需导入数据到一个空集群,建议可以适当调大该值,以提升导入性能。如果目标集群已经用于生产环境,请根据业务要求按需调整该参数值。 | -| `MAX_WRITE_SPEED=''` | 所有文件格式 | 控制写入到单个 TiKV 的速度,默认无速度限制。例如设置为 `1MiB`,则限制写入速度为 1 MiB/s。| -| `CHECKSUM_TABLE=''` | 所有文件格式 | 配置是否在导入完成后对目标表是否执行 CHECKSUM 检查来验证导入的完整性。可选的配置项为 `"required"`(默认)、`"optional"` 和 `"off"`。`"required"` 表示在导入完成后执行 CHECKSUM 检查,如果 CHECKSUM 检查失败,则会报错退出。`"optional"` 表示在导入完成后执行 CHECKSUM 检查,如果报错,会输出一条警告日志并忽略报错。`"off"` 表示导入结束后不执行 CHECKSUM 检查。 | -| `DETACHED` | 所有文件格式 | 该参数用于控制 `IMPORT INTO` 是否异步执行。开启该参数后,执行 `IMPORT INTO` 会立即返回该导入任务的 `Job_ID` 等信息,且该任务会在后台异步执行。 | -| `CLOUD_STORAGE_URI` | 所有文件格式 | 指定编码后的 KV 数据[全局排序](/tidb-global-sort.md)的目标存储地址。未指定该参数时,`IMPORT INTO` 会根据系统变量 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-从-v740-版本开始引入) 的值来确定是否使用全局排序,如果该系统变量指定了目标存储地址,就使用指定的地址进行全局排序。当指定该参数时,如果参数值不为空,`IMPORT INTO` 会使用该参数值作为目标存储地址;如果参数值为空,则表示强制使用本地排序。目前目标存储地址仅支持 Amazon S3,具体 Amazon S3 URI 格式配置,请参见 [Amazon S3 URI 格式](/external-storage-uri.md#amazon-s3-uri-格式)。注意当使用该功能时,所有 TiDB 节点都需要有目标 Amazon S3 bucket 的读写权限,至少包括 `s3:ListBucket`、`s3:GetObject`、`s3:DeleteObject`、`s3:PutObject`、`s3:AbortMultipartUpload`。 | -| `DISABLE_PRECHECK` | 所有文件格式、`SELECT` 语句的查询结果 | 设置该选项后会关闭非 critical 的前置检查项,如检查是否存在 CDC 或 PITR 等任务。 | - -## `IMPORT INTO ... FROM FILE` 使用说明 - -`IMPORT INTO ... FROM FILE` 支持导入存储在 Amazon S3、GCS 和 TiDB 本地的数据文件。 - -- 对于存储在 S3 或 GCS 的数据文件,`IMPORT INTO ... FROM FILE` 支持通过 [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md)运行。 - - - 当此框架功能开启时(即 [tidb_enable_dist_task](/system-variables.md#tidb_enable_dist_task-从-v710-版本开始引入) 为 `ON`),`IMPORT INTO` 会将一个数据导入任务拆分成多个子任务并分配到各个 TiDB 节点上运行,以提高导入效率。 - - 当此框架功能关闭时,`IMPORT INTO ... FROM FILE` 仅支持在当前用户连接的 TiDB 节点上运行。 - -- 对于存储在 TiDB 本地的数据文件,`IMPORT INTO ... FROM FILE` 仅支持在当前用户连接的 TiDB 节点上运行,因此数据文件需要存放在当前用户连接的 TiDB 节点上。如果是通过 PROXY 或者 Load Balancer 访问 TiDB,则无法导入存储在 TiDB 本地的数据文件。 +| `CHARACTER_SET=''` | CSV | 指定数据文件的字符集。默认字符集为 `utf8mb4`。支持的字符集包括 `binary`、`utf8`、`utf8mb4`、`gb18030`、`gbk`、`latin1` 和 `ascii`。 | +| `FIELDS_TERMINATED_BY=''` | CSV | 指定字段分隔符。默认分隔符为 `,`。 | +| `FIELDS_ENCLOSED_BY=''` | CSV | 指定字段定界符。默认定界符为 `"`。 | +| `FIELDS_ESCAPED_BY=''` | CSV | 指定字段转义字符。默认转义字符为 `\`。 | +| `FIELDS_DEFINED_NULL_BY=''` | CSV | 指定字段中表示 `NULL` 的值。默认值为 `\N`。 | +| `LINES_TERMINATED_BY=''` | CSV | 指定行终止符。默认情况下,`IMPORT INTO` 自动识别 `\n`、`\r` 或 `\r\n` 作为行终止符。如果行终止符是这三个之一,则不需要显式指定此选项。 | +| `SKIP_ROWS=` | CSV | 指定要跳过的行数。默认值为 `0`。你可以使用此选项跳过 CSV 文件中的标题。如果你使用通配符指定导入的源文件,此选项适用于 `fileLocation` 中通配符匹配的所有源文件。 | +| `SPLIT_FILE` | CSV | 将单个 CSV 文件拆分为多个大约 256 MiB 的小块进行并行处理,以提高导入效率。此参数仅适用于**未压缩**的 CSV 文件,并且具有与 TiDB Lightning [`strict-format`](https://docs.pingcap.com/tidb/stable/tidb-lightning-data-source#strict-format) 相同的使用限制。注意,对于此选项,你需要显式指定 `LINES_TERMINATED_BY`。 | +| `DISK_QUOTA=''` | 所有文件格式 | 指定数据排序期间可以使用的磁盘空间阈值。默认值为 TiDB [临时目录](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630)中磁盘空间的 80%。如果无法获取总磁盘大小,默认值为 50 GiB。显式指定 `DISK_QUOTA` 时,确保该值不超过 TiDB 临时目录中磁盘空间的 80%。 | +| `DISABLE_TIKV_IMPORT_MODE` | 所有文件格式 | 指定是否在导入过程中禁用将 TiKV 切换到导入模式。默认情况下,不禁用将 TiKV 切换到导入模式。如果集群中有正在进行的读写操作,你可以启用此选项以避免导入过程的影响。 | +| `THREAD=` | 所有文件格式和 `SELECT` 的查询结果 | 指定导入的并发度。对于 `IMPORT INTO ... FROM FILE`,`THREAD` 的默认值是 TiDB 节点 CPU 核数的 50%,最小值为 `1`,最大值为 CPU 核数。对于 `IMPORT INTO ... FROM SELECT`,`THREAD` 的默认值为 `2`,最小值为 `1`,最大值为 TiDB 节点 CPU 核数的两倍。要将数据导入到没有任何数据的新集群中,建议适当增加此并发度以提高导入性能。如果目标集群已在生产环境中使用,建议根据应用程序要求调整此并发度。 | +| `MAX_WRITE_SPEED=''` | 所有文件格式 | 控制对 TiKV 节点的写入速度。默认情况下,没有速度限制。例如,你可以将此选项指定为 `1MiB` 以将写入速度限制为 1 MiB/s。 | +| `CHECKSUM_TABLE=''` | 所有文件格式 | 配置是否在导入后对目标表执行校验和检查以验证导入完整性。支持的值包括 `"required"`(默认)、`"optional"` 和 `"off"`。`"required"` 表示在导入后执行校验和检查。如果校验和检查失败,TiDB 将返回错误并退出导入。`"optional"` 表示在导入后执行校验和检查。如果发生错误,TiDB 将返回警告并忽略错误。`"off"` 表示在导入后不执行校验和检查。 | +| `DETACHED` | 所有文件格式 | 控制是否异步执行 `IMPORT INTO`。启用此选项时,执行 `IMPORT INTO` 会立即返回导入作业的信息(如 `Job_ID`),作业在后台异步执行。 | +| `CLOUD_STORAGE_URI` | 所有文件格式 | 指定用于存储[全局排序](/tidb-global-sort.md)编码 KV 数据的目标地址。当未指定 `CLOUD_STORAGE_URI` 时,`IMPORT INTO` 根据系统变量 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740) 的值决定是否使用全局排序。如果该系统变量指定了目标存储地址,`IMPORT INTO` 使用该地址进行全局排序。当指定了非空的 `CLOUD_STORAGE_URI` 时,`IMPORT INTO` 使用该值作为目标存储地址。当指定了空的 `CLOUD_STORAGE_URI` 时,强制使用本地排序。目前,目标存储地址仅支持 S3。有关 URI 配置的详细信息,请参见 [Amazon S3 URI 格式](/external-storage-uri.md#amazon-s3-uri-format)。使用此功能时,所有 TiDB 节点必须具有目标 S3 存储桶的读写访问权限,至少包括以下权限:`s3:ListBucket`、`s3:GetObject`、`s3:DeleteObject`、`s3:PutObject`、`s3: AbortMultipartUpload`。 | +| `DISABLE_PRECHECK` | 所有文件格式和 `SELECT` 的查询结果 | 设置此选项将禁用非关键项目的预检查,例如检查是否存在 CDC 或 PITR 任务。 | +## `IMPORT INTO ... FROM FILE` 使用方法 + +对于 TiDB Self-Managed,`IMPORT INTO ... FROM FILE` 支持从存储在 Amazon S3、GCS 和 TiDB 本地存储中的文件导入数据。对于 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated),`IMPORT INTO ... FROM FILE` 支持从存储在 Amazon S3 和 GCS 中的文件导入数据。对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless),`IMPORT INTO ... FROM FILE` 支持从存储在 Amazon S3 和阿里云 OSS 中的文件导入数据。 + +- 对于存储在 Amazon S3 或 GCS 中的数据文件,`IMPORT INTO ... FROM FILE` 支持在 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) 中运行。 + + - 当启用 DXF([tidb_enable_dist_task](/system-variables.md#tidb_enable_dist_task-new-in-v710) 为 `ON`)时,`IMPORT INTO` 将数据导入作业拆分为多个子作业,并将这些子作业分配给不同的 TiDB 节点执行,以提高导入效率。 + - 当禁用 DXF 时,`IMPORT INTO ... FROM FILE` 只支持在当前用户连接的 TiDB 节点上运行。 + +- 对于存储在 TiDB 本地的数据文件,`IMPORT INTO ... FROM FILE` 只支持在当前用户连接的 TiDB 节点上运行。因此,数据文件需要放置在当前用户连接的 TiDB 节点上。如果你通过代理或负载均衡器访问 TiDB,则无法导入存储在 TiDB 本地的数据文件。 ### 压缩文件 -`IMPORT INTO ... FROM FILE` 支持导入压缩的 `CSV` 和 `SQL` 文件,会自动根据数据文件后缀来确定该文件是否为压缩文件以及压缩格式: +`IMPORT INTO ... FROM FILE` 支持导入压缩的 `CSV` 和 `SQL` 文件。它可以根据文件扩展名自动判断文件是否压缩以及压缩格式: -| 后缀名 | 压缩格式 | +| 扩展名 | 压缩格式 | |:---|:---| | `.gz`、`.gzip` | gzip 压缩格式 | | `.zstd`、`.zst` | ZStd 压缩格式 | @@ -177,22 +178,26 @@ SET 表达式左侧只能引用 `ColumnNameOrUserVarList` 中没有的列名。 > **注意:** > -> - Snappy 压缩文件必须遵循[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他非官方压缩格式。 -> - 由于无法对单个大压缩文件进行并发解压,因此压缩文件的大小会直接影响导入速度。建议解压后的文件大小不要超过 256 MiB。 +> - Snappy 压缩文件必须采用[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他变体的 Snappy 压缩。 +> - 由于 TiDB Lightning 无法并发解压单个大型压缩文件,压缩文件的大小会影响导入速度。建议源文件解压后不要超过 256 MiB。 ### 全局排序 -`IMPORT INTO ... FROM FILE` 会将源数据文件的导入拆分到多个子任务中,各个子任务独立进行编码排序并导入。如果各个子任务编码后的 KV (TiDB 将数据编码为 KV 的方式,参考 [TiDB 数据库的计算](/tidb-computing.md)) range 重叠过多,导入时 TiKV 需要不断地进行 compaction,会降低导入的性能和稳定性。 +> **注意:** +> +> 全局排序在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +`IMPORT INTO ... FROM FILE` 将源数据文件的数据导入作业拆分为多个子作业,每个子作业独立编码和排序数据后再导入。如果这些子作业的编码 KV 范围有显著重叠(要了解 TiDB 如何将数据编码为 KV,请参见 [TiDB 计算](/tidb-computing.md)),TiKV 需要在导入期间持续进行 compaction,导致导入性能和稳定性下降。 -在以下情况中,可能存在较多的 KV range 重叠: +在以下场景中,KV 范围可能会有显著重叠: -- 如果分配到各子任务的数据文件中的行存在主键范围的重叠,那么各个子任务编码后产生的数据 KV 也会存在重叠。 - - 说明:`IMPORT INTO` 会按数据文件遍历顺序来划分子任务,一般遍历文件按文件名字典序来排列。 -- 如果目标表索引较多,或索引列值在数据文件中较分散,那么各个子任务编码后产生的索引 KV 也会存在重叠。 +- 如果分配给每个子作业的数据文件中的行具有重叠的主键范围,则每个子作业编码生成的数据 KV 也会重叠。 + - `IMPORT INTO` 根据数据文件的遍历顺序拆分子作业,通常按文件名的字典序排序。 +- 如果目标表有很多索引,或者索引列的值在数据文件中分散,则每个子作业编码生成的索引 KV 也会重叠。 -当开启 [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md)时,可通过 `IMPORT INTO` 的 `CLOUD_STORAGE_URI` 参数,或者使用系统变量 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-从-v740-版本开始引入) 指定编码后的 KV 数据的目标存储地址来开启[全局排序](/tidb-global-sort.md)。全局排序目前支持使用 Amazon S3 作为全局排序存储地址。开启全局排序后,`IMPORT INTO` 会将编码后的 KV 数据写入云存储,并在云存储进行全局排序,之后再将全局排序后的索引数据和表数据并行导入到 TiKV,从而避免因 KV 重叠导致的问题,以提升导入的稳定性和性能。 +当启用 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) 时,你可以通过在 `IMPORT INTO` 语句中指定 `CLOUD_STORAGE_URI` 选项或使用系统变量 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740) 指定编码 KV 数据的目标存储地址来启用[全局排序](/tidb-global-sort.md)。目前,全局排序支持使用 Amazon S3 作为存储地址。启用全局排序后,`IMPORT INTO` 将编码的 KV 数据写入云存储,在云存储中执行全局排序,然后并行将全局排序后的索引和表数据导入到 TiKV。这可以防止由 KV 重叠引起的问题,并提高导入稳定性和性能。 -全局排序对内存资源的使用较高,在数据导入开始前,建议先设置 [`tidb_server_memory_limit_gc_trigger`](/system-variables.md#tidb_server_memory_limit_gc_trigger-从-v640-版本开始引入) 和 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 两个变量,避免频繁触发 golang GC 从而影响导入效率: +全局排序会消耗大量内存资源。在数据导入之前,建议配置 [`tidb_server_memory_limit_gc_trigger`](/system-variables.md#tidb_server_memory_limit_gc_trigger-new-in-v640) 和 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-new-in-v640) 变量,这可以避免 golang GC 频繁触发从而影响导入效率。 ```sql SET GLOBAL tidb_server_memory_limit_gc_trigger=1; @@ -201,14 +206,13 @@ SET GLOBAL tidb_server_memory_limit='75%'; > **注意:** > -> - 如果源数据文件 KV range 重叠较少,开启全局排序后可能会降低导入性能,因为全局排序需要等所有子任务的数据本地排序后,再进行额外的全局排序操作,之后才进行导入。 -> - 使用全局排序的导入任务完成后,存放在云存储里用于全局排序的文件会在后台线程中异步清理。 +> - 如果源数据文件中的 KV 范围重叠较低,启用全局排序可能会降低导入性能。这是因为启用全局排序后,TiDB 需要等待所有子作业完成本地排序后才能进行全局排序操作和后续导入。 +> - 使用全局排序的导入作业完成后,用于全局排序的云存储中的文件会在后台线程中异步清理。 +### 输出 -### 输出内容 +当 `IMPORT INTO ... FROM FILE` 完成导入或启用 `DETACHED` 模式时,TiDB 在输出中返回当前作业信息,如以下示例所示。有关每个字段的说明,请参见 [`SHOW IMPORT JOB(s)`](/sql-statements/sql-statement-show-import-job.md)。 -当 `IMPORT INTO ... FROM FILE` 导入完成,或者开启了 `DETACHED` 模式时,TiDB 会返回当前任务的信息。以下为一些示例,字段的含义描述请参考 [`SHOW IMPORT JOB(s)`](/sql-statements/sql-statement-show-import-job.md)。 - -当 `IMPORT INTO ... FROM FILE` 导入完成时输出: +当 `IMPORT INTO ... FROM FILE` 完成导入时,示例输出如下: ```sql IMPORT INTO t FROM '/path/to/small.csv'; @@ -219,7 +223,7 @@ IMPORT INTO t FROM '/path/to/small.csv'; +--------+--------------------+--------------+----------+-------+----------+------------------+---------------+----------------+----------------------------+----------------------------+----------------------------+------------+ ``` -开启了 `DETACHED` 模式时,执行 `IMPORT INTO ... FROM FILE` 语句会立即返回输出。从输出中,你可以看到该任务状态 `Status` 为 `pending`,表示等待执行。 +当启用 `DETACHED` 模式时,执行 `IMPORT INTO ... FROM FILE` 语句将立即在输出中返回作业信息。从输出中可以看到,作业的状态为 `pending`,表示等待执行。 ```sql IMPORT INTO t FROM '/path/to/small.csv' WITH DETACHED; @@ -230,29 +234,29 @@ IMPORT INTO t FROM '/path/to/small.csv' WITH DETACHED; +--------+--------------------+--------------+----------+-------+---------+------------------+---------------+----------------+----------------------------+------------+----------+------------+ ``` -### 查看和控制导入任务 +### 查看和管理导入作业 -对于开启了 `DETACHED` 模式的任务,可通过 [`SHOW IMPORT`](/sql-statements/sql-statement-show-import-job.md) 来查看当前任务的执行进度。 +对于启用了 `DETACHED` 模式的导入作业,你可以使用 [`SHOW IMPORT`](/sql-statements/sql-statement-show-import-job.md) 查看其当前作业进度。 -任务启动后,可通过 [`CANCEL IMPORT JOB `](/sql-statements/sql-statement-cancel-import-job.md) 来取消对应任务。 +在导入作业启动后,你可以使用 [`CANCEL IMPORT JOB `](/sql-statements/sql-statement-cancel-import-job.md) 取消它。 -### 使用示例 +### 示例 -#### 导入带有 header 的 CSV 文件 +#### 导入带有标题的 CSV 文件 ```sql IMPORT INTO t FROM '/path/to/file.csv' WITH skip_rows=1; ``` -#### 以 `DETACHED` 模式异步导入 +#### 在 `DETACHED` 模式下异步导入文件 ```sql IMPORT INTO t FROM '/path/to/file.csv' WITH DETACHED; ``` -#### 忽略数据文件中的特定字段 +#### 跳过导入数据文件中的特定字段 -假设数据文件为以下 CSV 文件: +假设你的数据文件是 CSV 格式,其内容如下: ``` id,name,age @@ -260,7 +264,7 @@ id,name,age 2,Jack,44 ``` -假设要导入的目标表结构为 `CREATE TABLE t(id int primary key, name varchar(100))`,则可通过以下方式来忽略导入文件中的 `age` 字段: +并且假设导入的目标表架构为 `CREATE TABLE t(id int primary key, name varchar(100))`。要跳过导入数据文件中的 `age` 字段到表 `t`,你可以执行以下 SQL 语句: ```sql IMPORT INTO t(id, name, @1) FROM '/path/to/file.csv' WITH skip_rows=1; @@ -268,37 +272,37 @@ IMPORT INTO t(id, name, @1) FROM '/path/to/file.csv' WITH skip_rows=1; #### 使用通配符导入多个数据文件 -假设在 `/path/to/` 目录下有 `file-01.csv`、`file-02.csv` 和 `file-03.csv` 三个文件,如需通过 `IMPORT INTO` 将这三个文件导入到目标表 `t` 中,可使用如下 SQL 语句: +假设在 `/path/to/` 目录下有三个文件,名为 `file-01.csv`、`file-02.csv` 和 `file-03.csv`。要使用 `IMPORT INTO` 将这三个文件导入到目标表 `t`,你可以执行以下 SQL 语句: ```sql IMPORT INTO t FROM '/path/to/file-*.csv'; ``` -如果只需要将 `file-01.csv` 和 `file-03.csv` 导入到目标表,可以使用如下 SQL 语句: +如果你只需要将 `file-01.csv` 和 `file-03.csv` 导入到目标表,执行以下 SQL 语句: ```sql IMPORT INTO t FROM '/path/to/file-0[13].csv'; ``` -#### 从 S3 或 GCS 导入数据 +#### 从 Amazon S3 或 GCS 导入数据文件 -- 从 S3 导入数据 +- 从 Amazon S3 导入数据文件: ```sql IMPORT INTO t FROM 's3://bucket-name/test.csv?access-key=XXX&secret-access-key=XXX'; ``` -- 从 GCS 导入数据 +- 从 GCS 导入数据文件: ```sql IMPORT INTO t FROM 'gs://import/test.csv?credentials-file=${credentials-file-path}'; ``` -关于 Amazon S3 或 GCS 的 URI 路径配置,详见[外部存储服务的 URI 格式](/external-storage-uri.md)。 +有关 Amazon S3 或 GCS 的 URI 路径配置详情,请参见[外部存储服务的 URI 格式](/external-storage-uri.md)。 -#### 通过 SetClause 语句计算列值 +#### 使用 SetClause 计算列值 -假设数据文件为以下 CSV 文件: +假设你的数据文件是 CSV 格式,其内容如下: ``` id,name,val @@ -306,7 +310,7 @@ id,name,val 2,book,440 ``` -要导入的目标表结构为 `CREATE TABLE t(id int primary key, name varchar(100), val int)`,并且希望在导入时将 `val` 列值扩大 100 倍,则可通过以下方式来导入: +并且假设导入的目标表架构为 `CREATE TABLE t(id int primary key, name varchar(100), val int)`。如果你想在导入过程中将 `val` 列的值乘以 100,你可以执行以下 SQL 语句: ```sql IMPORT INTO t(id, name, @1) SET val=@1*100 FROM '/path/to/file.csv' WITH skip_rows=1; @@ -318,41 +322,41 @@ IMPORT INTO t(id, name, @1) SET val=@1*100 FROM '/path/to/file.csv' WITH skip_ro IMPORT INTO t FROM '/path/to/file.sql' FORMAT 'sql'; ``` -#### 限制写入 TiKV 的速度 +#### 限制对 TiKV 的写入速度 -限制写入单个 TiKV 的速度为 10 MiB/s: +要将对 TiKV 节点的写入速度限制为 10 MiB/s,执行以下 SQL 语句: ```sql IMPORT INTO t FROM 's3://bucket/path/to/file.parquet?access-key=XXX&secret-access-key=XXX' FORMAT 'parquet' WITH MAX_WRITE_SPEED='10MiB'; ``` -## `IMPORT INTO ... FROM SELECT` 使用说明 +## `IMPORT INTO ... FROM SELECT` 使用方法 -`IMPORT INTO ... FROM SELECT` 支持将 `SELECT` 语句的查询结果导入到 TiDB 的一张空表中,也支持导入使用 [`AS OF TIMESTAMP`](/as-of-timestamp.md) 查询的历史数据。 +`IMPORT INTO ... FROM SELECT` 允许你将 `SELECT` 语句的查询结果导入到 TiDB 的空表中。你还可以使用它导入通过 [`AS OF TIMESTAMP`](/as-of-timestamp.md) 查询的历史数据。 -### 导入 SELECT 语句的查询结果 +### 导入 `SELECT` 的查询结果 -导入 `UNION` 结果到目标表 `t`,指定导入的并发度为 `8`,并且关闭非 critical 的 precheck 项: +要将 `UNION` 结果导入到目标表 `t`,并指定导入并发度为 `8`,配置禁用非关键项目的预检查,执行以下 SQL 语句: -``` +```sql IMPORT INTO t FROM SELECT * FROM src UNION SELECT * FROM src2 WITH THREAD = 8, DISABLE_PRECHECK; ``` ### 导入指定时间点的历史数据 -导入指定时间点的历史数据到目标表 `t`: +要将指定时间点的历史数据导入到目标表 `t`,执行以下 SQL 语句: -``` +```sql IMPORT INTO t FROM SELECT * FROM src AS OF TIMESTAMP '2024-02-27 11:38:00'; ``` ## MySQL 兼容性 -该语句是对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 * [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) * [`CANCEL IMPORT JOB`](/sql-statements/sql-statement-cancel-import-job.md) * [`SHOW IMPORT JOB(s)`](/sql-statements/sql-statement-show-import-job.md) -* [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md) +* [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) diff --git a/sql-statements/sql-statement-insert.md b/sql-statements/sql-statement-insert.md index 885826274f4a..34953ebeb322 100644 --- a/sql-statements/sql-statement-insert.md +++ b/sql-statements/sql-statement-insert.md @@ -1,11 +1,11 @@ --- -title: INSERT -summary: TiDB 数据库中 INSERT 的使用概况。 +title: INSERT | TiDB SQL 语句参考 +summary: TiDB 数据库中 INSERT 的使用概述。 --- # INSERT -使用 `INSERT` 语句在表中插入新行。 +此语句用于向表中插入新行。 ## 语法图 @@ -43,68 +43,28 @@ OnDuplicateKeyUpdate ::= > **注意:** > -> TiDB 从 v6.6.0 版本开始支持[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)功能。该功能可以将不同优先级的语句放在不同的资源组中执行,并为这些资源组分配不同的配额和优先级,可以达到更好的资源管控效果。在开启资源管控功能后,语句的调度主要受资源组的控制,`PriorityOpt` 将不再生效。建议在支持资源管控的版本优先使用资源管控功能。 +> 从 v6.6.0 开始,TiDB 支持[资源控制](/tidb-resource-control.md)。你可以使用此功能在不同的资源组中以不同的优先级执行 SQL 语句。通过为这些资源组配置适当的配额和优先级,你可以更好地控制不同优先级 SQL 语句的调度。当启用资源控制时,语句优先级(`PriorityOpt`)将不再生效。建议你使用[资源控制](/tidb-resource-control.md)来管理不同 SQL 语句的资源使用。 ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a INT); -``` - -``` +mysql> CREATE TABLE t1 (a INT); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} -```sql -CREATE TABLE t2 LIKE t1; -``` - -``` +mysql> CREATE TABLE t2 LIKE t1; Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (1); -``` -``` +mysql> INSERT INTO t1 VALUES (1); Query OK, 1 row affected (0.02 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (a) VALUES (1); -``` - -``` +mysql> INSERT INTO t1 (a) VALUES (1); Query OK, 1 row affected (0.01 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t2 SELECT * FROM t1; -``` -``` +mysql> INSERT INTO t2 SELECT * FROM t1; Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +------+ | a | +------+ @@ -112,15 +72,8 @@ SELECT * FROM t1; | 1 | +------+ 2 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t2; -``` -``` +mysql> SELECT * FROM t2; +------+ | a | +------+ @@ -128,26 +81,12 @@ SELECT * FROM t2; | 1 | +------+ 2 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t2 VALUES (2),(3),(4); -``` - -``` +mysql> INSERT INTO t2 VALUES (2),(3),(4); Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t2; -``` -``` +mysql> SELECT * FROM t2; +------+ | a | +------+ @@ -162,7 +101,7 @@ SELECT * FROM t2; ## MySQL 兼容性 -`INSERT` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `INSERT` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-kill.md b/sql-statements/sql-statement-kill.md index 1678cfda9498..eeebb9e28bc4 100644 --- a/sql-statements/sql-statement-kill.md +++ b/sql-statements/sql-statement-kill.md @@ -1,13 +1,13 @@ --- title: KILL -summary: TiDB 数据库中 KILL 的使用概况。 +summary: TiDB 数据库中 KILL 的使用概述。 --- # KILL -`KILL` 语句可以终止当前 TiDB 集群中任意一个 TiDB 实例中的某个连接,从 v6.2.0 开始,`KILL` 语句也可以终止正在执行中的 DDL 作业。 +`KILL` 语句用于终止当前 TiDB 集群中任何 TiDB 实例的连接。从 TiDB v6.2.0 开始,你还可以使用 `KILL` 语句终止正在进行的 DDL 作业。 -## 语法图 +## 语法概要 ```ebnf+diagram KillStmt ::= 'KILL' 'TIDB'? ( 'CONNECTION' | 'QUERY' )? CONNECTION_ID @@ -15,7 +15,7 @@ KillStmt ::= 'KILL' 'TIDB'? ( 'CONNECTION' | 'QUERY' )? CONNECTION_ID ## 示例 -查询当前集群中所有活跃查询,并终止其中某一个连接: +以下示例展示如何获取当前集群中所有活跃查询并终止其中任意一个。 {{< copyable "sql" >}} @@ -45,26 +45,46 @@ Query OK, 0 rows affected (0.00 sec) ## MySQL 兼容性 -- MySQL 的 `KILL` 语句仅能终止当前连接的 MySQL 实例上的连接,TiDB 的 `KILL` 语句能终止整个集群中任意一个 TiDB 实例上的连接。 -- v7.2.0 及之前的版本不支持使用 MySQL 命令行 Control+C 终止查询或连接。 +- MySQL 的 `KILL` 语句只能终止当前连接的 MySQL 实例中的连接,而 TiDB 的 `KILL` 语句可以终止整个集群中任何 TiDB 实例的连接。 +- 在 v7.2.0 及更早版本中,不支持使用 MySQL 命令行的 Control+C 来终止 TiDB 中的查询或连接。 ## 行为变更说明 -TiDB 从 v7.3.0 起支持生成 32 位 connection ID(由 [`enable-32bits-connection-id`](/tidb-configuration-file.md#enable-32bits-connection-id-从-v730-版本开始引入) 配置项控制,默认启用)。同时启用 Global Kill 功能和 32 位 connection ID 后,TiDB 将生成 32 位的 connection ID,从而支持在 MySQL 命令行中通过 Control+C 终止查询或连接。 + -> **注意:** +从 v7.3.0 开始,TiDB 支持生成 32 位连接 ID,默认启用,由配置项 [`enable-32bits-connection-id`](/tidb-configuration-file.md#enable-32bits-connection-id-new-in-v730) 控制。当 Global Kill 功能和 32 位连接 ID 都启用时,TiDB 生成 32 位连接 ID,你可以在 MySQL 命令行中使用 Control+C 终止查询或连接。 + +> **警告:** > -> 当集群中 TiDB 实例数量超过 2048 或者单个 TiDB 实例的同时连接数超过 1048576 时,由于 32 位 connection ID 空间不足,将自动升级为 64 位 connection ID。该升级过程不影响业务和已建立的连接,但后续的新建连接将无法通过 MySQL 命令行 Control+C 终止。 +> 当集群中 TiDB 实例数量超过 2048 个或单个 TiDB 实例并发连接数超过 1048576 时,32 位连接 ID 空间不足,会自动升级为 64 位连接 ID。升级过程中,现有业务和已建立的连接不受影响。但是,后续新建的连接将无法在 MySQL 命令行中使用 Control+C 终止。 + +从 v6.1.0 开始,TiDB 支持 Global Kill 功能,默认启用,由配置项 [`enable-global-kill`](/tidb-configuration-file.md#enable-global-kill-new-in-v610) 控制。 + + + + + +从 v7.3.0 开始,TiDB 支持生成 32 位连接 ID,默认启用。当 Global Kill 功能和 32 位连接 ID 都启用时,你可以在 MySQL 命令行中使用 Control+C 终止查询或连接。 + +从 v6.1.0 开始,TiDB 支持 Global Kill 功能,默认启用。 + + + +当启用 Global Kill 功能时,`KILL` 和 `KILL TIDB` 语句都可以跨实例终止查询或连接,因此你无需担心错误终止查询或连接。当你使用客户端连接到任何 TiDB 实例并执行 `KILL` 或 `KILL TIDB` 语句时,该语句将被转发到目标 TiDB 实例。如果客户端和 TiDB 集群之间有代理,`KILL` 和 `KILL TIDB` 语句也会被转发到目标 TiDB 实例执行。 + +如果未启用 Global Kill 功能或你使用的 TiDB 版本早于 v6.1.0,请注意以下事项: + +- 默认情况下,`KILL` 与 MySQL 不兼容。这有助于防止连接被错误的 TiDB 服务器终止,因为通常会在负载均衡器后面放置多个 TiDB 服务器。要终止当前连接的 TiDB 实例上的其他连接,你需要通过执行 `KILL TIDB` 语句显式添加 `TIDB` 后缀。 + + -TiDB 从 v6.1.0 起新增 Global Kill 功能(由 [`enable-global-kill`](/tidb-configuration-file.md#enable-global-kill-从-v610-版本开始引入) 配置项控制,默认启用)。启用 Global Kill 功能时,`KILL` 语句和 `KILL TIDB` 语句均能跨节点终止查询或连接,且无需担心错误地终止其他查询或连接。当你使用客户端连接到任何一个 TiDB 节点执行 `KILL` 语句或 `KILL TIDB` 语句时,该语句会被转发给对应的 TiDB 节点。当客户端和 TiDB 中间有代理时,`KILL` 及 `KILL TIDB` 语句也会被转发给对应的 TiDB 节点执行。 +- **强烈不建议**在配置文件中设置 [`compatible-kill-query = true`](/tidb-configuration-file.md#compatible-kill-query),除非你确定客户端将始终连接到同一个 TiDB 实例。这是因为在默认 MySQL 客户端中按 Control+C 会打开一个新连接来执行 `KILL`。如果客户端和 TiDB 集群之间有代理,新连接可能会被路由到不同的 TiDB 实例,这可能会错误地终止不同的会话。 -对于 TiDB v6.1.0 之前的版本,或未启用 Global Kill 功能时: + -- `KILL` 语句与 MySQL 不兼容,负载均衡器后面通常放有多个 TiDB 服务器,这种不兼容有助于防止在错误的 TiDB 服务器上终止连接。你需要显式地增加 `TIDB` 后缀,通过执行 `KILL TIDB` 语句来终止当前连接的 TiDB 实例上的其他连接。 -- **强烈不建议**在配置文件里设置 [`compatible-kill-query = true`](/tidb-configuration-file.md#compatible-kill-query),**除非**你确定客户端将始终连接到同一个 TiDB 节点。这是因为当你在默认的 MySQL 客户端按下 Control+C 时,客户端会开启一个新连接,并在这个新连接中执行 `KILL` 语句。此时,如果客户端和 TiDB 中间有代理,新连接可能会被路由到其他的 TiDB 节点,从而错误地终止其他会话。 -- `KILL TIDB` 语句是 TiDB 的扩展语法,其功能与 MySQL 命令 `KILL [CONNECTION|QUERY]` 和 MySQL 命令行 Control+C 相同。在同一个 TiDB 节点上,你可以安全地使用 `KILL TIDB` 语句。 +- `KILL TIDB` 语句是 TiDB 的扩展。此语句的功能类似于 MySQL 的 `KILL [CONNECTION|QUERY]` 命令和 MySQL 命令行的 Control+C。在同一个 TiDB 实例上使用 `KILL TIDB` 是安全的。 ## 另请参阅 -- [SHOW \[FULL\] PROCESSLIST](/sql-statements/sql-statement-show-processlist.md) -- [CLUSTER_PROCESSLIST](/information-schema/information-schema-processlist.md#cluster_processlist) +* [SHOW \[FULL\] PROCESSLIST](/sql-statements/sql-statement-show-processlist.md) +* [CLUSTER_PROCESSLIST](/information-schema/information-schema-processlist.md#cluster_processlist) diff --git a/sql-statements/sql-statement-load-data.md b/sql-statements/sql-statement-load-data.md index e4eeb81ab8e5..67d0f27fe473 100644 --- a/sql-statements/sql-statement-load-data.md +++ b/sql-statements/sql-statement-load-data.md @@ -1,22 +1,30 @@ --- -title: LOAD DATA -summary: TiDB 数据库中 LOAD DATA 的使用概况。 +title: LOAD DATA | TiDB SQL 语句参考 +summary: TiDB 数据库中 LOAD DATA 的使用概览。 --- # LOAD DATA -`LOAD DATA` 语句用于将数据批量加载到 TiDB 表中。 +`LOAD DATA` 语句用于批量将数据加载到 TiDB 表中。 -在 v7.0.0 版本支持以下功能: +从 TiDB v7.0.0 开始,`LOAD DATA` SQL 语句支持以下功能: -- 支持从 S3、GCS 导入数据 -- 新增参数 `FIELDS DEFINED NULL BY` +- 支持从 S3 和 GCS 导入数据 +- 添加新参数 `FIELDS DEFINED NULL BY` > **警告:** > -> v7.0.0 新增支持从 S3、GCS 导入数据和 `FIELDS DEFINED NULL BY` 参数为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 新参数 `FIELDS DEFINED NULL BY` 以及从 S3 和 GCS 导入数据的支持是实验性功能。不建议在生产环境中使用。此功能可能会在没有预先通知的情况下发生变更或移除。如果发现 bug,你可以在 GitHub 上提交[问题](https://github.com/pingcap/tidb/issues)。 -## 语法图 + + +> **注意:** +> +> 对于 `LOAD DATA INFILE` 语句,TiDB Cloud Dedicated 支持 `LOAD DATA LOCAL INFILE` 和从 Amazon S3 或 Google Cloud Storage 导入数据的 `LOAD DATA INFILE`,而 TiDB Cloud Serverless 仅支持 `LOAD DATA LOCAL INFILE`。 + + + +## 语法 ```ebnf+diagram LoadDataStmt ::= @@ -31,67 +39,101 @@ Fields ::= | 'DEFINED' 'NULL' 'BY' stringLit ('OPTIONALLY' 'ENCLOSED')?)? ``` -## 参数说明 +## 参数 ### `LOCAL` -你可以使用 `LOCAL` 来指定导入位于客户端的数据文件,此时传入文件参数必须为客户端文件系统路径。 +你可以使用 `LOCAL` 来指定要导入的客户端上的数据文件,其中文件参数必须是客户端上的文件系统路径。 + +如果你使用 TiDB Cloud,要使用 `LOAD DATA` 语句加载本地数据文件,你需要在连接到 TiDB Cloud 时在连接字符串中添加 `--local-infile` 选项。 + +- 以下是 TiDB Cloud Serverless 的示例连接字符串: + + ``` + mysql --connect-timeout 15 -u '' -h -P 4000 -D test --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p --local-infile + ``` + +- 以下是 TiDB Cloud Dedicated 的示例连接字符串: + + ``` + mysql --connect-timeout 15 --ssl-mode=VERIFY_IDENTITY --ssl-ca= --tls-version="TLSv1.2" -u root -h -P 4000 -D test -p --local-infile + ``` -### S3/GCS 路径 +### S3 和 GCS 存储 -如果你不指定 `LOCAL`,则文件参数必须是有效的 S3/GCS URI 路径,详见[外部存储](/br/backup-and-restore-storages.md)。 + -当数据文件存储在 S3/GCS 上时,你可以导入单个文件,也可使用通配符 `*` 来匹配需要导入的多个文件。注意通配符不会递归处理子目录下相关的文件。以数据存储在 S3 为例,示例如下: +如果不指定 `LOCAL`,文件参数必须是有效的 S3 或 GCS 路径,详见[外部存储](/br/backup-and-restore-storages.md)。 + + + + + +如果不指定 `LOCAL`,文件参数必须是有效的 S3 或 GCS 路径,详见[外部存储](https://docs.pingcap.com/tidb/stable/backup-and-restore-storages)。 + + + +当数据文件存储在 S3 或 GCS 上时,你可以导入单个文件或使用通配符 `*` 匹配多个要导入的文件。注意,通配符不会递归处理子目录中的文件。以下是一些示例: - 导入单个文件:`s3:///path/to/data/foo.csv` - 导入指定路径下的所有文件:`s3:///path/to/data/*` -- 导入指定路径下的所有以 `.csv` 结尾的文件:`s3:///path/to/data/*.csv` -- 导入指定路径下所有以 `foo` 为前缀的文件:`s3:///path/to/data/foo*` -- 导入指定路径下以 `foo` 为前缀、以 `.csv` 结尾的文件:`s3:///path/to/data/foo*.csv` +- 导入指定路径下所有以 `.csv` 结尾的文件:`s3:///path/to/data/*.csv` +- 导入指定路径下所有以 `foo` 开头的文件:`s3:///path/to/data/foo*` +- 导入指定路径下所有以 `foo` 开头且以 `.csv` 结尾的文件:`s3:///path/to/data/foo*.csv` -### `Fields`、`Lines`、`Ignore Lines` +### `Fields`、`Lines` 和 `Ignore Lines` -你可以使用 `Fields` 和 `Lines` 参数来指定如何处理数据格式: +你可以使用 `Fields` 和 `Lines` 参数来指定如何处理数据格式。 -- 使用 `FIELDS TERMINATED BY` 来指定数据的分隔符号。 -- 使用 `FIELDS ENCLOSED BY` 来指定数据的包围符号。 -- 如果你希望以某个字符为结尾来切分行数据,可以使用 `LINES TERMINATED BY` 来指定行的终止符。 +- `FIELDS TERMINATED BY`:指定数据分隔符。 +- `FIELDS ENCLOSED BY`:指定数据的包围字符。 +- `LINES TERMINATED BY`:指定行终止符,如果你想用某个字符结束一行。 -可以使用 `DEFINED NULL BY` 来指定数据文件中如何表示 NULL 值。 +你可以使用 `DEFINED NULL BY` 来指定在数据文件中如何表示 NULL 值。 -- 与 MySQL 行为一致,如果 `ESCAPED BY` 不为空时,例如是默认值 `\`,那么 `\N` 会被认为是 NULL 值。 -- 如果使用 `DEFINED NULL BY`,例如 `DEFINED NULL BY 'my-null'`,`my-null` 会被认为是 NULL 值。 -- 如果使用 `DEFINED NULL BY ... OPTIONALLY ENCLOSED`,例如 `DEFINED NULL BY 'my-null' OPTIONALLY ENCLOSED`,`my-null` 和 `"my-null"`(假设 `ENCLOSED BY '"'`)会被认为是 NULL 值。 -- 如果没有使用 `DEFINED NULL BY` 或者 `DEFINED NULL BY ... OPTIONALLY ENCLOSED`,但使用了 `ENCLOSED BY`,例如 `ENCLOSED BY '"'`,那么 `NULL` 会被认为是 NULL 值。这个行为与 MySQL 一致。 -- 其他情况不会被认为是 NULL 值。 +- 与 MySQL 行为一致,如果 `ESCAPED BY` 不为空,例如使用默认值 `\`,则 `\N` 将被视为 NULL 值。 +- 如果你使用 `DEFINED NULL BY`,例如 `DEFINED NULL BY 'my-null'`,则 `my-null` 被视为 NULL 值。 +- 如果你使用 `DEFINED NULL BY ... OPTIONALLY ENCLOSED`,例如 `DEFINED NULL BY 'my-null' OPTIONALLY ENCLOSED`,则 `my-null` 和 `"my-null"`(假设 `ENCLOSED BY '"'`)被视为 NULL 值。 +- 如果你不使用 `DEFINED NULL BY` 或 `DEFINED NULL BY ... OPTIONALLY ENCLOSED`,但使用 `ENCLOSED BY`,例如 `ENCLOSED BY '"'`,则 `NULL` 被视为 NULL 值。这种行为与 MySQL 一致。 +- 在其他情况下,不被视为 NULL 值。 -例如对于以下格式的数据: +以下面的数据格式为例: ``` "bob","20","street 1"\r\n "alice","33","street 1"\r\n ``` -如果想分别提取 `bob`、`20`、`street 1`,可以指定数据的分隔符号为 `','`,数据的包围符号为 `'\"'`。可以写成: +如果你想提取 `bob`、`20` 和 `street 1`,需要指定字段分隔符为 `','`,包围字符为 `'\"'`: ```sql FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' ``` -当不指定处理数据的参数时,将按以下参数处理: +如果你不指定上述参数,导入的数据默认按以下方式处理: ```sql FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' ``` -你可以通过 `IGNORE LINES` 参数来忽略文件开始的 `` 行。例如,可以使用 `IGNORE 1 LINES` 来忽略文件的第一行。 +你可以通过配置 `IGNORE LINES` 参数来忽略文件的前 `number` 行。例如,如果你配置 `IGNORE 1 LINES`,文件的第一行将被忽略。 ## 示例 -通过 `LOAD DATA` 导入数据,指定数据的分隔符为逗号,忽略包围数据的引号,并且忽略文件的第一行数据。 +以下示例使用 `LOAD DATA` 导入数据。指定逗号为字段分隔符。包围数据的双引号被忽略。文件的第一行被忽略。 + + + +如果你看到 `ERROR 1148 (42000): the used command is not allowed with this TiDB version`,请参考 [ERROR 1148 (42000): the used command is not allowed with this TiDB version](/error-codes.md#mysql-native-error-messages) 进行故障排除。 + + + + -如果此时遇到 `ERROR 1148 (42000): the used command is not allowed with this TiDB version` 报错信息。可以参考文档解决:[ERROR 1148 (42000): the used command is not allowed with this TiDB version 问题的处理方法](/error-codes.md#mysql-原生报错汇总) +如果你看到 `ERROR 1148 (42000): the used command is not allowed with this TiDB version`,请参考 [ERROR 1148 (42000): the used command is not allowed with this TiDB version](https://docs.pingcap.com/tidb/stable/error-codes#mysql-native-error-messages) 进行故障排除。 + + ```sql LOAD DATA LOCAL INFILE '/mnt/evo970/data-sets/bikeshare-data/2017Q4-capitalbikeshare-tripdata.csv' INTO TABLE trips FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES (duration, start_date, end_date, start_station_number, start_station, end_station_number, end_station, bike_number, member_type); @@ -102,33 +144,81 @@ Query OK, 815264 rows affected (39.63 sec) Records: 815264 Deleted: 0 Skipped: 0 Warnings: 0 ``` -`LOAD DATA` 也支持使用十六进制 ASCII 字符表达式或二进制 ASCII 字符表达式作为 `FIELDS ENCLOSED BY` 和 `FIELDS TERMINATED BY` 的参数。示例如下: +`LOAD DATA` 还支持使用十六进制 ASCII 字符表达式或二进制 ASCII 字符表达式作为 `FIELDS ENCLOSED BY` 和 `FIELDS TERMINATED BY` 的参数。请参见以下示例: ```sql LOAD DATA LOCAL INFILE '/mnt/evo970/data-sets/bikeshare-data/2017Q4-capitalbikeshare-tripdata.csv' INTO TABLE trips FIELDS TERMINATED BY x'2c' ENCLOSED BY b'100010' LINES TERMINATED BY '\r\n' IGNORE 1 LINES (duration, start_date, end_date, start_station_number, start_station, end_station_number, end_station, bike_number, member_type); ``` -以上示例中 `x'2c'` 是字符 `,` 的十六进制表示,`b'100010'` 是字符 `"` 的二进制表示。 +在上面的示例中,`x'2c'` 是 `,` 字符的十六进制表示,`b'100010'` 是 `"` 字符的二进制表示。 + + + +以下示例展示如何使用 `LOAD DATA INFILE` 语句从 Amazon S3 将数据导入到 TiDB Cloud Dedicated 集群: + +```sql +LOAD DATA INFILE 's3:///your-file.csv?role_arn=<你为 TiDB Cloud 导入创建的 IAM 角色的 ARN>&external_id=' +INTO TABLE . +FIELDS TERMINATED BY ',' +ENCLOSED BY '"' +LINES TERMINATED BY '\n' +IGNORE 1 LINES; +``` + + ## MySQL 兼容性 -TiDB 中的 `LOAD DATA` 语句语法上兼容 MySQL(除字符集选项被解析但会被忽略以外)。若发现任何语法兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +`LOAD DATA` 语句的语法与 MySQL 兼容,但字符集选项会被解析但忽略。如果发现任何语法兼容性差异,你可以[报告问题](https://docs.pingcap.com/tidb/stable/support)。 + + > **注意:** > -> - 在 TiDB v4.0.0 之前的版本中,`LOAD DATA` 语句每 20000 行进行一次提交。该行数不支持更改。 -> - 从 TiDB v4.0.0 开始一直到 TiDB v6.6.0 的版本,TiDB 默认在一个事务中提交所有行。如需 `LOAD DATA` 语句按照每固定的行数进行一次提交,可以设置 [`tidb_dml_batch_size`](/system-variables.md#tidb_dml_batch_size) 为所需的行数。 -> - 从 TiDB v7.0.0 起,`tidb_dml_batch_size` 对 `LOAD DATA` 语句不再生效,TiDB 将在一个事务中提交所有行。 -> - 从 TiDB v4.0.0 及以前版本升级后,可能出现 `ERROR 8004 (HY000) at line 1: Transaction is too large, size: 100000058` 错误。要解决该问题,建议调大 `tidb.toml` 文件中的 [`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit) 值。 -> - 在 TiDB v7.6.0 之前的版本中,无论以多少行为一个事务提交,`LOAD DATA` 都不会被显式事务中的 [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 语句回滚。 -> - 在 TiDB v7.6.0 之前的版本中,`LOAD DATA` 语句始终以乐观事务模式执行,不受 TiDB 事务模式设置的影响。 -> - 从 TiDB v7.6.0 开始,`LOAD DATA` 在事务中与其它普通 DML 的处理方式一致: -> - `LOAD DATA` 语句本身不会提交当前事务,也不会开启新事务。 -> - `LOAD DATA` 语句会受 TiDB 事务模式设置(乐观/悲观)影响。 -> - 事务内的 `LOAD DATA` 语句可以被事务的 [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 语句回滚。 +> - 对于 TiDB v4.0.0 之前的版本,`LOAD DATA` 每 20000 行提交一次,这个数值不可配置。 +> - 对于 TiDB v4.0.0 到 v6.6.0 的版本,TiDB 默认在一个事务中提交所有行。但如果你需要 `LOAD DATA` 语句每固定行数提交一次,你可以将 [`tidb_dml_batch_size`](/system-variables.md#tidb_dml_batch_size) 设置为所需的行数。 +> - 从 TiDB v7.0.0 开始,`tidb_dml_batch_size` 不再对 `LOAD DATA` 生效,TiDB 在一个事务中提交所有行。 +> - 从 TiDB v4.0.0 或更早版本升级后,可能会出现 `ERROR 8004 (HY000) at line 1: Transaction is too large, size: 100000058`。建议通过增加 `tidb.toml` 文件中的 [`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit) 值来解决此错误。 +> - 对于 TiDB v7.6.0 之前的版本,无论在一个事务中提交多少行,`LOAD DATA` 都不会被显式事务中的 [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 语句回滚。 +> - 对于 TiDB v7.6.0 之前的版本,`LOAD DATA` 语句始终在乐观事务模式下执行,不受 TiDB 事务模式配置的影响。 +> - 从 v7.6.0 开始,TiDB 处理事务中的 `LOAD DATA` 的方式与其他 DML 语句相同: +> - `LOAD DATA` 语句不会提交当前事务或开始新事务。 +> - `LOAD DATA` 语句受 TiDB 事务模式设置(乐观或悲观事务)的影响。 +> - 事务中的 `LOAD DATA` 语句可以被事务中的 [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 语句回滚。 + + + + + +> **注意:** +> +> - 对于 TiDB v4.0.0 之前的版本,`LOAD DATA` 每 20000 行提交一次,这个数值不可配置。 +> - 对于 TiDB v4.0.0 到 v6.6.0 的版本,TiDB 默认在一个事务中提交所有行。但如果你需要 `LOAD DATA` 语句每固定行数提交一次,你可以将 [`tidb_dml_batch_size`](/system-variables.md#tidb_dml_batch_size) 设置为所需的行数。 +> - 从 v7.0.0 开始,`tidb_dml_batch_size` 不再对 `LOAD DATA` 生效,TiDB 在一个事务中提交所有行。 +> - 从 TiDB v4.0.0 或更早版本升级后,可能会出现 `ERROR 8004 (HY000) at line 1: Transaction is too large, size: 100000058`。要解决此错误,你可以联系 [TiDB Cloud 支持团队](https://docs.pingcap.com/tidbcloud/tidb-cloud-support)以增加 [`txn-total-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-total-size-limit) 值。 +> - 对于 TiDB v7.6.0 之前的版本,无论在一个事务中提交多少行,`LOAD DATA` 都不会被显式事务中的 [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 语句回滚。 +> - 对于 TiDB v7.6.0 之前的版本,`LOAD DATA` 语句始终在乐观事务模式下执行,不受 TiDB 事务模式配置的影响。 +> - 从 v7.6.0 开始,TiDB 处理事务中的 `LOAD DATA` 的方式与其他 DML 语句相同: +> - `LOAD DATA` 语句不会提交当前事务或开始新事务。 +> - `LOAD DATA` 语句受 TiDB 事务模式设置(乐观或悲观事务)的影响。 +> - 事务中的 `LOAD DATA` 语句可以被事务中的 [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 语句回滚。 + + ## 另请参阅 + + * [INSERT](/sql-statements/sql-statement-insert.md) -* [乐观事务模型](/optimistic-transaction.md) -* [悲观事务模式](/pessimistic-transaction.md) +* [TiDB 乐观事务模型](/optimistic-transaction.md) +* [TiDB 悲观事务模式](/pessimistic-transaction.md) + + + + + +* [INSERT](/sql-statements/sql-statement-insert.md) +* [TiDB 乐观事务模型](/optimistic-transaction.md) +* [TiDB 悲观事务模式](/pessimistic-transaction.md) + + diff --git a/sql-statements/sql-statement-load-stats.md b/sql-statements/sql-statement-load-stats.md index a7371582ad50..c19e0215b005 100644 --- a/sql-statements/sql-statement-load-stats.md +++ b/sql-statements/sql-statement-load-stats.md @@ -1,12 +1,16 @@ --- title: LOAD STATS -summary: TiDB 数据库中 LOAD STATS 的使用概况。 +summary: TiDB 数据库中 LOAD STATS 的使用概览。 --- # LOAD STATS `LOAD STATS` 语句用于将统计信息加载到 TiDB 中。 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + ## 语法图 ```ebnf+diagram @@ -14,13 +18,13 @@ LoadStatsStmt ::= 'LOAD' 'STATS' stringLit ``` -## 参数说明 +## 示例 -用户直接指定统计信息文件路径,统计信息文件可通过访问 API `http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name}` 进行下载。 +你可以访问地址 `http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name}` 来下载 TiDB 实例的统计信息。 -路径可以是相对路径,也可以是绝对路径,如果是相对路径,会从启动 `tidb-server` 的路径为起点寻找对应文件。 +你也可以使用 `LOAD STATS ${stats_path}` 来加载特定的统计信息文件。 -下面是一个绝对路径的例子: +`${stats_path}` 可以是绝对路径或相对路径。如果使用相对路径,则从启动 `tidb-server` 的路径开始查找相应的文件。以下是一个示例: {{< copyable "sql" >}} @@ -38,4 +42,4 @@ Query OK, 0 rows affected (0.00 sec) ## 另请参阅 -* [常规统计信息](/statistics.md) +* [统计信息](/statistics.md) diff --git a/sql-statements/sql-statement-lock-stats.md b/sql-statements/sql-statement-lock-stats.md index 0177e1b2c452..e0a98a5abec0 100644 --- a/sql-statements/sql-statement-lock-stats.md +++ b/sql-statements/sql-statement-lock-stats.md @@ -1,11 +1,11 @@ --- title: LOCK STATS -summary: TiDB 数据库中 LOCK STATS 的使用概况。 +summary: TiDB 数据库中 LOCK STATS 的使用概述。 --- # LOCK STATS -`LOCK STATS` 语句用于锁定表或分区的统计信息,使得在锁定期间,TiDB 不会自动更新统计信息。具体行为请参见[锁定统计信息的行为说明](/statistics.md#锁定统计信息的行为说明)。 +`LOCK STATS` 用于锁定表或分区的统计信息。当统计信息被锁定时,TiDB 不会自动更新表或分区的统计信息。有关具体行为的详细信息,请参见[锁定统计信息的行为](/statistics.md#behaviors-of-locking-statistics)。 ## 语法图 @@ -25,7 +25,7 @@ PartitionNameList ::= ## 示例 -创建表 `t`,插入一些数据,在未锁定表 `t` 的统计信息的情况下成功执行 `ANALYZE` 语句。 +创建表 `t` 并向其中插入数据。当表 `t` 的统计信息未被锁定时,`ANALYZE` 语句可以成功执行。 ```sql mysql> CREATE TABLE t(a INT, b INT); @@ -47,7 +47,7 @@ mysql> SHOW WARNINGS; 1 row in set (0.00 sec) ``` -锁定表 `t` 的统计信息,执行 `ANALYZE` 语句,warning 提示跳过对表 `t` 的 `ANALYZE`。 +锁定表 `t` 的统计信息并执行 `ANALYZE`。从 `SHOW STATS_LOCKED` 的输出可以看到表 `t` 的统计信息已被锁定。警告信息显示 `ANALYZE` 语句已跳过表 `t`。 ```sql mysql> LOCK STATS t; @@ -74,9 +74,9 @@ mysql> SHOW WARNINGS; 2 rows in set (0.00 sec) ``` -另外,你也可以通过 `LOCK STATS` 语句锁定分区的统计信息。用例如下: +此外,你还可以使用 `LOCK STATS` 锁定分区的统计信息。例如: -创建分区表 `t`,插入一些数据,在未锁定分区 `p1` 的统计信息的情况下成功执行 `ANALYZE` 语句。 +创建分区表 `t` 并向其中插入数据。当分区 `p1` 的统计信息未被锁定时,`ANALYZE` 语句可以成功执行。 ```sql mysql> CREATE TABLE t(a INT, b INT) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (30)); @@ -103,7 +103,7 @@ mysql> SHOW WARNINGS; 6 rows in set (0.01 sec) ``` -锁定分区 `p1` 的统计信息,执行 `ANALYZE` 语句,warning 提示跳过对分区 `p1` 的 `ANALYZE`。 +锁定分区 `p1` 的统计信息并执行 `ANALYZE`。警告信息显示 `ANALYZE` 语句已跳过分区 `p1`。 ```sql mysql> LOCK STATS t PARTITION p1; @@ -130,7 +130,7 @@ mysql> SHOW WARNINGS; 2 rows in set (0.00 sec) ``` -解锁统计信息请参考 [UNLOCK STATS](/sql-statements/sql-statement-unlock-stats.md)。 +有关解锁统计信息的信息,请参见 [UNLOCK STATS](/sql-statements/sql-statement-unlock-stats.md)。 ## MySQL 兼容性 @@ -138,6 +138,6 @@ mysql> SHOW WARNINGS; ## 另请参阅 -* [统计信息](/statistics.md#锁定统计信息) +* [统计信息](/statistics.md#lock-statistics) * [UNLOCK STATS](/sql-statements/sql-statement-unlock-stats.md) * [SHOW STATS_LOCKED](/sql-statements/sql-statement-show-stats-locked.md) diff --git a/sql-statements/sql-statement-lock-tables-and-unlock-tables.md b/sql-statements/sql-statement-lock-tables-and-unlock-tables.md index 9b4bf4da747c..59bd486d0f33 100644 --- a/sql-statements/sql-statement-lock-tables-and-unlock-tables.md +++ b/sql-statements/sql-statement-lock-tables-and-unlock-tables.md @@ -1,25 +1,29 @@ --- title: LOCK TABLES 和 UNLOCK TABLES -summary: TiDB 数据库中 LOCK TABLES 和 UNLOCK TABLES 的使用概况。 +summary: TiDB 数据库中 LOCK TABLES 和 UNLOCK TABLES 的使用概览。 --- # LOCK TABLES 和 UNLOCK TABLES > **警告:** > -> `LOCK TABLES` 和 `UNLOCK TABLES` 目前为实验特性,不建议在生产环境中使用。 +> `LOCK TABLES` 和 `UNLOCK TABLES` 在当前版本中是实验性功能。不建议在生产环境中使用。 -客户端会话可以使用 `LOCK TABLES` 语句获取表锁,以便和其他会话合作访问表,或者防止其他会话修改表。会话只能为自己获取或释放锁。一个会话无法为另一个会话获取表锁或释放另一个会话持有的表锁。 +TiDB 允许客户端会话获取表锁,以便与其他会话协作访问表,或阻止其他会话修改表。一个会话只能为自己获取或释放锁。一个会话不能为另一个会话获取锁或释放另一个会话持有的锁。 -`LOCK TABLES` 可以为当前客户端会话获取表锁。你可以获取普通表的表锁,但你必须拥有锁定对象的 `LOCK TABLES` 和 `SELECT` 权限。 +`LOCK TABLES` 为当前客户端会话获取表锁。如果你对要锁定的每个对象都具有 `LOCK TABLES` 和 `SELECT` 权限,则可以为普通表获取表锁。 -`UNLOCK TABLES` 显式释放当前会话持有的所有表锁。`LOCK TABLES` 在获取新锁之前会隐式释放当前会话持有的所有表锁。 +`UNLOCK TABLES` 显式释放当前会话持有的任何表锁。`LOCK TABLES` 在获取新锁之前会隐式释放当前会话持有的所有表锁。 -表锁可以防止其他会话的读取或写入。持有 `WRITE` 锁的会话可以执行表级操作,例如 `DROP TABLE` 或 `TRUNCATE TABLE`。 +表锁可以防止其他会话进行读取或写入。持有 `WRITE` 锁的会话可以执行表级操作,如 `DROP TABLE` 或 `TRUNCATE TABLE`。 -> **警告:** +> **注意:** +> +> 表锁功能默认是禁用的。 > -> 开启表锁功能需要在所有 TiDB 实例的配置文件中设置 [`enable-table-lock`](/tidb-configuration-file.md#enable-table-lock-从-v400-版本开始引入) 为 `true`。 +> - 对于 TiDB Self-Managed,要启用表锁功能,你需要在所有 TiDB 实例的配置文件中将 [`enable-table-lock`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#enable-table-lock-new-in-v400) 设置为 `true`。 +> - 对于 TiDB Cloud Dedicated,要启用表锁功能,你需要联系 [TiDB Cloud Support](https://docs.pingcap.com/tidbcloud/tidb-cloud-support) 将 [`enable-table-lock`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#enable-table-lock-new-in-v400) 设置为 `true`。 +> - 对于 TiDB Cloud Serverless,不支持将 [`enable-table-lock`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#enable-table-lock-new-in-v400) 设置为 `true`。 ## 语法图 @@ -38,36 +42,36 @@ LockType ## 获取表锁 -你可以在会话中使用 `LOCK TABLES` 语句获取表锁。表锁有以下类型: +你可以使用 `LOCK TABLES` 语句在当前会话中获取表锁。可以使用以下锁类型: `READ` 锁: -- 持有 `READ` 锁的会话可以读表,但不能写入。 -- 多个会话可以同时获取同一个表的 `READ` 锁。 -- 其他会话可以在不显式获取 `READ` 锁的情况下读表。 +- 持有此锁的会话可以读取表,但不能写入。 +- 多个会话可以同时从同一个表获取 `READ` 锁。 +- 其他会话无需显式获取 `READ` 锁即可读取表。 -`READ LOCAL` 锁只是语法兼容 MySQL,实际上并不支持。 +`READ LOCAL` 锁仅用于与 MySQL 语法兼容,不支持此功能。 `WRITE` 锁: -- 持有 `WRITE` 锁的会话可以读取和写入表。 -- 只有持有 `WRITE` 锁的会话才能访问该表。在释放锁之前,其他会话不能读取或写入该表。 +- 持有此锁的会话可以读取和写入表。 +- 只有持有此锁的会话可以访问表。在锁释放之前,其他会话都不能访问它。 `WRITE LOCAL` 锁: -- 持有 `WRITE LOCAL` 锁的会话可以读取和写入表。 -- 只有持有 `WRITE LOCAL` 锁的会话才能写入该表,但其他会话依然可以读取该表的数据。 +- 持有此锁的会话可以读取和写入表。 +- 只有持有此锁的会话可以访问表。其他会话可以读取表,但不能写入。 -如果 `LOCK TABLES` 语句想要获取的表锁被其他会话持有且必须等待锁释放时,则 `LOCK TABLES` 语句会执行报错,例如: +如果 `LOCK TABLES` 语句需要的锁被另一个会话持有,`LOCK TABLES` 语句必须等待,并且在执行此语句时会返回错误,例如: ```sql -> LOCK TABLES t1 read; +> LOCK TABLES t1 READ; ERROR 8020 (HY000): Table 't1' was locked in WRITE by server: f4799bcb-cad7-4285-8a6d-23d3555173f1_session: 2199023255959 ``` -以上错误信息表明,在 TiDB `f4799bcb-cad7-4285-8a6d-23d3555173f1` 中,ID 为 `2199023255959` 的会话已经持有表 `t1` 的 `WRITE` 锁,所以,当前会话无法获取表 `t1` 的 `READ` 锁。 +上述错误消息表示,TiDB `f4799bcb-cad7-4285-8a6d-23d3555173f1` 中 ID 为 `2199023255959` 的会话已经在表 `t1` 上持有 `WRITE` 锁。因此,当前会话无法在表 `t1` 上获取 `READ` 锁。 -不能在单个 `LOCK TABLES` 语句中多次获取同一个表的锁。 +你不能在单个 `LOCK TABLES` 语句中多次获取相同的表锁。 ```sql > LOCK TABLES t WRITE, t READ; @@ -76,32 +80,32 @@ ERROR 1066 (42000): Not unique table/alias: 't' ## 释放表锁 -释放会话持有的表锁时,将同时释放该会话所有持有的表锁。会话可以显式或隐式释放表锁: +当会话持有的表锁被释放时,它们都会同时被释放。会话可以显式或隐式地释放其锁。 -- 会话可以使用 `UNLOCK TABLES` 语句显式释放其持有的所有表锁。 -- 当会话使用 `LOCK TABLES` 语句来获取表锁,而且同时已经持有其他表锁时,则在获取新表锁之前,将隐式释放其已经持有的所有表锁。 +- 会话可以使用 `UNLOCK TABLES` 显式释放其锁。 +- 如果已经持有锁的会话发出 `LOCK TABLES` 语句以获取锁,则在获取新锁之前会隐式释放其现有锁。 -当客户端会话的连接终止(无论是正常还是异常),TiDB 都会隐式释放会话持有的所有表锁。如果客户端重新连接,锁将不再有效。因此,通常不建议在客户端使用自动重新连接,因为在开启自动重新连接时,如果发生重新连接,任何表锁或当前事务都将丢失,而且不会通知客户端。禁用自动重新连接后,如果连接断开,则客户端会话发出的下一条语句将会收到报错信息。客户端可以检测到错误并采取适当的操作,例如重新获取锁或重做事务。 +如果客户端会话的连接终止(无论是正常还是异常终止),TiDB 会隐式释放该会话持有的所有表锁。如果客户端重新连接,锁将不再有效。因此,不建议在客户端启用自动重连。如果启用自动重连,客户端在重连发生时不会收到通知,所有表锁或当前事务都会丢失。相反,如果禁用自动重连,当连接断开时,下一条语句执行时会发生错误。客户端可以检测到错误并采取适当的操作,如重新获取锁或重做事务。 -## 表锁的使用限制和条件 +## 表锁限制和条件 -你可以安全地使用 `KILL` 语句终止已经持有表锁的会话。 +你可以安全地使用 `KILL` 终止持有表锁的会话。 -不支持获取以下数据库中表的表锁: +你不能在以下数据库中的表上获取表锁: - `INFORMATION_SCHEMA` - `PERFORMANCE_SCHEMA` -- `METRICS_SCHEMA` +- `METRICS_SCHEMA` - `mysql` -## 和 MySQL 的兼容性 +## MySQL 兼容性 -### 获取表锁 +### 表锁获取 -- 在 TiDB 中,如果会话 A 已经持有了一个表的表锁,另一个会话 B 对该表写入时会报错;但 MySQL 会阻塞会话 B 对该表的写入,直到会话 A 释放该表锁。其他会话对该表的锁请求会被阻塞直到当前会话释放 `WRITE` 锁。 -- 在 TiDB 中,如果 `LOCK TABLES` 语句想要获取的表锁被其他会话持有且必须等待锁释放时,`LOCK TABLES` 语句会执行报错;但 MySQL 会阻塞 `LOCK TABLES` 语句的执行,直到成功获取想要的表锁。 -- 在 TiDB 中,使用 `LOCK TABLES` 语句获取表锁的作用域是整个集群;但 MySQL 中表锁的作用域是单个 MySQL 服务器,与 NDB 群集不兼容。 +- 在 TiDB 中,如果会话 A 已经持有表锁,当会话 B 尝试写入表时会返回错误。在 MySQL 中,会话 B 的写入请求会被阻塞,直到会话 A 释放表锁,其他会话的锁定表请求会被阻塞,直到当前会话释放 `WRITE` 锁。 +- 在 TiDB 中,如果 `LOCK TABLES` 语句需要的锁被另一个会话持有,`LOCK TABLES` 语句必须等待,并且在执行此语句时会返回错误。在 MySQL 中,此语句会被阻塞,直到获取锁。 +- 在 TiDB 中,`LOCK TABLES` 语句在整个集群中生效。在 MySQL 中,此语句仅在当前 MySQL 服务器中生效,且与 NDB 集群不兼容。 -### 释放表锁 +### 表锁释放 -在 TiDB 的会话中显示开启一个事务时(例如使用 `BEGIN` 语句),TiDB 不会隐式释放当前会话已经持有的表锁;但 MySQL 会隐式释放当前会话已经持有的表锁。 +当在 TiDB 会话中显式启动事务时(例如,使用 `BEGIN` 语句),TiDB 不会隐式释放会话持有的表锁;但 MySQL 会。 diff --git a/sql-statements/sql-statement-modify-column.md b/sql-statements/sql-statement-modify-column.md index 232dc45f3a2b..268cdb91f86a 100644 --- a/sql-statements/sql-statement-modify-column.md +++ b/sql-statements/sql-statement-modify-column.md @@ -1,19 +1,19 @@ --- -title: MODIFY COLUMN -summary: TiDB 数据库中 MODIFY COLUMN 的使用概况。 +title: MODIFY COLUMN | TiDB SQL 语句参考 +summary: TiDB 数据库中 MODIFY COLUMN 的使用概览。 --- # MODIFY COLUMN -`ALTER TABLE .. MODIFY COLUMN` 语句用于修改已有表上的列,包括列的数据类型和属性。若要同时重命名,可改用 [`CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) 语句。 +`ALTER TABLE.. MODIFY COLUMN` 语句修改现有表上的列。修改可以包括更改数据类型和属性。如果同时需要重命名,请使用 [`CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) 语句。 -从 v5.1.0 版本起,TiDB 开始支持 Reorg 类型变更,包括但不限于: +从 v5.1.0 开始,TiDB 支持 Reorg 数据的数据类型更改,包括但不限于: -- 从 `VARCHAR` 转换为 `BIGINT` -- `DECIMAL` 精度修改 -- 从 `VARCHAR(10)` 到 `VARCHAR(5)` 的长度压缩 +- 将 `VARCHAR` 更改为 `BIGINT` +- 修改 `DECIMAL` 精度 +- 将 `VARCHAR(10)` 的长度压缩为 `VARCHAR(5)` -## 语法图 +## 语法 ```ebnf+diagram AlterTableStmt @@ -51,7 +51,7 @@ ColumnName ::= ## 示例 -### Meta-Only Change +### 仅元数据更改 {{< copyable "sql" >}} @@ -101,7 +101,7 @@ Create Table: CREATE TABLE `t1` ( 1 row in set (0.00 sec) ``` -### Reorg-Data Change +### Reorg 数据更改 {{< copyable "sql" >}} @@ -151,24 +151,24 @@ CREATE TABLE `t1` ( 1 row in set (0.00 sec) ``` -**注意:** - -> - 当所变更的类型与已经存在的数据行产生冲突时,TiDB 会进行报错处理。在上述例子中,TiDB 将进行如下报错: +> **注意:** +> +> - 当更改的数据类型与现有数据行冲突时,TiDB 会返回错误。在上面的示例中,TiDB 返回以下错误: > -> ``` -> alter table t1 modify column col1 varchar(4); -> ERROR 1406 (22001): Data Too Long, field len 4, data len 5 -> ``` +> ``` +> alter table t1 modify column col1 varchar(4); +> ERROR 1406 (22001): Data Too Long, field len 4, data len 5 +> ``` > -> - 由于和 Async Commit 功能兼容,DDL 在开始进入到 Reorg Data 前会有一定时间(约 2.5s)的等待处理: +> - 由于与 Async Commit 功能的兼容性,DDL 语句在开始处理 Reorg 数据之前会等待一段时间(约 2.5 秒)。 > -> ``` -> Query OK, 0 rows affected (2.52 sec) -> ``` +> ``` +> Query OK, 0 rows affected (2.52 sec) +> ``` ## MySQL 兼容性 -* 不支持修改主键列上需要 Reorg-Data 的类型,但是支持修改 Meta-Only 的类型。例如: +* 不支持在主键列上修改 Reorg 数据类型,但支持修改仅元数据类型。例如: ```sql CREATE TABLE t (a int primary key); @@ -188,7 +188,7 @@ CREATE TABLE `t1` ( Query OK, 0 rows affected (0.01 sec) ``` -* 不支持修改生成列的类型。例如: +* 不支持修改生成列的列类型。例如: ```sql CREATE TABLE t (a INT, b INT as (a+1)); @@ -196,7 +196,7 @@ CREATE TABLE `t1` ( ERROR 8200 (HY000): Unsupported modify column: column is generated ``` -* 不支持修改分区表上的列类型。例如: +* 不支持修改分区表的列类型。例如: ```sql CREATE TABLE t (c1 INT, c2 INT, c3 INT) partition by range columns(c1) ( partition p0 values less than (10), partition p1 values less than (maxvalue)); @@ -204,7 +204,7 @@ CREATE TABLE `t1` ( ERROR 8200 (HY000): Unsupported modify column: table is partition table ``` -* 不支持部分数据类型(例如,部分 TIME 类型、BIT、SET、ENUM、JSON 等)向某些类型的变更,因为 TiDB 的 `CAST` 函数与 MySQL 的行为有一些兼容性问题。例如: +* 由于 TiDB 和 MySQL 之间 `cast` 函数行为的一些兼容性问题,不支持从某些数据类型(例如某些 TIME 类型、BIT、SET、ENUM、JSON)转换为其他类型。 ```sql CREATE TABLE t (a DECIMAL(13, 7)); diff --git a/sql-statements/sql-statement-overview.md b/sql-statements/sql-statement-overview.md index b8baab5eb7f3..5b58c0d3f5a6 100644 --- a/sql-statements/sql-statement-overview.md +++ b/sql-statements/sql-statement-overview.md @@ -1,205 +1,279 @@ --- -title: SQL 语句概述 -summary: 介绍 TiDB 支持的 SQL 语句。 +title: SQL 语句概览 +summary: 了解 TiDB 支持的 SQL 语句。 --- -# SQL 语句概述 +# SQL 语句概览 -TiDB 使用的 SQL 语句旨在遵循 ISO/IEC SQL 标准,并在必要时对 MySQL 和 TiDB 特定的语句进行了扩展。 +TiDB 使用的 SQL 语句旨在遵循 ISO/IEC SQL 标准,并在必要时扩展 MySQL 和 TiDB 特定语句。 -## Schema 管理与数据定义语句 (DDL) +## 架构管理 / 数据定义语句 (DDL) | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ALTER DATABASE`](/sql-statements/sql-statement-alter-database.md) | 修改数据库。 | -| [`ALTER SEQUENCE`](/sql-statements/sql-statement-alter-sequence.md) | 修改序列对象。 | -| [`ALTER TABLE ... ADD COLUMN`](/sql-statements/sql-statement-add-column.md) | 在已有表中添加列。 | -| [`ALTER TABLE ... ADD INDEX`](/sql-statements/sql-statement-add-index.md) | 在已有表中添加索引。 | -| [`ALTER TABLE ... ALTER INDEX`](/sql-statements/sql-statement-alter-index.md) | 修改索引定义。 | -| [`ALTER TABLE ... CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) | 修改列定义。 | -| [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) | 对表进行数据整理。 | +| [`ALTER SEQUENCE`](/sql-statements/sql-statement-alter-sequence.md) | 修改序列。 | +| [`ALTER TABLE ... ADD COLUMN`](/sql-statements/sql-statement-add-column.md) | 向现有表添加列。 | +| [`ALTER TABLE ... ADD INDEX`](/sql-statements/sql-statement-add-index.md) | 向现有表添加索引。 | +| [`ALTER TABLE ... ALTER INDEX`](/sql-statements/sql-statement-alter-index.md) | 更改索引定义。 | +| [`ALTER TABLE ... CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) | 更改列定义。 | +| [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) | 压缩表。 | | [`ALTER TABLE ... DROP COLUMN`](/sql-statements/sql-statement-drop-column.md) | 从表中删除列。 | | [`ALTER TABLE ... MODIFY COLUMN`](/sql-statements/sql-statement-modify-column.md) | 修改列定义。 | | [`ALTER TABLE ... RENAME INDEX`](/sql-statements/sql-statement-rename-index.md) | 重命名索引。 | -| [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md) | 修改表定义。 | +| [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.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 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 VIEW`](/sql-statements/sql-statement-create-view.md) | 创建新视图。 | -| [`DROP DATABASE`](/sql-statements/sql-statement-drop-database.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 TABLE`](/sql-statements/sql-statement-drop-table.md) | 删除已有表。 | -| [`DROP VIEW`](/sql-statements/sql-statement-drop-view.md) | 删除已有视图。 | +| [`DROP TABLE`](/sql-statements/sql-statement-drop-table.md) | 删除现有表。 | +| [`DROP VIEW`](/sql-statements/sql-statement-drop-view.md) | 删除现有视图。 | | [`RENAME TABLE`](/sql-statements/sql-statement-rename-table.md) | 重命名表。 | -| [`SHOW COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) | 显示表的列。 | -| [`SHOW CREATE DATABASE`](/sql-statements/sql-statement-show-create-database.md) | 显示数据库的 `CREATE` 语句。 | -| [`SHOW CREATE SEQUENCE`](/sql-statements/sql-statement-show-create-sequence.md) | 显示序列的 `CREATE` 语句。 | -| [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) | 显示表的 `CREATE` 语句。 | +| [`SHOW COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) | 显示表中的列。 | +| [`SHOW CREATE DATABASE`](/sql-statements/sql-statement-show-create-database.md) | 显示数据库的 CREATE 语句。 | +| [`SHOW CREATE SEQUENCE`](/sql-statements/sql-statement-show-create-sequence.md) | 显示序列的 CREATE 语句。 | +| [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) | 显示表的 CREATE 语句。 | | [`SHOW DATABASES`](/sql-statements/sql-statement-show-databases.md) | 显示当前用户有权限访问的数据库列表。 | | [`SHOW FIELDS FROM`](/sql-statements/sql-statement-show-fields-from.md) | 显示表的列。 | | [`SHOW INDEXES`](/sql-statements/sql-statement-show-indexes.md) | 显示表的索引。 | | [`SHOW SCHEMAS`](/sql-statements/sql-statement-show-schemas.md) | `SHOW DATABASES` 的别名,显示当前用户有权限访问的数据库列表。 | -| [`SHOW TABLE NEXT_ROW_ID`](/sql-statements/sql-statement-show-table-next-rowid.md) | 显示表中下一个行的 ID。 | +| [`SHOW TABLE NEXT_ROW_ID`](/sql-statements/sql-statement-show-table-next-rowid.md) | 显示表的下一个行 ID。 | | [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) | 显示 TiDB 中表的 Region 信息。 | | [`SHOW TABLE STATUS`](/sql-statements/sql-statement-show-table-status.md) | 显示 TiDB 中表的各种统计信息。 | | [`SHOW TABLES`](/sql-statements/sql-statement-show-tables.md) | 显示数据库中的表。 | -| [`TRUNCATE`](/sql-statements/sql-statement-truncate.md) | 清空表中的所有数据。 | +| [`TRUNCATE`](/sql-statements/sql-statement-truncate.md) | 截断表中的所有数据。 | ## 数据操作语句 (DML) | SQL 语句 | 描述 | -|----------|------| -| [`BATCH`](/sql-statements/sql-statement-batch.md) | 在 TiDB 中将一个 DML 语句拆分为多个语句执行。 | +|---------------|-------------| +| [`BATCH`](/sql-statements/sql-statement-batch.md) | 在 TiDB 中将 DML 语句拆分为多个语句执行。 | | [`DELETE`](/sql-statements/sql-statement-delete.md) | 从表中删除行。 | | [`INSERT`](/sql-statements/sql-statement-insert.md) | 向表中插入新行。 | -| [`REPLACE`](/sql-statements/sql-statement-replace.md) | 替换现有的行或插入新行。 | +| [`REPLACE`](/sql-statements/sql-statement-replace.md) | 替换现有行或插入新行。 | | [`SELECT`](/sql-statements/sql-statement-select.md) | 从表中读取数据。 | -| [`TABLE`](/sql-statements/sql-statement-table.md) | 从表中读取行数据。 | -| [`UPDATE`](/sql-statements/sql-statement-update.md) | 修改表中现有的行。 | -| [`WITH`](/sql-statements/sql-statement-with.md) | 定义公用表表达式。 | +| [`TABLE`](/sql-statements/sql-statement-table.md) | 从表中检索行。 | +| [`UPDATE`](/sql-statements/sql-statement-update.md) | 更新表中的现有行。 | +| [`WITH`](/sql-statements/sql-statement-with.md) | 定义公共表表达式。 | ## 事务语句 | SQL 语句 | 描述 | -|----------|------| -| [`BEGIN`](/sql-statements/sql-statement-begin.md) | 启动一个新事务。 | +|---------------|-------------| +| [`BEGIN`](/sql-statements/sql-statement-begin.md) | 开始新事务。 | | [`COMMIT`](/sql-statements/sql-statement-commit.md) | 提交当前事务。 | | [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) | 回滚当前事务。 | -| [`SAVEPOINT`](/sql-statements/sql-statement-savepoint.md) | 在事务中设置一个保存点。 | -| [`SET TRANSACTION`](/sql-statements/sql-statement-set-transaction.md) | 在 `GLOBAL` 或 `SESSION` 范围更改当前隔离级别。 | -| [`START TRANSACTION`](/sql-statements/sql-statement-start-transaction.md) | 启动一个新事务。 | +| [`SAVEPOINT`](/sql-statements/sql-statement-savepoint.md) | 在事务中设置保存点。 | +| [`SET TRANSACTION`](/sql-statements/sql-statement-set-transaction.md) | 在 `GLOBAL` 或 `SESSION` 基础上更改当前隔离级别。 | +| [`START TRANSACTION`](/sql-statements/sql-statement-start-transaction.md) | 开始新事务。 | ## 预处理语句 | SQL 语句 | 描述 | -|----------|------| -| [`DEALLOCATE`](/sql-statements/sql-statement-deallocate.md) | 释放预处理语句以释放相关资源。 | +|---------------|-------------| +| [`DEALLOCATE`](/sql-statements/sql-statement-deallocate.md) | 释放预处理语句,释放相关资源。 | | [`EXECUTE`](/sql-statements/sql-statement-execute.md) | 使用特定参数值执行预处理语句。 | -| [`PREPARE`](/sql-statements/sql-statement-prepare.md) | 创建包含占位符的预处理语句。 | - +| [`PREPARE`](/sql-statements/sql-statement-prepare.md) | 创建带有占位符的预处理语句。 | ## 管理语句 + + | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ADMIN CANCEL DDL`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消 DDL 作业。 | | [`ADMIN CHECK [TABLE\|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) | 检查表或索引的完整性。 | | [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表的校验和。 | | [`ADMIN CLEANUP INDEX`](/sql-statements/sql-statement-admin-cleanup.md) | 清理表中的索引。 | -| [`ADMIN PAUSE DDL`](/sql-statements/sql-statement-admin-pause-ddl.md) | 暂停 DDL 作业。 | -| [`ADMIN RESUME DDL`](/sql-statements/sql-statement-admin-resume-ddl.md) | 恢复 DDL 作业。 | -| [`ADMIN SHOW DDL [JOBS\|JOB QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) | 显示 DDL 作业信息或 DDL 对应的查询语句。 | +| [`ADMIN PAUSE DDL`](/sql-statements/sql-statement-admin-pause-ddl.md) | 暂停 DDL 操作。 | +| [`ADMIN RESUME DDL`](/sql-statements/sql-statement-admin-resume-ddl.md) | 恢复 DDL 操作。 | +| [`ADMIN SHOW DDL [JOBS\|JOB QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) | 显示 DDL 作业或作业查询。 | | [`ADMIN`](/sql-statements/sql-statement-admin.md) | 执行各种管理任务。 | -| [`FLUSH TABLES`](/sql-statements/sql-statement-flush-tables.md) | 用于提供 [MySQL 兼容性](/mysql-compatibility.md),在 TiDB 中没有实际用途。 | +| [`FLUSH TABLES`](/sql-statements/sql-statement-flush-tables.md) | 为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。在 TiDB 中没有实际用途。 | | [`SET `](/sql-statements/sql-statement-set-variable.md) | 修改系统变量或用户变量。 | | [`SET [NAMES\|CHARACTER SET]`](/sql-statements/sql-statement-set-names.md) | 设置字符集和排序规则。 | -| [`SPLIT REGION`](/sql-statements/sql-statement-split-region.md) | 将 Region 切分为更小的 Region。 | +| [`SPLIT REGION`](/sql-statements/sql-statement-split-region.md) | 将一个 Region 分裂成更小的 Region。 | -## 数据导入和导出 + + + | SQL 语句 | 描述 | -|----------|------| -| [`CANCEL IMPORT JOB`](/sql-statements/sql-statement-cancel-import-job.md) | 取消正在进行的导入任务。 | -| [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) | 通过 TiDB Lightning 的[物理导入模式](/tidb-lightning/tidb-lightning-physical-import-mode.md) 将数据导入到表中。 | -| [`LOAD DATA`](/sql-statements/sql-statement-load-data.md) | 从 Amazon S3 或 Google Cloud Storage 加载数据到表中。 | -| [`SHOW IMPORT JOB`](/sql-statements/sql-statement-show-import-job.md) | 显示导入任务的状态。 | +|---------------|-------------| +| [`ADMIN CANCEL DDL`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消 DDL 作业。 | +| [`ADMIN CHECK [TABLE\|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) | 检查表或索引的完整性。 | +| [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表的校验和。 | +| [`ADMIN CLEANUP INDEX`](/sql-statements/sql-statement-admin-cleanup.md) | 清理表中的索引。 | +| [`ADMIN PAUSE DDL`](/sql-statements/sql-statement-admin-pause-ddl.md) | 暂停 DDL 操作。 | +| [`ADMIN RECOVER INDEX`](/sql-statements/sql-statement-admin-recover.md) | 基于冗余索引恢复一致性。 | +| [`ADMIN RESUME DDL`](/sql-statements/sql-statement-admin-resume-ddl.md) | 恢复 DDL 操作。 | +| [`ADMIN SHOW DDL [JOBS\|JOB QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) | 显示 DDL 作业或作业查询。 | +| [`ADMIN`](/sql-statements/sql-statement-admin.md) | 执行各种管理任务。 | +| [`FLUSH TABLES`](/sql-statements/sql-statement-flush-tables.md) | 为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。在 TiDB 中没有实际用途。 | +| [`SET `](/sql-statements/sql-statement-set-variable.md) | 修改系统变量或用户变量。 | +| [`SET [NAMES\|CHARACTER SET]`](/sql-statements/sql-statement-set-names.md) | 设置字符集和排序规则。 | +| [`SPLIT REGION`](/sql-statements/sql-statement-split-region.md) | 将一个 Region 分裂成更小的 Region。 | + + + +## 数据导入和导出 +| SQL 语句 | 描述 | +|---------------|-------------| +| [`CANCEL IMPORT JOB`](/sql-statements/sql-statement-cancel-import-job.md) | 取消正在进行的导入作业。 | +| [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) | 通过 TiDB Lightning 的[物理导入模式](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode)将数据导入到表中。 | +| [`LOAD DATA`](/sql-statements/sql-statement-load-data.md) | 从 Amazon S3 或 Google Cloud Storage 将数据加载到表中。 | +| [`SHOW IMPORT JOB`](/sql-statements/sql-statement-show-import-job.md) | 显示导入作业的状态。 | ## 备份和恢复 | SQL 语句 | 描述 | -|----------|------| -| [`BACKUP`](/sql-statements/sql-statement-backup.md) | 对 TiDB 集群执行分布式备份操作。 | -| [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) | 将集群恢复到特定的时间点。 | +|---------------|-------------| +| [`BACKUP`](/sql-statements/sql-statement-backup.md) | 执行 TiDB 集群的分布式备份。 | +| [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) | 将集群恢复到特定快照。 | | [`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.md) | 恢复被 `DROP` 语句删除的数据库及其数据。 | -| [`FLASHBACK TABLE`](/sql-statements/sql-statement-flashback-table.md) | 恢复被 `DROP` 或 `TRUNCATE` 操作删除的表及其数据。 | -| [`RECOVER TABLE`](/sql-statements/sql-statement-recover-table.md) | 恢复被删除的表及其数据。 | -| [`RESTORE`](/sql-statements/sql-statement-restore.md) | 从备份中恢复数据库。 | +| [`FLASHBACK TABLE`](/sql-statements/sql-statement-flashback-table.md) | 恢复被 `DROP` 或 `TRUNCATE` 操作删除的表和数据。 | +| [`RECOVER TABLE`](/sql-statements/sql-statement-recover-table.md) | 恢复已删除的表及其数据。 | +| [`RESTORE`](/sql-statements/sql-statement-restore.md) | 从备份恢复数据库。 | | [`SHOW BACKUPS`](/sql-statements/sql-statement-show-backups.md) | 显示备份任务。 | | [`SHOW RESTORES`](/sql-statements/sql-statement-show-backups.md) | 显示恢复任务。 | ## 放置策略 | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ALTER PLACEMENT POLICY`](/sql-statements/sql-statement-alter-placement-policy.md) | 修改放置策略。 | | [`ALTER RANGE`](/sql-statements/sql-statement-alter-range.md) | 修改放置策略的范围。 | | [`CREATE PLACEMENT POLICY`](/sql-statements/sql-statement-create-placement-policy.md) | 创建新的放置策略。 | -| [`DROP PLACEMENT POLICY`](/sql-statements/sql-statement-drop-placement-policy.md) | 删除现有放置策略。 | +| [`DROP PLACEMENT POLICY`](/sql-statements/sql-statement-drop-placement-policy.md) | 删除现有的放置策略。 | | [`SHOW CREATE PLACEMENT POLICY`](/sql-statements/sql-statement-show-create-placement-policy.md) | 显示放置策略的 `CREATE` 语句。 | -| [`SHOW PLACEMENT FOR`](/sql-statements/sql-statement-show-placement-for.md) | 显示指定表的放置策略。 | +| [`SHOW PLACEMENT FOR`](/sql-statements/sql-statement-show-placement-for.md) | 显示特定表的放置规则。 | | [`SHOW PLACEMENT LABELS`](/sql-statements/sql-statement-show-placement-labels.md) | 显示可用的放置标签。 | | [`SHOW PLACEMENT`](/sql-statements/sql-statement-show-placement.md) | 显示放置规则。 | ## 资源组 + + | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ALTER RESOURCE GROUP`](/sql-statements/sql-statement-alter-resource-group.md) | 修改资源组。 | -| [`CALIBRATE RESOURCE`](/sql-statements/sql-statement-calibrate-resource.md) | 估算并输出当前集群的 [Request Unit (RU)](/tidb-resource-control.md#什么是-request-unit-ru) 容量。 | +| [`CALIBRATE RESOURCE`](/sql-statements/sql-statement-calibrate-resource.md) | 估算并输出当前集群的[请求单元 (RU)](/tidb-resource-control.md#what-is-request-unit-ru) 容量。 | | [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) | 创建新的资源组。 | | [`DROP RESOURCE GROUP`](/sql-statements/sql-statement-drop-resource-group.md) | 删除资源组。 | -| [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md) | 管理 Runaway Queries 监控列表。 | +| [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md) | 管理失控查询监视列表。 | | [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md) | 设置资源组。 | | [`SHOW CREATE RESOURCE GROUP`](/sql-statements/sql-statement-show-create-resource-group.md) | 显示资源组的 `CREATE` 语句。 | -## 效用语句 + + + | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| +| [`ALTER RESOURCE GROUP`](/sql-statements/sql-statement-alter-resource-group.md) | 修改资源组。 | +| [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) | 创建新的资源组。 | +| [`DROP RESOURCE GROUP`](/sql-statements/sql-statement-drop-resource-group.md) | 删除资源组。 | +| [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md) | 管理失控查询监视列表。 | +| [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md) | 设置资源组。 | +| [`SHOW CREATE RESOURCE GROUP`](/sql-statements/sql-statement-show-create-resource-group.md) | 显示资源组的 `CREATE` 语句。 | + + + +## 实用工具语句 + +| SQL 语句 | 描述 | +|---------------|-------------| | [`DESC`](/sql-statements/sql-statement-desc.md) | `DESCRIBE` 的别名,显示表的结构。 | | [`DESCRIBE`](/sql-statements/sql-statement-describe.md) | 显示表的结构。 | -| [`DO`](/sql-statements/sql-statement-do.md) | 执行表达式,但不返回任何结果。 | +| [`DO`](/sql-statements/sql-statement-do.md) | 执行表达式但不返回任何结果。 | | [`EXPLAIN`](/sql-statements/sql-statement-explain.md) | 显示查询的执行计划。 | | [`TRACE`](/sql-statements/sql-statement-trace.md) | 提供查询执行的详细信息。 | -| [`USE`](/sql-statements/sql-statement-use.md) | 选择当前数据库。 | - +| [`USE`](/sql-statements/sql-statement-use.md) | 设置当前数据库。 | ## 显示语句 + + | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`SHOW BUILTINS`](/sql-statements/sql-statement-show-builtins.md) | 列出内置函数。 | | [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) | 列出字符集。 | | [`SHOW COLLATIONS`](/sql-statements/sql-statement-show-collation.md) | 列出排序规则。 | -| [`SHOW ERRORS`](/sql-statements/sql-statement-show-errors.md) | 显示先前已执行语句中的错误。 | -| [`SHOW STATUS`](/sql-statements/sql-statement-show-status.md) | 用于提供 [MySQL 兼容性](/mysql-compatibility.md)。对于大多数指标,TiDB 会使用 [Prometheus 和 Grafana](/tidb-monitoring-framework.md) 来集中收集,而不是使用 `SHOW STATUS`。 | +| [`SHOW ERRORS`](/sql-statements/sql-statement-show-errors.md) | 显示之前执行的语句的错误。 | +| [`SHOW STATUS`](/sql-statements/sql-statement-show-status.md) | 为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。TiDB 使用 [Prometheus 和 Grafana](/tidb-monitoring-framework.md) 进行集中指标收集,而不是使用 `SHOW STATUS` 来获取大多数指标。 | | [`SHOW VARIABLES`](/sql-statements/sql-statement-show-variables.md) | 显示系统变量。 | -| [`SHOW WARNINGS`](/sql-statements/sql-statement-show-warnings.md) | 显示先前已执行语句中的警告和注意。 | +| [`SHOW WARNINGS`](/sql-statements/sql-statement-show-warnings.md) | 显示之前执行的语句的警告和注意事项。 | + + + + + +| SQL 语句 | 描述 | +|---------------|-------------| +| [`SHOW BUILTINS`](/sql-statements/sql-statement-show-builtins.md) | 列出内置函数。 | +| [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) | 列出字符集。 | +| [`SHOW COLLATIONS`](/sql-statements/sql-statement-show-collation.md) | 列出排序规则。 | +| [`SHOW ERRORS`](/sql-statements/sql-statement-show-errors.md) | 显示之前执行的语句的错误。 | +| [`SHOW STATUS`](/sql-statements/sql-statement-show-status.md) | 为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。TiDB Cloud 提供[监控](/tidb-cloud/monitor-tidb-cluster.md)进行集中指标收集,而不是使用 `SHOW STATUS` 来获取大多数指标。 | +| [`SHOW VARIABLES`](/sql-statements/sql-statement-show-variables.md) | 显示系统变量。 | +| [`SHOW WARNINGS`](/sql-statements/sql-statement-show-warnings.md) | 显示之前执行的语句的警告和注意事项。 | + + ## 实例管理 + + | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ALTER INSTANCE`](/sql-statements/sql-statement-alter-instance.md) | 修改实例。 | -| [`FLUSH STATUS`](/sql-statements/sql-statement-flush-status.md) | 用于提供 [MySQL 兼容性](/mysql-compatibility.md)。对于大多数指标,TiDB 会使用 [Prometheus 和 Grafana](/tidb-monitoring-framework.md) 来集中收集,而不是使用 `SHOW STATUS`。 | -| [`KILL`](/sql-statements/sql-statement-kill.md) | 终止当前 TiDB 集群中任意一个 TiDB 实例的连接。 | -| [`SHOW CONFIG`](/sql-statements/sql-statement-show-config.md) | 显示 TiDB 各组件的配置信息。 | +| [`FLUSH STATUS`](/sql-statements/sql-statement-flush-status.md) | 为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。TiDB 使用 [Prometheus 和 Grafana](/tidb-monitoring-framework.md) 进行集中指标收集,而不是使用 `SHOW STATUS` 来获取大多数指标。 | +| [`KILL`](/sql-statements/sql-statement-kill.md) | 终止当前 TiDB 集群中任何 TiDB 实例中的连接。 | +| [`SHOW CONFIG`](/sql-statements/sql-statement-show-config.md) | 显示 TiDB 各个组件的配置。 | | [`SHOW ENGINES`](/sql-statements/sql-statement-show-engines.md) | 显示可用的存储引擎。 | | [`SHOW PLUGINS`](/sql-statements/sql-statement-show-plugins.md) | 显示已安装的插件。 | -| [`SHOW PROCESSLIST`](/sql-statements/sql-statement-show-processlist.md) | 显示连接到相同 TiDB 服务器的当前会话。 | -| [`SHOW PROFILES`](/sql-statements/sql-statement-show-profiles.md) | 用于提供 [MySQL 兼容性](/mysql-compatibility.md),目前返回结果为空。 | +| [`SHOW PROCESSLIST`](/sql-statements/sql-statement-show-processlist.md) | 显示连接到同一 TiDB 服务器的当前会话。 | +| [`SHOW PROFILES`](/sql-statements/sql-statement-show-profiles.md) | 为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。目前仅返回空结果。 | | [`SHUTDOWN`](/sql-statements/sql-statement-shutdown.md) | 停止客户端连接的 TiDB 实例,而不是整个 TiDB 集群。 | + + + + +| SQL 语句 | 描述 | +|---------------|-------------| +| [`ALTER INSTANCE`](/sql-statements/sql-statement-alter-instance.md) | 修改实例。 | +| [`FLUSH STATUS`](/sql-statements/sql-statement-flush-status.md) | 为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。TiDB Cloud 提供[监控](/tidb-cloud/monitor-tidb-cluster.md)进行集中指标收集,而不是使用 `SHOW STATUS` 来获取大多数指标。 | +| [`KILL`](/sql-statements/sql-statement-kill.md) | 终止当前 TiDB 集群中任何 TiDB 实例中的连接。 | +| [`SHOW ENGINES`](/sql-statements/sql-statement-show-engines.md) | 显示可用的存储引擎。 | +| [`SHOW PLUGINS`](/sql-statements/sql-statement-show-plugins.md) | 显示已安装的插件。 | +| [`SHOW PROCESSLIST`](/sql-statements/sql-statement-show-processlist.md) | 显示连接到同一 TiDB 服务器的当前会话。 | +| [`SHOW PROFILES`](/sql-statements/sql-statement-show-profiles.md) | 显示查询配置文件。为[与 MySQL 兼容性](/mysql-compatibility.md)而包含。目前仅返回空结果。 | + + + ## 锁定语句 | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`LOCK STATS`](/sql-statements/sql-statement-lock-stats.md) | 锁定表或分区的统计信息。 | -| [`LOCK TABLES`](/sql-statements/sql-statement-lock-tables-and-unlock-tables.md) | 锁定当前会话的表。 | +| [`LOCK TABLES`](/sql-statements/sql-statement-lock-tables-and-unlock-tables.md) | 为当前会话锁定表。 | | [`UNLOCK STATS`](/sql-statements/sql-statement-unlock-stats.md) | 解锁表或分区的统计信息。 | | [`UNLOCK TABLES`](/sql-statements/sql-statement-lock-tables-and-unlock-tables.md) | 解锁表。 | -## 账户管理与数据控制语言 (DCL) +## 账户管理 / 数据控制语言 | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ALTER USER`](/sql-statements/sql-statement-alter-user.md) | 修改用户。 | | [`CREATE ROLE`](/sql-statements/sql-statement-create-role.md) | 创建角色。 | | [`CREATE USER`](/sql-statements/sql-statement-create-user.md) | 创建新用户。 | | [`DROP ROLE`](/sql-statements/sql-statement-drop-role.md) | 删除现有角色。 | | [`DROP USER`](/sql-statements/sql-statement-drop-user.md) | 删除现有用户。 | -| [`FLUSH PRIVILEGES`](/sql-statements/sql-statement-flush-privileges.md) | 从权限表中重新加载权限的内存副本。 | +| [`FLUSH PRIVILEGES`](/sql-statements/sql-statement-flush-privileges.md) | 重新加载内存中的权限表副本。 | | [`GRANT `](/sql-statements/sql-statement-grant-privileges.md) | 授予权限。 | | [`GRANT `](/sql-statements/sql-statement-grant-role.md) | 授予角色。 | | [`RENAME USER`](/sql-statements/sql-statement-rename-user.md) | 重命名现有用户。 | @@ -212,30 +286,46 @@ TiDB 使用的 SQL 语句旨在遵循 ISO/IEC SQL 标准,并在必要时对 My | [`SHOW GRANTS`](/sql-statements/sql-statement-show-grants.md) | 显示与用户关联的权限。 | | [`SHOW PRIVILEGES`](/sql-statements/sql-statement-show-privileges.md) | 显示可用的权限。 | -## TiCDC 与 TiDB Binlog +## TiCDC & TiDB Binlog + + | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ADMIN [SET\|SHOW\|UNSET] BDR ROLE`](/sql-statements/sql-statement-admin-bdr-role.md) | 管理 BDR 角色。 | | [`CHANGE DRAINER`](/sql-statements/sql-statement-change-drainer.md) | 修改集群中 Drainer 的状态信息。 | | [`CHANGE PUMP`](/sql-statements/sql-statement-change-pump.md) | 修改集群中 Pump 的状态信息。 | | [`SHOW DRAINER STATUS`](/sql-statements/sql-statement-show-drainer-status.md) | 显示集群中所有 Drainer 节点的状态。 | -| [`SHOW MASTER STATUS`](/sql-statements/sql-statement-show-master-status.md) | 显示集群中当前最新的 TSO。 | +| [`SHOW MASTER STATUS`](/sql-statements/sql-statement-show-master-status.md) | 显示集群中的最新 TSO。 | | [`SHOW PUMP STATUS`](/sql-statements/sql-statement-show-pump-status.md) | 显示集群中所有 Pump 节点的状态信息。 | -## 统计信息和执行计划管理 + + + + +> **注意:** +> +> [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) 和 [TiDB Binlog](https://docs.pingcap.com/tidb/stable/tidb-binlog-overview) 是用于将 TiDB 数据复制到上游的 TiDB 自管理工具。大多数 TiCDC 和 TiDB Binlog 的 SQL 语句不适用于 TiDB Cloud。对于 TiDB Cloud,您可以使用 [TiDB Cloud 控制台](https://tidbcloud.com)中的[变更数据捕获](/tidb-cloud/changefeed-overview.md)功能来流式传输数据。 + +| SQL 语句 | 描述 | +|---------------|-------------| +| [`SHOW MASTER STATUS`](/sql-statements/sql-statement-show-master-status.md) | 显示集群中的最新 TSO。 | + + + +## 统计信息和计划管理 | SQL 语句 | 描述 | -|----------|------| +|---------------|-------------| | [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) | 收集表的统计信息。 | | [`CREATE BINDING`](/sql-statements/sql-statement-create-binding.md) | 为 SQL 语句创建执行计划绑定。 | -| [`DROP BINDING`](/sql-statements/sql-statement-drop-binding.md) | 删除 SQL 语句的执行计划绑定。 | -| [`DROP STATS`](/sql-statements/sql-statement-drop-stats.md) | 删除表的统计信息。 | -| [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) | 工作方式类似于 `EXPLAIN`,但主要区别在于 `EXPLAIN ANALYZE` 会执行语句。 | +| [`DROP BINDING`](/sql-statements/sql-statement-drop-binding.md) | 从 SQL 语句中删除执行计划绑定。 | +| [`DROP STATS`](/sql-statements/sql-statement-drop-stats.md) | 从表中删除统计信息。 | +| [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) | 与 `EXPLAIN` 类似,主要区别是它会执行语句。 | | [`LOAD STATS`](/sql-statements/sql-statement-load-stats.md) | 将统计信息加载到 TiDB 中。 | | [`SHOW ANALYZE STATUS`](/sql-statements/sql-statement-show-analyze-status.md) | 显示统计信息收集任务。 | | [`SHOW BINDINGS`](/sql-statements/sql-statement-show-bindings.md) | 显示已创建的 SQL 绑定。 | -| [`SHOW STATS_HEALTHY`](/sql-statements/sql-statement-show-stats-healthy.md) | 显示统计信息准确度的预估值。 | +| [`SHOW STATS_HEALTHY`](/sql-statements/sql-statement-show-stats-healthy.md) | 显示统计信息被认为准确程度的估计。 | | [`SHOW STATS_HISTOGRAMS`](/sql-statements/sql-statement-show-stats-histograms.md) | 显示统计信息中的直方图信息。 | | [`SHOW STATS_LOCKED`](/sql-statements/sql-statement-show-stats-locked.md) | 显示统计信息被锁定的表。 | -| [`SHOW STATS_META`](/sql-statements/sql-statement-show-stats-meta.md) | 显示表中的行数和表中发生更改的行数。 | +| [`SHOW STATS_META`](/sql-statements/sql-statement-show-stats-meta.md) | 显示表中有多少行以及该表中有多少行被更改。 | diff --git a/sql-statements/sql-statement-prepare.md b/sql-statements/sql-statement-prepare.md index 8113fc30a213..057af190b9ab 100644 --- a/sql-statements/sql-statement-prepare.md +++ b/sql-statements/sql-statement-prepare.md @@ -1,11 +1,11 @@ --- -title: PREPARE -summary: TiDB 数据库中 PREPARE 的使用概况。 +title: PREPARE | TiDB SQL 语句参考 +summary: TiDB 数据库中 PREPARE 的使用概览。 --- # PREPARE -`PREPARE` 语句为服务器端预处理语句提供 SQL 接口。 +`PREPARE` 语句为服务器端预处理语句提供了 SQL 接口。 ## 语法图 @@ -20,60 +20,34 @@ PrepareSQL ::= > **注意:** > -> `PREPARE` 语句最多支持 65535 个占位符。 +> 对于每个 `PREPARE` 语句,占位符的最大数量是 65535。 -你可以使用 [`max_prepared_stmt_count`](/system-variables.md#max_prepared_stmt_count) 系统变量来限制当前 TiDB 实例中 `PREPARE` 语句的数量。 +要限制当前 TiDB 实例中 `PREPARE` 语句的数量,你可以使用 [`max_prepared_stmt_count`](/system-variables.md#max_prepared_stmt_count) 系统变量。 ## 示例 -{{< copyable "sql" >}} - ```sql -PREPARE mystmt FROM 'SELECT ? as num FROM DUAL'; -``` - -``` +mysql> PREPARE mystmt FROM 'SELECT ? as num FROM DUAL'; Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -SET @number = 5; -``` - -``` +mysql> SET @number = 5; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -EXECUTE mystmt USING @number; -``` - -``` +mysql> EXECUTE mystmt USING @number; +------+ | num | +------+ | 5 | +------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -DEALLOCATE PREPARE mystmt; -``` - -``` +mysql> DEALLOCATE PREPARE mystmt; Query OK, 0 rows affected (0.00 sec) ``` ## MySQL 兼容性 -`PREPARE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `PREPARE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-query-watch.md b/sql-statements/sql-statement-query-watch.md index c7786a669a4d..f70061b99950 100644 --- a/sql-statements/sql-statement-query-watch.md +++ b/sql-statements/sql-statement-query-watch.md @@ -1,13 +1,17 @@ --- title: QUERY WATCH -summary: TiDB 数据库中 QUERY WATCH 的使用概况。 +summary: TiDB 数据库中 QUERY WATCH 的使用概述。 --- # QUERY WATCH -`QUERY WATCH` 语句用于在资源组中手动管理 Runaway Queries 监控列表。 +`QUERY WATCH` 语句用于手动管理资源组中失控查询的监视列表。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法概要 ```ebnf+diagram AddQueryWatchStmt ::= @@ -38,14 +42,14 @@ DropQueryWatchStmt ::= "QUERY" "WATCH" "REMOVE" NUM ``` -## 参数说明 +## 参数 -详见 [`QUERY WATCH` 语句说明](/tidb-resource-control.md#query-watch-语句说明)。 +参见 [`QUERY WATCH` 参数](/tidb-resource-control.md#query-watch-parameters)。 ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [Runaway Queries](/tidb-resource-control.md#管理资源消耗超出预期的查询-runaway-queries) +* [失控查询](/tidb-resource-control.md#manage-queries-that-consume-more-resources-than-expected-runaway-queries) diff --git a/sql-statements/sql-statement-recover-table.md b/sql-statements/sql-statement-recover-table.md index e6c19d1682b9..11d074213dec 100644 --- a/sql-statements/sql-statement-recover-table.md +++ b/sql-statements/sql-statement-recover-table.md @@ -1,27 +1,27 @@ --- title: RECOVER TABLE -summary: RECOVER TABLE 是用来恢复被删除的表及其数据的功能。在 DROP TABLE 后,在 GC life time 时间内,可以使用 RECOVER TABLE 语句来恢复被删除的表以及其数据。如果删除表后并过了 GC lifetime,就不能再用 RECOVER TABLE 来恢复被删除的表了。 +summary: TiDB 数据库中 RECOVER TABLE 的使用概述。 --- # RECOVER TABLE -`RECOVER TABLE` 的功能是恢复被删除的表及其数据。在 `DROP TABLE` 后,在 GC life time 时间内,可以用 `RECOVER TABLE` 语句恢复被删除的表以及其数据。 +`RECOVER TABLE` 用于在执行 `DROP TABLE` 语句后的 GC(垃圾回收)生命周期内恢复已删除的表及其数据。 ## 语法 {{< copyable "sql" >}} ```sql -RECOVER TABLE table_name +RECOVER TABLE table_name; ``` {{< copyable "sql" >}} ```sql -RECOVER TABLE BY JOB JOB_ID +RECOVER TABLE BY JOB JOB_ID; ``` -### 语法图 +## 语法图 ```ebnf+diagram RecoverTableStmt ::= @@ -35,33 +35,37 @@ Int64Num ::= NUM NUM ::= intLit ``` -## 注意事项 +> **注意:** +> +> + 如果表被删除且超出了 GC 生命周期,则无法使用 `RECOVER TABLE` 恢复该表。在这种情况下执行 `RECOVER TABLE` 会返回类似以下的错误:`snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST`。 +> +> + 如果 TiDB 版本是 3.0.0 或更高版本,不建议在使用 TiDB Binlog 时使用 `RECOVER TABLE`。 +> +> + `RECOVER TABLE` 在 Binlog 3.0.1 版本中得到支持,因此你可以在以下三种情况下使用 `RECOVER TABLE`: +> +> - Binlog 版本为 3.0.1 或更高版本。 +> - 上游集群和下游集群都使用 TiDB 3.0。 +> - 从集群的 GC 生命周期必须长于主集群。但是,由于上下游数据库之间的数据复制存在延迟,下游的数据恢复可能会失败。 -如果删除表后并过了 GC lifetime,就不能再用 `RECOVER TABLE` 来恢复被删除的表了,执行 `RECOVER TABLE` 语句会返回类似错误:`snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST`。 + -对于 3.0.0 及之后的 TiDB 版本,不推荐在使用 TiDB Binlog 的情况下使用 `RECOVER TABLE` 功能。 +**TiDB Binlog 复制期间的错误排查** -TiDB Binlog 在 3.0.1 支持 `RECOVER TABLE` 后,可在下面的情况下使用 `RECOVER TABLE`: +当你在 TiDB Binlog 复制期间在上游 TiDB 中使用 `RECOVER TABLE` 时,TiDB Binlog 可能会在以下三种情况下中断: -* 3.0.1+ 版本的 TiDB Binlog -* 主从集群都使用 TiDB 3.0 -* 从集群 GC lifetime 一定要长于主集群(不过由于上下游同步的延迟,可能也会造成下游 recover 失败) ++ 下游数据库不支持 `RECOVER TABLE` 语句。错误示例:`check the manual that corresponds to your MySQL server version for the right syntax to use near 'RECOVER TABLE table_name'`。 -### TiDB Binlog 同步错误处理 ++ 上游数据库和下游数据库之间的 GC 生命周期不一致。错误示例:`snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST`。 -当使用 TiDB Binlog 同步工具时,上游 TiDB 使用 `RECOVER TABLE` 后,TiDB Binlog 可能会因为下面几个原因造成同步中断: ++ 上游和下游数据库之间的复制存在延迟。错误示例:`snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST`。 -* 下游数据库不支持 `RECOVER TABLE` 语句。类似错误:`check the manual that corresponds to your MySQL server version for the right syntax to use near 'RECOVER TABLE table_name'`。 +对于上述三种情况,你可以通过[对已删除表进行完整导入](/ecosystem-tool-user-guide.md#backup-and-restore---backup--restore-br)来恢复 TiDB Binlog 的数据复制。 -* 上下游数据库的 GC lifetime 不一样。类似错误:`snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST`。 - -* 上下游数据库的同步延迟。类似错误:`snapshot is older than GC safe point 2019-07-10 13:45:57 +0800 CST`。 - -只能通过重新[全量导入被删除的表](/ecosystem-tool-user-guide.md#备份和恢复---backup--restore)来恢复 TiDB Binlog 的数据同步。 + ## 示例 -- 根据表名恢复被删除的表。 ++ 根据表名恢复已删除的表。 {{< copyable "sql" >}} @@ -75,14 +79,11 @@ TiDB Binlog 在 3.0.1 支持 `RECOVER TABLE` 后,可在下面的情况下使 RECOVER TABLE t; ``` - 根据表名恢复被删除的表需满足以下条件: - - - 最近 DDL JOB 历史中找到的第一个 `DROP TABLE` 操作,且 - - `DROP TABLE` 所删除的表的名称与 `RECOVER TABLE` 语句指定表名相同 + 此方法会搜索最近的 DDL 作业历史记录,并定位第一个 `DROP TABLE` 类型的 DDL 操作,然后恢复与 `RECOVER TABLE` 语句中指定的表名相同的已删除表。 -- 根据删除表时的 DDL JOB ID 恢复被删除的表。 ++ 根据表的 `DDL JOB ID` 恢复已删除的表。 - 如果第一次删除表 t 后,又新建了一个表 t,然后又把新建的表 t 删除了,此时如果想恢复最开始删除的表 t,就需要用到指定 DDL JOB ID 的语法了。 + 假设你删除了表 `t` 并创建了另一个 `t`,然后又删除了新创建的 `t`。如果你想恢复第一次删除的 `t`,则必须使用指定 `DDL JOB ID` 的方法。 {{< copyable "sql" >}} @@ -96,7 +97,7 @@ TiDB Binlog 在 3.0.1 支持 `RECOVER TABLE` 后,可在下面的情况下使 ADMIN SHOW DDL JOBS 1; ``` - 上面这个语句用来查找删除表 t 时的 DDL JOB ID,这里是 53: + 上面的第二条语句用于搜索删除 `t` 的表的 `DDL JOB ID`。在下面的示例中,ID 为 `53`。 ``` +--------+---------+------------+------------+--------------+-----------+----------+-----------+-----------------------------------+--------+ @@ -112,15 +113,15 @@ TiDB Binlog 在 3.0.1 支持 `RECOVER TABLE` 后,可在下面的情况下使 RECOVER TABLE BY JOB 53; ``` - 根据删除表时的 DDL JOB ID 恢复被删除的表,会直接用 DDL JOB ID 找到被删除表进行恢复。如果指定的 DDL JOB ID 的 DDL JOB 不是 `DROP TABLE` 类型,会报错。 + 此方法通过 `DDL JOB ID` 恢复已删除的表。如果相应的 DDL 作业不是 `DROP TABLE` 类型,则会发生错误。 -## 原理 +## 实现原理 -TiDB 在删除表时,实际上只删除了表的元信息,并将需要删除的表数据(行数据和索引数据)写一条数据到 `mysql.gc_delete_range` 表。TiDB 后台的 GC Worker 会定期从 `mysql.gc_delete_range` 表中取出超过 GC lifetime 相关范围的 key 进行删除。 +当删除表时,TiDB 只删除表元数据,并将要删除的表数据(行数据和索引数据)写入 `mysql.gc_delete_range` 表。TiDB 后台的 GC Worker 会定期从 `mysql.gc_delete_range` 表中删除超过 GC 生命周期的键。 -所以,RECOVER TABLE 只需要在 GC Worker 还没删除表数据前,恢复表的元信息并删除 `mysql.gc_delete_range` 表中相应的行记录就可以了。恢复表的元信息可以用 TiDB 的快照读实现。具体的快照读内容可以参考[读取历史数据](/read-historical-data.md)文档。 +因此,要恢复表,你只需要在 GC Worker 删除表数据之前恢复表元数据并删除 `mysql.gc_delete_range` 表中的相应行记录。你可以使用 TiDB 的快照读取来恢复表元数据。详情请参考[读取历史数据](/read-historical-data.md)。 -TiDB 中表的恢复是通过快照读获取表的元信息后,再走一次类似于 `CREATE TABLE` 的建表流程,所以 `RECOVER TABLE` 实际上也是一种 DDL。 +表恢复是通过 TiDB 通过快照读取获取表元数据,然后经过类似于 `CREATE TABLE` 的表创建过程来完成的。因此,`RECOVER TABLE` 本质上是一种 DDL 操作。 ## MySQL 兼容性 diff --git a/sql-statements/sql-statement-rename-index.md b/sql-statements/sql-statement-rename-index.md index b0b75a7dfd1e..42965436b762 100644 --- a/sql-statements/sql-statement-rename-index.md +++ b/sql-statements/sql-statement-rename-index.md @@ -1,13 +1,13 @@ --- -title: RENAME INDEX -summary: TiDB 数据库中 RENAME INDEX 的使用概况。 +title: RENAME INDEX | TiDB SQL 语句参考 +summary: TiDB 数据库中 RENAME INDEX 的使用概述。 --- # RENAME INDEX -`ALTER TABLE .. RENAME INDEX` 语句用于对已有索引进行重命名。这在 TiDB 中是即时操作的,仅需更改元数据。 +`ALTER TABLE .. RENAME INDEX` 语句将现有索引重命名为新名称。在 TiDB 中,此操作是即时的,只需要进行元数据更改。 -## 语法图 +## 语法 ```ebnf+diagram AlterTableStmt @@ -19,23 +19,11 @@ RenameIndexSpec ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL, INDEX col1 (c1)); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL, INDEX col1 (c1)); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} -```sql -SHOW CREATE TABLE t1; -``` - -``` +mysql> SHOW CREATE TABLE t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( @@ -45,25 +33,11 @@ Create Table: CREATE TABLE `t1` ( KEY `col1` (`c1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -ALTER TABLE t1 RENAME INDEX col1 TO c1; -``` - -``` +mysql> ALTER TABLE t1 RENAME INDEX col1 TO c1; Query OK, 0 rows affected (0.09 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW CREATE TABLE t1; -``` - -``` +mysql> SHOW CREATE TABLE t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( @@ -77,7 +51,7 @@ Create Table: CREATE TABLE `t1` ( ## MySQL 兼容性 -`RENAME INDEX` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `RENAME INDEX` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-rename-table.md b/sql-statements/sql-statement-rename-table.md index ae7a9f981ffa..9667576a43b9 100644 --- a/sql-statements/sql-statement-rename-table.md +++ b/sql-statements/sql-statement-rename-table.md @@ -1,13 +1,13 @@ --- -title: RENAME TABLE -summary: TiDB 数据库中 RENAME TABLE 的使用概况。 +title: RENAME TABLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 RENAME TABLE 的使用概览。 --- # RENAME TABLE -`RENAME TABLE` 语句用于重命名现有表和视图,支持同时重命名多个表及跨数据库重命名。 +此语句用于重命名现有的表和视图,支持同时重命名多个表以及跨数据库重命名。 -## 语法图 +## 语法 ```ebnf+diagram RenameTableStmt ::= @@ -61,7 +61,7 @@ SHOW TABLES; 1 row in set (0.00 sec) ``` -以下示例演示了如何跨数据库重命名多个表(假设数据库 `db1`、`db2`、`db3` 和 `db4` 已存在,表 `db1.t1` 和 `db3.t3` 已存在): +以下示例演示如何跨数据库重命名多个表,假设数据库 `db1`、`db2`、`db3` 和 `db4` 已经存在,并且表 `db1.t1` 和 `db3.t3` 已经存在: ```sql RENAME TABLE db1.t1 To db2.t2, db3.t3 To db4.t4; @@ -117,7 +117,7 @@ Database changed 1 row in set (0.00 sec) ``` -原子重命名可以确保在交换表时,表始终存在。 +原子重命名可用于替换表,而不会出现表不存在的时刻。 ```sql CREATE TABLE t1(id int PRIMARY KEY); @@ -160,7 +160,7 @@ Create Table: CREATE TABLE `t1` ( ## MySQL 兼容性 -`RENAME TABLE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `RENAME TABLE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-rename-user.md b/sql-statements/sql-statement-rename-user.md index ab2d2d2681af..a37852734cf5 100644 --- a/sql-statements/sql-statement-rename-user.md +++ b/sql-statements/sql-statement-rename-user.md @@ -1,21 +1,19 @@ --- title: RENAME USER -summary: TiDB 数据库中 RENAME USER 的使用概况。 +summary: TiDB 数据库中 RENAME USER 的使用概览。 --- # RENAME USER -`RENAME USER` 语句用于对已有用户进行重命名。 +`RENAME USER` 用于重命名现有用户。 -## 语法图 +## 语法 ```ebnf+diagram RenameUserStmt ::= 'RENAME' 'USER' UserToUser ( ',' UserToUser )* - UserToUser ::= Username 'TO' Username - Username ::= StringName ('@' StringName | singleAtIdentifier)? | 'CURRENT_USER' OptionalBraces ``` @@ -26,7 +24,7 @@ Username ::= CREATE USER 'newuser' IDENTIFIED BY 'mypassword'; ``` -``` +```sql Query OK, 1 row affected (0.02 sec) ``` @@ -34,7 +32,7 @@ Query OK, 1 row affected (0.02 sec) SHOW GRANTS FOR 'newuser'; ``` -``` +```sql +-------------------------------------+ | Grants for newuser@% | +-------------------------------------+ @@ -47,7 +45,7 @@ SHOW GRANTS FOR 'newuser'; RENAME USER 'newuser' TO 'testuser'; ``` -``` +```sql Query OK, 0 rows affected (0.08 sec) ``` @@ -55,7 +53,7 @@ Query OK, 0 rows affected (0.08 sec) SHOW GRANTS FOR 'testuser'; ``` -``` +```sql +--------------------------------------+ | Grants for testuser@% | +--------------------------------------+ @@ -68,13 +66,13 @@ SHOW GRANTS FOR 'testuser'; SHOW GRANTS FOR 'newuser'; ``` -``` +```sql ERROR 1141 (42000): There is no such grant defined for user 'newuser' on host '%' ``` ## MySQL 兼容性 -`RENAME USER` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +`RENAME USER` 预期与 MySQL 完全兼容。如果发现任何兼容性差异,你可以[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-replace.md b/sql-statements/sql-statement-replace.md index 1dda14c5d320..cd75afbe0986 100644 --- a/sql-statements/sql-statement-replace.md +++ b/sql-statements/sql-statement-replace.md @@ -1,11 +1,11 @@ --- -title: REPLACE -summary: TiDB 数据库中 REPLACE 的使用概况。 +title: REPLACE | TiDB SQL 语句参考 +summary: TiDB 数据库中 REPLACE 的使用概览。 --- # REPLACE -从语义上看,`REPLACE` 语句是 `DELETE` 语句和 `INSERT` 语句的结合,可用于简化应用程序代码。 +`REPLACE` 语句在语义上是一个组合的 `DELETE`+`INSERT` 语句。它可以用来简化应用程序代码。 ## 语法图 @@ -30,44 +30,23 @@ InsertValues ::= | SelectStmt | UnionStmt | 'SET' ColumnSetValue? ( ',' ColumnSetValue )* - - ``` > **注意:** > -> TiDB 从 v6.6.0 版本开始支持[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)功能。该功能可以将不同优先级的语句放在不同的资源组中执行,并为这些资源组分配不同的配额和优先级,可以达到更好的资源管控效果。在开启资源管控功能后,语句的调度主要受资源组的控制,`PriorityOpt` 将不再生效。建议在支持资源管控的版本优先使用资源管控功能。 +> 从 v6.6.0 开始,TiDB 支持[资源控制](/tidb-resource-control.md)。你可以使用此功能在不同的资源组中以不同的优先级执行 SQL 语句。通过为这些资源组配置适当的配额和优先级,你可以更好地控制不同优先级 SQL 语句的调度。当启用资源控制时,语句优先级(`PriorityOpt`)将不再生效。建议你使用[资源控制](/tidb-resource-control.md)来管理不同 SQL 语句的资源使用。 ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.12 sec) -``` - -{{< copyable "sql" >}} -```sql -INSERT INTO t1 (c1) VALUES (1), (2), (3); -``` - -``` +mysql> INSERT INTO t1 (c1) VALUES (1), (2), (3); Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -76,25 +55,11 @@ SELECT * FROM t1; | 3 | 3 | +----+----+ 3 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -REPLACE INTO t1 (id, c1) VALUES(3, 99); -``` -``` +mysql> REPLACE INTO t1 (id, c1) VALUES(3, 99); Query OK, 2 rows affected (0.01 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -107,7 +72,7 @@ SELECT * FROM t1; ## MySQL 兼容性 -`REPLACE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `REPLACE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-restore.md b/sql-statements/sql-statement-restore.md index 3dfb4bf73304..366b99d92417 100644 --- a/sql-statements/sql-statement-restore.md +++ b/sql-statements/sql-statement-restore.md @@ -1,31 +1,30 @@ --- -title: RESTORE -summary: TiDB 数据库中 RESTORE 的使用概况。 +title: RESTORE | TiDB SQL 语句参考 +summary: TiDB 数据库中 RESTORE 的使用概览。 --- # RESTORE +该语句从之前由 [`BACKUP` 语句](/sql-statements/sql-statement-backup.md)生成的备份存档执行分布式恢复。 + > **警告:** > -> `RESTORE` 语句目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 - -`RESTORE` 语句用于执行分布式恢复,把 [`BACKUP` 语句](/sql-statements/sql-statement-backup.md)生成的备份文件恢复到 TiDB 集群中。 - -`RESTORE` 语句使用的引擎与 [BR](/br/backup-and-restore-overview.md) 相同,但恢复过程是由 TiDB 本身驱动,而非单独的 BR 工具。BR 工具的优势和警告也适用于 `RESTORE` 语句。需要注意的是,**`RESTORE` 语句目前不遵循 ACID 原则**。 +> - 这是一个实验性功能。不建议在生产环境中使用。此功能可能会在没有事先通知的情况下更改或删除。如果发现错误,你可以在 GitHub 上报告[问题](https://github.com/pingcap/tidb/issues)。 +> - 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 -执行 `RESTORE` 语句前,确保集群已满足以下要求: +`RESTORE` 语句使用与 [BR 工具](https://docs.pingcap.com/tidb/stable/backup-and-restore-overview)相同的引擎,只是恢复过程由 TiDB 本身而不是单独的 BR 工具驱动。BR 的所有优点和注意事项也适用于此。特别是,**`RESTORE` 目前不符合 ACID**。在运行 `RESTORE` 之前,请确保满足以下要求: -* 集群处于“下线”状态,当前的 TiDB 会话是唯一在访问待恢复表的活跃 SQL 连接。 -* 执行全量恢复时,确保即将恢复的表不存在于集群中,因为现有的数据可能被覆盖,从而导致数据与索引不一致。 -* 执行增量恢复时,表的状态应该与创建备份时 `LAST_BACKUP` 时间戳的状态完全一致。 +* 集群处于"离线"状态,当前 TiDB 会话是访问所有要恢复的表的唯一活动 SQL 连接。 +* 当执行完整恢复时,要恢复的表不应该已经存在,因为现有数据可能会被覆盖并导致数据和索引之间的不一致。 +* 当执行增量恢复时,表应该与创建备份时的 `LAST_BACKUP` 时间戳处于完全相同的状态。 -执行 `RESTORE` 需要 `RESTORE_ADMIN` 或 `SUPER` 权限。此外,执行恢复操作的 TiDB 节点和集群中的所有 TiKV 节点都必须有对目标存储的读权限。 +运行 `RESTORE` 需要 `RESTORE_ADMIN` 或 `SUPER` 权限。此外,执行恢复的 TiDB 节点和集群中的所有 TiKV 节点都必须具有目标的读取权限。 -`RESTORE` 语句开始执行后将会被阻塞,直到整个恢复任务完成、失败或取消。因此,执行 `RESTORE` 时需要准备一个持久的连接。如需取消任务,可执行 [`KILL TIDB QUERY`](/sql-statements/sql-statement-kill.md) 语句。 +`RESTORE` 语句是阻塞的,只有在整个恢复任务完成、失败或取消后才会结束。运行 `RESTORE` 应准备一个长期存在的连接。可以使用 [`KILL TIDB QUERY`](/sql-statements/sql-statement-kill.md) 语句取消任务。 -一次只能执行一个 `BACKUP` 和 `RESTORE` 任务。如果 TiDB server 上已经在执行一个 `BACKUP` 或 `RESTORE` 语句,新的 `RESTORE` 将等待前面所有的任务完成后再执行。 +一次只能执行一个 `BACKUP` 和 `RESTORE` 任务。如果同一 TiDB 服务器上已经在运行 `BACKUP` 或 `RESTORE` 任务,新的 `RESTORE` 执行将等待所有先前的任务完成。 -`RESTORE` 只能在 "tikv" 存储引擎上使用,如果使用 "unistore" 存储引擎,`RESTORE` 操作会失败。 +`RESTORE` 只能与 "tikv" 存储引擎一起使用。使用 "unistore" 引擎的 `RESTORE` 将失败。 ## 语法图 @@ -49,7 +48,7 @@ Boolean ::= ## 示例 -### 从备份文件恢复 +### 从备份存档恢复 {{< copyable "sql" >}} @@ -66,21 +65,21 @@ RESTORE DATABASE * FROM 'local:///mnt/backup/2020/04/'; 1 row in set (28.961 sec) ``` -上述示例中,所有数据均从本地的备份文件中恢复到集群中。`RESTORE` 从 SST 文件里读取数据,SST 文件存储在所有 TiDB 和 TiKV 节点的 `/mnt/backup/2020/04/` 目录下。 +在上面的示例中,所有数据都从本地文件系统的备份存档中恢复。数据作为 SST 文件从分布在所有 TiDB 和 TiKV 节点中的 `/mnt/backup/2020/04/` 目录中读取。 -输出结果的第一行描述如下: +上面结果的第一行描述如下: -| 列名 | 描述 | +| 列 | 描述 | | :-------- | :--------- | -| `Destination` | 读取的目标存储 URL | -| `Size` | 备份文件的总大小,单位为字节 | -| `BackupTS` | 不适用 | -| `Queue Time` | `RESTORE` 任务开始排队的时间戳(当前时区) | -| `Execution Time` | `RESTORE` 任务开始执行的时间戳(当前时区) | +| `Destination` | 要读取的目标 URL | +| `Size` | 备份存档的总大小,以字节为单位 | +| `BackupTS` | (未使用) | +| `Queue Time` | `RESTORE` 任务排队的时间戳(当前时区) | +| `Execution Time` | `RESTORE` 任务开始运行的时间戳(当前时区) | ### 部分恢复 -你可以指定恢复部分数据库或部分表数据。如果备份文件中缺失了某些数据库或表,缺失的部分将被忽略。此时,`RESTORE` 语句不进行任何操作即完成执行。 +你可以指定要恢复的数据库或表。如果备份存档中缺少某些数据库或表,它们将被忽略,因此 `RESTORE` 将不执行任何操作就完成。 {{< copyable "sql" >}} @@ -96,7 +95,7 @@ RESTORE TABLE `test`.`sbtest01`, `test`.`sbtest02` FROM 'local:///mnt/backup/202 ### 外部存储 -BR 支持从 Amazon S3 或 Google Cloud Storage (GCS) 恢复数据: +BR 支持从 S3 或 GCS 恢复数据: {{< copyable "sql" >}} @@ -104,9 +103,9 @@ BR 支持从 Amazon S3 或 Google Cloud Storage (GCS) 恢复数据: RESTORE DATABASE * FROM 's3://example-bucket-2020/backup-05/'; ``` -有关详细的 URI 语法,见[外部存储服务的 URI 格式](/external-storage-uri.md)。 +URL 语法在[外部存储服务的 URI 格式](/external-storage-uri.md)中有进一步解释。 -当运行在云环境中时,不能分发凭证,可设置 `SEND_CREDENTIALS_TO_TIKV` 选项为 `FALSE`: +在不应分发凭证的云环境中运行时,将 `SEND_CREDENTIALS_TO_TIKV` 选项设置为 `FALSE`: {{< copyable "sql" >}} @@ -117,9 +116,9 @@ RESTORE DATABASE * FROM 's3://example-bucket-2020/backup-05/' ### 性能调优 -如果你需要减少网络带宽占用,可以通过 `RATE_LIMIT` 来限制每个 TiKV 节点的平均下载速度。 +使用 `RATE_LIMIT` 限制每个 TiKV 节点的平均下载速度以减少网络带宽。 -在恢复完成之前,`RESTORE` 将对备份文件中的数据进行校验,以验证数据的正确性。如果你确定无需进行校验,可以通过将 `CHECKSUM` 参数设置为 `FALSE` 来禁用该检查。 +在恢复完成之前,`RESTORE` 会对备份文件中的数据执行校验和以验证正确性。如果你确信这种验证是不必要的,可以通过将 `CHECKSUM` 参数设置为 `FALSE` 来禁用检查。 {{< copyable "sql" >}} @@ -132,9 +131,9 @@ RESTORE DATABASE * FROM 's3://example-bucket-2020/backup-06/' ### 增量恢复 -增量恢复没有特殊的语法。TiDB 将识别备份文件属于全量备份或增量备份,然后执行对应的恢复操作,用户只需按照正确顺序进行增量恢复。 +执行增量恢复没有特殊语法。TiDB 将识别备份存档是完整的还是增量的,并采取适当的操作。你只需要按正确的顺序应用每个增量恢复。 -假设按照如下方式创建一个备份任务: +例如,如果按如下方式创建备份任务: {{< copyable "sql" >}} @@ -144,7 +143,7 @@ BACKUP DATABASE `test` TO 's3://example-bucket/inc-backup-1' SNAPSHOT = 41497185 BACKUP DATABASE `test` TO 's3://example-bucket/inc-backup-2' SNAPSHOT = 416353458585600 LAST_BACKUP = 414971854848000; ``` -在恢复备份时,需要采取同样的顺序: +那么恢复时应该按相同的顺序应用: {{< copyable "sql" >}} diff --git a/sql-statements/sql-statement-revoke-privileges.md b/sql-statements/sql-statement-revoke-privileges.md index 8f32a86ccd88..6c8807dc1cea 100644 --- a/sql-statements/sql-statement-revoke-privileges.md +++ b/sql-statements/sql-statement-revoke-privileges.md @@ -1,13 +1,13 @@ --- -title: REVOKE -summary: TiDB 数据库中 REVOKE 的使用概况。 +title: REVOKE | TiDB SQL 语句参考 +summary: TiDB 数据库中 REVOKE 的使用概述。 --- # `REVOKE ` -`REVOKE ` 语句用于删除已有用户的权限。执行 `REVOKE ` 语句需要拥有分配的权限,并且拥有 `GRANT OPTION` 权限。 +此语句用于撤销现有用户的权限。执行此语句需要 `GRANT OPTION` 权限以及你要撤销的所有权限。 -## 语法图 +## 语法概要 ```ebnf+diagram RevokeStmt ::= @@ -58,33 +58,14 @@ UserSpecList ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE USER 'newuser' IDENTIFIED BY 'mypassword'; -``` - -``` +mysql> CREATE USER 'newuser' IDENTIFIED BY 'mypassword'; Query OK, 1 row affected (0.02 sec) -``` - -{{< copyable "sql" >}} -```sql -GRANT ALL ON test.* TO 'newuser'; -``` - -``` +mysql> GRANT ALL ON test.* TO 'newuser'; Query OK, 0 rows affected (0.03 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW GRANTS FOR 'newuser'; -``` - -``` +mysql> SHOW GRANTS FOR 'newuser'; +-------------------------------------------------+ | Grants for newuser@% | +-------------------------------------------------+ @@ -92,59 +73,36 @@ SHOW GRANTS FOR 'newuser'; | GRANT ALL PRIVILEGES ON test.* TO 'newuser'@'%' | +-------------------------------------------------+ 2 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -REVOKE ALL ON test.* FROM 'newuser'; -``` - -``` +mysql> REVOKE ALL ON test.* FROM 'newuser'; Query OK, 0 rows affected (0.03 sec) -``` - -{{< copyable "sql" >}} - -```sql -SHOW GRANTS FOR 'newuser'; -``` -``` +mysql> SHOW GRANTS FOR 'newuser'; +-------------------------------------+ | Grants for newuser@% | +-------------------------------------+ | GRANT USAGE ON *.* TO 'newuser'@'%' | +-------------------------------------+ 1 row in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -DROP USER 'newuser'; -``` -``` +mysql> DROP USER 'newuser'; Query OK, 0 rows affected (0.14 sec) -``` - -{{< copyable "sql" >}} - -```sql -SHOW GRANTS FOR 'newuser'; -``` -``` +mysql> SHOW GRANTS FOR 'newuser'; ERROR 1141 (42000): There is no such grant defined for user 'newuser' on host '%' ``` ## MySQL 兼容性 -`REVOKE ` 语句执行成功后,在 TiDB 中语句执行的结果会在当前连接立即生效,而 [MySQL 中部分权限的结果需要等到之后的连接才生效](https://dev.mysql.com/doc/refman/8.0/en/privilege-changes.html)。见 [TiDB #39356](https://github.com/pingcap/tidb/issues/39356)。 +* 在 TiDB 中,`REVOKE ` 语句成功执行后,执行结果会立即在当前连接上生效。而[在 MySQL 中,对于某些权限,执行结果仅在后续连接中生效](https://dev.mysql.com/doc/refman/8.0/en/privilege-changes.html)。详情请参见 [TiDB #39356](https://github.com/pingcap/tidb/issues/39356)。 ## 另请参阅 * [`GRANT `](/sql-statements/sql-statement-grant-privileges.md) * [SHOW GRANTS](/sql-statements/sql-statement-show-grants.md) -* [Privilege Management](/privilege-management.md) + + + +* [权限管理](/privilege-management.md) + + diff --git a/sql-statements/sql-statement-revoke-role.md b/sql-statements/sql-statement-revoke-role.md index 86f4cfeed028..aec5d5eb004e 100644 --- a/sql-statements/sql-statement-revoke-role.md +++ b/sql-statements/sql-statement-revoke-role.md @@ -1,11 +1,11 @@ --- -title: REVOKE -summary: TiDB 数据库中 REVOKE 的使用概况。 +title: REVOKE | TiDB SQL 语句参考 +summary: TiDB 数据库中 REVOKE 的使用概述。 --- # `REVOKE ` -`REVOKE ` 语句用于从指定的用户(或用户列表)中收回之前授予的角色。 +此语句用于从指定用户(或用户列表)中移除之前分配的角色。 ## 语法图 @@ -22,7 +22,7 @@ UsernameList ::= ## 示例 -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root @@ -44,13 +44,13 @@ GRANT analyticsteam TO jennifer; Query OK, 0 rows affected (0.01 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -需要注意的是,默认情况下,用户 `jennifer` 需要执行 `SET ROLE analyticsteam` 语句才能使用与角色相关联的权限: +注意,默认情况下,`jennifer` 需要执行 `SET ROLE analyticsteam` 才能使用与 `analyticsteam` 角色相关的权限: ```sql SHOW GRANTS; @@ -86,26 +86,26 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -执行 `SET DEFAULT ROLE` 语句将用户 `jennifer` 与 `analyticsteam` 角色相关联: +可以使用 `SET DEFAULT ROLE` 语句将角色 `analyticsteam` 关联到 `jennifer`: ```sql SET DEFAULT ROLE analyticsteam TO jennifer; Query OK, 0 rows affected (0.02 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -此时 `jennifer` 用户无需执行 `SET ROLE` 语句就能拥有 `analyticsteam` 角色相关联的权限: +此后,用户 `jennifer` 拥有与角色 `analyticsteam` 相关的权限,且 `jennifer` 不需要执行 `SET ROLE` 语句: ```sql SHOW GRANTS; @@ -127,26 +127,26 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -收回角色 `analyticsteam`: +从 `jennifer` 撤销 analyticsteam 角色: ```sql REVOKE analyticsteam FROM jennifer; Query OK, 0 rows affected (0.01 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -查看 `jennifer` 用户的权限: +显示 `jennifer` 的权限: ```sql SHOW GRANTS; @@ -160,7 +160,7 @@ SHOW GRANTS; ## MySQL 兼容性 -`REVOKE ` 语句与 MySQL 8.0 的角色功能完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `REVOKE ` 语句与 MySQL 8.0 的角色功能完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 @@ -169,4 +169,9 @@ SHOW GRANTS; * [`GRANT `](/sql-statements/sql-statement-grant-role.md) * [`SET ROLE`](/sql-statements/sql-statement-set-role.md) * [`SET DEFAULT ROLE`](/sql-statements/sql-statement-set-default-role.md) + + + * [基于角色的访问控制](/role-based-access-control.md) + + diff --git a/sql-statements/sql-statement-rollback.md b/sql-statements/sql-statement-rollback.md index 564482267467..1a8c74c98420 100644 --- a/sql-statements/sql-statement-rollback.md +++ b/sql-statements/sql-statement-rollback.md @@ -1,13 +1,13 @@ --- -title: ROLLBACK -summary: TiDB 数据库中 ROLLBACK 的使用概况。 +title: ROLLBACK | TiDB SQL 语句参考 +summary: TiDB 数据库中 ROLLBACK 的使用概览。 --- # ROLLBACK -`ROLLBACK` 语句用于还原 TiDB 内当前事务中的所有更改,作用与 `COMMIT` 语句相反。 +此语句撤销 TiDB 中当前事务的所有更改。它是 `COMMIT` 语句的反操作。 -## 语法图 +## 语法 ```ebnf+diagram RollbackStmt ::= @@ -20,60 +20,27 @@ CompletionTypeWithinTransaction ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); -``` - -``` +mysql> CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); Query OK, 0 rows affected (0.12 sec) -``` - -{{< copyable "sql" >}} - -```sql -BEGIN; -``` -``` +mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (1); -``` -``` +mysql> INSERT INTO t1 VALUES (1); Query OK, 1 row affected (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -ROLLBACK; -``` -``` +mysql> ROLLBACK; Query OK, 0 rows affected (0.01 sec) -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; Empty set (0.01 sec) ``` ## MySQL 兼容性 -* TiDB 解析但忽略 `ROLLBACK AND [NO] RELEASE` 语法。在 MySQL 中,使用该语法可在回滚事务后立即断开客户端会话。在 TiDB 中,建议使用客户端程序的 `mysql_close()` 来实现该功能。 -* TiDB 解析但忽略 `ROLLBACK AND [NO] CHAIN` 语法。在 MySQL 中,使用该语法可在回滚当前事务时立即以相同的隔离级别开启新事务。在 TiDB 中,推荐直接开启新事务。 +* TiDB 解析但忽略 `ROLLBACK AND [NO] RELEASE` 语法。此功能在 MySQL 中用于在回滚事务后立即断开客户端会话连接。在 TiDB 中,建议改用客户端驱动程序的 `mysql_close()` 功能。 +* TiDB 解析但忽略 `ROLLBACK AND [NO] CHAIN` 语法。此功能在 MySQL 中用于在当前事务回滚时立即以相同的隔离级别启动新事务。在 TiDB 中,建议直接启动新事务。 ## 另请参阅 diff --git a/sql-statements/sql-statement-savepoint.md b/sql-statements/sql-statement-savepoint.md index 6c660d0f48c4..48cb1af02fe0 100644 --- a/sql-statements/sql-statement-savepoint.md +++ b/sql-statements/sql-statement-savepoint.md @@ -1,11 +1,11 @@ --- -title: SAVEPOINT -summary: TiDB 数据库中 SAVEPOINT 的使用概况。 +title: SAVEPOINT | TiDB SQL 语句参考 +summary: TiDB 数据库中 SAVEPOINT 的使用概述。 --- # SAVEPOINT -`SAVEPOINT` 是 TiDB 从 v6.2.0 开始支持的特性,语法如下: +`SAVEPOINT` 是 TiDB v6.2.0 引入的功能。语法如下: ```sql SAVEPOINT identifier @@ -15,27 +15,28 @@ RELEASE SAVEPOINT identifier > **警告:** > -> `SAVEPOINT` 特性不支持与 TiDB Binlog 一起使用,也不支持在关闭 [`tidb_constraint_check_in_place_pessimistic`](/system-variables.md#tidb_constraint_check_in_place_pessimistic-从-v630-版本开始引入) 的悲观事务中使用。 +> - 启用 TiDB Binlog 时不能使用 `SAVEPOINT`。 +> - 当 [`tidb_constraint_check_in_place_pessimistic`](/system-variables.md#tidb_constraint_check_in_place_pessimistic-new-in-v630) 被禁用时,不能在悲观事务中使用 `SAVEPOINT`。 -- `SAVEPOINT` 语句用于在当前事务中,设置一个指定名字保存点。如果已经存在相同名字的保存点,就删除已有的保存点并设置新的保存点。 +- `SAVEPOINT` 用于在当前事务中设置指定名称的保存点。如果已存在同名的保存点,它将被删除,并设置一个同名的新保存点。 -- `ROLLBACK TO SAVEPOINT` 语句将事务回滚到指定名称的事务保存点,而不终止该事务。当前事务在设置保存点后,对表数据所做的修改将在回滚中撤销,且删除事务保存点之后的所有保存点。在悲观事务中,对于已经持有的悲观锁不会回滚,而是在事务结束时才释放。 +- `ROLLBACK TO SAVEPOINT` 将事务回滚到指定名称的保存点,且不会终止事务。保存点之后对表数据所做的更改将在回滚中被撤销,该保存点之后的所有保存点都将被删除。在悲观事务中,事务持有的锁不会被回滚。相反,这些锁将在事务结束时释放。 - 如果 `ROLLBACK TO SAVEPOINT` 语句中指定名称的保存点不存在,则会返回以下错误信息: + 如果 `ROLLBACK TO SAVEPOINT` 语句中指定的保存点不存在,该语句将返回以下错误: ``` ERROR 1305 (42000): SAVEPOINT identifier does not exist ``` -- `RELEASE SAVEPOINT` 语句将从当前事务中删除指定名称及之后的**_所有_**保存点,而不会提交或回滚当前事务。如果指定名称的保存点不存在,则会返回以下错误信息: +- `RELEASE SAVEPOINT` 语句从当前事务中删除指定名称的保存点以及该保存点之后的**所有保存点**,而不会提交或回滚当前事务。如果指定名称的保存点不存在,将返回以下错误: ``` ERROR 1305 (42000): SAVEPOINT identifier does not exist ``` - 当事务提交或者回滚后,事务中所有保存点都会被删除。 + 事务提交或回滚后,事务中的所有保存点都将被删除。 -## 语法图 +## 语法概要 ```ebnf+diagram SavepointStmt ::= @@ -53,7 +54,7 @@ ReleaseSavepointStmt ::= 创建表 `t1`: ```sql -CREATE TABLE t1 (a int NOT NULL PRIMARY KEY); +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); ``` ```sql @@ -88,7 +89,7 @@ SAVEPOINT sp1; Query OK, 0 rows affected (0.01 sec) ``` -向表中再次插入数据并设置保存点 `sp2`: +再次向表中插入数据并设置保存点 `sp2`: ```sql INSERT INTO t1 VALUES (2); @@ -106,7 +107,7 @@ SAVEPOINT sp2; Query OK, 0 rows affected (0.01 sec) ``` -释放保存点 `sp2`: +释放保存点 `sp2`: ```sql RELEASE SAVEPOINT sp2; @@ -116,7 +117,7 @@ RELEASE SAVEPOINT sp2; Query OK, 0 rows affected (0.01 sec) ``` -回滚至保存点 `sp1`: +回滚到保存点 `sp1`: ```sql ROLLBACK TO SAVEPOINT sp1; @@ -126,7 +127,7 @@ ROLLBACK TO SAVEPOINT sp1; Query OK, 0 rows affected (0.01 sec) ``` -提交事务并查询表格,发现表中仅有 `sp1` 前插入的数据: +提交事务并查询表。只返回 `sp1` 之前插入的数据。 ```sql COMMIT; @@ -151,14 +152,14 @@ SELECT * FROM t1; ## MySQL 兼容性 -使用 `ROLLBACK TO SAVEPOINT` 语句将事物回滚到指定保存点时,MySQL 会释放该保存点之后才持有的锁,但在 TiDB 悲观事务中,不会立即释放该保存点之后才持有的锁,而是等到事务提交或者回滚时,才释放全部持有的锁。 +当使用 `ROLLBACK TO SAVEPOINT` 将事务回滚到指定保存点时,MySQL 会立即释放仅在指定保存点之后持有的锁,而在 TiDB 悲观事务中,TiDB 不会立即释放指定保存点之后持有的锁。相反,TiDB 会在事务提交或回滚时释放所有锁。 -TiDB 不支持 MySQL 中的 `ROLLBACK WORK TO SAVEPOINT ...` 语法。 +TiDB 不支持 MySQL 的 `ROLLBACK WORK TO SAVEPOINT ...` 语法。 ## 另请参阅 * [COMMIT](/sql-statements/sql-statement-commit.md) * [ROLLBACK](/sql-statements/sql-statement-rollback.md) * [START TRANSACTION](/sql-statements/sql-statement-start-transaction.md) -* [TiDB 乐观事务模型](/optimistic-transaction.md) +* [TiDB 乐观事务模式](/optimistic-transaction.md) * [TiDB 悲观事务模式](/pessimistic-transaction.md) diff --git a/sql-statements/sql-statement-select.md b/sql-statements/sql-statement-select.md index 299abcbf1fdc..45e8c96c083a 100644 --- a/sql-statements/sql-statement-select.md +++ b/sql-statements/sql-statement-select.md @@ -1,6 +1,6 @@ --- -title: SELECT -summary: TiDB 数据库中 SELECT 的使用概况。 +title: SELECT | TiDB SQL 语句参考 +summary: TiDB 数据库中 SELECT 的使用概述。 --- # SELECT @@ -55,62 +55,43 @@ TableSampleOpt ::= ## 语法元素说明 -|语法元素 | 说明 | -| --------------------- | -------------------------------------------------- | -|`TableOptimizerHints`| 用于控制优化器行为的 Hint,具体可参见 [Optimizer Hints](/optimizer-hints.md)| -|`ALL`、`DISTINCT`、`DISTINCTROW` | 查询结果集中可能会包含重复值。指定 DISTINCT/DISTINCTROW 则在查询结果中过滤掉重复的行;指定 ALL 则列出所有的行。默认为 ALL。| -|`HIGH_PRIORITY` | 该语句为高优先级语句,TiDB 在执行阶段会优先处理这条语句| -|`SQL_CALC_FOUND_ROWS` | TiDB 不支持该语法,并报错(若 [`tidb_enable_noop_functions`](/system-variables.md#tidb_enable_noop_functions-从-v40-版本开始引入) 值设为 `1` 则不会报错) | -|`SQL_CACHE`、`SQL_NO_CACHE` | 是否把请求结果缓存到 TiKV (RocksDB) 的 `BlockCache` 中。对于一次性的大数据量的查询,比如 `count(*)` 查询,为了避免冲掉 `BlockCache` 中用户的热点数据,建议填上 `SQL_NO_CACHE` | -|`STRAIGHT_JOIN`|`STRAIGHT_JOIN` 会强制优化器按照 `FROM` 子句中所使用的表的顺序做联合查询。当优化器选择的 Join 顺序并不优秀时,你可以使用这个语法来加速查询的执行| -|`select_expr` | 投影操作列表,一般包括列名、表达式,或者是用 '\*' 表示全部列| -|`FROM table_references` | 表示数据来源,数据来源可以是一个表 (`select * from t;`) 或者是多个表 (`select * from t1 join t2;`) 或者是 0 个表(`select 1+1 from dual;`,等价于 `select 1+1;`)| -|`WHERE where_condition` | Where 子句用于设置过滤条件,查询结果中只会包含满足条件的数据| -|`GROUP BY` | GroupBy 子句用于对查询结果集进行分组| -|`HAVING where_condition` | Having 子句与 Where 子句作用类似,Having 子句可以让过滤 GroupBy 后的各种数据,Where 子句用于在聚合前过滤记录。| -|`ORDER BY` | OrderBy 子句用于指定结果排序顺序,可以按照列、表达式或者是 `select_expr` 列表中某个位置的字段进行排序。| -|`LIMIT` | Limit 子句用于限制结果条数。Limit 接受一个或两个数字参数,如果只有一个参数,那么表示返回数据的最大行数;如果是两个参数,那么第一个参数表示返回数据的第一行的偏移量(第一行数据的偏移量是 0),第二个参数指定返回数据的最大条目数。另支持 `FETCH FIRST/NEXT n ROW/ROWS ONLY` 语法,与 `LIMIT n` 效果相同,其中 `n` 可省略,省略时与 `LIMIT 1` 效果相同。| -|`Window window_definition`| 窗口函数的相关语法,用来进行一些分析型计算的操作,详情可见[窗口函数](/functions-and-operators/window-functions.md)| -|`FOR UPDATE` | 对查询结果集所有行上锁(对于在查询条件内,但是不在结果集的行,将不会加锁,如事务启动后由其他事务写入的行),以监测其他事务对这些的并发修改。当 TiDB 使用[乐观事务模型](/optimistic-transaction.md)时,语句执行期间不会检测锁,因此,不会像 PostgreSQL 之类的数据库一样,在当前事务结束前阻止其他事务执行 `UPDATE`、`DELETE` 和 `SELECT FOR UPDATE`。在事务的提交阶段 `SELECT FOR UPDATE` 读到的行,也会进行两阶段提交,因此,它们也可以参与事务冲突检测。如发生写入冲突,那么包含 `SELECT FOR UPDATE` 语句的事务会提交失败。如果没有冲突,事务将成功提交,当提交结束时,这些被加锁的行,会产生一个新版本,可以让其他尚未提交的事务,在将来提交时发现写入冲突。当 TiDB 使用[悲观事务模型](/pessimistic-transaction.md)时,其行为与其他数据库基本相同,不一致之处参考[和 MySQL InnoDB 的差异](/pessimistic-transaction.md#和-mysql-innodb-的差异)。TiDB 支持 `FOR UPDATE NOWAIT` 语法,详情可见 [TiDB 中悲观事务模式的行为](/pessimistic-transaction.md#悲观事务模式的行为)。| -|`LOCK IN SHARE MODE` | TiDB 出于兼容性解析这个语法,但是不做任何处理| -|`TABLESAMPLE`| 从表中获取一些行的样本数据。| +|语法元素|说明| +|:--------------------- | :-------------------------------------------------- | +|`TableOptimizerHints`| 这是用于控制 TiDB 优化器行为的提示。更多信息,请参考[优化器提示](/optimizer-hints.md)。| +|`ALL`,`DISTINCT`,`DISTINCTROW` | `ALL`,`DISTINCT`/`DISTINCTROW` 修饰符指定是否应返回重复行。ALL(默认值)指定应返回所有匹配的行。| +|`HIGH_PRIORITY` | `HIGH_PRIORITY` 给当前语句比其他语句更高的优先级。| +|`SQL_CALC_FOUND_ROWS`| TiDB 不支持此功能,除非设置了 [`tidb_enable_noop_functions=1`](/system-variables.md#tidb_enable_noop_functions-new-in-v40),否则将返回错误。| +|`SQL_CACHE`,`SQL_NO_CACHE` | `SQL_CACHE` 和 `SQL_NO_CACHE` 用于控制是否将请求结果缓存到 TiKV(RocksDB)的 `BlockCache` 中。对于大量数据的一次性查询,如 `count(*)` 查询,建议填写 `SQL_NO_CACHE` 以避免刷新 `BlockCache` 中的热用户数据。| +|`STRAIGHT_JOIN`| `STRAIGHT_JOIN` 强制优化器按照 `FROM` 子句中使用的表的顺序进行联合查询。当优化器选择的联接顺序不好时,可以使用此语法来加快查询的执行速度。| +|`select_expr` | 每个 `select_expr` 表示要检索的列,包括列名和表达式。`\*` 代表所有列。| +|`FROM table_references` | `FROM table_references` 子句指示要从中检索行的表(如 `select * from t;`),或表(如 `select * from t1 join t2;`),甚至是 0 个表(如 `select 1+1 from dual;` 等同于 `select 1+1;`)。| +|`WHERE where_condition` | `WHERE` 子句(如果给定)指示行必须满足的条件才能被选择。结果只包含满足条件的数据。| +|`GROUP BY` | `GROUP BY` 语句用于对结果集进行分组。| +|`HAVING where_condition` | `HAVING` 子句和 `WHERE` 子句都用于过滤结果。`HAVING` 子句过滤 `GROUP BY` 的结果,而 `WHERE` 子句在聚合之前过滤结果。| +|`ORDER BY` | `ORDER BY` 子句用于根据列、表达式或 `select_expr` 列表中的项目按升序或降序对数据进行排序。| +|`LIMIT` | `LIMIT` 子句可用于限制返回的行数。`LIMIT` 接受一个或两个数字参数。使用一个参数时,该参数指定要返回的最大行数,默认情况下第一行是表的第一行;使用两个参数时,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。TiDB 还支持 `FETCH FIRST/NEXT n ROW/ROWS ONLY` 语法,其效果与 `LIMIT n` 相同。在此语法中可以省略 `n`,其效果与 `LIMIT 1` 相同。| +|`Window window_definition`| 这是窗口函数的语法,通常用于进行一些分析计算。更多信息,请参考[窗口函数](/functions-and-operators/window-functions.md)。| +| `FOR UPDATE` | `SELECT FOR UPDATE` 子句锁定结果集中的所有数据以检测来自其他事务的并发更新。匹配查询条件但不存在于结果集中的数据不会被读锁定,例如在当前事务启动后由其他事务写入的行数据。当 TiDB 使用[乐观事务模式](/optimistic-transaction.md)时,在语句执行阶段不会检测事务冲突。因此,当前事务不会像其他数据库(如 PostgreSQL)那样阻止其他事务执行 `UPDATE`、`DELETE` 或 `SELECT FOR UPDATE`。在提交阶段,`SELECT FOR UPDATE` 读取的行以两阶段方式提交,这意味着它们也可以参与冲突检测。如果发生写冲突,包含 `SELECT FOR UPDATE` 子句的所有事务的提交都会失败。如果未检测到冲突,提交成功。并且会为锁定的行生成新版本,以便在稍后提交其他未提交的事务时可以检测到写冲突。当 TiDB 使用[悲观事务模式](/pessimistic-transaction.md)时,行为基本与其他数据库相同。请参考[与 MySQL InnoDB 的差异](/pessimistic-transaction.md#difference-with-mysql-innodb)了解详细信息。TiDB 支持 `FOR UPDATE` 的 `NOWAIT` 修饰符。有关详细信息,请参见 [TiDB 悲观事务模式](/pessimistic-transaction.md#behaviors)。| +|`LOCK IN SHARE MODE` | 为保证兼容性,TiDB 解析这三个修饰符,但会忽略它们。| +| `TABLESAMPLE` | 用于从表中获取行样本。| > **注意:** > -> TiDB 从 v6.6.0 版本开始支持[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)功能。该功能可以将不同优先级的语句放在不同的资源组中执行,并为这些资源组分配不同的配额和优先级,可以达到更好的资源管控效果。在开启资源管控功能后,语句的调度主要受资源组的控制,`HIGH_PRIORITY` 将不再生效。建议在支持资源管控的版本优先使用资源管控功能。 +> 从 v6.6.0 开始,TiDB 支持[资源控制](/tidb-resource-control.md)。你可以使用此功能在不同的资源组中以不同的优先级执行 SQL 语句。通过为这些资源组配置适当的配额和优先级,你可以更好地控制不同优先级 SQL 语句的调度。当启用资源控制时,语句优先级(`HIGH_PRIORITY`)将不再生效。建议你使用[资源控制](/tidb-resource-control.md)来管理不同 SQL 语句的资源使用。 ## 示例 ### SELECT -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -123,8 +104,6 @@ SELECT * FROM t1; 5 rows in set (0.00 sec) ``` -下面这个例子使用 `tiup bench tpcc prepare` 生成的数据,其中第一个查询展示了 `TABLESAMPLE` 的用法。 - ```sql mysql> SELECT AVG(s_quantity), COUNT(s_quantity) FROM stock TABLESAMPLE REGIONS(); +-----------------+-------------------+ @@ -143,21 +122,24 @@ mysql> SELECT AVG(s_quantity), COUNT(s_quantity) FROM stock; 1 row in set (0.52 sec) ``` +上面的示例使用了通过 `tiup bench tpcc prepare` 生成的数据。第一个查询展示了 `TABLESAMPLE` 的使用。 + ### SELECT ... INTO OUTFILE -`SELECT ... INTO OUTFILE` 语句用于将查询结果写入到文件中。 +`SELECT ... INTO OUTFILE` 语句用于将查询结果写入文件。 > **注意:** > -> 该语句不支持将查询结果写入任何[外部存储](/br/backup-and-restore-storages.md),如 Amazon S3 或 GCS。 +> - 此语句仅适用于 TiDB 自建集群,在 [TiDB Cloud](https://docs.pingcap.com/tidbcloud/) 上不可用。 +> - 此语句不支持将查询结果写入任何[外部存储](https://docs.pingcap.com/tidb/stable/backup-and-restore-storages),如 Amazon S3 或 GCS。 -在该语句中,你可以使用以下子句来指定输出文件的格式: +在语句中,你可以使用以下子句指定输出文件的格式: -- `FIELDS TERMINATED BY`:指定文件中字段的分隔符。例如,你可以将分隔符指定为 `','` 以输出逗号分隔值(CSV)或 `'\t'` 以输出制表符分隔值(TSV)。 -- `FIELDS ENCLOSED BY`:指定文件中包裹每个字段的字符。 -- `LINES TERMINATED BY`:如果你希望以某个特殊的字符为结尾来切分行数据,可以使用该子句指定文件中行的终止符。 +- `FIELDS TERMINATED BY`:指定文件中的字段分隔符。例如,你可以指定为 `','` 以输出逗号分隔值(CSV)或 `'\t'` 以输出制表符分隔值(TSV)。 +- `FIELDS ENCLOSED BY`:指定包围文件中每个字段的封闭字符。 +- `LINES TERMINATED BY`:指定文件中的行终止符,如果你想用某个字符结束一行。 -假设有一个名为 `t` 的表,包含以下三列: +假设有一个包含三列的表 `t`,如下所示: ```sql mysql> CREATE TABLE t (a INT, b VARCHAR(10), c DECIMAL(10,2)); @@ -167,16 +149,16 @@ mysql> INSERT INTO t VALUES (1, 'a', 1.1), (2, 'b', 2.2), (3, 'c', 3.3); Query OK, 3 rows affected (0.01 sec) ``` -以下示例展示了如何使用 `SELECT ... INTO OUTFILE` 语句将查询结果写入到文件中。 +以下示例展示如何使用 `SELECT ... INTO OUTFILE` 语句将查询结果写入文件。 -**示例 1:** +**示例 1:** ```sql mysql> SELECT * FROM t INTO OUTFILE '/tmp/tmp_file1'; Query OK, 3 rows affected (0.00 sec) ``` -在此示例中,你可以在 `/tmp/tmp_file1` 中看到以下查询结果: +在此示例中,你可以在 `/tmp/tmp_file1` 中找到如下查询结果: ``` 1 a 1.10 @@ -184,14 +166,14 @@ Query OK, 3 rows affected (0.00 sec) 3 c 3.30 ``` -**示例 2:** +**示例 2:** ```sql mysql> SELECT * FROM t INTO OUTFILE '/tmp/tmp_file2' FIELDS TERMINATED BY ',' ENCLOSED BY '"'; Query OK, 3 rows affected (0.00 sec) ``` -在此示例中,你可以在 `/tmp/tmp_file2` 中看到以下查询结果: +在此示例中,你可以在 `/tmp/tmp_file2` 中找到如下查询结果: ``` "1","a","1.10" @@ -199,7 +181,7 @@ Query OK, 3 rows affected (0.00 sec) "3","c","3.30" ``` -**示例 3:** +**示例 3:** ```sql mysql> SELECT * FROM t INTO OUTFILE '/tmp/tmp_file3' @@ -207,7 +189,7 @@ mysql> SELECT * FROM t INTO OUTFILE '/tmp/tmp_file3' Query OK, 3 rows affected (0.00 sec) ``` -在此示例中,你可以在 `/tmp/tmp_file3` 中看到以下查询结果: +在此示例中,你可以在 `/tmp/tmp_file3` 中找到如下查询结果: ``` '1','a','1.10'<<< @@ -219,8 +201,8 @@ Query OK, 3 rows affected (0.00 sec) - 不支持 `SELECT ... INTO @variable` 语法。 - 不支持 `SELECT ... INTO DUMPFILE` 语法。 -- 不支持 MySQL 5.7 中支持的 `SELECT .. GROUP BY expr` 语法,而是匹配 MySQL 8.0 的行为,不按照默认的顺序进行排序。 -- `SELECT ... TABLESAMPLE ...` 是 TiDB 的扩展语法,用于兼容其他数据库以及 [ISO/IEC 9075-2](https://standards.iso.org/iso-iec/9075/-2/ed-6/en/) 标准,但 MySQL 不支持该语法。 +- `SELECT .. GROUP BY expr` 语法不像在 MySQL 5.7 中那样隐含 `GROUP BY expr ORDER BY expr`。TiDB 反而匹配 MySQL 8.0 的行为,不隐含默认顺序。 +- `SELECT ... TABLESAMPLE ...` 语法是 TiDB 的扩展,设计用于与其他数据库系统和 [ISO/IEC 9075-2](https://standards.iso.org/iso-iec/9075/-2/ed-6/en/) 标准兼容,但目前 MySQL 不支持此语法。 ## 另请参阅 diff --git a/sql-statements/sql-statement-set-default-role.md b/sql-statements/sql-statement-set-default-role.md index eccef140c46a..2cdd6f4dfefd 100644 --- a/sql-statements/sql-statement-set-default-role.md +++ b/sql-statements/sql-statement-set-default-role.md @@ -1,13 +1,13 @@ --- -title: SET DEFAULT ROLE -summary: TiDB 数据库中 SET DEFAULT ROLE 的使用概况。 +title: SET DEFAULT ROLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 SET DEFAULT ROLE 的使用概述。 --- # `SET DEFAULT ROLE` -`SET DEFAULT ROLE` 语句默认设置将特定角色应用于用户。因此,用户不必执行 `SET ROLE ` 或 `SET ROLE ALL` 语句,也可以自动具有与角色相关联的权限。 +此语句用于设置默认应用于用户的特定角色。这样,用户无需执行 `SET ROLE ` 或 `SET ROLE ALL` 就可以自动拥有与该角色相关联的权限。 -## 语法图 +## 语法概要 ```ebnf+diagram SetDefaultRoleStmt ::= @@ -16,13 +16,13 @@ SetDefaultRoleStmt ::= ## 示例 -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -创建新角色 `analyticsteam` 和新用户 `jennifer`: +创建一个新角色 `analyticsteam` 和一个新用户 `jennifer`: ```sql CREATE ROLE analyticsteam; @@ -38,13 +38,13 @@ GRANT analyticsteam TO jennifer; Query OK, 0 rows affected (0.01 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -需要注意的是,默认情况下,用户 `jennifer` 需要执行 `SET ROLE analyticsteam` 语句才能使用与 `analyticsteam` 角色相关联的权限: +注意,默认情况下,`jennifer` 需要执行 `SET ROLE analyticsteam` 才能使用与 `analyticsteam` 角色相关联的权限: ```sql SHOW GRANTS; @@ -80,26 +80,26 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -以 `root` 用户连接 TiDB: +以 `root` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u root ``` -执行 `SET DEFAULT ROLE` 语句将用户 `jennifer` 与 `analyticsteam` 角色相关联: +可以使用 `SET DEFAULT ROLE` 语句将角色 `analyticsteam` 关联到 `jennifer`: ```sql SET DEFAULT ROLE analyticsteam TO jennifer; Query OK, 0 rows affected (0.02 sec) ``` -以 `jennifer` 用户连接 TiDB: +以 `jennifer` 用户身份连接到 TiDB: ```shell mysql -h 127.0.0.1 -P 4000 -u jennifer ``` -此时 `jennifer` 用户无需执行 `SET ROLE` 语句就能拥有 `analyticsteam` 角色相关联的权限: +此后,用户 `jennifer` 拥有与角色 `analyticsteam` 相关联的权限,且 `jennifer` 不需要执行 `SET ROLE` 语句: ```sql SHOW GRANTS; @@ -121,7 +121,7 @@ SHOW TABLES IN test; 1 row in set (0.00 sec) ``` -`SET DEFAULT ROLE` 语句不会自动将相关角色授予 (`GRANT`) 用户。若尝试为 `jennifer` 尚未被授予的角色执行 `SET DEFAULT ROLE` 语句会导致以下错误: +`SET DEFAULT ROLE` 不会自动将相关角色 `GRANT` 给用户。尝试为 `jennifer` 设置未被授予的角色作为默认角色会导致以下错误: ```sql SET DEFAULT ROLE analyticsteam TO jennifer; @@ -130,7 +130,7 @@ ERROR 3530 (HY000): `analyticsteam`@`%` is is not granted to jennifer@% ## MySQL 兼容性 -`SET DEFAULT ROLE` 语句与 MySQL 8.0 的角色功能完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SET DEFAULT ROLE` 语句与 MySQL 8.0 的角色功能完全兼容。如果发现任何兼容性差异,请[报告 bug](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 @@ -139,4 +139,9 @@ ERROR 3530 (HY000): `analyticsteam`@`%` is is not granted to jennifer@% * [`GRANT `](/sql-statements/sql-statement-grant-role.md) * [`REVOKE `](/sql-statements/sql-statement-revoke-role.md) * [`SET ROLE`](/sql-statements/sql-statement-set-role.md) + + + * [基于角色的访问控制](/role-based-access-control.md) + + diff --git a/sql-statements/sql-statement-set-names.md b/sql-statements/sql-statement-set-names.md index 8d68a42519be..0e091da87ecf 100644 --- a/sql-statements/sql-statement-set-names.md +++ b/sql-statements/sql-statement-set-names.md @@ -1,11 +1,11 @@ --- -title: SET [NAMES|CHARACTER SET] -summary: TiDB 数据库中 SET [NAMES|CHARACTER SET] 的使用概况。 +title: SET [NAMES|CHARACTER SET] | TiDB SQL 语句参考 +summary: TiDB 数据库中 SET [NAMES|CHARACTER SET] 的使用概览。 --- # SET [NAMES|CHARACTER SET] -`SET NAMES`,`SET CHARACTER SET` 和 `SET CHARSET` 语句用于修改当前连接的变量 `character_set_client`,`character_set_results` 和 `character_set_connection`。 +`SET NAMES`、`SET CHARACTER SET` 和 `SET CHARSET` 语句修改当前连接的 `character_set_client`、`character_set_results` 和 `character_set_connection` 变量。 ## 语法图 @@ -17,10 +17,7 @@ SetNamesStmt ::= ## 示例 ```sql -SHOW VARIABLES LIKE 'character_set%'; -``` - -``` +mysql> SHOW VARIABLES LIKE 'character_set%'; +--------------------------+--------------------------------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------------------------------+ @@ -34,21 +31,11 @@ SHOW VARIABLES LIKE 'character_set%'; | character_set_server | utf8mb4 | +--------------------------+--------------------------------------------------------+ 8 rows in set (0.01 sec) -``` - -```sql -SET NAMES utf8; -``` -``` +mysql> SET NAMES utf8; Query OK, 0 rows affected (0.00 sec) -``` - -```sql -SHOW VARIABLES LIKE 'character_set%'; -``` -``` +mysql> SHOW VARIABLES LIKE 'character_set%'; +--------------------------+--------------------------------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------------------------------+ @@ -62,21 +49,11 @@ SHOW VARIABLES LIKE 'character_set%'; | character_set_filesystem | binary | +--------------------------+--------------------------------------------------------+ 8 rows in set (0.00 sec) -``` - -```sql -SET CHARACTER SET utf8mb4; -``` -``` +mysql> SET CHARACTER SET utf8mb4; Query OK, 0 rows affected (0.00 sec) -``` -```sql -SHOW VARIABLES LIKE 'character_set%'; -``` - -``` +mysql> SHOW VARIABLES LIKE 'character_set%'; +--------------------------+--------------------------------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------------------------------+ @@ -94,10 +71,10 @@ SHOW VARIABLES LIKE 'character_set%'; ## MySQL 兼容性 -`SET [NAMES|CHARACTER SET]` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SET [NAMES|CHARACTER SET]` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 * [SHOW \[GLOBAL|SESSION\] VARIABLES](/sql-statements/sql-statement-show-variables.md) * [`SET `](/sql-statements/sql-statement-set-variable.md) -* [Character Set Support](/character-set-and-collation.md) +* [字符集和排序规则支持](/character-set-and-collation.md) diff --git a/sql-statements/sql-statement-set-password.md b/sql-statements/sql-statement-set-password.md index a8dd89d9b177..46db3ddf3670 100644 --- a/sql-statements/sql-statement-set-password.md +++ b/sql-statements/sql-statement-set-password.md @@ -1,13 +1,13 @@ --- -title: SET PASSWORD -summary: TiDB 数据库中 SET PASSWORD 的使用概况。 +title: SET PASSWORD | TiDB SQL 语句参考 +summary: TiDB 数据库中 SET PASSWORD 的使用概述。 --- # SET PASSWORD -`SET PASSWORD` 语句用于更改 TiDB 系统数据库中的用户密码。 +此语句用于更改 TiDB 系统数据库中用户账户的密码。 -## 语法图 +## 语法 ```ebnf+diagram SetPasswordStmt ::= @@ -16,85 +16,36 @@ SetPasswordStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -SET PASSWORD='test'; -``` - -``` +mysql> SET PASSWORD='test'; -- 更改我的密码 Query OK, 0 rows affected (0.01 sec) -``` - -{{< copyable "sql" >}} -```sql -CREATE USER 'newuser' IDENTIFIED BY 'test'; -``` - -``` +mysql> CREATE USER 'newuser' IDENTIFIED BY 'test'; Query OK, 1 row affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW CREATE USER 'newuser'; -``` - -``` +mysql> SHOW CREATE USER 'newuser'; +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE USER for newuser@% | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE USER 'newuser'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SET PASSWORD FOR 'newuser' = 'test'; -``` - -``` +mysql> SET PASSWORD FOR newuser = 'test'; Query OK, 0 rows affected (0.01 sec) -``` - -{{< copyable "sql" >}} - -```sql -SHOW CREATE USER 'newuser'; -``` -``` +mysql> SHOW CREATE USER 'newuser'; +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE USER for newuser@% | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE USER 'newuser'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -SET PASSWORD FOR 'newuser' = PASSWORD('test'); -``` -上述语法是早期 MySQL 版本的过时语法。 - -``` +mysql> SET PASSWORD FOR newuser = PASSWORD('test'); -- 早期 MySQL 版本中已弃用的语法 Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW CREATE USER 'newuser'; -``` - -``` +mysql> SHOW CREATE USER 'newuser'; +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE USER for newuser@% | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -105,9 +56,14 @@ SHOW CREATE USER 'newuser'; ## MySQL 兼容性 -`SET PASSWORD` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SET PASSWORD` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 * [CREATE USER](/sql-statements/sql-statement-create-user.md) -* [Privilege Management](/privilege-management.md) + + + +* [权限管理](/privilege-management.md) + + diff --git a/sql-statements/sql-statement-set-resource-group.md b/sql-statements/sql-statement-set-resource-group.md index c8e110cbcefc..304d96d4b213 100644 --- a/sql-statements/sql-statement-set-resource-group.md +++ b/sql-statements/sql-statement-set-resource-group.md @@ -1,11 +1,15 @@ --- title: SET RESOURCE GROUP -summary: TiDB 数据库中 SET RESOURCE GROUP 的使用概况。 +summary: TiDB 数据库中 SET RESOURCE GROUP 的使用概述。 --- # SET RESOURCE GROUP -`SET RESOURCE GROUP` 用于设置当前会话使用的资源组。 +`SET RESOURCE GROUP` 用于设置当前会话的资源组。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ## 语法图 @@ -22,7 +26,7 @@ ResourceGroupName ::= ## 示例 -创建一个用户 `user1`,创建两个资源组 `rg1` 和 `rg2`,并将用户 `user1` 绑定资源组 `rg1`。 +创建用户 `user1`,创建两个资源组 `rg1` 和 `rg2`,并将用户 `user1` 绑定到资源组 `rg1`。 ```sql CREATE USER 'user1'; @@ -30,13 +34,13 @@ CREATE RESOURCE GROUP 'rg1' RU_PER_SEC = 1000; ALTER USER 'user1' RESOURCE GROUP `rg1`; ``` -使用 `user1` 登录,查看当前用户绑定的资源组。 +使用 `user1` 登录并查看当前用户绑定的资源组。 ```sql SELECT CURRENT_RESOURCE_GROUP(); ``` -```sql +``` +--------------------------+ | CURRENT_RESOURCE_GROUP() | +--------------------------+ @@ -52,7 +56,7 @@ SET RESOURCE GROUP `rg2`; SELECT CURRENT_RESOURCE_GROUP(); ``` -```sql +``` +--------------------------+ | CURRENT_RESOURCE_GROUP() | +--------------------------+ @@ -61,7 +65,7 @@ SELECT CURRENT_RESOURCE_GROUP(); 1 row in set (0.00 sec) ``` -执行 `SET RESOURCE GROUP` 设置当前会话使用默认资源组。 +执行 `SET RESOURCE GROUP` 指定当前会话使用默认资源组。 ```sql SET RESOURCE GROUP `default`; @@ -79,11 +83,11 @@ SELECT CURRENT_RESOURCE_GROUP(); ## MySQL 兼容性 -MySQL 也支持 [SET RESOURCE GROUP](https://dev.mysql.com/doc/refman/8.0/en/set-resource-group.html),但是接受的参数和 TiDB 不同,两者并不兼容。 +MySQL 也支持 [SET RESOURCE GROUP](https://dev.mysql.com/doc/refman/8.0/en/set-resource-group.html)。但是可接受的参数与 TiDB 的不同,它们不兼容。 ## 另请参阅 * [CREATE RESOURCE GROUP](/sql-statements/sql-statement-create-resource-group.md) * [DROP RESOURCE GROUP](/sql-statements/sql-statement-drop-resource-group.md) * [ALTER RESOURCE GROUP](/sql-statements/sql-statement-alter-resource-group.md) -* [使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md) +* [资源控制](/tidb-resource-control.md) diff --git a/sql-statements/sql-statement-set-role.md b/sql-statements/sql-statement-set-role.md index 567a5c27baf3..fa0c39c0e2da 100644 --- a/sql-statements/sql-statement-set-role.md +++ b/sql-statements/sql-statement-set-role.md @@ -1,13 +1,13 @@ --- -title: SET ROLE -summary: TiDB 数据库中 SET ROLE 的使用概况。 +title: SET ROLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 SET ROLE 的使用概览。 --- # SET ROLE -`SET ROLE` 用于在当前用户会话中启用角色。使用 `SET ROLE` 启用角色后,用户可以使用这些角色的权限。 +`SET ROLE` 语句用于在当前会话中启用角色。启用角色后,用户可以使用该角色的权限。 -## 语法图 +## 语法 ```ebnf+diagram SetRoleStmt ::= @@ -16,7 +16,7 @@ SetRoleStmt ::= ## 示例 -创建一个用户 `'u1'@'%'`,创建三个角色 `'r1'@'%'`、`'r2'@'%'` 和 `'r3'@'%'` 并将这些角色授予给 `'u1'@'%'`。将 `'u1'@'%'` 的默认启用角色设置为 `'r1'@'%'`。 +创建一个用户 `'u1'@'%'` 和三个角色:`'r1'@'%'`、`'r2'@'%'` 和 `'r3'@'%'`。将这些角色授予 `'u1'@'%'` 并将 `'r1'@'%'` 设置为 `'u1'@'%'` 的默认角色。 ```sql CREATE USER 'u1'@'%'; @@ -25,7 +25,7 @@ GRANT 'r1', 'r2', 'r3' TO 'u1'@'%'; SET DEFAULT ROLE 'r1' TO 'u1'@'%'; ``` -使用 `'u1'@'%'` 登录,执行 `SET ROLE` 将启用角色设置为 `ALL`。 +以 `'u1'@'%'` 身份登录并执行以下 `SET ROLE` 语句以启用所有角色。 ```sql SET ROLE ALL; @@ -41,7 +41,7 @@ SELECT CURRENT_ROLE(); 1 row in set (0.000 sec) ``` -执行 `SET ROLE` 将启用角色设置为 `'r2'` 和 `'r3'`。 +执行以下 `SET ROLE` 语句以启用 `'r2'` 和 `'r3'`。 ```sql SET ROLE 'r2', 'r3'; @@ -57,7 +57,7 @@ SELECT CURRENT_ROLE(); 1 row in set (0.000 sec) ``` -执行 `SET ROLE` 将启用角色设置为 `DEFAULT`。 +执行以下 `SET ROLE` 语句以启用默认角色。 ```sql SET ROLE DEFAULT; @@ -73,7 +73,7 @@ SELECT CURRENT_ROLE(); 1 row in set (0.000 sec) ``` -执行 `SET ROLE` 将启用角色设置为 `NONE`。 +执行以下 `SET ROLE` 语句以取消所有已启用的角色。 ```sql SET ROLE NONE; @@ -91,13 +91,18 @@ SELECT CURRENT_ROLE(); ## MySQL 兼容性 -`SET ROLE` 语句与 MySQL 8.0 的角色功能完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SET ROLE` 语句与 MySQL 8.0 的角色功能完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 -* [`CREATE ROLE`](/sql-statements/sql-statement-create-role.md) -* [`DROP ROLE`](/sql-statements/sql-statement-drop-role.md) +* [CREATE ROLE](/sql-statements/sql-statement-create-role.md) +* [DROP ROLE](/sql-statements/sql-statement-drop-role.md) * [`GRANT `](/sql-statements/sql-statement-grant-role.md) * [`REVOKE `](/sql-statements/sql-statement-revoke-role.md) -* [`SET DEFAULT ROLE`](/sql-statements/sql-statement-set-default-role.md) +* [SET DEFAULT ROLE](/sql-statements/sql-statement-set-default-role.md) + + + * [基于角色的访问控制](/role-based-access-control.md) + + diff --git a/sql-statements/sql-statement-set-transaction.md b/sql-statements/sql-statement-set-transaction.md index d0e1fb67df39..4d5efc27d68d 100644 --- a/sql-statements/sql-statement-set-transaction.md +++ b/sql-statements/sql-statement-set-transaction.md @@ -1,20 +1,19 @@ --- -title: SET TRANSACTION -summary: TiDB 数据库中 SET TRANSACTION 的使用概况。 +title: SET TRANSACTION | TiDB SQL 语句参考 +summary: TiDB 数据库中 SET TRANSACTION 的使用概述。 --- # SET TRANSACTION -`SET TRANSACTION` 语句用于在 `GLOBAL` 或 `SESSION` 的基础上更改当前的隔离级别,是 `SET transaction_isolation ='new-value'` 的替代语句,提供 MySQL 和 SQL 标准的兼容性。 +`SET TRANSACTION` 语句可用于在 `GLOBAL` 或 `SESSION` 级别更改当前的隔离级别。这种语法是 `SET transaction_isolation='new-value'` 的替代方式,包含它是为了与 MySQL 和 SQL 标准保持兼容。 -## 语法图 +## 语法 ```ebnf+diagram - SetStmt ::= - 'SET' ( VariableAssignmentList | - 'PASSWORD' ('FOR' Username)? '=' PasswordOpt | - ( 'GLOBAL'| 'SESSION' )? 'TRANSACTION' TransactionChars | + 'SET' ( VariableAssignmentList | + 'PASSWORD' ('FOR' Username)? '=' PasswordOpt | + ( 'GLOBAL'| 'SESSION' )? 'TRANSACTION' TransactionChars | 'CONFIG' ( Identifier | stringLit) ConfigItemName EqOrAssignmentEq SetExpr ) TransactionChars ::= @@ -29,63 +28,30 @@ AsOfClause ::= ## 示例 -{{< copyable "sql" >}} - ```sql -SHOW SESSION VARIABLES LIKE 'transaction_isolation'; -``` - -``` +mysql> SHOW SESSION VARIABLES LIKE 'transaction_isolation'; +-----------------------+-----------------+ | Variable_name | Value | +-----------------------+-----------------+ | transaction_isolation | REPEATABLE-READ | +-----------------------+-----------------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -``` - -``` +mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW SESSION VARIABLES LIKE 'transaction_isolation'; -``` - -``` +mysql> SHOW SESSION VARIABLES LIKE 'transaction_isolation'; +-----------------------+----------------+ | Variable_name | Value | +-----------------------+----------------+ | transaction_isolation | READ-COMMITTED | +-----------------------+----------------+ 1 row in set (0.01 sec) -``` - -{{< copyable "sql" >}} - -```sql -SET SESSION transaction_isolation = 'REPEATABLE-READ'; -``` -``` +mysql> SET SESSION transaction_isolation = 'REPEATABLE-READ'; Query OK, 0 rows affected (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW SESSION VARIABLES LIKE 'transaction_isolation'; -``` - -``` +mysql> SHOW SESSION VARIABLES LIKE 'transaction_isolation'; +-----------------------+-----------------+ | Variable_name | Value | +-----------------------+-----------------+ @@ -96,12 +62,12 @@ SHOW SESSION VARIABLES LIKE 'transaction_isolation'; ## MySQL 兼容性 -* TiDB 支持仅在语法中将事务设置为只读的功能。 -* 不支持隔离级别 `READ-UNCOMMITTED` 和 `SERIALIZABLE`。 -* 通过快照隔离 (Snapshot Isolation) 技术,实现乐观事务的 `REPEATABLE-READ` 隔离级别,和 MySQL 兼容。 -* 在悲观事务中,TiDB 支持与 MySQL 兼容的 `REPEATABLE-READ` 和 `READ-COMMITTED` 两种隔离级别。具体描述详见 [Isolation Levels](/transaction-isolation-levels.md)。 +* TiDB 仅在语法上支持将事务设置为只读。 +* 不支持 `READ-UNCOMMITTED` 和 `SERIALIZABLE` 隔离级别。 +* `REPEATABLE-READ` 隔离级别是通过使用快照隔离技术实现的,与 MySQL 部分兼容。 +* 在悲观事务中,TiDB 支持两种与 MySQL 兼容的隔离级别:`REPEATABLE-READ` 和 `READ-COMMITTED`。详细说明请参见[隔离级别](/transaction-isolation-levels.md)。 ## 另请参阅 -* [`SET \[GLOBAL|SESSION\] `](/sql-statements/sql-statement-set-variable.md) -* [Isolation Levels](/transaction-isolation-levels.md) +* [`SET [GLOBAL|SESSION] `](/sql-statements/sql-statement-set-variable.md) +* [隔离级别](/transaction-isolation-levels.md) diff --git a/sql-statements/sql-statement-set-variable.md b/sql-statements/sql-statement-set-variable.md index e31eb0dfecd9..1f4c9c357fff 100644 --- a/sql-statements/sql-statement-set-variable.md +++ b/sql-statements/sql-statement-set-variable.md @@ -1,19 +1,19 @@ --- -title: SET [GLOBAL|SESSION] -summary: TiDB 数据库中 SET [GLOBAL|SESSION] 的使用概况。 +title: SET [GLOBAL|SESSION] | TiDB SQL 语句参考 +summary: TiDB 数据库中 SET [GLOBAL|SESSION] 的使用概述。 --- # `SET [GLOBAL|SESSION] ` -`SET [GLOBAL|SESSION]` 语句用于对某个 TiDB 的内置变量进行更改。这些变量可以是范围为 `SESSION` 或 `GLOBAL` 的[系统变量](/system-variables.md)或是[用户自定义变量](/user-defined-variables.md)。 +`SET [GLOBAL|SESSION]` 语句用于修改 TiDB 的内置变量。这些变量可以是作用域为 `SESSION` 或 `GLOBAL` 的[系统变量](/system-variables.md)或[用户变量](/user-defined-variables.md)。 > **警告:** > -> 用户自定义变量为实验特性,不建议在生产环境中使用。 +> 用户定义变量仍然是一个实验性功能。**不建议**在生产环境中使用它们。 > **注意:** > -> 与 MySQL 类似,对 `GLOBAL` 变量的更改不适用于已有连接或本地连接,只有新会话才会反映值的变化。 +> 与 MySQL 类似,对 `GLOBAL` 变量的更改不会应用于现有连接或本地连接。只有新会话才会反映值的更改。 ## 语法图 @@ -23,31 +23,23 @@ SetVariableStmt ::= Variable ::= ("GLOBAL" | "SESSION") SystemVariable -| UserVariable +| UserVariable ``` ## 示例 -获取 `sql_mode` 的值: +获取 `sql_mode` 的值。 ```sql -SHOW GLOBAL VARIABLES LIKE 'sql_mode'; -``` - -``` +mysql> SHOW GLOBAL VARIABLES LIKE 'sql_mode'; +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value | +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | 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) -``` -```sql -SHOW SESSION VARIABLES LIKE 'sql_mode'; -``` - -``` +mysql> SHOW SESSION VARIABLES LIKE 'sql_mode'; +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value | +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ @@ -56,36 +48,21 @@ SHOW SESSION VARIABLES LIKE 'sql_mode'; 1 row in set (0.00 sec) ``` -更新全局的 `sql_mode`: +全局更新 `sql_mode` 的值。如果在更新后检查 `SQL_mode` 的值,你可以看到 `SESSION` 级别的值尚未更新: ```sql -SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER'; -``` - -``` +mysql> SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER'; Query OK, 0 rows affected (0.03 sec) -``` - -检查更新之后的 `sql_mode` 的取值,可以看到 SESSION 级别的值没有更新: - -```sql -SHOW GLOBAL VARIABLES LIKE 'sql_mode'; -``` -``` +mysql> SHOW GLOBAL VARIABLES LIKE 'sql_mode'; +---------------+-----------------------------------------+ | Variable_name | Value | +---------------+-----------------------------------------+ | sql_mode | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER | +---------------+-----------------------------------------+ 1 row in set (0.00 sec) -``` - -```sql -SHOW SESSION VARIABLES LIKE 'sql_mode'; -``` -``` +mysql> SHOW SESSION VARIABLES LIKE 'sql_mode'; +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value | +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ @@ -94,21 +71,13 @@ SHOW SESSION VARIABLES LIKE 'sql_mode'; 1 row in set (0.00 sec) ``` -`SET SESSION` 则可以立即生效: +使用 `SET SESSION` 会立即生效: ```sql -SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER'; -``` - -``` +mysql> SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER'; Query OK, 0 rows affected (0.01 sec) -``` -```sql -SHOW SESSION VARIABLES LIKE 'sql_mode'; -``` - -``` +mysql> SHOW SESSION VARIABLES LIKE 'sql_mode'; +---------------+-----------------------------------------+ | Variable_name | Value | +---------------+-----------------------------------------+ @@ -117,7 +86,7 @@ SHOW SESSION VARIABLES LIKE 'sql_mode'; 1 row in set (0.00 sec) ``` -以 `@` 开头的用户变量: +用户变量以 `@` 开头。 ```sql SET @myvar := 5; @@ -134,12 +103,12 @@ SELECT @myvar, @myvar + 1; ## MySQL 兼容性 -使用 `SET [GLOBAL|SESSION] ` 更改系统变量上,TiDB 与 MySQL 存在以下差异 +存在以下行为差异: -* 与 MySQL 不同,TiDB 中使用 `SET GLOBAL` 所作的修改会应用于集群中的全部 TiDB 实例。而在 MySQL 中,修改不会应用于副本。 -* TiDB 中的若干变量可读又可设置,这是与 MySQL 相兼容的要求,因为应用程序和连接器常读取 MySQL 变量。例如:JDBC 连接器同时读取和设置缓存查询的参数,尽管并不依赖这一行为。 -* 即使在 TiDB 服务器重启后,`SET GLOBAL` 的更改也仍然有效。这样,TiDB 中的 `SET GLOBAL` 更类似于 MySQL 8.0 及更高版本中的 `SET PERSIST`。 -* TiDB 会持久化全局变量,因此 TiDB 不支持 `SET PERSIST` 和 `SET PERSIST_ONLY`。 +* 使用 `SET GLOBAL` 进行的更改将传播到集群中的所有 TiDB 实例。这与 MySQL 不同,在 MySQL 中更改不会传播到副本。 +* TiDB 将多个变量设置为既可读又可设置。这是 MySQL 兼容性所必需的,因为应用程序和连接器通常都会读取 MySQL 变量。例如:JDBC 连接器会读取和设置查询缓存设置,尽管不依赖该行为。 +* 使用 `SET GLOBAL` 进行的更改将在 TiDB 服务器重启后保持。这意味着 TiDB 中的 `SET GLOBAL` 的行为更类似于 MySQL 8.0 及以上版本中的 `SET PERSIST`。 +* TiDB 不支持 `SET PERSIST` 和 `SET PERSIST_ONLY`,因为 TiDB 会持久化全局变量。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-analyze-status.md b/sql-statements/sql-statement-show-analyze-status.md index e3306e9e627e..d85b210cbc87 100644 --- a/sql-statements/sql-statement-show-analyze-status.md +++ b/sql-statements/sql-statement-show-analyze-status.md @@ -1,35 +1,34 @@ --- title: SHOW ANALYZE STATUS -summary: TiDB 数据库中 SHOW ANALYZE STATUS 的使用概况。 +summary: TiDB 数据库中 SHOW ANALYZE STATUS 的使用概述。 --- # SHOW ANALYZE STATUS -`SHOW ANALYZE STATUS` 语句提供 TiDB 正在执行的统计信息收集任务以及有限条历史任务记录。 +`SHOW ANALYZE STATUS` 语句显示 TiDB 正在执行的统计信息收集任务和有限数量的历史任务记录。 -从 TiDB v6.1.0 起,执行 `SHOW ANALYZE STATUS` 语句将显示集群级别的任务,且 TiDB 重启后仍能看到重启之前的任务记录。在 TiDB v6.1.0 之前,执行 `SHOW ANALYZE STATUS` 语句仅显示实例级别的任务,且 TiDB 重启后任务记录会被清空。 +从 TiDB v6.1.0 开始,`SHOW ANALYZE STATUS` 语句支持显示集群级别的任务。即使在 TiDB 重启后,你仍然可以使用此语句查看重启前的任务记录。在 TiDB v6.1.0 之前,`SHOW ANALYZE STATUS` 语句只能显示实例级别的任务,且任务记录会在 TiDB 重启后被清除。 -从 TiDB v6.1.0 起,你可以通过系统表 `mysql.analyze_jobs` 查看过去 7 天内的历史记录。 +从 TiDB v6.1.0 开始,你可以通过系统表 `mysql.analyze_jobs` 查看最近 7 天的历史任务。 -从 TiDB v7.3.0 起,你可以通过系统表 `mysql.analyze_jobs` 或者 `SHOW ANALYZE STATUS` 查看当前 `ANALYZE` 任务的进度。 +从 TiDB v7.3.0 开始,你可以通过系统表 `mysql.analyze_jobs` 或 `SHOW ANALYZE STATUS` 查看当前 `ANALYZE` 任务的进度。 目前,`SHOW ANALYZE STATUS` 语句返回以下列: -| 列名 | 说明 | -| :-------- | :------------- | -| `Table_schema` | 数据库名 | -| `Table_name` | 表名 | +| 列名 | 描述 | +| :--------------- | :------------- | +| `Table_schema` | 数据库名 | +| `Table_name` | 表名 | | `Partition_name` | 分区名 | -| `Job_info` | 任务具体信息。当收集索引的统计信息时,该信息会包含索引名。当 `tidb_analyze_version = 2` 时,该信息会包含采样率等配置项。 | -| `Processed_rows` | 已经 `ANALYZE` 的行数 | -| `Start_time` | 任务开始执行的时间 | -| `End_time` | 任务结束执行的时间 | -| `State` | 任务状态,包括 pending(等待)、running(正在执行)、finished(执行成功)和 failed(执行失败)| -| `Fail_reason` | 任务失败的原因。如果执行成功则为 `NULL`。 | -| `Instance` | 执行任务的 TiDB 实例 | -| `Process_id` | 执行任务的 process ID | +| `Job_info` | 任务信息。如果分析了索引,此信息将包括索引名。当 `tidb_analyze_version =2` 时,此信息将包括采样率等配置项。 | +| `Processed_rows` | 已分析的行数 | +| `Start_time` | 任务开始时间 | +| `State` | 任务状态,包括 `pending`、`running`、`finished` 和 `failed` | +| `Fail_reason` | 任务失败的原因。如果执行成功,该值为 `NULL`。 | +| `Instance` | 执行任务的 TiDB 实例 | +| `Process_id` | 执行任务的进程 ID | -## 语法图 +## 语法概要 ```ebnf+diagram ShowAnalyzeStatusStmt ::= 'SHOW' 'ANALYZE' 'STATUS' ShowLikeOrWhereOpt @@ -83,8 +82,8 @@ mysql> show analyze status; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [`ANALYZE_STATUS` 表](/information-schema/information-schema-analyze-status.md) \ No newline at end of file +* [ANALYZE_STATUS 表](/information-schema/information-schema-analyze-status.md) diff --git a/sql-statements/sql-statement-show-backups.md b/sql-statements/sql-statement-show-backups.md index 50a70263ff13..3743b69b48cd 100644 --- a/sql-statements/sql-statement-show-backups.md +++ b/sql-statements/sql-statement-show-backups.md @@ -1,15 +1,23 @@ --- -title: SHOW [BACKUPS|RESTORES] -summary: TiDB 数据库中 SHOW [BACKUPS|RESTORES] 的使用概况。 +title: SHOW [BACKUPS|RESTORES] | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW [BACKUPS|RESTORES] 的使用概览。 --- # SHOW [BACKUPS|RESTORES] -`SHOW [BACKUPS|RESTORES]` 语句会列出所有队列中或正在执行的 [`BACKUP`](/sql-statements/sql-statement-backup.md) 和 [`RESTORE`](/sql-statements/sql-statement-restore.md) 任务。 +这些语句显示在 TiDB 实例上执行的所有排队、正在运行和最近完成的 [`BACKUP`](/sql-statements/sql-statement-backup.md) 和 [`RESTORE`](/sql-statements/sql-statement-restore.md) 任务的列表。 -查询 `BACKUP` 任务时,使用 `SHOW BACKUPS` 语句。查询 `RESTORE` 任务时,使用 `SHOW RESTORES` 语句。执行两个语句均需要 `SUPER` 权限。 +这两个语句都需要 `SUPER` 权限才能运行。 -## 语法图 +使用 `SHOW BACKUPS` 查询 `BACKUP` 任务,使用 `SHOW RESTORES` 查询 `RESTORE` 任务。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +使用 `br` 命令行工具启动的备份和恢复不会显示在结果中。 + +## 语法 ```ebnf+diagram ShowBRIEStmt ::= @@ -22,15 +30,15 @@ ShowLikeOrWhere ::= ## 示例 -在一个连接中,执行以下命令备份数据库: +在一个连接中执行以下语句: {{< copyable "sql" >}} ```sql -BACKUP DATABASE `test` TO 's3://example-bucket/backup-01/'; +BACKUP DATABASE `test` TO 's3://example-bucket/backup-01'; ``` -在备份完成之前,在新的连接中执行 `SHOW BACKUPS`: +在备份完成之前,在新连接中运行 `SHOW BACKUPS`: {{< copyable "sql" >}} @@ -39,27 +47,36 @@ SHOW BACKUPS; ``` ```sql -+--------------------------------+---------+----------+---------------------+---------------------+-------------+------------+ -| Destination | State | Progress | Queue_Time | Execution_Time | Finish_Time | Connection | -+--------------------------------+---------+----------+---------------------+---------------------+-------------+------------+ -| s3://example-bucket/backup-01/ | Backup | 98.38 | 2020-04-12 23:09:03 | 2020-04-12 23:09:25 | NULL | 4 | -+--------------------------------+---------+----------+---------------------+---------------------+-------------+------------+ ++--------------------------------+---------+----------+---------------------+---------------------+-------------+------------+---------+ +| Destination | State | Progress | Queue_time | Execution_time | Finish_time | Connection | Message | ++--------------------------------+---------+----------+---------------------+---------------------+-------------+------------+---------+ +| s3://example-bucket/backup-01/ | Backup | 98.38 | 2020-04-12 23:09:03 | 2020-04-12 23:09:25 | NULL | 4 | NULL | ++--------------------------------+---------+----------+---------------------+---------------------+-------------+------------+---------+ 1 row in set (0.00 sec) ``` -输出结果的第一行描述如下: +上述结果的第一行描述如下: | 列名 | 描述 | | :-------- | :--------- | -| `Destination` | 目标存储的 URL(为避免泄露密钥,所有参数均不显示) | +| `Destination` | 目标 URL(已去除所有参数以避免泄露密钥) | | `State` | 任务状态 | -| `Progress` | 当前状态的进度(百分比) | -| `Queue Time` | 任务开始排队的时间 | -| `Execution Time` | 任务开始执行的时间;对于队列中任务,该值为 `0000-00-00 00:00:00` | -| `Finish_Time` | (暂不适用) | -| `Connection` | 运行任务的连接 ID | +| `Progress` | 当前状态下的估计进度百分比 | +| `Queue_time` | 任务排队的时间 | +| `Execution_time` | 任务开始执行的时间;对于排队中的任务,值为 `0000-00-00 00:00:00` | +| `Finish_time` | 任务完成的时间戳;对于排队中和正在运行的任务,值为 `0000-00-00 00:00:00` | +| `Connection` | 运行此任务的连接 ID | +| `Message` | 包含详细信息的消息 | + +可能的状态有: + +| 状态 | 描述 | +| :-----|:------------| +| Backup | 正在进行备份 | +| Wait | 等待执行 | +| Checksum | 正在运行校验和操作 | -连接 ID 可用于在 [`KILL TIDB QUERY`](/sql-statements/sql-statement-kill.md) 语句中取消备份/恢复任务: +连接 ID 可以通过 [`KILL TIDB QUERY`](/sql-statements/sql-statement-kill.md) 语句用来取消备份/恢复任务。 {{< copyable "sql" >}} @@ -73,7 +90,7 @@ Query OK, 0 rows affected (0.00 sec) ### 过滤 -在 `LIKE` 子句中使用通配符,可以按目标存储 URL 筛选任务: +使用 `LIKE` 子句通过将目标 URL 与通配符表达式匹配来过滤任务。 {{< copyable "sql" >}} @@ -81,7 +98,7 @@ Query OK, 0 rows affected (0.00 sec) SHOW BACKUPS LIKE 's3://%'; ``` -使用 `WHERE` 子句,可以按列筛选任务: +使用 `WHERE` 子句按列进行过滤。 {{< copyable "sql" >}} @@ -91,7 +108,7 @@ SHOW BACKUPS WHERE `Progress` < 25.0; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-bindings.md b/sql-statements/sql-statement-show-bindings.md index 213cb7eeae02..eb7b955a5117 100644 --- a/sql-statements/sql-statement-show-bindings.md +++ b/sql-statements/sql-statement-show-bindings.md @@ -1,11 +1,11 @@ --- title: SHOW [GLOBAL|SESSION] BINDINGS -summary: TiDB 数据库中 SHOW [GLOBAL|SESSION] BINDINGS 的使用概况。 +summary: TiDB 数据库中 SHOW BINDINGS 绑定的使用。 --- # SHOW [GLOBAL|SESSION] BINDINGS -`SHOW BINDINGS` 语句用于显示创建过的 SQL 绑定的相关信息。`BINDING` 语句可以在 `GLOBAL` 或者 `SESSION` 作用域内显示执行计划绑定。在不指定作用域时,默认的作用域为 `SESSION`。 +`SHOW BINDINGS` 语句用于显示已创建的 SQL 绑定信息。`BINDING` 可以是 `GLOBAL` 或 `SESSION` 级别。默认是 `SESSION`。 ## 语法图 @@ -20,60 +20,60 @@ ShowLikeOrWhere ::= ## 语法说明 -该语句会输出 GLOBAL 或者 SESSION 作用域内的执行计划绑定,在不指定作用域时默认作用域为 SESSION。目前 `SHOW BINDINGS` 会输出 8 列,具体如下: +该语句输出 GLOBAL 或 SESSION 级别的执行计划绑定。默认范围是 SESSION。目前 `SHOW BINDINGS` 输出八列,如下所示: -| 列名 | 说明 | +| 列名 | 描述 | | :---------- | :------------- | -| original_sql | 参数化后的原始 SQL | -| bind_sql | 带 Hint 的绑定 SQL | -| default_db | 默认数据库名 | -| status | 状态,包括 using(正在使用)、deleted(已删除)、 invalid(无效)、rejected(演进时被拒绝)和 pending verify(等待演进验证) | +| original_sql | 参数化后的原始 SQL 语句 | +| bind_sql | 带有提示的绑定 SQL 语句 | +| default_db | 默认数据库 | +| status | 状态,包括 'Using'、'Deleted'、'Invalid'、'Rejected' 和 'Pending verification' | | create_time | 创建时间 | | update_time | 更新时间 | | charset | 字符集 | | collation | 排序规则 | -| source | 创建方式,包括 manual (由 `create [global] binding` 生成)、capture(由 tidb 自动创建生成)和 evolve (由 tidb 自动演进生成) | +| source | 绑定创建的方式,包括 `manual`(通过 `create [global] binding` SQL 语句创建)、`capture`(由 TiDB 自动捕获)和 `evolve`(由 TiDB 自动演进) | ## 示例 ```sql -CREATE TABLE t1 ( - id INT NOT NULL PRIMARY KEY auto_increment, - b INT NOT NULL, - pad VARBINARY(255), - INDEX(b) - ); +mysql> CREATE TABLE t1 ( + id INT NOT NULL PRIMARY KEY auto_increment, + b INT NOT NULL, + pad VARBINARY(255), + INDEX(b) + ); Query OK, 0 rows affected (0.07 sec) -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM dual; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM dual; Query OK, 1 row affected (0.01 sec) Records: 1 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 8 rows affected (0.00 sec) Records: 8 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 1000 rows affected (0.04 sec) Records: 1000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (1.74 sec) Records: 100000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (2.15 sec) Records: 100000 Duplicates: 0 Warnings: 0 -INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; +mysql> INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; Query OK, 100000 rows affected (2.64 sec) Records: 100000 Duplicates: 0 Warnings: 0 -SELECT SLEEP(1); +mysql> SELECT SLEEP(1); +----------+ | SLEEP(1) | +----------+ @@ -81,10 +81,10 @@ SELECT SLEEP(1); +----------+ 1 row in set (1.00 sec) -ANALYZE TABLE t1; +mysql> ANALYZE TABLE t1; Query OK, 0 rows affected (1.33 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ @@ -94,13 +94,13 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------------+---------+---------+-----------+----------------------+---------------------------------------------------------------------------+-----------------------------------+----------------+------+ 3 rows in set (0.02 sec) -CREATE SESSION BINDING FOR - SELECT * FROM t1 WHERE b = 123 - USING - SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123; +mysql> CREATE SESSION BINDING FOR + SELECT * FROM t1 WHERE b = 123 + USING + SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123; Query OK, 0 rows affected (0.00 sec) -EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +mysql> EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ @@ -110,7 +110,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 WHERE b = 123; +-------------------------+-----------+---------+-----------+---------------+--------------------------------------------------------------------------------+--------------------+---------------+------+ 3 rows in set (0.22 sec) -SHOW SESSION BINDINGS\G +mysql> SHOW SESSION BINDINGS\G *************************** 1. row *************************** Original_sql: select * from t1 where b = ? Bind_sql: SELECT * FROM t1 IGNORE INDEX (b) WHERE b = 123 @@ -125,12 +125,12 @@ Original_sql: select * from t1 where b = ? ## MySQL 兼容性 -`SHOW [GLOBAL|SESSION] BINDINGS` 语句是 TiDB 对 MySQL 语法的扩展。 +该语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 * [CREATE [GLOBAL|SESSION] BINDING](/sql-statements/sql-statement-create-binding.md) * [DROP [GLOBAL|SESSION] BINDING](/sql-statements/sql-statement-drop-binding.md) -* [ANALYZE](/sql-statements/sql-statement-analyze-table.md) -* [Optimizer Hints](/optimizer-hints.md) -* [执行计划管理 (SPM)](/sql-plan-management.md) +* [ANALYZE TABLE](/sql-statements/sql-statement-analyze-table.md) +* [优化器提示](/optimizer-hints.md) +* [SQL 计划管理](/sql-plan-management.md) diff --git a/sql-statements/sql-statement-show-builtins.md b/sql-statements/sql-statement-show-builtins.md index 8a17cbaeed5e..2265f8a24e23 100644 --- a/sql-statements/sql-statement-show-builtins.md +++ b/sql-statements/sql-statement-show-builtins.md @@ -1,13 +1,13 @@ --- title: SHOW BUILTINS -summary: TiDB 数据库中 SHOW BUILTINS 的使用概况。 +summary: TiDB 中 SHOW BUILTINS 的使用。 --- # SHOW BUILTINS -`SHOW BUILTINS` 语句用于列出 TiDB 中所有的内置函数。 +`SHOW BUILTINS` 用于列出 TiDB 中所有支持的内置函数。 -## 语法图 +## 语法概要 ```ebnf+diagram ShowBuiltinsStmt ::= @@ -299,4 +299,4 @@ SHOW BUILTINS; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 diff --git a/sql-statements/sql-statement-show-character-set.md b/sql-statements/sql-statement-show-character-set.md index e6708a10656d..d23880f76cd5 100644 --- a/sql-statements/sql-statement-show-character-set.md +++ b/sql-statements/sql-statement-show-character-set.md @@ -1,11 +1,11 @@ --- -title: SHOW CHARACTER SET -summary: TiDB 数据库中 SHOW CHARACTER SET 的使用概况。 +title: SHOW CHARACTER SET | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW CHARACTER SET 的使用概述。 --- # SHOW CHARACTER SET -`SHOW CHARACTER SET` 语句提供 TiDB 中可用字符集的静态列表。此列表不反映当前连接或用户的任何属性。 +此语句提供 TiDB 中可用字符集的静态列表。输出不反映当前连接或用户的任何属性。 ## 语法图 @@ -68,7 +68,7 @@ SHOW CHARACTER SET WHERE Description='UTF-8 Unicode'; ## MySQL 兼容性 -`SHOW CHARACTER SET` 语句功能与 MySQL 完全兼容。注意,TiDB 中字符集的默认排序规则与 MySQL 有所不同,具体可以参考[与 MySQL 兼容性对比](/mysql-compatibility.md#默认设置)。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中 `SHOW CHARACTER SET` 语句的用法与 MySQL 完全兼容。但是,TiDB 中的字符集可能与 MySQL 相比具有不同的默认排序规则。详情请参考[与 MySQL 的兼容性](/mysql-compatibility.md)。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-collation.md b/sql-statements/sql-statement-show-collation.md index 318e218c9a20..9218ef635b1d 100644 --- a/sql-statements/sql-statement-show-collation.md +++ b/sql-statements/sql-statement-show-collation.md @@ -1,17 +1,17 @@ --- -title: SHOW COLLATION -summary: TiDB 数据库中 SHOW COLLATION 的使用概况。 +title: SHOW COLLATION | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW COLLATION 的使用概述。 --- # SHOW COLLATION -`SHOW COLLATION` 语句用于提供一个静态的排序规则列表,确保与 MySQL 客户端库的兼容性。 +此语句提供排序规则的静态列表,包含它是为了与 MySQL 客户端库保持兼容。 > **注意:** > -> `SHOW COLLATION` 所展示的排序规则列表与 TiDB 集群是否开启[新排序规则框架](/character-set-and-collation.md#新框架下的排序规则支持)有关,详情请见 [TiDB 字符集和排序规则](/character-set-and-collation.md)。 +> 当启用["新的排序规则框架"](/character-set-and-collation.md#new-framework-for-collations)时,`SHOW COLLATION` 的结果会有所不同。有关新排序规则框架的详细信息,请参阅[字符集和排序规则](/character-set-and-collation.md)。 -## 语法图 +## 语法 ```ebnf+diagram ShowCollationStmt ::= @@ -24,13 +24,13 @@ ShowLikeOrWhere ::= ## 示例 -若未开启新排序规则框架,仅展示二进制排序规则: +当禁用新的排序规则框架时,只显示二进制排序规则。 ```sql SHOW COLLATION; ``` -```sql +``` +-------------+---------+------+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen | +-------------+---------+------+---------+----------+---------+ @@ -43,13 +43,13 @@ SHOW COLLATION; 5 rows in set (0.02 sec) ``` -若开启了新排序规则框架,则在二进制排序规则之外,额外支持 `utf8_general_ci` 和 `utf8mb4_general_ci` 两种大小写和口音不敏感的排序规则: +当启用新的排序规则框架时,还额外支持 `utf8_general_ci` 和 `utf8mb4_general_ci`。 ```sql SHOW COLLATION; ``` -```sql +``` +--------------------+---------+------+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen | +--------------------+---------+------+---------+----------+---------+ @@ -68,7 +68,7 @@ SHOW COLLATION; 11 rows in set (0.001 sec) ``` -要过滤字符集,可以添加 `WHERE` 子句。 +要筛选字符集,你可以添加 `WHERE` 子句。 ```sql SHOW COLLATION WHERE Charset="utf8mb4"; @@ -89,7 +89,7 @@ SHOW COLLATION WHERE Charset="utf8mb4"; ## MySQL 兼容性 -`SHOW COLLATION` 语句功能与 MySQL 完全兼容。注意,TiDB 中字符集的默认排序规则与 MySQL 有所不同,具体可参考[与 MySQL 兼容性对比](/mysql-compatibility.md#默认设置)。如发现任何其他兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中 `SHOW COLLATION` 语句的用法与 MySQL 完全兼容。但是,TiDB 中的字符集可能与 MySQL 相比有不同的默认排序规则。详情请参阅[与 MySQL 的兼容性](/mysql-compatibility.md)。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-column-stats-usage.md b/sql-statements/sql-statement-show-column-stats-usage.md index 7c7f98f02f76..ddb596ceeaef 100644 --- a/sql-statements/sql-statement-show-column-stats-usage.md +++ b/sql-statements/sql-statement-show-column-stats-usage.md @@ -1,28 +1,29 @@ --- title: SHOW COLUMN_STATS_USAGE -summary: TiDB 数据库中 SHOW COLUMN_STATS_USAGE 的使用概况。 +summary: TiDB 数据库中 SHOW COLUMN_STATS_USAGE 的使用概览。 --- # SHOW COLUMN_STATS_USAGE -`SHOW COLUMN_STATS_USAGE` 语句显示列统计信息的最近一次使用时间和收集时间。你还可以使用该语句来查看 `PREDICATE COLUMNS` 和已收集统计信息的列。 +`SHOW COLUMN_STATS_USAGE` 语句显示列统计信息的最后使用时间和收集时间。你还可以使用它来定位 `PREDICATE COLUMNS` 和已收集统计信息的列。 目前,`SHOW COLUMN_STATS_USAGE` 语句返回以下列: -| 列名 | 说明 | +| 列名 | 描述 | | -------- | ------------- | -| `Db_name` | 数据库名 | +| `Db_name` | 数据库名称 | | `Table_name` | 表名 | -| `Partition_name` | 分区名 | +| `Partition_name` | 分区名称 | | `Column_name` | 列名 | -| `Last_used_at` | 最近一次将列统计信息用于查询优化的时间 | -| `Last_analyzed_at` | 最近一次收集列统计信息的时间 | +| `Last_used_at` | 列统计信息在查询优化中最后一次使用的时间 | +| `Last_analyzed_at` | 列统计信息最后一次收集的时间 | -## 语法图 +## 语法 ```ebnf+diagram ShowColumnStatsUsageStmt ::= "SHOW" "COLUMN_STATS_USAGE" ShowLikeOrWhere? + ShowLikeOrWhere ::= "LIKE" SimpleExpr | "WHERE" Expression @@ -49,9 +50,9 @@ SHOW COLUMN_STATS_USAGE; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 * [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) -* [常规统计信息](/statistics.md) \ No newline at end of file +* [统计信息简介](/statistics.md) diff --git a/sql-statements/sql-statement-show-columns-from.md b/sql-statements/sql-statement-show-columns-from.md index d6861a6657f5..609cd7f1ebb7 100644 --- a/sql-statements/sql-statement-show-columns-from.md +++ b/sql-statements/sql-statement-show-columns-from.md @@ -1,19 +1,19 @@ --- -title: SHOW [FULL] COLUMNS FROM -summary: TiDB 数据库中 SHOW [FULL] COLUMNS FROM 的使用概况。 +title: SHOW [FULL] COLUMNS FROM | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW [FULL] COLUMNS FROM 的使用概述。 --- # SHOW [FULL] COLUMNS FROM -`SHOW [FULL] COLUMNS FROM ` 语句用于以表格格式描述表或视图中的列。可选关键字 `FULL` 用于显示当前用户对该列的权限,以及表定义中的 `comment`。 +`SHOW [FULL] COLUMNS FROM ` 语句以有用的表格格式描述表或视图的列。可选关键字 `FULL` 显示当前用户对该列的权限,以及来自表定义的 `comment`。 -`SHOW [FULL] FIELDS FROM `、`DESC `、`DESCRIBE ` 和 `EXPLAIN ` 语句都是 `SHOW [FULL] COLUMNS FROM` 的别名。 +语句 `SHOW [FULL] FIELDS FROM `、`DESC `、`DESCRIBE ` 和 `EXPLAIN ` 都是此语句的别名。 > **注意:** > -> `DESC TABLE `、`DESCRIBE TABLE ` 和 `EXPLAIN TABLE ` 与上面的语句并不等价,它们是 [`DESC SELECT * FROM `](/sql-statements/sql-statement-explain.md) 的别名。 +> `DESC TABLE `、`DESCRIBE TABLE ` 和 `EXPLAIN TABLE ` 与上述语句不等价。它们是 [`DESC SELECT * FROM `](/sql-statements/sql-statement-explain.md) 的别名。 -## 语法图 +## 语法概要 ```ebnf+diagram ShowColumnsFromStmt ::= @@ -30,96 +30,58 @@ ShowLikeOrWhere ::= ## 示例 ```sql -CREATE VIEW v1 AS SELECT 1; -``` - -``` +mysql> CREATE VIEW v1 AS SELECT 1; Query OK, 0 rows affected (0.11 sec) -``` - -```sql -SHOW COLUMNS FROM v1; -``` -``` +mysql> SHOW COLUMNS FROM v1; +-------+-----------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------+------+------+---------+-------+ | 1 | bigint(1) | YES | | NULL | | +-------+-----------+------+------+---------+-------+ 1 row in set (0.00 sec) -``` -```sql -DESC v1; -``` - -``` +mysql> DESC v1; +-------+-----------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------+------+------+---------+-------+ | 1 | bigint(1) | YES | | NULL | | +-------+-----------+------+------+---------+-------+ 1 row in set (0.00 sec) -``` -```sql -DESCRIBE v1; -``` - -``` +mysql> DESCRIBE v1; +-------+-----------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------+------+------+---------+-------+ | 1 | bigint(1) | YES | | NULL | | +-------+-----------+------+------+---------+-------+ 1 row in set (0.00 sec) -``` -```sql -EXPLAIN v1; -``` - -``` +mysql> EXPLAIN v1; +-------+-----------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------+------+------+---------+-------+ | 1 | bigint(1) | YES | | NULL | | +-------+-----------+------+------+---------+-------+ 1 row in set (0.00 sec) -``` -```sql -SHOW FIELDS FROM v1; -``` - -``` +mysql> SHOW FIELDS FROM v1; +-------+-----------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------+------+------+---------+-------+ | 1 | bigint(1) | YES | | NULL | | +-------+-----------+------+------+---------+-------+ 1 row in set (0.00 sec) -``` -```sql -SHOW FULL COLUMNS FROM v1 -``` - -``` +mysql> SHOW FULL COLUMNS FROM v1; +-------+-----------+-----------+------+------+---------+-------+---------------------------------+---------+ | Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment | +-------+-----------+-----------+------+------+---------+-------+---------------------------------+---------+ | 1 | bigint(1) | NULL | YES | | NULL | | select,insert,update,references | | +-------+-----------+-----------+------+------+---------+-------+---------------------------------+---------+ 1 row in set (0.00 sec) -``` -```sql -SHOW FULL COLUMNS FROM mysql.user; -``` - -``` +mysql> SHOW FULL COLUMNS FROM mysql.user; +------------------------+---------------+-------------+------+------+---------+-------+---------------------------------+---------+ | Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment | +------------------------+---------------+-------------+------+------+---------+-------+---------------------------------+---------+ @@ -167,7 +129,7 @@ SHOW FULL COLUMNS FROM mysql.user; ## MySQL 兼容性 -`SHOW [FULL] COLUMNS FROM` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW [FULL] COLUMNS FROM` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告 bug](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-create-database.md b/sql-statements/sql-statement-show-create-database.md index 3d64aa940f9c..c2735309b150 100644 --- a/sql-statements/sql-statement-show-create-database.md +++ b/sql-statements/sql-statement-show-create-database.md @@ -1,11 +1,11 @@ --- title: SHOW CREATE DATABASE -summary: TiDB 数据库中 SHOW CREATE DATABASE 的使用概况。 +summary: TiDB 数据库中 SHOW CREATE DATABASE 的使用概览。 --- # SHOW CREATE DATABASE -`SHOW CREATE DATABASE` 语句用于显示用 SQL 重新创建已有库的确切语句。`SHOW CREATE SCHEMA` 与其同义。 +`SHOW CREATE DATABASE` 用于显示重新创建现有数据库所需的精确 SQL 语句。`SHOW CREATE SCHEMA` 是它的同义词。 ## 语法图 @@ -18,23 +18,19 @@ ShowCreateDatabaseStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql CREATE DATABASE test; ``` -``` +```sql Query OK, 0 rows affected (0.12 sec) ``` -{{< copyable "sql" >}} - ```sql SHOW CREATE DATABASE test; ``` -``` +```sql +----------+------------------------------------------------------------------+ | Database | Create Database | +----------+------------------------------------------------------------------+ @@ -43,13 +39,11 @@ SHOW CREATE DATABASE test; 1 row in set (0.00 sec) ``` -{{< copyable "sql" >}} - ```sql SHOW CREATE SCHEMA IF NOT EXISTS test; ``` -``` +```sql +----------+-------------------------------------------------------------------------------------------+ | Database | Create Database | +----------+-------------------------------------------------------------------------------------------+ @@ -60,7 +54,7 @@ SHOW CREATE SCHEMA IF NOT EXISTS test; ## MySQL 兼容性 -`SHOW CREATE DATABASE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +`SHOW CREATE DATABASE` 预期与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-create-placement-policy.md b/sql-statements/sql-statement-show-create-placement-policy.md index 0531232d447e..69974ba65aab 100644 --- a/sql-statements/sql-statement-show-create-placement-policy.md +++ b/sql-statements/sql-statement-show-create-placement-policy.md @@ -1,11 +1,15 @@ --- title: SHOW CREATE PLACEMENT POLICY -summary: TiDB 数据库中 SHOW CREATE PLACEMENT POLICY 的使用概况。 +summary: TiDB 中 SHOW CREATE PLACEMENT POLICY 的使用。 --- # SHOW CREATE PLACEMENT POLICY -`SHOW CREATE PLACEMENT POLICY` 语句可用于查看放置策略当前的定义,并在另一个 TiDB 集群中重新创建该策略。 +`SHOW CREATE PLACEMENT POLICY` 用于显示放置策略的定义。这可以用来查看放置策略的当前定义,并在另一个 TiDB 集群中重新创建它。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ## 语法图 @@ -44,7 +48,7 @@ Create Policy | CREATE PLACEMENT POLICY `p1` PRIMARY_REGION="us-east-1" REGIONS= ## 另请参阅 -* [Placement Rules in SQL](/placement-rules-in-sql.md) +* [SQL 中的放置规则](/placement-rules-in-sql.md) * [SHOW PLACEMENT](/sql-statements/sql-statement-show-placement.md) * [CREATE PLACEMENT POLICY](/sql-statements/sql-statement-create-placement-policy.md) * [ALTER PLACEMENT POLICY](/sql-statements/sql-statement-alter-placement-policy.md) diff --git a/sql-statements/sql-statement-show-create-resource-group.md b/sql-statements/sql-statement-show-create-resource-group.md index 805de071a147..29daad1805b1 100644 --- a/sql-statements/sql-statement-show-create-resource-group.md +++ b/sql-statements/sql-statement-show-create-resource-group.md @@ -1,13 +1,17 @@ --- title: SHOW CREATE RESOURCE GROUP -summary: TiDB 数据库中 SHOW CREATE RESOURCE GROUP 的使用概况。 +summary: 了解 TiDB 中 SHOW CREATE RESOURCE GROUP 的使用方法。 --- # SHOW CREATE RESOURCE GROUP -`SHOW CREATE RESOURCE GROUP` 语句可用于查看资源组当前的定义。 +你可以使用 `SHOW CREATE RESOURCE GROUP` 语句查看资源组的当前定义。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法 ```ebnf+diagram ShowCreateResourceGroupStmt ::= @@ -20,13 +24,15 @@ ResourceGroupName ::= ## 示例 -查看资源组 `rg1` 当前的定义: +创建一个资源组 `rg1`。 ```sql CREATE RESOURCE GROUP rg1 RU_PER_SEC=100; Query OK, 0 rows affected (0.10 sec) ``` +查看 `rg1` 的定义。 + ```sql SHOW CREATE RESOURCE GROUP rg1; ***************************[ 1. row ]*************************** @@ -40,11 +46,11 @@ SHOW CREATE RESOURCE GROUP rg1; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 的扩展。 ## 另请参阅 -* [TiDB RESOURCE CONTROL](/tidb-resource-control.md) +* [TiDB 资源控制](/tidb-resource-control.md) * [CREATE RESOURCE GROUP](/sql-statements/sql-statement-alter-resource-group.md) * [ALTER RESOURCE GROUP](/sql-statements/sql-statement-alter-resource-group.md) * [DROP RESOURCE GROUP](/sql-statements/sql-statement-drop-resource-group.md) diff --git a/sql-statements/sql-statement-show-create-sequence.md b/sql-statements/sql-statement-show-create-sequence.md index e500af44183e..dbcac0e99149 100644 --- a/sql-statements/sql-statement-show-create-sequence.md +++ b/sql-statements/sql-statement-show-create-sequence.md @@ -1,13 +1,13 @@ --- title: SHOW CREATE SEQUENCE -summary: TiDB 数据库中 SHOW CREATE SEQUENCE 的使用概况。 +summary: TiDB 数据库中 SHOW CREATE SEQUENCE 的使用概述。 --- # SHOW CREATE SEQUENCE -`SHOW CREATE SEQUENCE` 语句用于查看一个序列的详细信息,类似于 `SHOW CREATE TABLE` 语句。 +`SHOW CREATE SEQUENCE` 显示序列的详细信息,类似于 `SHOW CREATE TABLE`。 -## 语法图 +## 语法 ```ebnf+diagram ShowCreateSequenceStmt ::= @@ -39,7 +39,7 @@ SHOW CREATE SEQUENCE seq; ## MySQL 兼容性 -该语句是 TiDB 的扩展,序列的实现借鉴自 MariaDB。 +此语句是 TiDB 扩展语法。其实现参考了 MariaDB 中可用的序列功能。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-create-table.md b/sql-statements/sql-statement-show-create-table.md index 69760792ee39..681029b467fd 100644 --- a/sql-statements/sql-statement-show-create-table.md +++ b/sql-statements/sql-statement-show-create-table.md @@ -1,11 +1,11 @@ --- -title: SHOW CREATE TABLE -summary: TiDB 数据库中 SHOW CREATE TABLE 的使用概况。 +title: SHOW CREATE TABLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW CREATE TABLE 的使用概述。 --- # SHOW CREATE TABLE -`SHOW CREATE TABLE` 语句用于显示用 SQL 重新创建已有表的确切语句。 +此语句显示使用 SQL 重新创建现有表的确切语句。 ## 语法图 @@ -16,23 +16,11 @@ ShowCreateTableStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a INT); -``` - -``` +mysql> CREATE TABLE t1 (a INT); Query OK, 0 rows affected (0.12 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW CREATE TABLE t1\G -``` - -``` +mysql> SHOW CREATE TABLE t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( @@ -43,7 +31,7 @@ Create Table: CREATE TABLE `t1` ( ## MySQL 兼容性 -`SHOW CREATE TABLE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW CREATE TABLE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-create-user.md b/sql-statements/sql-statement-show-create-user.md index 8e7276105b5b..cec05cd833bc 100644 --- a/sql-statements/sql-statement-show-create-user.md +++ b/sql-statements/sql-statement-show-create-user.md @@ -1,11 +1,11 @@ --- -title: SHOW CREATE USER -summary: TiDB 数据库中 SHOW CREATE USER 的使用概况。 +title: SHOW CREATE USER | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW CREATE USER 的使用概览。 --- # SHOW CREATE USER -`SHOW CREATE USER` 语句用于显示如何使用 `CREATE USER` 语法来重新创建用户。 +该语句显示如何使用 `CREATE USER` 语法重新创建用户。 ## 语法图 @@ -16,13 +16,8 @@ ShowCreateUserStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -SHOW CREATE USER 'root'; -``` - -``` +mysql> SHOW CREATE USER 'root'; +--------------------------------------------------------------------------------------------------------------------------+ | CREATE USER for root@% | +--------------------------------------------------------------------------------------------------------------------------+ @@ -41,7 +36,17 @@ mysql> SHOW GRANTS FOR 'root'; ## MySQL 兼容性 -* `SHOW CREATE USER` 的输出结果旨在匹配 MySQL,但 TiDB 尚不支持若干 `CREATE` 选项。尚未支持的选项在语句执行过程中会被解析但会被跳过执行。详情可参阅[与 MySQL 安全特性差异](/security-compatibility-with-mysql.md)。 + + +* `SHOW CREATE USER` 的输出设计为与 MySQL 匹配,但 TiDB 尚未支持几个 `CREATE` 选项。尚未支持的选项将被解析但被忽略。更多详细信息,请参见[安全兼容性](/security-compatibility-with-mysql.md)。 + + + + + +* `SHOW CREATE USER` 的输出设计为与 MySQL 匹配,但 TiDB 尚未支持几个 `CREATE` 选项。尚未支持的选项将被解析但被忽略。更多详细信息,请参见[安全兼容性](https://docs.pingcap.com/tidb/stable/security-compatibility-with-mysql/)。 + + ## 另请参阅 diff --git a/sql-statements/sql-statement-show-databases.md b/sql-statements/sql-statement-show-databases.md index f9118883b472..3a19bbdc9ec6 100644 --- a/sql-statements/sql-statement-show-databases.md +++ b/sql-statements/sql-statement-show-databases.md @@ -1,18 +1,16 @@ --- -title: SHOW DATABASES -summary: TiDB 数据库中 SHOW DATABASES 的使用概况。 +title: SHOW DATABASES | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW DATABASES 的使用概览。 --- # SHOW DATABASES -`SHOW DATABASES` 语句用于显示当前用户有权访问的数据库列表。当前用户无权访问的数据库将从列表中隐藏。`information_schema` 数据库始终出现在列表的最前面。 +该语句显示当前用户具有权限的数据库列表。当前用户无权访问的数据库将在列表中隐藏。`information_schema` 数据库始终在数据库列表中首先显示。 -`SHOW SCHEMAS` 是 `SHOW DATABASES` 语句的别名。 +`SHOW SCHEMAS` 是该语句的别名。 ## 语法图 -**ShowDatabasesStmt:** - ```ebnf+diagram ShowDatabasesStmt ::= "SHOW" "DATABASES" ShowLikeOrWhere? @@ -25,10 +23,7 @@ ShowLikeOrWhere ::= ## 示例 ```sql -SHOW DATABASES; -``` - -``` +mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ @@ -38,21 +33,11 @@ SHOW DATABASES; | test | +--------------------+ 4 rows in set (0.00 sec) -``` - -```sql -CREATE DATABASE mynewdb; -``` -``` +mysql> CREATE DATABASE mynewdb; Query OK, 0 rows affected (0.10 sec) -``` -```sql -SHOW DATABASES; -``` - -``` +mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ @@ -67,7 +52,7 @@ SHOW DATABASES; ## MySQL 兼容性 -`SHOW DATABASES` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW DATABASES` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-engines.md b/sql-statements/sql-statement-show-engines.md index 7ed61ed59740..ca2b246b218d 100644 --- a/sql-statements/sql-statement-show-engines.md +++ b/sql-statements/sql-statement-show-engines.md @@ -1,17 +1,18 @@ --- -title: SHOW ENGINES -summary: TiDB 数据库中 SHOW ENGINES 的使用概况。 +title: SHOW ENGINES | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW ENGINES 的使用概述。 --- # SHOW ENGINES -`SHOW ENGINES` 语句用于列出所有支持的存储引擎,该语法仅提供 MySQL 兼容性。 +此语句用于列出所有支持的存储引擎。包含此语法仅是为了与 MySQL 保持兼容。 -## 语法图 +## 语法 ```ebnf+diagram ShowEnginesStmt ::= "SHOW" "ENGINES" ShowLikeOrWhere? + ShowLikeOrWhere ::= "LIKE" SimpleExpr | "WHERE" Expression @@ -19,13 +20,8 @@ ShowLikeOrWhere ::= ## 示例 -{{< copyable "sql" >}} - ```sql -SHOW ENGINES; -``` - -``` +mysql> SHOW ENGINES; +--------+---------+------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------+---------+------------------------------------------------------------+--------------+------+------------+ @@ -36,4 +32,4 @@ SHOW ENGINES; ## MySQL 兼容性 -* `SHOW ENGINES` 语句始终只返回 InnoDB 作为其支持的引擎。但 TiDB 内部通常使用 [TiKV](/tikv-overview.md) 作为存储引擎。 +* 此语句将始终只返回 InnoDB 作为支持的引擎。在内部,TiDB 通常使用 [TiKV](/tikv-overview.md) 作为存储引擎。 diff --git a/sql-statements/sql-statement-show-errors.md b/sql-statements/sql-statement-show-errors.md index 44b565cbb100..5a1299910873 100644 --- a/sql-statements/sql-statement-show-errors.md +++ b/sql-statements/sql-statement-show-errors.md @@ -1,15 +1,15 @@ --- -title: SHOW ERRORS -summary: TiDB 数据库中 SHOW ERRORS 的使用概况。 +title: SHOW ERRORS | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW ERRORS 的使用概述。 --- # SHOW ERRORS -`SHOW ERRORS` 语句用于显示已执行语句中的错误。一旦先前的语句成功执行,就会清除错误缓冲区,这时 `SHOW ERRORS` 会返回一个空集。 +此语句显示之前执行的语句中的错误。当语句成功执行时,错误缓冲区会被清除。在这种情况下,`SHOW ERRORS` 将返回一个空集。 -当前的 `sql_mode` 很大程度决定了哪些语句会产生错误与警告。 +哪些语句生成错误而不是警告的行为很大程度上受当前 `sql_mode` 的影响。 -## 语法图 +## 语法概要 ```ebnf+diagram ShowErrorsStmt ::= @@ -22,33 +22,12 @@ ShowLikeOrWhere ::= ## 示例 -{{< copyable "sql" >}} - ```sql -select invalid; -``` - -``` +mysql> select invalid; ERROR 1054 (42S22): Unknown column 'invalid' in 'field list' -``` - -{{< copyable "sql" >}} - -```sql -create invalid; -``` - -``` +mysql> create invalid; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 14 near "invalid" -``` - -{{< copyable "sql" >}} - -```sql -SHOW ERRORS; -``` - -``` +mysql> SHOW ERRORS; +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -56,46 +35,24 @@ SHOW ERRORS; | Error | 1064 | You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 14 near "invalid" | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -CREATE invalid2; -``` - -``` +mysql> CREATE invalid2; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 15 near "invalid2" -``` - -{{< copyable "sql" >}} - -```sql -SELECT 1; -``` - -``` +mysql> SELECT 1; +------+ | 1 | +------+ | 1 | +------+ 1 row in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -SHOW ERRORS; -``` - -``` +mysql> SHOW ERRORS; Empty set (0.00 sec) ``` ## MySQL 兼容性 -`SHOW ERRORS` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW ERRORS` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告 bug](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-fields-from.md b/sql-statements/sql-statement-show-fields-from.md index 1a44f4fd9417..e677ad25880d 100644 --- a/sql-statements/sql-statement-show-fields-from.md +++ b/sql-statements/sql-statement-show-fields-from.md @@ -1,8 +1,8 @@ --- -title: SHOW [FULL] FIELDS FROM -summary: TiDB 数据库中 SHOW [FULL] FIELDS FROM 的使用概况。 +title: SHOW [FULL] FIELDS FROM | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW [FULL] FIELDS FROM 的使用概览。 --- # SHOW [FULL] FIELDS FROM -`SHOW [FULL] FIELDS FROM` 是 [`SHOW [FULL] COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) 的别名。包含该语句提供了 MySQL 兼容性。 +此语句是 [`SHOW [FULL] COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) 的别名。它是为了与 MySQL 兼容而包含的。 diff --git a/sql-statements/sql-statement-show-grants.md b/sql-statements/sql-statement-show-grants.md index 05ffc3de86b2..8f7b4958f253 100644 --- a/sql-statements/sql-statement-show-grants.md +++ b/sql-statements/sql-statement-show-grants.md @@ -1,11 +1,11 @@ --- -title: SHOW GRANTS -summary: TiDB 数据库中 SHOW GRANTS 的使用概况。 +title: SHOW GRANTS | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW GRANTS 的使用概述。 --- # SHOW GRANTS -`SHOW GRANTS` 语句用于显示与用户关联的权限列表。与在 MySQL 中一样,`USAGE` 权限表示登录 TiDB 的能力。 +此语句显示与用户关联的权限列表。与 MySQL 一样,`USAGE` 权限表示登录 TiDB 的能力。 ## 语法图 @@ -24,47 +24,23 @@ RolenameList ::= ## 示例 ```sql -SHOW GRANTS; -``` - -``` +mysql> SHOW GRANTS; +-------------------------------------------+ | Grants for User | +-------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' | +-------------------------------------------+ 1 row in set (0.00 sec) -``` - -```sql -SHOW GRANTS FOR 'u1'; -``` -``` +mysql> SHOW GRANTS FOR 'u1'; ERROR 1141 (42000): There is no such grant defined for user 'u1' on host '%' -``` - -```sql -CREATE USER u1; -``` - -``` +mysql> CREATE USER u1; Query OK, 1 row affected (0.04 sec) -``` - -```sql -GRANT SELECT ON test.* TO u1; -``` -``` +mysql> GRANT SELECT ON test.* TO u1; Query OK, 0 rows affected (0.04 sec) -``` - -```sql -SHOW GRANTS FOR u1; -``` -``` +mysql> SHOW GRANTS FOR u1; +------------------------------------+ | Grants for u1@% | +------------------------------------+ @@ -76,7 +52,7 @@ SHOW GRANTS FOR u1; ## MySQL 兼容性 -`SHOW GRANTS` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW GRANTS` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-import-job.md b/sql-statements/sql-statement-show-import-job.md index 598969433dd1..b2804eeeea64 100644 --- a/sql-statements/sql-statement-show-import-job.md +++ b/sql-statements/sql-statement-show-import-job.md @@ -1,16 +1,16 @@ --- title: SHOW IMPORT -summary: TiDB 数据库中 SHOW IMPORT 的使用概况。 +summary: TiDB 中 SHOW IMPORT 的使用概览。 --- # SHOW IMPORT -`SHOW IMPORT` 语句用于显示 TiDB 中已经创建的 IMPORT 任务。该语句只能显示由当前用户创建的任务。 +`SHOW IMPORT` 语句用于显示在 TiDB 中创建的导入作业。此语句只能显示当前用户创建的作业。 ## 所需权限 -- 对于 `SHOW IMPORT JOBS` 语句,如果用户有 `SUPER` 权限,则可以看到所有 job,否则只能看到当前用户创建的 job。 -- 对于 `SHOW IMPORT JOB `,只有 job 创建者或者拥有 `SUPER` 权限的用户才可以查看。 +- `SHOW IMPORT JOBS`:如果用户具有 `SUPER` 权限,此语句显示 TiDB 中的所有导入作业。否则,此语句仅显示当前用户创建的作业。 +- `SHOW IMPORT JOB `:只有导入作业的创建者或具有 `SUPER` 权限的用户可以使用此语句查看特定作业。 ## 语法图 @@ -22,22 +22,22 @@ ShowImportJobStmt ::= 'SHOW' 'IMPORT' 'JOB' JobID ``` -`SHOW IMPORT` 语句输出结果的字段含义如下: +`SHOW IMPORT` 语句的输出字段说明如下: -| 列名 | 说明 | +| 列名 | 描述 | |------------------|-------------------------| -| Job_ID | 任务 ID | -| Data_Source | 数据源信息 | -| Target_Table | 目标表 | -| Phase | 表示任务当前所处的阶段,导入过程分为 `importing`、`validating`、`add-index` 等阶段 | -| Status | 表示当前任务的状态。有以下几种状态:`pending` 表示任务已创建但还未开始运行;`running` 表示运行中;`canceled` 表示已经取消的任务;`failed` 表示任务失败并退出;`finished` 表示任务已完成。| -| Source_File_Size | 源文件大小 | -| Imported_Rows | 已经读到并写入目标表的数据行数 | -| Result_Message | 如果导入失败,则返回错误信息,否则为空。| -| Create_Time | 任务创建时间 | -| Start_Time | 任务启动时间 | -| End_Time | 任务结束时间 | -| Created_By | 创建该任务的数据库用户名 | +| Job_ID | 任务的 ID | +| Data_Source | 数据源信息 | +| Target_Table | 目标表的名称 | +| Phase | 作业的当前阶段,包括 `importing`、`validating` 和 `add-index` | +| Status | 作业的当前状态,包括 `pending`(表示已创建但尚未开始)、`running`、`canceled`、`failed` 和 `finished` | +| Source_File_Size | 源文件的大小 | +| Imported_Rows | 已读取并写入目标表的数据行数 | +| Result_Message | 如果导入失败,此字段返回错误消息。否则为空。| +| Create_Time | 任务创建的时间 | +| Start_Time | 任务开始的时间 | +| End_Time | 任务结束的时间 | +| Created_By | 创建任务的数据库用户名 | ## 示例 diff --git a/sql-statements/sql-statement-show-indexes.md b/sql-statements/sql-statement-show-indexes.md index bcd057263513..680838ec8d2e 100644 --- a/sql-statements/sql-statement-show-indexes.md +++ b/sql-statements/sql-statement-show-indexes.md @@ -1,13 +1,13 @@ --- -title: SHOW INDEXES [FROM|IN] -summary: TiDB 数据库中 SHOW INDEXES [FROM|IN] 的使用概况。 +title: SHOW INDEXES [FROM|IN] | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW INDEXES [FROM|IN] 的使用概览。 --- # SHOW INDEXES [FROM|IN] -`SHOW INDEXES [FROM|IN]` 语句用于列出指定表上的索引。`SHOW INDEX [FROM | IN]` 和 `SHOW KEYS [FROM | IN]` 是该语句的别名。包含该语句提供了 MySQL 兼容性。 +`SHOW INDEXES [FROM|IN]` 语句列出指定表上的索引。语句 `SHOW INDEX [FROM|IN]`、`SHOW KEYS [FROM|IN]` 是此语句的别名,为了与 MySQL 兼容而包含。 -## 语法图 +## 语法 ```ebnf+diagram ShowIndexStmt ::= @@ -20,23 +20,11 @@ ShowLikeOrWhere ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id int not null primary key AUTO_INCREMENT, col1 INT, INDEX(col1)); -``` - -``` +mysql> CREATE TABLE t1 (id int not null primary key AUTO_INCREMENT, col1 INT, INDEX(col1)); Query OK, 0 rows affected (0.12 sec) -``` - -{{< copyable "sql" >}} -```sql -SHOW INDEXES FROM t1; -``` - -``` +mysql> SHOW INDEXES FROM t1; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ @@ -44,15 +32,8 @@ SHOW INDEXES FROM t1; | t1 | 1 | col1 | 1 | col1 | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ 2 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW INDEX FROM t1; -``` - -``` +mysql> SHOW INDEX FROM t1; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ @@ -60,15 +41,8 @@ SHOW INDEX FROM t1; | t1 | 1 | col1 | 1 | col1 | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ 2 rows in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW KEYS FROM t1; -``` - -``` +mysql> SHOW KEYS FROM t1; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ @@ -78,11 +52,11 @@ SHOW KEYS FROM t1; 2 rows in set (0.00 sec) ``` -注意为了兼容 MySQL,TiDB 在语法上支持 `HASH`、`BTREE` 和 `RTREE` 等索引类型,但会忽略它们。 +注意,TiDB 在语法上接受 `HASH`、`BTREE` 和 `RTREE` 等索引类型以与 MySQL 兼容,但会忽略它们。 ## MySQL 兼容性 -`SHOW INDEXES [FROM|IN]` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW INDEXES [FROM|IN]` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-master-status.md b/sql-statements/sql-statement-show-master-status.md index d7092aa274d1..78e5b6e57ca7 100644 --- a/sql-statements/sql-statement-show-master-status.md +++ b/sql-statements/sql-statement-show-master-status.md @@ -1,11 +1,11 @@ --- title: SHOW MASTER STATUS -summary: TiDB 数据库中 SHOW MASTER STATUS 的使用概况。 +summary: TiDB 数据库中 SHOW MASTER STATUS 的使用概述。 --- # SHOW MASTER STATUS -`SHOW MASTER STATUS` 语句用于显示集群当前最新的 TSO 信息。 +`SHOW MASTER STATUS` 语句显示集群中的最新 TSO。 ## 示例 @@ -26,13 +26,23 @@ SHOW MASTER STATUS; ## MySQL 兼容性 -`SHOW MASTER STATUS` 语句与 MySQL 兼容,但是执行结果有差异,在 MySQL 中执行结果为 binlog 的位置信息,而在 TiDB 中为最新的 TSO 信息。 +`SHOW MASTER STATUS` 的输出格式设计为与 MySQL 匹配。但是,执行结果不同,MySQL 的结果是 binlog 位置信息,而 TiDB 的结果是最新的 TSO 信息。 -`SHOW BINARY LOG STATUS` 语句在 TiDB 中是 `SHOW MASTER STATUS` 的别名,但 `SHOW MASTER STATUS` 在 MySQL 8.2.0 及更高版本中已被废弃。 +`SHOW BINARY LOG STATUS` 语句作为 `SHOW MASTER STATUS` 的别名被添加到 TiDB 中,而 `SHOW MASTER STATUS` 在 MySQL 8.2.0 及更新版本中已被弃用。 ## 另请参阅 + + * [SHOW PUMP STATUS](/sql-statements/sql-statement-show-pump-status.md) * [SHOW DRAINER STATUS](/sql-statements/sql-statement-show-drainer-status.md) * [CHANGE PUMP STATUS](/sql-statements/sql-statement-change-pump.md) * [CHANGE DRAINER STATUS](/sql-statements/sql-statement-change-drainer.md) + + + + + +* [`SHOW TABLE STATUS`](/sql-statements/sql-statement-show-table-status.md) + + diff --git a/sql-statements/sql-statement-show-placement-for.md b/sql-statements/sql-statement-show-placement-for.md index d2caa5ade273..3aa3a74443d3 100644 --- a/sql-statements/sql-statement-show-placement-for.md +++ b/sql-statements/sql-statement-show-placement-for.md @@ -1,17 +1,21 @@ --- title: SHOW PLACEMENT FOR -summary: TiDB 数据库中 SHOW PLACEMENT FOR 的使用概况。 +summary: TiDB 中 SHOW PLACEMENT FOR 的使用。 --- # SHOW PLACEMENT FOR -`SHOW PLACEMENT FOR` 用于汇总所有放置策略 (placement policy),并用统一的形式呈现特定表、数据库或分区的信息。 +`SHOW PLACEMENT FOR` 汇总特定表、数据库模式或分区的所有放置选项,并以规范形式呈现它们。 -本语句返回结果中的 `Scheduling_State` 列标识了 Placement Driver (PD) 在当前对象上的调度进度,有以下可能的结果: +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 -* `PENDING`: PD 没有进行调度。可能的原因之一是放置规则虽然语法上正确,但集群拓扑并不满足。比如指定 `FOLLOWERS=4` 但只有 3 个可用作 follower 的 TiKV 实例。 -* `INPROGRESS`: PD 正在进行调度。 -* `SCHEDULED`: PD 调度完成。 +该语句返回一个结果集,其中 `Scheduling_State` 字段指示 Placement Driver (PD) 在调度放置时的当前进度: + +* `PENDING`:PD 尚未开始调度放置。这可能表明放置规则在语义上是正确的,但当前集群无法满足。例如,如果设置 `FOLLOWERS=4` 但只有 3 个 TiKV 存储节点可作为从节点的候选者。 +* `INPROGRESS`:PD 当前正在调度放置。 +* `SCHEDULED`:PD 已成功调度放置。 ## 语法图 @@ -29,7 +33,6 @@ ShowPlacementTarget ::= ```sql CREATE PLACEMENT POLICY p1 PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-west-1" FOLLOWERS=4; -use test; ALTER DATABASE test PLACEMENT POLICY=p1; CREATE TABLE t1 (a INT); SHOW PLACEMENT FOR DATABASE test; @@ -39,7 +42,7 @@ CREATE TABLE t3 (a INT) PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN (1 SHOW PLACEMENT FOR TABLE t3 PARTITION p1\G ``` -```sql +``` Query OK, 0 rows affected (0.02 sec) Query OK, 0 rows affected (0.00 sec) @@ -80,6 +83,6 @@ Scheduling_State | PENDING ## 另请参阅 -* [Placement Rules in SQL](/placement-rules-in-sql.md) +* [SQL 中的放置规则](/placement-rules-in-sql.md) * [SHOW PLACEMENT](/sql-statements/sql-statement-show-placement.md) * [CREATE PLACEMENT POLICY](/sql-statements/sql-statement-create-placement-policy.md) diff --git a/sql-statements/sql-statement-show-placement-labels.md b/sql-statements/sql-statement-show-placement-labels.md index ef1456e07cd6..6a51e54ec613 100644 --- a/sql-statements/sql-statement-show-placement-labels.md +++ b/sql-statements/sql-statement-show-placement-labels.md @@ -1,13 +1,17 @@ --- title: SHOW PLACEMENT LABELS -summary: TiDB 数据库中 SHOW PLACEMENT LABELS 的使用概况。 +summary: TiDB 中 SHOW PLACEMENT LABELS 的使用。 --- # SHOW PLACEMENT LABELS -`SHOW PLACEMENT LABELS` 汇总可用于放置规则 (Placement Rules) 的标签 (label) 和值。 +`SHOW PLACEMENT LABELS` 用于汇总可用于放置规则的标签和值。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法概要 ```ebnf+diagram ShowStmt ::= @@ -20,7 +24,7 @@ ShowStmt ::= SHOW PLACEMENT LABELS; ``` -```sql +``` +--------+----------------+ | Key | Values | +--------+----------------+ @@ -32,10 +36,10 @@ SHOW PLACEMENT LABELS; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [Placement Rules in SQL](/placement-rules-in-sql.md) +* [SQL 中的放置规则](/placement-rules-in-sql.md) * [SHOW PLACEMENT](/sql-statements/sql-statement-show-placement.md) * [CREATE PLACEMENT POLICY](/sql-statements/sql-statement-create-placement-policy.md) diff --git a/sql-statements/sql-statement-show-placement.md b/sql-statements/sql-statement-show-placement.md index 8c50968d54fe..b1ccb06090e0 100644 --- a/sql-statements/sql-statement-show-placement.md +++ b/sql-statements/sql-statement-show-placement.md @@ -1,17 +1,21 @@ --- title: SHOW PLACEMENT -summary: TiDB 数据库中 SHOW PLACEMENT 的使用概况。 +summary: TiDB 中 SHOW PLACEMENT 的使用。 --- # SHOW PLACEMENT -`SHOW PLACEMENT` 汇总了所有放置策略 (placement policy),并用统一的形式呈现相关信息。 +`SHOW PLACEMENT` 汇总了来自放置策略的所有放置选项,并以规范形式呈现它们。 -本语句返回结果中的 `Scheduling_State` 列标识了 Placement Driver (PD) 在当前对象上的调度进度,有以下可能结果: +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 -* `PENDING`: PD 没有进行调度。可能的原因之一是放置规则虽然语法上正确,但集群拓扑并不满足。比如指定 `FOLLOWERS=4` 但只有 3 个可用作 follower 的 TiKV 实例。 -* `INPROGRESS`: PD 正在进行调度。 -* `SCHEDULED`: PD 调度完成。 +该语句返回一个结果集,其中 `Scheduling_State` 字段指示 Placement Driver (PD) 在调度放置时的当前进度: + +* `PENDING`:PD 尚未开始调度放置。这可能表明放置规则在语义上是正确的,但当前集群无法满足。例如,如果设置 `FOLLOWERS=4` 但只有 3 个 TiKV 存储节点可作为从节点的候选者。 +* `INPROGRESS`:PD 当前正在调度放置。 +* `SCHEDULED`:PD 已成功调度放置。 ## 语法图 @@ -28,7 +32,7 @@ CREATE TABLE t1 (a INT) PLACEMENT POLICY=p1; SHOW PLACEMENT; ``` -```sql +``` Query OK, 0 rows affected (0.01 sec) Query OK, 0 rows affected (0.00 sec) @@ -49,6 +53,6 @@ Query OK, 0 rows affected (0.00 sec) ## 另请参阅 -* [Placement Rules in SQL](/placement-rules-in-sql.md) +* [SQL 中的放置规则](/placement-rules-in-sql.md) * [SHOW PLACEMENT FOR](/sql-statements/sql-statement-show-placement-for.md) * [CREATE PLACEMENT POLICY](/sql-statements/sql-statement-create-placement-policy.md) diff --git a/sql-statements/sql-statement-show-plugins.md b/sql-statements/sql-statement-show-plugins.md index 1ea160abeb0a..17eabe762785 100644 --- a/sql-statements/sql-statement-show-plugins.md +++ b/sql-statements/sql-statement-show-plugins.md @@ -1,13 +1,17 @@ --- title: SHOW PLUGINS -summary: TiDB 数据库中 SHOW PLUGINS 的使用概况。 +summary: TiDB 数据库中 SHOW PLUGINS 的使用概述。 --- # SHOW PLUGINS -`SHOW PLUGINS` 用于查看 TiDB 安装的插件,各个插件运行的状态以及插件版本信息。 +`SHOW PLUGINS` 显示在 TiDB 中安装的所有插件,包括每个插件的状态和版本信息。 -## 语法图 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +## 语法 ```ebnf+diagram ShowPluginsStmt ::= @@ -29,8 +33,6 @@ SHOW PLUGINS; 1 row in set (0.000 sec) ``` -`SHOW PLUGINS` 也支持模糊匹配: - ```sql SHOW PLUGINS LIKE 'a%'; ``` @@ -46,8 +48,8 @@ SHOW PLUGINS LIKE 'a%'; ## MySQL 兼容性 -`SHOW PLUGINS` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW PLUGINS` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 -## 扩展阅读 +## 另请参阅 -- [`ADMIN PLUGINS`](/sql-statements/sql-statement-admin.md#admin-plugin-语句) +- [`ADMIN PLUGINS`](/sql-statements/sql-statement-admin.md#admin-plugins-related-statement) diff --git a/sql-statements/sql-statement-show-privileges.md b/sql-statements/sql-statement-show-privileges.md index 980e7ebd5ea8..7e5ad1b7ddb7 100644 --- a/sql-statements/sql-statement-show-privileges.md +++ b/sql-statements/sql-statement-show-privileges.md @@ -1,11 +1,11 @@ --- -title: SHOW PRIVILEGES -summary: TiDB 数据库中 SHOW PRIVILEGES 的使用概况。 +title: SHOW PRIVILEGES | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW PRIVILEGES 的使用概述。 --- # SHOW PRIVILEGES -`SHOW PRIVILEGES` 语句用于显示 TiDB 中可分配权限的列表。此列表为静态列表,不反映当前用户的权限。 +此语句显示 TiDB 中可分配的权限列表。这是一个静态列表,不反映当前用户的权限。 ## 语法图 @@ -20,44 +20,44 @@ ShowPrivilegesStmt ::= SHOW PRIVILEGES; ``` -```sql +``` +---------------------------------+---------------------------------------+-------------------------------------------------------+ | Privilege | Context | Comment | +---------------------------------+---------------------------------------+-------------------------------------------------------+ -| Alter | Tables | To alter the table | -| Alter routine | Functions,Procedures | To alter or drop stored functions/procedures | -| Config | Server Admin | To use SHOW CONFIG and SET CONFIG statements | -| Create | Databases,Tables,Indexes | To create new databases and tables | -| Create routine | Databases | To use CREATE FUNCTION/PROCEDURE | -| Create role | Server Admin | To create new roles | -| Create temporary tables | Databases | To use CREATE TEMPORARY TABLE | -| Create view | Tables | To create new views | -| Create user | Server Admin | To create new users | -| Delete | Tables | To delete existing rows | -| Drop | Databases,Tables | To drop databases, tables, and views | -| Drop role | Server Admin | To drop roles | -| Event | Server Admin | To create, alter, drop and execute events | -| Execute | Functions,Procedures | To execute stored routines | -| File | File access on server | To read and write files on the server | -| Grant option | Databases,Tables,Functions,Procedures | To give to other users those privileges you possess | -| Index | Tables | To create or drop indexes | -| Insert | Tables | To insert data into tables | -| Lock tables | Databases | To use LOCK TABLES (together with SELECT privilege) | -| Process | Server Admin | To view the plain text of currently executing queries | -| Proxy | Server Admin | To make proxy user possible | -| References | Databases,Tables | To have references on tables | -| Reload | Server Admin | To reload or refresh tables, logs and privileges | -| Replication client | Server Admin | To ask where the slave or master servers are | -| Replication slave | Server Admin | To read binary log events from the master | -| Select | Tables | To retrieve rows from table | -| Show databases | Server Admin | To see all databases with SHOW DATABASES | -| Show view | Tables | To see views with SHOW CREATE VIEW | -| Shutdown | Server Admin | To shut down the server | -| Super | Server Admin | To use KILL thread, SET GLOBAL, CHANGE MASTER, etc. | -| Trigger | Tables | To use triggers | -| Create tablespace | Server Admin | To create/alter/drop tablespaces | -| Update | Tables | To update existing rows | -| Usage | Server Admin | No privileges - allow connect only | +| Alter | Tables | 修改表 | +| Alter routine | Functions,Procedures | 修改或删除存储函数/存储过程 | +| Config | Server Admin | 使用 SHOW CONFIG 和 SET CONFIG 语句 | +| Create | Databases,Tables,Indexes | 创建新的数据库和表 | +| Create routine | Databases | 使用 CREATE FUNCTION/PROCEDURE | +| Create role | Server Admin | 创建新角色 | +| Create temporary tables | Databases | 使用 CREATE TEMPORARY TABLE | +| Create view | Tables | 创建新视图 | +| Create user | Server Admin | 创建新用户 | +| Delete | Tables | 删除现有行 | +| Drop | Databases,Tables | 删除数据库、表和视图 | +| Drop role | Server Admin | 删除角色 | +| Event | Server Admin | 创建、修改、删除和执行事件 | +| Execute | Functions,Procedures | 执行存储过程 | +| File | File access on server | 在服务器上读写文件 | +| Grant option | Databases,Tables,Functions,Procedures | 将你拥有的权限授予其他用户 | +| Index | Tables | 创建或删除索引 | +| Insert | Tables | 向表中插入数据 | +| Lock tables | Databases | 使用 LOCK TABLES(需要配合 SELECT 权限) | +| Process | Server Admin | 查看当前执行查询的明文 | +| Proxy | Server Admin | 使代理用户成为可能 | +| References | Databases,Tables | 在表上拥有引用 | +| Reload | Server Admin | 重新加载或刷新表、日志和权限 | +| Replication client | Server Admin | 查询从服务器或主服务器的位置 | +| Replication slave | Server Admin | 从主服务器读取二进制日志事件 | +| Select | Tables | 从表中检索行 | +| Show databases | Server Admin | 使用 SHOW DATABASES 查看所有数据库 | +| Show view | Tables | 使用 SHOW CREATE VIEW 查看视图 | +| Shutdown | Server Admin | 关闭服务器 | +| Super | Server Admin | 使用 KILL thread、SET GLOBAL、CHANGE MASTER 等 | +| Trigger | Tables | 使用触发器 | +| Create tablespace | Server Admin | 创建/修改/删除表空间 | +| Update | Tables | 更新现有行 | +| Usage | Server Admin | 无权限 - 仅允许连接 | | BACKUP_ADMIN | Server Admin | | | RESTORE_ADMIN | Server Admin | | | SYSTEM_USER | Server Admin | | @@ -79,10 +79,22 @@ SHOW PRIVILEGES; ## MySQL 兼容性 -`SHOW PRIVILEGES` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW PRIVILEGES` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 + + * [SHOW GRANTS](/sql-statements/sql-statement-show-grants.md) * [权限管理](/privilege-management.md) * [`GRANT `](/sql-statements/sql-statement-grant-privileges.md) + + + + + +* [SHOW GRANTS](/sql-statements/sql-statement-show-grants.md) +* [权限管理](https://docs.pingcap.com/tidb/stable/privilege-management) +* [`GRANT `](/sql-statements/sql-statement-grant-privileges.md) + + diff --git a/sql-statements/sql-statement-show-processlist.md b/sql-statements/sql-statement-show-processlist.md index 4677b8ec9c6c..a547fba1cda4 100644 --- a/sql-statements/sql-statement-show-processlist.md +++ b/sql-statements/sql-statement-show-processlist.md @@ -1,13 +1,13 @@ --- -title: SHOW [FULL] PROCESSLIST -summary: TiDB 数据库中 SHOW [FULL] PROCESSLIST 的使用概况。 +title: SHOW [FULL] PROCESSLIST | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW [FULL] PROCESSLIST 的使用概览。 --- # SHOW [FULL] PROCESSLIST -`SHOW [FULL] PROCESSLIST` 语句列出连接到相同 TiDB 服务器的当前会话。 +此语句列出连接到同一 TiDB 服务器的当前会话。`Info` 列包含查询文本,除非指定可选关键字 `FULL`,否则该文本将被截断。 -## 语法图 +## 语法 ```ebnf+diagram ShowProcesslistStmt ::= @@ -17,10 +17,7 @@ ShowProcesslistStmt ::= ## 示例 ```sql -SHOW PROCESSLIST; -``` - -```sql +mysql> SHOW PROCESSLIST; +------+------+-----------------+------+---------+------+------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +------+------+-----------------+------+---------+------+------------+------------------+ @@ -29,16 +26,9 @@ SHOW PROCESSLIST; 1 rows in set (0.00 sec) ``` -以上返回结果中的主要字段描述如下: - -- `Command`:SQL 语句的类型,通常值为 `Query`。 -- `Time`:SQL 语句开始执行的时间。 -- `State`:SQL 语句的状态。常见的值是 `autocommit`,表示该 SQL 语句是自动提交的。`in transaction` 表示该 SQL 语句处于事务中。 -- `Info`:表示具体的 SQL 文本。除非指定可选关键字 `FULL`,否则文本会被截断。 - ## MySQL 兼容性 -* TiDB 中的 `State` 列是非描述性的。在 TiDB 中,将状态表示为单个值更复杂,因为查询是并行执行的,而且每个 Go 线程在任一时刻都有不同的状态。 +* TiDB 中的 `State` 列是非描述性的。在 TiDB 中将状态表示为单个值更复杂,因为查询是并行执行的,每个 goroutine 在任何时候都会有不同的状态。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-profiles.md b/sql-statements/sql-statement-show-profiles.md index 42d08e74b2c2..bbfa2165c5fd 100644 --- a/sql-statements/sql-statement-show-profiles.md +++ b/sql-statements/sql-statement-show-profiles.md @@ -1,11 +1,11 @@ --- title: SHOW PROFILES -summary: TiDB 数据库中 SHOW PROFILES 的使用概况。 +summary: TiDB 数据库中 SHOW PROFILES 的使用概览。 --- # SHOW PROFILES -`SHOW PROFILES` 语句目前只会返回空结果。 +`SHOW PROFILES` 语句目前仅返回空结果。 ## 语法图 @@ -21,7 +21,7 @@ ShowLikeOrWhere ::= ## 示例 ```sql -SHOW PROFILES +SHOW PROFILES; ``` ``` @@ -30,6 +30,6 @@ Empty set (0.00 sec) ## MySQL 兼容性 -该语句仅与 MySQL 兼容,无其他作用。执行 `SHOW PROFILES` 始终返回空结果。 +此语句仅为与 MySQL 兼容而包含。执行 `SHOW PROFILES` 始终返回空结果。 -作为替代方案,TiDB 提供了 [Statement Summary Tables](/statement-summary-tables.md),以帮助理解 SQL 性能问题。 \ No newline at end of file +作为替代方案,TiDB 提供了[语句概要表](/statement-summary-tables.md)来帮助理解 SQL 性能问题。 diff --git a/sql-statements/sql-statement-show-schemas.md b/sql-statements/sql-statement-show-schemas.md index 087657304a79..cfb287611403 100644 --- a/sql-statements/sql-statement-show-schemas.md +++ b/sql-statements/sql-statement-show-schemas.md @@ -1,8 +1,8 @@ --- -title: SHOW SCHEMAS -summary: TiDB 数据库中 SHOW SCHEMAS 的使用概况。 +title: SHOW SCHEMAS | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW SCHEMAS 的使用概述。 --- # SHOW SCHEMAS -`SHOW SCHEMAS` 语句是 [`SHOW DATABASES`](/sql-statements/sql-statement-show-databases.md) 的别名。包含该语句提供了 MySQL 兼容性。 +此语句是 [`SHOW DATABASES`](/sql-statements/sql-statement-show-databases.md) 的别名。它是为了与 MySQL 兼容而包含的。 diff --git a/sql-statements/sql-statement-show-stats-buckets.md b/sql-statements/sql-statement-show-stats-buckets.md index 80b4b42b6f33..2fe76ea00b40 100644 --- a/sql-statements/sql-statement-show-stats-buckets.md +++ b/sql-statements/sql-statement-show-stats-buckets.md @@ -1,33 +1,34 @@ --- title: SHOW STATS_BUCKETS -summary: TiDB 数据库中 SHOW STATS_BUCKETS 的使用概况。 +summary: TiDB 数据库中 SHOW STATS_BUCKETS 的使用概述。 --- # SHOW STATS_BUCKETS -`SHOW STATS_BUCKETS` 语句显示[常规统计信息](/statistics.md)中桶的信息。 +`SHOW STATS_BUCKETS` 语句显示[统计信息](/statistics.md)中的桶信息。 目前,`SHOW STATS_BUCKETS` 语句返回以下列: -| 列名 | 说明 | +| 列名 | 描述 | | :-------- | :------------- | -| `Db_name` | 数据库名 | +| `Db_name` | 数据库名称 | | `Table_name` | 表名 | -| `Partition_name` | 分区名 | -| `Column_name` | 取决于 `Is_index` 值:`Is_index` 为 `0` 时显示列名,为 `1` 时显示索引名 | -| `Is_index` | 是否是索引列 | +| `Partition_name` | 分区名称 | +| `Column_name` | 当 `is_index` 为 `0` 时表示列名,当 `is_index` 为 `1` 时表示索引名 | +| `Is_index` | 是否为索引列 | | `Bucket_id` | 桶的 ID | -| `Count` | 该桶和之前桶中所有数值的个数 | +| `Count` | 落在该桶及之前所有桶中的值的数量 | | `Repeats` | 最大值的出现次数 | | `Lower_bound` | 最小值 | | `Upper_bound` | 最大值 | -| `Ndv` | 桶中不同值的数量。该字段已废弃,其值由于不准确会始终显示为 `0`。 | +| `Ndv` | 桶中不同值的数量。由于该字段的值不准确,已被弃用且始终显示为 `0`。 | -## 语法图 +## 语法 ```ebnf+diagram ShowStatsBucketsStmt ::= "SHOW" "STATS_BUCKETS" ShowLikeOrWhere? + ShowLikeOrWhere ::= "LIKE" SimpleExpr | "WHERE" Expression @@ -55,9 +56,9 @@ SHOW STATS_BUCKETS WHERE Table_name='t'; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 * [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) -* [常规统计信息](/statistics.md) \ No newline at end of file +* [统计信息简介](/statistics.md) diff --git a/sql-statements/sql-statement-show-stats-healthy.md b/sql-statements/sql-statement-show-stats-healthy.md index c2d056cae725..848428c16a60 100644 --- a/sql-statements/sql-statement-show-stats-healthy.md +++ b/sql-statements/sql-statement-show-stats-healthy.md @@ -1,24 +1,24 @@ --- title: SHOW STATS_HEALTHY -summary: TiDB 数据库中 SHOW STATS_HEALTHY 的使用概况。 +summary: TiDB 数据库中 SHOW STATS_HEALTHY 的使用概述。 --- # SHOW STATS_HEALTHY -`SHOW STATS_HEALTHY` 语句可以预估统计信息的准确度,也就是健康度。健康度低的表可能会生成次优查询执行计划。 +`SHOW STATS_HEALTHY` 语句显示统计信息被认为准确程度的估计值。健康度百分比较低的表可能会生成次优的查询执行计划。 -可以通过执行 [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) 语句来改善表的健康度。当表的健康度下降到低于 [`tidb_auto_analyze_ratio`](/system-variables.md#tidb_auto_analyze_ratio) 时,则会自动执行 `ANALYZE` 语句。 +可以通过运行 [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) 语句来提高表的健康度。当健康度低于 [`tidb_auto_analyze_ratio`](/system-variables.md#tidb_auto_analyze_ratio) 阈值时,`ANALYZE` 会自动运行。 目前,`SHOW STATS_HEALTHY` 语句返回以下列: -| 列名 | 说明 | -| :-------- | :------------- | -| `Db_name` | 数据库名 | +| 列名 | 描述 | +| -------- | ------------- | +| `Db_name` | 数据库名称 | | `Table_name` | 表名 | -| `Partition_name`| 分区名 | -| `Healthy` | 健康度,0~100 之间 | +| `Partition_name` | 分区名称 | +| `Healthy` | 介于 0 和 100 之间的健康度百分比 | -## 语法图 +## 语法 ```ebnf+diagram ShowStatsHealthyStmt ::= @@ -31,7 +31,7 @@ ShowLikeOrWhere ::= ## 示例 -加载示例数据并运行 `ANALYZE` 语句: +加载示例数据并运行 `ANALYZE`: ```sql CREATE TABLE t1 ( @@ -40,6 +40,7 @@ CREATE TABLE t1 ( pad VARBINARY(255), INDEX(b) ); + INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM dual; INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; @@ -49,14 +50,12 @@ INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN INSERT INTO t1 SELECT NULL, FLOOR(RAND()*1000), RANDOM_BYTES(255) FROM t1 a JOIN t1 b JOIN t1 c LIMIT 100000; SELECT SLEEP(1); ANALYZE TABLE t1; -SHOW STATS_HEALTHY; # should be 100% healthy -``` - -```sql -SHOW STATS_HEALTHY; +SHOW STATS_HEALTHY; # 应该是 100% 健康 ``` ```sql +... +mysql> SHOW STATS_HEALTHY; +---------+------------+----------------+---------+ | Db_name | Table_name | Partition_name | Healthy | +---------+------------+----------------+---------+ @@ -65,15 +64,15 @@ SHOW STATS_HEALTHY; 1 row in set (0.00 sec) ``` -执行批量更新来删除大约 30% 的记录,然后检查统计信息的健康度: +执行批量更新,删除大约 30% 的记录。检查统计信息的健康度: ```sql -DELETE FROM t1 WHERE id BETWEEN 101010 AND 201010; # delete about 30% of records -SHOW STATS_HEALTHY; +DELETE FROM t1 WHERE id BETWEEN 101010 AND 201010; # 删除大约 30% 的记录 +SHOW STATS_HEALTHY; ``` ```sql -SHOW STATS_HEALTHY; +mysql> SHOW STATS_HEALTHY; +---------+------------+----------------+---------+ | Db_name | Table_name | Partition_name | Healthy | +---------+------------+----------------+---------+ @@ -84,9 +83,9 @@ SHOW STATS_HEALTHY; ## MySQL 兼容性 -`SHOW STATS_HEALTHY` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) -* [常规统计信息](/statistics.md) \ No newline at end of file +* [ANALYZE](/sql-statements/sql-statement-analyze-table.md) +* [统计信息简介](/statistics.md) diff --git a/sql-statements/sql-statement-show-stats-histograms.md b/sql-statements/sql-statement-show-stats-histograms.md index 3d69b51e287c..447f11178f12 100644 --- a/sql-statements/sql-statement-show-stats-histograms.md +++ b/sql-statements/sql-statement-show-stats-histograms.md @@ -1,34 +1,34 @@ --- title: SHOW STATS_HISTOGRAMS -aliases: ['/zh/tidb/stable/sql-statement-show-histograms'] -summary: TiDB 数据库中 SHOW STATS_HISTOGRAMS 语句的简单说明。 +aliases: ['/tidb/stable/sql-statement-show-histograms'] +summary: TiDB 数据库中 SHOW HISTOGRAMS 的使用概述。 --- # SHOW STATS_HISTOGRAMS -你可以使用 `SHOW STATS_HISTOGRAMS` 语句查看通过 [`ANALYZE` 语句](/sql-statements/sql-statement-analyze-table.md)收集的直方图信息,该内容是数据库[常规统计信息](/statistics.md)的一部分。 +此语句显示由 [`ANALYZE` 语句](/sql-statements/sql-statement-analyze-table.md)作为数据库[统计信息](/statistics.md)的一部分收集的直方图信息。 目前,`SHOW STATS_HISTOGRAMS` 语句返回以下列: -| 列名 | 说明 | +| 列名 | 描述 | | -------- | ------------- | -| `Db_name` | 数据库名 | +| `Db_name` | 数据库名 | | `Table_name` | 表名 | | `Partition_name` | 分区名 | -| `Column_name` | 取决于 `Is_index` 值:`Is_index` 为 `0` 时显示列名,为 `1` 时显示索引名 | -| `Is_index` | 是否是索引列 | +| `Column_name` | 当 `is_index` 为 `0` 时表示列名,当 `is_index` 为 `1` 时表示索引名 | +| `Is_index` | 是否为索引列 | | `Update_time` | 更新时间 | -| `Distinct_count` | 不同值数量 | -| `Null_count` | `NULL` 的数量 | -| `Avg_col_size` | 列平均长度 | -| `Correlation` | 该列与整型主键的皮尔逊系数,表示两列之间的关联程度 | -| `Load_status` | 加载状态,例如 `allEvicted` 和 `allLoaded` | -| `Total_mem_usage` | 总内存占用 | -| `Hist_mem_usage` | 历史内存占用 | -| `Topn_mem_usage` | `TopN` 内存占用 | -| `Cms_mem_usage` | CMS 内存占用 | - -## 语法图 +| `Distinct_count` | 不同值的数量 | +| `Null_count` | NULL 值的数量 | +| `Avg_col_size` | 平均列大小 | +| `Correlation` | 该列与整数主键列之间的皮尔逊相关系数,表示两列之间的关联程度 | +| `Load_status` | 加载状态,如 `allEvicted` 和 `allLoaded` | +| `Total_mem_usage` | 总内存使用量 | +| `Hist_mem_usage` | 历史内存使用量 | +| `Topn_mem_usage` | TopN 内存使用量 | +| `Cms_mem_usage` | CMS 内存使用量 | + +## 语法概要 ```ebnf+diagram ShowStatsHistogramsStmt ::= @@ -72,9 +72,9 @@ SHOW STATS_HISTOGRAMS WHERE table_name = 't2'; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) -* [常规统计信息](/statistics.md) +* [ANALYZE](/sql-statements/sql-statement-analyze-table.md) +* [统计信息简介](/statistics.md) diff --git a/sql-statements/sql-statement-show-stats-locked.md b/sql-statements/sql-statement-show-stats-locked.md index a9e3898eba96..a8210c8b7474 100644 --- a/sql-statements/sql-statement-show-stats-locked.md +++ b/sql-statements/sql-statement-show-stats-locked.md @@ -1,20 +1,20 @@ --- title: SHOW STATS_LOCKED -summary: TiDB 数据库中 SHOW STATS_LOCKED 的使用概况。 +summary: TiDB 数据库中 SHOW STATS_LOCKED 的使用概览。 --- # SHOW STATS_LOCKED -`SHOW STATS_LOCKED` 语句显示统计信息被锁定的表。 +`SHOW STATS_LOCKED` 显示统计信息被锁定的表。 目前,`SHOW STATS_LOCKED` 语句返回以下列: -| 列名 | 说明 | +| 列名 | 描述 | | -------- | ------------- | -| `Db_name` | 数据库名 | -| `Table_name` | 表名 | -| `Partition_name` | 分区名 | -| `Status` | 统计信息状态,例如 `locked` | +| `Db_name` | 数据库名称 | +| `Table_name` | 表名称 | +| `Partition_name` | 分区名称 | +| `Status` | 统计信息状态,如 `locked` | ## 语法图 @@ -26,7 +26,7 @@ ShowLikeOrWhereOpt ::= 'LIKE' SimpleExpr | 'WHERE' Expression ## 示例 -创建表 `t`,插入一些数据,在未锁定表 `t` 的统计信息的情况下成功执行 `ANALYZE` 语句。 +创建表 `t` 并向其中插入数据。当表 `t` 的统计信息未被锁定时,可以成功执行 `ANALYZE` 语句。 ```sql mysql> CREATE TABLE t(a INT, b INT); @@ -48,7 +48,7 @@ mysql> SHOW WARNINGS; 1 row in set (0.00 sec) ``` -锁定表 `t` 的统计信息,执行 `SHOW STATS_LOCKED` 语句,显示表 `t` 的统计信息被锁定。 +锁定表 `t` 的统计信息并执行 `SHOW STATS_LOCKED`。输出显示表 `t` 的统计信息已被锁定。 ```sql mysql> LOCK STATS t; @@ -69,6 +69,6 @@ mysql> SHOW STATS_LOCKED; ## 另请参阅 -* [统计信息](/statistics.md#锁定统计信息) +* [统计信息](/statistics.md#lock-statistics) * [LOCK STATS](/sql-statements/sql-statement-lock-stats.md) * [UNLOCK STATS](/sql-statements/sql-statement-unlock-stats.md) diff --git a/sql-statements/sql-statement-show-stats-meta.md b/sql-statements/sql-statement-show-stats-meta.md index 92462304d524..a18f2882ddc2 100644 --- a/sql-statements/sql-statement-show-stats-meta.md +++ b/sql-statements/sql-statement-show-stats-meta.md @@ -1,26 +1,26 @@ --- title: SHOW STATS_META -summary: TiDB 数据库中 SHOW STATS_META 语句的简单说明。 +summary: TiDB 数据库中 SHOW STATS_META 的使用概述。 --- # SHOW STATS_META -你可以通过 `SHOW STATS_META` 来查看表的总行数以及修改的行数等信息,可以通过 ShowLikeOrWhere 来筛选需要的信息。 +你可以使用 `SHOW STATS_META` 来查看表中有多少行以及该表中有多少行被更改。使用此语句时,你可以通过 `ShowLikeOrWhere` 子句过滤所需信息。 -目前 `SHOW STATS_META` 会输出 6 列,具体如下: +目前,`SHOW STATS_META` 语句输出 6 列: -| 列名 | 说明 | +| 列名 | 描述 | | -------- | ------------- | -| db_name | 数据库名 | +| db_name | 数据库名称 | | table_name | 表名 | -| partition_name| 分区名 | -| update_time | 更新时间 | +| partition_name | 分区名称 | +| update_time | 最后更新时间 | | modify_count | 修改的行数 | | row_count | 总行数 | > **注意:** > -> 在 TiDB 根据 DML 语句自动更新总行数以及修改的行数时,`update_time` 也会被更新,因此并不能认为 `update_time` 是最近一次发生 Analyze 的时间。 +> `update_time` 是在 TiDB 根据 DML 语句更新 `modify_count` 和 `row_count` 字段时更新的。因此 `update_time` 不是 `ANALYZE` 语句的最后执行时间。 ## 语法图 @@ -71,5 +71,5 @@ SHOW STATS_META WHERE table_name = 't2'; ## 另请参阅 -* [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) -* [常规统计信息](/statistics.md) +* [ANALYZE](/sql-statements/sql-statement-analyze-table.md) +* [统计信息简介](/statistics.md) diff --git a/sql-statements/sql-statement-show-stats-topn.md b/sql-statements/sql-statement-show-stats-topn.md index e087e1178293..ba19dbc4515d 100644 --- a/sql-statements/sql-statement-show-stats-topn.md +++ b/sql-statements/sql-statement-show-stats-topn.md @@ -1,29 +1,30 @@ --- title: SHOW STATS_TOPN -summary: TiDB 数据库中 SHOW STATS_TOPN 的使用概况。 +summary: TiDB 数据库中 SHOW STATS_TOPN 的使用概览。 --- # SHOW STATS_TOPN -`SHOW STATS_TOPN` 语句显示[常规统计信息](/statistics.md)中的 Top-N 信息。 +`SHOW STATS_TOPN` 语句显示[统计信息](/statistics.md)中的 Top-N 信息。 目前,`SHOW STATS_TOPN` 语句返回以下列: -| 列名 | 说明 | +| 列名 | 描述 | | ---- | ----| -| `Db_name` | 数据库名 | +| `Db_name` | 数据库名称 | | `Table_name` | 表名 | -| `Partition_name` | 分区名 | -| `Column_name` | 取决于 `Is_index` 值:`Is_index` 为 `0` 时显示列名,为 `1` 时显示索引名 | -| `Is_index` | 是否是索引列 | +| `Partition_name` | 分区名称 | +| `Column_name` | 列名(当 `is_index` 为 `0` 时)或索引名(当 `is_index` 为 `1` 时) | +| `Is_index` | 是否为索引列 | | `Value` | 该列的值 | -| `Count` | 值出现的次数 | +| `Count` | 该值出现的次数 | -## 语法图 +## 语法 ```ebnf+diagram ShowStatsTopnStmt ::= "SHOW" "STATS_TOPN" ShowLikeOrWhere? + ShowLikeOrWhere ::= "LIKE" SimpleExpr | "WHERE" Expression @@ -51,9 +52,9 @@ SHOW STATS_TOPN WHERE Table_name='t'; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 * [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) -* [常规统计信息](/statistics.md) \ No newline at end of file +* [统计信息简介](/statistics.md) diff --git a/sql-statements/sql-statement-show-status.md b/sql-statements/sql-statement-show-status.md index 83f7534b6644..7cf76f321330 100644 --- a/sql-statements/sql-statement-show-status.md +++ b/sql-statements/sql-statement-show-status.md @@ -1,21 +1,23 @@ --- -title: SHOW [GLOBAL|SESSION] STATUS -summary: TiDB 数据库中 SHOW [GLOBAL|SESSION] STATUS 的使用概况。 +title: SHOW [GLOBAL|SESSION] STATUS | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW [GLOBAL|SESSION] STATUS 的使用概览。 --- # SHOW [GLOBAL|SESSION] STATUS -`SHOW [GLOBAL|SESSION] STATUS` 语句用于提供 MySQL 兼容性。对于大部分监控指标,TiDB 使用 Prometheus 和 Grafana 来集中收集,而不是使用 `SHOW STATUS`。 +此语句是为了与 MySQL 兼容而包含的。对于大多数指标,TiDB 使用 Prometheus 和 Grafana 进行集中指标收集,而不是使用 `SHOW STATUS`。 -该语句输出中各变量的详细介绍,请参考[服务器状态变量](/status-variables.md)。 +变量的完整描述可以在这里找到:[状态变量](/status-variables.md) -## 语法图 +## 语法 ```ebnf+diagram ShowStatusStmt ::= 'SHOW' Scope? 'STATUS' ShowLikeOrWhere? + Scope ::= ( 'GLOBAL' | 'SESSION' ) + ShowLikeOrWhere ::= "LIKE" SimpleExpr | "WHERE" Expression @@ -24,10 +26,7 @@ ShowLikeOrWhere ::= ## 示例 ```sql -SHOW SESSION STATUS; -``` - -``` +mysql> SHOW SESSION STATUS; +-------------------------------+--------------------------------------+ | Variable_name | Value | +-------------------------------+--------------------------------------+ @@ -46,13 +45,8 @@ SHOW SESSION STATUS; | server_id | 61160e73-ab80-40ff-8f33-27d55d475fd1 | +-------------------------------+--------------------------------------+ 13 rows in set (0.00 sec) -``` -```sql -SHOW GLOBAL STATUS; -``` - -``` +mysql> SHOW GLOBAL STATUS; +-----------------------+--------------------------------------+ | Variable_name | Value | +-----------------------+--------------------------------------+ @@ -71,9 +65,9 @@ SHOW GLOBAL STATUS; ## MySQL 兼容性 -`SHOW [GLOBAL|SESSION] STATUS` 语句与 MySQL 兼容。 +* 此语句与 MySQL 兼容。 ## 另请参阅 * [FLUSH STATUS](/sql-statements/sql-statement-flush-status.md) -* [服务器状态变量](/status-variables.md) \ No newline at end of file +* [服务器状态变量](/status-variables.md) diff --git a/sql-statements/sql-statement-show-table-next-rowid.md b/sql-statements/sql-statement-show-table-next-rowid.md index 2f0869eec8e2..943a53fb7b63 100644 --- a/sql-statements/sql-statement-show-table-next-rowid.md +++ b/sql-statements/sql-statement-show-table-next-rowid.md @@ -1,18 +1,18 @@ --- title: SHOW TABLE NEXT_ROW_ID -summary: TiDB 数据库中 SHOW TABLE NEXT_ROW_ID 的使用概况。 +summary: 了解在 TiDB 中 `SHOW TABLE NEXT_ROW_ID` 的用法。 --- # SHOW TABLE NEXT_ROW_ID -`SHOW TABLE NEXT_ROW_ID` 语句用于显示用户表中某些特殊列的详情,主要包含以下几种类型: +`SHOW TABLE NEXT_ROW_ID` 用于显示表中某些特殊列的详细信息,包括: -* TiDB 创建的 [`AUTO_INCREMENT`](/auto-increment.md) 类型列,即 `_tidb_rowid` 列 -* 用户创建的 `AUTO_INCREMENT` 类型列 -* 用户创建的 [`AUTO_RANDOM`](/auto-random.md) 类型列 -* 用户创建的 [`SEQUENCE`](/sql-statements/sql-statement-create-sequence.md) 对象信息 +* TiDB 自动创建的 [`AUTO_INCREMENT`](/auto-increment.md) 列,即 `_tidb_rowid` 列。 +* 用户创建的 `AUTO_INCREMENT` 列。 +* 用户创建的 [`AUTO_RANDOM`](/auto-random.md) 列。 +* 用户创建的 [`SEQUENCE`](/sql-statements/sql-statement-create-sequence.md)。 -## 语法图 +## 语法概要 ```ebnf+diagram ShowTableNextRowIDStmt ::= @@ -21,9 +21,7 @@ ShowTableNextRowIDStmt ::= ## 示例 -下面示例中,对于新建的表,由于没有任何的 Row ID 分配,NEXT_GLOBAL_ROW_ID 值为 `1`。 - -{{< copyable "sql" >}} +对于新创建的表,由于尚未分配行 ID,`NEXT_GLOBAL_ROW_ID` 为 `1`。 ```sql CREATE TABLE t(a int); @@ -40,9 +38,7 @@ SHOW TABLE t NEXT_ROW_ID; 1 row in set (0.00 sec) ``` -下面示例中,表中写入了数据,负责写入的 TiDB Server 一次性向存储层请求了 30000 个 ID 缓存起来,NEXT_GLOBAL_ROW_ID 值为 `30001`。ID 的数量由 [`AUTO_ID_CACHE`](/auto-increment.md#auto_id_cache) 控制。 - -{{< copyable "sql" >}} +数据已写入表中。插入数据的 TiDB 服务器一次性分配并缓存了 30000 个 ID。因此,NEXT_GLOBAL_ROW_ID 现在是 30001。ID 的数量由 [`AUTO_ID_CACHE`](/auto-increment.md#auto_id_cache) 控制。 ```sql INSERT INTO t VALUES (), (), (); @@ -62,7 +58,7 @@ SHOW TABLE t NEXT_ROW_ID; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-table-regions.md b/sql-statements/sql-statement-show-table-regions.md index b7c4faa8a7ea..af2a70390616 100644 --- a/sql-statements/sql-statement-show-table-regions.md +++ b/sql-statements/sql-statement-show-table-regions.md @@ -1,21 +1,24 @@ --- title: SHOW TABLE REGIONS -summary: 了解如何使用 TiDB 数据库中的 SHOW TABLE REGIONS。 +summary: 了解如何在 TiDB 中使用 SHOW TABLE REGIONS。 --- # SHOW TABLE REGIONS -`SHOW TABLE REGIONS` 语句用于显示 TiDB 中某个表的 Region 信息。 +`SHOW TABLE REGIONS` 语句用于显示 TiDB 中表的 Region 信息。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ## 语法 ```sql SHOW TABLE [table_name] REGIONS [WhereClauseOptional]; - SHOW TABLE [table_name] INDEX [index_name] REGIONS [WhereClauseOptional]; ``` -### 语法图 +## 语法图 ```ebnf+diagram ShowTableRegionStmt ::= @@ -25,29 +28,41 @@ TableName ::= (SchemaName ".")? Identifier ``` -`SHOW TABLE REGIONS` 会返回如下列: +执行 `SHOW TABLE REGIONS` 返回以下列: -* `REGION_ID`:Region 的 ID。 -* `START_KEY`:Region 的 Start key。 -* `END_KEY`:Region 的 End key。 +* `REGION_ID`:Region ID。 +* `START_KEY`:Region 的起始键。 +* `END_KEY`:Region 的结束键。 * `LEADER_ID`:Region 的 Leader ID。 -* `LEADER_STORE_ID`:Region leader 所在的 store (TiKV) ID。 -* `PEERS`:Region 所有副本的 ID。 -* `SCATTERING`:Region 是否正在调度中。1 表示正在调度。 -* `WRITTEN_BYTES`:估算的 Region 在 1 个心跳周期内的写入数据量大小,单位是 byte。 -* `READ_BYTES`:估算的 Region 在 1 个心跳周期内的读数据量大小,单位是 byte。 -* `APPROXIMATE_SIZE(MB)`:估算的 Region 的数据量大小,单位是 MB。 -* `APPROXIMATE_KEYS`:估算的 Region 内 Key 的个数。 -* `SCHEDULING_CONSTRAINTS`:Region 所在的表或者分区所关联的[放置策略](/placement-rules-in-sql.md)的规则。 -* `SCHEDULING_STATE`:关联了放置策略的 Region 的当前调度状态。 +* `LEADER_STORE_ID`:Region leader 所在的 store(TiKV)的 ID。 +* `PEERS`:所有 Region 副本的 ID。 +* `SCATTERING`:Region 是否正在调度。`1` 表示是。 +* `WRITTEN_BYTES`:一个心跳周期内估计写入该 Region 的数据量,单位为字节。 +* `READ_BYTES`:一个心跳周期内估计从该 Region 读取的数据量,单位为字节。 +* `APPROXIMATE_SIZE(MB)`:该 Region 中数据量的估计值,单位为兆字节(MB)。 +* `APPROXIMATE_KEYS`:该 Region 中 Key 的估计数量。 + + + +* `SCHEDULING_CONSTRAINTS`:与 Region 所属的表或分区相关联的[放置规则设置](/placement-rules-in-sql.md)。 + + + + + +* `SCHEDULING_CONSTRAINTS`:与 Region 所属的表或分区相关联的放置规则设置。 + + + +* `SCHEDULING_STATE`:具有放置规则的 Region 的调度状态。 > **注意:** > -> `WRITTEN_BYTES`,`READ_BYTES`,`APPROXIMATE_SIZE(MB)`,`APPROXIMATE_KEYS` 的值是 PD 根据 Region 的心跳汇报信息统计,估算出来的数据,所以不是精确的数据。 +> `WRITTEN_BYTES`、`READ_BYTES`、`APPROXIMATE_SIZE(MB)`、`APPROXIMATE_KEYS` 的值不是准确数据。它们是 PD 根据从 Region 收到的心跳信息估算的数据。 ## 示例 -创建一个示例表,并在若干 Region 中填充足够的数据量: +创建一个包含足够数据以填充几个 Region 的示例表: {{< copyable "sql" >}} @@ -75,13 +90,11 @@ SELECT SLEEP(5); SHOW TABLE t1 REGIONS; ``` -结果显示示例表被切分成多个 Regions。`REGION_ID`、`START_KEY` 和 `END_KEY` 可能不完全匹配: +输出应该显示表被分割成多个 Region。`REGION_ID`、`START_KEY` 和 `END_KEY` 可能不完全匹配: ```sql -SHOW TABLE t1 REGIONS; -``` - -``` +... +mysql> SHOW TABLE t1 REGIONS; +-----------+--------------+--------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ | REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS | SCHEDULING_CONSTRAINTS | SCHEDULING_STATE | +-----------+--------------+--------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ @@ -92,32 +105,20 @@ SHOW TABLE t1 REGIONS; 3 rows in set (0.00 sec) ``` -解释: - -上面 `START_KEY` 列的值 `t_75_r_31717` 和 `END_KEY` 列的值 `t_75_r_63434` 表示主键在 `31717` 和 `63434` 之间的数据存储在该 Region 中。`t_75_` 是前缀,表示这是表格 (`t`) 的 Region,`75` 是表格的内部 ID。若 `START_KEY` 或 `END_KEY` 的一对键值为空,分别表示负无穷大或正无穷大。 - -TiDB 会根据需要自动重新平衡 Regions。建议使用 `SPLIT TABLE REGION` 语句手动进行平衡: - -{{< copyable "sql" >}} +在上面的输出中,`START_KEY` 为 `t_75_r_31717` 和 `END_KEY` 为 `t_75_r_63434` 表示主键在 `31717` 和 `63434` 之间的数据存储在这个 Region 中。前缀 `t_75_` 表示这是一个表(`t`)的 Region,该表的内部表 ID 为 `75`。`START_KEY` 或 `END_KEY` 的空值分别表示负无穷或正无穷。 -```sql -SPLIT TABLE t1 BETWEEN (31717) AND (63434) REGIONS 2; -``` +TiDB 会根据需要自动重新平衡 Region。对于手动重新平衡,使用 `SPLIT TABLE REGION` 语句: ```sql +mysql> SPLIT TABLE t1 BETWEEN (31717) AND (63434) REGIONS 2; +--------------------+----------------------+ | TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO | +--------------------+----------------------+ | 1 | 1 | +--------------------+----------------------+ 1 row in set (42.34 sec) -``` -```sql -SHOW TABLE t1 REGIONS; -``` - -```sql +mysql> SHOW TABLE t1 REGIONS; +-----------+--------------+--------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ | REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS | SCHEDULING_CONSTRAINTS | SCHEDULING_STATE | +-----------+--------------+--------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ @@ -129,20 +130,15 @@ SHOW TABLE t1 REGIONS; 4 rows in set (0.00 sec) ``` -上面的输出结果显示 Region 96 被切分,并创建一个新的 Region 98。切分操作不会影响表中的其他 Region。输出结果同样证实: +上面的输出显示 Region 96 被分割,创建了一个新的 Region 98。表中的其他 Region 不受分割操作的影响。这可以通过输出统计信息确认: -- `TOTAL_SPLIT_REGION` 表示新切的 Region 数量。以上示例新切了 1 个 Region。 -- `SCATTER_FINISH_RATIO` 表示新切的 Region 的打散成功率,1.0 表示都已经打散了。 - -更详细的示例如下: - -{{< copyable "sql" >}} +* `TOTAL_SPLIT_REGION` 表示新分割的 Region 数量。在此示例中,数量为 1。 +* `SCATTER_FINISH_RATIO` 表示新分割的 Region 成功分散的比率。`1.0` 表示所有 Region 都已分散。 -```sql -SHOW TABLE t REGIONS; -``` +更详细的示例: ```sql +mysql> SHOW TABLE t REGIONS; +-----------+--------------+--------------+-----------+-----------------+---------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ | REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS | SCHEDULING_CONSTRAINTS | SCHEDULING_STATE | +-----------+--------------+--------------+-----------+-----------------+---------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ @@ -156,20 +152,17 @@ SHOW TABLE t REGIONS; 6 rows in set ``` -解释: - -- Region 102 的 `START_KEY` 和 `END_KEY` 中,`t_43` 是表数据前缀和 table ID,`_r` 是表 t record 数据的前缀,索引数据的前缀是 `_i`,所以 Region 102 的 `START_KEY` 和 `END_KEY` 表示用来存储 `[-inf, 20000)` 之前的 record 数据。其他 Region (106, 110, 114, 3) 的存储范围依次类推。 -- Region 98 用来存储索引数据存储。表 t 索引数据的起始 key 是 `t_43_i`,处于 Region 98 的存储范围内。 +在上面的示例中: -查看表 t 在 store 1 上的 region,用 `WHERE` 条件过滤。 +* 表 t 对应六个 Region。在这些 Region 中,`102`、`106`、`110`、`114` 和 `3` 存储行数据,`98` 存储索引数据。 +* 对于 Region `102` 的 `START_KEY` 和 `END_KEY`,`t_43` 表示表前缀和 ID。`_r` 是表 t 中记录数据的前缀。`_i` 是索引数据的前缀。 +* 在 Region `102` 中,`START_KEY` 和 `END_KEY` 表示存储了范围 `[-inf, 20000)` 内的记录数据。同样,也可以计算出 Region(`106`、`110`、`114`、`3`)中数据存储的范围。 +* Region `98` 存储索引数据。表 t 的索引数据的起始键是 `t_43_i`,它在 Region `98` 的范围内。 -{{< copyable "sql" >}} +要检查 store 1 中对应表 t 的 Region,使用 `WHERE` 子句: ```sql -SHOW TABLE t REGIONS WHERE leader_store_id =1; -``` - -``` +test> SHOW TABLE t REGIONS WHERE leader_store_id =1; +-----------+-----------+---------+-----------+-----------------+--------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ | REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS | SCHEDULING_CONSTRAINTS | SCHEDULING_STATE | +-----------+-----------+---------+-----------+-----------------+--------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ @@ -177,15 +170,10 @@ SHOW TABLE t REGIONS WHERE leader_store_id =1; +-----------+-----------+---------+-----------+-----------------+--------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ ``` -用 `SPLIT TABLE REGION` 语法切分索引数据的 Region,下面语法把表 t 的索引 name 数据在 [a,z] 范围内切分成 2 个 Region。 - -{{< copyable "sql" >}} +使用 `SPLIT TABLE REGION` 将索引数据分割成 Region。在下面的示例中,表 t 的索引数据 `name` 在范围 `[a,z]` 内被分割成两个 Region。 ```sql -SPLIT TABLE t INDEX name BETWEEN ("a") AND ("z") REGIONS 2; -``` - -``` +test> SPLIT TABLE t INDEX name BETWEEN ("a") AND ("z") REGIONS 2; +--------------------+----------------------+ | TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO | +--------------------+----------------------+ @@ -194,15 +182,10 @@ SPLIT TABLE t INDEX name BETWEEN ("a") AND ("z") REGIONS 2; 1 row in set ``` -现在表 t 一共有 7 个 Region,其中 5 个 Region (102, 106, 110, 114, 3) 用来存表 t 的 record 数据,另外 2 个 Region (135, 98) 用来存 name 索引的数据。 - -{{< copyable "sql" >}} +现在表 t 对应七个 Region。其中五个(`102`、`106`、`110`、`114`、`3`)存储表 t 的记录数据,另外两个(`135`、`98`)存储索引数据 `name`。 ```sql -SHOW TABLE t REGIONS; -``` - -``` +test> SHOW TABLE t REGIONS; +-----------+-----------------------------+-----------------------------+-----------+-----------------+---------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ | REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS | SCHEDULING_CONSTRAINTS | SCHEDULING_STATE | +-----------+-----------------------------+-----------------------------+-----------+-----------------+---------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ @@ -219,7 +202,7 @@ SHOW TABLE t REGIONS; ## MySQL 兼容性 -`SHOW TABLE REGIONS` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-table-status.md b/sql-statements/sql-statement-show-table-status.md index 9578fe8d65dc..b58f49efe804 100644 --- a/sql-statements/sql-statement-show-table-status.md +++ b/sql-statements/sql-statement-show-table-status.md @@ -1,17 +1,17 @@ --- -title: SHOW TABLE STATUS -summary: TiDB 数据库中 SHOW TABLE STATUS 的使用概况。 +title: SHOW TABLE STATUS | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW TABLE STATUS 的使用概述。 --- # SHOW TABLE STATUS -`SHOW TABLE STATUS` 语句用于显示 TiDB 中表的各种统计信息。如果显示统计信息过期,建议运行 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md)。 +此语句显示 TiDB 中表的各种统计信息。如果统计信息看起来已过期,建议运行 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md)。 -## 语法图 +## 语法概要 ```ebnf+diagram -ShowTableStmt ::= - "SHOW" "FULL"? "TABLES" ("FROM" Identifier | "IN" Identifier )? ShowLikeOrWhere? +ShowTableStatusStmt ::= + "SHOW" "TABLE" "STATUS" ("FROM" Identifier | "IN" Identifier )? ShowLikeOrWhere? ShowLikeOrWhere ::= "LIKE" SimpleExpr @@ -21,27 +21,14 @@ ShowLikeOrWhere ::= ## 示例 ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) -``` - -```sql -INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); -``` -``` +mysql> INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -```sql -SHOW TABLE STATUS LIKE 't1'; -``` -``` +mysql> SHOW TABLE STATUS LIKE 't1'\G *************************** 1. row *************************** Name: t1 Engine: InnoDB @@ -62,21 +49,11 @@ Max_data_length: 0 Create_options: Comment: 1 row in set (0.00 sec) -``` - -```sql -ANALYZE TABLE t1; -``` -``` +mysql> ANALYZE TABLE t1; Query OK, 0 rows affected (0.12 sec) -``` -```sql -SHOW TABLE STATUS LIKE 't1'; -``` - -``` +mysql> SHOW TABLE STATUS LIKE 't1'\G *************************** 1. row *************************** Name: t1 Engine: InnoDB @@ -101,7 +78,7 @@ Max_data_length: 0 ## MySQL 兼容性 -`SHOW TABLE STATUS` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW TABLE STATUS` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告 bug](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-tables.md b/sql-statements/sql-statement-show-tables.md index 42f94d4b3112..1ae3267622e4 100644 --- a/sql-statements/sql-statement-show-tables.md +++ b/sql-statements/sql-statement-show-tables.md @@ -1,13 +1,13 @@ --- -title: SHOW [FULL] TABLES -summary: TiDB 数据库中 SHOW [FULL] TABLES 的使用概况。 +title: SHOW [FULL] TABLES | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW [FULL] TABLES 的使用概览。 --- # SHOW [FULL] TABLES -`SHOW [FULL] TABLES` 语句用于显示当前所选数据库中表和视图的列表。可选关键字 `FULL` 说明表的类型是 `BASE TABLE`、`SEQUENCE` 还是 `VIEW`。 +该语句显示当前选定数据库中的表和视图列表。可选关键字 `FULL` 表示一个表是 `BASE TABLE`、`SEQUENCE` 还是 `VIEW` 类型。 -若要在不同的数据库中显示表,可使用 `SHOW TABLES IN DatabaseName` 语句。 +要显示其他数据库中的表,使用 `SHOW TABLES IN DatabaseName`。 ## 语法图 @@ -77,11 +77,11 @@ mysql> SHOW TABLES IN mysql; ## MySQL 兼容性 -`SHOW [FULL] TABLES` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW [FULL] TABLES` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 * [CREATE TABLE](/sql-statements/sql-statement-create-table.md) * [DROP TABLE](/sql-statements/sql-statement-drop-table.md) * [SHOW CREATE TABLE](/sql-statements/sql-statement-show-create-table.md) -* [`information_schema.tables`](/information-schema/information-schema-tables.md) \ No newline at end of file +* [`INFORMATION_SCHEMA.TABLES`](/information-schema/information-schema-tables.md) diff --git a/sql-statements/sql-statement-show-variables.md b/sql-statements/sql-statement-show-variables.md index b9c73de12b0f..c2112deabd16 100644 --- a/sql-statements/sql-statement-show-variables.md +++ b/sql-statements/sql-statement-show-variables.md @@ -1,18 +1,18 @@ --- -title: SHOW [GLOBAL|SESSION] VARIABLES -summary: TiDB 数据库中 SHOW [GLOBAL|SESSION] VARIABLES 的使用概况。 +title: SHOW [GLOBAL|SESSION] VARIABLES | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW [GLOBAL|SESSION] VARIABLES 的使用概述。 --- # SHOW [GLOBAL|SESSION] VARIABLES -`SHOW [GLOBAL|SESSION] VARIABLES` 语句用于显示 `GLOBAL` 或 `SESSION` 范围的变量列表。如果未指定范围,则应用默认范围 `SESSION`。 +此语句显示 `GLOBAL` 或 `SESSION` 作用域的变量列表。如果未指定作用域,则默认使用 `SESSION` 作用域。 ## 语法图 ```ebnf+diagram ShowVariablesStmt ::= "SHOW" ("GLOBAL" | "SESSION")? VARIABLES ShowLikeOrWhere? - + ShowLikeOrWhere ::= "LIKE" SimpleExpr | "WHERE" Expression @@ -20,15 +20,10 @@ ShowLikeOrWhere ::= ## 示例 -查看 TiDB 定义的专用系统变量,关于这些变量的含义参见[系统变量和语法](/system-variables.md)。 - -{{< copyable "sql" >}} - -```sql -SHOW GLOBAL VARIABLES LIKE 'tidb%'; -``` +列出所有 TiDB 特定的变量。有关详细说明,请参考[系统变量](/system-variables.md)。 ```sql +mysql> SHOW GLOBAL VARIABLES LIKE 'tidb%'; +-------------------------------------+---------------------+ | Variable_name | Value | +-------------------------------------+---------------------+ @@ -63,7 +58,7 @@ SHOW GLOBAL VARIABLES LIKE 'tidb%'; | tidb_enable_radix_join | 0 | | tidb_enable_slow_log | 1 | | tidb_enable_stmt_summary | 1 | -| tidb_enable_table_partition | on | +| tidb_enable_table_partition | on | | tidb_enable_vectorized_expression | 1 | | tidb_enable_window_function | 1 | | tidb_evolve_plan_baselines | off | @@ -139,41 +134,24 @@ SHOW GLOBAL VARIABLES LIKE 'tidb%'; | tidb_window_concurrency | 4 | +-------------------------------------+---------------------+ 108 rows in set (0.01 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW GLOBAL VARIABLES LIKE 'time_zone%'; -``` - -```sql +mysql> SHOW GLOBAL VARIABLES LIKE 'time_zone%'; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | time_zone | SYSTEM | +---------------+--------+ 1 row in set (0.00 sec) -``` -```sql -SHOW VARIABLES WHERE Variable_name="tidb_window_concurrency"; -``` - -```sql +mysql> SHOW VARIABLES WHERE Variable_name="tidb_window_concurrency"; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | tidb_window_concurrency | -1 | +-------------------------+-------+ 1 row in set (0.00 sec) -``` -```sql -SHOW VARIABLES WHERE Value=300; -``` - -```sql +mysql> SHOW VARIABLES WHERE Value=300; +--------------------------------+-------+ | Variable_name | Value | +--------------------------------+-------+ @@ -190,7 +168,7 @@ SHOW VARIABLES WHERE Value=300; ## MySQL 兼容性 -`SHOW [GLOBAL|SESSION] VARIABLES` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW [GLOBAL|SESSION] VARIABLES` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-show-warnings.md b/sql-statements/sql-statement-show-warnings.md index c4eb9144d544..0cfdf2dab8a6 100644 --- a/sql-statements/sql-statement-show-warnings.md +++ b/sql-statements/sql-statement-show-warnings.md @@ -1,13 +1,13 @@ --- -title: SHOW WARNINGS -summary: TiDB 数据库中 SHOW WARNINGS 的使用概况。 +title: SHOW WARNINGS | TiDB SQL 语句参考 +summary: TiDB 数据库中 SHOW WARNINGS 的使用概览。 --- # SHOW WARNINGS -`SHOW WARNINGS` 语句用于显示当前客户端连接中已执行语句的报错列表。与在 MySQL 中一样,`sql_mode` 极大地影响哪些语句会导致错误与警告。 +此语句显示当前客户端连接中之前执行的语句产生的警告列表。与 MySQL 一样,`sql_mode` 会显著影响哪些语句会导致错误或警告。 -## 语法图 +## 语法 ```ebnf+diagram ShowWarningsStmt ::= @@ -16,123 +16,54 @@ ShowWarningsStmt ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a INT UNSIGNED); -``` - -``` +mysql> CREATE TABLE t1 (a INT UNSIGNED); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} -```sql -INSERT INTO t1 VALUES (0); -``` - -``` +mysql> INSERT INTO t1 VALUES (0); Query OK, 1 row affected (0.02 sec) -``` - -{{< copyable "sql" >}} - -```sql -SELECT 1/a FROM t1; -``` -``` +mysql> SELECT 1/a FROM t1; +------+ | 1/a | +------+ | NULL | +------+ 1 row in set, 1 warning (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -SHOW WARNINGS; -``` -``` +mysql> SHOW WARNINGS; +---------+------+---------------+ | Level | Code | Message | +---------+------+---------------+ | Warning | 1365 | Division by 0 | +---------+------+---------------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (-1); -``` - -``` +mysql> INSERT INTO t1 VALUES (-1); ERROR 1264 (22003): Out of range value for column 'a' at row 1 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +------+ | a | +------+ | 0 | +------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} - -```sql -SET sql_mode=''; -``` - -``` +mysql> SET sql_mode=''; Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (-1); -``` -``` +mysql> INSERT INTO t1 VALUES (-1); Query OK, 1 row affected, 1 warning (0.01 sec) -``` - -{{< copyable "sql" >}} -```sql -SHOW WARNINGS; -``` - -``` +mysql> SHOW WARNINGS; +---------+------+---------------------------+ | Level | Code | Message | +---------+------+---------------------------+ | Warning | 1690 | constant -1 overflows int | +---------+------+---------------------------+ 1 row in set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +------+ | a | +------+ @@ -140,11 +71,12 @@ SELECT * FROM t1; | 0 | +------+ 2 rows in set (0.00 sec) + ``` ## MySQL 兼容性 -`SHOW WARNINGS` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `SHOW WARNINGS` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-split-region.md b/sql-statements/sql-statement-split-region.md index 2108d5244de3..fd5ce2b50801 100644 --- a/sql-statements/sql-statement-split-region.md +++ b/sql-statements/sql-statement-split-region.md @@ -1,15 +1,19 @@ --- -title: Split Region 使用文档 -summary: TiDB 中的 Split Region 功能可以解决表数据超过默认 Region 大小限制后的热点问题。预切分 Region 可以根据指定的参数,预先为某个表切分出多个 Region,并打散到各个 TiKV 上去。使用 `SPLIT` 语句可以实现均匀切分和不均匀切分,返回结果包括新增预切分的 Region 数量和打散完成的比率。需要注意 `tidb_wait_split_region_finish` 和 `tidb_wait_split_region_timeout` 会影响 `SPLIT` 语句的行为。 +title: Split Region +summary: TiDB 数据库中 Split Region 的使用概览。 --- -# Split Region 使用文档 +# Split Region -在 TiDB 中新建一个表后,默认会单独切分出 1 个 [Region](/tidb-storage.md#region) 来存储这个表的数据,这个默认行为由配置文件中的 `split-table` 控制。当这个 Region 中的数据超过默认 Region 大小限制后,这个 Region 会开始分裂成 2 个 Region。 +在 TiDB 中创建的每个新表默认会分配一个 [Region](/tidb-storage.md#region) 来存储该表的数据。这个默认行为由 TiDB 配置文件中的 `split-table` 控制。当该 Region 中的数据超过默认的 Region 大小限制时,该 Region 会开始分裂成两个。 -上述情况中,如果在新建的表上发生大批量写入,则会造成热点,因为开始只有一个 Region,所有的写请求都发生在该 Region 所在的那台 TiKV 上。 +在上述情况下,由于开始时只有一个 Region,所有写请求都会发生在该 Region 所在的 TiKV 上。如果对新创建的表有大量写入,就会造成热点问题。 -为解决上述场景中的热点问题,TiDB 引入了预切分 Region 的功能,即可以根据指定的参数,预先为某个表切分出多个 Region,并打散到各个 TiKV 上去。 +为了解决上述场景中的热点问题,TiDB 引入了预分裂功能,可以根据指定的参数为某个表预先分裂多个 Region,并将这些 Region 分散到各个 TiKV 节点上。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 ## 语法图 @@ -36,7 +40,7 @@ RowValue ::= ## Split Region 的使用 -Split Region 有 2 种不同的语法,具体如下: +Split Region 语法有两种类型: - 均匀切分的语法: @@ -44,7 +48,7 @@ Split Region 有 2 种不同的语法,具体如下: SPLIT TABLE table_name [INDEX index_name] BETWEEN (lower_value) AND (upper_value) REGIONS region_num ``` - `BETWEEN lower_value AND upper_value REGIONS region_num` 语法是通过指定数据的上、下边界和 Region 数量,然后在上、下边界之间均匀切分出 `region_num` 个 Region。 + `BETWEEN lower_value AND upper_value REGIONS region_num` 定义了上界、下界和 Region 数量。然后当前的 Region 会在上下界之间被均匀地分裂成指定数量(由 `region_num` 指定)的 Region。 - 不均匀切分的语法: @@ -52,9 +56,9 @@ Split Region 有 2 种不同的语法,具体如下: SPLIT TABLE table_name [INDEX index_name] BY (value_list) [, (value_list)] ... ``` - `BY value_list…` 语法将手动指定一系列的点,然后根据这些指定的点切分 Region,适用于数据不均匀分布的场景。 + `BY value_list…` 手动指定一系列点,基于这些点对当前 Region 进行分裂。这适用于数据分布不均匀的场景。 -`SPLIT` 语句的返回结果示例如下: +以下示例显示了 `SPLIT` 语句的结果: ```sql +--------------------+----------------------+ @@ -64,43 +68,43 @@ Split Region 有 2 种不同的语法,具体如下: +--------------------+----------------------+ ``` -* `TOTAL_SPLIT_REGION`:表示新增预切分的 Region 数量。 -* `SCATTER_FINISH_RATIO`:表示新增预切分 Region 中,打散完成的比率。如 `1.0` 表示全部完成。`0.5`表示只有一半的 Region 已经打散完成,剩下的还在打散过程中。 +* `TOTAL_SPLIT_REGION`:新分裂的 Region 数量。 +* `SCATTER_FINISH_RATIO`:新分裂 Region 的分散完成率。`1.0` 表示所有 Region 都已分散。`0.5` 表示只有一半的 Region 已分散,其余正在分散中。 > **注意:** > -> 以下会话变量会影响 `SPLIT` 语句的行为,需要特别注意: +> 以下两个会话变量可能会影响 `SPLIT` 语句的行为: > -> * `tidb_wait_split_region_finish`:打散 Region 的时间可能较长,由 PD 调度以及 TiKV 的负载情况所决定。这个变量用来设置在执行 `SPLIT REGION` 语句时,是否同步等待所有 Region 都打散完成后再返回结果给客户端。默认 `1` 代表等待打散完成后再返回结果。`0` 代表不等待 Region 打散完成就返回结果。 -> * `tidb_wait_split_region_timeout`:这个变量用来设置 `SPLIT REGION` 语句的执行超时时间,单位是秒,默认值是 300 秒,如果超时还未完成 `Split` 操作,就返回一个超时错误。 +> - `tidb_wait_split_region_finish`:分散 Region 可能需要一段时间。这个时间取决于 PD 调度和 TiKV 负载。此变量用于控制执行 `SPLIT REGION` 语句时是否等待所有 Region 分散完成后才向客户端返回结果。如果其值设置为 `1`(默认值),TiDB 仅在分散完成后返回结果。如果其值设置为 `0`,TiDB 会不考虑分散状态直接返回结果。 +> - `tidb_wait_split_region_timeout`:此变量用于设置 `SPLIT REGION` 语句的执行超时时间,单位为秒。默认值为 300s。如果 `split` 操作在此时间内未完成,TiDB 会返回超时错误。 -### Split Table Region +### 切分表 Region -表中行数据的 key 由 `table_id` 和 `row_id` 编码组成,格式如下: +每个表中行数据的 key 由 `table_id` 和 `row_id` 编码而成。格式如下: ```go t[table_id]_r[row_id] ``` -例如,当 `table_id` 是 22,`row_id` 是 11 时: +例如,当 `table_id` 为 22,`row_id` 为 11 时: ```go t22_r11 ``` -同一表中行数据的 `table_id` 是一样的,但 `row_id` 肯定不一样,所以可以根据 `row_id` 来切分 Region。 +同一个表中的行数据具有相同的 `table_id`,但每一行都有其唯一的 `row_id`,可以用于 Region 切分。 #### 均匀切分 -由于 `row_id` 是整数,所以根据指定的 `lower_value`、`upper_value` 以及 `region_num`,可以推算出需要切分的 key。TiDB 先计算 step (`step = (upper_value - lower_value)/region_num`),然后在 `lower_value` 和 `upper_value` 之间每隔 step 区间切一次,最终切出 `region_num` 个 Region。 +因为 `row_id` 是整数,可以根据指定的 `lower_value`、`upper_value` 和 `region_num` 计算出要切分的 key 的值。TiDB 首先计算步长值(`step = (upper_value - lower_value)/region_num`)。然后在 `lower_value` 和 `upper_value` 之间按每个"步长"均匀切分,生成 `region_num` 指定数量的 Region。 -例如,对于表 t,如果想要从 `minInt64`~`maxInt64` 之间均匀切割出 16 个 Region,可以用以下语句: +例如,如果你想为表 t 在 key 范围 `minInt64`~`maxInt64` 之间均匀切分出 16 个 Region,可以使用以下语句: ```sql SPLIT TABLE t BETWEEN (-9223372036854775808) AND (9223372036854775807) REGIONS 16; ``` -该语句会把表 t 从 minInt64 到 maxInt64 之间均匀切割出 16 个 Region。如果已知主键的范围没有这么大,比如只会在 0~1000000000 之间,那可以用 0 和 1000000000 分别代替上面的 minInt64 和 maxInt64 来切分 Region。 +此语句将表 t 在 minInt64 和 maxInt64 之间切分成 16 个 Region。如果给定的主键范围小于指定范围,例如 0~1000000000,你可以使用 0 和 1000000000 分别代替 minInt64 和 maxInt64 来切分 Region。 ```sql SPLIT TABLE t BETWEEN (0) AND (1000000000) REGIONS 16; @@ -108,93 +112,93 @@ SPLIT TABLE t BETWEEN (0) AND (1000000000) REGIONS 16; #### 不均匀切分 -如果已知数据不是均匀分布的,比如想要 -inf ~ 10000 切一个 Region,10000 ~ 90000 切一个 Region,90000 ~ +inf 切一个 Region,可以通过手动指定点来切分 Region,示例如下: +如果已知数据分布不均匀,想要在 key 范围 -inf ~ 10000、10000 ~ 90000 和 90000 ~ +inf 分别切分一个 Region,可以通过设置固定点来实现,如下所示: ```sql SPLIT TABLE t BY (10000), (90000); ``` -### Split Index Region +### 切分索引 Region -表中索引数据的 key 由 `table_id`、`index_id` 以及索引列的值编码组成,格式如下: +表中索引数据的 key 由 `table_id`、`index_id` 和索引列的值编码而成。格式如下: ```go t[table_id]_i[index_id][index_value] ``` -例如,当 `table_id` 是 22,`index_id` 是 5,`index_value` 是 abc 时: +例如,当 `table_id` 为 22,`index_id` 为 5,`index_value` 为 abc 时: ```go t22_i5abc ``` -同一表中同一索引数据的 `table_id` 和 `index_id` 是一样的,所以要根据 `index_value` 切分索引 Region。 +同一个表中同一个索引的数据具有相同的 `table_id` 和 `index_id`。要切分索引 Region,需要根据 `index_value` 进行切分。 #### 均匀切分 -索引均匀切分与行数据均匀切分的原理一样,只是计算 step 的值较为复杂,因为 `index_value` 可能不是整数。 +索引的均匀切分方式与数据的均匀切分方式相同。但是计算步长值更复杂,因为 `index_value` 可能不是整数。 -`upper` 和 `lower` 的值会先编码成 byte 数组,去掉 `lower` 和 `upper` byte 数组的最长公共前缀后,从 `lower` 和 `upper` 各取前 8 字节转成 uint64,再计算 `step = (upper - lower)/num`。计算出 step 后再将 step 编码成 byte 数组,添加到之前 `upper`和 `lower`的最长公共前缀后面组成一个 key 后去做切分。示例如下: +首先将 `upper` 和 `lower` 的值编码成字节数组。在移除 `lower` 和 `upper` 字节数组的最长公共前缀后,将 `lower` 和 `upper` 的前 8 个字节转换为 uint64 格式。然后计算 `step = (upper - lower)/num`。之后,将计算出的步长编码成字节数组,并将其附加到 `lower` 和 `upper` 字节数组的最长公共前缀后面用于索引切分。以下是一个示例: -如果索引 idx 的列也是整数类型,可以用如下 SQL 语句切分索引数据: +如果 `idx` 索引的列是整数类型,你可以使用以下 SQL 语句切分索引数据: ```sql SPLIT TABLE t INDEX idx BETWEEN (-9223372036854775808) AND (9223372036854775807) REGIONS 16; ``` -该语句会把表 t 中 idx 索引数据 Region 从 `minInt64` 到 `maxInt64` 之间均匀切割出 16 个 Region。 +此语句将表 t 中的索引 idx 从 `minInt64` 到 `maxInt64` 切分成 16 个 Region。 -如果索引 idx1 的列是 varchar 类型,希望根据前缀字母来切分索引数据: +如果索引 idx1 的列是 varchar 类型,你想按前缀字母切分索引数据: ```sql SPLIT TABLE t INDEX idx1 BETWEEN ("a") AND ("z") REGIONS 25; ``` -该语句会把表 t 中 idx1 索引数据的 Region 从 a~z 切成 25 个 Region,region1 的范围是 [minIndexValue, b),region2 的范围是 [b, c),……,region25 的范围是 [y, maxIndexValue)。对于 idx1 索引以 a 为前缀的数据都会写到 region1,以 b 为前缀的索引数据都会写到 region2,以此类推。 +此语句将索引 idx1 从 a~z 切分成 25 个 Region。Region 1 的范围是 `[minIndexValue, b)`;Region 2 的范围是 `[b, c)`;... Region 25 的范围是 `[y, minIndexValue]`。对于 `idx` 索引,前缀为 `a` 的数据写入 Region 1,前缀为 `b` 的数据写入 Region 2。 -上面的切分方法,以 y 和 z 前缀的索引数据都会写到 region 25,因为 `z` 并不是一个上界,真正的上界是 `z` 在 ASCII 码中的下一位 `{`,所以更准确的切分方法如下: +在上述切分方法中,前缀为 `y` 和 `z` 的数据都会写入 Region 25,因为上界不是 `z`,而是 `{`(ASCII 中 `z` 的下一个字符)。因此,更准确的切分方法如下: ```sql SPLIT TABLE t INDEX idx1 BETWEEN ("a") AND ("{") REGIONS 26; ``` -该语句会把表 t 中 idx1 索引数据的 Region 从 a~`{` 切成 26 个 Region,region1 的范围是 [minIndexValue, b),region2 的范围是 [b, c),……,region25 的范围是 [y,z),region26 的范围是 [z, maxIndexValue)。 +此语句将表 `t` 的索引 idx1 从 a~`{` 切分成 26 个 Region。Region 1 的范围是 `[minIndexValue, b)`;Region 2 的范围是 `[b, c)`;... Region 25 的范围是 `[y, z)`,Region 26 的范围是 `[z, maxIndexValue)`。 -如果索引 idx2 的列是 timestamp/datetime 等时间类型,希望根据时间区间,按年为间隔切分索引数据,示例如下: +如果索引 `idx2` 的列是时间类型(如 timestamp/datetime),你想按年份切分索引 Region: ```sql SPLIT TABLE t INDEX idx2 BETWEEN ("2010-01-01 00:00:00") AND ("2020-01-01 00:00:00") REGIONS 10; ``` -该语句会把表 t 中 idx2 的索引数据 Region 从 `2010-01-01 00:00:00` 到 `2020-01-01 00:00:00` 切成 10 个 Region。region1 的范围是从 `[minIndexValue, 2011-01-01 00:00:00)`,region2 的范围是 `[2011-01-01 00:00:00, 2012-01-01 00:00:00)`…… +此语句将表 `t` 中的索引 `idx2` 从 `2010-01-01 00:00:00` 到 `2020-01-01 00:00:00` 切分成 10 个 Region。Region 1 的范围是 `[minIndexValue, 2011-01-01 00:00:00)`;Region 2 的范围是 `[2011-01-01 00:00:00, 2012-01-01 00:00:00)`。 -如果希望按照天为间隔切分索引,示例如下: +如果你想按天切分索引 Region,参考以下示例: ```sql SPLIT TABLE t INDEX idx2 BETWEEN ("2020-06-01 00:00:00") AND ("2020-07-01 00:00:00") REGIONS 30; ``` -该语句会将表 `t` 中 `idx2` 索引位于 2020 年 6 月份的数据按天为间隔切分成 30 个 Region。 +此语句将表 `t` 中索引 `idx2` 的 2020 年 6 月的数据切分成 30 个 Region,每个 Region 代表 1 天。 -其他索引列类型的切分方法也是类似的。 +其他类型索引列的 Region 切分方法类似。 -对于联合索引的数据 Region 切分,唯一不同的是可以指定多个 column 的值。 +对于联合索引的数据 Region 切分,唯一的区别是你可以指定多个列值。 -比如索引 `idx3 (a, b)` 包含 2 列,a 是 timestamp,b 是 int。如果只想根据 a 列做时间范围的切分,可以用切分单列时间索引的 SQL 语句来切分,`lower_value` 和 `upper_velue` 中不指定 b 列的值即可。 +例如,索引 `idx3 (a, b)` 包含 2 列,列 `a` 是 timestamp 类型,列 `b` 是 int 类型。如果你只想根据列 `a` 进行时间范围切分,可以使用单列时间索引的 SQL 语句。在这种情况下,不要在 `lower_value` 和 `upper_velue` 中指定列 `b` 的值。 ```sql SPLIT TABLE t INDEX idx3 BETWEEN ("2010-01-01 00:00:00") AND ("2020-01-01 00:00:00") REGIONS 10; ``` -如果想在时间相同的情况下,根据 b 列再做一次切分,在切分时指定 b 列的值即可。 +在相同的时间范围内,如果你想根据列 b 再进行一次切分。只需在切分时指定列 b 的值即可。 ```sql SPLIT TABLE t INDEX idx3 BETWEEN ("2010-01-01 00:00:00", "a") AND ("2010-01-01 00:00:00", "z") REGIONS 10; ``` -该语句在 a 列时间前缀相同的情况下,根据 b 列的值从 a~z 切了 10 个 Region。如果指定的 a 列的值不相同,那么可能不会用到 b 列的值。 +此语句根据列 b 的值在 a~z 范围内切分 10 个 Region,列 a 的时间前缀相同。如果为列 a 指定的值不同,则可能不会使用列 b 的值。 -如果表的主键为非聚簇索引 [`NONCLUSTERED`](/clustered-indexes.md),切分 Region 时需要用反引号 ``` ` ``` 来转义 `PRIMARY` 关键字。例如: +如果表的主键是[非聚簇索引](/clustered-indexes.md),在切分 Region 时需要使用反引号 ``` ` ``` 来转义 `PRIMARY` 关键字。例如: ```sql SPLIT TABLE t INDEX `PRIMARY` BETWEEN (-9223372036854775808) AND (9223372036854775807) REGIONS 16; @@ -202,15 +206,15 @@ SPLIT TABLE t INDEX `PRIMARY` BETWEEN (-9223372036854775808) AND (92233720368547 #### 不均匀切分 -索引数据也可以根据用户指定的索引值来做切分。 +索引数据也可以通过指定索引值来切分。 -假如有 idx4 (a,b),其中 a 列是 varchar 类型,b 列是 timestamp 类型。 +例如,有 `idx4 (a,b)`,列 `a` 是 varchar 类型,列 `b` 是 timestamp 类型。 ```sql SPLIT TABLE t1 INDEX idx4 BY ("a", "2000-01-01 00:00:01"), ("b", "2019-04-17 14:26:19"), ("c", ""); ``` -该语句指定了 3 个值,会切分出 4 个 Region,每个 Region 的范围如下。 +此语句指定 3 个值来切分 4 个 Region。每个 Region 的范围如下: ``` region1 [ minIndexValue , ("a", "2000-01-01 00:00:01")) @@ -219,31 +223,31 @@ region3 [("b", "2019-04-17 14:26:19") , ("c", "") ) region4 [("c", "") , maxIndexValue ) ``` -### Split 分区表的 Region +### 切分分区表的 Region -预切分分区表的 Region 在使用上和普通表一样,差别是会为每一个 partition 都做相同的切分。 +切分分区表的 Region 与切分普通表的 Region 相同。唯一的区别是对每个分区执行相同的切分操作。 -- 均匀切分的语法如下: ++ 均匀切分的语法: ```sql SPLIT [PARTITION] TABLE t [PARTITION] [(partition_name_list...)] [INDEX index_name] BETWEEN (lower_value) AND (upper_value) REGIONS region_num ``` -- 不均匀切分的语法如下: ++ 不均匀切分的语法: ```sql SPLIT [PARTITION] TABLE table_name [PARTITION (partition_name_list...)] [INDEX index_name] BY (value_list) [, (value_list)] ... ``` -#### Split 分区表的 Region 示例 +#### 切分分区表 Region 的示例 -1. 首先创建一个分区表。如果你要建一个 Hash 分区表,分成 2 个 partition,示例语句如下: +1. 创建一个分区表 `t`。假设你想创建一个分成两个分区的 Hash 表。示例语句如下: ```sql CREATE TABLE t (a INT, b INT, INDEX idx(a)) PARTITION BY HASH(a) PARTITIONS 2; ``` - 此时建完表后会为每个 partition 都单独 split 一个 Region,用 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) 语法查看该表的 Region 如下: + 创建表 `t` 后,为每个分区切分一个 Region。使用 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) 语法查看此表的 Region: ```sql SHOW TABLE t REGIONS; @@ -258,19 +262,19 @@ region4 [("c", "") , maxIndexValue ) +-----------+-----------+---------+-----------+-----------------+------------------+------------+---------------+------------+----------------------+------------------+ ``` -2. 用 `SPLIT` 语法为每个 partition 切分 Region。如果你要将各个 partition 的 [0,10000] 范围内的数据切分成 4 个 Region,示例语句如下: +2. 使用 `SPLIT` 语法为每个分区切分一个 Region。假设你想将每个分区中 `[0,10000]` 范围内的数据切分成四个 Region。示例语句如下: ```sql - SPLIT PARTITION TABLE t BETWEEN (0) AND (10000) REGIONS 4; + split partition table t between (0) and (10000) regions 4; ``` - 其中,`0` 和 `10000` 分别代表你想要打散的热点数据对应的上、下边界的 `row_id`。 + 在上述语句中,`0` 和 `10000` 分别表示你想要分散的热点数据对应的上下界 `row_id`。 > **注意:** > - > 此示例仅适用于数据热点均匀分布的场景。如果热点数据在你指定的数据范围内是不均匀分布的,请参考 [Split 分区表的 Region](#split-分区表的-region) 中不均匀切分的语法。 + > 此示例仅适用于热点数据均匀分布的场景。如果热点数据在指定数据范围内分布不均匀,请参考[切分分区表的 Region](#切分分区表的-region) 中的不均匀切分语法。 -3. 用 `SHOW TABLE REGIONS` 语法查看该表的 Region。如下会发现该表现在一共有 10 个 Region,每个 partition 分别有 5 个 Region,其中 4 个 Region 是表的行数据,1 个 Region 是表的索引数据。 +3. 再次使用 `SHOW TABLE REGIONS` 语法查看此表的 Region。你可以看到此表现在有十个 Region,每个分区有五个 Region,其中四个是行数据,一个是索引数据。 ```sql SHOW TABLE t REGIONS; @@ -293,17 +297,17 @@ region4 [("c", "") , maxIndexValue ) +-----------+---------------+---------------+-----------+-----------------+------------------+------------+---------------+------------+----------------------+------------------+ ``` -4. 如果你要给每个分区的索引切分 Region,如将索引 `idx` 的 [1000,10000] 范围切分成 2 个 Region,示例语句如下: +4. 你也可以为每个分区的索引切分 Region。例如,你可以将 `idx` 索引的 `[1000,10000]` 范围切分成两个 Region。示例语句如下: ```sql SPLIT PARTITION TABLE t INDEX idx BETWEEN (1000) AND (10000) REGIONS 2; ``` -#### Split 单个分区的 Region 示例 +#### 切分单个分区的示例 -可以单独指定要切分的 partition,示例如下: +你可以指定要切分的分区。 -1. 首先创建一个分区表。如果你要建一个 Range 分区表,分成 3 个 partition,示例语句如下: +1. 创建一个分区表。假设你想创建一个分成三个分区的 Range 分区表。示例语句如下: ```sql CREATE TABLE t ( a INT, b INT, INDEX idx(b)) PARTITION BY RANGE( a ) ( @@ -312,19 +316,19 @@ region4 [("c", "") , maxIndexValue ) PARTITION p3 VALUES LESS THAN (MAXVALUE) ); ``` -2. 如果你要将 `p1` 分区的 [0,10000] 范围内的数据预切分 2 个 Region,示例语句如下: +2. 假设你想将 `p1` 分区中 `[0,10000]` 范围的数据切分成两个 Region。示例语句如下: ```sql SPLIT PARTITION TABLE t PARTITION (p1) BETWEEN (0) AND (10000) REGIONS 2; ``` -3. 如果你要将 `p2` 分区的 [10000,20000] 范围内的数据预切分 2 个 Region,示例语句如下: +3. 假设你想将 `p2` 分区中 `[10000,20000]` 范围的数据切分成两个 Region。示例语句如下: ```sql SPLIT PARTITION TABLE t PARTITION (p2) BETWEEN (10000) AND (20000) REGIONS 2; ``` -4. 用 `SHOW TABLE REGIONS` 语法查看该表的 Region 如下: +4. 你可以使用 `SHOW TABLE REGIONS` 语法查看此表的 Region: ```sql SHOW TABLE t REGIONS; @@ -342,7 +346,7 @@ region4 [("c", "") , maxIndexValue ) +-----------+----------------+----------------+-----------+-----------------+------------------+------------+---------------+------------+----------------------+------------------+ ``` -5. 如果你要将 `p1` 和 `p2` 分区的索引 `idx` 的 [0,20000] 范围预切分 2 个 Region,示例语句如下: +5. 假设你想将 `p1` 和 `p2` 分区的 `idx` 索引的 `[0,20000]` 范围切分成两个 Region。示例语句如下: ```sql SPLIT PARTITION TABLE t PARTITION (p1,p2) INDEX idx BETWEEN (0) AND (20000) REGIONS 2; @@ -350,15 +354,13 @@ region4 [("c", "") , maxIndexValue ) ## pre_split_regions -创建带有 `AUTO_RANDOM` 或 `SHARD_ROW_ID_BITS` 属性的表时,如果希望在建表成功后就开始预均匀切分 Region,可以考虑配合 `PRE_SPLIT_REGIONS` 一起使用。预切分成的 Region 数量为 `2^(PRE_SPLIT_REGIONS)`。 +在创建具有 `AUTO_RANDOM` 或 `SHARD_ROW_ID_BITS` 属性的表时,如果你希望在表创建后立即将表均匀预分裂成多个 Region,也可以指定 `PRE_SPLIT_REGIONS` 选项。表的预分裂 Region 数量为 `2^(PRE_SPLIT_REGIONS)`。 > **注意:** > > `PRE_SPLIT_REGIONS` 的值必须小于或等于 `SHARD_ROW_ID_BITS` 或 `AUTO_RANDOM` 的值。 -以下全局变量会影响 `PRE_SPLIT_REGIONS` 的行为,需要特别注意: - -* `tidb_scatter_region`:该变量用于控制建表完成后是否等待预切分和打散 Region 完成后再返回结果。如果建表后有大批量写入,需要设置该变量值为 `1`,表示等待所有 Region 都切分和打散完成后再返回结果给客户端。否则未打散完成就进行写入会对写入性能影响有较大的影响。 +`tidb_scatter_region` 全局变量会影响 `PRE_SPLIT_REGIONS` 的行为。此变量控制在表创建后是否等待 Region 预分裂和分散完成后再返回结果。如果在创建表后有密集写入,你需要将此变量的值设置为 `1`,这样 TiDB 会等到所有 Region 分裂和分散完成后才向客户端返回结果。否则,TiDB 会在分散完成之前写入数据,这会对写入性能产生显著影响。 ### pre_split_regions 示例 @@ -366,9 +368,9 @@ region4 [("c", "") , maxIndexValue ) CREATE TABLE t (a INT, b INT, INDEX idx1(a)) SHARD_ROW_ID_BITS = 4 PRE_SPLIT_REGIONS=2; ``` -该语句在建表后,会对这个表 t 预切分出 4 + 1 个 Region。4 (2^2) 个 Region 是用来存 table 的行数据的,1 个 Region 是用来存 idx1 索引的数据。 +创建表后,此语句为表 t 分裂 `4 + 1` 个 Region。`4 (2^2)` 个 Region 用于保存表行数据,1 个 Region 用于保存 `idx1` 的索引数据。 -4 个 table Region 的范围区间如下: +这 4 个表 Region 的范围如下: ``` region1: [ -inf , 1<<61 ) @@ -377,9 +379,13 @@ region3: [ 2<<61 , 3<<61 ) region4: [ 3<<61 , +inf ) ``` -## 注意事项 + -Split Region 语句切分的 Region 会受到 PD 中 [Region merge](/best-practices/pd-scheduling-best-practices.md#region-merge) 调度的控制,需要使用[表属性](/table-attributes.md)或者[动态修改](/pd-control.md) Region merge 相关的配置项,避免新切分的 Region 不久后又被 PD 重新合并的情况。 +> **注意:** +> +> Split Region 语句分裂的 Region 受 PD 中的 [Region 合并](/best-practices/pd-scheduling-best-practices.md#region-merge)调度器控制。为了避免 PD 在新分裂的 Region 后很快就重新合并,你需要使用[表属性](/table-attributes.md)或[动态修改](/pd-control.md)与 Region 合并功能相关的配置项。 + + ## MySQL 兼容性 @@ -388,5 +394,4 @@ Split Region 语句切分的 Region 会受到 PD 中 [Region merge](/best-practi ## 另请参阅 * [SHOW TABLE REGIONS](/sql-statements/sql-statement-show-table-regions.md) - -* Session 变量:[`tidb_scatter_region`](/system-variables.md#tidb_scatter_region),[`tidb_wait_split_region_finish`](/system-variables.md#tidb_wait_split_region_finish) 和[`tidb_wait_split_region_timeout`](/system-variables.md#tidb_wait_split_region_timeout). +* 会话变量:[`tidb_scatter_region`](/system-variables.md#tidb_scatter_region)、[`tidb_wait_split_region_finish`](/system-variables.md#tidb_wait_split_region_finish) 和 [`tidb_wait_split_region_timeout`](/system-variables.md#tidb_wait_split_region_timeout)。 diff --git a/sql-statements/sql-statement-start-transaction.md b/sql-statements/sql-statement-start-transaction.md index b0f18fd73a22..74d7bacb8a7e 100644 --- a/sql-statements/sql-statement-start-transaction.md +++ b/sql-statements/sql-statement-start-transaction.md @@ -1,20 +1,20 @@ --- -title: START TRANSACTION -summary: TiDB 数据库中 START TRANSACTION 的使用概况。 +title: START TRANSACTION | TiDB SQL 语句参考 +summary: TiDB 数据库中 START TRANSACTION 的使用概述。 --- # START TRANSACTION -`START TRANSACTION` 语句用于在 TiDB 内部启动新事务。它类似于语句 `BEGIN`。 +此语句在 TiDB 中启动一个新的事务。它类似于 `BEGIN` 语句。 -在没有 `START TRANSACTION` 语句的情况下,每个语句都会在各自的事务中自动提交,这样可确保 MySQL 兼容性。 +在没有 `START TRANSACTION` 语句的情况下,每个语句默认会在其自己的事务中自动提交。这种行为确保了与 MySQL 的兼容性。 ## 语法图 **BeginTransactionStmt:** ```ebnf+diagram -BeginTransactionStmt ::= +BeginTransactionStmt ::= 'BEGIN' ( 'PESSIMISTIC' | 'OPTIMISTIC' )? | 'START' 'TRANSACTION' ( 'READ' ( 'WRITE' | 'ONLY' ( ( 'WITH' 'TIMESTAMP' 'BOUND' TimestampBound )? | AsOfClause ) ) | 'WITH' 'CONSISTENT' 'SNAPSHOT' | 'WITH' 'CAUSAL' 'CONSISTENCY' 'ONLY' )? @@ -24,54 +24,29 @@ AsOfClause ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a int NOT NULL PRIMARY KEY); -``` - -``` +mysql> CREATE TABLE t1 (a int NOT NULL PRIMARY KEY); Query OK, 0 rows affected (0.12 sec) -``` - -{{< copyable "sql" >}} -```sql -START TRANSACTION; -``` - -``` +mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -INSERT INTO t1 VALUES (1); -``` - -``` +mysql> INSERT INTO t1 VALUES (1); Query OK, 1 row affected (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -COMMIT; -``` - -``` +mysql> COMMIT; Query OK, 0 rows affected (0.01 sec) ``` ## MySQL 兼容性 -* 执行 `START TRANSACTION` 在 TiDB 中开启事务并立即生成快照。而在 MySQL 中,执行 `START TRANSACTION` 会开启事务但不会立即生成快照。TiDB 中的 `START TRANSACTION` 等同于 MySQL 中的 `START TRANSACTION WITH CONSISTENT SNAPSHOT`。 -* 为与 MySQL 兼容,TiDB 会解析 `START TRANSACTION READ ONLY` 语句,但解析后 TiDB 仍允许写入操作。 +* `START TRANSACTION` 在 TiDB 中立即启动一个事务。这与 MySQL 不同,MySQL 中的 `START TRANSACTION` 会延迟创建事务。但是 TiDB 中的 `START TRANSACTION` 等同于 MySQL 的 `START TRANSACTION WITH CONSISTENT SNAPSHOT`。 + +* 为了与 MySQL 兼容,会解析 `START TRANSACTION READ ONLY` 语句,但仍然允许写操作。 ## 另请参阅 * [COMMIT](/sql-statements/sql-statement-commit.md) * [ROLLBACK](/sql-statements/sql-statement-rollback.md) * [BEGIN](/sql-statements/sql-statement-begin.md) -* [START TRANSACTION WITH CAUSAL CONSISTENCY ONLY](/transaction-overview.md#因果一致性事务) +* [START TRANSACTION WITH CAUSAL CONSISTENCY ONLY](/transaction-overview.md#causal-consistency) diff --git a/sql-statements/sql-statement-table.md b/sql-statements/sql-statement-table.md index ce53854afac3..d133f8ec0110 100644 --- a/sql-statements/sql-statement-table.md +++ b/sql-statements/sql-statement-table.md @@ -1,11 +1,11 @@ --- -title: TABLE -summary: TiDB 数据库中 TABLE 语句的使用概况。 +title: TABLE | TiDB SQL 语句参考 +summary: TiDB 数据库中 TABLE 的使用概述。 --- # TABLE -当不需要聚合或复杂的过滤操作时,可以用 `TABLE` 语句代替 `SELECT * FROM`。 +当不需要聚合或复杂过滤时,可以使用 `TABLE` 语句代替 `SELECT * FROM`。 ## 语法图 @@ -22,13 +22,13 @@ TableStmt ::= CREATE TABLE t1(id INT PRIMARY KEY); ``` -插入一些数据: +向 `t1` 插入一些数据: ```sql INSERT INTO t1 VALUES (1),(2),(3); ``` -查看表 `t1` 的数据: +查看表 `t1` 中的数据: ```sql TABLE t1; @@ -45,7 +45,7 @@ TABLE t1; 3 rows in set (0.01 sec) ``` -查询 `t1` 表,并按 `id` 字段倒序排列结果: +查询 `t1` 并按 `id` 字段降序排序: ```sql TABLE t1 ORDER BY id DESC; @@ -62,7 +62,7 @@ TABLE t1 ORDER BY id DESC; 3 rows in set (0.01 sec) ``` -查询表 `t1` 中的前 1 条记录: +查询 `t1` 中的第一条记录: ```sql TABLE t1 LIMIT 1; @@ -79,9 +79,9 @@ TABLE t1 LIMIT 1; ## MySQL 兼容性 -`TABLE` 语句是从 MySQL 8.0.19 开始引入的。 +`TABLE` 语句在 MySQL 8.0.19 中引入。 ## 另请参阅 -- [SELECT](/sql-statements/sql-statement-select.md) -- [TABLE statements in MySQL](https://dev.mysql.com/doc/refman/8.0/en/table.html) +- [`SELECT`](/sql-statements/sql-statement-select.md) +- [MySQL 中的 `TABLE` 语句](https://dev.mysql.com/doc/refman/8.0/en/table.html) diff --git a/sql-statements/sql-statement-trace.md b/sql-statements/sql-statement-trace.md index a2b669ff78fc..6fc8de07d063 100644 --- a/sql-statements/sql-statement-trace.md +++ b/sql-statements/sql-statement-trace.md @@ -1,13 +1,13 @@ --- -title: TRACE -summary: TiDB 数据库中 TRACE 的使用概况。 +title: TRACE | TiDB SQL 语句参考 +summary: TiDB 数据库中 TRACE 的使用概述。 --- # TRACE -`TRACE` 语句用于提供查询执行的详细信息,可通过 TiDB 服务器状态端口所公开的图形界面进行查看。 +`TRACE` 语句提供查询执行的详细信息。它旨在通过 TiDB 服务器状态端口暴露的图形界面进行查看。 -## 语法图 +## 语法 ```ebnf+diagram TraceStmt ::= @@ -17,11 +17,11 @@ TracableStmt ::= ( SelectStmt | DeleteFromStmt | UpdateStmt | InsertIntoStmt | ReplaceIntoStmt | UnionStmt | LoadDataStmt | BeginTransactionStmt | CommitStmt | RollbackStmt | SetStmt ) ``` -| Format | 描述 | +| 格式 | 描述 | |--------|------------------------------------| -| `row` | 以树形格式输出 | -| `json` | 以 JSON 格式结构化输出 | -| `log` | 基于日志输出 | +| row | 以树形格式输出 | +| json | 以 JSON 格式结构化输出 | +| log | 基于日志的输出 | ## 示例 @@ -31,7 +31,7 @@ TracableStmt ::= TRACE FORMAT='row' SELECT * FROM mysql.user; ``` -```sql +``` +--------------------------------------------+-----------------+------------+ | operation | startTS | duration | +--------------------------------------------+-----------------+------------+ @@ -58,7 +58,7 @@ TRACE FORMAT='row' SELECT * FROM mysql.user; TRACE FORMAT='json' SELECT * FROM mysql.user; ``` -可将 JSON 格式的跟踪文件粘贴到跟踪查看器中。查看器可通过 TiDB 状态端口访问: +JSON 格式的跟踪信息可以粘贴到跟踪查看器中,该查看器可通过 TiDB 状态端口访问: ![TiDB Trace Viewer-1](/media/trace-paste.png) @@ -70,7 +70,7 @@ TRACE FORMAT='json' SELECT * FROM mysql.user; TRACE FORMAT='log' SELECT * FROM mysql.user; ``` -```sql +``` +----------------------------+--------------------------------------------------------+------+------------------------------------+ | time | event | tags | spanName | +----------------------------+--------------------------------------------------------+------+------------------------------------+ @@ -94,7 +94,7 @@ TRACE FORMAT='log' SELECT * FROM mysql.user; ## MySQL 兼容性 -`TRACE` 语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 diff --git a/sql-statements/sql-statement-truncate.md b/sql-statements/sql-statement-truncate.md index 8e30bbb5a4e6..632271de87fa 100644 --- a/sql-statements/sql-statement-truncate.md +++ b/sql-statements/sql-statement-truncate.md @@ -1,15 +1,15 @@ --- -title: TRUNCATE -summary: TiDB 数据库中 TRUNCATE 的使用概况。 +title: TRUNCATE | TiDB SQL 语句参考 +summary: TiDB 数据库中 TRUNCATE 的使用概览。 --- # TRUNCATE -`TRUNCATE` 语句以非事务方式从表中删除所有数据。可认为 `TRUNCATE` 语句同 `DROP TABLE` + `CREATE TABLE` 组合在语义上相同,定义与 `DROP TABLE` 语句相同。 +`TRUNCATE` 语句以非事务方式删除表中的所有数据。`TRUNCATE` 在语义上可以被理解为等同于 `DROP TABLE` + 使用之前的定义 `CREATE TABLE`。 -`TRUNCATE TABLE tableName` 和 `TRUNCATE tableName` 均为有效语法。 +`TRUNCATE TABLE tableName` 和 `TRUNCATE tableName` 都是有效的语法。 -## 语法图 +## 语法 ```ebnf+diagram TruncateTableStmt ::= @@ -21,34 +21,15 @@ TableName ::= ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); -``` - -``` +mysql> CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); Query OK, 0 rows affected (0.11 sec) -``` -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 VALUES (1),(2),(3),(4),(5); -``` - -``` +mysql> INSERT INTO t1 VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +---+ | a | +---+ @@ -59,52 +40,24 @@ SELECT * FROM t1; | 5 | +---+ 5 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -TRUNCATE t1; -``` -``` +mysql> TRUNCATE t1; Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; Empty set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -INSERT INTO t1 VALUES (1),(2),(3),(4),(5); -``` - -``` +mysql> INSERT INTO t1 VALUES (1),(2),(3),(4),(5); Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0 -``` -{{< copyable "sql" >}} - -```sql -TRUNCATE TABLE t1; -``` - -``` +mysql> TRUNCATE TABLE t1; Query OK, 0 rows affected (0.11 sec) ``` ## MySQL 兼容性 -`TRUNCATE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `TRUNCATE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-unlock-stats.md b/sql-statements/sql-statement-unlock-stats.md index 01b8ea7c3a71..e3542c38e079 100644 --- a/sql-statements/sql-statement-unlock-stats.md +++ b/sql-statements/sql-statement-unlock-stats.md @@ -1,13 +1,13 @@ --- title: UNLOCK STATS -summary: TiDB 数据库中 UNLOCK STATS 的使用概况。 +summary: TiDB 数据库中 UNLOCK STATS 的使用概述。 --- # UNLOCK STATS -`UNLOCK STATS` 语句用于解锁统计信息被锁定的表。 +`UNLOCK STATS` 用于解锁表或多个表的统计信息。 -## 语法图 +## 语法概要 ```ebnf+diagram UnlockStatsStmt ::= @@ -25,9 +25,9 @@ PartitionNameList ::= ## 示例 -参考 [LOCK STATS](/sql-statements/sql-statement-lock-stats.md) 语句的示例来创建表 `t`,并锁定表 `t` 的统计信息。 +参考 [LOCK STATS](/sql-statements/sql-statement-lock-stats.md) 中的示例创建表 `t` 并锁定其统计信息。 -解锁表 `t` 的统计信息,成功执行 `ANALYZE` 语句。 +解锁表 `t` 的统计信息后,可以成功执行 `ANALYZE`。 ```sql mysql> UNLOCK STATS t; @@ -45,9 +45,9 @@ mysql> SHOW WARNINGS; 1 row in set (0.00 sec) ``` -参考 [LOCK STATS](/sql-statements/sql-statement-lock-stats.md) 语句的示例来创建表 `t`,并锁定表 `t` 的分区 `p1` 的统计信息。 +参考 [LOCK STATS](/sql-statements/sql-statement-lock-stats.md) 中的示例创建表 `t` 并锁定其分区 `p1` 的统计信息。 -解锁分区 `p1` 的统计信息,成功执行 `ANALYZE` 语句。 +解锁分区 `p1` 的统计信息后,可以成功执行 `ANALYZE`。 ```sql mysql> UNLOCK STATS t PARTITION p1; @@ -67,10 +67,10 @@ mysql> SHOW WARNINGS; ## MySQL 兼容性 -该语句是 TiDB 对 MySQL 语法的扩展。 +此语句是 TiDB 对 MySQL 语法的扩展。 ## 另请参阅 -* [统计信息](/statistics.md#锁定统计信息) +* [统计信息](/statistics.md#lock-statistics) * [LOCK STATS](/sql-statements/sql-statement-lock-stats.md) * [SHOW STATS_LOCKED](/sql-statements/sql-statement-show-stats-locked.md) diff --git a/sql-statements/sql-statement-update.md b/sql-statements/sql-statement-update.md index 92e29748ab87..e783e54b6955 100644 --- a/sql-statements/sql-statement-update.md +++ b/sql-statements/sql-statement-update.md @@ -1,6 +1,6 @@ --- -title: UPDATE -summary: TiDB 数据库中 UPDATE 的使用概况。 +title: UPDATE | TiDB SQL 语句参考 +summary: TiDB 数据库中 UPDATE 的使用概述。 --- # UPDATE @@ -28,38 +28,19 @@ TableRefs ::= > **注意:** > -> TiDB 从 v6.6.0 版本开始支持[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)功能。该功能可以将不同优先级的语句放在不同的资源组中执行,并为这些资源组分配不同的配额和优先级,可以达到更好的资源管控效果。在开启资源管控功能后,语句的调度主要受资源组的控制,`LOW_PRIORITY` 或 `HIGH_PRIORITY` 将不再生效。建议在支持资源管控的版本优先使用资源管控功能。 +> 从 v6.6.0 开始,TiDB 支持[资源控制](/tidb-resource-control.md)。你可以使用此功能在不同的资源组中以不同的优先级执行 SQL 语句。通过为这些资源组配置适当的配额和优先级,你可以更好地控制不同优先级 SQL 语句的调度。当启用资源控制时,语句优先级(`LOW_PRIORITY` 和 `HIGH_PRIORITY`)将不再生效。建议你使用[资源控制](/tidb-resource-control.md)来管理不同 SQL 语句的资源使用。 ## 示例 -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); -``` - -``` +mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL); Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - -```sql -INSERT INTO t1 (c1) VALUES (1), (2), (3); -``` -``` +mysql> INSERT INTO t1 (c1) VALUES (1), (2), (3); Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -68,26 +49,12 @@ SELECT * FROM t1; | 3 | 3 | +----+----+ 3 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -UPDATE t1 SET c1=5 WHERE c1=3; -``` -``` +mysql> UPDATE t1 SET c1=5 WHERE c1=3; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 -``` -{{< copyable "sql" >}} - -```sql -SELECT * FROM t1; -``` - -``` +mysql> SELECT * FROM t1; +----+----+ | id | c1 | +----+----+ @@ -100,7 +67,7 @@ SELECT * FROM t1; ## MySQL 兼容性 -在计算表达式中的列时,TiDB 总使用原始的值。例如: +TiDB 在计算表达式时始终使用列的原始值。例如: ```sql CREATE TABLE t (a int, b int); @@ -108,9 +75,9 @@ INSERT INTO t VALUES (1,2); UPDATE t SET a = a+1,b=a; ``` -在 MySQL 中,`b` 列的值会被更新成 2,因为 `b` 列被设置为与 `a` 列相同,而 `a`(最初是 1)在同一条语句中被更新成了 2。 +在 MySQL 中,列 `b` 被更新为 2,因为它被设置为 `a` 的值,而 `a` 的值(1)在同一语句中被更新为 `a+1`(即 2)。 -TiDB 遵守标准的 SQL 行为,这里将 `b` 列值更新成 1。 +TiDB 遵循更标准的 SQL 行为,将 `b` 更新为 1。 ## 另请参阅 diff --git a/sql-statements/sql-statement-use.md b/sql-statements/sql-statement-use.md index 4cd13a14462a..9a3566e26dbd 100644 --- a/sql-statements/sql-statement-use.md +++ b/sql-statements/sql-statement-use.md @@ -1,13 +1,13 @@ --- -title: USE -summary: TiDB 数据库中 USE 的使用概况。 +title: USE | TiDB SQL 语句参考 +summary: TiDB 数据库中 USE 的使用概述。 --- # USE -`USE` 语句可为用户会话选择当前数据库。 +`USE` 语句为用户会话选择当前数据库。 -## 语法图 +## 语法 ```ebnf+diagram UseStmt ::= @@ -19,26 +19,13 @@ DBName ::= ## 示例 -{{< copyable "sql" >}} - ```sql -USE mysql; -``` - -``` +mysql> USE mysql; 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; -``` - -``` +mysql> SHOW TABLES; +-------------------------+ | Tables_in_mysql | +-------------------------+ @@ -64,55 +51,19 @@ SHOW TABLES; | user | +-------------------------+ 20 rows in set (0.01 sec) -``` - -{{< copyable "sql" >}} - -```sql -CREATE DATABASE newtest; -``` -``` +mysql> CREATE DATABASE newtest; Query OK, 0 rows affected (0.10 sec) -``` - -{{< copyable "sql" >}} - -```sql -USE newtest; -``` -``` +mysql> USE newtest; Database changed -``` - -{{< copyable "sql" >}} - -```sql -SHOW TABLES; -``` - -``` +mysql> SHOW TABLES; Empty set (0.00 sec) -``` - -{{< copyable "sql" >}} -```sql -CREATE TABLE t1 (a int); -``` - -``` +mysql> CREATE TABLE t1 (a int); Query OK, 0 rows affected (0.10 sec) -``` -{{< copyable "sql" >}} - -```sql -SHOW TABLES; -``` - -``` +mysql> SHOW TABLES; +-------------------+ | Tables_in_newtest | +-------------------+ @@ -123,7 +74,7 @@ SHOW TABLES; ## MySQL 兼容性 -`USE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请尝试 [TiDB 支持资源](/support.md)。 +TiDB 中的 `USE` 语句与 MySQL 完全兼容。如果发现任何兼容性差异,请[报告问题](https://docs.pingcap.com/tidb/stable/support)。 ## 另请参阅 diff --git a/sql-statements/sql-statement-with.md b/sql-statements/sql-statement-with.md index 135d1cdaadf5..b0aaa2a73c43 100644 --- a/sql-statements/sql-statement-with.md +++ b/sql-statements/sql-statement-with.md @@ -1,13 +1,13 @@ --- -title: WITH -summary: TiDB 数据库中 WITH (公共表表达式) 的使用概况。 +title: WITH | TiDB SQL 语句参考 +summary: TiDB 数据库中 WITH(公用表表达式)的使用概览。 --- # WITH -公共表表达式 (CTE) 是一个临时的中间结果集,能够在 SQL 语句中引用多次,提高 SQL 语句的可读性与执行效率。在 TiDB 中可以通过 `WITH` 语句使用公共表表达式。 +公用表表达式(Common Table Expression,CTE)是一个临时结果集,可以在 SQL 语句中多次引用,以提高语句的可读性和执行效率。你可以使用 `WITH` 语句来使用公用表表达式。 -## 语法图 +## 语法 **WithClause:** @@ -41,7 +41,7 @@ IdentListWithParenOpt ::= ## 示例 -非递归的 CTE: +非递归 CTE: ```sql WITH cte AS (SELECT 1, 2) SELECT * FROM cte t1, cte t2; @@ -56,7 +56,7 @@ WITH cte AS (SELECT 1, 2) SELECT * FROM cte t1, cte t2; 1 row in set (0.00 sec) ``` -递归的 CTE: +递归 CTE: ```sql WITH RECURSIVE cte(a) AS (SELECT 1 UNION SELECT a+1 FROM cte WHERE a < 5) SELECT * FROM cte; @@ -77,14 +77,14 @@ WITH RECURSIVE cte(a) AS (SELECT 1 UNION SELECT a+1 FROM cte WHERE a < 5) SELECT ## MySQL 兼容性 -* 在严格模式下,当递归部分算出的数据长度超过初始部分的数据长度时,TiDB 会返回警告,而 MySQL 会返回错误。在非严格模式下,TiDB 与 MySQL 行为一致。 -* 递归 CTE 所使用的数据类型由初始部分决定。初始部分的数据类型在某些情况(例如函数)下与 MySQL 并不完全一致。 -* 多个 UNION / UNION ALL 情况下,MySQL 不允许 UNION 后面加 UNION ALL,TiDB 允许。 -* 如果 CTE 的定义存在问题,TiDB 会报错,而 MySQL 在未引用的情况下不报错。 +* 在严格模式下,当递归计算的数据长度超过种子部分的数据长度时,TiDB 返回警告,而 MySQL 返回错误。在非严格模式下,TiDB 的行为与 MySQL 一致。 +* 递归 CTE 的数据类型由种子部分决定。在某些情况下(如函数),种子部分的数据类型与 MySQL 不完全一致。 +* 在有多个 `UNION` / `UNION ALL` 运算符的情况下,MySQL 不允许 `UNION` 后面跟 `UNION ALL`,但 TiDB 允许。 +* 如果 CTE 的定义有问题,TiDB 会报错,而 MySQL 在 CTE 未被引用时不会报错。 ## 另请参阅 -* [公共表表达式 (CTE)](/develop/dev-guide-use-common-table-expression.md) +* [开发者指南:公用表表达式](/develop/dev-guide-use-common-table-expression.md) * [SELECT](/sql-statements/sql-statement-select.md) * [INSERT](/sql-statements/sql-statement-insert.md) * [DELETE](/sql-statements/sql-statement-delete.md) diff --git a/stale-read.md b/stale-read.md index aca4137271fd..7153b0c76995 100644 --- a/stale-read.md +++ b/stale-read.md @@ -1,75 +1,91 @@ --- -title: Stale Read 功能的使用场景 -summary: 介绍 Stale Read 功能和使用场景。 +title: Stale Read 的使用场景 +summary: 了解 Stale Read 及其使用场景。 --- -# Stale Read 功能的使用场景 +# Stale Read 的使用场景 -本文档介绍 Stale Read 的使用场景。Stale Read 是一种读取历史数据版本的机制,读取 TiDB 中存储的历史数据版本。通过 Stale Read 功能,你能从指定时间点或时间范围内读取对应的历史数据,从而避免数据同步带来延迟。当使用 Stale Read 时,TiDB 默认会随机选择一个副本来读取数据,因此能利用所有副本。如果你的应用程序不能容忍读到非实时的数据,请勿使用 Stale Read,否则读到的数据可能不是最新成功写入的数据。 +本文介绍 Stale Read 的使用场景。Stale Read 是 TiDB 用于读取存储在 TiDB 中的历史版本数据的机制。使用此机制,你可以读取特定时间点或指定时间范围内的相应历史数据,从而节省存储节点之间数据复制带来的延迟。 -## 场景描述 +当你使用 Stale Read 时,TiDB 会随机选择一个副本进行数据读取,这意味着所有副本都可用于数据读取。如果你的应用程序无法容忍读取非实时数据,请不要使用 Stale Read;否则,从副本读取的数据可能不是写入 TiDB 的最新数据。 -+ 场景一:如果一个事务仅涉及只读操作,并且一定程度上可容忍牺牲实时性,你可以使用 Stale Read 功能来读取历史数据。由于牺牲了一定的实时性,使用 Stale Read 后,TiDB 可以让请求分发到任一个副本上,使得查询的执行获得更大的吞吐量。特别是在一些小表的查询场景中,如果使用了强一致性读,Leader 可能集中在某一个存储节点上,导致查询压力集中在该节点,成为整个查询的瓶颈。通过 Stale Read,可以提升了查询整体的吞吐能力,从而显著提升查询性能。 +## 场景示例 -+ 场景二:在部分跨数据中心部署的场景中,如果使用了强一致性的 Follower 读,为了读到的数据与 Leader 上的数据一致,会产生跨数据中心获取 `Readindex` 来校验的请求,导致整体查询的访问延迟增加。通过使用 Stale Read 功能,可以牺牲一定的实时性,就近访问对应数据所在当前中心的副本,避免跨数据中心的网络延迟,降低整体查询的访问延迟。详情参考[在三数据中心下就近读取数据](/best-practices/three-dc-local-read.md)。 + + ++ 场景一:如果一个事务只涉及读操作,并且在一定程度上可以容忍数据不是最新的,你可以使用 Stale Read 来获取历史数据。使用 Stale Read 时,TiDB 以牺牲一定实时性能为代价,将查询请求发送到任意副本,从而提高查询执行的吞吐量。特别是在一些小表查询的场景中,如果使用强一致性读取,leader 可能会集中在某个存储节点上,导致查询压力也集中在该节点上。因此,该节点可能成为整个查询的瓶颈。而 Stale Read 可以提高整体查询吞吐量,显著提升查询性能。 + ++ 场景二:在一些地理分布式部署的场景中,如果使用强一致性的 follower 读取,为了确保从 Follower 读取的数据与存储在 Leader 中的数据一致,TiDB 需要从不同数据中心请求 `Readindex` 进行验证,这增加了整个查询过程的访问延迟。使用 Stale Read,TiDB 以牺牲一定实时性能为代价,访问当前数据中心的副本来读取相应数据,避免了跨中心连接带来的网络延迟,减少了整个查询的访问延迟。更多信息,请参见[三中心部署下的本地读取](/best-practices/three-dc-local-read.md)。 + + + + + +如果一个事务只涉及读操作,并且在一定程度上可以容忍数据不是最新的,你可以使用 Stale Read 来获取历史数据。使用 Stale Read 时,TiDB 以牺牲一定实时性能为代价,将查询请求发送到任意副本,从而提高查询执行的吞吐量。特别是在一些小表查询的场景中,如果使用强一致性读取,leader 可能会集中在某个存储节点上,导致查询压力也集中在该节点上。因此,该节点可能成为整个查询的瓶颈。而 Stale Read 可以提高整体查询吞吐量,显著提升查询性能。 + + ## 使用方法 -TiDB 提供语句级别、会话级别以及全局级别的 Stale Read 使用方式,具体使用方法如下: +TiDB 提供以下语句级别、会话级别和全局级别的 Stale Read 方法: -- 语句级别: - - 指定一个精确的时间点(**推荐**):如需 TiDB 读取一个时间点上保证全局事务记录一致性的数据并且不破坏隔离级别,你可以指定这个时间点对应的时间戳。要使用该方式,请参阅 [`AS OF TIMESTAMP` 语法](/as-of-timestamp.md#语法方式)文档。 - - 指定时间范围:如需 TiDB 读取在一个时间范围内尽可能新的数据并且不破坏隔离级别,你可以指定一个时间范围。在指定时间范围内,TiDB 会选择一个合适的时间戳,该时间戳能保证所访问的副本上不存在开始于这个时间戳之前且还没有提交的相关事务,即能保证在所访问的可用副本上可执行读取操作而且不会被阻塞。要使用该方式,请参阅 [`AS OF TIMESTAMP` 语法](/as-of-timestamp.md#语法方式)文档和该文档中 [`TIDB_BOUNDED_STALENESS` 函数](/as-of-timestamp.md#语法方式)部分的介绍。 -- 会话级别: - - 指定时间范围:在会话级别中,如需 TiDB 在后续的查询中读取一个时间范围内尽可能新的数据并且不破坏隔离级别,你可以通过设置一个 session 变量 `tidb_read_staleness` 来指定一个时间范围。要使用该方式,请参阅[通过系统变量 `tidb_read_staleness` 读取历史数据](/tidb-read-staleness.md)。 +- 语句级别 + - 指定精确时间点(**推荐**):如果你需要 TiDB 读取特定时间点的全局一致数据,且不违反隔离级别,可以在查询语句中指定该时间点的对应时间戳。详细用法请参见 [`AS OF TIMESTAMP` 子句](/as-of-timestamp.md#语法)。 + - 指定时间范围:如果你需要 TiDB 在指定时间范围内读取尽可能新的数据,且不违反隔离级别,可以在查询语句中指定时间范围。在指定的时间范围内,TiDB 选择一个合适的时间戳来读取相应的数据。"合适"意味着在访问的副本上没有在此时间戳之前开始且尚未提交的事务,即 TiDB 可以在访问的副本上执行读取操作,且读取操作不会被阻塞。详细用法请参见 [`AS OF TIMESTAMP` 子句](/as-of-timestamp.md#语法)和 [`TIDB_BOUNDED_STALENESS` 函数](/as-of-timestamp.md#语法)的介绍。 +- 会话级别 + - 指定时间范围:在会话中,如果你需要 TiDB 在后续查询中读取指定时间范围内尽可能新的数据,且不违反隔离级别,可以通过设置 `tidb_read_staleness` 系统变量来指定时间范围。详细用法请参见 [`tidb_read_staleness`](/tidb-read-staleness.md)。 -除此以外,你也可以通过设置系统变量 [`tidb_external_ts`](/system-variables.md#tidb_external_ts-从-v640-版本开始引入) 和 [`tidb_enable_external_ts_read`](/system-variables.md#tidb_enable_external_ts_read-从-v640-版本开始引入) 来在某一会话或全局范围读取某一时间点前的历史数据。要使用该方式,请参阅[通过系统变量 `tidb_external_ts` 读取历史数据](/tidb-external-ts.md)。 +此外,TiDB 还提供了通过设置 [`tidb_external_ts`](/system-variables.md#tidb_external_ts-new-in-v640) 和 [`tidb_enable_external_ts_read`](/system-variables.md#tidb_enable_external_ts_read-new-in-v640) 系统变量在会话或全局级别指定精确时间点的方式。详细用法请参见[使用 `tidb_external_ts` 进行 Stale Read](/tidb-external-ts.md)。 -### 减少 Stale Read 延时 +### 降低 Stale Read 延迟 -Stale Read 功能会定期推进 TiDB 集群的 Resolved TS 时间戳,该时间戳能保证 TiDB 读到满足事务一致性的数据。当 Stale Read 使用的时间戳(比如 `AS OF TIMESTAMP '2016-10-08 16:45:26'`)大于 Resolved TS 时,Stale Read 会先触发 TiDB 推进 Resolved TS,等待推进完成后再读取数据,从而导致延时上升。 +Stale Read 功能会定期推进 TiDB 集群的 Resolved TS 时间戳,以确保 TiDB 读取满足事务一致性的数据。如果 Stale Read 使用的时间戳(例如 `AS OF TIMESTAMP '2016-10-08 16:45:26'`)大于 Resolved TS,Stale Read 会先触发 TiDB 推进 Resolved TS,并等待推进完成后再读取数据,导致延迟增加。 -通过调整下面 TiKV 的配置项,你可以使 TiDB 加快 Resolved TS 推进,以减少 Stale Read 延时: +为了降低 Stale Read 延迟,你可以修改以下 TiKV 配置项,使 TiDB 更频繁地推进 Resolved TS 时间戳: ```toml [resolved-ts] -advance-ts-interval = "20s" # 默认为 20 秒,可适当调小该值以加快 Resolved TS 推进,比如调整为 1 秒。 +advance-ts-interval = "20s" # 默认值为 "20s"。你可以设置为更小的值,如 "1s",以更频繁地推进 Resolved TS 时间戳。 ``` > **注意:** > -> 调小该参数会增加 TiKV CPU 使用率和各节点之间的流量。 +> 减小上述 TiKV 配置项会导致 TiKV CPU 使用率和节点间流量增加。 + + + +关于 Resolved TS 的内部原理和诊断技术的更多信息,请参见[理解 TiKV 中的 Stale Read 和 safe-ts](/troubleshoot-stale-read.md)。 -关于 Resolved TS 的内部原理和诊断方法,请参阅[理解 TiKV 中的 Stale Read 和 safe-ts](/troubleshoot-stale-read.md)。 + ## 限制 -当对表的 Stale Read 查询下推到 TiFlash 时,如果该表在 Stale Read 所指定的读取时间戳之后执行过 DDL 操作,此查询将会报错。原因是 TiFlash 只支持从最新的表结构读取数据。 +当对表的 Stale Read 查询下推到 TiFlash 时,如果该表在查询指定的读取时间戳之后执行了较新的 DDL 操作,查询将返回错误。这是因为 TiFlash 仅支持读取具有最新 schema 的表的数据。 -例如: +以下面的表为例: ```sql create table t1(id int); alter table t1 set tiflash replica 1; ``` -一分钟后进行 DDL 操作: +一分钟后执行以下 DDL 操作: ```sql alter table t1 add column c1 int not null; ``` -然后使用 Stale Read 读取一分钟前的数据: +然后,使用 Stale Read 查询一分钟前的数据: ```sql set @@session.tidb_enforce_mpp=1; select * from t1 as of timestamp NOW() - INTERVAL 1 minute; ``` -此时 TiFlash 会报错: +TiFlash 将报告如下错误: ``` ERROR 1105 (HY000): other error for mpp stream: From MPP,task_id:1>: Code: 0, e.displayText() = DB::TiFlashException: Table 323 schema version 104 newer than query schema version 100, e.what() = DB::TiFlashException, ``` -把 Stale Read 指定的读取时间戳改成 DDL 操作完成之后的时间,即可避免该错误。 +为避免此错误,你可以将 Stale Read 指定的读取时间戳更改为 DDL 操作之后的时间。 diff --git a/statement-summary-tables.md b/statement-summary-tables.md index 41f12e06282a..8c64415ac9a4 100644 --- a/statement-summary-tables.md +++ b/statement-summary-tables.md @@ -1,47 +1,54 @@ --- -title: Statement Summary Tables -summary: MySQL 的 `performance_schema` 提供了 `statement summary tables`,用于监控和统计 SQL 性能。TiDB 在 `information_schema` 中提供了类似功能的系统表,包括 `statements_summary`、`statements_summary_history`、`cluster_statements_summary` 和 `cluster_statements_summary_history`。这些表用于保存 SQL 监控指标聚合后的结果,帮助用户定位 SQL 问题。同时,还提供了参数配置来控制 statement summary 的功能,如清空周期、保存历史的数量等。 +title: Statement Summary 表 +summary: 了解 TiDB 中的 Statement Summary 表。 --- -# Statement Summary Tables +# Statement Summary 表 -针对 SQL 性能相关的问题,MySQL 在 `performance_schema` 提供了 [statement summary tables](https://dev.mysql.com/doc/refman/8.0/en/performance-schema-statement-summary-tables.html),用来监控和统计 SQL。例如其中的一张表 `events_statements_summary_by_digest`,提供了丰富的字段,包括延迟、执行次数、扫描行数、全表扫描次数等,有助于用户定位 SQL 问题。 +为了更好地处理 SQL 性能问题,MySQL 在 `performance_schema` 中提供了 [statement summary 表](https://dev.mysql.com/doc/refman/8.0/en/performance-schema-statement-summary-tables.html) 来监控带有统计信息的 SQL。其中,`events_statements_summary_by_digest` 表通过其丰富的字段(如延迟、执行次数、扫描行数和全表扫描等)在定位 SQL 问题时非常有用。 -为此,从 4.0.0-rc.1 版本开始,TiDB 在 `information_schema`(_而不是_ `performance_schema`)中提供与 `events_statements_summary_by_digest` 功能相似的系统表: +因此,从 v4.0.0-rc.1 开始,TiDB 在 `information_schema` 中(_不是_ `performance_schema`)提供了与 `events_statements_summary_by_digest` 功能类似的系统表。 -- `statements_summary` -- `statements_summary_history` -- `cluster_statements_summary` -- `cluster_statements_summary_history` +- [`statements_summary`](#statements_summary) +- [`statements_summary_history`](#statements_summary_history) +- [`cluster_statements_summary`](#statements_summary_evicted) +- [`cluster_statements_summary_history`](#statements_summary_evicted) +- [`statements_summary_evicted`](#statements_summary_evicted) -本文将详细介绍这些表,以及如何利用它们来排查 SQL 性能问题。 +> **注意:** +> +> 上述表在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +本文详细介绍这些表,并说明如何使用它们来排查 SQL 性能问题。 ## `statements_summary` -`statements_summary` 是 `information_schema` 里的一张系统表,它把 SQL 按所属资源组、SQL digest 和 plan digest 分组,统计每一组的 SQL 信息。 +`statements_summary` 是 `information_schema` 中的系统表。`statements_summary` 按资源组、SQL 指纹和执行计划指纹对 SQL 语句进行分组,并为每个 SQL 类别提供统计信息。 -此处的 SQL digest 与 slow log 里的 SQL digest 一样,是把 SQL 规一化后算出的唯一标识符。SQL 的规一化会忽略常量、空白符、大小写的差别。即语法一致的 SQL 语句,其 digest 也相同。 +这里的"SQL 指纹"与慢日志中使用的含义相同,是通过规范化 SQL 语句计算得出的唯一标识符。规范化过程会忽略常量、空白字符,并且不区分大小写。因此,具有一致语法的语句具有相同的指纹。例如: -例如: +{{< copyable "sql" >}} ```sql SELECT * FROM employee WHERE id IN (1, 2, 3) AND salary BETWEEN 1000 AND 2000; select * from EMPLOYEE where ID in (4, 5) and SALARY between 3000 and 4000; ``` -归一化后都是: +规范化后,它们都属于以下类别: + +{{< copyable "sql" >}} ```sql select * from employee where id in (...) and salary between ? and ?; ``` -此处的 plan digest 是把执行计划规一化后算出的唯一标识符。执行计划的规一化会忽略常量的差别。由于相同的 SQL 可能产生不同的执行计划,所以可能分到多个组,同一个组内的执行计划是相同的。 +这里的"执行计划指纹"是指通过规范化执行计划计算得出的唯一标识符。规范化过程会忽略常量。相同的 SQL 语句可能会因为执行计划不同而被分到不同的类别中。同一类别的 SQL 语句具有相同的执行计划。 -`statements_summary` 用于保存 SQL 监控指标聚合后的结果。一般来说,每一项监控指标都包含平均值和最大值。例如执行延时对应 `AVG_LATENCY` 和 `MAX_LATENCY` 两个字段,分别是平均延时和最大延时。 +`statements_summary` 存储 SQL 监控指标的聚合结果。通常,每个监控指标都包括最大值和平均值。例如,执行延迟指标对应两个字段:`AVG_LATENCY`(平均延迟)和 `MAX_LATENCY`(最大延迟)。 -为了监控指标的即时性,`statements_summary` 里的数据定期被清空,只展现最近一段时间内的聚合结果。清空周期由系统变量 `tidb_stmt_summary_refresh_interval` 设置。如果刚好在清空之后进行查询,显示的数据可能很少。 +为确保监控指标保持最新,`statements_summary` 表中的数据会定期清除,只保留和显示最近的聚合结果。定期数据清除由 `tidb_stmt_summary_refresh_interval` 系统变量控制。如果您恰好在清除后立即查询,显示的数据可能会很少。 -以下为查询 `statements_summary` 的部分结果: +以下是查询 `statements_summary` 的示例输出: ``` SUMMARY_BEGIN_TIME: 2020-01-02 11:00:00 @@ -78,53 +85,67 @@ select * from employee where id in (...) and salary between ? and ?; > **注意:** > -> - 在 TiDB 中,statement summary tables 中字段的时间单位是纳秒 (ns),而 MySQL 中的时间单位是皮秒 (ps)。 -> - 从 v7.5.1 和 v7.6.0 版本开始,对于开启[资源管控](/tidb-resource-control.md)的集群,`statements_summary` 会分资源组进行聚合,即在不同资源组执行的相同语句会被收集为不同的记录。 - +> - 在 TiDB 中,statement summary 表中字段的时间单位是纳秒(ns),而在 MySQL 中时间单位是皮秒(ps)。 +> - 从 v7.5.1 和 v7.6.0 开始,对于启用了[资源控制](/tidb-resource-control.md)的集群,`statements_summary` 将按资源组进行聚合,例如,在不同资源组中执行的相同语句将被收集为不同的记录。 ## `statements_summary_history` -`statements_summary_history` 的表结构与 `statements_summary` 完全相同,用于保存历史时间段的数据。通过历史数据,可以排查过去出现的异常,也可以对比不同时间的监控指标。 +`statements_summary_history` 的表结构与 `statements_summary` 相同。`statements_summary_history` 保存一定时间范围内的历史数据。通过检查历史数据,您可以排查异常并比较不同时间范围的监控指标。 -字段 `SUMMARY_BEGIN_TIME` 和 `SUMMARY_END_TIME` 代表历史时间段的开始时间和结束时间。 +字段 `SUMMARY_BEGIN_TIME` 和 `SUMMARY_END_TIME` 表示历史时间范围的开始时间和结束时间。 ## `statements_summary_evicted` -[`tidb_stmt_summary_max_stmt_count`](/system-variables.md#tidb_stmt_summary_max_stmt_count-从-v40-版本开始引入) 系统变量用于限制 `statements_summary` 和 `statements_summary_history` 这两张表在内存中可存储的 SQL digest 总数。当超出该限制时,TiDB 会从 `statements_summary` 和 `statements_summary_history` 这两张表中驱逐最久未使用的 SQL digest。 +[`tidb_stmt_summary_max_stmt_count`](/system-variables.md#tidb_stmt_summary_max_stmt_count-new-in-v40) 系统变量限制了 `statements_summary` 和 `statements_summary_history` 表在内存中可以存储的 SQL 指纹总数。一旦超过此限制,TiDB 将从 `statements_summary` 和 `statements_summary_history` 表中淘汰最近最少使用的 SQL 指纹。 + + > **注意:** > -> 当启用 [`tidb_stmt_summary_enable_persistent`](#持久化-statements-summary) 时,`statements_summary_history` 表中的数据会持久化到磁盘。此时,`tidb_stmt_summary_max_stmt_count` 仅限制 `statements_summary` 表在内存中可存储的 SQL digest 数量;当超出 `tidb_stmt_summary_max_stmt_count` 的限制时,TiDB 仅会从 `statements_summary` 表中驱逐最久未使用的 SQL digest。 +> 当启用 [`tidb_stmt_summary_enable_persistent`](#persist-statements-summary) 时,`statements_summary_history` 表中的数据会持久化到磁盘。在这种情况下,`tidb_stmt_summary_max_stmt_count` 仅限制 `statements_summary` 表在内存中可以存储的 SQL 指纹数量,当超过 `tidb_stmt_summary_max_stmt_count` 时,TiDB 仅从 `statements_summary` 表中淘汰最近最少使用的 SQL 指纹。 + + -`statements_summary_evicted` 表记录了发生 SQL digest 驱逐的时间段,以及该时间段内被驱逐的 SQL digest 数量。通过该表,你可以评估当前 `tidb_stmt_summary_max_stmt_count` 的配置是否适合你的工作负载。如果该表中存在记录,说明在某个时间点上 SQL digest 的数量曾超出过 `tidb_stmt_summary_max_stmt_count` 的限制。 +`statements_summary_evicted` 表记录了发生淘汰的时间段以及在该时间段内淘汰的 SQL 指纹数量。此表可帮助您评估 `tidb_stmt_summary_max_stmt_count` 是否针对您的工作负载进行了适当配置。如果此表包含记录,则表明在某个时间点 SQL 指纹数量超过了 `tidb_stmt_summary_max_stmt_count`。 -在 [TiDB Dashboard 的 SQL 语句分析列表页面](/dashboard/dashboard-statement-list.md#others)中,被驱逐的语句信息会显示在 `Others` 行中。 + -## statement summary 的 cluster 表 +在 [TiDB Dashboard 的 SQL 语句页面](/dashboard/dashboard-statement-list.md#others)中,被淘汰语句的信息显示在 `Others` 行中。 -`statements_summary`、`statements_summary_history` 和 `statements_summary_evicted` 仅显示单台 TiDB server 的 statement summary 数据。若要查询整个集群的数据,需要查询 `cluster_statements_summary`、`cluster_statements_summary_history` 或 `cluster_statements_summary_evicted` 表。 + -`cluster_statements_summary` 显示各台 TiDB server 的 `statements_summary` 数据,`cluster_statements_summary_history` 显示各台 TiDB server 的 `statements_summary_history` 数据,而 `cluster_statements_summary_evicted` 则显示各台 TiDB server 的 `statements_summary_evicted` 数据。这三张表用字段 `INSTANCE` 表示 TiDB server 的地址,其他字段与 `statements_summary`、`statements_summary_history` 和 `statements_summary_evicted` 表相同。 + +在[诊断页面的 SQL 语句标签页](/tidb-cloud/tune-performance.md#statement-analysis)中,被淘汰语句的信息显示在 `Others` 行中。 + + + +## statement summary 的集群表 + +`statements_summary`、`statements_summary_history` 和 `statements_summary_evicted` 表仅显示单个 TiDB 服务器的 statement summary。要查询整个集群的数据,您需要查询 `cluster_statements_summary`、`cluster_statements_summary_history` 或 `cluster_statements_summary_evicted` 表。 + +`cluster_statements_summary` 显示每个 TiDB 服务器的 `statements_summary` 数据。`cluster_statements_summary_history` 显示每个 TiDB 服务器的 `statements_summary_history` 数据。`cluster_statements_summary_evicted` 显示每个 TiDB 服务器的 `statements_summary_evicted` 数据。这些表使用 `INSTANCE` 字段表示 TiDB 服务器的地址。其他字段与 `statements_summary`、`statements_summary_history` 和 `statements_summary_evicted` 中的字段相同。 ## 参数配置 以下系统变量用于控制 statement summary: -- `tidb_enable_stmt_summary`:是否打开 statement summary 功能。1 代表打开,0 代表关闭,默认打开。statement summary 关闭后,系统表里的数据会被清空,下次打开后重新统计。经测试,打开后对性能几乎没有影响。 -- `tidb_stmt_summary_refresh_interval`:`statements_summary` 的清空周期,单位是秒 (s),默认值是 `1800`。 -- `tidb_stmt_summary_history_size`:`statements_summary_history` 保存每种 SQL 的历史的数量,也是 `statements_summary_evicted` 的表容量,默认值是 `24`。 -- `tidb_stmt_summary_max_stmt_count`:限制 `statements_summary` 和 `statements_summary_history` 这两张表在内存中可存储的 SQL digest 总数。默认值为 3000 条。 +- `tidb_enable_stmt_summary`:确定是否启用 statement summary 功能。`1` 表示启用,`0` 表示禁用。默认启用此功能。如果禁用此功能,系统表中的统计信息将被清除。下次启用此功能时,统计信息将重新计算。测试表明启用此功能对性能影响很小。 +- `tidb_stmt_summary_refresh_interval`:`statements_summary` 表刷新的时间间隔。时间单位为秒(s)。默认值为 `1800`。 +- `tidb_stmt_summary_history_size`:`statements_summary_history` 表中存储的每个 SQL 语句类别的大小,也是 `statements_summary_evicted` 表中的最大记录数。默认值为 `24`。 +- `tidb_stmt_summary_max_stmt_count`:限制 `statements_summary` 和 `statements_summary_history` 表在内存中可以存储的 SQL 指纹总数。默认值为 `3000`。 - 当超出该限制时,TiDB 会从 `statements_summary` 和 `statements_summary_history` 这两张表中驱逐最久未使用的 SQL digest。这些被驱逐的 SQL digest 的数量将会被记录在 [`statements_summary_evicted`](#statements_summary_evicted) 表中。 + 一旦超过此限制,TiDB 将从 `statements_summary` 和 `statements_summary_history` 表中淘汰最近最少使用的 SQL 指纹。这些被淘汰的指纹随后会在 [`statements_summary_evicted`](#statements_summary_evicted) 表中计数。 > **注意:** > - > - 当 SQL digest 被驱逐时,其相关的所有时间段的 summary 数据都会从 `statements_summary` 和 `statements_summary_history` 这两张表中移除。因此,即使一个时间段的 SQL digest 数量没有超过限制,`statements_summary_history` 表中的 SQL digest 数量也可能小于实际的 SQL digest 数量。如果遇到该情况,并且影响了性能,建议调大 `tidb_stmt_summary_max_stmt_count` 的值。 - > - 当启用 [`tidb_stmt_summary_enable_persistent`](#持久化-statements-summary) 时,`statements_summary_history` 表中的数据会持久化到磁盘。此时,`tidb_stmt_summary_max_stmt_count` 仅限制 `statements_summary` 表在内存中可存储的 SQL digest 数量;当超出 `tidb_stmt_summary_max_stmt_count` 的限制时,TiDB 仅会从 `statements_summary` 表中驱逐最久未使用的 SQL digest。 + > - 当一个 SQL 指纹被淘汰时,其在 `statements_summary` 和 `statements_summary_history` 表中所有时间范围的相关汇总数据都会被移除。因此,即使特定时间范围内的 SQL 指纹数量未超过限制,`statements_summary_history` 表中的 SQL 指纹数量可能少于实际的 SQL 指纹数量。如果出现这种情况并影响性能,建议增加 `tidb_stmt_summary_max_stmt_count` 的值。 + > - 对于 TiDB Self-Managed,当启用 [`tidb_stmt_summary_enable_persistent`](#persist-statements-summary) 时,`statements_summary_history` 表中的数据会持久化到磁盘。在这种情况下,`tidb_stmt_summary_max_stmt_count` 仅限制 `statements_summary` 表在内存中可以存储的 SQL 指纹数量,当超过 `tidb_stmt_summary_max_stmt_count` 时,TiDB 仅从 `statements_summary` 表中淘汰最近最少使用的 SQL 指纹。 + +- `tidb_stmt_summary_max_sql_length`:指定 `DIGEST_TEXT` 和 `QUERY_SAMPLE_TEXT` 的最长显示长度。默认值为 `4096`。 +- `tidb_stmt_summary_internal_query`:确定是否统计 TiDB SQL 语句。`1` 表示统计,`0` 表示不统计。默认值为 `0`。 -- `tidb_stmt_summary_max_sql_length`:字段 `DIGEST_TEXT` 和 `QUERY_SAMPLE_TEXT` 的最大显示长度,默认值是 4096。 -- `tidb_stmt_summary_internal_query`:是否统计 TiDB 的内部 SQL。1 代表统计,0 代表不统计,默认不统计。 +以下是 statement summary 配置的示例: -statement summary 配置示例如下: +{{< copyable "sql" >}} ```sql set global tidb_stmt_summary_max_stmt_count = 3000; @@ -133,23 +154,22 @@ set global tidb_stmt_summary_refresh_interval = 1800; set global tidb_stmt_summary_history_size = 24; ``` -以上配置生效后,`statements_summary` 每 30 分钟清空一次,`statements_summary_history` 最多保存 3000 种 SQL 种类的数据,每种类型的 SQL 保存最近出现过的 24 个时间段的数据。`statements_summary_evicted` 保存最近 24 个发生了 evict 的时间段记录;`statements_summary_evicted` 则以 30 分钟为一个记录周期,表容量为 24 个时间段。 +在上述配置生效后,`statements_summary` 表每 30 分钟清除一次,`statements_summary_history` 表最多存储 3000 种 SQL 语句。对于每种类型,`statements_summary_history` 表存储最近 24 个时间段的数据。`statements_summary_evicted` 表记录最近 24 个发生 SQL 语句淘汰的时间段。`statements_summary_evicted` 表每 30 分钟更新一次。 > **注意:** > -> - 假设某种 SQL 每分钟都出现,那 `statements_summary_history` 中会保存这种 SQL 最近 12 个小时的数据。但如果某种 SQL 只在每天 00:00 ~ 00:30 出现,则 `statements_summary_history` 中会保存这种 SQL 24 个时间段的数据,每个时间段的间隔都是 1 天,所以会有这种 SQL 最近 24 天的数据。 -> - `tidb_stmt_summary_history_size`、`tidb_stmt_summary_max_stmt_count`、`tidb_stmt_summary_max_sql_length` 这些配置都影响内存占用,建议根据实际情况调整(取决于 SQL 大小、SQL 数量、机器配置)不宜设置得过大。内存大小可通过 `tidb_stmt_summary_history_size` \* `tidb_stmt_summary_max_stmt_count` \* `tidb_stmt_summary_max_sql_length` \* `3` 来进行估算。 - -### 为 statement summary 设定合适的大小 +> - 如果一个 SQL 类型每分钟都出现,则 `statements_summary_history` 存储最近 12 小时的数据。如果一个 SQL 类型每天只在 00:00 到 00:30 出现,则 `statements_summary_history` 存储最近 24 个时间段的数据,每个时间段为 1 天。因此,对于这个 SQL 类型,`statements_summary_history` 存储最近 24 天的数据。 +> - `tidb_stmt_summary_history_size`、`tidb_stmt_summary_max_stmt_count` 和 `tidb_stmt_summary_max_sql_length` 配置项会影响内存使用。建议您根据需求、SQL 大小、SQL 数量和机器配置来调整这些配置。不建议设置过大的值。您可以使用 `tidb_stmt_summary_history_size` \* `tidb_stmt_summary_max_stmt_count` \* `tidb_stmt_summary_max_sql_length` \* `3` 来计算内存使用量。 +### 为 statement summary 设置合适的大小 -在系统运行一段时间后(视系统负载而定),可以查看 `statements_summary` 表检查是否发生了 evict,例如: +系统运行一段时间后(取决于系统负载),您可以检查 `statement_summary` 表以查看是否发生了 SQL 淘汰。例如: ```sql select @@global.tidb_stmt_summary_max_stmt_count; select count(*) from information_schema.statements_summary; ``` -``` +```sql +-------------------------------------------+ | @@global.tidb_stmt_summary_max_stmt_count | +-------------------------------------------+ @@ -165,13 +185,13 @@ select count(*) from information_schema.statements_summary; 1 row in set (0.001 sec) ``` -可以发现 `statements_summary` 表已经满了。再查看 `statements_summary_evicted` 表检查 evict 的数据。 +您可以看到 `statements_summary` 表已经充满记录。然后从 `statements_summary_evicted` 表中检查被淘汰的数据: ```sql select * from information_schema.statements_summary_evicted; ``` -``` +```sql +---------------------+---------------------+---------------+ | BEGIN_TIME | END_TIME | EVICTED_COUNT | +---------------------+---------------------+---------------+ @@ -182,195 +202,4 @@ select * from information_schema.statements_summary_evicted; 2 row in set (0.001 sec) ``` -由上可知,对最多 59 种 SQL 发生了 evict。此时,建议将 `statements_summary` 表的容量至少增大 59 条记录,即至少增大至 3059 条。 - -## 目前的限制 - -由于 statement summary tables 默认都存储在内存中,TiDB server 重启后,statement summary 会全部丢失。 - -为解决该问题,TiDB v6.6.0 实验性地引入了 [statement summary 持久化](#持久化-statements-summary)功能,该功能默认为关闭。开启该功能后,历史数据不再存储在内存内,而是直接写入磁盘。TiDB server 重启后,历史数据也依然可用。 - -## 持久化 statements summary - -> **警告:** -> -> statements summary 持久化目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 - -如[目前的限制](#目前的限制)一节所描述,默认情况下 statements summary 只在内存中维护,一旦 TiDB server 发生重启,所有 statements summary 数据都会丢失。自 v6.6.0 起,TiDB 实验性地提供了配置项 [`tidb_stmt_summary_enable_persistent`](/tidb-configuration-file.md#tidb_stmt_summary_enable_persistent-从-v660-版本开始引入) 来允许用户控制是否开启 statements summary 持久化。 - -如果要开启 statements summary 持久化,可以在 TiDB 配置文件中添加如下配置: - -```toml -[instance] -tidb_stmt_summary_enable_persistent = true -# 以下配置为默认值,可根据需求调整。 -# tidb_stmt_summary_filename = "tidb-statements.log" -# tidb_stmt_summary_file_max_days = 3 -# tidb_stmt_summary_file_max_size = 64 # MiB -# tidb_stmt_summary_file_max_backups = 0 -``` - -开启 statements summary 持久化后,内存中只维护当前的实时数据,不再维护历史数据。历史数据生成后直接被写入磁盘文件,写入周期参考[参数配置](#参数配置)一节所描述的 `tidb_stmt_summary_refresh_interval`。后续针对 `statements_summary_history` 或 `cluster_statements_summary_history` 表的查询将结合内存和磁盘两处数据返回结果。 - -> **注意:** -> -> - 当开启持久化后,由于不再于内存中维护历史数据,因此[参数配置](#参数配置)一节所描述的 `tidb_stmt_summary_history_size` 将不再生效,而是由 [`tidb_stmt_summary_file_max_days`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_days-从-v660-版本开始引入)、[`tidb_stmt_summary_file_max_size`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_size-从-v660-版本开始引入) 和 [`tidb_stmt_summary_file_max_backups`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_backups-从-v660-版本开始引入) 这三项配置来决定历史数据在磁盘上的保留数量和时间。 -> - `tidb_stmt_summary_refresh_interval` 取值越小,数据写入到磁盘就越实时,但写入磁盘的冗余数据也会随之增多。 - -## 排查示例 - -下面用两个示例问题演示如何利用 statement summary 来排查。 - -### SQL 延迟比较大,是不是服务端的问题? - -例如客户端显示 employee 表的点查比较慢,那么可以按 SQL 文本来模糊查询: - -```sql -SELECT avg_latency, exec_count, query_sample_text - FROM information_schema.statements_summary - WHERE digest_text LIKE 'select * from employee%'; -``` - -结果如下,`avg_latency` 是 1 ms 和 0.3 ms,在正常范围,所以可以判定不是服务端的问题,继而排查客户端或网络问题。 - -``` -+-------------+------------+------------------------------------------+ -| avg_latency | exec_count | query_sample_text | -+-------------+------------+------------------------------------------+ -| 1042040 | 2 | select * from employee where name='eric' | -| 345053 | 3 | select * from employee where id=3100 | -+-------------+------------+------------------------------------------+ -2 rows in set (0.00 sec) -``` - -### 哪类 SQL 的总耗时最高? - -假如上午 10:00 到 10:30 的 QPS 明显下降,可以从历史表中找出当时耗时最高的三类 SQL: - -```sql -SELECT sum_latency, avg_latency, exec_count, query_sample_text - FROM information_schema.statements_summary_history - WHERE summary_begin_time='2020-01-02 10:00:00' - ORDER BY sum_latency DESC LIMIT 3; -``` - -结果显示以下三类 SQL 的总延迟最高,所以这些 SQL 需要重点优化。 - -``` -+-------------+-------------+------------+-----------------------------------------------------------------------+ -| sum_latency | avg_latency | exec_count | query_sample_text | -+-------------+-------------+------------+-----------------------------------------------------------------------+ -| 7855660 | 1122237 | 7 | select avg(salary) from employee where company_id=2013 | -| 7241960 | 1448392 | 5 | select * from employee join company on employee.company_id=company.id | -| 2084081 | 1042040 | 2 | select * from employee where name='eric' | -+-------------+-------------+------------+-----------------------------------------------------------------------+ -3 rows in set (0.00 sec) -``` - -## 表的字段介绍 - -### `statements_summary` 字段介绍 - -下面介绍 `statements_summary` 表中各个字段的含义。 - -SQL 的基础信息: - -- `STMT_TYPE`:SQL 语句的类型 -- `SCHEMA_NAME`:执行这类 SQL 的当前 schema -- `DIGEST`:这类 SQL 的 digest -- `DIGEST_TEXT`:规一化后的 SQL -- `QUERY_SAMPLE_TEXT`:这类 SQL 的原 SQL 语句,多条语句只取其中一条 -- `TABLE_NAMES`:SQL 中涉及的所有表,多张表用 `,` 分隔 -- `INDEX_NAMES`:SQL 中使用的索引名,多个索引用 `,` 分隔 -- `SAMPLE_USER`:执行这类 SQL 的用户名,多个用户名只取其中一个 -- `PLAN_DIGEST`:执行计划的 digest -- `PLAN`:原执行计划,多条语句只取其中一条的执行计划 -- `BINARY_PLAN`:以二进制格式编码后的原执行计划,存在多条语句时,只取其中一条语句的执行计划。用 [`SELECT tidb_decode_binary_plan('xxx...')`](/functions-and-operators/tidb-functions.md#tidb_decode_binary_plan) SQL 语句可以解析出具体的执行计划。 -- `PLAN_CACHE_HITS`:这类 SQL 语句命中 plan cache 的总次数 -- `PLAN_IN_CACHE`:这类 SQL 语句的上次执行是否命中了 plan cache - -执行时间相关的信息: - -- `SUMMARY_BEGIN_TIME`:当前统计的时间段的开始时间 -- `SUMMARY_END_TIME`:当前统计的时间段的结束时间 -- `FIRST_SEEN`:这类 SQL 的首次出现时间 -- `LAST_SEEN`:这类 SQL 的最后一次出现时间 - -在 TiDB server 上的执行数据: - -- `EXEC_COUNT`:这类 SQL 的总执行次数 -- `SUM_ERRORS`:执行过程中遇到的 error 的总数 -- `SUM_WARNINGS`:执行过程中遇到的 warning 的总数 -- `SUM_LATENCY`:这类 SQL 的总延时 -- `MAX_LATENCY`:这类 SQL 的最大延时 -- `MIN_LATENCY`:这类 SQL 的最小延时 -- `AVG_LATENCY`:这类 SQL 的平均延时 -- `AVG_PARSE_LATENCY`:解析器的平均延时 -- `MAX_PARSE_LATENCY`:解析器的最大延时 -- `AVG_COMPILE_LATENCY`:优化器的平均延时 -- `MAX_COMPILE_LATENCY`:优化器的最大延时 -- `AVG_MEM`:使用的平均内存,单位 byte -- `MAX_MEM`:使用的最大内存,单位 byte -- `AVG_DISK`:使用的平均硬盘空间,单位 byte -- `MAX_DISK`:使用的最大硬盘空间,单位 byte - -和 TiKV Coprocessor Task 相关的字段: - -- `SUM_COP_TASK_NUM`:发送 Coprocessor 请求的总数 -- `MAX_COP_PROCESS_TIME`:cop-task 的最大处理时间 -- `MAX_COP_PROCESS_ADDRESS`:执行时间最长的 cop-task 所在地址 -- `MAX_COP_WAIT_TIME`:cop-task 的最大等待时间 -- `MAX_COP_WAIT_ADDRESS`:等待时间最长的 cop-task 所在地址 -- `AVG_PROCESS_TIME`:SQL 在 TiKV 的平均处理时间 -- `MAX_PROCESS_TIME`:SQL 在 TiKV 的最大处理时间 -- `AVG_WAIT_TIME`:SQL 在 TiKV 的平均等待时间 -- `MAX_WAIT_TIME`:SQL 在 TiKV 的最大等待时间 -- `AVG_BACKOFF_TIME`:SQL 遇到需要重试的错误时在重试前的平均等待时间 -- `MAX_BACKOFF_TIME`:SQL 遇到需要重试的错误时在重试前的最大等待时间 -- `AVG_TOTAL_KEYS`:Coprocessor 扫过的 key 的平均数量 -- `MAX_TOTAL_KEYS`:Coprocessor 扫过的 key 的最大数量 -- `AVG_PROCESSED_KEYS`:Coprocessor 处理的 key 的平均数量。相比 `avg_total_keys`,`avg_processed_keys` 不包含 MVCC 的旧版本。如果 `avg_total_keys` 和 `avg_processed_keys` 相差很大,说明旧版本比较多 -- `MAX_PROCESSED_KEYS`:Coprocessor 处理的 key 的最大数量 - -和事务相关的字段: - -- `AVG_PREWRITE_TIME`:prewrite 阶段消耗的平均时间 -- `MAX_PREWRITE_TIME` prewrite 阶段消耗的最大时间 -- `AVG_COMMIT_TIME`:commit 阶段消耗的平均时间 -- `MAX_COMMIT_TIME`:commit 阶段消耗的最大时间 -- `AVG_GET_COMMIT_TS_TIME`:获取 commit_ts 的平均时间 -- `MAX_GET_COMMIT_TS_TIME`:获取 commit_ts 的最大时间 -- `AVG_COMMIT_BACKOFF_TIME`:commit 时遇到需要重试的错误时在重试前的平均等待时间 -- `MAX_COMMIT_BACKOFF_TIME`:commit 时遇到需要重试的错误时在重试前的最大等待时间 -- `AVG_RESOLVE_LOCK_TIME`:解决事务的锁冲突的平均时间 -- `MAX_RESOLVE_LOCK_TIME`:解决事务的锁冲突的最大时间 -- `AVG_LOCAL_LATCH_WAIT_TIME`:本地事务等待的平均时间 -- `MAX_LOCAL_LATCH_WAIT_TIME`:本地事务等待的最大时间 -- `AVG_WRITE_KEYS`:写入 key 的平均数量 -- `MAX_WRITE_KEYS`:写入 key 的最大数量 -- `AVG_WRITE_SIZE`:写入的平均数据量,单位 byte -- `MAX_WRITE_SIZE`:写入的最大数据量,单位 byte -- `AVG_PREWRITE_REGIONS`:prewrite 涉及的平均 Region 数量 -- `MAX_PREWRITE_REGIONS`:prewrite 涉及的最大 Region 数量 -- `AVG_TXN_RETRY`:事务平均重试次数 -- `MAX_TXN_RETRY`:事务最大重试次数 -- `SUM_BACKOFF_TIMES`:这类 SQL 遇到需要重试的错误后的总重试次数 -- `BACKOFF_TYPES`:遇到需要重试的错误时的所有错误类型及每种类型重试的次数,格式为 `类型:次数`。如有多种错误则用 `,` 分隔,例如 `txnLock:2,pdRPC:1` -- `AVG_AFFECTED_ROWS`:平均影响行数 -- `PREV_SAMPLE_TEXT`:当 SQL 是 `COMMIT` 时,该字段为 `COMMIT` 的前一条语句;否则该字段为空字符串。当 SQL 是 `COMMIT` 时,按 digest 和 `prev_sample_text` 一起分组,即不同 `prev_sample_text` 的 `COMMIT` 也会分到不同的行 - -和资源管控相关的字段: - -- `AVG_REQUEST_UNIT_WRITE`:执行 SQL 语句平均消耗的写 RU -- `MAX_REQUEST_UNIT_WRITE`:执行 SQL 语句最大消耗的写 RU -- `AVG_REQUEST_UNIT_READ`:执行 SQL 语句平均消耗的读 RU -- `MAX_REQUEST_UNIT_READ`:执行 SQL 语句最大消耗的读 RU -- `AVG_QUEUED_RC_TIME`:执行 SQL 语句等待可用 RU 的平均耗时 -- `MAX_QUEUED_RC_TIME`:执行 SQL 语句等待可用 RU 的最大耗时 -- `RESOURCE_GROUP`:执行 SQL 语句绑定的资源组 - -### `statements_summary_evicted` 字段介绍 - -- `BEGIN_TIME`: 记录的开始时间; -- `END_TIME`: 记录的结束时间; -- `EVICTED_COUNT`:在记录的时间段内 evict 了多少种 SQL。 +从上述结果可以看出,最多有 59 个 SQL 类别被淘汰。在这种情况下,建议您至少增加 59 条记录的 `statement_summary` 表大小,这意味着将大小增加到至少 3059 条记录。 diff --git a/statistics.md b/statistics.md index 15e064ff3c6f..afd8b83927f1 100644 --- a/statistics.md +++ b/statistics.md @@ -1,726 +1,47 @@ --- -title: 常规统计信息 -summary: 介绍 TiDB 中常规统计信息的收集和使用。 +title: 统计信息简介 +summary: 了解统计信息如何收集表级和列级信息。 --- -# 常规统计信息 +# 统计信息简介 -TiDB 使用统计信息作为优化器的输入,用于估算 SQL 语句的执行计划中每个步骤处理的行数。优化器会估算每个可用执行计划的成本,包括[索引的选择](/choose-index.md)和表连接的顺序,并为每个可用执行计划生成成本。然后,优化器会选择总体成本最低的执行计划。 +TiDB 使用统计信息作为优化器的输入,以估计 SQL 语句中每个计划步骤处理的行数。优化器估计每个可用计划选择的成本,包括[索引访问](/choose-index.md)和表连接的顺序,并为每个可用计划生成成本。然后,优化器选择总体成本最低的执行计划。 ## 收集统计信息 -本小节介绍收集统计信息的两种方式:自动更新和手动收集。 +本节描述收集统计信息的两种方式:自动更新和手动收集。 ### 自动更新 -对于 [`INSERT`](/sql-statements/sql-statement-insert.md)、[`DELETE`](/sql-statements/sql-statement-delete.md) 或 [`UPDATE`](/sql-statements/sql-statement-update.md) 语句,TiDB 会自动更新统计信息中表的总行数和修改的行数。 +对于 [`INSERT`](/sql-statements/sql-statement-insert.md)、[`DELETE`](/sql-statements/sql-statement-delete.md) 或 [`UPDATE`](/sql-statements/sql-statement-update.md) 语句,TiDB 会自动更新统计信息中的行数和修改行数。 -TiDB 会定期持久化更新的统计信息,更新周期为 20 * [`stats-lease`](/tidb-configuration-file.md#stats-lease)。`stats-lease` 配置项的默认值为 `3s`,如果将其指定为 `0`,TiDB 将停止自动更新统计信息。 + -TiDB 根据表的变更次数自动调度 [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) 来收集这些表的统计信息。统计信息的自动更新由 [`tidb_enable_auto_analyze`](/system-variables.md#tidb_enable_auto_analyze-从-v610-版本开始引入) 系统变量和以下 `tidb_auto_analyze%` 变量控制。 +TiDB 定期持久化更新信息,更新周期为 20 * [`stats-lease`](/tidb-configuration-file.md#stats-lease)。`stats-lease` 的默认值为 `3s`。如果将该值指定为 `0`,TiDB 将停止自动更新统计信息。 -| 系统变量名 | 默认值 | 功能描述 | -| --------- | ----- | --------- | -| [`tidb_enable_auto_analyze`](/system-variables.md#tidb_enable_auto_analyze-从-v610-版本开始引入) | `ON` | 是否启用自动更新表的统计信息 | -| [`tidb_auto_analyze_ratio`](/system-variables.md#tidb_auto_analyze_ratio) | `0.5` | 自动更新阈值 | -| [`tidb_auto_analyze_start_time`](/system-variables.md#tidb_auto_analyze_start_time) | `00:00 +0000` | 一天中能够进行自动更新的开始时间 | -| [`tidb_auto_analyze_end_time`](/system-variables.md#tidb_auto_analyze_end_time) | `23:59 +0000` | 一天中能够进行自动更新的结束时间 | -| [`tidb_auto_analyze_partition_batch_size`](/system-variables.md#tidb_auto_analyze_partition_batch_size-从-v640-版本开始引入) | `128` | TiDB 自动 analyze 分区表(即自动更新分区表的统计信息)时,每次同时 analyze 分区的个数 | -| [`tidb_enable_auto_analyze_priority_queue`](/system-variables.md#tidb_enable_auto_analyze_priority_queue-从-v800-版本开始引入) | `ON` | 是否启用优先队列来调度自动收集统计信息的任务。开启该变量后,TiDB 会优先收集那些更有收集价值的表,例如新创建的索引、发生分区变更的分区表等。同时,TiDB 也会优先处理那些健康度较低的表,将它们安排在队列的前端。 | + -当某个表 `tbl` 的修改行数与总行数的比值大于 `tidb_auto_analyze_ratio`,并且当前时间在 `tidb_auto_analyze_start_time` 和 `tidb_auto_analyze_end_time` 之间时,TiDB 会在后台执行 `ANALYZE TABLE tbl` 语句自动更新这个表的统计信息。 + -为了避免小表因为少量数据修改而频繁触发自动更新,当表的行数小于 1000 时,TiDB 不会触发对此表的自动更新。你可以通过 `SHOW STATS_META` 语句来查看表的行数。 +TiDB 每 60 秒持久化一次更新信息。 -> **注意:** -> -> 目前,自动更新不会记录手动 `ANALYZE` 时输入的配置项。因此,当你使用 [`WITH`](/sql-statements/sql-statement-analyze-table.md) 语法控制 `ANALYZE` 的收集行为时,需要手动设置定时任务来收集统计信息。 - -### 手动收集 - -目前 TiDB 收集统计信息为全量收集。你可以通过 `ANALYZE TABLE` 语句的以下语法来全量收集统计信息: - -- 收集 `TableNameList` 中所有表的统计信息: - - ```sql - ANALYZE TABLE TableNameList [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; - ``` - -- `WITH NUM BUCKETS` 用于指定生成直方图的桶数量上限。 -- `WITH NUM TOPN` 用于指定生成的 `TOPN` 数量的上限。 -- `WITH NUM CMSKETCH DEPTH` 用于指定 CM Sketch 的长。 -- `WITH NUM CMSKETCH WIDTH` 用于指定 CM Sketch 的宽。 -- `WITH NUM SAMPLES` 用于指定采样的数目。 -- `WITH FLOAT_NUM SAMPLERATE` 用于指定采样率。 - -`WITH NUM SAMPLES` 与 `WITH FLOAT_NUM SAMPLERATE` 这两种设置对应了两种不同的收集采样的算法。 - -相关详细解释参见[直方图](#直方图)、[Top-N 值](#top-n) and [CMSketch](#count-min-sketch) (Count-Min Sketch)。关于 `SAMPLES` 和 `SAMPLERATE`,参见[提升统计信息收集性能](#提升统计信息收集性能)。 - -关于持久化 `ANALYZE` 配置以便后续沿用的更多信息,参见[持久化 `ANALYZE` 配置](#持久化-analyze-配置)。 - -## 统计信息的类型 - -本小节介绍统计信息的三种类型:直方图、Count-Min Sketch 和 Top-N。 - -### 直方图 - -直方图统计信息被优化器用于估算区间或范围谓词的选择,并可能用于确定列中不同值的数量,以估算 Version 2 统计信息(参见[统计信息版本](#统计信息版本))中的等值查询或 `IN` 查询的谓词。 - -直方图是对数据分布的近似表示。它将整个数值范围划分为一系列桶,并使用简单的数据来描述每个桶,例如落入该桶的数值数量。在 TiDB 中,会为每个表的具体列创建等深直方图,可用于估算区间查询。 - -等深直方图,就是让落入每个桶里的数值数量尽量相等。例如,对于给定的集合 {1.6, 1.9, 1.9, 2.0, 2.4, 2.6, 2.7, 2.7, 2.8, 2.9, 3.4, 3.5} 生成 4 个桶,那么最终的等深直方图就会如下图所示,包含四个桶 [1.6, 1.9],[2.0, 2.6],[2.7, 2.8],[2.9, 3.5],其桶深均为 3。 - -![等深直方图示例](/media/statistics-1.png) - -你可以通过 `WITH NUM BUCKETS` 参数控制直方图的桶数量上限,参见[手动收集](#手动收集)小节。桶数量越多,直方图的估算精度就越高,不过也会同时增加统计信息的内存使用。可以视具体情况来调整桶的数量上限。 - -### Count-Min Sketch - -> **注意:** -> -> Count-Min Sketch 在统计信息 Version 1 仅用于等值查询或 `IN` 查询的谓词估算。在 Version 2 中,为了避免 Count-Min Sketch 可能带来的哈希冲突,TiDB 不再使用 Count-Min Sketch 统计信息,而是使用直方图估算等值查询或 `IN` 查询的谓词。 - -Count-Min Sketch 是一种哈希结构,当处理等值查询(如 `a = 1`)或者 `IN` 查询(如 `a in (1, 2, 3)`)时,TiDB 便会使用这种数据结构来进行估算。 - -由于 Count-Min Sketch 是一个哈希结构,就有出现哈希冲突的可能。当在 `EXPLAIN` 语句中发现等值查询的估算偏离实际值较大时,就可以认为是一个比较大的值和一个比较小的值被哈希到了一起。这时有以下两种方法来避免哈希冲突: - -- 修改 `WITH NUM TOPN` 参数。TiDB 会将出现频率前 x 的数据单独储存,之后的数据再储存到 Count-Min Sketch 中。因此,为了避免一个比较大的值和一个比较小的值被哈希到一起,可以调大 `WITH NUM TOPN` 的值。该参数的默认值是 `20`,最大值是 `1024`。关于该参数的更多信息,参见[手动收集](#手动收集)小节。 -- 修改 `WITH NUM CMSKETCH DEPTH` 和 `WITH NUM CMSKETCH WIDTH` 两个参数。这两个参数会影响哈希的桶数和冲突概率,可视具体情况适当调大这两个参数的值来减少冲突概率,不过调大后也会增加统计信息的内存使用。`WITH NUM CMSKETCH DEPTH` 的默认值是 `5`,`WITH NUM CMSKETCH WIDTH` 的默认值是 `2048`。关于这两个参数的更多信息,参见[手动收集](#手动收集)小节。 - -### Top-N - -Top-N 值是列或索引中出现次数前 N 的值。Top-N 统计信息通常被称为频率统计信息或数据倾斜。 - -TiDB 会记录 Top-N 的值和出现次数。参数 `WITH NUM TOPN` 控制 Top-N 值的数量,默认值是 `20`,表示收集出现频率最高的前 20 个值;最大值是 `1024`。关于该参数的详细信息,参见[手动收集](#手动收集)小节。 - -## 选择性收集统计信息 - -本小节介绍如何选择性地收集统计信息。 - -### 收集索引的统计信息 + -如果要收集 `TableName` 中 `IndexNameList` 里所有索引的统计信息,请使用以下语法: +根据表的变更数量,TiDB 会自动调度 [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) 来收集这些表的统计信息。这由系统变量 [`tidb_enable_auto_analyze`](/system-variables.md#tidb_enable_auto_analyze-new-in-v610) 和以下 `tidb_auto_analyze%` 变量控制。 -```sql -ANALYZE TABLE TableName INDEX [IndexNameList] [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; -``` +| 系统变量 | 默认值 | 描述 | +|---|---|---| +| [`tidb_enable_auto_analyze`](/system-variables.md#tidb_enable_auto_analyze-new-in-v610) | `ON` | 控制 TiDB 是否自动执行 `ANALYZE`。 | +| [`tidb_auto_analyze_ratio`](/system-variables.md#tidb_auto_analyze_ratio) | `0.5` | 自动更新的阈值。 | +| [`tidb_auto_analyze_start_time`](/system-variables.md#tidb_auto_analyze_start_time) | `00:00 +0000` | TiDB 一天中可以执行自动更新的开始时间。 | +| [`tidb_auto_analyze_end_time`](/system-variables.md#tidb_auto_analyze_end_time) | `23:59 +0000` | TiDB 一天中可以执行自动更新的结束时间。 | +| [`tidb_auto_analyze_partition_batch_size`](/system-variables.md#tidb_auto_analyze_partition_batch_size-new-in-v640) | `128` | TiDB 在分析分区表时自动分析的分区数量(即在自动更新分区表的统计信息时)。 | +| [`tidb_enable_auto_analyze_priority_queue`](/system-variables.md#tidb_enable_auto_analyze_priority_queue-new-in-v800) | `ON` | 控制是否启用优先级队列来调度自动收集统计信息的任务。启用此变量后,TiDB 会优先收集更有价值的表的统计信息,例如新创建的索引和分区变更的分区表。此外,TiDB 会优先处理健康分数较低的表,将它们放在队列前面。 | -当 `IndexNameList` 为空时,该语法将收集 `TableName` 中所有索引的统计信息。 +当表 `tbl` 中修改的行数与总行数的比率大于 `tidb_auto_analyze_ratio`,并且当前时间在 `tidb_auto_analyze_start_time` 和 `tidb_auto_analyze_end_time` 之间时,TiDB 会在后台执行 `ANALYZE TABLE tbl` 语句,自动更新这个表的统计信息。 -> **注意:** -> -> 为了保证收集前与收集后统计信息的一致性,当设置 `tidb_analyze_version = 2` 时,该语法也会收集整个表的统计信息(包括所有列和所有索引的统计信息),而不限于索引的统计信息。 - -### 收集部分列的统计信息 - -执行 SQL 语句时,优化器在大多数情况下只会用到部分列的统计信息。例如,`WHERE`、`JOIN`、`ORDER BY`、`GROUP BY` 子句中出现的列,这些被用到的列称为 `PREDICATE COLUMNS`。 - -如果一个表有很多列,收集所有列的统计信息会产生较大的开销。为了降低开销,你可以只收集选定列或者 `PREDICATE COLUMNS` 的统计信息供优化器使用。如果要持久化列配置以便将来沿用,参见[持久化列配置](#持久化列配置)。 +为了避免频繁修改小表数据触发自动更新的情况,当表的行数少于 1000 行时,修改不会触发 TiDB 的自动更新。您可以使用 `SHOW STATS_META` 语句查看表中的行数。 > **注意:** > -> - 收集 `PREDICATE COLUMNS` 的统计信息的功能仅适用于 [`tidb_analyze_version = 2`](/system-variables.md#tidb_analyze_version-从-v510-版本开始引入) 的情况。 -> - TiDB v7.2.0 引入了系统变量 [`tidb_analyze_skip_column_types`](/system-variables.md#tidb_analyze_skip_column_types-从-v720-版本开始引入),该变量可以控制在执行 `ANALYZE` 命令收集统计信息时,跳过哪些类型的列的统计信息收集。该变量仅适用于 `tidb_analyze_version = 2` 的情况。 - -- 如果要收集指定列的统计信息,请使用以下语法: - - ```sql - ANALYZE TABLE TableName COLUMNS ColumnNameList [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; - ``` - - 其中,`ColumnNameList` 表示指定列的名称列表。如果需要指定多列,请使用用逗号 `,` 分隔列名。例如, `ANALYZE table t columns a, b`。该语法除了收集指定表中指定列的统计信息,将同时收集该表中索引列的统计信息以及所有索引的统计信息。 - -- 如果要收集 `PREDICATE COLUMNS` 的统计信息,请进行以下操作: - - > **警告:** - > - > 收集 `PREDICATE COLUMNS` 的统计信息目前为实验特性,不建议在生产环境中使用。 - - 1. 将系统变量 [`tidb_enable_column_tracking`](/system-variables.md#tidb_enable_column_tracking-从-v540-版本开始引入) 的值设置为 `ON`,以开启 TiDB 对 `PREDICATE COLUMNS` 的收集。 - - 开启后,TiDB 将每隔 100 * [`stats-lease`](/tidb-configuration-file.md#stats-lease) 时间将 `PREDICATE COLUMNS` 信息写入系统表 [`mysql.column_stats_usage`](/mysql-schema/mysql-schema.md#统计信息相关系统表)。 - - 2. 在业务的查询模式稳定以后,使用以下语法收集 `PREDICATE COLUMNS` 的统计信息。 - - ```sql - ANALYZE TABLE TableName PREDICATE COLUMNS [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; - ``` - - 该语法除了收集指定表中 `PREDICATE COLUMNS` 的统计信息,将同时收集该表中索引列的统计信息以及所有索引的统计信息。 - - > **注意:** - > - > - 如果系统表 [`mysql.column_stats_usage`](/mysql-schema/mysql-schema.md#统计信息相关系统表) 中没有关于该表的 `PREDICATE COLUMNS` 记录,执行以上语句会收集该表中所有列的统计信息以及所有索引的统计信息。 - > - 对于任何被排除在此次统计信息收集(无论是手动列出列名,还是使用 `PREDICATE COLUMNS`)之外的列,它们的统计信息不会被覆盖。当执行新类型的 SQL 查询时,如果存在旧的统计信息,优化器将使用这些列的旧统计信息;如果从未收集过列的统计信息,则使用伪列统计信息。下一次使用 `PREDICATE COLUMNS` 的 `ANALYZE` 将收集这些列的统计信息。 - -- 如果要收集所有列的统计信息以及所有索引的统计信息,请使用以下语法: - - ```sql - ANALYZE TABLE TableName ALL COLUMNS [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; - ``` - -### 收集分区的统计信息 - -- 如果要收集 `TableName` 中 `PartitionNameList` 里所有分区的统计信息,请使用以下语法: - - ```sql - ANALYZE TABLE TableName PARTITION PartitionNameList [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; - ``` - -- 如果要收集 `TableName` 中 `PartitionNameList` 里所有分区的索引统计信息,请使用以下语法: - - ```sql - ANALYZE TABLE TableName PARTITION PartitionNameList INDEX [IndexNameList] [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; - ``` - -- 当收集分区的统计信息时,如果只需要[收集部分列的统计信息](/statistics.md#收集部分列的统计信息),请使用以下语法: - - > **警告:** - > - > 收集 `PREDICATE COLUMNS` 的统计信息目前为实验特性,不建议在生产环境中使用。 - - ```sql - ANALYZE TABLE TableName PARTITION PartitionNameList [COLUMNS ColumnNameList|PREDICATE COLUMNS|ALL COLUMNS] [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE]; - ``` - -#### 收集动态裁剪模式下的分区表统计信息 - -在分区表开启[动态裁剪模式](/partitioned-table.md#动态裁剪模式)(从 v6.3.0 开始,默认开启)的情况下,TiDB 将收集表级别的汇总统计信息,以下称 GlobalStats。目前 GlobalStats 由分区统计信息合并汇总得到。在动态裁剪模式下,任何分区表的统计信息更新都可能触发 GlobalStats 更新。 - -如果分区为空,或者某些分区上的列缺失,那么统计信息收集行为将受 [`tidb_skip_missing_partition_stats`](/system-variables.md#tidb_skip_missing_partition_stats-从-v730-版本开始引入) 变量的控制: - -- 当触发 GlobalStats 更新且 [`tidb_skip_missing_partition_stats`](/system-variables.md#tidb_skip_missing_partition_stats-从-v730-版本开始引入) 为 `OFF` 时: - - - 如果某些分区缺失统计信息(例如从未进行过 analyze 的新分区),GlobalStats 生成会中断,并显示 warning 信息提示这些分区没有可用的统计信息。 - - 如果某些分区中缺失某些列的统计信息(这些分区中指定了不同的列进行 analyze),当这些列的统计信息被合并汇总时,GlobalStats 生成会中断,并显示 warning 信息提示某些分区中缺少某些列的统计信息。 - -- 当触发 GlobalStats 更新且 [`tidb_skip_missing_partition_stats`](/system-variables.md#tidb_skip_missing_partition_stats-从-v730-版本开始引入) 为 `ON` 时: - - - 如果某些分区缺失全部列或部分列的统计信息,TiDB 在生成 GlobalStats 时会跳过这些缺失的分区统计信息,不影响 GlobalStats 生成。 - -在动态裁剪模式下,分区和分区表的 `ANALYZE` 配置应保持一致。因此,如果在 `ANALYZE TABLE TableName PARTITION PartitionNameList` 语句后指定了 `COLUMNS` 配置或在 `WITH` 后指定了 `OPTIONS` 配置,TiDB 将忽略这些配置并返回 warning 信息提示。 - -## 提升统计信息收集性能 - -> **注意:** -> -> 在 TiDB 中执行 `ANALYZE TABLE` 语句可能比在 MySQL 或 InnoDB 中耗时更长。InnoDB 采样的只是少量页面,而 TiDB 默认会完全重构一套全面的统计信息。 - -TiDB 提供了两种方法来提升统计信息收集的性能: - -- 收集列的子集的统计信息。参见[收集部分列的统计信息](#收集部分列的统计信息)。 -- 采样。参见[统计信息采样](#统计信息采样)。 - -### 统计信息采样 - -采样是通过 `ANALYZE` 语句的两个选项来实现的,每个选项对应一种不同的收集算法: - -- `WITH NUM SAMPLES` 指定了采样集的大小,在 TiDB 中是以蓄水池采样的方式实现。当表较大时,不推荐使用这种方式收集统计信息。因为蓄水池采样中间结果集会产生一定的冗余结果,会对内存等资源造成额外的压力。 -- `WITH FLOAT_NUM SAMPLERATE` 是从 v5.3.0 开始引入的采样方式,指定了采样率的大小,取值范围是 `(0, 1]`。在 TiDB 中是以伯努利采样的方式实现,更适合对较大的表进行采样,在收集效率和资源使用上更有优势。 - -在 v5.3.0 之前,TiDB 采用蓄水池采样的方式收集统计信息。自 v5.3.0 版本起,TiDB Version 2 的统计信息默认会选取伯努利采样的方式收集统计信息。若要重新使用蓄水池采样的方式采样,可以使用 `WITH NUM SAMPLES` 语句。 - -目前采样率基于自适应算法进行计算。当你通过 [`SHOW STATS_META`](/sql-statements/sql-statement-show-stats-meta.md) 可以观察到一个表的行数时,可通过这个行数去计算采集 10 万行所对应的采样率。如果你观察不到这个值,可通过表 [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) 结果中所有 `APPROXIMATE_KEYS` 列值的总和作为另一个参考来计算采样率。 - -> **注意:** -> -> 通常情况下,`STATS_META` 比 `APPROXIMATE_KEYS` 更可信。但是,当 `STATS_META` 的结果远小于 `APPROXIMATE_KEYS` 的结果时,推荐使用 `APPROXIMATE_KEYS` 计算采样率。 - -### 统计信息收集的内存限制 - -> **警告:** -> -> 目前限制 `ANALYZE` 的内存使用量为实验特性,在生产环境中使用时可能存在内存统计有误差的情况。 - -TiDB 从 v6.1.0 开始引入了统计信息收集的内存限制,你可以通过 [`tidb_mem_quota_analyze`](/system-variables.md#tidb_mem_quota_analyze-从-v610-版本开始引入) 变量来控制 TiDB 更新统计信息时的最大总内存占用。 - -要合理地配置 `tidb_mem_quota_analyze` 的值,你需要考虑集群的数据规模。在使用默认采样率的情况下,主要考虑列的数量、列值的大小,以及 TiDB 的内存配置。你可参考以下建议来配置该变量的最大值和最小值: - -> **注意:** -> -> 以下配置建议仅供参考,实际配置需要在真实场景中测试确定。 - -- 最小值:需要大于 TiDB 从集群上列最多的表收集统计信息时使用的最大内存。一个粗略的参考信息是,在测试集上,20 列的表在默认配置下,统计信息收集的最大内存使用量约为 800 MiB;160 列的表在默认配置下,统计信息收集的最大内存使用量约为 5 GiB。 -- 最大值:需要小于集群在不进行统计信息收集时的内存空余量。 - -## 持久化 `ANALYZE` 配置 - -从 v5.4.0 起,TiDB 支持 `ANALYZE` 配置持久化,方便后续收集统计信息时沿用已有配置。 - -TiDB 支持以下 `ANALYZE` 配置的持久化: - -| 配置 | 对应的 `ANALYZE` 语法 | -| --- | --- | -| 直方图桶数 | `WITH NUM BUCKETS` | -| TopN 个数 | `WITH NUM TOPN` | -| 采样数 | `WITH NUM SAMPLES` | -| 采样率 | `WITH FLOATNUM SAMPLERATE` | -| `ANALYZE` 的列的类型 | AnalyzeColumnOption ::= ( 'ALL COLUMNS' \| 'PREDICATE COLUMNS' \| 'COLUMNS' ColumnNameList ) | -| `ANALYZE` 的列 | ColumnNameList ::= Identifier ( ',' Identifier )* | - -### 开启 `ANALYZE` 配置持久化 - -`ANALYZE` 配置持久化功能默认开启,即系统变量 `tidb_analyze_version` 为默认值 `2`,`tidb_persist_analyze_options` 为默认值 `ON`。 - -`ANALYZE` 配置持久化功能可用于记录手动执行 `ANALYZE` 语句时指定的持久化配置。记录后,当 TiDB 下一次自动更新统计信息或者你手动收集统计信息但未指定配置时,TiDB 会按照记录的配置收集统计信息。 - -如果要查询某张表上的持久化配置用于自动更新统计信息,使用以下 SQL 语句: - -```sql -SELECT sample_num, sample_rate, buckets, topn, column_choice, column_ids FROM mysql.analyze_options opt JOIN information_schema.tables tbl ON opt.table_id = tbl.tidb_table_id WHERE tbl.table_schema = '{db_name}' AND tbl.table_name = '{table_name}'; -``` - -TiDB 会使用最新的 `ANALYZE` 语句中指定的配置覆盖先前记录的持久化配置。例如,如果你运行 `ANALYZE TABLE t WITH 200 TOPN;` ,它将在 `ANALYZE` 语句中设置前 200 个值。随后,执行 `ANALYZE TABLE t WITH 0.1 SAMPLERATE;` 将为自动 `ANALYZE` 语句同时设置前 200 个值和 0.1 的采样率,类似于 `ANALYZE TABLE t WITH 200 TOPN, 0.1 SAMPLERATE;`。 - -### 关闭 `ANALYZE` 配置持久化 - -如果要关闭 `ANALYZE` 配置持久化功能,请将系统变量 `tidb_persist_analyze_options` 设置为 `OFF`。此外,由于 `ANALYZE` 配置持久化功能在 `tidb_analyze_version = 1` 的情况下不适用,因此设置 `tidb_analyze_version = 1` 同样会达到关闭配置持久化的效果。 - -关闭 `ANALYZE` 配置持久化功能后,已持久化的配置记录不会被清除。因此,当再次开启该功能时,TiDB 会继续使用之前记录的持久化配置收集统计信息。 - -> **注意:** -> -> 当再次开启 `ANALYZE` 配置持久化功能时,如果之前记录的持久化配置项已经不适用当前的数据,请手动执行 `ANALYZE` 语句并指定新的持久化配置。 - -### 持久化列配置 - -如果要持久化 `ANALYZE` 语句中列的配置(包括 `COLUMNS ColumnNameList`、`PREDICATE COLUMNS`、`ALL COLUMNS`),请将系统变量 [`tidb_persist_analyze_options`](/system-variables.md#tidb_persist_analyze_options-从-v540-版本开始引入) 的值设置为 `ON`,以开启[持久化 `ANALYZE` 配置](/statistics.md#持久化-analyze-配置)功能。开启 `ANALYZE` 配置持久化之后: - -- 当 TiDB 自动收集统计信息或者你手动执行 `ANALYZE` 语句收集统计信息但未指定列的配置时,TiDB 会继续沿用之前持久化的配置。 -- 当多次手动执行 `ANALYZE` 语句并指定列的配置时,TiDB 会使用最新一次 `ANALYZE` 指定的配置项覆盖上一次记录的持久化配置。 - -如果要查看一个表中哪些列是 `PREDICATE COLUMNS`、哪些列的统计信息已经被收集,请使用 [`SHOW COLUMN_STATS_USAGE`](/sql-statements/sql-statement-show-column-stats-usage.md) 语句。 - -在以下示例中,执行 `ANALYZE TABLE t PREDICATE COLUMNS;` 后,TiDB 将收集 `b`、`c`、`d` 列的统计信息,其中 `b` 列是 `PREDICATE COLUMN`,`c` 列和 `d` 列是索引列。 - -```sql -SET GLOBAL tidb_enable_column_tracking = ON; -Query OK, 0 rows affected (0.00 sec) - -CREATE TABLE t (a INT, b INT, c INT, d INT, INDEX idx_c_d(c, d)); -Query OK, 0 rows affected (0.00 sec) - --- 在此查询中优化器用到了 b 列的统计信息。 -SELECT * FROM t WHERE b > 1; -Empty set (0.00 sec) - --- 等待一段时间(100 * stats-lease)后,TiDB 将收集的 `PREDICATE COLUMNS` 写入 mysql.column_stats_usage。 --- 指定 `last_used_at IS NOT NULL` 表示显示 TiDB 收集到的 `PREDICATE COLUMNS`。 -SHOW COLUMN_STATS_USAGE WHERE db_name = 'test' AND table_name = 't' AND last_used_at IS NOT NULL; -+---------+------------+----------------+-------------+---------------------+------------------+ -| Db_name | Table_name | Partition_name | Column_name | Last_used_at | Last_analyzed_at | -+---------+------------+----------------+-------------+---------------------+------------------+ -| test | t | | b | 2022-01-05 17:21:33 | NULL | -+---------+------------+----------------+-------------+---------------------+------------------+ -1 row in set (0.00 sec) - -ANALYZE TABLE t PREDICATE COLUMNS; -Query OK, 0 rows affected, 1 warning (0.03 sec) - --- 指定 `last_analyzed_at IS NOT NULL` 表示显示收集过统计信息的列。 -SHOW COLUMN_STATS_USAGE WHERE db_name = 'test' AND table_name = 't' AND last_analyzed_at IS NOT NULL; -+---------+------------+----------------+-------------+---------------------+---------------------+ -| Db_name | Table_name | Partition_name | Column_name | Last_used_at | Last_analyzed_at | -+---------+------------+----------------+-------------+---------------------+---------------------+ -| test | t | | b | 2022-01-05 17:21:33 | 2022-01-05 17:23:06 | -| test | t | | c | NULL | 2022-01-05 17:23:06 | -| test | t | | d | NULL | 2022-01-05 17:23:06 | -+---------+------------+----------------+-------------+---------------------+---------------------+ -3 rows in set (0.00 sec) -``` - -## 统计信息版本 - -系统变量 [`tidb_analyze_version`](/system-variables.md#tidb_analyze_version-从-v510-版本开始引入) 用于控制 TiDB 收集统计信息的行为。目前 TiDB 支持两个版本的统计信息,即 `tidb_analyze_version = 1` 和 `tidb_analyze_version = 2`。 - -- 从 v5.3.0 开始,变量 `tidb_analyze_version` 的默认值从 `1` 变为了 `2`。 -- 如果从 v5.3.0 之前版本的集群升级至 v5.3.0 或之后的版本,该变量的默认值不会发生变化。 - - -更推荐选择 Version 2。Version 2 将继续增强,并最终完全取代 Version 1。与 Version 1 相比,Version 2 提高了大数据量场景下多项统计信息收集的准确性。此外,Version 2 在进行谓词选择率估算时不再需要收集 Count-Min Sketch 统计信息,并支持仅对选定列进行自动收集(参见[收集部分列的统计信息](#收集部分列的统计信息)),从而提高了收集性能。 - -以下表格列出了两个统计信息版本为优化器估算收集的信息: - -| 信息 | Version 1 | Version 2| -| --- | --- | ---| -| 表的总行数 | ⎷ | ⎷ | -| 等值查询或 `IN` 查询的谓词估算 | ⎷(列/索引 Top-N & Count-Min Sketch) | ⎷(列/索引 Top-N & 直方图) | -| Range 范围谓词估算 | ⎷(列/索引 Top-N & 直方图) | ⎷(列/索引 Top-N & 直方图) | -| `NULL` 谓词估算 | ⎷ | ⎷ | -| 列的平均长度 | ⎷ | ⎷ | -| 索引的平均长度 | ⎷ | ⎷ | - -### 切换统计信息版本 - -建议确保所有表、索引(和分区)使用相同版本的统计信息收集功能。推荐使用 Version 2,但不建议在没有正当理由(例如使用中的版本出现问题)的情况下切换版本。版本之间的切换可能需要一段时间,在此期间可能没有统计信息,直到所有表都使用了新版本进行统计。如果没有统计信息,可能会影响优化器的计划选择。 - -切换版本的正当理由可能包括:使用 Version 1 在收集 Count-Min Sketch 统计信息时,由于哈希冲突导致等值查询或 `IN` 查询谓词估算不准确。此时,你可以参考 [Count-Min Sketch](#count-min-sketch) 小节中描述的解决方案,或者设置 `tidb_analyze_version = 2` 并对所有对象重新运行 `ANALYZE`。在 Version 2 的早期阶段,执行 `ANALYZE` 后有内存溢出的风险,现在这个问题已经解决,但最初的解决方案是设置 `tidb_analyze_version = 1` 并对所有对象重新运行 `ANALYZE`。 - -要为切换统计信息版本做好 `ANALYZE` 准备,请根据情况进行以下操作: - -- 如果 `ANALYZE` 语句是手动执行的,请手动统计每张需要统计的表: - - ```sql - SELECT DISTINCT(CONCAT('ANALYZE TABLE ', table_schema, '.', table_name, ';')) - FROM information_schema.tables JOIN mysql.stats_histograms - ON table_id = tidb_table_id - WHERE stats_ver = 2; - ``` - -- 如果 `ANALYZE` 语句是由 TiDB 自动执行的(当开启自动更新统计信息时),请执行以下语句生成 [`DROP STATS`](/sql-statements/sql-statement-drop-stats.md) 语句: - - ```sql - SELECT DISTINCT(CONCAT('DROP STATS ', table_schema, '.', table_name, ';')) - FROM information_schema.tables ON mysql.stats_histograms - ON table_id = tidb_table_id - WHERE stats_ver = 2; - ``` - -- 如果上一条语句的返回结果太长,不方便复制粘贴,可以将结果导出到临时文件后,再执行: - - ```sql - SELECT DISTINCT ... INTO OUTFILE '/tmp/sql.txt'; - mysql -h ${TiDB_IP} -u user -P ${TIDB_PORT} ... < '/tmp/sql.txt' - ``` - -## 查看统计信息 - -你可以使用一些 SQL 语句来查看 `ANALYZE` 的状态和统计信息的情况。 - -### `ANALYZE` 状态 - -在执行 `ANALYZE` 语句时,可以使用 [`SHOW ANALYZE STATUS`](/sql-statements/sql-statement-show-analyze-status.md) 语句来查看当前 `ANALYZE` 的状态。 - -从 TiDB v6.1.0 起,执行 `SHOW ANALYZE STATUS` 语句将显示集群级别的任务,且 TiDB 重启后仍能看到重启之前的任务记录。在 TiDB v6.1.0 之前,执行 `SHOW ANALYZE STATUS` 语句仅显示实例级别的任务,且 TiDB 重启后任务记录会被清空。 - -`SHOW ANALYZE STATUS` 仅显示最近的任务记录。从 TiDB v6.1.0 起,你可以通过系统表 `mysql.analyze_jobs` 查看过去 7 天内的历史记录。 - -当设置了系统变量 [`tidb_mem_quota_analyze`](/system-variables.md#tidb_mem_quota_analyze-从-v610-版本开始引入) 且 TiDB 后台的统计信息自动更新任务的内存占用超过了这个阈值时,自动更新任务会重试。失败的任务和重试的任务都可以在 `SHOW ANALYZE STATUS` 语句的执行结果中查看。 - -当 [`tidb_max_auto_analyze_time`](/system-variables.md#tidb_max_auto_analyze_time-从-v610-版本开始引入) 大于 `0` 时,如果后台统计信息自动更新任务的执行时间超过这个阈值,该任务会被终止。 - -语法如下: - -```sql -SHOW ANALYZE STATUS [ShowLikeOrWhere]; -``` - -``` -+--------------+------------+----------------+-------------------------------------------------------------------------------------------+----------------+---------------------+---------------------+----------+-------------------------------------------------------------------------------| -| Table_schema | Table_name | Partition_name | Job_info | Processed_rows | Start_time | End_time | State | Fail_reason | -+--------------+------------+----------------+-------------------------------------------------------------------------------------------+----------------+---------------------+---------------------+----------+-------------------------------------------------------------------------------| -| test | sbtest1 | | retry auto analyze table all columns with 100 topn, 0.055 samplerate | 2000000 | 2022-05-07 16:41:09 | 2022-05-07 16:41:20 | finished | NULL | -| test | sbtest1 | | auto analyze table all columns with 100 topn, 0.5 samplerate | 0 | 2022-05-07 16:40:50 | 2022-05-07 16:41:09 | failed | analyze panic due to memory quota exceeds, please try with smaller samplerate | -``` - -### 表的元信息 - -你可以使用 [`SHOW STATS_META`](/sql-statements/sql-statement-show-stats-meta.md) 语句来查看表的总行数以及修改的行数等信息。 - -### 表的健康度信息 - -你可以使用 [`SHOW STATS_HEALTHY`](/sql-statements/sql-statement-show-stats-healthy.md) 语句查看表的统计信息健康度,并粗略估计表上统计信息的准确度。当 `modify_count` >= `row_count` 时,健康度为 0;当 `modify_count` < `row_count` 时,健康度为 (1 - `modify_count`/`row_count`) * 100。 - -### 列的元信息 - -你可以使用 [`SHOW STATS_HISTOGRAMS`](/sql-statements/sql-statement-show-stats-histograms.md) 语句查看列的不同值数量以及 `NULL` 数量等信息。 - -### 直方图桶的信息 - -你可以使用 [`SHOW STATS_BUCKETS`](/sql-statements/sql-statement-show-stats-buckets.md) 语句查看直方图每个桶的信息。 - -### Top-N 信息 - -你可以使用 [`SHOW STATS_TOPN`](/sql-statements/sql-statement-show-stats-topn.md) 语句查看当前 TiDB 收集的 Top-N 值的信息。 - -## 删除统计信息 - -你可以通过执行 [`DROP STATS`](/sql-statements/sql-statement-drop-stats.md) 语句来删除统计信息。 - -## 加载统计信息 - -默认情况下,列的统计信息占用空间大小不同,TiDB 对统计信息的加载方式也会不同: - -- 对于 count、distinctCount、nullCount 等占用空间较小的统计信息,只要有数据更新,TiDB 就会自动将对应的统计信息加载进内存供 SQL 优化阶段使用。 -- 对于直方图、TopN、CMSketch 等占用空间较大的统计信息,为了确保 SQL 执行的性能,TiDB 会按需进行异步加载。例如,对于直方图,只有当某条 SQL 语句的优化阶段使用到了某列的直方图统计信息时,TiDB 才会将该列的直方图信息加载到内存。按需异步加载的优势是统计信息加载不会影响到 SQL 执行的性能,但在 SQL 优化时有可能使用不完整的统计信息。 - -从 v5.4.0 开始,TiDB 引入了统计信息同步加载的特性,支持执行当前 SQL 语句时将直方图、TopN、CMSketch 等占用空间较大的统计信息同步加载到内存,提高该 SQL 语句优化时统计信息的完整性。 - -要开启该特性,请将系统变量 [`tidb_stats_load_sync_wait`](/system-variables.md#tidb_stats_load_sync_wait-从-v540-版本开始引入) 的值设置为 SQL 优化可以等待的同步加载完整的列统计信息的最长超时时间(单位为毫秒)。该变量的默认值为 `100`,代表开启统计信息同步加载。 - -开启同步加载统计信息特性后,你可以进一步配置该特性: - -- 通过修改系统变量 [`tidb_stats_load_pseudo_timeout`](/system-variables.md#tidb_stats_load_pseudo_timeout-从-v540-版本开始引入) 的值控制 SQL 优化等待超时后 TiDB 的行为。该变量默认值为 `ON`,表示超时后 SQL 优化过程不会使用任何列上的直方图、TopN 或 CMSketch。当该变量设置为 `OFF` 时,表示超时后 SQL 执行失败。 -- 通过修改 TiDB 配置项 [`stats-load-concurrency`](/tidb-configuration-file.md#stats-load-concurrency-从-v540-版本开始引入) 的值控制统计信息同步加载可以并发处理的最大列数。该配置项的默认值为 `5`。 -- 通过修改 TiDB 配置项 [`stats-load-queue-size`](/tidb-configuration-file.md#stats-load-queue-size-从-v540-版本开始引入) 的值设置统计信息同步加载最多可以缓存多少列的请求。该配置项的默认值为 `1000`。 - -在 TiDB 启动阶段,初始统计信息加载完成之前执行的 SQL 可能有不合理的执行计划,从而影响性能。为了避免这种情况,从 v7.1.0 开始,TiDB 引入了配置参数 [`force-init-stats`](/tidb-configuration-file.md#force-init-stats-从-v657-和-v710-版本开始引入)。你可以使用该配置参数控制 TiDB 启动时是否在统计信息初始化完成后再对外提供服务。该配置参数从 v7.2.0 起默认开启。 - -从 v7.1.0 开始,TiDB 引入了配置参数 [`lite-init-stats`](/tidb-configuration-file.md#lite-init-stats-从-v710-版本开始引入),用于控制是否开启轻量级的统计信息初始化。 - -- 当 `lite-init-stats` 设置为 `true` 时,统计信息初始化时列和索引的直方图、TopN、Count-Min Sketch 均不会加载到内存中。 -- 当 `lite-init-stats` 设置为 `false` 时,统计信息初始化时索引和主键的直方图、TopN、Count-Min Sketch 会被加载到内存中,非主键列的直方图、TopN、Count-Min Sketch 不会加载到内存中。当优化器需要某一索引或者列的直方图、TopN、Count-Min Sketch 时,这些统计信息会被同步或异步加载到内存中。 - -`lite-init-stats` 的默认值为 `true`,即开启轻量级的统计信息初始化。将 `lite-init-stats` 设置为 `true` 可以加速统计信息初始化,避免加载不必要的统计信息,从而减少 TiDB 的内存使用。 - -## 导出和导入统计信息 - -本小节介绍如何导出和导入统计信息。 - -### 导出统计信息 - -统计信息的导出接口如下: - -+ 通过以下接口可以获取数据库 `${db_name}` 中的表 `${table_name}` 的 JSON 格式的统计信息: - - ``` - http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name} - ``` - - 示例如下: - - ``` - curl -s http://127.0.0.1:10080/stats/dump/test/t1 -o /tmp/t1.json - ``` - -+ 通过以下接口可以获取数据库 `${db_name}` 中的表 `${table_name}` 在指定时间上的 JSON 格式的统计信息。指定的时间应在 GC SafePoint 之后。 - - ``` - http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name}/${yyyyMMddHHmmss} - ``` - -### 导入统计信息 - -> **注意:** -> -> 启动 MySQL 客户端时,请使用 `--local-infile=1` 参数。 - -导入的统计信息一般指通过统计信息导出接口得到的 JSON 文件。你可以使用 [`LOAD STATS`](/sql-statements/sql-statement-load-stats.md) 语句来导入统计信息。 - -语法如下: - -```sql -LOAD STATS 'file_name'; -``` - -`file_name` 为要导入的统计信息的文件名。 - -## 锁定统计信息 - -从 v6.5.0 开始,TiDB 支持锁定统计信息。当一张表或一个分区的统计信息被锁定以后,该表或分区的统计信息将无法被修改,也无法对该表进行 `ANALYZE` 操作。示例如下: - -创建表 `t`,并插入一些数据。在未锁定表 `t` 的统计信息时,可以成功执行 `ANALYZE` 语句: - -```sql -mysql> CREATE TABLE t(a INT, b INT); -Query OK, 0 rows affected (0.03 sec) - -mysql> INSERT INTO t VALUES (1,2), (3,4), (5,6), (7,8); -Query OK, 4 rows affected (0.00 sec) -Records: 4 Duplicates: 0 Warnings: 0 - -mysql> ANALYZE TABLE t; -Query OK, 0 rows affected, 1 warning (0.02 sec) - -mysql> SHOW WARNINGS; -+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Level | Code | Message | -+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t, reason to use this rate is "Row count in stats_meta is much smaller compared with the row count got by PD, use min(1, 15000/4) as the sample-rate=1" | -+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -1 row in set (0.00 sec) -``` - -锁定表 `t` 的统计信息,再执行 `ANALYZE` 语句,warning 提示跳过对表 `t` 的 `ANALYZE`: - -```sql -mysql> LOCK STATS t; -Query OK, 0 rows affected (0.00 sec) - -mysql> SHOW STATS_LOCKED; -+---------+------------+----------------+--------+ -| Db_name | Table_name | Partition_name | Status | -+---------+------------+----------------+--------+ -| test | t | | locked | -+---------+------------+----------------+--------+ -1 row in set (0.01 sec) - -mysql> ANALYZE TABLE t; -Query OK, 0 rows affected, 2 warnings (0.00 sec) - -mysql> SHOW WARNINGS; -+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ -| Level | Code | Message | -+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t, reason to use this rate is "use min(1, 110000/8) as the sample-rate=1" | -| Warning | 1105 | skip analyze locked table: test.t | -+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ -2 rows in set (0.00 sec) -``` - -解锁表 `t` 的统计信息,可以成功执行 `ANALYZE` 语句: - -```sql -mysql> UNLOCK STATS t; -Query OK, 0 rows affected (0.01 sec) - -mysql> ANALYZE TABLE t; -Query OK, 0 rows affected, 1 warning (0.03 sec) - -mysql> SHOW WARNINGS; -+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ -| Level | Code | Message | -+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t, reason to use this rate is "use min(1, 110000/8) as the sample-rate=1" | -+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ -1 row in set (0.00 sec) -``` - -另外,你也可以通过 `LOCK STATS` 语句锁定分区的统计信息。示例如下: - -创建分区表 `t`,并插入一些数据。在未锁定分区 `p1` 的统计信息时,可以成功执行 `ANALYZE` 语句: - -```sql -mysql> CREATE TABLE t(a INT, b INT) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (30)); -Query OK, 0 rows affected (0.03 sec) - -mysql> INSERT INTO t VALUES (1,2), (3,4), (5,6), (7,8); -Query OK, 4 rows affected (0.00 sec) -Records: 4 Duplicates: 0 Warnings: 0 - -mysql> ANALYZE TABLE t; -Query OK, 0 rows affected, 6 warning (0.02 sec) - -mysql> SHOW WARNINGS; -+---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Level | Code | Message | -+---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Warning | 1105 | disable dynamic pruning due to t has no global stats | -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0, reason to use this rate is "Row count in stats_meta is much smaller compared with the row count got by PD, use min(1, 15000/4) as the sample-rate=1" | -| Warning | 1105 | disable dynamic pruning due to t has no global stats | -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | -| Warning | 1105 | disable dynamic pruning due to t has no global stats | -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p2, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | -+---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -6 rows in set (0.01 sec) -``` - -锁定分区 `p1` 的统计信息,再执行 `ANALYZE` 语句,warning 提示跳过对分区 `p1` 的 `ANALYZE`: - -```sql -mysql> LOCK STATS t PARTITION p1; -Query OK, 0 rows affected (0.00 sec) - -mysql> SHOW STATS_LOCKED; -+---------+------------+----------------+--------+ -| Db_name | Table_name | Partition_name | Status | -+---------+------------+----------------+--------+ -| test | t | p1 | locked | -+---------+------------+----------------+--------+ -1 row in set (0.00 sec) - -mysql> ANALYZE TABLE t PARTITION p1; -Query OK, 0 rows affected, 2 warnings (0.01 sec) - -mysql> SHOW WARNINGS; -+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Level | Code | Message | -+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | -| Warning | 1105 | skip analyze locked table: test.t partition (p1) | -+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -2 rows in set (0.00 sec) -``` - -解锁分区 `p1` 的统计信息,可以成功执行 `ANALYZE` 语句: - -```sql -mysql> UNLOCK STATS t PARTITION p1; -Query OK, 0 rows affected (0.00 sec) - -mysql> ANALYZE TABLE t PARTITION p1; -Query OK, 0 rows affected, 1 warning (0.01 sec) - -mysql> SHOW WARNINGS; -+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Level | Code | Message | -+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | -+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -1 row in set (0.00 sec) -``` - -### 锁定统计信息的行为说明 - -* 如果统计信息在分区表上锁定,那么该分区表上所有分区的统计信息就都保持锁定。 -* 如果表或者分区被 truncate,该表或分区上的统计信息锁定将会被解除。 - -具体行为参见下面表格: - -| | 删除整张表 | Truncate 整张表 | Truncate 某个分区 | 创建一个新分区 | 删除某个分区 | Reorganize 某个分区 | 交换某个分区 | -|-----|----------|----------------|-----------------|--------------|-----------|-----------|-------| -| 非分区表被锁定 | 锁定失效 | 锁定失效,因为 TiDB 删除了旧表,所以锁定信息也一起被删除 | / | / | / | / | / | -| 分区表并且整张表被锁定 | 锁定失效 | 锁定失效,因为 TiDB 删除了旧表,所以锁定信息也一起被删除 | 旧的分区锁定信息失效,自动锁定新的分区 | 自动锁定新分区 | 被删除的分区锁定信息被清理,整张表锁继续生效 | 被删除的分区锁定信息被清理,新分区被自动锁定 | 锁定信息被转移到被交换表,新分区被自动锁定 | -| 分区表并且只锁定了某些分区 | 锁定失效 | 锁定失效,因为 TiDB 删除了旧的分区表,所以锁定信息也一起被删除 | 锁定失效,因为 TiDB 删除了旧的分区表,所以锁定信息也一起被删除 | / | 被删除的分区锁定信息被清理 | 被删除的分区锁定信息被清理 | 锁定信息被转移到被交换表 | - -## 管理 `ANALYZE` 任务与并发 - -本小节介绍如何终止后台的 `ANALYZE` 任务,如何控制 `ANALYZE` 并发度。 - -### 终止后台的 `ANALYZE` 任务 - -从 TiDB v6.0 起,TiDB 支持通过 `KILL` 语句终止正在后台运行的 `ANALYZE` 任务。如果发现正在后台运行的 `ANALYZE` 任务消耗大量资源影响业务,你可以通过以下步骤终止该 `ANALYZE` 任务: - -1. 执行以下 SQL 语句: - - ```sql - SHOW ANALYZE STATUS - ``` - - 查看 `instance` 列和 `process_id` 列,获得正在执行后台 `ANALYZE` 任务的 TiDB 实例地址和任务 `ID`。 - -2. 终止正在后台运行的 `ANALYZE` 任务。 - - - 如果 [`enable-global-kill`](/tidb-configuration-file.md#enable-global-kill-从-v610-版本开始引入) 的值为 `true`(默认为 `true`),你可以直接执行 `KILL TIDB ${id};` 语句。其中,`${id}` 为上一步中查询得到的后台 `ANALYZE` 任务的 `ID`。 - - 如果 `enable-global-kill` 的值为 `false`,你需要先使用客户端连接到执行后台 `ANALYZE` 任务的 TiDB 实例,然后再执行 `KILL TIDB ${id};` 语句。如果使用客户端连接到其他 TiDB 实例,或者客户端和 TiDB 中间有代理,则 `KILL` 语句不能终止后台的 `ANALYZE` 任务。 - - 关于 `KILL` 语句的更多信息,参见 [`KILL`](/sql-statements/sql-statement-kill.md)。 - -### 控制 `ANALYZE` 并发度 - -执行 `ANALYZE` 语句的时候,你可以通过一些系统变量来调整并发度,以控制对系统的影响。 - -相关系统变量的关系如下图所示: - -![analyze_concurrency](/media/analyze_concurrency.png) - -`tidb_build_stats_concurrency`、`tidb_build_sampling_stats_concurrency` 和 `tidb_analyze_partition_concurrency` 为上下游关系。实际的总并发为:`tidb_build_stats_concurrency`* (`tidb_build_sampling_stats_concurrency` + `tidb_analyze_partition_concurrency`) 。所以在变更这些参数的时候,需要同时考虑这三个参数的值。建议按 `tidb_analyze_partition_concurrency`、`tidb_build_sampling_stats_concurrency`、`tidb_build_stats_concurrency` 的顺序逐个调节,并观察对系统的影响。这三个参数的值越大,对系统的资源开销就越大。 - -#### `tidb_build_stats_concurrency` - -`ANALYZE` 任务在执行时会被切分成一个个小任务,每个任务只负责某一个列或者索引的统计信息收集。你可以使用 [`tidb_build_stats_concurrency`](/system-variables.md#tidb_build_stats_concurrency) 控制可以同时执行的小任务的数量,其默认值是 `2`。TiDB v7.4.0 及其之前版本中,默认值为 `4`。 - -#### `tidb_build_sampling_stats_concurrency` - -在执行 `ANALYZE` 普通列任务的时候,你可以使用 [`tidb_build_sampling_stats_concurrency`](/system-variables.md#tidb_build_sampling_stats_concurrency-从-v750-版本开始引入) 控制执行采样任务的并发数量,其默认值是 `2`。 - -#### `tidb_analyze_partition_concurrency` - -在执行 `ANALYZE` 任务的时候,你可以使用 [`tidb_analyze_partition_concurrency`](/system-variables.md#tidb_analyze_partition_concurrency) 控制对分区表统计信息进行读写的并发度,其默认值是 `2`。TiDB v7.4.0 及其之前版本中,默认值为 `1`。 - -#### `tidb_distsql_scan_concurrency` - -在执行 `ANALYZE` 普通列任务的时候,你可以使用 [`tidb_distsql_scan_concurrency`](/system-variables.md#tidb_distsql_scan_concurrency) 控制一次读取的 Region 数量,其默认值是 `15`。修改该变量的值会影响查询性能,请谨慎调整。 - -#### `tidb_index_serial_scan_concurrency` - -在执行 `ANALYZE` 索引列任务的时候,你可以使用 [`tidb_index_serial_scan_concurrency`](/system-variables.md#tidb_index_serial_scan_concurrency) 控制一次读取的 Region 数量,其默认值是 `1`。修改该变量的值会影响查询性能,请谨慎调整。 - -## 另请参阅 - -* [`LOAD STATS`](/sql-statements/sql-statement-load-stats.md) -* [`DROP STATS`](/sql-statements/sql-statement-drop-stats.md) -* [`LOCK STATS`](/sql-statements/sql-statement-lock-stats.md) -* [`UNLOCK STATS`](/sql-statements/sql-statement-unlock-stats.md) -* [`SHOW STATS_LOCKED`](/sql-statements/sql-statement-show-stats-locked.md) \ No newline at end of file +> 目前,自动更新不会记录手动 `ANALYZE` 时输入的配置项。因此,当您使用 [`WITH`](/sql-statements/sql-statement-analyze-table.md) 语法控制 `ANALYZE` 的收集行为时,您需要手动设置定时任务来收集统计信息。 diff --git a/status-variables.md b/status-variables.md index 747a04bd2448..53a1114af444 100644 --- a/status-variables.md +++ b/status-variables.md @@ -1,122 +1,122 @@ --- title: 服务器状态变量 -summary: 使用状态变量查看系统和会话状态。 +summary: 使用状态变量查看系统和会话状态 --- # 服务器状态变量 -服务器状态变量提供有关服务器全局状态和 TiDB 中当前会话状态的信息。大多数变量与 MySQL 兼容。 +服务器状态变量提供了 TiDB 中服务器全局状态和当前会话状态的信息。这些变量中的大多数都是为了与 MySQL 兼容而设计的。 -你可以使用 [SHOW GLOBAL STATUS](/sql-statements/sql-statement-show-status.md) 命令查看全局状态,使用 [SHOW SESSION STATUS](/sql-statements/sql-statement-show-status.md) 命令查看当前会话状态。 +你可以使用 [SHOW GLOBAL STATUS](/sql-statements/sql-statement-show-status.md) 命令查看全局状态,使用 [SHOW SESSION STATUS](/sql-statements/sql-statement-show-status.md) 命令查看当前会话的状态。 -此外,[FLUSH STATUS](/sql-statements/sql-statement-flush-status.md) 命令与 MySQL 兼容。 +此外,为了与 MySQL 兼容,还支持 [FLUSH STATUS](/sql-statements/sql-statement-flush-status.md) 命令。 ## 变量参考 ### Compression - 作用域:SESSION -- 类型:布尔值 -- MySQL 是否使用压缩协议。 +- 类型:Boolean +- 表示 MySQL 协议是否使用压缩。 ### Compression_algorithm - 作用域:SESSION -- 类型:字符串 -- MySQL 协议使用的压缩算法。 +- 类型:String +- 表示 MySQL 协议使用的压缩算法。 ### Compression_level - 作用域:SESSION -- 类型:整数型 -- MySQL 协议使用的压缩等级。 +- 类型:Integer +- MySQL 协议使用的压缩级别。 ### Ssl_cipher - 作用域:SESSION | GLOBAL -- 类型:字符串 -- 正在使用的 TLS 加密套件。 +- 类型:String +- 当前使用的 TLS 加密算法。 ### Ssl_cipher_list - 作用域:SESSION | GLOBAL -- 类型:字符串 -- 服务器支持的 TLS 加密套件列表。 +- 类型:String +- 服务器支持的 TLS 加密算法列表。 ### Ssl_server_not_after - 作用域:SESSION | GLOBAL -- 类型:日期 -- 服务器用于 TLS 连接的 X.509 证书的过期时间。 +- 类型:Date +- 用于 TLS 连接的服务器 X.509 证书的过期日期。 ### Ssl_server_not_before - 作用域:SESSION | GLOBAL -- 类型:字符串 -- 服务器用于 TLS 连接的 X.509 证书的开始时间。 +- 类型:String +- 用于 TLS 连接的服务器 X.509 证书的生效日期。 ### Ssl_verify_mode - 作用域:SESSION | GLOBAL -- 类型:整数型 -- TLS 验证模式掩码。 +- 类型:Integer +- TLS 验证模式位掩码。 ### Ssl_version - 作用域:SESSION | GLOBAL -- 类型:字符串 -- TLS 协议使用的版本。 +- 类型:String +- 使用的 TLS 协议版本。 ### Uptime - 作用域:SESSION | GLOBAL -- 类型:整数型 -- 服务器正常运行时间(秒)。 +- 类型:Integer +- 服务器运行时间,以秒为单位。 ### ddl_schema_version - 作用域:SESSION | GLOBAL -- 类型:整数型 -- DDL schema 使用的版本。 +- 类型:Integer +- 使用的 DDL schema 版本。 -### last_plan_binding_update_time 从 v5.2.0 版本开始引入 +### last_plan_binding_update_time New in v5.2.0 - 作用域:SESSION -- 类型:时间戳 -- 最后一次计划绑定更新的日期时间。 +- 类型:Timestamp +- 最后一次执行计划绑定更新的时间和日期。 ### server_id - 作用域:SESSION | GLOBAL -- 类型:字符串 -- 服务器的通用唯一识别码 (UUID)。 +- 类型:String +- 服务器的 UUID。 ### tidb_gc_last_run_time - 作用域:SESSION | GLOBAL -- 类型:字符串 -- 最近一次运行[垃圾回收 (GC)](/garbage-collection-overview.md) 的时间戳。 +- 类型:String +- 最后一次运行 [GC](/garbage-collection-overview.md) 的时间戳。 ### tidb_gc_leader_desc - 作用域:SESSION | GLOBAL -- 类型:字符串 -- [GC](/garbage-collection-overview.md) leader 的相关信息,包括主机名和进程 ID (PID)。 +- 类型:String +- [GC](/garbage-collection-overview.md) leader 的信息,包括主机名和进程 ID (pid)。 ### tidb_gc_leader_lease - 作用域:SESSION | GLOBAL -- 类型:字符串 -- [GC](/garbage-collection-overview.md) leader 的租约时间戳。 +- 类型:String +- [GC](/garbage-collection-overview.md) lease 的时间戳。 ### tidb_gc_leader_uuid - 作用域:SESSION | GLOBAL -- 类型:字符串 +- 类型:String - [GC](/garbage-collection-overview.md) leader 的 UUID。 ### tidb_gc_safe_point - 作用域:SESSION | GLOBAL -- 类型:字符串 +- 类型:String - [GC](/garbage-collection-overview.md) safe point 的时间戳。 diff --git a/storage-engine/rocksdb-overview.md b/storage-engine/rocksdb-overview.md index 3ba999f39b2f..467233dccdbe 100644 --- a/storage-engine/rocksdb-overview.md +++ b/storage-engine/rocksdb-overview.md @@ -1,52 +1,63 @@ --- -title: RocksDB 简介 -summary: RocksDB 是 Facebook 基于 LevelDB 开发的 LSM-tree 架构引擎,提供键值存储与读写功能。数据先写入磁盘上的 WAL,再写入内存中的跳表。内存数据达到阈值后刷到磁盘生成 SST 文件,分为多层,90% 数据存储在最后一层。RocksDB 允许创建多个 ColumnFamily,共享同一个 WAL 文件。为提高读取性能,文件按大小切分成 block,存在 BlockCache 中。后台线程执行 MemTable 转化为 SST 文件和合并操作。L0 文件数量过多会触发 WriteStall 阻塞写入。 +title: RocksDB 概述 +summary: 了解 RocksDB 的基本概念和工作原理。 +category: reference --- -# RocksDB 简介 +# RocksDB 概述 -[RocksDB](https://github.com/facebook/rocksdb) 是由 Facebook 基于 LevelDB 开发的一款提供键值存储与读写功能的 LSM-tree 架构引擎。用户写入的键值对会先写入磁盘上的 WAL (Write Ahead Log),然后再写入内存中的跳表(SkipList,这部分结构又被称作 MemTable)。LSM-tree 引擎由于将用户的随机修改(插入)转化为了对 WAL 文件的顺序写,因此具有比 B 树类存储引擎更高的写吞吐。 +[RocksDB](https://github.com/facebook/rocksdb) 是一个提供键值存储和读写功能的 LSM-tree 存储引擎。它由 Facebook 开发,基于 LevelDB。用户写入的键值对首先被插入到预写日志(Write Ahead Log,WAL)中,然后写入内存中的跳表(SkipList,一种称为 MemTable 的数据结构)。LSM-tree 引擎将随机修改(插入)转换为对 WAL 文件的顺序写入,因此它们提供比 B-tree 引擎更好的写入吞吐量。 -内存中的数据达到一定阈值后,会刷到磁盘上生成 SST 文件 (Sorted String Table),SST 又分为多层(默认至多 6 层),每一层的数据达到一定阈值后会挑选一部分 SST 合并到下一层,每一层的数据是上一层的 10 倍(因此 90% 的数据存储在最后一层)。 +一旦内存中的数据达到一定大小,RocksDB 就会将内容刷新到磁盘上的排序字符串表(Sorted String Table,SST)文件中。SST 文件组织在多个层级中(默认最多 6 层)。当某一层的总大小达到阈值时,RocksDB 会选择部分 SST 文件并将它们合并到下一层。每个后续层的大小是前一层的 10 倍,因此 90% 的数据存储在最后一层。 -RocksDB 允许用户创建多个 ColumnFamily,这些 ColumnFamily 各自拥有独立的内存跳表以及 SST 文件,但是共享同一个 WAL 文件,这样的好处是可以根据应用特点为不同的 ColumnFamily 选择不同的配置,但是又没有增加对 WAL 的写次数。 +RocksDB 允许用户创建多个列族(Column Families,CFs)。CFs 有自己的 SkipList 和 SST 文件,并且它们共享同一个 WAL 文件。这样,不同的 CFs 可以根据应用特性有不同的设置。同时它不会增加对 WAL 的写入次数。 ## TiKV 架构 -TiKV 的系统架构如下图所示: +TiKV 的架构如下图所示: ![TiKV RocksDB](/media/tikv-rocksdb.png) -RocksDB 作为 TiKV 的核心存储引擎,用于存储 Raft 日志以及用户数据。每个 TiKV 实例中有两个 RocksDB 实例,一个用于存储 Raft 日志(通常被称为 raftdb),另一个用于存储用户数据以及 MVCC 信息(通常被称为 kvdb)。kvdb 中有四个 ColumnFamily:raft、lock、default 和 write: +作为 TiKV 的存储引擎,RocksDB 用于存储 Raft 日志和用户数据。TiKV 节点中的所有数据共享两个 RocksDB 实例。一个用于 Raft 日志(通常称为 raftdb),另一个用于用户数据和 MVCC 元数据(通常称为 kvdb)。kvdb 中有四个 CFs:raft、lock、default 和 write: -* raft 列:用于存储各个 Region 的元信息。仅占极少量空间,用户可以不必关注。 -* lock 列:用于存储悲观事务的悲观锁以及分布式事务的一阶段 Prewrite 锁。当用户的事务提交之后,lock cf 中对应的数据会很快删除掉,因此大部分情况下 lock cf 中的数据也很少(少于 1GB)。如果 lock cf 中的数据大量增加,说明有大量事务等待提交,系统出现了 bug 或者故障。 -* write 列:用于存储用户真实的写入数据以及 MVCC 信息(该数据所属事务的开始时间以及提交时间)。当用户写入了一行数据时,如果该行数据长度小于或等于 255 字节,那么会被存储 write 列中,否则该行数据会被存入到 default 列中。由于 TiDB 的非 unique 索引存储的 value 为空,unique 索引存储的 value 为主键索引,因此二级索引只会占用 writecf 的空间。 -* default 列:用于存储超过 255 字节长度的数据。 +* raft CF:存储每个 Region 的元数据。它只占用很少的空间,用户不需要关心。 +* lock CF:存储悲观事务的悲观锁和分布式事务的预写锁。事务提交后,lock CF 中的相应数据会被快速删除。因此,lock CF 中的数据大小通常很小(小于 1 GB)。如果 lock CF 中的数据大量增加,这意味着大量事务正在等待提交,系统可能遇到了 bug 或故障。 +* write CF:存储用户的实际写入数据和 MVCC 元数据(数据所属事务的开始时间戳和提交时间戳)。当用户写入一行数据时,如果数据长度小于或等于 255 字节,则存储在 write CF 中。否则,存储在 default CF 中。在 TiDB 中,二级索引只占用 write CF 的空间,因为非唯一索引存储的值为空,而唯一索引存储的值是主键索引。 +* default CF:存储长度超过 255 字节的数据。 -## RocksDB 的内存占用 +## RocksDB 内存使用 -为了提高读取性能以及减少对磁盘的读取,RocksDB 将存储在磁盘上的文件都按照一定大小切分成 block(默认是 64KB),读取 block 时先去内存中的 BlockCache 中查看该块数据是否存在,存在的话则可以直接从内存中读取而不必访问磁盘。 +为了提高读取性能并减少对磁盘的读取操作,RocksDB 根据一定大小(默认为 64 KB)将存储在磁盘上的文件分成块。读取块时,首先检查数据是否已存在于内存中的 BlockCache 中。如果是,则可以直接从内存中读取数据,而无需访问磁盘。 -BlockCache 按照 LRU 算法淘汰低频访问的数据,TiKV 默认将系统总内存大小的 45% 用于 BlockCache,用户也可以自行修改 `storage.block-cache.capacity` 配置设置为合适的值,但是不建议超过系统总内存的 60%。 +BlockCache 根据 LRU 算法丢弃最近最少使用的数据。默认情况下,TiKV 将系统内存的 45% 用于 BlockCache。用户也可以自行修改 `storage.block-cache.capacity` 配置为适当的值。但不建议超过系统总内存的 60%。 -写入 RocksDB 中的数据会写入 MemTable,当一个 MemTable 的大小超过 128MB 时,会切换到一个新的 MemTable 来提供写入。TiKV 中一共有 2 个 RocksDB 实例,合计 4 个 ColumnFamily,每个 ColumnFamily 的单个 MemTable 大小限制是 128MB,最多允许 5 个 MemTable 存在,否则会阻塞前台写入,因此这部分占用的内存最多为 4 x 5 x 128MB = 2.5GB。这部分占用内存较少,不建议用户自行更改。 +写入 RocksDB 的数据首先写入 MemTable。当 MemTable 的大小超过 128 MB 时,它会切换到一个新的 MemTable。TiKV 中有 2 个 RocksDB 实例,共 4 个 CFs。每个 CF 的单个 MemTable 大小限制为 128 MB。同时最多可以存在 5 个 MemTable,否则前台写入会被阻塞。这部分占用的内存最多为 2.5 GB(4 x 5 x 128 MB)。由于内存消耗较少,不建议更改此限制。 -## RocksDB 的空间占用 +## RocksDB 空间使用 -* 多版本:RocksDB 作为一个 LSM-tree 结构的键值存储引擎,MemTable 中的数据会首先被刷到 L0。L0 层的 SST 之间的范围可能存在重叠(因为文件顺序是按照生成的顺序排列),因此同一个 key 在 L0 中可能存在多个版本。当文件从 L0 合并到 L1 的时候,会按照一定大小(默认是 8MB)切割为多个文件,同一层的文件的范围互不重叠,所以 L1 及其以后的层每一层的 key 都只有一个版本。 -* 空间放大:RocksDB 的每一层文件总大小都是上一层的 x 倍,在 TiKV 中这个配置默认是 10,因此 90% 的数据存储在最后一层,这也意味着 RocksDB 的空间放大不超过 1.11(L0 层的数据较少,可以忽略不计)。 -* TiKV 的空间放大:TiKV 在 RocksDB 之上还有一层自己的 MVCC,当用户写入一个 key 的时候,实际上写入到 RocksDB 的是 key + commit_ts,也就是说,用户的更新和删除都是会写入新的 key 到 RocksDB。TiKV 每隔一段时间会删除旧版本的数据(通过 RocksDB 的 Delete 接口),因此可以认为用户存储在 TiKV 上的数据的实际空间放大为,1.11 加最近 10 分钟内写入的数据(假设 TiKV 回收旧版本数据足够及时)。详情见[《TiDB in Action》](https://github.com/pingcap-incubator/tidb-in-action/blob/master/session4/chapter7/compact.md#tikv-%E7%9A%84%E7%A9%BA%E9%97%B4%E6%94%BE%E5%A4%A7)。 +* 多版本:由于 RocksDB 是具有 LSM-tree 结构的键值存储引擎,MemTable 中的数据首先刷新到 L0。由于文件按生成顺序排列,L0 中的 SST 范围可能会重叠。因此,同一个键在 L0 中可能有多个版本。当文件从 L0 合并到 L1 时,它会被切割成特定大小的多个文件(默认为 8 MB)。同一层上每个文件的键范围不会相互重叠,因此在 L1 和后续层级中每个键只有一个版本。 +* 空间放大:每一层文件的总大小是前一层的 x 倍(默认为 10),因此 90% 的数据存储在最后一层。这也意味着 RocksDB 的空间放大不超过 1.11(L0 数据较少,可以忽略)。 +* TiKV 的空间放大:TiKV 有自己的 MVCC 策略。当用户写入一个键时,实际写入 RocksDB 的是 key + commit_ts,也就是说,更新和删除也会向 RocksDB 写入一个新键。TiKV 会定期删除旧版本的数据(通过 RocksDB 的 Delete 接口),因此可以认为用户在 TiKV 上存储的数据实际空间被放大到 1.11 加上最近 10 分钟写入的数据(假设 TiKV 及时清理旧数据)。 -## RocksDB 后台线程与 Compact +## RocksDB 后台线程和压缩 -RocksDB 中,将内存中的 MemTable 转化为磁盘上的 SST 文件,以及合并各个层级的 SST 文件等操作都是在后台线程池中执行的。后台线程池的默认大小是 8,当机器 CPU 数量小于等于 8 时,则后台线程池默认大小为 CPU 数量减一。通常来说,用户不需要更改这个配置。如果用户在一个机器上部署了多个 TiKV 实例,或者机器的读负载比较高而写负载比较低,那么可以适当调低 `rocksdb/max-background-jobs` 至 3 或者 4。 +在 RocksDB 中,将 MemTable 转换为 SST 文件以及合并各层 SST 文件等操作都在后台线程池中执行。后台线程池的默认大小为 8。当机器的 CPU 数量小于或等于 8 时,后台线程池的默认大小为 CPU 数量减一。 + +通常情况下,用户不需要更改此配置。如果用户在一台机器上部署多个 TiKV 实例,或者机器的读取负载相对较高而写入负载较低,可以适当将 `rocksdb/max-background-jobs` 调整为 3 或 4。 ## WriteStall -RocksDB 的 L0 与其他层不同,L0 的各个 SST 是按照生成顺序排列,各个 SST 之间的 key 范围存在重叠,因此查询的时候必须依次查询 L0 中的每一个 SST。为了不影响查询性能,当 L0 中的文件数量过多时,会触发 WriteStall 阻塞写入。 + + +> **注意:** +> +> 本节适用于 TiDB,不适用于 TiDB Cloud。 + + + +RocksDB 的 L0 与其他层不同。L0 的 SST 按生成顺序排列,SST 之间的键范围可能重叠。因此,执行查询时必须依次查询 L0 中的每个 SST。为了不影响查询性能,当 L0 中的文件过多时,会触发 WriteStall 来阻塞写入。 -如果用户遇到了写延迟突然大幅度上涨,可以先查看 Grafana RocksDB KV 面板 WriteStall Reason 指标,如果是 L0 文件数量过多引起的 WriteStall,可以调整下面几个配置到 64,详细见[《TiDB in Action》](https://github.com/pingcap-incubator/tidb-in-action/blob/master/session4/chapter8/threadpool-optimize.md#5-rocksdb)。 +当遇到写入延迟突然大幅增加时,可以首先查看 Grafana RocksDB KV 面板上的 **WriteStall Reason** 指标。如果是由于 L0 文件过多导致的 WriteStall,可以将以下配置调整为 64。 ``` rocksdb.defaultcf.level0-slowdown-writes-trigger diff --git a/subquery-optimization.md b/subquery-optimization.md index cd3bf0c698bf..a12916b3533f 100644 --- a/subquery-optimization.md +++ b/subquery-optimization.md @@ -1,13 +1,13 @@ --- -title: 子查询相关的优化 -summary: 了解子查询相关的优化。 +title: 子查询相关优化 +summary: 了解与子查询相关的优化。 --- -# 子查询相关的优化 +# 子查询相关优化 -本文主要介绍子查询相关的优化。 +本文主要介绍与子查询相关的优化。 -通常会遇到如下情况的子查询: +子查询通常出现在以下情况: - `NOT IN (SELECT ... FROM ...)` - `NOT EXISTS (SELECT ... FROM ...)` @@ -15,32 +15,34 @@ summary: 了解子查询相关的优化。 - `EXISTS (SELECT ... FROM ...)` - `... >/>=/ ANY (SELECT ... FROM ...)` +## `... < ALL (SELECT ... FROM ...)` 或 `... > ANY (SELECT ... FROM ...)` -对于这种情况,可以将 `ALL` 或者 `ANY` 用 `MAX` 以及 `MIN` 来代替。不过由于在表为空时,`MAX(EXPR)` 以及 `MIN(EXPR)` 的结果会为 `NULL`,其表现形式和 `EXPR` 是有 `NULL` 值的结果一样。以及外部表达式结果为 `NULL` 时也会影响表达式的最终结果,因此这里完整的改写会是如下的形式: +在这种情况下,`ALL` 和 `ANY` 可以被 `MAX` 和 `MIN` 替代。当表为空时,`MAX(EXPR)` 和 `MIN(EXPR)` 的结果为 NULL。当 `EXPR` 的结果包含 `NULL` 时也是如此。`EXPR` 的结果是否包含 `NULL` 可能会影响表达式的最终结果,因此完整的重写形式如下: -- `t.id < all(select s.id from s)` 会被改写为 `t.id < min(s.id) and if(sum(s.id is null) != 0, null, true)`。 -- `t.id > any (select s.id from s)` 会被改写为 `t.id > max(s.id) or if(sum(s.id is null) != 0, null, false)`。 +- `t.id < all (select s.id from s)` 重写为 `t.id < min(s.id) and if(sum(s.id is null) != 0, null, true)` +- `t.id > any (select s.id from s)` 重写为 `t.id > max(s.id) or if(sum(s.id is null) != 0, null, false)` ## `... != ANY (SELECT ... FROM ...)` -对于这种情况,当子查询中不同值的个数只有一种的话,那只要和这个值对比就即可。如果子查询中不同值的个数多于 1 个,那么必然会有不相等的情况出现。因此这样的子查询可以采取如下的改写手段: +在这种情况下,如果子查询中的所有值都是不同的,那么只需要将查询与它们进行比较。如果子查询中不同值的数量超过一个,那么一定存在不等。因此,这类子查询可以重写如下: -- `select * from t where t.id != any (select s.id from s)` 会被改写为 `select t.* from t, (select s.id, count(distinct s.id) as cnt_distinct from s) where (t.id != s.id or cnt_distinct > 1)` +- `select * from t where t.id != any (select s.id from s)` 重写为 `select t.* from t, (select s.id, count(distinct s.id) as cnt_distinct from s) where (t.id != s.id or cnt_distinct > 1)` ## `... = ALL (SELECT ... FROM ...)` -对于这种情况,当子查询中不同值的个数多于一种的话,那么这个表达式的结果必然为假。因此这样的子查询在 TiDB 中会改写为如下的形式: +在这种情况下,当子查询中不同值的数量超过一个时,该表达式的结果必定为 false。因此,在 TiDB 中这类子查询被重写为以下形式: -- `select * from t where t.id = all (select s.id from s)` 会被改写为 `select t.* from t, (select s.id, count(distinct s.id) as cnt_distinct from s) where (t.id = s.id and cnt_distinct <= 1)` +- `select * from t where t.id = all (select s.id from s)` 重写为 `select t.* from t, (select s.id, count(distinct s.id) as cnt_distinct from s ) where (t.id = s.id and cnt_distinct <= 1)` ## `... IN (SELECT ... FROM ...)` -对于这种情况,会将其 `IN` 的子查询改写为 `SELECT ... FROM ... GROUP ...` 的形式,然后将 `IN` 改写为普通的 `JOIN` 的形式。如 `select * from t1 where t1.a in (select t2.a from t2)` 会被改写为 `select t1.* from t1, (select distinct(a) a from t2) t2 where t1.a = t2.a` 的形式。同时这里的 `DISTINCT` 可以在 `t2.a` 具有 `UNIQUE` 属性时被自动消去。 +在这种情况下,`IN` 的子查询被重写为 `SELECT ... FROM ... GROUP ...`,然后重写为 `JOIN` 的常规形式。 + +例如,`select * from t1 where t1.a in (select t2.a from t2)` 被重写为 `select t1.* from t1, (select distinct(a) a from t2) t2 where t1.a = t2.a`。如果 `t2.a` 具有 `UNIQUE` 属性,这里的 `DISTINCT` 属性可以自动消除。 {{< copyable "sql" >}} @@ -61,11 +63,11 @@ explain select * from t1 where t1.a in (select t2.a from t2); +------------------------------+---------+-----------+------------------------+----------------------------------------------------------------------------+ ``` -这个改写会在 `IN` 子查询相对较小,而外部查询相对较大时产生更好的执行性能。因为不经过改写的情况下,我们无法使用以 t2 为驱动表的 `index join`。同时这里的弊端便是,当改写生成的聚合无法被自动消去且 `t2` 表比较大时,反而会影响查询的性能。目前 TiDB 中使用 [tidb\_opt\_insubq\_to\_join\_and\_agg](/system-variables.md#tidb_opt_insubq_to_join_and_agg) 变量来控制这个优化的打开与否。当遇到不合适这个优化的情况可以手动关闭。 +当 `IN` 子查询相对较小而外部查询相对较大时,这种重写可以获得更好的性能,因为不重写的话,无法使用以 t2 为驱动表的 `index join`。然而,缺点是当重写过程中无法自动消除聚合且 `t2` 表相对较大时,这种重写会影响查询性能。目前,使用变量 [tidb\_opt\_insubq\_to\_join\_and\_agg](/system-variables.md#tidb_opt_insubq_to_join_and_agg) 来控制这个优化。当这个优化不适合时,你可以手动禁用它。 -## `EXISTS` 子查询以及 `... >/>=//>=/}} @@ -85,8 +87,10 @@ explain select * from t1 where exists (select * from t2); +------------------------+----------+-----------+---------------+--------------------------------+ ``` -在上述优化中,优化器会自动优化语句执行。除以上情况外,你也可以在语句中添加 [`SEMI_JOIN_REWRITE`](/optimizer-hints.md#semi_join_rewrite) hint 进一步改写语句。 +在上述优化中,优化器会自动优化语句执行。此外,你还可以添加 [`SEMI_JOIN_REWRITE`](/optimizer-hints.md#semi_join_rewrite) 提示来进一步重写语句。 + +如果不使用此提示重写查询,当执行计划中选择 hash join 时,semi-join 查询只能使用子查询来构建哈希表。在这种情况下,当子查询的结果大于外部查询的结果时,执行速度可能会比预期慢。 -如果不使用 `SEMI_JOIN_REWRITE` 进行改写,Semi Join 在选择 Hash Join 的执行方式时,只能够使用子查询构建哈希表,因此在子查询比外查询结果集大时,执行速度可能会不及预期。Semi Join 在选择 Index Join 的执行方式时,只能够使用外查询作为驱动表,因此在子查询比外查询结果集小时,执行速度可能会不及预期。 +同样,当执行计划中选择 index join 时,semi-join 查询只能使用外部查询作为驱动表。在这种情况下,当子查询的结果小于外部查询的结果时,执行速度可能会比预期慢。 -使用 `SEMI_JOIN_REWRITE` 改写后,优化器便可以扩大选择范围,选择更好的执行方式。 +当使用 `SEMI_JOIN_REWRITE()` 重写查询时,优化器可以扩展选择范围以选择更好的执行计划。 diff --git a/sys-schema/sys-schema-unused-indexes.md b/sys-schema/sys-schema-unused-indexes.md index 399149d90cab..03b60d872e08 100644 --- a/sys-schema/sys-schema-unused-indexes.md +++ b/sys-schema/sys-schema-unused-indexes.md @@ -1,15 +1,15 @@ --- title: schema_unused_indexes -summary: 了解 TiDB `sys` 系统数据库中的 `schema_unused_indexes` 表。 +summary: 了解 `sys` schema 中的 `schema_unused_indexes` 表。 --- # `schema_unused_indexes` -`schema_unused_indexes` 用于记录自 TiDB 上次启动以来未被使用的索引信息,包括如下列: +`schema_unused_indexes` 记录了自 TiDB 上次启动以来未被使用过的索引。它包含以下列: -- `OBJECT_SCHEMA`:索引所在表的所属数据库的名称。 -- `OBJECT_NAME`:索引所在表的名称。 -- `INDEX_NAME`:索引的名称。 +- `OBJECT_SCHEMA`:包含索引的表所属的数据库名称。 +- `OBJECT_NAME`:包含索引的表名。 +- `INDEX_NAME`:索引名称。 ```sql USE SYS; @@ -31,7 +31,7 @@ DESC SCHEMA_UNUSED_INDEXES; ## 手动创建 `schema_unused_indexes` 视图 -对于从 v8.0.0 之前版本升级的集群,`sys` Schema 和其中的视图不会自动创建。你可以通过以下 SQL 语句手动创建: +对于从 v8.0.0 之前版本升级的集群,`sys` schema 及其中的视图不会自动创建。你可以使用以下 SQL 语句手动创建它们: ```sql CREATE DATABASE IF NOT EXISTS sys; @@ -49,6 +49,6 @@ CREATE OR REPLACE VIEW sys.schema_unused_indexes AS sum(last_access_time) is null; ``` -## 更多阅读 +## 更多信息 - [`INFORMATION_SCHEMA.TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) diff --git a/sys-schema/sys-schema.md b/sys-schema/sys-schema.md index 0b472394cdc8..6c144962db83 100644 --- a/sys-schema/sys-schema.md +++ b/sys-schema/sys-schema.md @@ -1,14 +1,14 @@ --- title: sys Schema -summary: 了解 TiDB `sys` 系统数据库。 +summary: 了解 `sys` schema 中的系统表。 --- # `sys` Schema -TiDB 从 v8.0.0 开始提供 `sys` Schema。你可以通过查看 `sys` 系统数据库中的表或视图理解 TiDB 的系统表、[`INFORMATION_SCHEMA`](/information-schema/information-schema.md) 表和 [`PERFORMANCE SCHEMA`](/performance-schema/performance-schema.md) 表内的数据。 +从 v8.0.0 开始,TiDB 提供了 `sys` schema。你可以使用 `sys` schema 中的视图来了解 TiDB 系统表、[`INFORMATION_SCHEMA`](/information-schema/information-schema.md) 和 [`PERFORMANCE SCHEMA`](/performance-schema/performance-schema.md) 中的数据。 -## 与 MySQL 兼容的表 +## MySQL 兼容性表 -| 表名 | 描述 | -|---------------------------------------------------------------------|---------------------------| -| [`schema_unused_indexes`](/sys-schema/sys-schema-unused-indexes.md) | 记录自 TiDB 上次启动以来未被使用的索引信息。 | +| 表名 | 描述 | +|--------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| [`schema_unused_indexes`](/sys-schema/sys-schema-unused-indexes.md) | 记录自 TiDB 上次启动以来未被使用过的索引。 | diff --git a/system-variables.md b/system-variables.md index b342c56e9f5d..d70ee5aee1bd 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1,272 +1,272 @@ --- title: 系统变量 -summary: 使用 TiDB 系统变量来优化性能或修改运行行为。 +summary: 使用系统变量来优化性能或改变运行行为。 --- # 系统变量 -TiDB 系统变量的行为与 MySQL 相似,变量的作用范围可以是会话级别有效 (Session Scope) 或全局范围有效 (Global Scope)。其中: +TiDB 系统变量的行为与 MySQL 类似,设置应用于 `SESSION` 或 `GLOBAL` 范围: -- 对 `SESSION` 作用域变量的更改,设置后**只影响当前会话**。 -- 对 `GLOBAL` 作用域变量的更改,设置后立即生效。如果该变量也有 `SESSION` 作用域,已经连接的所有会话 (包括当前会话) 将继续使用会话当前的 `SESSION` 变量值。 -- 要设置变量值,可使用 [`SET` 语句](/sql-statements/sql-statement-set-variable.md)。 +- 在 `SESSION` 范围内的更改只会影响当前会话。 +- 在 `GLOBAL` 范围内的更改会立即生效。如果此变量也是 `SESSION` 范围的,则所有会话(包括您的会话)将继续使用其当前的会话值。 +- 使用 [`SET` 语句](/sql-statements/sql-statement-set-variable.md) 进行更改: ```sql -# 以下两个语句等价地改变一个 Session 变量 +# 这两个相同的语句更改会话变量 SET tidb_distsql_scan_concurrency = 10; SET SESSION tidb_distsql_scan_concurrency = 10; -# 以下两个语句等价地改变一个 Global 变量 +# 这两个相同的语句更改全局变量 SET @@global.tidb_distsql_scan_concurrency = 10; SET GLOBAL tidb_distsql_scan_concurrency = 10; ``` > **注意:** > -> 部分 `GLOBAL` 作用域的变量会持久化到 TiDB 集群中。文档中的变量有一个“是否持久化到集群”的说明,可以为“是”或者“否”。 +> 几个 `GLOBAL` 变量会持久化到 TiDB 集群。本文档中的某些变量具有“持久化到集群”设置,可以配置为“是”或“否”。 > -> - 对于持久化到集群的变量,当该全局变量被修改后,会通知所有 TiDB 服务器刷新其系统变量缓存。在集群中增加一个新的 TiDB 服务器时,或者重启现存的 TiDB 服务器时,都将自动使用该持久化变量。 -> - 对于不持久化到集群的变量,对变量的修改只对当前连接的 TiDB 实例生效。如果需要保留设置过的值,需要在 `tidb.toml` 配置文件中声明。 +> - 对于“持久化到集群:是”的变量,当全局变量更改时,会向所有 TiDB 服务器发送通知以刷新其系统变量缓存。当您添加其他 TiDB 服务器或重新启动现有 TiDB 服务器时,将自动使用持久化的配置值。 +> - 对于“持久化到集群:否”的变量,更改仅适用于您连接到的本地 TiDB 实例。要保留任何设置的值,您需要在 `tidb.toml` 配置文件中指定这些变量。 > -> 此外,由于应用和连接器通常需要读取 MySQL 变量,为了兼容这一需求,在 TiDB 中,部分 MySQL 的变量既可读取也可设置。例如,尽管 JDBC 连接器不依赖于查询缓存 (query cache) 的行为,但仍然可以读取和设置查询缓存。 +> 此外,TiDB 将几个 MySQL 变量显示为可读和可设置。这是兼容性所必需的,因为应用程序和连接器通常会读取 MySQL 变量。例如,JDBC 连接器会读取和设置查询缓存设置,尽管不依赖于该行为。 > **注意:** > -> 变量取较大值并不总会带来更好的性能。由于大部分变量对单个连接生效,设置变量时,还应考虑正在执行语句的并发连接数量。 +> 较大的值并不总是能带来更好的性能。同样重要的是要考虑执行语句的并发连接数,因为大多数设置都适用于每个连接。 > -> 确定安全值时,应考虑变量的单位: +> 在确定安全值时,请考虑变量的单位: > -> * 如果单位为线程,安全值通常取决于 CPU 核的数量。 -> * 如果单位为字节,安全值通常小于系统内存的总量。 -> * 如果单位为时间,单位可能为秒或毫秒。 +> * 对于线程,安全值通常最多为 CPU 核心数。 +> * 对于字节,安全值通常小于系统内存量。 +> * 对于时间,请注意单位可能是秒或毫秒。 > -> 单位相同的多个变量可能会争夺同一组资源。 +> 使用相同单位的变量可能会争用同一组资源。 -从 v7.4.0 开始,部分 `SESSION` 作用域的变量可以通过 [`SET_VAR`](/optimizer-hints.md#set_varvar_namevar_value) Hint 在语句执行期间临时修改变量的值。当语句执行完成后,系统变量将在当前会话中自动恢复为原始值。通过这个 Hint 可以修改一部分与优化器、执行器相关的系统变量行为。文档中的变量有一个“是否受 Hint [`SET_VAR`](/optimizer-hints.md#set_varvar_namevar_value) 控制”的说明,可以为“是”或者“否”。 +从 v7.4.0 开始,您可以使用 [`SET_VAR`](/optimizer-hints.md#set_varvar_namevar_value) 在语句执行期间临时修改某些 `SESSION` 变量的值。语句执行完毕后,当前会话中系统变量的值会自动更改回原始值。此 hint 可用于修改一些与优化器和执行器相关的系统变量。本文档中的变量具有“适用于 hint SET_VAR”设置,可以配置为“是”或“否”。 -- 对于受 Hint SET_VAR 控制的变量,你可以在语句中使用 `/*+ SET_VAR(...) */` 修改语句执行期间变量的值。 -- 对于不受 Hint SET_VAR 控制的变量,你不能在语句中使用 `/*+ SET_VAR(...) */` 修改语句执行期间变量的值。 +- 对于“适用于 hint SET_VAR:是”的变量,您可以使用 [`SET_VAR`](/optimizer-hints.md#set_varvar_namevar_value) hint 在语句执行期间修改当前会话中系统变量的值。 +- 对于“适用于 hint SET_VAR:否”的变量,您不能使用 [`SET_VAR`](/optimizer-hints.md#set_varvar_namevar_value) hint 在语句执行期间修改当前会话中系统变量的值。 -关于 SET_VAR Hint 的更多说明,参考 [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value)。 +有关 `SET_VAR` hint 的更多信息,请参阅 [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value)。 ## 变量参考 -### `allow_auto_random_explicit_insert` 从 v4.0.3 版本开始引入 +### allow_auto_random_explicit_insert v4.0.3 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔 - 默认值:`OFF` -- 是否允许在 `INSERT` 语句中显式指定含有 `AUTO_RANDOM` 属性的列的值。 +- 确定是否允许在 `INSERT` 语句中显式指定具有 `AUTO_RANDOM` 属性的列的值。 -### `authentication_ldap_sasl_auth_method_name` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_auth_method_name v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:枚举 - 默认值:`SCRAM-SHA-1` -- 可选值:`SCRAM-SHA-1`、`SCRAM-SHA-256`、`GSSAPI` -- LDAP SASL 身份验证中,验证方法的名称。 - -### `authentication_ldap_sasl_bind_base_dn` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 默认值:"" -- LDAP SASL 身份验证中,搜索用户的范围。如果创建用户时没有通过 `AS ...` 指定 `dn`,TiDB 会自动在 LDAP Server 的该范围中根据用户名搜索用户 `dn`。例如 `dc=example,dc=org`。 - -### `authentication_ldap_sasl_bind_root_dn` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 默认值:"" -- LDAP SASL 身份验证中,TiDB 登录 LDAP Server 搜索用户时使用的 `dn`。 - -### `authentication_ldap_sasl_bind_root_pwd` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 默认值:"" -- LDAP SASL 身份验证中,TiDB 登录 LDAP Server 搜索用户时使用的密码。 - -### `authentication_ldap_sasl_ca_path` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 默认值:"" -- LDAP SASL 身份验证中,TiDB 对 StartTLS 连接使用的 CA 证书的路径。 - -### `authentication_ldap_sasl_init_pool_size` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`10` -- 范围:`[1, 32767]` -- LDAP SASL 身份验证中,TiDB 与 LDAP Server 间连接池的初始连接数。 - -### `authentication_ldap_sasl_max_pool_size` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`1000` -- 范围:`[1, 32767]` -- LDAP SASL 身份验证中,TiDB 与 LDAP Server 间连接池的最大连接数。 - -### `authentication_ldap_sasl_server_host` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 默认值:"" -- LDAP SASL 身份验证中,LDAP Server 的主机名或地址。 - -### `authentication_ldap_sasl_server_port` 从 v7.1.0 版本开始引入 +- 可能的值:`SCRAM-SHA-1`、`SCRAM-SHA-256` 和 `GSSAPI`。 +- 对于 LDAP SASL 身份验证,此变量指定身份验证方法名称。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`389` -- 范围:`[1, 65535]` -- LDAP SASL 身份验证中,LDAP Server 的 TCP/IP 端口号。 - -### `authentication_ldap_sasl_tls` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- LDAP SASL 身份验证中,是否使用 StartTLS 对连接加密。 - -### `authentication_ldap_simple_auth_method_name` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 -- 默认值:`SIMPLE` -- 可选值:`SIMPLE` -- LDAP simple 身份验证中,验证方法的名称。现在仅支持 `SIMPLE`。 +### authentication_ldap_sasl_bind_base_dn v7.1.0 新增 -### `authentication_ldap_simple_bind_base_dn` 从 v7.1.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:字符串 - 默认值:"" -- LDAP simple 身份验证中,搜索用户的范围。如果创建用户时没有通过 `AS ...` 指定 `dn`,TiDB 会自动在 LDAP Server 的该范围中根据用户名搜索用户 `dn`。例如 `dc=example,dc=org`。 +- 对于 LDAP SASL 身份验证,此变量限制搜索树内的搜索范围。如果创建用户时没有 `AS ...` 子句,TiDB 将根据用户名自动在 LDAP 服务器中搜索 `dn`。 -### `authentication_ldap_simple_bind_root_dn` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_bind_root_dn v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:字符串 - 默认值:"" -- LDAP simple 身份验证中,TiDB 登录 LDAP Server 搜索用户时使用的 `dn`。 +- 对于 LDAP SASL 身份验证,此变量指定用于登录到 LDAP 服务器以搜索用户的 `dn`。 -### `authentication_ldap_simple_bind_root_pwd` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_bind_root_pwd v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:字符串 - 默认值:"" -- LDAP simple 身份验证中,TiDB 登录 LDAP Server 搜索用户时使用的密码。 +- 对于 LDAP SASL 身份验证,此变量指定用于登录到 LDAP 服务器以搜索用户的密码。 -### `authentication_ldap_simple_ca_path` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_ca_path v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:字符串 - 默认值:"" -- LDAP simple 身份验证中,TiDB 对 StartTLS 连接使用的 CA 证书的路径。 +- 对于 LDAP SASL 身份验证,此变量指定 StartTLS 连接的证书颁发机构文件的绝对路径。 -### `authentication_ldap_simple_init_pool_size` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_init_pool_size v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`10` - 范围:`[1, 32767]` -- LDAP simple 身份验证中,TiDB 与 LDAP Server 间连接池的初始连接数。 +- 对于 LDAP SASL 身份验证,此变量指定 LDAP 服务器连接池中的初始连接数。 -### `authentication_ldap_simple_max_pool_size` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_max_pool_size v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`1000` - 范围:`[1, 32767]` -- LDAP simple 身份验证中,TiDB 与 LDAP Server 间连接池的最大连接数。 +- 对于 LDAP SASL 身份验证,此变量指定 LDAP 服务器连接池中的最大连接数。 -### `authentication_ldap_simple_server_host` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_server_host v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:字符串 - 默认值:"" -- LDAP simple 身份验证中,LDAP Server 的主机名或地址。 +- 对于 LDAP SASL 身份验证,此变量指定 LDAP 服务器主机名或 IP 地址。 -### `authentication_ldap_simple_server_port` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_server_port v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`389` - 范围:`[1, 65535]` -- LDAP simple 身份验证中,LDAP Server 的 TCP/IP 端口号。 +- 对于 LDAP SASL 身份验证,此变量指定 LDAP 服务器的 TCP/IP 端口号。 -### `authentication_ldap_simple_tls` 从 v7.1.0 版本开始引入 +### authentication_ldap_sasl_tls v7.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔 - 默认值:`OFF` -- LDAP simple 身份验证中,是否使用 StartTLS 对连接加密。 +- 对于 LDAP SASL 身份验证,此变量控制插件与 LDAP 服务器的连接是否受 StartTLS 保护。 + +### authentication_ldap_simple_auth_method_name v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 枚举 +- 默认值: `SIMPLE` +- 可选值: `SIMPLE`。 +- 对于 LDAP 简单认证,此变量指定认证方法名称。唯一支持的值是 `SIMPLE`。 + +### authentication_ldap_simple_bind_base_dn v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 字符串 +- 默认值: "" +- 对于 LDAP 简单认证,此变量限制搜索树内的搜索范围。如果用户创建时没有使用 `AS ...` 子句,TiDB 将根据用户名自动在 LDAP 服务器中搜索 `dn`。 + +### authentication_ldap_simple_bind_root_dn v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 字符串 +- 默认值: "" +- 对于 LDAP 简单认证,此变量指定用于登录 LDAP 服务器以搜索用户的 `dn`。 + +### authentication_ldap_simple_bind_root_pwd v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 字符串 +- 默认值: "" +- 对于 LDAP 简单认证,此变量指定用于登录 LDAP 服务器以搜索用户的密码。 + +### authentication_ldap_simple_ca_path v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 字符串 +- 默认值: "" +- 对于 LDAP 简单认证,此变量指定 StartTLS 连接的证书颁发机构文件的绝对路径。 + +### authentication_ldap_simple_init_pool_size v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 整数 +- 默认值: `10` +- 范围: `[1, 32767]` +- 对于 LDAP 简单认证,此变量指定到 LDAP 服务器的连接池中的初始连接数。 + +### authentication_ldap_simple_max_pool_size v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 整数 +- 默认值: `1000` +- 范围: `[1, 32767]` +- 对于 LDAP 简单认证,此变量指定到 LDAP 服务器的连接池中的最大连接数。 + +### authentication_ldap_simple_server_host v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 字符串 +- 默认值: "" +- 对于 LDAP 简单认证,此变量指定 LDAP 服务器主机名或 IP 地址。 + +### authentication_ldap_simple_server_port v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 整数 +- 默认值: `389` +- 范围: `[1, 65535]` +- 对于 LDAP 简单认证,此变量指定 LDAP 服务器的 TCP/IP 端口号。 + +### authentication_ldap_simple_tls v7.1.0 新增 + +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 布尔值 +- 默认值: `OFF` +- 对于 LDAP 简单认证,此变量控制插件到 LDAP 服务器的连接是否受 StartTLS 保护。 + +### auto_increment_increment -### `auto_increment_increment` - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`1` -- 范围:`[1, 65535]` -- 控制 `AUTO_INCREMENT` 自增值字段的自增步长和 `AUTO_RANDOM` ID 的分配规则。该变量常与 [`auto_increment_offset`](#auto_increment_offset) 一起使用。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 整数 +- 默认值: `1` +- 范围: `[1, 65535]` +- 控制分配给列的 `AUTO_INCREMENT` 值的步长,以及 `AUTO_RANDOM` ID 的分配规则。通常与 [`auto_increment_offset`](#auto_increment_offset) 结合使用。 -### `auto_increment_offset` +### auto_increment_offset -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`1` -- 范围:`[1, 65535]` -- 控制 `AUTO_INCREMENT` 自增值字段的初始值和 `AUTO_RANDOM` ID 的分配规则。该变量常与 [`auto_increment_increment`](#auto_increment_increment) 一起使用。示例如下: +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 整数 +- 默认值: `1` +- 范围: `[1, 65535]` +- 控制分配给列的 `AUTO_INCREMENT` 值的初始偏移量,以及 `AUTO_RANDOM` ID 的分配规则。此设置通常与 [`auto_increment_increment`](#auto_increment_increment) 结合使用。例如: ```sql mysql> CREATE TABLE t1 (a int not null primary key auto_increment); @@ -294,352 +294,474 @@ mysql> SELECT * FROM t1; 4 rows in set (0.00 sec) ``` -### `autocommit` +### autocommit -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON` -- 用于设置在非显式事务时是否自动提交事务。更多信息,请参见[事务概述](/transaction-overview.md#自动提交)。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 布尔值 +- 默认值: `ON` +- 控制语句在没有显式事务时是否应自动提交。有关更多信息,请参见 [事务概述](/transaction-overview.md#autocommit)。 -### `block_encryption_mode` +### block_encryption_mode -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 -- 默认值:`aes-128-ecb` -- 可选值:`aes-128-ecb`、`aes-192-ecb`、`aes-256-ecb`、`aes-128-cbc`、`aes-192-cbc`、`aes-256-cbc`、`aes-128-ofb`、`aes-192-ofb`、`aes-256-ofb`、`aes-128-cfb`、`aes-192-cfb`、`aes-256-cfb` -- 该变量用于设置 [`AES_ENCRYPT()`](/functions-and-operators/encryption-and-compression-functions.md#aes_encrypt) 和 [`AES_DECRYPT()`](/functions-and-operators/encryption-and-compression-functions.md#aes_decrypt) 函数的加密模式。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: 枚举 +- 默认值: `aes-128-ecb` +- 值选项: `aes-128-ecb`, `aes-192-ecb`, `aes-256-ecb`, `aes-128-cbc`, `aes-192-cbc`, `aes-256-cbc`, `aes-128-ofb`, `aes-192-ofb`, `aes-256-ofb`, `aes-128-cfb`, `aes-192-cfb`, `aes-256-cfb` +- 此变量设置内置函数 [`AES_ENCRYPT()`](/functions-and-operators/encryption-and-compression-functions.md#aes_encrypt) 和 [`AES_DECRYPT()`](/functions-and-operators/encryption-and-compression-functions.md#aes_decrypt) 的加密模式。 -### `character_set_client` +### character_set_client -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`utf8mb4` -- 这个变量表示从客户端发出的数据所用的字符集。有关更多 TiDB 支持的字符集和排序规则,参阅[字符集和排序规则](/character-set-and-collation.md)文档。如果需要更改字符集,建议使用 [`SET NAMES`](/sql-statements/sql-statement-set-names.md) 语句。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 默认值: `utf8mb4` +- 从客户端发送的数据的字符集。有关在 TiDB 中使用字符集和排序规则的详细信息,请参见 [字符集和排序规则](/character-set-and-collation.md)。建议使用 [`SET NAMES`](/sql-statements/sql-statement-set-names.md) 在需要时更改字符集。 -### `character_set_connection` +### character_set_connection -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`utf8mb4` -- 若没有为字符串常量指定字符集,该变量表示这些字符串常量所使用的字符集。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 默认值: `utf8mb4` +- 没有指定字符集的字符串文字的字符集。 -### `character_set_database` +### character_set_database -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`utf8mb4` -- 该变量表示当前默认在用数据库的字符集,**不建议设置该变量**。选择新的默认数据库后,服务器会更改该变量的值。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 默认值: `utf8mb4` +- 此变量指示正在使用的默认数据库的字符集。**不建议设置此变量**。当选择新的默认数据库时,服务器会更改变量值。 -### `character_set_results` +### character_set_results -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`utf8mb4` -- 该变量表示数据发送至客户端时所使用的字符集。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 默认值: `utf8mb4` +- 将数据发送到客户端时使用的字符集。 -### `character_set_server` +### character_set_server -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`utf8mb4` -- 当 `CREATE SCHEMA` 中没有指定字符集时,该变量表示这些新建的表结构所使用的字符集。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 默认值: `utf8mb4` +- 服务器的默认字符集。 -### `collation_connection` +### collation_connection - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`utf8mb4_bin` -- 该变量表示连接中所使用的排序规则。与 MySQL 中的 `collation_connection` 一致。 +- 此变量指示当前连接中使用的排序规则。它与 MySQL 变量 `collation_connection` 一致。 -### `collation_database` +### collation_database - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`utf8mb4_bin` -- 该变量表示当前数据库默认所使用的排序规则。与 MySQL 中的 `collation_database` 一致。**不建议设置此变量**,当前使用的数据库变动时,此变量会被 TiDB 修改。 +- 此变量指示正在使用的数据库的默认排序规则。**不建议设置此变量**。当选择一个新的数据库时,TiDB 会更改此变量的值。 -### `collation_server` +### collation_server - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`utf8mb4_bin` -- 该变量表示创建数据库时默认的排序规则。 +- 创建数据库时使用的默认排序规则。 -### `cte_max_recursion_depth` +### cte_max_recursion_depth - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:整数 - 默认值:`1000` - 范围:`[0, 4294967295]` -- 这个变量用于控制公共表表达式的最大递归深度。 +- 控制公共表表达式中的最大递归深度。 + +### datadir + +> **注意:** +> +> 此变量在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 上不受支持。 -### `datadir` + - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:使用的组件和部署方式不同,默认值也不同。 - - `/tmp/tidb`:如果你将 [`--store`](/command-line-flags-for-tidb-configuration.md#--store) 设置为 `"unistore"` 或没有设置 `--store`,则默认值为 `/tmp/tidb`。 - - `${pd-ip}:${pd-port}`:如果你设置的存储引擎是 TiKV(如果使用 TiUP 和 TiDB Operator 部署,则默认的存储引擎为 TiKV),则默认值为 `${pd-ip}:${pd-port}`。 -- 这个变量表示数据存储的位置,位置可以是本地路径 `/tmp/tidb`。如果数据存储在 TiKV 上,则可以是指向 PD 服务器的路径。变量值的格式为 `${pd-ip}:${pd-port}`,表示 TiDB 在启动时连接到的 PD 服务器。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:取决于组件和部署方法。 + - `/tmp/tidb`:当你为 [`--store`](/command-line-flags-for-tidb-configuration.md#--store) 设置 `"unistore"` 时,或者如果你不设置 `--store`。 + - `${pd-ip}:${pd-port}`:当你使用 TiKV 时,这是 TiUP 和 Kubernetes 部署的 TiDB Operator 的默认存储引擎。 +- 此变量指示数据存储的位置。此位置可以是本地路径 `/tmp/tidb`,或者如果数据存储在 TiKV 上,则指向 PD 服务器。`${pd-ip}:${pd-port}` 格式的值表示 TiDB 启动时连接到的 PD 服务器。 -### `ddl_slow_threshold` + + + + +- 作用域:NONE +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:取决于组件和部署方法。 + - `/tmp/tidb`:当你为 [`--store`](https://docs.pingcap.com/tidb/stable/command-line-flags-for-tidb-configuration#--store) 设置 `"unistore"` 时,或者如果你不设置 `--store`。 + - `${pd-ip}:${pd-port}`:当你使用 TiKV 时,这是 TiUP 和 Kubernetes 部署的 TiDB Operator 的默认存储引擎。 +- 此变量指示数据存储的位置。此位置可以是本地路径 `/tmp/tidb`,或者如果数据存储在 TiKV 上,则指向 PD 服务器。`${pd-ip}:${pd-port}` 格式的值表示 TiDB 启动时连接到的 PD 服务器。 + + + +### ddl_slow_threshold + + + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + + - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否持久化到集群:否,仅适用于你当前连接的 TiDB 实例。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`300` -- 取值范围:`[0, 2147483647]` +- 范围:`[0, 2147483647]` - 单位:毫秒 -- 耗时超过该阈值的 DDL 操作会被输出到日志。 +- 记录执行时间超过阈值的 DDL 操作。 -### `default_authentication_plugin` +### default_authentication_plugin - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:枚举 - 默认值:`mysql_native_password` -- 可选值:`mysql_native_password`,`caching_sha2_password`,`tidb_sm3_password`,`tidb_auth_token`,`authentication_ldap_sasl` 或 `authentication_ldap_simple`。 -- 服务器和客户端建立连接时,这个变量用于设置服务器对外通告的默认身份验证方式。如要了解该变量的其他可选值,参见[可用的身份验证插件](/security-compatibility-with-mysql.md#可用的身份验证插件)。 -- 若要在用户登录时使用 `tidb_sm3_password` 插件,需要使用 [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3) 进行连接。 +- 可能的值:`mysql_native_password`、`caching_sha2_password`、`tidb_sm3_password`、`tidb_auth_token`、`authentication_ldap_sasl` 和 `authentication_ldap_simple`。 +- 此变量设置服务器在建立服务器-客户端连接时声明的身份验证方法。 +- 要使用 `tidb_sm3_password` 方法进行身份验证,你可以使用 [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3) 连接到 TiDB。 + + -### `default_collation_for_utf8mb4` 从 v7.4.0 版本开始引入 +有关此变量的更多可能值,请参阅 [身份验证插件状态](/security-compatibility-with-mysql.md#authentication-plugin-status)。 + + + +### default_collation_for_utf8mb4 v7.4.0 新增 - 作用域:GLOBAL | SESSION - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:字符串 - 默认值:`utf8mb4_bin` - 可选值:`utf8mb4_bin`、`utf8mb4_general_ci`、`utf8mb4_0900_ai_ci` -- 该变量用于设置 utf8mb4 字符集的默认[排序规则](/character-set-and-collation.md)。它会影响以下语句的行为: - - [`SHOW COLLATION`](/sql-statements/sql-statement-show-collation.md) 和 [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) 语句显示的默认排序规则。 - - [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 和 [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md) 语句中对表或列使用 `CHARACTER SET` 语法明确指定 utf8mb4 字符集而未指定排序规则时,将使用该变量指定的排序规则。不影响未使用 `CHARACTER SET` 语法时的行为。 - - [`CREATE DATABASE`](/sql-statements/sql-statement-create-database.md) 和 [`ALTER DATABASE`](/sql-statements/sql-statement-alter-database.md) 语句中使用 `CHARACTER SET` 语法明确指定 utf8mb4 字符集而未指定排序规则时,将使用该变量指定的排序规则。不影响未使用 `CHARACTER SET` 语法时的行为。 - - 任何使用 `_utf8mb4'string'` 形式的字面量在未使用 `COLLATE` 语法指定排序规则时,将使用该变量指定的排序规则。 +- 此变量用于设置 `utf8mb4` 字符集的默认[排序规则](/character-set-and-collation.md)。它会影响以下语句的行为: + - [`SHOW COLLATION`](/sql-statements/sql-statement-show-collation.md) 和 [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) 语句中显示的默认排序规则。 + - 如果 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 和 [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md) 语句包含针对表或列的 `CHARACTER SET utf8mb4` 子句,但未指定排序规则,则使用此变量指定的排序规则。这不会影响不使用 `CHARACTER SET` 子句时的行为。 + - 如果 [`CREATE DATABASE`](/sql-statements/sql-statement-create-database.md) 和 [`ALTER DATABASE`](/sql-statements/sql-statement-alter-database.md) 语句包含 `CHARACTER SET utf8mb4` 子句,但未指定排序规则,则使用此变量指定的排序规则。这不会影响不使用 `CHARACTER SET` 子句时的行为。 + - 如果未使用 `COLLATE` 子句,则任何 `_utf8mb4'string'` 格式的文字字符串都使用此变量指定的排序规则。 -### `default_password_lifetime` 从 v6.5.0 版本开始引入 +### default_password_lifetime v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`0` -- 取值范围:`[0, 65535]` -- 该变量用于设置全局自动密码过期策略,默认值为 `0`,即禁用全局自动密码过期。如果设置该变量的值为正整数 N,则表示允许的密码生存期为 N,即必须在 N 天之内更改密码。 +- 范围:`[0, 65535]` +- 设置自动密码过期的全局策略。默认值 `0` 表示密码永不过期。如果此系统变量设置为正整数 `N`,则表示密码有效期为 `N` 天,你必须在 `N` 天内更改密码。 -### `default_week_format` +### default_week_format - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`0` -- 取值范围:`[0, 7]` -- 设置 `WEEK()` 函数使用的周格式。 +- 范围:`[0, 7]` +- 设置 `WEEK()` 函数使用的星期格式。 -### `disconnect_on_expired_password` 从 v6.5.0 版本开始引入 +### disconnect_on_expired_password v6.5.0 新增 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`ON` -- 该变量是一个只读变量,用来显示 TiDB 是否会直接断开密码已过期用户的连接。当其值为 `ON`,表示 TiDB 会断开密码已过期用户的连接。当其值为 `OFF`,表示 TiDB 会将密码已过期用户的连接置于“沙盒模式”,允许该用户建立连接并执行密码重置操作。 -- 如果需要改变 TiDB 对密码已过期用户连接的处理方式,请在 TiDB 配置文件中的 `[security]` 部分修改 [`disconnect-on-expired-password`](/tidb-configuration-file.md#disconnect-on-expired-password-从-v650-版本开始引入) 选项。 +- 此变量是只读的。它指示当密码过期时,TiDB 是否断开客户端连接。如果变量设置为 `ON`,则当密码过期时,客户端连接将断开。如果变量设置为 `OFF`,则客户端连接将限制为“沙盒模式”,并且用户只能执行密码重置操作。 -### `div_precision_increment` 从 v8.0.0 版本开始引入 + + +- 如果你需要更改过期密码的客户端连接的行为,请修改配置文件中的 [`security.disconnect-on-expired-password`](/tidb-configuration-file.md#disconnect-on-expired-password-new-in-v650) 配置项。 + + + + + +- 如果你需要更改过期密码的客户端连接的默认行为,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + + + +### div_precision_increment v8.0.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`4` -- 范围:`[0, 30]` -- 这个变量用于控制使用运算符 `/` 执行除法操作时,结果增加的小数位数。该功能与 MySQL 保持一致。 +- 取值范围:`[0, 30]` +- 该变量指定使用 `/` 运算符执行除法运算时,结果的小数位数增加的位数。该变量与 MySQL 相同。 -### `error_count` +### error_count - 作用域:SESSION +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 表示上一条生成消息的 SQL 语句中的错误数。该变量为只读变量。 +- 一个只读变量,指示生成消息的最后一个语句产生的错误数。 -### `foreign_key_checks` +### foreign_key_checks - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:在 v6.6.0 之前版本中为 `OFF`,在 v6.6.0 及之后的版本中为 `ON`。 -- 表示是否开启外键约束检查。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:v6.6.0 之前,默认值为 `OFF`。从 v6.6.0 开始,默认值为 `ON`。 +- 该变量控制是否启用外键约束检查。 -### `group_concat_max_len` +### group_concat_max_len - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1024` - 取值范围:`[4, 18446744073709551615]` -- 表示 `GROUP_CONCAT()` 函数缓冲区的最大长度。 +- `GROUP_CONCAT()` 函数中项目的最大缓冲区大小。 -### `have_openssl` +### have_openssl - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`DISABLED` - 用于 MySQL 兼容性的只读变量。当服务器启用 TLS 时,服务器将其设置为 `YES`。 -### `have_ssl` +### have_ssl - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`DISABLED` - 用于 MySQL 兼容性的只读变量。当服务器启用 TLS 时,服务器将其设置为 `YES`。 -### `hostname` +### hostname - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:(系统主机名) -- 这个变量为只读变量,表示 TiDB server 的主机名。 +- TiDB 服务器的主机名,作为只读变量。 -### `identity` 从 v5.3.0 版本开始引入 +### identity v5.3.0 新增 -- 该变量为变量 [`last_insert_id`](#last_insert_id-从-v530-版本开始引入) 的别名。 +该变量是 [`last_insert_id`](#last_insert_id) 的别名。 -### `init_connect` +### init_connect - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 用户首次连接到 TiDB 服务器时,`init_connect` 特性允许 TiDB 自动执行一条或多条 SQL 语句。如果你有 `CONNECTION_ADMIN` 或者 `SUPER` 权限,这些 SQL 语句将不会被自动执行。如果这些语句执行报错,你的用户连接将被终止。 +- `init_connect` 功能允许在首次连接到 TiDB 服务器时自动执行 SQL 语句。如果您具有 `CONNECTION_ADMIN` 或 `SUPER` 权限,则不会执行此 `init_connect` 语句。如果 `init_connect` 语句导致错误,您的用户连接将被终止。 -### `innodb_lock_wait_timeout` +### innodb_lock_wait_timeout - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`50` -- 范围:`[1, 3600]` +- 取值范围:`[1, 3600]` - 单位:秒 -- 悲观事务语句等锁时间。 +- 悲观事务的锁等待超时时间(默认)。 + +### interactive_timeout -### `interactive_timeout` +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`28800` -- 范围:`[1, 31536000]` +- 取值范围:`[1, 31536000]` - 单位:秒 -- 该变量表示交互式用户会话的空闲超时。交互式用户会话是指使用 `CLIENT_INTERACTIVE` 选项调用 [`mysql_real_connect()`](https://dev.mysql.com/doc/c-api/5.7/en/mysql-real-connect.html) API 建立的会话(例如:MySQL shell 和 MySQL client)。该变量与 MySQL 完全兼容。 +- 此变量表示交互式用户会话的空闲超时时间。交互式用户会话是指通过使用 `CLIENT_INTERACTIVE` 选项调用 [`mysql_real_connect()`](https://dev.mysql.com/doc/c-api/5.7/en/mysql-real-connect.html) API 建立的会话(例如,MySQL Shell 和 MySQL Client)。此变量与 MySQL 完全兼容。 -### `last_insert_id` 从 v5.3.0 版本开始引入 +### last_insert_id - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` - 取值范围:`[0, 18446744073709551615]` -- 返回由 `INSERT` 语句产生的最新 `AUTO_INSCRENT` 或者 `AUTO_RANDOM` 值,与 `LAST_INSERT_ID()` 的返回的结果相同。与 MySQL 中的 `last_insert_id` 一致。 +- 此变量返回由 insert 语句生成的最后一个 `AUTO_INCREMENT` 或 `AUTO_RANDOM` 值。 +- `last_insert_id` 的值与函数 `LAST_INSERT_ID()` 返回的值相同。 -### `last_plan_from_binding` 从 v4.0 版本开始引入 +### last_plan_from_binding v4.0 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量用来显示上一条执行的语句所使用的执行计划是否来自 binding 的[执行计划](/sql-plan-management.md)。 +- 此变量用于显示先前语句中使用的执行计划是否受到 [计划绑定](/sql-plan-management.md) 的影响。 -### `last_plan_from_cache` 从 v4.0 版本开始引入 +### last_plan_from_cache v4.0 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来显示上一个 `execute` 语句所使用的执行计划是不是直接从 plan cache 中取出来的。 +- 此变量用于显示先前 `execute` 语句中使用的执行计划是否直接从计划缓存中获取。 -### `last_sql_use_alloc` 从 v6.4.0 版本开始引入 +### last_sql_use_alloc v6.4.0 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`OFF` -- 这个变量是一个只读变量,用来显示上一个语句是否使用了缓存的 Chunk 对象 (Chunk allocation)。 +- 此变量是只读的。它用于显示先前的语句是否使用了缓存的 chunk 对象(chunk 分配)。 -### `license` +### license - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`Apache License 2.0` -- 这个变量表示 TiDB 服务器的安装许可证。 +- 此变量指示 TiDB 服务器安装的许可证。 -### `log_bin` +### log_bin - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量表示是否使用 [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md)。 +- 此变量指示是否使用 [TiDB Binlog](https://docs.pingcap.com/tidb/stable/tidb-binlog-overview)。 + +### max_allowed_packet v6.1.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 + +- 作用域:SESSION | GLOBAL +- 是否持久化到集群:是 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`67108864` +- 取值范围:`[1024, 1073741824]` +- 该值应为 1024 的整数倍。如果该值不能被 1024 整除,则会提示警告,并且该值将被向下舍入。例如,当该值设置为 1025 时,TiDB 中的实际值为 1024。 +- 服务器和客户端在一次数据包传输中允许的最大数据包大小。 +- 在 `SESSION` 作用域中,此变量是只读的。 +- 此变量与 MySQL 兼容。 -### `max_connections` +### password_history v6.5.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否持久化到集群:是 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` -- 取值范围:`[0, 100000]` -- 该变量表示 TiDB 中同时允许的最大客户端连接数,用于资源控制。 -- 默认情况下,该变量值为 `0` 表示不限制客户端连接数。当本变量的值大于 `0` 且客户端连接数到达此值时,TiDB 服务端将会拒绝新的客户端连接。 +- 取值范围:`[0, 4294967295]` +- 此变量用于建立密码重用策略,允许 TiDB 根据密码更改的次数限制密码重用。默认值 `0` 表示禁用基于密码更改次数的密码重用策略。当此变量设置为正整数 `N` 时,不允许重用最近 `N` 个密码。 -### `max_execution_time` +### mpp_exchange_compression_mode v6.6.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 默认值:`UNSPECIFIED` +- 取值选项:`NONE`,`FAST`,`HIGH_COMPRESSION`,`UNSPECIFIED` +- 此变量用于指定 MPP Exchange 算子的数据压缩模式。当 TiDB 选择版本号为 `1` 的 MPP 执行计划时,此变量生效。变量值的含义如下: + - `UNSPECIFIED`:表示未指定。TiDB 将自动选择压缩模式。目前,TiDB 自动选择 `FAST` 模式。 + - `NONE`:不使用数据压缩。 + - `FAST`:快速模式。整体性能良好,压缩率低于 `HIGH_COMPRESSION`。 +- `HIGH_COMPRESSION`: 高压缩比模式。 + +### mpp_version v6.6.0 新增 + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 默认值:`UNSPECIFIED` +- 可选值:`UNSPECIFIED`,`0`,`1`,`2` +- 此变量用于指定 MPP 执行计划的不同版本。指定版本后,TiDB 会选择指定版本的 MPP 执行计划。变量值的含义如下: + - `UNSPECIFIED`: 表示未指定。TiDB 自动选择最新版本 `2`。 + - `0`: 兼容所有 TiDB 集群版本。MPP 版本大于 `0` 的功能在此模式下不生效。 + - `1`: v6.6.0 新增,用于启用 TiFlash 上带压缩的数据交换。有关详细信息,请参阅 [MPP 版本和交换数据压缩](/explain-mpp.md#mpp-version-and-exchange-data-compression)。 + - `2`: v7.3.0 新增,用于在 MPP 任务在 TiFlash 上遇到错误时提供更准确的错误消息。 + +### password_reuse_interval v6.5.0 新增 + +- 作用域:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`0` +- 范围:`[0, 4294967295]` +- 此变量用于建立密码重用策略,允许 TiDB 基于经过的时间限制密码重用。默认值 `0` 表示禁用基于经过时间的密码重用策略。当此变量设置为正整数 `N` 时,不允许重用过去 `N` 天内使用的任何密码。 + +### max_connections + +- 作用域:GLOBAL +- 持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`0` +- 范围:`[0, 100000]` +- 单个 TiDB 实例允许的最大并发连接数。此变量可用于资源控制。 +- 默认值 `0` 表示没有限制。当此变量的值大于 `0`,并且连接数达到该值时,TiDB 服务器将拒绝来自客户端的新连接。 + +### max_execution_time + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`0` - 范围:`[0, 2147483647]` - 单位:毫秒 -- 语句最长执行时间。默认值 (0) 表示无限制。 +- 语句的最大执行时间。默认值为无限制(零)。 > **注意:** > -> - 在 v6.4.0 之前,`max_execution_time` 对所有类型的语句生效。从 v6.4.0 开始,该变量只用于控制只读语句的最大执行时长。实际精度在 100ms 级别,而非更准确的毫秒级别。 -> - 对于使用了 [`MAX_EXECUTION_TIME`](/optimizer-hints.md#max_execution_timen) Hint 的 SQL 语句,这些语句的最长执行时间将不受该变量限制,而是由该 Hint 进行限制。你也可以使用该 Hint 来创建 SQL 绑定,详情请参考 [SQL 操作常见问题](/faq/sql-faq.md#如何阻止特定的-sql-语句执行或者将某个-sql-语句加入黑名单)。 +> 在 v6.4.0 之前,`max_execution_time` 系统变量对所有类型的语句生效。从 v6.4.0 开始,此变量仅控制只读语句的最大执行时间。超时值的精度约为 100 毫秒。这意味着语句可能不会在你指定的精确毫秒数内终止。 + + + +对于带有 [`MAX_EXECUTION_TIME`](/optimizer-hints.md#max_execution_timen) hint 的 SQL 语句,此语句的最大执行时间受 hint 限制,而不是受此变量限制。该 hint 也可以与 SQL 绑定一起使用,如 [SQL FAQ](/faq/sql-faq.md#how-to-prevent-the-execution-of-a-particular-sql-statement) 中所述。 + + + + + +对于带有 [`MAX_EXECUTION_TIME`](/optimizer-hints.md#max_execution_timen) hint 的 SQL 语句,此语句的最大执行时间受 hint 限制,而不是受此变量限制。该 hint 也可以与 SQL 绑定一起使用,如 [SQL FAQ](https://docs.pingcap.com/tidb/stable/sql-faq) 中所述。 -### `max_prepared_stmt_count` + + +### max_prepared_stmt_count - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` - 范围:`[-1, 1048576]` -- 指定当前实例中 [`PREPARE`](/sql-statements/sql-statement-prepare.md) 语句的最大数量。 -- 值为 `-1` 时表示不对实例中的 `PREPARE` 语句数量进行限制。 -- 如果将变量值设为超过上限 `1048576`,则使用上限值 `1048576`: +- 指定当前 TiDB 实例中 [`PREPARE`](/sql-statements/sql-statement-prepare.md) 语句的最大数量。 +- 值 `-1` 表示当前 TiDB 实例中 `PREPARE` 语句的最大数量没有限制。 +- 如果将变量设置为超过上限 `1048576` 的值,则使用 `1048576` 代替: ```sql mysql> SET GLOBAL max_prepared_stmt_count = 1048577; @@ -662,349 +784,376 @@ mysql> SHOW GLOBAL VARIABLES LIKE 'max_prepared_stmt_count'; 1 row in set (0.00 sec) ``` -### `max_allowed_packet` 从 v6.1.0 版本开始引入 - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`67108864` -- 取值范围:`[1024, 1073741824]` -- 该变量取值应为 1024 的整数倍。若取值无法被 1024 整除,则会提示 warning 并向下取整。例如设置为 1025 时,则 TiDB 中的实际取值为 1024。 -- 服务器端和客户端在一次传送数据包的过程中所允许最大的数据包大小,单位为字节。 -- 在 `SESSION` 作用域下,该变量为只读变量。 -- 该变量的行为与 MySQL 兼容。 - -### `mpp_exchange_compression_mode` 从 v6.6.0 版本开始引入 - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 默认值:`UNSPECIFIED` -- 可选值:`NONE`,`FAST`,`HIGH_COMPRESSION`,`UNSPECIFIED` -- 该变量用于选择 MPP Exchange 算子的数据压缩模式,当 TiDB 选择版本号为 `1` 的 MPP 执行计划时生效。该变量值的含义如下: - - `UNSPECIFIED`:表示未指定,TiDB 将自动选择压缩模式,当前 TiDB 自动选择 `FAST` 模式 - - `NONE`:不使用数据压缩 - - `FAST`:快速模式,整体性能较好,压缩比小于 `HIGH_COMPRESSION` - - `HIGH_COMPRESSION`:高压缩比模式 - -### `mpp_version` 从 v6.6.0 版本开始引入 - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 默认值:`UNSPECIFIED` -- 可选值:`UNSPECIFIED`,`0`,`1`,`2` -- 该变量用于指定不同版本的 MPP 执行计划。指定后,TiDB 会选择指定版本的 MPP 执行计划。该变量值含义如下: - - `UNSPECIFIED`:表示未指定,此时 TiDB 自动选择最新版本 `2`。 - - `0`:兼容所有 TiDB 集群版本,MPP 版本大于 `0` 的新特性均不会生效。 - - `1`:从 v6.6.0 版本开始引入,用于开启 TiFlash 带压缩的数据交换,详情参见 [MPP Version 和 Exchange 数据压缩](/explain-mpp.md#mpp-version-和-exchange-数据压缩)。 - - `2`:从 v7.3.0 版本开始引入,用于确保在 TiFlash 执行出错的情况下,获取到准确的报错信息。 - -### `password_history` 从 v6.5.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`0` -- 范围:`[0, 4294967295]` -- 该变量用于建立密码重用策略,使 TiDB 基于密码更改次数限制密码的重复使用。该变量默认值为 `0`,表示禁用基于密码更改次数的密码重用策略。当设置该变量为一个正整数 N 时,表示不允许重复使用最近 N 次使用过的密码。 - -### `password_reuse_interval` 从 v6.5.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`0` -- 范围:`[0, 4294967295]` -- 该变量用于建立密码重用策略,使 TiDB 基于经过时间限制密码重复使用。该变量默认值为 0,表示禁用基于密码经过时间的密码重用策略。当设置该变量为一个正整数 N 时,表示不允许重复使用最近 N 天内使用过的密码。 - -### `pd_enable_follower_handle_region` 从 v7.6.0 版本开始引入 +### pd_enable_follower_handle_region v7.6.0 新增 > **警告:** > -> [Active PD Follower](/tune-region-performance.md#通过-active-pd-follower-提升-pd-region-信息查询服务的扩展能力) 目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> [Active PD Follower](https://docs.pingcap.com/tidb/dev/tune-region-performance#use-the-active-pd-follower-feature-to-enhance-the-scalability-of-pds-region-information-query-service) 功能是实验性的。不建议在生产环境中使用。此功能可能会更改或删除,恕不另行通知。如果发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用于控制是否开启 Active PD Follower 特性(目前该特性只适用于处理获取 Region 信息的相关请求)。当该值为 `OFF` 时,TiDB 仅从 PD leader 获取 Region 信息。当该值为 `ON` 时,TiDB 在获取 Region 信息时会将请求均匀地发送到所有 PD 节点上,因此 PD follower 也可以处理 Region 信息请求,从而减轻 PD leader 的 CPU 压力。 -- 适合开启 Active PD Follower 的场景: - - 集群 Region 数量较多,PD leader 由于处理心跳和调度任务的开销大,导致 CPU 资源紧张。 - - 集群中 TiDB 实例数量较多,Region 信息请求并发量较大,PD leader CPU 压力大。 +- 此变量控制是否启用 Active PD Follower 功能(目前仅适用于 Region 信息请求)。当值为 `OFF` 时,TiDB 仅从 PD leader 获取 Region 信息。当值为 `ON` 时,TiDB 将 Region 信息请求均匀地分配给所有 PD 服务器,PD follower 也可以处理 Region 请求,从而降低 PD leader 的 CPU 压力。 +- 启用 Active PD Follower 的场景: + * 在具有大量 Region 的集群中,由于处理心跳和调度任务的开销增加,PD leader 遇到高 CPU 压力。 + * 在具有许多 TiDB 实例的 TiDB 集群中,由于 Region 信息请求的高并发,PD leader 遇到高 CPU 压力。 + +### plugin_dir -### `plugin_dir` +> **注意:** +> +> [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 不支持此变量。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 指定加载插件的目录。 +- 指示要加载插件的目录,由命令行标志指定。 -### `plugin_load` +### plugin_load + +> **注意:** +> +> [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 不支持此变量。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 指定 TiDB 启动时加载的插件,多个插件之间用逗号(,)分隔。 +- 指示 TiDB 启动时要加载的插件。这些插件由命令行标志指定,并用逗号分隔。 -### `port` +### port - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`4000` - 范围:`[0, 65535]` -- 使用 MySQL 协议时 tidb-server 监听的端口。 +- `tidb-server` 在使用 MySQL 协议时监听的端口。 -### `rand_seed1` +### rand_seed1 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`0` - 范围:`[0, 2147483647]` -- 该变量用于为 SQL 函数 `RAND()` 中使用的随机值生成器添加种子。 -- 该变量的行为与 MySQL 兼容。 +- 此变量用于为 `RAND()` SQL 函数中使用的随机值生成器设定种子。 +- 此变量的行为与 MySQL 兼容。 -### `rand_seed2` +### rand_seed2 -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 范围:SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`0` - 范围:`[0, 2147483647]` -- 该变量用于为 SQL 函数 `RAND()` 中使用的随机值生成器添加种子。 -- 该变量的行为与 MySQL 兼容。 +- 此变量用于为 `RAND()` SQL 函数中使用的随机值生成器设定种子。 +- 此变量的行为与 MySQL 兼容。 -### `require_secure_transport` 从 v6.1.0 版本开始引入 +### require_secure_transport v6.1.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 该变量控制是否所有 TiDB 的连接都在本地 socket 上进行通信,或使用 TLS。详情见[为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md)。 -- 该变量设置为 `ON` 时,必须使用开启 TLS 的会话连接到 TiDB,防止在 TLS 配置不正确时出现锁定的情况。 -- 在 v6.1.0 之前这个开关通过 TiDB 配置文件 (`security.require-secure-transport`) 进行配置,升级到 v6.1.0 时会自动继承原有设置。 -- 从 v6.5.6、v7.1.2、v7.5.1 和 v8.0.0 起,当启用了安全增强模式 (SEM) 时,禁止将 `security.require-secure-transport` 设置为 `ON`。 +> **注意:** +> +> 目前,[TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 不支持此变量。请**勿**为 TiDB Cloud Dedicated 集群启用此变量。否则,可能会导致 SQL 客户端连接失败。此限制是一项临时控制措施,将在未来的版本中解决。 -### `skip_name_resolve` 从 v5.2.0 版本开始引入 +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 +- 默认值:对于 TiDB Self-Managed 和 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 为 `OFF`,对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 为 `ON` -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 + + +- 此变量确保所有与 TiDB 的连接要么在本地套接字上,要么使用 TLS。有关更多详细信息,请参阅[启用 TiDB 客户端和服务器之间的 TLS](/enable-tls-between-clients-and-servers.md)。 + + + + + +- 此变量确保所有与 TiDB 的连接要么在本地套接字上,要么使用 TLS。 + + + +- 将此变量设置为 `ON` 需要你从启用了 TLS 的会话连接到 TiDB。这有助于防止在 TLS 配置不正确时出现锁定情况。 +- 此设置以前是一个 `tidb.toml` 选项 (`security.require-secure-transport`),但从 TiDB v6.1.0 开始更改为系统变量。 +- 从 v6.5.6、v7.1.2、v7.5.1 和 v8.0.0 开始,当启用安全增强模式 (SEM) 时,禁止将此变量设置为 `ON`,以避免用户潜在的连接问题。 + +### skip_name_resolve v5.2.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 + +- 范围:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 该变量控制 `tidb-server` 实例是否将主机名作为连接握手的一部分来解析。 -- 当 DNS 不可靠时,可以启用该变量来提高网络性能。 +- 此变量控制 `tidb-server` 实例是否在连接握手过程中解析主机名。 +- 当 DNS 不可靠时,你可以启用此选项以提高网络性能。 > **注意:** > -> 当 `skip_name_resolve` 设置为 `ON` 时,身份信息中包含主机名的用户将无法登录服务器。例如: +> 当 `skip_name_resolve=ON` 时,身份中包含主机名的用户将无法再登录到服务器。例如: > > ```sql > CREATE USER 'appuser'@'apphost' IDENTIFIED BY 'app-password'; > ``` > -> 该示例中,建议将 `apphost` 替换为 IP 地址或通配符(`%`)。 +> 在此示例中,建议将 `apphost` 替换为 IP 地址或通配符 (`%`)。 -### `socket` +### socket -- 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:NONE +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 使用 MySQL 协议时,tidb-server 所监听的本地 unix 套接字文件。 +- `tidb-server` 在使用 MySQL 协议时监听的本地 unix 套接字文件。 -### `sql_log_bin` +### sql_log_bin -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 + +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`ON` -- 表示是否将更改写入 TiDB Binlog。 +- 指示是否将更改写入 [TiDB Binlog](https://docs.pingcap.com/tidb/stable/tidb-binlog-overview)。 > **注意:** > -> 不建议将 `sql_log_bin` 设置为全局变量,因为 TiDB 的未来版本可能只允许将其设置为会话变量。 +> 不建议将 `sql_log_bin` 设置为全局变量,因为未来版本的 TiDB 可能只允许将其设置为会话变量。 -### `sql_mode` +### sql_mode -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 默认值:`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 兼容行为。详情见 [SQL 模式](/sql-mode.md)。 +- 此变量控制许多 MySQL 兼容性行为。有关更多信息,请参阅 [SQL Mode](/sql-mode.md)。 -### `sql_require_primary_key` 从 v6.3.0 版本开始引入 +### sql_require_primary_key v6.3.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 这个变量用于控制表是否必须有主键。启用该变量后,如果在没有主键的情况下创建或修改表,将返回错误。 -- 该功能基于 MySQL 8.0 的特性 [`sql_require_primary_key`](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_sql_require_primary_key)。 -- 强烈推荐在使用 TiCDC 时启用该变量,因为同步数据变更至 MySQL sink 时要求表必须有主键。 -- 如果启用了该变量,且使用了 TiDB Data Migration (DM) 来迁移数据,建议在 [DM 任务配置文件](/dm/task-configuration-file-full.md#完整配置文件示例)里的 `session` 中添加该系统变量 `sql_require_primary_key` 并设置为 `OFF`,否则会导致 DM 任务创建失败。 +- 此变量控制是否强制要求表具有主键。启用此变量后,尝试创建或更改没有主键的表将产生错误。 +- 此功能基于 MySQL 8.0 中类似命名的 [`sql_require_primary_key`](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_sql_require_primary_key)。 +- 强烈建议在使用 TiCDC 时启用此变量。这是因为将更改复制到 MySQL sink 需要表具有主键。 -### `sql_select_limit` 从 v4.0.2 版本开始引入 + -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 如果你启用此变量并使用 TiDB Data Migration (DM) 迁移数据,建议你将 `sql_require_ primary_key` 添加到 [DM 任务配置文件](/dm/task-configuration-file-full.md#task-configuration-file-template-advanced) 的 `session` 部分,并将其设置为 `OFF`。否则,将导致 DM 无法创建任务。 + + + +### sql_select_limit v4.0.2 新增 + +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`18446744073709551615` - 范围:`[0, 18446744073709551615]` - 单位:行 - `SELECT` 语句返回的最大行数。 -### `ssl_ca` +### ssl_ca -- 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 + + +- 范围:NONE +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 证书颁发机构 (CA) 文件的位置。若文件不存在,则变量值为空。该变量的值由 TiDB 配置项 [`ssl-ca`](/tidb-configuration-file.md#ssl-ca) 定义。 +- 证书颁发机构文件的位置(如果有)。此变量的值由 TiDB 配置文件项 [`ssl-ca`](/tidb-configuration-file.md#ssl-ca) 定义。 -### `ssl_cert` + -- 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 + + +- 范围:NONE +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 用于 SSL/TLS 连接的证书文件的位置。若文件不存在,则变量值为空。该变量的值由 TiDB 配置项 [`ssl-cert`](/tidb-configuration-file.md#ssl-cert) 定义。 +- 证书颁发机构文件的位置(如果有)。此变量的值由 TiDB 配置文件项 [`ssl-ca`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#ssl-ca) 定义。 -### `ssl_key` + -- 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +### ssl_cert + + + +- 范围:NONE +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 用于 SSL/TLS 连接的私钥文件的位置。若文件不存在,则变量值为空。该变量的值由 TiDB 配置项 [`ssl-key`](/tidb-configuration-file.md#ssl-cert) 定义。 +- 用于 SSL/TLS 连接的证书文件的位置(如果有文件)。此变量的值由 TiDB 配置文件项 [`ssl-cert`](/tidb-configuration-file.md#ssl-cert) 定义。 -### `system_time_zone` + -- 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:(随系统) -- 该变量显示首次引导启动 TiDB 时的系统时区。另请参阅 [`time_zone`](#time_zone)。 + -### `tidb_adaptive_closest_read_threshold` 从 v6.3.0 版本开始引入 +- 范围:NONE +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:"" +- 用于 SSL/TLS 连接的证书文件的位置(如果有文件)。此变量的值由 TiDB 配置文件项 [`ssl-cert`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#ssl-cert) 定义。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 + + +### ssl_key + + + +- 范围:NONE +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:"" +- 用于 SSL/TLS 连接的私钥文件(如果存在)的位置。此变量的值由 TiDB 配置文件项 [`ssl-key`](/tidb-configuration-file.md#ssl-cert) 定义。 + + + + + +- 范围:无 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:"" +- 用于 SSL/TLS 连接的私钥文件(如果存在)的位置。此变量的值由 TiDB 配置文件项 [`ssl-key`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#ssl-key) 定义。 + + + +### system_time_zone + +- 范围:无 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:(系统相关) +- 此变量显示 TiDB 首次启动时的系统时区。另请参阅 [`time_zone`](#time_zone)。 + +### tidb_adaptive_closest_read_threshold v6.3.0 新增 + +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`4096` -- 取值范围:`[0, 9223372036854775807]` +- 范围:`[0, 9223372036854775807]` - 单位:字节 -- 这个变量用于控制当 [`replica-read`](#tidb_replica_read-从-v40-版本开始引入) 设置为 `closest-adaptive` 时,优先将读请求发送至 TiDB server 所在区域副本的阈值。当读请求预估的返回结果的大小超过此阈值时,TiDB 会将读请求优先发送至同一可用区的副本,否则会发送至 leader 副本。 +- 此变量用于控制当 [`tidb_replica_read`](#tidb_replica_read-new-in-v40) 设置为 `closest-adaptive` 时,TiDB 服务器倾向于将读取请求发送到与 TiDB 服务器位于同一可用区中的副本的阈值。如果估计结果高于或等于此阈值,TiDB 倾向于将读取请求发送到同一可用区中的副本。否则,TiDB 将读取请求发送到 leader 副本。 -### `tidb_allow_tiflash_cop` 从 v7.3.0 版本开始引入 +### tidb_allow_tiflash_cop v7.3.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 当 TiDB 给 TiFlash 下推计算任务时,有三种方法(或协议)可供选择:Cop、BatchCop 和 MPP。相比于 Cop 和 BatchCop,MPP 协议更加成熟,提供更好的任务和资源管理。因此,更推荐使用 MPP 协议。 +- 当 TiDB 将计算任务下推到 TiFlash 时,有三种方法(或协议)可供选择:Cop、BatchCop 和 MPP。与 Cop 和 BatchCop 相比,MPP 协议更成熟,并提供更好的任务和资源管理。因此,建议使用 MPP 协议。 + - `0` 或 `OFF`:优化器仅生成使用 TiFlash MPP 协议的计划。 + - `1` 或 `ON`:优化器根据成本估算确定是使用 Cop、BatchCop 还是 MPP 协议来生成执行计划。 - * `0` 或 `OFF`:优化器仅生成使用 TiFlash MPP 协议的计划。 - * `1` 或 `ON`:优化器根据成本估算从 Cop、BatchCop 和 MPP 协议中选择一个用于生成执行计划。 +### tidb_allow_batch_cop v4.0 新增 -### `tidb_allow_batch_cop` 从 v4.0 版本开始引入 - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:整数 - 默认值:`1` - 范围:`[0, 2]` -- 这个变量用于控制 TiDB 向 TiFlash 发送 coprocessor 请求的方式,有以下几种取值: +- 此变量用于控制 TiDB 如何将 coprocessor 请求发送到 TiFlash。它具有以下值: - * 0:从不批量发送请求 - * 1:aggregation 和 join 的请求会进行批量发送 - * 2:所有的 cop 请求都会批量发送 + * `0`:从不批量发送请求 + * `1`:聚合和连接请求批量发送 + * `2`:所有 coprocessor 请求批量发送 -### `tidb_allow_fallback_to_tikv` 从 v5.0 版本开始引入 +### tidb_allow_fallback_to_tikv v5.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 默认值:"" -- 这个变量表示将 TiKV 作为备用存储引擎的存储引擎列表。当该列表中的存储引擎发生故障导致 SQL 语句执行失败时,TiDB 会使用 TiKV 作为存储引擎再次执行该 SQL 语句。目前支持设置该变量为 "" 或者 "tiflash"。如果设置该变量为 "tiflash",当 TiFlash 返回超时错误(对应的错误码为 ErrTiFlashServerTimeout)时,TiDB 会使用 TiKV 作为存储引擎再次执行该 SQL 语句。 +- 此变量用于指定可能回退到 TiKV 的存储引擎列表。如果 SQL 语句的执行由于列表中指定的存储引擎发生故障而失败,TiDB 会使用 TiKV 重试执行此 SQL 语句。此变量可以设置为 "" 或 "tiflash"。当此变量设置为 "tiflash" 时,如果 TiFlash 返回超时错误(错误代码:ErrTiFlashServerTimeout),TiDB 会使用 TiKV 重试执行此 SQL 语句。 -### `tidb_allow_function_for_expression_index` 从 v5.2.0 版本开始引入 +### tidb_allow_function_for_expression_index v5.2.0 新增 -- 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:无 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`json_array, json_array_append, json_array_insert, json_contains, json_contains_path, json_depth, json_extract, json_insert, json_keys, json_length, json_merge_patch, json_merge_preserve, json_object, json_pretty, json_quote, json_remove, json_replace, json_search, json_set, json_storage_size, json_type, json_unquote, json_valid, lower, md5, reverse, tidb_shard, upper, vitess_hash` -- 这个只读变量用于显示创建[表达式索引](/sql-statements/sql-statement-create-index.md#表达式索引)所允许使用的函数。 +- 此只读变量用于显示允许用于创建[表达式索引](/sql-statements/sql-statement-create-index.md#expression-index)的函数。 -### `tidb_allow_mpp` 从 v5.0 版本开始引入 +### tidb_allow_mpp v5.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:布尔值 - 默认值:`ON` -- 这个变量用于控制是否使用 TiFlash 的 MPP 模式执行查询,可以设置的值包括: - - `0` 或 `OFF`,代表从不使用 MPP 模式。如果在 v7.3.0 及之后的版本将该变量值设置为 `0` 或 `OFF`,你需要同时开启 [`tidb_allow_tiflash_cop`](/system-variables.md#tidb_allow_tiflash_cop-从-v730-版本开始引入) 变量,否则可能遇到查询报错。 - - `1` 或 `ON`,代表由优化器根据代价估算选择是否使用 MPP 模式(默认)。 +- 控制是否使用 TiFlash 的 MPP 模式来执行查询。值选项如下: + - `0` 或 `OFF`,表示不使用 MPP 模式。对于 v7.3.0 或更高版本,如果将此变量的值设置为 `0` 或 `OFF`,还需要启用 [`tidb_allow_tiflash_cop`](/system-variables.md#tidb_allow_tiflash_cop-new-in-v730) 变量。否则,查询可能会返回错误。 + - `1` 或 `ON`,表示优化器根据成本估算(默认)确定是否使用 MPP 模式。 -MPP 是 TiFlash 引擎提供的分布式计算框架,允许节点之间的数据交换并提供高性能、高吞吐的 SQL 算法。MPP 模式选择的详细说明参见[控制是否选择 MPP 模式](/tiflash/use-tiflash-mpp-mode.md#控制是否选择-mpp-模式)。 +MPP 是 TiFlash 引擎提供的分布式计算框架,允许节点之间的数据交换,并提供高性能、高吞吐量的 SQL 算法。有关 MPP 模式选择的详细信息,请参阅[控制是否选择 MPP 模式](/tiflash/use-tiflash-mpp-mode.md#control-whether-to-select-the-mpp-mode)。 -### `tidb_allow_remove_auto_inc` 从 v2.1.18 和 v3.0.4 版本开始引入 +### tidb_allow_remove_auto_inc v2.1.18 和 v3.0.4 新增 -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 + + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + + + +- 范围:SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 这个变量用来控制是否允许通过 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 来移除某个列的 `AUTO_INCREMENT` 属性。默认 (`OFF`) 为不允许。 +- 此变量用于设置是否允许通过执行 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 语句删除列的 `AUTO_INCREMENT` 属性。默认情况下不允许。 -### `tidb_analyze_distsql_scan_concurrency` 从 v7.6.0 版本开始引入 +### tidb_analyze_distsql_scan_concurrency v7.6.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`4` - 范围:`[1, 4294967295]` -- 这个变量用来设置执行 `ANALYZE` 时 `scan` 操作的并发度。 +- 此变量用于设置执行 `ANALYZE` 操作时 `scan` 操作的并发度。 -### `tidb_analyze_partition_concurrency` +### tidb_analyze_partition_concurrency -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`2`。TiDB v7.4.0 及其之前版本默认值为 `1`。 -- 这个变量用于 TiDB analyze 分区表时,对分区表统计信息进行读写的并发度。 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`2`。对于 v7.4.0 及更早版本,默认值为 `1`。 +- 此变量指定 TiDB 分析分区表时,读取和写入分区表的统计信息的并发度。 -### `tidb_analyze_version` 从 v5.1.0 版本开始引入 +### tidb_analyze_version v5.1.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`2` - 范围:`[1, 2]` -- 这个变量用于控制 TiDB 收集统计信息的行为。 -- 在 v5.3.0 及之后的版本中,该变量的默认值为 `2`,具体可参照[常规统计信息](/statistics.md)文档。如果从 v5.3.0 之前版本的集群升级至 v5.3.0 及之后的版本,`tidb_analyze_version` 的默认值不发生变化。 +- 控制 TiDB 如何收集统计信息。 + - 对于 TiDB Self-Managed,从 v5.3.0 开始,此变量的默认值从 `1` 更改为 `2`。 + - 对于 TiDB Cloud,从 v6.5.0 开始,此变量的默认值从 `1` 更改为 `2`。 + - 如果您的集群是从早期版本升级的,则升级后 `tidb_analyze_version` 的默认值不会更改。 +- 有关此变量的详细介绍,请参见[统计信息介绍](/statistics.md)。 -### `tidb_analyze_skip_column_types` 从 v7.2.0 版本开始引入 +### tidb_analyze_skip_column_types v7.2.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"json,blob,mediumblob,longblob" -- 可选值:"json,blob,mediumblob,longblob,text,mediumtext,longtext" -- 这个变量表示在执行 `ANALYZE` 命令收集统计信息时,跳过哪些类型的列的统计信息收集。该变量仅适用于 [`tidb_analyze_version = 2`](#tidb_analyze_version-从-v510-版本开始引入) 的情况。即使使用 `ANALYZE TABLE t COLUMNS c1, ..., cn` 语法指定列,如果指定的列的类型在 `tidb_analyze_skip_column_types` 中,也不会收集该列的统计信息。 +- 可能的值: "json,blob,mediumblob,longblob,text,mediumtext,longtext" +- 此变量控制在执行 `ANALYZE` 命令收集统计信息时,哪些类型的列将被跳过统计信息收集。该变量仅适用于 `tidb_analyze_version = 2`。即使你使用 `ANALYZE TABLE t COLUMNS c1, ... , cn` 指定了一个列,如果该列的类型在 `tidb_analyze_skip_column_types` 中,也不会收集该列的统计信息。 -```sql +``` mysql> SHOW CREATE TABLE t; +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | @@ -1050,305 +1199,306 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; 1 row in set (0.00 sec) ``` -### `tidb_auto_analyze_end_time` +### tidb_auto_analyze_end_time -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:时间 -- 默认值:`23:59 +0000` -- 这个变量用来设置一天中允许自动 ANALYZE 更新统计信息的结束时间。例如,只允许在 UTC 时间的凌晨 1:00 至 3:00 之间自动更新统计信息,可以设置如下: +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Time +- 默认值: `23:59 +0000` +- 此变量用于限制允许自动更新统计信息的时间窗口。例如,要仅允许在 UTC 时间的凌晨 1 点到凌晨 3 点之间自动更新统计信息,请设置 `tidb_auto_analyze_start_time='01:00 +0000'` 和 `tidb_auto_analyze_end_time='03:00 +0000'`。 - - `tidb_auto_analyze_start_time='01:00 +0000'` - - `tidb_auto_analyze_end_time='03:00 +0000'` +### tidb_auto_analyze_partition_batch_size v6.4.0 新增 -### `tidb_auto_analyze_partition_batch_size` 从 v6.4.0 版本开始引入 +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 默认值: `128`。在 v7.6.0 之前,默认值为 `1`。 +- 范围: `[1, 1024]` +- 此变量指定 TiDB 在分析分区表时(意味着自动收集分区表的统计信息)[自动分析](/statistics.md#automatic-update)的分区数量。 +- 如果此变量的值小于分区数,TiDB 会分批自动分析分区表的所有分区。如果此变量的值大于或等于分区数,TiDB 会同时分析分区表的所有分区。 +- 如果分区表的分区数远大于此变量值,并且自动分析花费的时间很长,则可以增加此变量的值以减少时间消耗。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`128`。对于 TiDB v7.6.0 之前的版本,默认值为 `1`。 -- 范围:`[1, 1024]` -- 用于设置 TiDB [自动 analyze](/statistics.md#自动更新) 分区表(即自动收集分区表上的统计信息)时,每次同时 analyze 分区的个数。 -- 若该变量值小于分区表的分区数,则 TiDB 会分多批自动 analyze 该分区表的所有分区。若该变量值大于等于分区表的分区数,则 TiDB 会同时 analyze 该分区表的所有分区。 -- 若分区表个数远大于该变量值,且自动 analyze 花费时间较长,可调大该参数的值以减少耗时。 - -### `tidb_auto_analyze_ratio` +### tidb_auto_analyze_ratio -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:浮点数 -- 默认值:`0.5` -- 范围:`(0, 1]`,v8.0.0 及之前版本范围为 `[0, 18446744073709551615]`。 -- 这个变量用来设置 TiDB 在后台自动执行 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 更新统计信息的阈值。`0.5` 指的是当表中超过 50% 的行被修改时,触发自动 ANALYZE 更新。可以指定 `tidb_auto_analyze_start_time` 和 `tidb_auto_analyze_end_time` 来限制自动 ANALYZE 的时间。 +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Float +- 默认值: `0.5` +- 范围: `(0, 1]`。 v8.0.0 及更早版本的范围是 `[0, 18446744073709551615]`。 +- 此变量用于设置 TiDB 在后台线程中自动执行 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 以更新表统计信息的阈值。例如,值为 0.5 表示当表中超过 50% 的行被修改时,将触发自动分析。可以通过指定 `tidb_auto_analyze_start_time` 和 `tidb_auto_analyze_end_time` 将自动分析限制为仅在一天中的某些小时执行。 -> **注意:** +> **注意:** > -> 当系统变量 `tidb_enable_auto_analyze` 设置为 `ON` 时,TiDB 才会触发 `auto_analyze`。 - -### `tidb_auto_analyze_start_time` +> 此功能需要将系统变量 `tidb_enable_auto_analyze` 设置为 `ON`。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:时间 -- 默认值:`00:00 +0000` -- 这个变量用来设置一天中允许自动 ANALYZE 更新统计信息的开始时间。例如,只允许在 UTC 时间的凌晨 1:00 至 3:00 之间自动更新统计信息,可以设置如下: +### tidb_auto_analyze_start_time - - `tidb_auto_analyze_start_time='01:00 +0000'` - - `tidb_auto_analyze_end_time='03:00 +0000'` +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Time +- 默认值: `00:00 +0000` +- 此变量用于限制允许自动更新统计信息的时间窗口。例如,要仅允许在 UTC 时间的凌晨 1 点到凌晨 3 点之间自动更新统计信息,请设置 `tidb_auto_analyze_start_time='01:00 +0000'` 和 `tidb_auto_analyze_end_time='03:00 +0000'`。 -### `tidb_auto_build_stats_concurrency` 从 v6.5.0 版本开始引入 +### tidb_auto_build_stats_concurrency v6.5.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`1` -- 范围:`[1, 256]` -- 这个变量用来设置执行统计信息自动更新的并发度。 +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `1` +- 范围: `[1, 256]` +- 此变量用于设置执行自动更新统计信息的并发度。 -### `tidb_backoff_lock_fast` +### tidb_backoff_lock_fast -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`10` -- 范围:`[1, 2147483647]` -- 这个变量用来设置读请求遇到锁的 backoff 时间。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `10` +- 范围: `[1, 2147483647]` +- 此变量用于设置读取请求遇到锁时的 `backoff` 时间。 -### `tidb_backoff_weight` +### tidb_backoff_weight -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`2` -- 范围:`[0, 2147483647]` -- 这个变量用来给 TiDB 的 `backoff` 最大时间增加权重,即内部遇到网络或其他组件 (TiKV, PD) 故障时,发送重试请求的最大重试时间。可以通过这个变量来调整最大重试时间,最小值为 1。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `2` +- 范围: `[0, 2147483647]` +- 此变量用于增加 TiDB `backoff` 的最大时间权重,即遇到内部网络或其他组件(TiKV、PD)故障时,发送重试请求的最大重试时间。此变量可用于调整最大重试时间,最小值为 1。 - 例如,TiDB 向 PD 取 TSO 的基础超时时间是 15 秒,当 `tidb_backoff_weight = 2` 时,取 TSO 的最大超时时间为:基础时间 \* 2 等于 30 秒。 + 例如,TiDB 从 PD 获取 TSO 的基本超时时间为 15 秒。当 `tidb_backoff_weight = 2` 时,获取 TSO 的最大超时时间为:*基本时间 \* 2 = 30 秒*。 - 在网络环境较差的情况下,适当增大该变量值可以有效缓解因为超时而向应用端报错的情况;而如果应用端希望更快地接到报错信息,则应该尽量减小该变量的值。 + 在网络环境较差的情况下,适当增加此变量的值可以有效缓解因超时而导致的应用端错误报告。如果应用端希望更快地收到错误信息,请尽量减小此变量的值。 -### `tidb_batch_commit` +### tidb_batch_commit -> **警告:** +> **警告:** > -> **不建议**开启此变量。 +> **不**建议启用此变量。 -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 该变量控制是否启用已废弃的 batch-commit 特性。当该变量开启时,事务可能会通过分组一些语句被拆分为多个事务,并被非原子地提交。不推荐使用这种方式。 +- 作用域: SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `OFF` +- 该变量用于控制是否启用已弃用的批量提交功能。启用此变量后,事务可能会被拆分为多个事务,通过对一些语句进行分组并以非原子方式提交,不建议这样做。 -### `tidb_batch_delete` +### tidb_batch_delete > **警告:** > -> 该变量与废弃的 batch-dml 特性相关,可能会导致数据损坏。因此,不建议开启该变量来使用 batch-dml。作为替代,请使用[非事务 DML 语句](/non-transactional-dml.md)。 +> 此变量与已弃用的批量 DML 功能相关联,可能会导致数据损坏。因此,不建议为批量 DML 启用此变量。请改用[非事务性 DML](/non-transactional-dml.md)。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量控制是否启用已废弃的 batch-dml 特性中的 batch-delete 特性。当该变量开启时,`DELETE` 语句可能会被拆分为多个事务,并被非原子地提交。要使该特性生效,还需要开启 `tidb_enable_batch_dml` 并将 `tidb_dml_batch_size` 的值设置为正数。不推荐使用这种方式。 +- 该变量用于控制是否启用批量删除功能,该功能是已弃用的批量 DML 功能的一部分。启用此变量后,`DELETE` 语句可能会被拆分为多个事务并以非原子方式提交。要使其工作,还需要启用 `tidb_enable_batch_dml` 并为 `tidb_dml_batch_size` 设置一个正值,不建议这样做。 -### `tidb_batch_insert` +### tidb_batch_insert > **警告:** > -> 该变量与废弃的 batch-dml 特性相关,可能会导致数据损坏。因此,不建议开启该变量来使用 batch-dml。作为替代,请使用[非事务 DML 语句](/non-transactional-dml.md)。 +> 此变量与已弃用的批量 DML 功能相关联,可能会导致数据损坏。因此,不建议为批量 DML 启用此变量。请改用[非事务性 DML](/non-transactional-dml.md)。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量控制是否启用已废弃的 batch-dml 特性中的 batch-insert 特性。当该变量开启时,`INSERT` 语句可能会被拆分为多个事务,并被非原子地提交。要使该特性生效,还需要开启 `tidb_enable_batch_dml` 并将 `tidb_dml_batch_size` 的值设置为正数。不推荐使用这种方式。 +- 该变量用于控制是否启用批量插入功能,该功能是已弃用的批量 DML 功能的一部分。启用此变量后,`INSERT` 语句可能会被拆分为多个事务并以非原子方式提交。要使其工作,还需要启用 `tidb_enable_batch_dml` 并为 `tidb_dml_batch_size` 设置一个正值,不建议这样做。 -### `tidb_batch_pending_tiflash_count` 从 v6.0 版本开始引入 +### tidb_batch_pending_tiflash_count v6.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`4000` - 范围:`[0, 4294967295]` -- 使用 `ALTER DATABASE SET TIFLASH REPLICA` 语句为 TiFlash 添加副本时,能容许的不可用表的个数上限。如果超过该上限,则会停止或者以非常慢的速度为库中的剩余表设置 TiFlash 副本。 +- 指定使用 `ALTER DATABASE SET TIFLASH REPLICA` 添加 TiFlash 副本时允许的最大不可用表数量。如果不可用表的数量超过此限制,则操作将被停止,或者为剩余表设置 TiFlash 副本的速度将非常慢。 -### `tidb_broadcast_join_threshold_count` 从 v5.0 版本开始引入 +### tidb_broadcast_join_threshold_count v5.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`10240` - 范围:`[0, 9223372036854775807]` - 单位:行 -- 如果 join 的对象为子查询,优化器无法估计子查询结果集大小,在这种情况下通过结果集行数判断。如果子查询的行数估计值小于该变量,则选择 Broadcast Hash Join 算法。否则选择 Shuffled Hash Join 算法。 -- 开启 [`tidb_prefer_broadcast_join_by_exchange_data_size`](/system-variables.md#tidb_prefer_broadcast_join_by_exchange_data_size-从-v710-版本开始引入) 功能后,该变量将不再生效。 +- 如果 join 操作的对象属于子查询,优化器无法估计子查询结果集的大小。在这种情况下,大小由结果集中的行数决定。如果子查询中估计的行数小于此变量的值,则使用 Broadcast Hash Join 算法。否则,使用 Shuffled Hash Join 算法。 +- 在启用 [`tidb_prefer_broadcast_join_by_exchange_data_size`](/system-variables.md#tidb_prefer_broadcast_join_by_exchange_data_size-new-in-v710) 后,此变量将不起作用。 -### `tidb_broadcast_join_threshold_size` 从 v5.0 版本开始引入 +### tidb_broadcast_join_threshold_size v5.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`104857600` (100 MiB) - 范围:`[0, 9223372036854775807]` - 单位:字节 -- 如果表大小(字节数)小于该值,则选择 Broadcast Hash Join 算法。否则选择 Shuffled Hash Join 算法。 -- 开启 [`tidb_prefer_broadcast_join_by_exchange_data_size`](/system-variables.md#tidb_prefer_broadcast_join_by_exchange_data_size-从-v710-版本开始引入) 功能后,该变量将不再生效。 +- 如果表大小小于该变量的值,则使用 Broadcast Hash Join 算法。否则,使用 Shuffled Hash Join 算法。 +- 在启用 [`tidb_prefer_broadcast_join_by_exchange_data_size`](/system-variables.md#tidb_prefer_broadcast_join_by_exchange_data_size-new-in-v710) 后,此变量将不起作用。 -### `tidb_build_stats_concurrency` +### tidb_build_stats_concurrency - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`2`。对于 v7.4.0 及更早版本,默认值为 `4`。 +- 范围:`[1, 256]` - 单位:线程 -- 默认值:`2`。TiDB v7.4.0 及其之前版本默认值为 `4`。 -- 取值范围:`[1, 256]` -- 这个变量用来设置 ANALYZE 语句执行时并发度。 -- 当这个变量被设置得更大时,会对其它的查询语句执行性能产生一定影响。 +- 此变量用于设置执行 `ANALYZE` 语句的并发性。 +- 当变量设置为较大的值时,会影响其他查询的执行性能。 -### `tidb_build_sampling_stats_concurrency` 从 v7.5.0 版本开始引入 +### tidb_build_sampling_stats_concurrency v7.5.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 单位:线程 - 默认值:`2` -- 取值范围:`[1, 256]` -- 这个变量用来设置 `ANALYZE` 过程中的采样并发度。 -- 当这个变量被设置得更大时,会对其它的查询语句执行性能产生一定影响。 +- 范围:`[1, 256]` +- 此变量用于设置 `ANALYZE` 过程中的采样并发性。 +- 当变量设置为较大的值时,会影响其他查询的执行性能。 -### `tidb_capture_plan_baselines` 从 v4.0 版本开始引入 +### tidb_capture_plan_baselines v4.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用于控制是否开启[自动捕获绑定](/sql-plan-management.md#自动捕获绑定-baseline-capturing)功能。该功能依赖 Statement Summary,因此在使用自动绑定之前需打开 Statement Summary 开关。 -- 开启该功能后会定期遍历一次 Statement Summary 中的历史 SQL 语句,并为至少出现两次的 SQL 语句自动创建绑定。 +- 此变量用于控制是否启用[基线捕获](/sql-plan-management.md#baseline-capturing)功能。此功能依赖于语句摘要,因此在使用基线捕获之前需要启用语句摘要。 +- 启用此功能后,会定期遍历语句摘要中的历史 SQL 语句,并自动为至少出现两次的 SQL 语句创建绑定。 -### `tidb_cdc_write_source` 从 v6.5.0 版本开始引入 +### tidb_cdc_write_source v6.5.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION - 是否持久化到集群:否 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值: `0` +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`0` - 范围:`[0, 15]` -- 当变量非 `0` 时,该 SESSION 写入的数据将被视为是由 TiCDC 写入的。这个变量仅由 TiCDC 设置,任何时候都不应该手动调整该变量。 +- 当此变量设置为 0 以外的值时,在此会话中写入的数据被认为是 TiCDC 写入的。此变量只能由 TiCDC 修改。在任何情况下都不要手动修改此变量。 -### `tidb_check_mb4_value_in_utf8` +### tidb_check_mb4_value_in_utf8 + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 设置该变量为 `ON` 可强制只存储[基本多文种平面 (BMP)](https://zh.wikipedia.org/zh-hans/Unicode字符平面映射) 编码区段内的 `utf8` 字符值。若要存储 BMP 区段外的 `utf8` 值,推荐使用 `utf8mb4` 字符集。 -- 早期版本的 TiDB 中 (v2.1.x),`utf8` 检查更为宽松。如果你的 TiDB 集群是从早期版本升级的,推荐关闭该变量,详情参阅[升级与升级后常见问题](/faq/upgrade-faq.md)。 +- 此变量用于强制 `utf8` 字符集仅存储来自 [基本多文种平面 (BMP)](https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane) 的值。要存储 BMP 之外的字符,建议使用 `utf8mb4` 字符集。 +- 当您从早期版本的 TiDB 升级集群时,可能需要禁用此选项,因为早期版本的 TiDB 中 `utf8` 检查更为宽松。有关详细信息,请参见[升级后常见问题解答](https://docs.pingcap.com/tidb/stable/upgrade-faq)。 + +### tidb_checksum_table_concurrency + +- 作用域:SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`4` +- 范围:`[1, 256]` +- 单位:线程 +- 此变量用于设置执行 [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) 语句的扫描索引并发性。 +- 当变量设置为较大的值时,会影响其他查询的执行性能。 -### `tidb_committer_concurrency` 从 v6.1.0 版本开始引入 +### tidb_committer_concurrency v6.1.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`128` - 范围:`[1, 10000]` -- 在单个事务的提交阶段,用于执行提交操作相关请求的 goroutine 数量。 -- 若提交的事务过大,事务提交时的流控队列等待耗时可能会过长。此时,可以通过调大该配置项来加速提交。 -- 在 v6.1.0 之前这个开关通过 TiDB 配置文件 (`performance.committer-concurrency`) 进行配置,升级到 v6.1.0 时会自动继承原有设置。 +- 用于处理单事务提交阶段中执行提交相关请求的 Goroutine 数量。 +- 如果要提交的事务太大,则提交事务时流控队列的等待时间可能过长。在这种情况下,您可以增加此配置值以加快提交速度。 +- 此设置以前是一个 `tidb.toml` 选项 (`performance.committer-concurrency`),但从 TiDB v6.1.0 开始更改为系统变量。 -### `tidb_checksum_table_concurrency` +### tidb_config -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`4` -- 取值范围:`[1, 256]` -- 单位:线程 -- 这个变量用来设置 [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) 语句执行时扫描索引的并发度。当这个变量被设置得更大时,会对其它的查询语句执行性能产生一定影响。 - -### `tidb_config` +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 这个变量是一个只读变量,用来获取当前 TiDB Server 的配置信息。 +- 此变量是只读的。它用于获取当前 TiDB 服务器的配置信息。 -### `tidb_constraint_check_in_place` +### tidb_constraint_check_in_place - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量仅适用于乐观事务模型。悲观事务模式中的行为由 [`tidb_constraint_check_in_place_pessimistic`](#tidb_constraint_check_in_place_pessimistic-从-v630-版本开始引入) 控制。 -- 当这个变量设置为 `OFF` 时,唯一索引的重复值检查会被推迟到事务提交时才进行。这有助于提高性能,但对于某些应用,可能导致非预期的行为。详情见[约束](/constraints.md#乐观事务)。 +- 此变量仅适用于乐观事务。对于悲观事务,请改用 [`tidb_constraint_check_in_place_pessimistic`](#tidb_constraint_check_in_place_pessimistic-new-in-v630)。 +- 当此变量设置为 `OFF` 时,对唯一索引中重复值的检查将延迟到事务提交时。这有助于提高性能,但对于某些应用程序来说可能是一种意想不到的行为。有关详细信息,请参见 [约束](/constraints.md#optimistic-transactions)。 - - 乐观事务模型下将 `tidb_constraint_check_in_place` 设置为 `OFF`: - - {{< copyable "sql" >}} + - 当设置 `tidb_constraint_check_in_place` 为 `OFF` 并使用乐观事务时: ```sql - create table t (i int key); - insert into t values (1); - begin optimistic; - insert into t values (1); - ``` - - ``` + tidb> create table t (i int key); + tidb> insert into t values (1); + tidb> begin optimistic; + tidb> insert into t values (1); Query OK, 1 row affected + tidb> commit; -- 仅在事务提交时检查。 + ERROR 1062 : Duplicate entry '1' for key 't.PRIMARY' ``` - {{< copyable "sql" >}} + - 当设置 `tidb_constraint_check_in_place` 为 `ON` 并使用乐观事务时: ```sql - tidb> commit; -- 事务提交时才检查 - ``` - - ``` + tidb> set @@tidb_constraint_check_in_place=ON; + tidb> begin optimistic; + tidb> insert into t values (1); ERROR 1062 : Duplicate entry '1' for key 't.PRIMARY' ``` - - 乐观事务模型下将 `tidb_constraint_check_in_place` 设置为 `ON`: +### tidb_constraint_check_in_place_pessimistic v6.3.0 新增 - {{< copyable "sql" >}} +- 作用域:SESSION +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - ```sql - set @@tidb_constraint_check_in_place=ON; - begin optimistic; - insert into t values (1); - ``` + - ``` - ERROR 1062 : Duplicate entry '1' for key 't.PRIMARY' - ``` +- 默认值:默认情况下,[`pessimistic-txn.constraint-check-in-place-pessimistic`](/tidb-configuration-file.md#constraint-check-in-place-pessimistic-new-in-v640) 配置项为 `true`,因此此变量的默认值为 `ON`。当 [`pessimistic-txn.constraint-check-in-place-pessimistic`](/tidb-configuration-file.md#constraint-check-in-place-pessimistic-new-in-v640) 设置为 `false` 时,此变量的默认值为 `OFF`。 -### `tidb_constraint_check_in_place_pessimistic` 从 v6.3.0 版本开始引入 + -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:当配置项 [`pessimistic-txn.constraint-check-in-place-pessimistic`](/tidb-configuration-file.md#constraint-check-in-place-pessimistic-从-v640-版本开始引入) 为默认值 `true` 时,该变量的默认值为 `ON`。当配置项 [`pessimistic-txn.constraint-check-in-place-pessimistic`](/tidb-configuration-file.md#constraint-check-in-place-pessimistic-从-v640-版本开始引入) 为 `false` 时,该变量的默认值为 `OFF`。 -- 该变量仅适用于悲观事务模型。乐观事务模式中的行为由 [`tidb_constraint_check_in_place`](#tidb_constraint_check_in_place) 控制。 -- 当这个变量设置为 `OFF` 时,唯一约束检查会被推迟到下一次需要对这个索引加锁的语句执行时,或事务提交时才进行。这有助于提高性能,但对于某些应用,可能导致非预期的行为。详情见[约束](/constraints.md#悲观事务)。 -- 关闭该变量可能会导致悲观事务中返回 `LazyUniquenessCheckFailure` 报错。返回该错误时,TiDB 将会回滚当前事务。 -- 关闭该变量后,悲观事务中不支持使用 [`SAVEPOINT`](/sql-statements/sql-statement-savepoint.md) 功能。 -- 关闭该变量时,commit 语句可能会报出 `Write conflict` 错误或 `Duplicate entry` 错误,两种错误都意味着事务回滚。 + + +- 默认值:`ON` + + - - 悲观事务模型下将 `tidb_constraint_check_in_place_pessimistic` 设置为 `OFF`: +- 此变量仅适用于悲观事务。对于乐观事务,请改用 [`tidb_constraint_check_in_place`](#tidb_constraint_check_in_place)。 +- 当此变量设置为 `OFF` 时,TiDB 会延迟唯一索引的唯一约束检查(延迟到下次执行需要锁定索引的语句时,或延迟到提交事务时)。这有助于提高性能,但对于某些应用程序来说可能是一种意想不到的行为。有关详细信息,请参见 [约束](/constraints.md#pessimistic-transactions)。 +- 禁用此变量可能会导致 TiDB 在悲观事务中返回 `LazyUniquenessCheckFailure` 错误。发生此错误时,TiDB 会回滚当前事务。 +- 禁用此变量后,您无法在悲观事务中使用 [`SAVEPOINT`](/sql-statements/sql-statement-savepoint.md)。 +- 禁用此变量后,提交悲观事务可能会返回 `Write conflict` 或 `Duplicate entry` 错误。发生此类错误时,TiDB 会回滚当前事务。 + + - 当设置 `tidb_constraint_check_in_place_pessimistic` 为 `OFF` 并使用悲观事务时: {{< copyable "sql" >}} @@ -1365,14 +1515,14 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; ``` ```sql - tidb> commit; -- 事务提交时才检查 + tidb> commit; -- 仅在事务提交时检查。 ``` ``` ERROR 1062 : Duplicate entry '1' for key 't.PRIMARY' ``` - - 悲观事务模型下将 `tidb_constraint_check_in_place_pessimistic` 设置为 `ON`: + - 当设置 `tidb_constraint_check_in_place_pessimistic` 为 `ON` 并使用悲观事务时: ```sql set @@tidb_constraint_check_in_place_pessimistic=ON; @@ -1384,1150 +1534,1333 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; ERROR 1062 : Duplicate entry '1' for key 't.PRIMARY' ``` -### `tidb_cost_model_version` 从 v6.2.0 版本开始引入 +### tidb_cost_model_version v6.2.0 新增 > **注意:** > -> - 自 v6.5.0 开始,新创建的 TiDB 集群默认使用 Cost Model Version 2。如果从 v6.4.0 及之前版本的集群升级到 v6.5.0 及之后的版本,`tidb_cost_model_version` 的值不发生变化。 -> - 切换代价模型版本可能会引起查询计划的变动。 +> - 从 TiDB v6.5.0 开始,新创建的集群默认使用 Cost Model Version 2。如果您从早于 v6.5.0 的 TiDB 版本升级到 v6.5.0 或更高版本,则 `tidb_cost_model_version` 值不会更改。 +> - 切换成本模型版本可能会导致查询计划发生变化。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`2` -- 取值范围:`[1, 2]` - 可选值: - - `1`:使用 Cost Model Version 1 代价模型。TiDB v6.4.0 及之前的版本默认使用 Cost Model Version 1。 - - `2`:使用 Cost Model Version 2 代价模型。TiDB v6.5.0 正式发布了代价模型 [Cost Model Version 2](/cost-model.md#cost-model-version-2),在内部测试中比 Version 1 版本的代价模型更加准确。 -- 代价模型会影响优化器对计划的选择,具体可见[代价模型](/cost-model.md)。 + - `1`:启用 Cost Model Version 1,这是 TiDB v6.4.0 及更早版本中默认使用的。 + - `2`:启用 [Cost Model Version 2](/cost-model.md#cost-model-version-2),该版本在 TiDB v6.5.0 中正式发布,并且在内部测试中比版本 1 更准确。 +- 成本模型的版本会影响优化器的计划决策。有关更多详细信息,请参见 [成本模型](/cost-model.md)。 -### `tidb_current_ts` +### tidb_current_ts - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` -- 取值范围:`[0, 9223372036854775807]` -- 这个变量是一个只读变量,用来获取当前事务的时间戳。 +- 范围:`[0, 9223372036854775807]` +- 此变量是只读的。它用于获取当前事务的时间戳。 -### `tidb_ddl_disk_quota` 从 v6.3.0 版本开始引入 +### tidb_ddl_disk_quota v6.3.0 新增 + +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless),此变量是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`107374182400` (100 GiB) - 范围:`[107374182400, 1125899906842624]` ([100 GiB, 1 PiB]) - 单位:字节 -- 这个变量仅在 [`tidb_ddl_enable_fast_reorg`](#tidb_ddl_enable_fast_reorg-从-v630-版本开始引入) 开启的情况下生效,用于设置创建索引的回填过程中本地存储空间的使用限制。 +- 仅当启用 [`tidb_ddl_enable_fast_reorg`](#tidb_ddl_enable_fast_reorg-new-in-v630) 时,此变量才生效。它设置创建索引时回填期间本地存储的使用限制。 + +### tidb_ddl_enable_fast_reorg v6.3.0 新增 -### `tidb_ddl_enable_fast_reorg` 从 v6.3.0 版本开始引入 +> **注意:** +> +> - 如果您使用的是 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 集群,要使用此变量提高索引创建速度,请确保您的 TiDB 集群托管在 AWS 上,并且您的 TiDB 节点大小至少为 8 vCPU。 +> - 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群,此变量是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制是否开启添加索引加速功能,来提升创建索引回填过程的速度。开启该变量对于数据量较大的表有一定的性能提升。 -- TiDB v7.1.0 引入了快速加索引功能的检查点机制,即使 TiDB owner 因故障重启或者切换,也能够通过自动定期保存的检查点恢复部分进度。 -- 要验证已经完成的 `ADD INDEX` 操作是否使用了添加索引加速功能,可以执行 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl-jobs) 语句查看 `JOB_TYPE` 一列中是否含有 `ingest` 字样。 +- 此变量控制是否启用 `ADD INDEX` 和 `CREATE INDEX` 的加速功能,以提高创建索引时回填数据的速度。将此变量值设置为 `ON` 可以提高大数据量表上创建索引的性能。 +- 从 v7.1.0 版本开始,索引加速操作支持检查点。即使 TiDB owner 节点由于故障而重启或更改,TiDB 仍然可以从定期自动更新的检查点恢复进度。 +- 要验证已完成的 `ADD INDEX` 操作是否已加速,您可以执行 [`ADMIN SHOW DDL JOBS`](/sql-statements/sql-statement-admin-show-ddl.md#admin-show-ddl-jobs) 语句,查看 `JOB_TYPE` 列中是否显示 `ingest`。 + + > **注意:** > -> * 要使用索引加速功能,你需要提供一个可写且具有足够空余空间的临时路径 [`temp-dir`](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入)。如果 `temp-dir` 无法使用,TiDB 会退回到非加速的索引创建方式。建议将 `temp-dir` 挂载在 SSD 磁盘上。 +> * 索引加速需要一个可写的且具有足够可用空间的 [`temp-dir`](/tidb-configuration-file.md#temp-dir-new-in-v630)。如果 `temp-dir` 不可用,TiDB 将回退到非加速索引构建。建议将 `temp-dir` 放在 SSD 磁盘上。 +> +> * 在将 TiDB 升级到 v6.5.0 或更高版本之前,建议您检查 TiDB 的 [`temp-dir`](/tidb-configuration-file.md#temp-dir-new-in-v630) 路径是否已正确挂载到 SSD 磁盘。确保运行 TiDB 的操作系统用户具有此目录的读写权限。否则,DDL 操作可能会遇到不可预测的问题。此路径是 TiDB 配置项,在 TiDB 重启后生效。因此,在升级前设置此配置项可以避免再次重启。 + + + + + +> **警告:** > -> * 在升级到 v6.5.0 及以上版本时,请确保 TiDB 的 [`temp-dir`](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入) 路径已正确挂载了 SSD 磁盘,并确保运行 TiDB 的操作系统用户对该目录有读写权限,否则在运行时可能产生不可预知的问题。该参数是 TiDB 的配置参数,设置后需要重启 TiDB 才能生效。因此,在升级前提前进行设置,可以避免再次重启。 +> 目前,此功能与[在单个 `ALTER TABLE` 语句中更改多个列或索引](/sql-statements/sql-statement-alter-table.md)不完全兼容。在使用索引加速添加唯一索引时,需要避免在同一语句中更改其他列或索引。 + + -### `tidb_enable_dist_task` 从 v7.1.0 版本开始引入 +### tidb_enable_dist_task v7.1.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否支持 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`ON` -- 这个变量用于控制是否开启 [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md)。开启分布式执行框架后,DDL 和 Import 等将会由集群中多个 TiDB 节点共同完成。 -- 从 TiDB v7.1.0 开始,支持分布式执行分区表的 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md)。 -- 从 TiDB v7.2.0 开始,支持分布式导入任务 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md)。 -- 从 TiDB v8.1.0 开始,该变量默认开启。如果要从低版本的集群升级到 v8.1.0 或更高版本,且该集群已开启分布式执行框架,为了避免升级期间 `ADD INDEX` 操作可能导致数据索引不一致的问题,请在升级前关闭分布式执行框架(即将 `tidb_enable_dist_task` 设置为 `OFF`),升级后再手动开启。 -- 该变量由 `tidb_ddl_distribute_reorg` 改名而来。 +- 此变量用于控制是否启用 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md)。启用该框架后,DDL 和导入等 DXF 任务将由集群中的多个 TiDB 节点分布式执行和完成。 +- 从 TiDB v7.1.0 开始,DXF 支持分布式执行分区表的 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 语句。 +- 从 TiDB v7.2.0 开始,DXF 支持分布式执行导入作业的 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 语句。 +- 从 TiDB v8.1.0 开始,默认启用此变量。如果要将启用了 DXF 的集群升级到 v8.1.0 或更高版本,请在升级前禁用 DXF(通过将 `tidb_enable_dist_task` 设置为 `OFF`),以避免升级期间的 `ADD INDEX` 操作导致数据索引不一致。升级后,您可以手动启用 DXF。 +- 此变量已从 `tidb_ddl_distribute_reorg` 重命名。 -### `tidb_cloud_storage_uri` 从 v7.4.0 版本开始引入 +### tidb_cloud_storage_uri v7.4.0 新增 > **注意:** > -> 目前,[全局排序](/tidb-global-sort.md)会使用大量 TiDB 节点的计算与内存资源。对于在线增加索引等同时有用户业务在运行的场景,建议为集群添加新的 TiDB 节点,为这些 TiDB 节点设置 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入),并连接到这些节点上创建任务。这样分布式框架就会将任务调度到这些节点上,将工作负载与其他 TiDB 节点隔离,以减少执行后端任务(如 `ADD INDEX` 和 `IMPORT INTO`)对用户业务的影响。 +> 目前,[全局排序](/tidb-global-sort.md)过程会消耗 TiDB 节点的大量计算和内存资源。在用户业务应用程序正在运行的情况下在线添加索引等场景中,建议向集群添加新的 TiDB 节点,为这些节点配置 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 变量,并连接到这些节点以创建任务。这样,分布式框架会将任务调度到这些节点,从而将工作负载与其他 TiDB 节点隔离,以减少执行 `ADD INDEX` 和 `IMPORT INTO` 等后端任务对用户业务应用程序的影响。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否支持 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`""` -- 该变量用来指定[全局排序](/tidb-global-sort.md)中使用的 Amazon S3 云存储的 URI。在开启 [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md)后,你可以配置 URI 指向具有访问存储所需权限的云存储路径,以此来实现全局排序的功能。更多详情,参考 [Amazon S3 的 URI 格式](/external-storage-uri.md#amazon-s3-uri-格式)。 -- 以下语句支持全局排序功能: +- 此变量用于指定 Amazon S3 云存储 URI 以启用[全局排序](/tidb-global-sort.md)。启用 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) 后,您可以通过配置 URI 并将其指向具有访问存储所需权限的适当云存储路径来使用全局排序功能。有关更多详细信息,请参阅 [Amazon S3 URI 格式](/external-storage-uri.md#amazon-s3-uri-format)。 +- 以下语句可以使用全局排序功能。 - [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 语句。 - - 用于将数据导入本地部署的 TiDB 的 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 语句。 + - 导入作业的 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 语句。 -### `tidb_ddl_error_count_limit` +### tidb_ddl_error_count_limit + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否支持 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`512` - 范围:`[0, 9223372036854775807]` -- 这个变量用来控制 DDL 操作失败重试的次数。失败重试次数超过该参数的值后,会取消出错的 DDL 操作。 +- 此变量用于设置 DDL 操作失败时的重试次数。当重试次数超过参数值时,错误的 DDL 操作将被取消。 + +### tidb_ddl_flashback_concurrency v6.3.0 新增 -### `tidb_ddl_flashback_concurrency` 从 v6.3.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否支持 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`64` - 范围:`[1, 256]` -- 这个变量用来控制 [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) 的并发数。 +- 此变量控制 [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) 的并发性。 -### `tidb_ddl_reorg_batch_size` +### tidb_ddl_reorg_batch_size + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否支持 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`256` - 范围:`[32, 10240]` - 单位:行 -- 这个变量用来设置 DDL 操作 `re-organize` 阶段的 batch size。比如 `ADD INDEX` 操作,需要回填索引数据,通过并发 `tidb_ddl_reorg_worker_cnt` 个 worker 一起回填数据,每个 worker 以 batch 为单位进行回填。 +- 此变量用于设置 DDL 操作的 `re-organize` 阶段的批量大小。例如,当 TiDB 执行 `ADD INDEX` 操作时,索引数据需要由 `tidb_ddl_reorg_worker_cnt` (数量)个并发 worker 回填。每个 worker 批量回填索引数据。 + - 如果 `tidb_ddl_enable_fast_reorg` 设置为 `OFF`,则 `ADD INDEX` 作为事务执行。如果在 `ADD INDEX` 执行期间目标列中存在许多更新操作(例如 `UPDATE` 和 `REPLACE`),则较大的批量大小表示事务冲突的可能性更大。在这种情况下,建议您将批量大小设置为较小的值。最小值是 32。 + - 如果不存在事务冲突,或者如果 `tidb_ddl_enable_fast_reorg` 设置为 `ON`,则可以将批量大小设置为较大的值。这使得数据回填更快,但也增加了 TiKV 的写入压力。对于合适的批量大小,您还需要参考 `tidb_ddl_reorg_worker_cnt` 的值。有关参考,请参阅 [在线工作负载和 `ADD INDEX` 操作的交互测试](https://docs.pingcap.com/tidb/dev/online-workloads-and-add-index-operations)。 - - 当设置 `tidb_ddl_enable_fast_reorg` 为 `OFF` 时,`ADD INDEX` 会通过事务的方式执行,执行时如果 `ADD INDEX` 的目标列有较多 `UPDATE` 或者 `REPLACE` 等更新操作,batch size 设置的值越大,事务冲突的概率也会越大。此时建议调小 batch size 的值,最小值是 32。 - - 在没有事务冲突的情况下,或者当 `tidb_ddl_enable_fast_reorg` 为 `ON` 时,batch size 可设为较大值,这样回填数据的速度更快,但是 TiKV 的写入压力也会变大。设置 batch size 时需要参考 `tidb_ddl_reorg_worker_cnt` 的设置值,详情见[线上负载与 `ADD INDEX` 相互影响测试](/benchmark/online-workloads-and-add-index-operations.md)。 +### tidb_ddl_reorg_priority -### `tidb_ddl_reorg_priority` +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否支持 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`PRIORITY_LOW` -- 可选值:`PRIORITY_LOW`、`PRIORITY_NORMAL`、`PRIORITY_HIGH` -- 这个变量用来设置 `ADD INDEX` 操作 `re-organize` 阶段的执行优先级,可设置为 `PRIORITY_LOW`/`PRIORITY_NORMAL`/`PRIORITY_HIGH`。 +- 值选项:`PRIORITY_LOW`,`PRIORITY_NORMAL`,`PRIORITY_HIGH` +- 此变量用于设置在 `re-organize` 阶段执行 `ADD INDEX` 操作的优先级。 +- 您可以将此变量的值设置为 `PRIORITY_LOW`、`PRIORITY_NORMAL` 或 `PRIORITY_HIGH`。 + +### tidb_ddl_reorg_worker_cnt -### `tidb_ddl_reorg_worker_cnt` +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`4` - 范围:`[1, 256]` - 单位:线程 -- 这个变量用来设置 DDL 操作 `re-organize` 阶段的并发度。 +- 此变量用于设置 `re-organize` 阶段 DDL 操作的并发度。 -### `tidb_enable_fast_create_table` 从 v8.0.0 版本开始引入 +### `tidb_enable_fast_create_table` v8.0.0 新增 > **警告:** > -> 该变量目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 此变量目前是一项实验性功能,不建议在生产环境中使用。此功能可能会更改或删除,恕不另行通知。如果您发现错误,请在 GitHub 上提出 [issue](https://github.com/pingcap/tidb/issues) 进行反馈。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用于控制是否开启 [TiDB 加速建表](/accelerated-table-creation.md)。 -- 从 TiDB v8.0.0 开始,支持使用 `tidb_enable_fast_create_table` 加速建表 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md)。 -- 该变量是由 v7.6.0 中引入的 [`tidb_ddl_version`](https://docs.pingcap.com/zh/tidb/v7.6/system-variables#tidb_ddl_version-从-v760-版本开始引入) 更名而来。从 v8.0.0 开始,`tidb_ddl_version` 不再生效。 +- 此变量用于控制是否启用 [TiDB 加速建表](/accelerated-table-creation.md)。 +- 从 v8.0.0 开始,TiDB 支持使用 `tidb_enable_fast_create_table` 通过 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 语句加速建表。 +- 此变量是从 v7.6.0 中引入的变量 [`tidb_ddl_version`](https://docs.pingcap.com/tidb/v7.6/system-variables#tidb_ddl_version-new-in-v760) 重命名的。从 v8.0.0 开始,`tidb_ddl_version` 不再生效。 -### `tidb_default_string_match_selectivity` 从 v6.2.0 版本开始引入 +### tidb_default_string_match_selectivity v6.2.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float - 默认值:`0.8` - 范围:`[0, 1]` -- 这个变量用来设置过滤条件中的 `like`、`rlike`、`regexp` 函数在行数估算时的默认选择率,以及是否对这些函数启用 TopN 辅助估算。 -- TiDB 总是会尝试利用统计信息对过滤条件中的 `like` 进行估算,但是当 `like` 匹配的字符串太复杂时,或者面对 `rlike` 或 `regexp` 时,往往无法充分利用统计信息,转而使用 `0.8` 作为选择率,造成行数估算的误差较大。 -- 该变量可以用于修改这个行为,当变量被设为 `0` 以外的值时,会使用变量的值而不是默认的 `0.8` 作为选择率。 -- 如果将该变量的值设为 `0`,TiDB 在对上述三个函数进行行数估算时,会尝试利用统计信息中的 TopN 进行求值来提高估算精度,同时也会考虑统计信息中的 NULL 数。求值操作预计会造成少量性能损耗。这个功能生效的前提是统计信息是在 [`tidb_analyze_version`](#tidb_analyze_version-从-v510-版本开始引入) 设为 `2` 时收集的。 -- 当该变量的值被设为默认值以外的值的时候,会对 `not like`、`not rlike`、`not regexp` 的行数估算也进行相应的调整。 +- 此变量用于设置在估计行数时,过滤器条件中 `like`、`rlike` 和 `regexp` 函数的默认选择性。此变量还控制是否启用 TopN 来帮助估计这些函数。 +- TiDB 尝试使用统计信息来估计过滤器条件中的 `like`。但是,当 `like` 匹配复杂的字符串,或者使用 `rlike` 或 `regexp` 时,TiDB 通常无法完全使用统计信息,而是将默认值 `0.8` 设置为选择性比率,从而导致不准确的估计。 +- 此变量用于更改上述行为。如果将该变量设置为 `0` 以外的值,则选择性比率是指定的变量值,而不是 `0.8`。 +- 如果将该变量设置为 `0`,TiDB 会尝试使用统计信息中的 TopN 进行评估,以提高准确性,并在估计上述三个函数时考虑统计信息中的 NULL 数量。前提是在 [`tidb_analyze_version`](#tidb_analyze_version-new-in-v510) 设置为 `2` 时收集统计信息。这种评估可能会稍微影响性能。 +- 如果将该变量设置为 `0.8` 以外的值,TiDB 会相应地调整对 `not like`、`not rlike` 和 `not regexp` 的估计。 -### `tidb_disable_txn_auto_retry` +### tidb_disable_txn_auto_retry > **警告:** > -> 从 v8.0.0 开始,该变量被废弃。废弃后,TiDB 不再支持乐观事务的自动重试。作为替代,当使用乐观事务模式发生冲突时,请在应用里捕获错误并重试,或改用[悲观事务模式](/pessimistic-transaction.md)。 +> 从 v8.0.0 开始,此变量已弃用,TiDB 不再支持乐观事务的自动重试。作为替代方案,当遇到乐观事务冲突时,您可以在应用程序中捕获错误并重试事务,或者改用 [悲观事务模式](/pessimistic-transaction.md)。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来设置是否禁用显式的乐观事务自动重试,设置为 `ON` 时,不会自动重试,如果遇到事务冲突需要在应用层重试。 +- 此变量用于设置是否禁用显式乐观事务的自动重试。默认值 `ON` 表示事务不会在 TiDB 中自动重试,并且 `COMMIT` 语句可能会返回需要在应用程序层处理的错误。 + + 将值设置为 `OFF` 表示 TiDB 将自动重试事务,从而减少 `COMMIT` 语句中的错误。更改此设置时要小心,因为它可能会导致更新丢失。 + + 此变量不影响自动提交的隐式事务和 TiDB 中内部执行的事务。这些事务的最大重试次数由 `tidb_retry_limit` 的值决定。 - 如果将该变量的值设为 `OFF`,TiDB 将会自动重试事务,这样在事务提交时遇到的错误更少。需要注意的是,这样可能会导致数据更新丢失。 + 有关更多详细信息,请参见 [重试限制](/optimistic-transaction.md#limits-of-retry)。 - 这个变量不会影响自动提交的隐式事务和 TiDB 内部执行的事务,它们依旧会根据 `tidb_retry_limit` 的值来决定最大重试次数。 + - 关于是否需要禁用自动重试,请参考[重试的局限性](/optimistic-transaction.md#重试的局限性)。 + 此变量仅适用于乐观事务,不适用于悲观事务。悲观事务的重试次数由 [`max_retry_count`](/tidb-configuration-file.md#max-retry-count) 控制。 - 该变量只适用于乐观事务,不适用于悲观事务。悲观事务的重试次数由 [`max_retry_count`](/tidb-configuration-file.md#max-retry-count) 控制。 + -### `tidb_distsql_scan_concurrency` + + + 此变量仅适用于乐观事务,不适用于悲观事务。悲观事务的重试次数为 256。 + + + +### tidb_distsql_scan_concurrency - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`15` - 范围:`[1, 256]` - 单位:线程 -- 这个变量用来设置 scan 操作的并发度。 -- AP 类应用适合较大的值,TP 类应用适合较小的值。对于 AP 类应用,最大值建议不要超过所有 TiKV 节点的 CPU 核数。 -- 若表的分区较多可以适当调小该参数(取决于扫描数据量的大小以及扫描频率),避免 TiKV 内存溢出 (OOM)。 -- 对于仅包含 `LIMIT` 子句的简单查询,如果 `LIMIT` 行数小于 100000,该查询的 scan 操作被下推到 TiKV 时,会将该变量的值视为 `1` 进行处理,以提升执行效率。 -- 对于查询语句 `SELECT MAX/MIN(col) FROM ...`,如果 `col` 列有索引且该索引的顺序与 `MAX(col)` 或 `MIN(col)` 函数所需的顺序一致,TiDB 会将该查询改写为 `SELECT col FROM ... LIMIT 1` 进行处理,该变量的值也将视为 `1` 进行处理。例如,对于 `SELECT MIN(col) FROM ...`,如果 `col` 列有升序排列的索引,TiDB 通过将该查询改写为 `SELECT col FROM ... LIMIT 1`,可以直接读取该索引中第一条数据,从而快速得到 `MIN(col)` 值。 +- 此变量用于设置 `scan` 操作的并发度。 +- 在 OLAP 场景中使用较大的值,在 OLTP 场景中使用较小的值。 +- 对于 OLAP 场景,最大值不应超过所有 TiKV 节点的 CPU 核心数。 +- 如果表有很多分区,您可以适当减小变量值(由要扫描的数据大小和扫描频率决定),以避免 TiKV 内存不足 (OOM)。 +- 对于只有 `LIMIT` 子句的简单查询,如果 `LIMIT` 值小于 100000,则下推到 TiKV 的扫描操作会将此变量的值视为 `1`,以提高执行效率。 +- 对于 `SELECT MAX/MIN(col) FROM ...` 查询,如果 `col` 列具有以 `MAX(col)` 或 `MIN(col)` 函数所需的相同顺序排序的索引,TiDB 会将查询重写为 `SELECT col FROM ... LIMIT 1` 进行处理,并且此变量的值也将被处理为 `1`。例如,对于 `SELECT MIN(col) FROM ...`,如果 `col` 列具有升序索引,TiDB 可以通过将查询重写为 `SELECT col FROM ... LIMIT 1` 并直接读取索引的第一行来快速获得 `MIN(col)` 值。 -### `tidb_dml_batch_size` +### tidb_dml_batch_size > **警告:** > -> 该变量与废弃的 batch-dml 特性相关,可能会导致数据损坏。因此,不建议开启该变量来使用 batch-dml。作为替代,请使用[非事务 DML 语句](/non-transactional-dml.md)。 +> 此变量与已弃用的 batch-dml 功能相关联,该功能可能会导致数据损坏。因此,不建议为 batch-dml 启用此变量。而是使用 [非事务性 DML](/non-transactional-dml.md)。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` - 范围:`[0, 2147483647]` - 单位:行 -- 这个变量的值大于 `0` 时,TiDB 会将 `INSERT` 语句在更小的事务中批量提交。这样可减少内存使用,确保大批量修改时事务大小不会达到 `txn-total-size-limit` 限制。 -- 只有变量值为 `0` 时才符合 ACID 要求。否则无法保证 TiDB 的原子性和隔离性要求。 -- 要使该特性生效,还需要开启 `tidb_enable_batch_dml`,以及至少开启 `tidb_batch_insert` 和 `tidb_batch_delete` 中的一个。 +- 当此值大于 `0` 时,TiDB 会将 `INSERT` 等语句批量提交到较小的事务中。这减少了内存使用量,并有助于确保批量修改不会达到 `txn-total-size-limit`。 +- 只有值 `0` 提供 ACID 兼容性。将此值设置为任何其他值将破坏 TiDB 的原子性和隔离性保证。 +- 要使此变量生效,您还需要启用 `tidb_enable_batch_dml` 和 `tidb_batch_insert` 和 `tidb_batch_delete` 中的至少一个。 > **注意:** > -> 自 v7.0.0 起,`tidb_dml_batch_size` 对 [`LOAD DATA` 语句](/sql-statements/sql-statement-load-data.md)不再生效。 +> 从 v7.0.0 开始,`tidb_dml_batch_size` 不再对 [`LOAD DATA` 语句](/sql-statements/sql-statement-load-data.md) 生效。 -### `tidb_dml_type` 从 v8.0.0 版本开始引入 +### tidb_dml_type v8.0.0 新增 > **警告:** > -> 批量 DML 执行方式 (`tidb_dml_type = "bulk"`) 目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。在当前版本中,使用批量 DML 执行方式执行超大事务时,可能会影响 TiCDC、TiFlash 和 TiKV 的 resolved-ts 模块的内存使用和执行效率,可能引发 OOM 问题。此外,BR 在遇到锁时也可能被阻塞无法继续执行。因此,不建议在启用这些组件和功能时使用。 +> 批量 DML 执行模式 (`tidb_dml_type = "bulk"`) 是一项实验性功能。不建议在生产环境中使用。此功能可能会更改或删除,恕不另行通知。如果您发现错误,可以报告 [issue](https://github.com/pingcap/tidb/issues)。在当前版本中,当 TiDB 使用批量 DML 模式执行大型事务时,可能会影响 TiCDC、TiFlash 和 TiKV 的 resolved-ts 模块的内存使用和执行效率,并可能导致 OOM 问题。此外,BR 可能会被阻塞,并且在遇到锁时无法处理。因此,不建议在启用这些组件或功能时使用此模式。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:字符串 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:String - 默认值:`"standard"` -- 可选值:`"standard"`、`"bulk"` -- 该变量用来设置 DML 语句的执行方式。 - - `"standard"` 表示使用标准的 DML 执行方式,TiDB 事务在提交前缓存在内存中。适用于处理高并发且可能存在冲突的事务场景,为默认推荐使用的执行方式。 - - `"bulk"` 表示使用批量 DML 执行方式,适合于处理因大量数据写入导致 TiDB 内存使用过多的情况。 - - 在 TiDB 事务执行过程中,数据不是完全缓存在 TiDB 内存中,而是持续写入 TiKV,以减少内存的占用,同时平滑写入压力。 - - 只有 `INSERT`、`UPDATE`、`REPLACE` 和 `DELETE` 语句受 `"bulk"` 方式的影响。由于 `"bulk"` 模式流水线执行的方式,其中 `INSERT IGNORE ... ON DUPLICATE UPDATE ...` 的用法可能会在更新造成冲突时报出 `Duplicate entry` 的错误;而在 `"standard"` 模式下,由于设置了 `IGNORE` 关键字,该错误会被忽略,不会返回给用户。 - - `"bulk"` 方式仅适用于大批量**无冲突数据写入**的场景,不能高效处理写入冲突的场景,写写冲突可能会导致大批量事务提交失败并被回滚。 - - `"bulk"` 方式只对自动提交 (auto-commit) 的语句生效。当设置为 `"bulk"` 时,[`pessimistic-auto-commit`](/tidb-configuration-file.md#pessimistic-auto-commit) 配置项的效果等同于设置为 `false`。 - - 使用 `"bulk"` 方式执行语句时,需要确保在语句执行过程中保持[元数据锁](/metadata-lock.md)处于开启状态。 - - `"bulk"` 方式不可以在[临时表](/temporary-tables.md)、[缓存表](/cached-tables.md)上使用。 - - `"bulk"` 方式不可以在开启外键约束检查时 (`foreign_key_checks = ON`) 对包含外键的表和被外键引用的表使用。 - - 当遇到不支持或不兼容的情况时,`"bulk"` 方式会回退到 `"standard"` 方式执行,并返回一条警告信息。你可以通过 [`tidb_last_txn_info`](#tidb_last_txn_info-从-v409-版本开始引入) 查看 `pipelined` 字段,如果为 `true` 则表示是使用 `"bulk"` 方式执行。 - - 以 `"bulk"` 方式执行超大事务时,事务耗时可能较长。对于这种模式的事务,其事务锁的最大 TTL 为 [`max-txn-ttl`](/tidb-configuration-file.md#max-txn-ttl) 与 24 小时中的较大值。此外,当事务执行时间超过 [`tidb_gc_max_wait_time`](#tidb_gc_max_wait_time-从-v610-版本开始引入) 设定值后,GC 可能会强制回滚事务,导致事务失败。 - - 以 `"bulk"` 方式执行事务时,事务的大小不受 TiDB 配置项 [`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit) 的限制。 - - `"bulk"` 方式由 Pipelined DML 特性实现,详细设计和 GitHub issue 可见 [Pipelined DML](https://github.com/pingcap/tidb/blob/release-8.1/docs/design/2024-01-09-pipelined-DML.md) 和 [#50215](https://github.com/pingcap/tidb/issues/50215)。 - -### `tidb_enable_1pc` 从 v5.0 版本开始引入 +- 可选值:`"standard"`, `"bulk"` +- 此变量控制 DML 语句的执行模式。 + - `"standard"` 表示标准 DML 执行模式,其中 TiDB 事务在提交之前缓存在内存中。此模式适用于具有潜在冲突的高并发事务场景,是默认推荐的执行模式。 + - `"bulk"` 表示批量 DML 执行模式,适用于写入大量数据导致 TiDB 内存使用过多的场景。 + - 在 TiDB 事务执行期间,数据不会完全缓存在 TiDB 内存中,而是持续写入 TiKV 以减少内存使用并平滑写入压力。 + - 只有 `INSERT`、`UPDATE`、`REPLACE` 和 `DELETE` 语句受 `"bulk"` 模式影响。由于 `"bulk"` 模式下的流水线式执行,当更新导致冲突时,使用 `INSERT IGNORE ... ON DUPLICATE UPDATE ...` 可能会导致 `Duplicate entry` 错误。 相比之下,在 `"standard"` 模式下,由于设置了 `IGNORE` 关键字,此错误将被忽略,不会返回给用户。 + - `"bulk"` 模式仅适用于**写入大量数据且没有冲突**的场景。此模式对于处理写入冲突效率不高,因为写入-写入冲突可能导致大型事务失败并回滚。 + - `"bulk"` 模式仅对启用自动提交的语句生效,并且需要将 [`pessimistic-auto-commit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#pessimistic-auto-commit-new-in-v600) 配置项设置为 `false`。 + - 使用 `"bulk"` 模式执行语句时,请确保在执行过程中 [metadata lock](/metadata-lock.md) 保持启用状态。 + - `"bulk"` 模式不能用于 [临时表](/temporary-tables.md) 和 [缓存表](/cached-tables.md)。 + - 当外键约束检查启用 (`foreign_key_checks = ON`) 时,`"bulk"` 模式不能用于包含外键的表和被外键引用的表。 + - 在环境不支持或与 `"bulk"` 模式不兼容的情况下,TiDB 会回退到 `"standard"` 模式并返回警告消息。要验证是否使用了 `"bulk"` 模式,可以使用 [`tidb_last_txn_info`](#tidb_last_txn_info-new-in-v409) 检查 `pipelined` 字段。`true` 值表示使用了 `"bulk"` 模式。 + - 在 `"bulk"` 模式下执行大型事务时,事务持续时间可能会很长。对于此模式下的事务,事务锁的最大 TTL 是 [`max-txn-ttl`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#max-txn-ttl) 和 24 小时之间的较大值。此外,如果事务执行时间超过了 [`tidb_gc_max_wait_time`](#tidb_gc_max_wait_time-new-in-v610) 设置的值,GC 可能会强制回滚事务,导致事务失败。 + - 当 TiDB 在 `"bulk"` 模式下执行事务时,事务大小不受 TiDB 配置项 [`txn-total-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-total-size-limit) 的限制。 + - 此模式由 Pipelined DML 功能实现。有关详细设计和 GitHub issue,请参阅 [Pipelined DML](https://github.com/pingcap/tidb/blob/release-8.1/docs/design/2024-01-09-pipelined-DML.md) 和 [#50215](https://github.com/pingcap/tidb/issues/50215)。 + +### tidb_enable_1pc New in v5.0 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 指定是否在只涉及一个 Region 的事务上启用一阶段提交特性。比起传统两阶段提交,一阶段提交能大幅降低事务提交延迟并提升吞吐。 +- 此变量用于指定是否为仅影响一个 Region 的事务启用单阶段提交功能。与常用的两阶段提交相比,单阶段提交可以大大减少事务提交的延迟并提高吞吐量。 > **注意:** > -> - 对于新创建的集群,默认值为 ON。对于升级版本的集群,如果升级前是 v5.0 以下版本,升级后默认值为 `OFF`。 -> - 启用 TiDB Binlog 后,开启该选项无法获得性能提升。要获得性能提升,建议使用 [TiCDC](/ticdc/ticdc-overview.md) 替代 TiDB Binlog。 -> - 启用该参数仅意味着一阶段提交成为可选的事务提交模式,实际由 TiDB 自行判断选择最合适的提交模式进行事务提交。 +> - 默认值 `ON` 仅适用于新集群。如果您的集群是从早期版本的 TiDB 升级而来,则将使用值 `OFF`。 +> - 如果您已启用 TiDB Binlog,则启用此变量无法提高性能。为了提高性能,建议使用 [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) 代替。 +> - 启用此参数仅意味着单阶段提交成为事务提交的可选模式。实际上,最合适的事务提交模式由 TiDB 决定。 -### `tidb_enable_analyze_snapshot` 从 v6.2.0 版本开始引入 +### tidb_enable_analyze_snapshot New in v6.2.0 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量控制 `ANALYZE` 读取历史时刻的数据还是读取最新的数据。当该变量设置为 `ON` 时,`ANALYZE` 读取 `ANALYZE` 开始时刻的历史数据。当该变量设置为 `OFF` 时,`ANALYZE` 读取最新的数据。 -- 在 v5.2 之前,`ANALYZE` 读取最新的数据。v5.2 至 v6.1 版本 `ANALYZE` 读取 `ANALYZE` 开始时刻的历史数据。 +- 此变量控制执行 `ANALYZE` 时是读取历史数据还是最新数据。如果此变量设置为 `ON`,则 `ANALYZE` 读取 `ANALYZE` 时可用的历史数据。如果此变量设置为 `OFF`,则 `ANALYZE` 读取最新数据。 +- 在 v5.2 之前,`ANALYZE` 读取最新数据。从 v5.2 到 v6.1,`ANALYZE` 读取 `ANALYZE` 时可用的历史数据。 > **警告:** > -> 如果 `ANALYZE` 读取 `ANALYZE` 开始时刻的历史数据,长时间的 `AUTO ANALYZE` 可能会因为历史数据被 GC 而出现 `GC life time is shorter than transaction duration` 的报错。 +> 如果 `ANALYZE` 读取 `ANALYZE` 时可用的历史数据,则 `AUTO ANALYZE` 的长时间运行可能会导致 `GC life time is shorter than transaction duration` 错误,因为历史数据已被垃圾回收。 + +### tidb_enable_async_commit New in v5.0 -### `tidb_enable_async_commit` 从 v5.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 该变量控制是否启用 Async Commit 特性,使事务两阶段提交的第二阶段于后台异步进行。开启本特性能降低事务提交的延迟。 +- 此变量控制是否启用异步提交功能,以便在两阶段事务提交的第二阶段在后台异步执行。启用此功能可以减少事务提交的延迟。 > **注意:** > -> - 对于新创建的集群,默认值为 ON。对于升级版本的集群,如果升级前是 v5.0 以下版本,升级后默认值为 `OFF`。 -> - 启用 TiDB Binlog 后,开启该选项无法获得性能提升。要获得性能提升,建议使用 [TiCDC](/ticdc/ticdc-overview.md) 替代 TiDB Binlog。 -> - 启用该参数仅意味着 Async Commit 成为可选的事务提交模式,实际由 TiDB 自行判断选择最合适的提交模式进行事务提交。 +> - 默认值 `ON` 仅适用于新集群。如果您的集群是从早期版本的 TiDB 升级而来,则将使用值 `OFF`。 +> - 如果您已启用 TiDB Binlog,则启用此变量无法提高性能。为了提高性能,建议使用 [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) 代替。 +> - 启用此参数仅意味着异步提交成为事务提交的可选模式。实际上,最合适的事务提交模式由 TiDB 决定。 -### `tidb_enable_auto_analyze` 从 v6.1.0 版本开始引入 +### tidb_enable_auto_analyze New in v6.1.0 -- 作用域:GLOBAL +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 + +- 范围:全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`ON` -- 该变量控制 TiDB 是否以后台操作自动更新表的统计信息。 -- 在 v6.1.0 之前这个开关通过 TiDB 配置文件 (`performance.run-auto-analyze`) 进行配置,升级到 v6.1.0 时会自动继承原有设置。 +- 决定 TiDB 是否自动更新表统计信息作为后台操作。 +- 此设置以前是 `tidb.toml` 选项 (`performance.run-auto-analyze`),但从 TiDB v6.1.0 开始更改为系统变量。 -### `tidb_enable_auto_analyze_priority_queue` 从 v8.0.0 版本开始引入 +### tidb_enable_auto_analyze_priority_queue v8.0.0 新增 -- 作用域:GLOBAL +- 范围:全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`ON` -- 该变量控制是否启用优先队列来调度自动收集统计信息的任务。开启该变量后,TiDB 会优先收集那些更有收集价值的表,例如新创建的索引、发生分区变更的分区表等。同时,TiDB 也会优先处理那些健康度较低的表,将它们安排在队列的前端。 +- 此变量用于控制是否启用优先级队列来调度自动收集统计信息的任务。启用此变量后,TiDB 会优先收集对收集更有价值的表的统计信息,例如新创建的索引和具有分区更改的分区表。此外,TiDB 会优先处理健康评分较低的表,将其放在队列的前面。 -### `tidb_enable_auto_increment_in_generated` +### tidb_enable_auto_increment_in_generated -- 作用域:SESSION | GLOBAL +- 范围:会话 | 全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`OFF` -- 这个变量用于控制是否允许在创建生成列或者表达式索引时引用自增列。 +- 此变量用于确定在创建生成列或表达式索引时是否包含 `AUTO_INCREMENT` 列。 -### `tidb_enable_batch_dml` +### tidb_enable_batch_dml > **警告:** > -> 该变量与废弃的 batch-dml 特性相关,可能会导致数据损坏。因此,不建议开启该变量来使用 batch-dml。作为替代,请使用[非事务 DML 语句](/non-transactional-dml.md)。 +> 此变量与已弃用的 batch-dml 功能相关联,可能会导致数据损坏。因此,不建议为 batch-dml 启用此变量。请改用[非事务性 DML](/non-transactional-dml.md)。 -- 作用域:GLOBAL +- 范围:全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`OFF` -- 该变量控制是否启用废弃的 batch-dml 特性。启用该变量后,部分语句可能会被拆分为多个事务执行,这是非原子性的,使用时需谨慎。使用 batch-dml 时,必须确保正在操作的数据没有并发操作。要使该变量生效,还需要为 `tidb_batch_dml_size` 指定一个正值,并启用 `tidb_batch_insert` 和 `tidb_batch_delete` 中的至少一个。 +- 此变量控制是否启用已弃用的 batch-dml 功能。启用后,某些语句可能会拆分为多个事务,这是非原子的,应谨慎使用。使用 batch-dml 时,必须确保您操作的数据上没有并发操作。要使其工作,您还必须为 `tidb_batch_dml_size` 指定一个正值,并启用 `tidb_batch_insert` 和 `tidb_batch_delete` 中的至少一个。 -### `tidb_enable_cascades_planner` +### tidb_enable_cascades_planner > **警告:** > -> 目前 cascades planner 为实验特性,不建议在生产环境中使用。 +> 目前,cascades planner 是一项实验性功能。不建议在生产环境中使用它。 -- 作用域:SESSION | GLOBAL +- 范围:会话 | 全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:布尔型 - 默认值:`OFF` -- 这个变量用于控制是否开启 cascades planner。 +- 此变量用于控制是否启用 cascades planner。 -### `tidb_enable_check_constraint` 从 v7.2.0 版本开始引入 +### tidb_enable_check_constraint v7.2.0 新增 -- 作用域:GLOBAL +- 范围:全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`OFF` -- 这个变量用于控制是否启用 [`CHECK` 约束](/constraints.md#check-约束)。 +- 此变量用于控制是否启用 [`CHECK` 约束](/constraints.md#check)功能。 -### `tidb_enable_chunk_rpc` 从 v4.0 版本开始引入 +### tidb_enable_chunk_rpc v4.0 新增 -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 范围:会话 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`ON` -- 这个变量用来设置是否启用 Coprocessor 的 `Chunk` 数据编码格式。 +- 此变量用于控制是否在 Coprocessor 中启用 `Chunk` 数据编码格式。 -### `tidb_enable_clustered_index` 从 v5.0 版本开始引入 +### tidb_enable_clustered_index v5.0 新增 -- 作用域:SESSION | GLOBAL +- 范围:会话 | 全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:枚举 - 默认值:`ON` -- 可选值:`OFF`,`ON`,`INT_ONLY` -- 这个变量用于控制默认情况下表的主键是否使用[聚簇索引](/clustered-indexes.md)。“默认情况”即不显式指定 `CLUSTERED`/`NONCLUSTERED` 关键字的情况。可设置为 `OFF`/`ON`/`INT_ONLY`。 - - `OFF` 表示所有主键默认使用非聚簇索引。 - - `ON` 表示所有主键默认使用聚簇索引。 - - `INT_ONLY` 此时的行为受配置项 `alter-primary-key` 控制。如果该配置项取值为 `true`,则所有主键默认使用非聚簇索引;如果该配置项取值为 `false`,则由单个整数类型的列构成的主键默认使用聚簇索引,其他类型的主键默认使用非聚簇索引。 +- 可选值:`OFF`、`ON`、`INT_ONLY` +- 此变量用于控制是否默认将主键创建为[聚簇索引](/clustered-indexes.md)。“默认”是指语句未显式指定关键字 `CLUSTERED`/`NONCLUSTERED`。支持的值为 `OFF`、`ON` 和 `INT_ONLY`: + - `OFF` 表示默认将主键创建为非聚簇索引。 + - `ON` 表示默认将主键创建为聚簇索引。 + - `INT_ONLY` 表示该行为由配置项 `alter-primary-key` 控制。如果 `alter-primary-key` 设置为 `true`,则默认将所有主键创建为非聚簇索引。如果设置为 `false`,则仅将由整数列组成的主键创建为聚簇索引。 -### `tidb_enable_collect_execution_info` +### tidb_enable_ddl v6.3.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 + +- 范围:全局 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`ON` +- 可选值:`OFF`、`ON` +- 此变量控制相应的 TiDB 实例是否可以成为 DDL 所有者。如果当前 TiDB 集群中只有一个 TiDB 实例,则无法阻止其成为 DDL 所有者,这意味着您无法将其设置为 `OFF`。 + +### tidb_enable_collect_execution_info + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + +- 范围:全局 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`ON` -- 这个变量用于控制是否同时将各个执行算子的执行信息记录入 slow query log 中,以及是否维护[访问索引有关的统计信息](/information-schema/information-schema-tidb-index-usage.md)。 +- 此变量控制是否在慢查询日志中记录每个算子的执行信息,以及是否记录[索引的使用统计信息](/information-schema/information-schema-tidb-index-usage.md)。 -### `tidb_enable_column_tracking` 从 v5.4.0 版本开始引入 +### tidb_enable_column_tracking v5.4.0 新增 > **警告:** > -> 收集 `PREDICATE COLUMNS` 的统计信息目前为实验特性,不建议在生产环境中使用。 +> 目前,收集 `PREDICATE COLUMNS` 的统计信息是一项实验性功能。不建议在生产环境中使用它。 -- 作用域:GLOBAL +- 范围:全局 - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`OFF` -- 这个变量用于控制是否开启 TiDB 对 `PREDICATE COLUMNS` 的收集。关闭该变量后,之前收集的 `PREDICATE COLUMNS` 会被清除。详情见[收集部分列的统计信息](/statistics.md#收集部分列的统计信息)。 +- 此变量控制是否启用 TiDB 收集 `PREDICATE COLUMNS`。启用收集后,如果禁用它,则会清除先前收集的 `PREDICATE COLUMNS` 的信息。有关详细信息,请参见[收集某些列的统计信息](/statistics.md#collect-statistics-on-some-columns)。 -### `tidb_enable_ddl` 从 v6.3.0 版本开始引入 +### tidb_enable_enhanced_security -- 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`ON` -- 可选值:`OFF`,`ON` -- 用于设置该 TiDB 实例是否可以成为 DDL owner。若当前 TiDB 集群中只有一台 TiDB 实例,则不能禁止该实例成为 DDL owner,即不能设置为 `OFF`。 +- 范围:无 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔型 -### `tidb_enable_enhanced_security` + -- 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 - 默认值:`OFF` -- 这个变量表示所连接的 TiDB 服务器是否启用了安全增强模式 (SEM)。若要改变该变量值,你需要在 TiDB 服务器的配置文件中修改 `enable-sem` 项的值,并重启 TiDB 服务器。 -- 安全增强模式受[安全增强式 Linux](https://zh.wikipedia.org/wiki/安全增强式Linux) 等系统设计的启发,削减拥有 MySQL `SUPER` 权限的用户能力,转而使用细粒度的 `RESTRICTED` 权限作为替代。这些细粒度的 `RESTRICTED` 权限如下: - - `RESTRICTED_TABLES_ADMIN`:能够写入 `mysql` 库中的系统表,能查看 `information_schema` 表上的敏感列。 - - `RESTRICTED_STATUS_ADMIN`:能够在 `SHOW STATUS` 命令中查看敏感内容。 - - `RESTRICTED_VARIABLES_ADMIN`:能够在 `SHOW [GLOBAL] VARIABLES` 和 `SET` 命令中查看和设置包含敏感内容的变量。 - - `RESTRICTED_USER_ADMIN`:能够阻止其他用户更改或删除用户帐户。 - - `RESTRICTED_CONNECTION_ADMIN`:能够阻止其它用户使用 `KILL` 语句终止连接。 +- 此变量指示您连接的 TiDB 服务器是否启用了安全增强模式 (SEM)。要更改其值,您需要修改 TiDB 服务器配置文件中 `enable-sem` 的值并重新启动 TiDB 服务器。 + + + + -### `tidb_enable_exchange_partition` +- 默认值:`ON` +- 此变量是只读的。对于 TiDB Cloud,默认启用安全增强模式 (SEM)。 + + + +- SEM 的灵感来自 [Security-Enhanced Linux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) 等系统的设计。它减少了具有 MySQL `SUPER` 权限的用户的能力,而是需要授予 `RESTRICTED` 细粒度权限作为替代。这些细粒度权限包括: + - `RESTRICTED_TABLES_ADMIN`:能够将数据写入 `mysql` schema 中的系统表,并查看 `information_schema` 表上的敏感列。 + - `RESTRICTED_STATUS_ADMIN`:能够查看命令 `SHOW STATUS` 中的敏感变量。 + - `RESTRICTED_VARIABLES_ADMIN`:能够查看和设置 `SHOW [GLOBAL] VARIABLES` 和 `SET` 中的敏感变量。 +- `RESTRICTED_USER_ADMIN`: 阻止其他用户更改或删除用户帐户的能力。 + +### tidb_enable_exchange_partition - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 该变量用于设置是否启用 [`exchange partitions with tables`](/partitioned-table.md#分区管理) 特性。默认值为 `ON`,即默认开启该功能。 -- 该变量自 v6.3.0 开始废弃,其取值将固定为默认值 `ON`,即默认开启 `exchange partitions with tables`。 +- 此变量控制是否启用 [`exchange partitions with tables`](/partitioned-table.md#partition-management) 功能。默认值为 `ON`,即默认启用 `exchange partitions with tables`。 +- 此变量自 v6.3.0 起已弃用。它的值将固定为默认值 `ON`,即默认启用 `exchange partitions with tables`。 -### `tidb_enable_extended_stats` +### tidb_enable_extended_stats - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 该变量指定 TiDB 是否收集[扩展统计信息](/extended-statistics.md)来指导优化器。 +- 此变量指示 TiDB 是否可以收集扩展统计信息来指导优化器。有关更多信息,请参见[扩展统计信息简介](/extended-statistics.md)。 -### `tidb_enable_external_ts_read` 从 v6.4.0 版本开始引入 +### tidb_enable_external_ts_read v6.4.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 当此变量设置为 `ON` 时,TiDB 会读取 [`tidb_external_ts`](#tidb_external_ts-从-v640-版本开始引入) 指定时间戳前的历史数据。 +- 如果此变量设置为 `ON`,TiDB 会使用 [`tidb_external_ts`](#tidb_external_ts-new-in-v640) 指定的时间戳读取数据。 -### `tidb_external_ts` 从 v6.4.0 版本开始引入 +### tidb_external_ts v6.4.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` -- 当 [`tidb_enable_external_ts_read`](#tidb_enable_external_ts_read-从-v640-版本开始引入) 设置为 `ON` 时,TiDB 会依据该变量指定的时间戳读取历史数据。 +- 如果 [`tidb_enable_external_ts_read`](#tidb_enable_external_ts_read-new-in-v640) 设置为 `ON`,TiDB 会使用此变量指定的时间戳读取数据。 -### `tidb_restricted_read_only` 从 v5.2.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 可选值:`OFF` 和 `ON` -- `tidb_restricted_read_only`和 [`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入) 的作用相似。在大多数情况下,你只需要使用 [`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入) 即可。 -- 拥有 `SUPER` 或 `SYSTEM_VARIABLES_ADMIN` 权限的用户可以修改该变量。如果 TiDB 开启了[安全增强模式](#tidb_enable_enhanced_security),你还需要额外的 `RESTRICTED_VARIABLES_ADMIN` 权限才能读取或修改该变量。 -- `tidb_restricted_read_only` 的设置将影响 [`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入) 的值: - - - 当设置 `tidb_restricted_read_only` 为 `ON` 时,[`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入) 的将自动被设置为 `ON`。 - - 当设置 `tidb_restricted_read_only` 为 `OFF` 时,[`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入) 的值将不受影响。 - - 当 `tidb_restricted_read_only` 为 `ON` 时,[`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入) 的值无法设置为 `OFF`。 - -- 对于 TiDB 的 DBaaS 供应商,当 TiDB 为另一个数据库的下游数据库时,如果要将整个 TiDB 集群设置为只读模式,你需要开启[安全增强模式](#tidb_enable_enhanced_security) 并将 `tidb_restricted_read_only` 设置为 `ON`,从而防止你的用户通过 [`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入) 将 TiDB 集群设置为可写。实现方法:首先开启[安全增强模式](#tidb_enable_enhanced_security),然后由你(作为 DBaaS 的控制面)使用一个 admin 用户控制 `tidb_restricted_read_only`(需要拥有 `SYSTEM_VARIABLES_ADMIN` 和 `RESTRICTED_VARIABLES_ADMIN` 权限),由你的数据库用户使用 root 用户控制 [`tidb_super_read_only`](#tidb_super_read_only-从-v531-版本开始引入)(需要拥有 `SUPER` 权限)。 -- 该变量可以控制整个集群的只读状态。开启后(即该值为 `ON`),整个集群中的 TiDB 服务器都将进入只读状态,只有 `SELECT`、`USE`、`SHOW` 等不会修改数据的语句才能被执行,其他如 `INSERT`、`UPDATE` 等语句会被拒绝执行。 -- 该变量开启只读模式只保证整个集群最终进入只读模式,当变量修改状态还没被同步到其他 TiDB 服务器时,尚未同步的 TiDB 仍然停留在非只读模式。 -- 在执行 SQL 语句之前,TiDB 会检查集群的只读标志。从 v6.2.0 起,在提交 SQL 语句之前,TiDB 也会检查该标志,从而防止在服务器被置于只读模式后某些长期运行的 [auto commit](/transaction-overview.md#自动提交) 语句可能修改数据的情况。 -- 在变量开启时,对于尚未提交的事务: - - 如果有尚未提交的只读事务,可正常提交该事务。 - - 如果尚未提交的事务为非只读事务,在事务内执行写入的 SQL 语句会被拒绝。 - - 如果尚未提交的事务已经有数据改动,其提交也会被拒绝。 -- 当集群开启只读模式后,所有用户(包括 `SUPER` 用户)都无法执行可能写入数据的 SQL 语句,除非该用户被显式地授予了 `RESTRICTED_REPLICA_WRITER_ADMIN` 权限。 - -### `tidb_enable_fast_analyze` +### tidb_enable_fast_analyze > **警告:** > -> 从 v7.5.0 开始,该变量被废弃。 +> 从 v7.5.0 开始,此变量已弃用。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来控制是否启用统计信息快速分析功能。默认值 0 表示不开启。 -- 快速分析功能开启后,TiDB 会随机采样约 10000 行的数据来构建统计信息。因此在数据分布不均匀或者数据量比较少的情况下,统计信息的准确度会比较低。这可能导致执行计划不优,比如选错索引。如果可以接受普通 `ANALYZE` 语句的执行时间,则推荐关闭快速分析功能。 +- 此变量用于设置是否启用统计信息 `Fast Analyze` 功能。 +- 如果启用了统计信息 `Fast Analyze` 功能,TiDB 会随机抽样大约 10,000 行数据作为统计信息。当数据分布不均匀或数据量较小时,统计信息的准确性较低。这可能会导致非最佳执行计划,例如,选择错误的索引。如果常规 `Analyze` 语句的执行时间可以接受,建议禁用 `Fast Analyze` 功能。 -### `tidb_enable_fast_table_check` 从 v7.2.0 版本开始引入 +### tidb_enable_fast_table_check v7.2.0 新增 > **注意:** > -> 该功能对[多值索引](/sql-statements/sql-statement-create-index.md#多值索引)和前缀索引不生效。 +> 此变量不适用于[多值索引](/sql-statements/sql-statement-create-index.md#multi-valued-indexes)和前缀索引。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于控制是否使用基于校验和的方式来快速检查表中数据和索引的一致性。默认值 `ON` 表示该功能默认开启。 -- 开启后,TiDB 执行 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 语句的速度更快。 +- 此变量用于控制是否使用基于校验和的方法来快速检查表中数据和索引的完整性。默认值 `ON` 表示默认启用此功能。 +- 启用此变量后,TiDB 可以更快地执行 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 语句。 -### `tidb_enable_foreign_key` 从 v6.3.0 版本开始引入 +### tidb_enable_foreign_key v6.3.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:在 v6.6.0 之前版本中为 `OFF`,在 v6.6.0 及之后的版本中为 `ON`。 -- 这个变量用于控制是否开启 `FOREIGN KEY` 特性。 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:v6.6.0 之前,默认值为 `OFF`。从 v6.6.0 开始,默认值为 `ON`。 +- 此变量控制是否启用 `FOREIGN KEY` 功能。 -### `tidb_enable_gc_aware_memory_track` +### tidb_enable_gc_aware_memory_track > **警告:** > -> 该变量为 TiDB 内部调试变量,可能会在未来版本中删除,**请勿**设置该变量。 +> 此变量是 TiDB 中用于调试的内部变量。它可能会在未来的版本中被删除。**请勿**设置此变量。 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用于控制是否开启可感知到垃圾回收的内存追踪 (GC-Aware memory track)。 +- 此变量控制是否启用 GC-Aware 内存跟踪。 -### `tidb_enable_global_index` 从 v7.6.0 版本开始引入 +### tidb_enable_global_index v7.6.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` - 可选值:`OFF`,`ON` -- 这个变量用于控制是否支持对分区表创建 `Global index`。`Global index` 当前正处于开发阶段,**不推荐修改该变量值**。 +- 此变量控制是否支持为分区表创建 `Global indexes`。`Global index` 目前处于开发阶段。**不建议修改此系统变量的值**。 -### `tidb_enable_non_prepared_plan_cache` +### tidb_enable_non_prepared_plan_cache - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来控制是否开启[非 Prepare 语句执行计划缓存](/sql-non-prepared-plan-cache.md)。 -- 开启此功能可能会带来额外的内存和 CPU 开销,并不一定适用于所有场景,请根据具体的使用情况决定是否开启该功能。 +- 此变量控制是否启用 [Non-prepared plan cache](/sql-non-prepared-plan-cache.md) 功能。 +- 启用此功能可能会产生额外的内存和 CPU 开销,并且可能不适用于所有情况。请根据您的实际情况确定是否启用此功能。 -### `tidb_enable_non_prepared_plan_cache_for_dml` 从 v7.1.0 版本开始引入 +### tidb_enable_non_prepared_plan_cache_for_dml v7.1.0 新增 > **警告:** > -> 针对 DML 语句的非 Prepare 语句执行计划缓存目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 用于 DML 语句的非预备执行计划缓存是一项实验性功能。不建议在生产环境中使用它。此功能可能会更改或删除,恕不另行通知。如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用来控制[非 Prepare 语句执行计划缓存](/sql-non-prepared-plan-cache.md)是否支持 DML 语句。 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:`OFF`。 +- 此变量控制是否为 DML 语句启用 [Non-prepared plan cache](/sql-non-prepared-plan-cache.md) 功能。 -### `tidb_enable_gogc_tuner` 从 v6.4.0 版本开始引入 +### tidb_enable_gogc_tuner v6.4.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 该变量来用控制是否开启 GOGC Tuner。 +- 此变量控制是否启用 GOGC Tuner。 -### `tidb_enable_historical_stats` +### tidb_enable_historical_stats - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制是否开启历史统计信息。默认值为 `ON` 表示默认开启历史统计信息。 +- 此变量控制是否启用历史统计信息。默认值从 `OFF` 更改为 `ON`,这意味着默认启用历史统计信息。 -### `tidb_enable_historical_stats_for_capture` +### tidb_enable_historical_stats_for_capture > **警告:** > -> 当前版本中该变量控制的功能尚未完全生效,请保留默认值。 +> 此变量控制的功能在当前 TiDB 版本中尚未完全实现。请勿更改默认值。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来控制 `PLAN REPLAYER CAPTURE` 抓取的内容是否默认带历史统计信息。默认值为 `OFF`,表示默认不带历史统计信息。 +- 此变量控制 `PLAN REPLAYER CAPTURE` 捕获的信息是否默认包含历史统计信息。默认值 `OFF` 表示默认不包含历史统计信息。 -### `tidb_enable_index_merge` 从 v4.0 版本开始引入 +### tidb_enable_index_merge v4.0 新增 > **注意:** > -> - 当集群从 v4.0.0 以下版本升级到 v5.4.0 及以上版本时,该变量开关默认关闭,防止升级后计划发生变化导致回退。 -> - 当集群从 v4.0.0 及以上版本升级到 v5.4.0 及以上版本时,该变量开关保持升级前的状态。 -> - 对于 v5.4.0 及以上版本的新建集群,该变量开关默认开启。 +> - 将 TiDB 集群从低于 v4.0.0 的版本升级到 v5.4.0 或更高版本后,默认情况下禁用此变量,以防止由于执行计划的更改而导致性能下降。 +> +> - 将 TiDB 集群从 v4.0.0 或更高版本升级到 v5.4.0 或更高版本后,此变量保持升级前的设置。 +> +> - 自 v5.4.0 起,对于新部署的 TiDB 集群,默认启用此变量。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于控制是否开启 index merge 功能。 +- 此变量用于控制是否启用索引合并功能。 -### `tidb_enable_index_merge_join` +### tidb_enable_index_merge_join - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 表示是否启用 `IndexMergeJoin` 算子。 -- 该变量为 TiDB 内部变量,**不推荐使用**,否则可能会造成数据正确性问题。 +- 指定是否启用 `IndexMergeJoin` 算子。 +- 此变量仅用于 TiDB 的内部操作。**不建议**调整它。否则,可能会影响数据的正确性。 -### `tidb_enable_legacy_instance_scope` 从 v6.0.0 版本开始引入 +### tidb_enable_legacy_instance_scope v6.0.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于允许使用 `SET SESSION` 对 `INSTANCE` 作用域的变量进行设置,用法同 `SET GLOBAL`。 -- 为了兼容之前的 TiDB 版本,该变量值默认为 `ON`。 +- 此变量允许使用 `SET SESSION` 以及 `SET GLOBAL` 语法来设置 `INSTANCE` 作用域的变量。 +- 默认启用此选项是为了与早期版本的 TiDB 兼容。 -### `tidb_enable_list_partition` 从 v5.0 版本开始引入 +### tidb_enable_list_partition v5.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来设置是否开启 `LIST (COLUMNS) TABLE PARTITION` 特性。 +- 此变量用于设置是否启用 `LIST (COLUMNS) TABLE PARTITION` 功能。 -### `tidb_enable_local_txn` +### tidb_enable_local_txn + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量用于一个未发布的特性,**请勿修改该变量值**。 +- 此变量用于尚未发布的功能。**请勿更改变量值**。 -### `tidb_enable_metadata_lock` 从 v6.3.0 版本开始引入 +### tidb_enable_metadata_lock v6.3.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来设置是否开启[元数据锁](/metadata-lock.md)特性。需要注意,在设置该变量时,集群中不能有 DDL 任务,以免造成非预期数据正确性、一致性问题。 +- 此变量用于设置是否启用 [Metadata lock](/metadata-lock.md) 功能。请注意,在设置此变量时,需要确保集群中没有正在运行的 DDL 语句。否则,数据可能不正确或不一致。 -### `tidb_enable_mutation_checker` 从 v6.0.0 版本开始引入 +### tidb_enable_mutation_checker v6.0.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于设置是否开启 mutation checker。mutation checker 是一项在 DML 语句执行过程中进行的数据索引一致性校验,校验报错会回滚当前语句。开启该校验会导致 CPU 使用轻微上升。详见[数据索引一致性报错](/troubleshoot-data-inconsistency-errors.md)。 -- 对于新创建的 v6.0.0 及以上的集群,默认值为 `ON`。对于升级版本的集群,如果升级前是低于 v6.0.0 的版本,升级后默认值为 `OFF`。 +- 此变量用于控制是否启用 TiDB mutation checker,该工具用于检查 DML 语句执行期间数据和索引之间的一致性。如果 checker 为某个语句返回错误,TiDB 会回滚该语句的执行。启用此变量会导致 CPU 使用率略有增加。有关更多信息,请参见 [解决数据和索引不一致问题](/troubleshoot-data-inconsistency-errors.md)。 +- 对于 v6.0.0 或更高版本的新集群,默认值为 `ON`。对于从早于 v6.0.0 的版本升级的现有集群,默认值为 `OFF`。 -### `tidb_enable_new_cost_interface` 从 v6.2.0 版本开始引入 +### tidb_enable_new_cost_interface v6.2.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- TiDB v6.2.0 对代价模型的实现进行了代码层面的重构,这个变量用来控制是否使用重构后的代价模型 [Cost Model Version 2](/cost-model.md#cost-model-version-2)。 -- 重构后的代价模型使用完全一样的代价公式,因此不会引起计划选择的变动,此开关默认打开。 -- 从 v6.1 升级至 v6.2 的用户,此开关保持升级前的 `OFF` 状态,此时建议直接打开;对于从 v6.1 之前版本升级至 v6.2 的用户,此开关默认为 `ON`。 +- TiDB v6.2.0 重构了之前成本模型的实现。此变量控制是否启用重构后的成本模型实现。 +- 默认启用此变量,因为重构后的成本模型使用与之前相同的成本公式,这不会改变计划决策。 +- 如果您的集群是从 v6.1 升级到 v6.2,则此变量保持 `OFF`,建议手动启用它。如果您的集群是从早于 v6.1 的版本升级的,则默认情况下此变量设置为 `ON`。 -### `tidb_enable_new_only_full_group_by_check` 从 v6.1.0 版本开始引入 +### tidb_enable_new_only_full_group_by_check v6.1.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 该变量用于控制 TiDB 执行 `ONLY_FULL_GROUP_BY` 检查时的行为。有关 `ONLY_FULL_GROUP_BY` 的信息可以参考 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_only_full_group_by)。在 v6.1 中 TiDB 对该项检查做了更严格正确的处理。 -- 由于可能存在版本升级造成的兼容性问题,在 v6.1 中该变量默认值是 `OFF`,即默认关闭。 +- 此变量控制 TiDB 执行 `ONLY_FULL_GROUP_BY` 检查时的行为。有关 `ONLY_FULL_GROUP_BY` 的详细信息,请参阅 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_only_full_group_by)。在 v6.1.0 中,TiDB 更严格和正确地处理此检查。 +- 为了避免版本升级可能导致的兼容性问题,此变量在 v6.1.0 中的默认值为 `OFF`。 -### `tidb_enable_noop_functions` 从 v4.0 版本开始引入 +### tidb_enable_noop_functions v4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`OFF` -- 可选值:`ON`、`OFF`、`WARN` -- 默认情况下,用户尝试将某些语法用于尚未实现的功能时,TiDB 会报错。若将该变量值设为 `ON`,TiDB 则自动忽略此类功能不可用的情况,即不会报错。若用户无法更改 SQL 代码,可考虑将变量值设为 `ON`。 -- 启用 `noop` 函数可以控制以下行为: +- 可能的值:`OFF`、`ON`、`WARN` +- 默认情况下,当您尝试使用尚未实现的功能的语法时,TiDB 会返回错误。当变量值设置为 `ON` 时,TiDB 会静默地忽略此类不可用功能的情况,如果您无法更改 SQL 代码,这将很有帮助。 +- 启用 `noop` 函数控制以下行为: * `LOCK IN SHARE MODE` 语法 * `SQL_CALC_FOUND_ROWS` 语法 * `START TRANSACTION READ ONLY` 和 `SET TRANSACTION READ ONLY` 语法 - * `tx_read_only`、`transaction_read_only`、`offline_mode`、`super_read_only`、`read_only` 以及 `sql_auto_is_null` 系统变量 + * `tx_read_only`、`transaction_read_only`、`offline_mode`、`super_read_only`、`read_only` 和 `sql_auto_is_null` 系统变量 * `GROUP BY ASC|DESC` 语法 > **警告:** > -> 该变量只有在默认值 `OFF` 时,才算是安全的。因为设置 `tidb_enable_noop_functions=1` 后,TiDB 会自动忽略某些语法而不报错,这可能会导致应用程序出现异常行为。例如,允许使用语法 `START TRANSACTION READ ONLY` 时,事务仍会处于读写模式。 +> 只有默认值 `OFF` 才能被认为是安全的。设置 `tidb_enable_noop_functions=1` 可能会导致应用程序中出现意外行为,因为它允许 TiDB 忽略某些语法而不提供错误。例如,允许使用语法 `START TRANSACTION READ ONLY`,但事务仍处于读写模式。 -### `tidb_enable_noop_variables` 从 v6.2.0 版本开始引入 +### tidb_enable_noop_variables v6.2.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`ON` -- 若该变量值为 `OFF`,TiDB 具有以下行为: - * 使用 `SET` 设置 `noop` 的系统变量时会报 `"setting *variable_name* has no effect in TiDB"` 的警告。 - * `SHOW [SESSION | GLOBAL] VARIABLES` 的结果不显示 `noop` 的系统变量。 - * 使用 `SELECT` 读取 `noop` 的系统变量时会报 `"variable *variable_name* has no effect in TiDB"` 的警告。 -- 你可以通过 `SELECT * FROM INFORMATION_SCHEMA.CLIENT_ERRORS_SUMMARY_GLOBAL;` 语句来检查 TiDB 实例是否曾设置和读取 `noop` 系统变量。 +- 如果您将变量值设置为 `OFF`,TiDB 的行为如下: + * 当您使用 `SET` 设置 `noop` 变量时,TiDB 返回 `“setting *variable_name* has no effect in TiDB”` 警告。 + * `SHOW [SESSION | GLOBAL] VARIABLES` 的结果不包括 `noop` 变量。 + * 当您使用 `SELECT` 读取 `noop` 变量时,TiDB 返回 `“variable *variable_name* has no effect in TiDB”` 警告。 +- 要检查 TiDB 实例是否已设置和读取 `noop` 变量,可以使用 `SELECT * FROM INFORMATION_SCHEMA.CLIENT_ERRORS_SUMMARY_GLOBAL;` 语句。 -### `tidb_enable_null_aware_anti_join` 从 v6.3.0 版本开始引入 +### tidb_enable_null_aware_anti_join v6.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:在 v7.0.0 之前版本中为 `OFF`,即默认关闭。在 v7.0.0 及之后的版本中为 `ON`,即默认开启。 -- 这个变量用于控制 TiDB 对特殊集合算子 `NOT IN` 和 `!= ALL` 引导的子查询产生的 ANTI JOIN 是否采用 Null Aware Hash Join 的执行方式。 -- 从旧版本升级到 v7.0.0 及之后版本,该功能自动开启,即该变量的值修改为默认值 `ON`。 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 默认值:在 v7.0.0 之前,默认值为 `OFF`。从 v7.0.0 开始,默认值为 `ON`。 +- 类型:Boolean +- 此变量控制当由特殊集合运算符 `NOT IN` 和 `!= ALL` 引导的子查询生成 ANTI JOIN 时,TiDB 是否应用 Null Aware Hash Join。 +- 当您从早期版本升级到 v7.0.0 或更高版本的集群时,该功能会自动启用,这意味着此变量设置为 `ON`。 -### `tidb_enable_outer_join_reorder` 从 v6.1.0 版本开始引入 +### tidb_enable_outer_join_reorder v6.1.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`ON` -- 自 v6.1.0 起,TiDB 的 [Join Reorder 算法](/join-reorder.md)开始支持 Outer Join。该变量用于控制是否启用 Outer Join 的 Join Reorder。 -- 对于从较低版本升级到当前版本的 TiDB: +- 从 v6.1.0 版本开始,TiDB 的 [Join Reorder](/join-reorder.md) 算法支持 Outer Join。此变量控制 TiDB 是否启用 Join Reorder 对 Outer Join 的支持。 +- 如果您的集群是从早期版本的 TiDB 升级而来,请注意以下事项: - - 如果升级前 TiDB 的版本低于 v6.1.0,升级后该变量的默认值为 `ON`。 - - 如果升级前 TiDB 的版本等于或大于 v6.1.0,升级后该变量的默认值跟随升级前的设定值。 + - 如果升级前的 TiDB 版本早于 v6.1.0,则升级后此变量的默认值为 `ON`。 + - 如果升级前的 TiDB 版本为 v6.1.0 或更高版本,则升级后此变量的默认值与升级前的值保持一致。 -### `tidb_enable_inl_join_inner_multi_pattern` 从 v7.0.0 版本开始引入 +### `tidb_enable_inl_join_inner_multi_pattern` v7.0.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 该变量用于控制当内表上有 `Selection`/`Projection` 算子时是否支持 Index Join。`OFF` 表示不支持。 +- 此变量控制当内表上有 `Selection` 或 `Projection` 算子时,是否支持 Index Join。默认值 `OFF` 表示在这种情况下不支持 Index Join。 -### `tidb_enable_ordered_result_mode` +### tidb_enable_ordered_result_mode - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 指定是否对最终的输出结果进行自动排序。 -- 例如,开启该变量后,TiDB 会将 `SELECT a, MAX(b) FROM t GROUP BY a` 处理为 `SELECT a, MAX(b) FROM t GROUP BY a ORDER BY a, MAX(b)`。 +- 指定是否自动对最终输出结果进行排序。 +- 例如,启用此变量后,TiDB 将 `SELECT a, MAX(b) FROM t GROUP BY a` 处理为 `SELECT a, MAX(b) FROM t GROUP BY a ORDER BY a, MAX(b)`。 -### `tidb_enable_paging` 从 v5.4.0 版本开始引入 +### tidb_enable_paging v5.4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于控制是否使用分页 (paging) 方式发送 Coprocessor 请求。对于 [v5.4.0, v6.2.0) 区间的 TiDB 版本,该变量只对 `IndexLookup` 算子生效;对于 v6.2.0 以及之后的版本,该变量对全局生效。从 v6.4.0 版本开始,该变量默认值由 `OFF` 改成 `ON`。 -- 适用场景: +- 此变量控制是否使用分页的方法发送 Coprocessor 请求。对于 [v5.4.0, v6.2.0) 中的 TiDB 版本,此变量仅对 `IndexLookup` 算子生效;对于 v6.2.0 及更高版本,此变量全局生效。从 v6.4.0 开始,此变量的默认值从 `OFF` 更改为 `ON`。 +- 用户场景: - - 推荐在所有偏 OLTP 的场景下使用 paging。 - - 对于使用 `IndexLookUp` 和 `Limit` 并且 `Limit` 无法下推到 `IndexScan` 上的读请求,可能会出现读请求的延迟高、TiKV 的 Unified read pool CPU 使用率高的情况。在这种情况下,由于 `Limit` 算子只需要少部分数据,开启 [`tidb_enable_paging`](#tidb_enable_paging-从-v540-版本开始引入) 能够减少处理数据的数量,从而降低延迟、减少资源消耗。 - - 对于 [Dumpling](/dumpling-overview.md) 数据导出或者全表扫描这类的场景,开启 paging 后可以有效降低 TiDB 进程的内存消耗。 + - 在所有 OLTP 场景中,建议使用分页方法。 + - 对于使用 `IndexLookup` 和 `Limit` 的读取查询,并且 `Limit` 无法下推到 `IndexScan`,读取查询可能存在高延迟,并且 TiKV `Unified read pool CPU` 的使用率很高。在这种情况下,由于 `Limit` 算子只需要少量数据,如果将 [`tidb_enable_paging`](#tidb_enable_paging-new-in-v540) 设置为 `ON`,TiDB 处理的数据量会减少,从而降低查询延迟和资源消耗。 + - 在使用 [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview) 进行数据导出和全表扫描等场景中,启用分页可以有效降低 TiDB 进程的内存消耗。 > **注意:** > -> 对于偏 OLAP 的场景,并且以 TiKV 而非 TiFlash 作为存储引擎时,开启 paging 可能导致部分场景下性能回退。此时,你可以考虑通过该变量关闭 paging 或者通过系统变量 [`tidb_min_paging_size`](/system-variables.md#tidb_min_paging_size-从-v620-版本开始引入) 和 [`tidb_max_paging_size`](/system-variables.md#tidb_max_paging_size-从-v630-版本开始引入) 调整 paging size 的行数范围。 +> 在使用 TiKV 作为存储引擎而不是 TiFlash 的 OLAP 场景中,启用分页在某些情况下可能会导致性能下降。如果发生性能下降,请考虑使用此变量禁用分页,或者使用 [`tidb_min_paging_size`](/system-variables.md#tidb_min_paging_size-new-in-v620) 和 [`tidb_max_paging_size`](/system-variables.md#tidb_max_paging_size-new-in-v630) 变量来调整分页大小的行数范围。 -### `tidb_enable_parallel_apply` 从 v5.0 版本开始引入 +### tidb_enable_parallel_apply v5.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用于控制是否开启 Apply 算子并发,并发数由 `tidb_executor_concurrency` 变量控制。Apply 算子用来处理关联子查询且默认无并发,所以执行速度较慢。打开 Apply 并发开关可增加并发度,提高执行速度。目前默认关闭。 +- 此变量控制是否为 `Apply` 算子启用并发。并发数由 `tidb_executor_concurrency` 变量控制。`Apply` 算子处理相关子查询,默认情况下没有并发,因此执行速度很慢。将此变量值设置为 `1` 可以增加并发并加快执行速度。目前,默认情况下禁用 `Apply` 的并发。 -### `tidb_enable_parallel_hashagg_spill` 从 v8.0.0 版本开始引入 +### tidb_enable_parallel_hashagg_spill v8.0.0 新增 > **警告:** > -> 该变量控制的功能为实验特性,不建议在生产环境上使用。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 目前,此变量控制的功能是实验性的。不建议在生产环境中使用。如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:在 v8.1.0 中为 `ON`,在 v8.1.1 及后续的 8.1 补丁版本中为 `OFF` -- 这个变量用来控制 TiDB 是否支持并行 HashAgg 进行落盘。当该变量设置为 `ON` 时,并行 HashAgg 将支持落盘。该变量将在功能正式发布后废弃。 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:v8.1.0 为 `ON`;v8.1.1 及之后的 8.1 patch 版本为 `OFF` +- 此变量控制 TiDB 是否支持并行 HashAgg 算法的磁盘溢出。当它为 `ON` 时,可以为并行 HashAgg 算法触发磁盘溢出。此变量将在未来版本中此功能普遍可用后被弃用。 -### `tidb_enable_pipelined_window_function` +### tidb_enable_pipelined_window_function - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 该变量指定是否对[窗口函数](/functions-and-operators/window-functions.md)采用流水线的执行算法。 +- 此变量指定是否对 [窗口函数](/functions-and-operators/window-functions.md) 使用流水线执行算法。 -### `tidb_enable_plan_cache_for_param_limit` 从 v6.6.0 版本开始引入 +### tidb_enable_plan_cache_for_param_limit v6.6.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制 Prepared Plan Cache 是否缓存 `LIMIT` 后面带变量 (`LIMIT ?`) 的执行计划。目前不支持缓存 `LIMIT` 后面带变量且变量值大于 10000 的执行计划。 +- 此变量控制 Prepared Plan Cache 是否缓存以变量作为 `LIMIT` 参数 (`LIMIT ?`) 的执行计划。默认值为 `ON`,表示 Prepared Plan Cache 支持缓存此类执行计划。请注意,Prepared Plan Cache 不支持缓存变量大于 10000 的执行计划。 -### `tidb_enable_plan_cache_for_subquery` 从 v7.0.0 版本开始引入 +### tidb_enable_plan_cache_for_subquery v7.0.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制 Prepared Plan Cache 是否缓存包含子查询的查询。 +- 此变量控制 Prepared Plan Cache 是否缓存包含子查询的查询。 -### `tidb_enable_plan_replayer_capture` +### tidb_enable_plan_replayer_capture + + - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:`ON` +- 此变量控制是否启用 `PLAN REPLAYER CAPTURE` 功能。默认值 `ON` 表示启用 `PLAN REPLAYER CAPTURE` 功能。 + + + + + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制是否开启 [`PLAN REPLAYER CAPTURE` 功能](/sql-plan-replayer.md#使用-plan-replayer-capture-抓取目标计划)。默认值 `ON` 代表开启 `PLAN REPLAYER CAPTURE` 功能。 +- 此变量控制是否启用 [`PLAN REPLAYER CAPTURE` 功能](/sql-plan-replayer.md#use-plan-replayer-capture-to-capture-target-plans)。默认值 `ON` 表示启用 `PLAN REPLAYER CAPTURE` 功能。 -### `tidb_enable_plan_replayer_continuous_capture` 从 v7.0.0 版本开始引入 + + +### tidb_enable_plan_replayer_continuous_capture v7.0.0 新增 + + - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来控制是否开启 [`PLAN REPLAYER CONTINUOUS CAPTURE` 功能](/sql-plan-replayer.md#使用-plan-replayer-continuous-capture)。默认值 `OFF` 代表关闭功能。 +- 此变量控制是否启用 `PLAN REPLAYER CONTINUOUS CAPTURE` 功能。默认值 `OFF` 表示禁用该功能。 -### `tidb_enable_prepared_plan_cache` 从 v6.1.0 版本开始引入 + + + - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:`OFF` +- 此变量控制是否启用 [`PLAN REPLAYER CONTINUOUS CAPTURE` 功能](/sql-plan-replayer.md#use-plan-replayer-continuous-capture)。默认值 `OFF` 表示禁用该功能。 + + + +### tidb_enable_prepared_plan_cache v6.1.0 新增 + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:布尔型 - 默认值:`ON` -- 这个变量用来控制是否开启 [Prepared Plan Cache](/sql-prepared-plan-cache.md)。开启后,对 `Prepare`、`Execute` 请求的执行计划会进行缓存,以便在后续执行时跳过查询计划优化这个步骤,获得性能上的提升。 -- 在 v6.1.0 之前这个开关通过 TiDB 配置文件 (`prepared-plan-cache.enabled`) 进行配置,升级到 v6.1.0 时会自动继承原有设置。 +- 决定是否启用 [Prepared Plan Cache](/sql-prepared-plan-cache.md)。启用后,`Prepare` 和 `Execute` 的执行计划会被缓存,以便后续执行跳过优化执行计划的步骤,从而提高性能。 +- 此设置之前是 `tidb.toml` 中的一个选项 (`prepared-plan-cache.enabled`),但从 TiDB v6.1.0 开始更改为系统变量。 -### `tidb_enable_prepared_plan_cache_memory_monitor` 从 v6.4.0 版本开始引入 +### tidb_enable_prepared_plan_cache_memory_monitor v6.4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`ON` -- 这个变量用来控制是否统计 Prepared Plan Cache 中所缓存的执行计划占用的内存。具体可见 [Prepared Plan Cache 的内存管理](/sql-prepared-plan-cache.md#prepared-plan-cache-的内存管理)。 +- 此变量控制是否统计 Prepared Plan Cache 中缓存的执行计划所消耗的内存。有关详细信息,请参阅 [Prepared Plan Cache 的内存管理](/sql-prepared-plan-cache.md#memory-management-of-prepared-plan-cache)。 -### `tidb_enable_pseudo_for_outdated_stats` 从 v5.3.0 版本开始引入 +### tidb_enable_pseudo_for_outdated_stats v5.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:布尔型 - 默认值:`OFF` -- 这个变量用来控制优化器在一张表上的统计信息过期时的行为。 -- 统计信息过期的判断标准:最近一次对某张表执行 `ANALYZE` 获得统计信息后,该表数据被修改的行数大于该表总行数的 80%,便可判定该表的统计信息已过期。该比例可通过 [`pseudo-estimate-ratio`](/tidb-configuration-file.md#pseudo-estimate-ratio) 配置参数调整。 -- 默认情况下(即该变量值为 `OFF` 时),某张表上的统计信息过期后,优化器仍会使用该表上的统计信息。将该变量值设为 `ON` 时,当统计信息过期后,优化器认为该表上除总行数以外的统计信息不再可靠,转而使用 pseudo 统计信息。 -- 如果表数据修改较频繁,没有及时对表执行 `ANALYZE`,但又希望执行计划保持稳定,推荐将该变量值设为 `OFF`。 +- 此变量控制优化器在表统计信息过期时使用该统计信息的行为。 + + + +- 优化器通过以下方式确定表的统计信息是否过期:自上次对表执行 `ANALYZE` 以获取统计信息以来,如果 80% 的表行被修改(修改的行数除以总行数),则优化器确定此表的统计信息已过期。您可以使用 [`pseudo-estimate-ratio`](/tidb-configuration-file.md#pseudo-estimate-ratio) 配置更改此比率。 + + + + + +- 优化器通过以下方式确定表的统计信息是否过期:自上次对表执行 `ANALYZE` 以获取统计信息以来,如果 80% 的表行被修改(修改的行数除以总行数),则优化器确定此表的统计信息已过期。 + + -### `tidb_enable_rate_limit_action` +- 默认情况下(变量值为 `OFF`),当表的统计信息过期时,优化器仍会继续使用该表的统计信息。如果将变量值设置为 `ON`,则优化器会确定该表的统计信息不再可靠,除非总行数。然后,优化器使用伪统计信息。 +- 如果表上的数据经常被修改而没有及时对该表执行 `ANALYZE`,为了保持执行计划的稳定,建议将变量值设置为 `OFF`。 + +### tidb_enable_rate_limit_action - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`OFF` -- 这个变量控制是否为读数据的算子开启动态内存控制功能。读数据的算子默认启用 [`tidb_distsql_scan_concurrency`](/system-variables.md#tidb_distsql_scan_concurrency) 所允许的最大线程数来读取数据。当单条 SQL 语句的内存使用每超过 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 一次,读数据的算子会停止一个线程。 -- 当读数据的算子只剩 1 个线程且当单条 SQL 语句的内存使用继续超过 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 时,该 SQL 语句会触发其它的内存控制行为,例如[落盘](/system-variables.md#tidb_enable_tmp_storage_on_oom)。 -- 该变量在单条查询仅涉及读数据的情况下,对内存控制效果较好。若还存在额外的计算操作(如连接、聚合等),打开该变量可能会导致内存不受 `tidb_mem_quota_query` 控制,加剧 OOM 风险。 +- 此变量控制是否为读取数据的算子启用动态内存控制功能。默认情况下,此算子启用 [`tidb_distsql_scan_concurrency`](/system-variables.md#tidb_distsql_scan_concurrency) 允许的最大线程数来读取数据。当单个 SQL 语句的内存使用量每次超过 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 时,读取数据的算子会停止一个线程。 + + + +- 当读取数据的算子只剩下一个线程,并且单个 SQL 语句的内存使用量持续超过 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 时,此 SQL 语句会触发其他内存控制行为,例如 [将数据溢出到磁盘](/system-variables.md#tidb_enable_tmp_storage_on_oom)。 +- 当 SQL 语句仅读取数据时,此变量可以有效地控制内存使用量。如果需要计算操作(例如连接或聚合操作),则内存使用量可能不受 `tidb_mem_quota_query` 的控制,这会增加 OOM 的风险。 + + + + + +- 当读取数据的算子只剩下一个线程,并且单个 SQL 语句的内存使用量继续超过 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 时,此 SQL 语句会触发其他内存控制行为,例如将数据溢出到磁盘。 + + -### `tidb_enable_resource_control` 从 v6.6.0 版本开始引入 +### tidb_enable_resource_control v6.6.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`ON` - 类型:布尔型 -- 该变量是[资源管控特性](/tidb-resource-control.md)的开关。该变量设置为 `ON` 时,集群支持应用按照资源组做资源隔离。 +- 此变量是 [资源控制功能](/tidb-resource-control.md) 的开关。当此变量设置为 `ON` 时,TiDB 集群可以基于资源组隔离应用程序资源。 -### `tidb_enable_reuse_chunk` 从 v6.4.0 版本开始引入 +### tidb_enable_reuse_chunk v6.4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`ON` - 可选值:`OFF`,`ON` -- 该变量用于控制 TiDB 是否启用 Chunk 对象缓存。如果为 `ON`,则优先使用缓存中的 Chunk 对象,缓存中找不到申请的对象时才会从系统内存中申请。如果为 `OFF`,则直接从系统内存中申请 Chunk 对象。 +- 此变量控制 TiDB 是否启用 chunk 对象缓存。如果值为 `ON`,TiDB 倾向于使用缓存的 chunk 对象,只有当请求的对象不在缓存中时才从系统请求。如果值为 `OFF`,TiDB 直接从系统请求 chunk 对象。 -### `tidb_enable_slow_log` +### tidb_enable_slow_log + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`ON` -- 这个变量用于控制是否开启 slow log 功能。 +- 此变量用于控制是否启用慢查询日志功能。 -### `tidb_enable_stmt_summary` 从 v3.0.4 版本开始引入 +### tidb_enable_tmp_storage_on_oom - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`ON` +- 可选值:`OFF`,`ON` +- 控制当单个 SQL 语句超过系统变量 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 指定的内存配额时,是否为某些算子启用临时存储。 +- 在 v6.3.0 之前,您可以使用 TiDB 配置项 `oom-use-tmp-storage` 启用或禁用此功能。将集群升级到 v6.3.0 或更高版本后,TiDB 集群将使用 `oom-use-tmp-storage` 的值自动初始化此变量。之后,更改 `oom-use-tmp-storage` 的值将**不再**生效。 + +### tidb_enable_stmt_summary v3.0.4 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 + +- 作用域:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`ON` -- 这个变量用来控制是否开启 statement summary 功能。如果开启,SQL 的耗时等执行信息将被记录到系统表 `information_schema.STATEMENTS_SUMMARY` 中,用于定位和排查 SQL 性能问题。 +- 此变量用于控制是否启用语句摘要功能。如果启用,SQL 执行信息(如时间消耗)将被记录到 `information_schema.STATEMENTS_SUMMARY` 系统表中,以识别和排除 SQL 性能问题。 -### `tidb_enable_strict_double_type_check` 从 v5.0 版本开始引入 +### tidb_enable_strict_double_type_check v5.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:布尔型 - 默认值:`ON` -- 这个变量用来控制是否可以用 `DOUBLE` 类型的无效定义创建表。该设置的目的是提供一个从 TiDB 早期版本升级的方法,因为早期版本在验证类型方面不太严格。 -- 该变量的默认值 `ON` 与 MySQL 兼容。 +- 此变量用于控制是否可以使用 `DOUBLE` 类型的无效定义创建表。此设置旨在提供从早期 TiDB 版本升级的途径,因为早期版本在验证类型方面不太严格。 +- 默认值 `ON` 与 MySQL 兼容。 -例如,由于无法保证浮点类型的精度,现在将 `DOUBLE(10)` 类型视为无效。将 `tidb_enable_strict_double_type_check` 更改为 `OFF` 后,将会创建表。如下所示: +例如,类型 `DOUBLE(10)` 现在被认为是无效的,因为浮点类型的精度无法保证。将 `tidb_enable_strict_double_type_check` 更改为 `OFF` 后,表将被创建: ```sql -CREATE TABLE t1 (id int, c double(10)); +mysql> CREATE TABLE t1 (id int, c double(10)); ERROR 1149 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use -SET tidb_enable_strict_double_type_check = 'OFF'; + +mysql> SET tidb_enable_strict_double_type_check = 'OFF'; Query OK, 0 rows affected (0.00 sec) -CREATE TABLE t1 (id int, c double(10)); + +mysql> CREATE TABLE t1 (id int, c double(10)); Query OK, 0 rows affected (0.09 sec) ``` > **注意:** > -> 该设置仅适用于 `DOUBLE` 类型,因为 MySQL 允许为 `FLOAT` 类型指定精度。从 MySQL 8.0.17 开始已弃用此行为,不建议为 `FLOAT` 或 `DOUBLE` 类型指定精度。 +> 此设置仅适用于 `DOUBLE` 类型,因为 MySQL 允许 `FLOAT` 类型的精度。从 MySQL 8.0.17 开始,此行为已被弃用,不建议为 `FLOAT` 或 `DOUBLE` 类型指定精度。 -### `tidb_enable_table_partition` +### tidb_enable_table_partition - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:枚举 - 默认值:`ON` -- 类型:枚举型 - 可选值:`OFF`,`ON`,`AUTO` -- 这个变量用来设置是否开启 `TABLE PARTITION` 特性。目前变量支持以下三种值: - - 默认值 `ON` 表示开启 TiDB 当前已实现了的分区表类型,目前 Range partition、Hash partition 以及 Range column 单列的场景会生效。 - - `AUTO` 目前作用和 `ON` 一样。 - - `OFF` 表示关闭 `TABLE PARTITION` 特性,此时语法还是保持兼容,只是创建的表并不是真正的分区表,而是普通的表。 +- 此变量用于设置是否启用 `TABLE PARTITION` 功能: + - `ON` 表示启用 Range 分区、Hash 分区和单列 Range 列分区。 + - `AUTO` 的功能与 `ON` 相同。 + - `OFF` 表示禁用 `TABLE PARTITION` 功能。在这种情况下,可以执行创建分区表的语法,但创建的表不是分区表。 -### `tidb_enable_telemetry` 从 v4.0.2 版本开始引入,从 v8.1.0 版本开始废弃 +### tidb_enable_telemetry v4.0.2 新增,v8.1.0 弃用 > **警告:** > -> 从 TiDB v8.1.0 开始,TiDB 已移除遥测功能,该变量已不再生效。保留该变量仅用于与之前版本兼容。 +> 从 v8.1.0 开始,TiDB 中的遥测功能已移除,此变量不再起作用。保留此变量仅是为了与早期版本兼容。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 在 v8.1.0 之前,这个变量用于动态地控制 TiDB 遥测功能是否开启。 -### `tidb_enable_tiflash_read_for_write_stmt` 从 v6.3.0 版本开始引入 + + +- 在 v8.1.0 之前,此变量控制是否启用 TiDB 中的遥测收集。 + + + + + +- 此 TiDB 变量不适用于 TiDB Cloud。 + + + +### tidb_enable_tiflash_read_for_write_stmt v6.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`ON` -- 这个变量用于控制包含增删改的 SQL 语句中的读取操作能否下推到 TiFlash,比如: +- 此变量控制包含 `INSERT`、`DELETE` 和 `UPDATE` 的 SQL 语句中的读取操作是否可以下推到 TiFlash。例如: - - `INSERT INTO SELECT` 语句中的 `SELECT` 查询(典型应用场景为 [TiFlash 查询结果物化](/tiflash/tiflash-results-materialization.md)) + - `INSERT INTO SELECT` 语句中的 `SELECT` 查询(典型使用场景:[TiFlash 查询结果物化](/tiflash/tiflash-results-materialization.md)) - `UPDATE` 和 `DELETE` 语句中的 `WHERE` 条件过滤 -- 从 v7.1.0 开始,该变量废弃。当 [`tidb_allow_mpp = ON`](/system-variables.md#tidb_allow_mpp-从-v50-版本开始引入) 时,优化器将根据 [SQL 模式](/sql-mode.md)及 TiFlash 副本的代价估算自行决定是否将查询下推至 TiFlash。需要注意的是,只有当前会话的 [SQL 模式](/sql-mode.md)为非严格模式(即 `sql_mode` 值不包含 `STRICT_TRANS_TABLES` 和 `STRICT_ALL_TABLES`)时,TiDB 才允许将包含增删改的 SQL 语句(如 `INSERT INTO SELECT`)中的读取操作下推至 TiFlash。 +- 从 v7.1.0 开始,此变量已被弃用。当 [`tidb_allow_mpp = ON`](/system-variables.md#tidb_allow_mpp-new-in-v50) 时,优化器会根据 [SQL 模式](/sql-mode.md) 和 TiFlash 副本的成本估算智能地决定是否将查询下推到 TiFlash。请注意,仅当当前会话的 [SQL 模式](/sql-mode.md) 不是严格模式时,TiDB 才允许将包含 `INSERT`、`DELETE` 和 `UPDATE` 的 SQL 语句(例如 `INSERT INTO SELECT`)中的读取操作下推到 TiFlash,这意味着 `sql_mode` 值不包含 `STRICT_TRANS_TABLES` 和 `STRICT_ALL_TABLES`。 -### `tidb_enable_tmp_storage_on_oom` +### tidb_enable_top_sql v5.4.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON` -- 设置是否在单条 SQL 语句的内存使用超出系统变量 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 限制时为某些算子启用临时磁盘。 -- 在 v6.3.0 之前这个开关可通过 TiDB 配置文件中的 `oom-use-tmp-storage` 项进行配置。在升级到 v6.3.0 及更新的版本后,集群会自动使用原 `oom-use-tmp-storage` 的值来初始化该开关,配置文件中 `oom-use-tmp-storage` 的新设置不再影响该开关。 - -### `tidb_enable_top_sql` 从 v5.4.0 版本开始引入 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 这个变量用于控制是否开启 [Top SQL 特性](/dashboard/top-sql.md)。 -### `tidb_enable_tso_follower_proxy` 从 v5.3.0 版本开始引入 + + +- 此变量用于控制是否启用 [Top SQL](/dashboard/top-sql.md) 功能。 + + + + + +- 此变量用于控制是否启用 [Top SQL](https://docs.pingcap.com/tidb/stable/top-sql) 功能。 + + + +### tidb_enable_tso_follower_proxy v5.3.0 新增 + +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless),此变量是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 这个变量用于控制是否开启 TSO Follower Proxy 特性。当该值为 `OFF` 时,TiDB 仅会从 PD leader 获取 TSO。当该值为 `ON` 时,TiDB 在获取 TSO 时会将请求均匀地发送到所有 PD 节点上,因此 PD follower 也可以处理 TSO 请求,从而减轻 PD leader 的 CPU 压力。 -- 适合开启 TSO Follower Proxy 的场景: - * PD leader 因高压力的 TSO 请求而达到 CPU 瓶颈,导致 TSO RPC 请求的延迟较高。 - * 集群中的 TiDB 实例数量较多,且调高 [`tidb_tso_client_batch_max_wait_time`](/system-variables.md#tidb_tso_client_batch_max_wait_time-从-v530-版本开始引入) 并不能缓解 TSO RPC 请求延迟高的问题。 +- 此变量控制是否启用 TSO Follower Proxy 功能。当值为 `OFF` 时,TiDB 仅从 PD leader 获取 TSO。当值为 `ON` 时,TiDB 将 TSO 请求均匀地分配给所有 PD 服务器,PD follower 也可以处理 TSO 请求,从而降低 PD leader 的 CPU 压力。 +- 启用 TSO Follower Proxy 的场景: + * 由于 TSO 请求压力过大,PD leader 的 CPU 达到瓶颈,导致 TSO RPC 请求的延迟较高。 + * TiDB 集群有许多 TiDB 实例,并且增加 [`tidb_tso_client_batch_max_wait_time`](#tidb_tso_client_batch_max_wait_time-new-in-v530) 的值无法缓解 TSO RPC 请求的高延迟问题。 > **注意:** > -> 如果 PD leader 的 TSO RPC 延迟升高,但其现象并非由 CPU 使用率达到瓶颈而导致(可能存在网络等问题),此时,打开 TSO Follower Proxy 可能会导致 TiDB 的语句执行延迟上升,从而影响集群的 QPS 表现。 +> 假设 TSO RPC 延迟增加的原因不是 PD leader 的 CPU 使用率瓶颈(例如网络问题)。在这种情况下,启用 TSO Follower Proxy 可能会增加 TiDB 中的执行延迟并影响集群的 QPS 性能。 -### `tidb_enable_unsafe_substitute` 从 v6.3.0 版本开始引入 +### tidb_enable_unsafe_substitute v6.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 这个变量用于控制是否对生成列中表达式替换使用不安全的替换方式。默认值为 `OFF`,即默认关闭不安全的替换方式。详情见[生成列](/generated-columns.md)。 +- 此变量控制是否以不安全的方式将表达式替换为生成列。默认值为 `OFF`,表示默认禁用不安全替换。有关更多详细信息,请参见 [生成列](/generated-columns.md)。 -### `tidb_enable_vectorized_expression` 从 v4.0 版本开始引入 +### tidb_enable_vectorized_expression v4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:布尔值 - 默认值:`ON` -- 这个变量用于控制是否开启向量化执行。 +- 此变量用于控制是否启用向量化执行。 -### `tidb_enable_window_function` +### tidb_enable_window_function - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`ON` -- 这个变量用来控制是否开启[窗口函数](/functions-and-operators/window-functions.md)的支持。 -- 由于窗口函数会使用一些保留关键字,可能导致原先可以正常执行的 SQL 语句在升级 TiDB 后无法被解析语法,此时可以将 `tidb_enable_window_function` 设置为 `OFF`。 +- 此变量用于控制是否启用对 [窗口函数](/functions-and-operators/window-functions.md) 的支持。请注意,窗口函数可能会使用保留关键字。这可能会导致原本可以正常执行的 SQL 语句在 TiDB 升级后无法解析。在这种情况下,您可以将 `tidb_enable_window_function` 设置为 `OFF`。 -### `tidb_enable_row_level_checksum` 从 v7.1.0 版本开始引入 +### `tidb_enable_row_level_checksum` v7.1.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔值 - 默认值:`OFF` -- 这个变量用于控制是否开启 [TiCDC 单行数据正确性校验](/ticdc/ticdc-integrity-check.md)功能。 -- 你可以使用 [`TIDB_ROW_CHECKSUM()`](/functions-and-operators/tidb-functions.md#tidb_row_checksum) 函数查询行数据的 Checksum 值。 -### `tidb_enforce_mpp` 从 v5.1 版本开始引入 + + +- 此变量用于控制是否启用 [TiCDC 单行数据的数据完整性验证](/ticdc/ticdc-integrity-check.md) 功能。 + + + + + +- 此变量用于控制是否启用 [TiCDC 单行数据的数据完整性验证](https://docs.pingcap.com/tidb/stable/ticdc-integrity-check) 功能。 + + + +- 您可以使用 [`TIDB_ROW_CHECKSUM()`](/functions-and-operators/tidb-functions.md#tidb_row_checksum) 函数来获取行的校验和值。 + +### tidb_enforce_mpp v5.1 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`OFF`(表示关闭)。如需修改此变量的默认值,请配置 [`performance.enforce-mpp`](/tidb-configuration-file.md#enforce-mpp) 参数。 -- 这个变量用于控制是否忽略优化器代价估算,强制使用 TiFlash 的 MPP 模式执行查询,可以设置的值包括: - - 0 或 OFF,代表不强制使用 MPP 模式(默认) - - 1 或 ON,代表将忽略代价估算,强制使用 MPP 模式。注意:只有当 `tidb_allow_mpp=true` 时该设置才生效。 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean +- 默认值:`OFF` + + + +- 要更改此默认值,请修改 [`performance.enforce-mpp`](/tidb-configuration-file.md#enforce-mpp) 配置值。 + + -MPP 是 TiFlash 引擎提供的分布式计算框架,允许节点之间的数据交换并提供高性能、高吞吐的 SQL 算法。MPP 模式选择的详细说明参见[控制是否选择 MPP 模式](/tiflash/use-tiflash-mpp-mode.md#控制是否选择-mpp-模式)。 +- 控制是否忽略优化器的成本估算,并强制使用 TiFlash 的 MPP 模式执行查询。取值选项如下: + - `0` 或 `OFF`,表示不强制使用 MPP 模式(默认)。 + - `1` 或 `ON`,表示忽略成本估算,强制使用 MPP 模式。请注意,此设置仅在 `tidb_allow_mpp=true` 时生效。 -### `tidb_evolve_plan_baselines` 从 v4.0 版本开始引入 +MPP 是 TiFlash 引擎提供的分布式计算框架,支持节点间的数据交换,并提供高性能、高吞吐量的 SQL 算法。有关 MPP 模式选择的详细信息,请参考 [控制是否选择 MPP 模式](/tiflash/use-tiflash-mpp-mode.md#control-whether-to-select-the-mpp-mode)。 + +### tidb_evolve_plan_baselines v4.0 新增 > **警告:** > -> 该变量控制的功能为实验特性,不建议在生产环境中使用。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 此变量控制的功能为实验性功能。不建议在生产环境中使用。如果发现 Bug,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用于控制是否启用自动演进绑定功能。该功能的详细介绍和使用方法可以参考[自动演进绑定](/sql-plan-management.md#自动演进绑定-baseline-evolution)。 -- 为了减少自动演进对集群的影响,可以进行以下配置: +- 此变量用于控制是否启用基线演进功能。有关详细介绍或用法,请参见 [基线演进](/sql-plan-management.md#baseline-evolution)。 +- 为了减少基线演进对集群的影响,请使用以下配置: + - 设置 `tidb_evolve_plan_task_max_time` 以限制每个执行计划的最大执行时间。默认值为 600 秒。 + - 设置 `tidb_evolve_plan_task_start_time` 和 `tidb_evolve_plan_task_end_time` 以限制时间窗口。默认值分别为 `00:00 +0000` 和 `23:59 +0000`。 - - 设置 `tidb_evolve_plan_task_max_time`,限制每个执行计划运行的最长时间,其默认值为 600s; - - 设置`tidb_evolve_plan_task_start_time` 和 `tidb_evolve_plan_task_end_time`,限制运行演进任务的时间窗口,默认值分别为 `00:00 +0000` 和 `23:59 +0000`。 - -### `tidb_evolve_plan_task_end_time` 从 v4.0 版本开始引入 +### tidb_evolve_plan_task_end_time v4.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:时间 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Time - 默认值:`23:59 +0000` -- 这个变量用来设置一天中允许自动演进的结束时间。 +- 此变量用于设置一天中基线演进的结束时间。 -### `tidb_evolve_plan_task_max_time` 从 v4.0 版本开始引入 +### tidb_evolve_plan_task_max_time v4.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`600` - 范围:`[-1, 9223372036854775807]` - 单位:秒 -- 该变量用于限制自动演进功能中,每个执行计划运行的最长时间。 +- 此变量用于限制基线演进功能中每个执行计划的最大执行时间。 -### `tidb_evolve_plan_task_start_time` 从 v4.0 版本开始引入 +### tidb_evolve_plan_task_start_time v4.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:时间 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Time - 默认值:`00:00 +0000` -- 这个变量用来设置一天中允许自动演进的开始时间。 +- 此变量用于设置一天中基线演进的开始时间。 -### `tidb_executor_concurrency` 从 v5.0 版本开始引入 +### tidb_executor_concurrency v5.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`5` - 范围:`[1, 256]` - 单位:线程 -变量用来统一设置各个 SQL 算子的并发度,包括: +此变量用于设置以下 SQL 算子的并发度(设置为一个值): - `index lookup` - `index lookup join` - `hash join` -- `hash aggregation`(partial 和 final 阶段) +- `hash aggregation`(`partial` 和 `final` 阶段) - `window` - `projection` -`tidb_executor_concurrency` 整合了已有的系统变量,方便管理。这些变量所列如下: +`tidb_executor_concurrency` 将以下现有系统变量作为一个整体进行合并,以便于管理: + `tidb_index_lookup_concurrency` + `tidb_index_lookup_join_concurrency` @@ -2537,948 +2870,1177 @@ MPP 是 TiFlash 引擎提供的分布式计算框架,允许节点之间的数 + `tidb_projection_concurrency` + `tidb_window_concurrency` -v5.0 后,用户仍可以单独修改以上系统变量(会有废弃警告),且修改只影响单个算子。后续通过 `tidb_executor_concurrency` 的修改也不会影响该算子。若要通过 `tidb_executor_concurrency` 来管理所有算子的并发度,需要将以上所列变量的值设置为 `-1`。 +自 v5.0 起,您仍然可以单独修改上面列出的系统变量(会返回弃用警告),并且您的修改只会影响相应的单个算子。之后,如果您使用 `tidb_executor_concurrency` 修改算子并发度,则单独修改的算子将不受影响。如果您想使用 `tidb_executor_concurrency` 修改所有算子的并发度,可以将上面列出的所有变量的值设置为 `-1`。 + +对于从早期版本升级到 v5.0 的系统,如果您没有修改上面列出的任何变量的值(这意味着 `tidb_hash_join_concurrency` 的值为 `5`,其余变量的值为 `4`),则先前由这些变量管理的算子并发度将自动由 `tidb_executor_concurrency` 管理。如果您修改了这些变量中的任何一个,则相应算子的并发度仍将由修改后的变量控制。 -对于从 v5.0 之前的版本升级到 v5.0 的系统,如果用户对上述所列变量的值没有做过改动(即 `tidb_hash_join_concurrency` 值为 `5`,其他值为 `4`),则会自动转为使用 `tidb_executor_concurrency` 来统一管理算子并发度。如果用户对上述变量的值做过改动,则沿用之前的变量对相应的算子做并发控制。 +### tidb_expensive_query_time_threshold -### `tidb_expensive_query_time_threshold` +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`60` - 范围:`[10, 2147483647]` - 单位:秒 -- 这个变量用来控制打印 expensive query 日志的阈值时间,默认值是 60 秒。expensive query 日志和慢日志的差别是,慢日志是在语句执行完后才打印,expensive query 日志可以把正在执行中的语句且执行时间超过阈值的语句及其相关信息打印出来。 +- 此变量用于设置确定是否打印昂贵查询日志的阈值。昂贵查询日志和慢查询日志的区别在于: + - 慢查询日志在语句执行后打印。 + - 昂贵查询日志打印正在执行的语句,其执行时间超过阈值,以及它们的相关信息。 + +### tidb_expensive_txn_time_threshold v7.2.0 新增 + + -### `tidb_expensive_txn_time_threshold` 从 v7.2.0 版本开始引入 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + + - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`600` - 范围:`[60, 2147483647]` - 单位:秒 -- 这个变量用来控制打印 expensive transaction 日志的阈值时间,默认值是 600 秒。expensive transaction 日志会将尚未 COMMIT 或 ROLLBACK 且持续时间超过该阈值的事务的相关信息打印出来。 +- 此变量控制记录昂贵事务的阈值,默认为 600 秒。当事务的持续时间超过阈值,且事务既未提交也未回滚时,该事务被认为是昂贵事务,并将被记录。 + +### tidb_force_priority -### `tidb_force_priority` +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`NO_PRIORITY` -- 可选值:`NO_PRIORITY`、`LOW_PRIORITY`、`DELAYED`、`HIGH_PRIORITY` -- 这个变量用于改变 TiDB server 上执行的语句的默认优先级。例如,你可以通过设置该变量来确保正在执行 OLAP 查询的用户优先级低于正在执行 OLTP 查询的用户。 -- 默认值 `NO_PRIORITY` 表示不强制改变执行语句的优先级。 +- 可选值:`NO_PRIORITY`、`LOW_PRIORITY`、`HIGH_PRIORITY`、`DELAYED` +- 此变量用于更改在 TiDB 服务器上执行的语句的默认优先级。一个用例是确保执行 OLAP 查询的特定用户获得的优先级低于执行 OLTP 查询的用户。 +- 默认值 `NO_PRIORITY` 表示不强制更改语句的优先级。 > **注意:** > -> TiDB 从 v6.6.0 版本开始支持[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md)功能。该功能可以将不同优先级的语句放在不同的资源组中执行,并为这些资源组分配不同的配额和优先级,可以达到更好的资源管控效果。在开启资源管控功能后,语句的调度主要受资源组的控制,`PRIORITY` 将不再生效。建议在支持资源管控的版本优先使用资源管控功能。 +> 从 v6.6.0 版本开始,TiDB 支持 [资源控制](/tidb-resource-control.md)。你可以使用此功能在不同的资源组中以不同的优先级执行 SQL 语句。通过为这些资源组配置适当的配额和优先级,你可以更好地控制具有不同优先级的 SQL 语句的调度。启用资源控制后,语句优先级将不再生效。建议你使用 [资源控制](/tidb-resource-control.md) 来管理不同 SQL 语句的资源使用情况。 -### `tidb_gc_concurrency` 从 v5.0 版本开始引入 +### tidb_gc_concurrency v5.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` - 范围:`[1, 256]` - 单位:线程 -- 这个变量用于指定 GC 在[Resolve Locks(清理锁)](/garbage-collection-overview.md#resolve-locks清理锁)步骤中线程的数量。默认值 `-1` 表示由 TiDB 自主判断运行 GC 要使用的线程的数量。 +- 指定 GC 的 [Resolve Locks](/garbage-collection-overview.md#resolve-locks) 步骤中的线程数。值为 `-1` 表示 TiDB 将自动决定要使用的垃圾回收线程数。 + +### tidb_gc_enable v5.0 新增 -### `tidb_gc_enable` 从 v5.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于控制是否启用 TiKV 的垃圾回收 (GC) 机制。如果不启用 GC 机制,系统将不再清理旧版本的数据,因此会有损系统性能。 +- 启用 TiKV 的垃圾回收。禁用垃圾回收会降低系统性能,因为旧版本的行将不再被清除。 -### `tidb_gc_life_time` 从 v5.0 版本开始引入 +### tidb_gc_life_time v5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:Duration - 默认值:`10m0s` -- 范围:`[10m0s, 8760h0m0s]` -- 这个变量用于指定每次进行垃圾回收 (GC) 时保留数据的时限。变量值为 Go 的 Duration 字符串格式。每次进行 GC 时,将以当前时间减去该变量的值作为 safe point。 +- 范围:对于 TiDB Self-Managed 和 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 为 `[10m0s, 8760h0m0s]`,对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 为 `[10m0s, 168h0m0s]` +- 每次 GC 保留数据的时间限制,格式为 Go Duration。发生 GC 时,当前时间减去此值即为安全点。 -> **Note:** +> **注意:** > -> - 在数据频繁更新的场景下,将 `tidb_gc_life_time` 的值设置得过大(如数天甚至数月)可能会导致一些潜在的问题,如: -> - 占用更多的存储空间。 -> - 大量的历史数据可能会在一定程度上影响系统性能,尤其是范围的查询(如 `select count(*) from t`)。 -> - 如果一个事务的运行时长超过了 `tidb_gc_life_time` 配置的值,在 GC 时,为了使这个事务可以继续正常运行,系统会保留从这个事务开始时间 `start_ts` 以来的数据。例如,如果 `tidb_gc_life_time` 的值配置为 10 分钟,且在一次 GC 时,集群正在运行的事务中最早开始的那个事务已经运行了 15 分钟,那么本次 GC 将保留最近 15 分钟的数据。 +> - 在频繁更新的场景中,`tidb_gc_life_time` 的较大值(几天甚至几个月)可能会导致潜在问题,例如: +> - 更大的存储使用量 +> - 大量的历史数据可能会在一定程度上影响性能,特别是对于范围查询,例如 `select count(*) from t` +> - 如果有任何事务的运行时间超过 `tidb_gc_life_time`,在 GC 期间,将保留自 `start_ts` 以来的数据,以使该事务继续执行。例如,如果 `tidb_gc_life_time` 配置为 10 分钟,在所有正在执行的事务中,最早开始的事务已经运行了 15 分钟,GC 将保留最近 15 分钟的数据。 + +### tidb_gc_max_wait_time v6.1.0 新增 -### `tidb_gc_max_wait_time` 从 v6.1.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`86400` - 范围:`[600, 31536000]` - 单位:秒 -- 这个变量用于指定活跃事务阻碍 GC safe point 推进的最大时间。每次进行 GC 时,默认 GC safe point 不会超过正在执行中的事务的开始时间。如果活跃事务运行时间未超过该值,GC safe point 会一直被阻塞不更新,直到活跃事务运行时间超过该值 safe point 才会正常推进。 +- 此变量用于设置活动事务阻塞 GC 安全点的最大时间。在每次 GC 时,默认情况下,安全点不会超过正在进行的事务的开始时间。如果活动事务的运行时长不超过此变量值,则 GC 安全点将被阻塞,直到运行时长超过此值。 -### `tidb_gc_run_interval` 从 v5.0 版本开始引入 +### tidb_gc_run_interval v5.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:Duration - 默认值:`10m0s` - 范围:`[10m0s, 8760h0m0s]` -- 这个变量用于指定垃圾回收 (GC) 运行的时间间隔。变量值为 Go 的 Duration 字符串格式,如`"1h30m"`、`"15m"`等。 +- 指定 GC 间隔,格式为 Go Duration,例如 `"1h30m"` 和 `"15m"` -### `tidb_gc_scan_lock_mode` 从 v5.0 版本开始引入 +### tidb_gc_scan_lock_mode v5.0 新增 > **警告:** > -> Green GC 目前是实验性功能,不建议在生产环境中使用。 +> 目前,Green GC 是一项实验性功能。不建议在生产环境中使用它。 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`LEGACY` -- 可设置为:`PHYSICAL`,`LEGACY` +- 可选值:`PHYSICAL`,`LEGACY` - `LEGACY`:使用旧的扫描方式,即禁用 Green GC。 - - `PHYSICAL`:使用物理扫描方式,即启用 Green GC。 -- 这个变量用于指定垃圾回收 (GC) 的 Resolve Locks(清理锁)步骤中扫描锁的方式。当变量值设置为 `LEGACY` 时,TiDB 以 Region 为单位进行扫描。当变量值设置为 `PHYSICAL` 时,每个 TiKV 节点分别绕过 Raft 层直接扫描数据,可以有效地缓解在启用 [Hibernate Region](/tikv-configuration-file.md#hibernate-regions) 功能时,GC 唤醒全部 Region 的影响,从而提升 Resolve Locks(清理锁)这个步骤的执行速度。 + - `PHYSICAL`:使用物理扫描方法,即启用 Green GC。 -### `tidb_general_log` + + +- 此变量指定 GC 的 Resolve Locks 步骤中扫描锁的方式。当变量值设置为 `LEGACY` 时,TiDB 按 Region 扫描锁。当使用值 `PHYSICAL` 时,它使每个 TiKV 节点能够绕过 Raft 层并直接扫描数据,这可以有效地缓解启用 [Hibernate Region](/tikv-configuration-file.md#hibernate-regions) 功能时 GC 唤醒所有 Region 的影响,从而提高 Resolve Locks 步骤的执行速度。 + + + + + +- 此变量指定 GC 的 Resolve Locks 步骤中扫描锁的方式。当变量值设置为 `LEGACY` 时,TiDB 按 Region 扫描锁。当使用值 `PHYSICAL` 时,它使每个 TiKV 节点能够绕过 Raft 层并直接扫描数据,这可以有效地缓解 GC 唤醒所有 Region 的影响,从而提高 Resolve Locks 步骤的执行速度。 + + + +### tidb_general_log + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否持久化到集群:否,仅适用于你当前连接的 TiDB 实例。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来设置是否在[日志](/tidb-configuration-file.md#logfile)里记录所有的 SQL 语句。该功能默认关闭。如果系统运维人员在定位问题过程中需要追踪所有 SQL 记录,可考虑开启该功能。 -- 如果指定了 [`log.general-log-file`](/tidb-configuration-file.md#general-log-file-从-v800-版本开始引入) 配置项,general log 将被单独写入到指定的文件中。 -- 通过 [`log.format`](/tidb-configuration-file.md#format) 配置项可以配置日志消息的格式,无论 general log 是在单独的文件中还是合并在其它日志文件中。 -- 通过 [`tidb_redact_log`](#tidb_redact_log) 变量可以对 general log 中记录的 SQL 语句进行脱敏处理。 -- 只有执行成功的语句才会被记录在 general log 中。失败的语句不会记录在 general log 中,而是以 `command dispatched failed` 消息的形式记录在 TiDB 日志中。 -- 在 TiDB 配置项 [`log.level`](/tidb-configuration-file.md#level) 为 `"info"` 或 `"debug"` 时,通过查询 `"GENERAL_LOG"` 字符串可以定位到该功能在日志中的所有记录。日志会记录以下内容: - - `time`:事件发生时间 - - `conn`:当前会话对应的 ID - - `user`:当前会话用户 - - `schemaVersion`:当前 schema 版本 - - `txnStartTS`:当前事务的开始时间戳 - - `forUpdateTS`:事务模式为悲观事务时,SQL 语句的当前时间戳。悲观事务内发生写冲突时,会重试当前执行语句,该时间戳会被更新。重试次数由 [`max-retry-count`](/tidb-configuration-file.md#max-retry-count) 配置。事务模式为乐观事务时,该条目与 `txnStartTS` 等价。 - - `isReadConsistency`:当前事务隔离级别是否是读已提交 (RC) - - `current_db`:当前数据库名 - - `txn_mode`:事务模式。可选值:`OPTIMISTIC`(乐观事务模式),或 `PESSIMISTIC`(悲观事务模式) - - `sql`:当前查询对应的 SQL 语句 - -### `tidb_non_prepared_plan_cache_size` + + + +- 此变量用于设置是否在日志中记录所有 SQL 语句。默认情况下,此功能已禁用。如果需要在定位问题时跟踪所有 SQL 语句,请启用此功能。 + + + + + +- 此变量用于设置是否将所有 SQL 语句记录在 [日志](/tidb-configuration-file.md#logfile) 中。默认情况下,此功能已禁用。如果维护人员需要在定位问题时跟踪所有 SQL 语句,他们可以启用此功能。 + +- 如果指定了 [`log.general-log-file`](/tidb-configuration-file.md#general-log-file-new-in-v800) 配置项,则通用日志将单独写入指定的文件。 + +- [`log.format`](/tidb-configuration-file.md#format) 配置项使你能够配置日志消息格式,无论通用日志是位于单独的文件中还是与其他日志组合在一起。 + +- [`tidb_redact_log`](#tidb_redact_log) 变量使你能够编辑通用日志中记录的 SQL 语句。 + +- 只有成功执行的语句才会记录在通用日志中。失败的语句不会记录在通用日志中,而是记录在 TiDB 日志中,并显示 `command dispatched failed` 消息。 + +- 要查看此功能在日志中的所有记录,您需要将 TiDB 配置项 [`log.level`](/tidb-configuration-file.md#level) 设置为 `"info"` 或 `"debug"`,然后查询 `"GENERAL_LOG"` 字符串。记录以下信息: + - `time`: 事件发生的时间。 + - `conn`: 当前会话的 ID。 + - `user`: 当前会话用户。 + - `schemaVersion`: 当前 schema 版本。 + - `txnStartTS`: 当前事务开始的时间戳。 + - `forUpdateTS`: 在悲观事务模式下,`forUpdateTS` 是当前 SQL 语句的时间戳。当悲观事务中发生写冲突时,TiDB 会重试当前正在执行的 SQL 语句并更新此时间戳。您可以通过 [`max-retry-count`](/tidb-configuration-file.md#max-retry-count) 配置重试次数。在乐观事务模型中,`forUpdateTS` 等同于 `txnStartTS`。 + - `isReadConsistency`: 指示当前事务隔离级别是否为读已提交 (RC)。 + - `current_db`: 当前数据库的名称。 + - `txn_mode`: 事务模式。可选值为 `OPTIMISTIC` 和 `PESSIMISTIC`。 + - `sql`: 与当前查询对应的 SQL 语句。 + + + +### tidb_non_prepared_plan_cache_size > **警告:** > -> 从 v7.1.0 开始,该变量被废弃。请使用 [`tidb_session_plan_cache_size`](#tidb_session_plan_cache_size-从-v710-版本开始引入) 进行设置。 +> 从 v7.1.0 开始,此变量已被弃用。请改用 [`tidb_session_plan_cache_size`](#tidb_session_plan_cache_size-new-in-v710) 进行设置。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`100` - 范围:`[1, 100000]` -- 这个变量用来控制[非 Prepare 语句执行计划缓存](/sql-non-prepared-plan-cache.md)最多能够缓存的计划数量。 +- 此变量控制 [Non-prepared plan cache](/sql-non-prepared-plan-cache.md) 可以缓存的最大执行计划数量。 + +### tidb_generate_binary_plan New in v6.2.0 -### `tidb_generate_binary_plan` 从 v6.2.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于指定是否在 slow log 和 statement summary 里包含以二进制格式编码的执行计划。 -- 开启该变量后,即可在 TiDB Dashboard 中查看查询的图形化执行计划。注意,TiDB Dashboard 只显示变量开启时产生的查询的执行计划。 -- 用 [`SELECT tidb_decode_binary_plan('xxx...')`](/functions-and-operators/tidb-functions.md#tidb_decode_binary_plan) SQL 语句可以从编码后的执行计划解析出具体的执行计划。 +- 此变量控制是否在慢日志和语句摘要中生成二进制编码的执行计划。 +- 当此变量设置为 `ON` 时,您可以在 TiDB Dashboard 中查看可视化执行计划。请注意,TiDB Dashboard 仅提供在此变量启用后生成的执行计划的可视化显示。 +- 您可以执行 [`SELECT tidb_decode_binary_plan('xxx...')`](/functions-and-operators/tidb-functions.md#tidb_decode_binary_plan) 语句来从二进制计划中解析特定计划。 -### `tidb_gogc_tuner_max_value` 从 v7.5.0 版本开始引入 +### tidb_gogc_tuner_max_value New in v7.5.0 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`500` - 范围:`[10, 2147483647]` -- 该变量用来控制 GOGC Tuner 可调节 GOGC 的最大值。 +- 该变量用于控制 GOGC Tuner 可以调整的 GOGC 最大值。 -### `tidb_gogc_tuner_min_value` 从 v7.5.0 版本开始引入 +### tidb_gogc_tuner_min_value New in v7.5.0 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`100` - 范围:`[10, 2147483647]` -- 该变量用来控制 GOGC Tuner 可调节 GOGC 的最小值。 +- 该变量用于控制 GOGC Tuner 可以调整的 GOGC 最小值。 -### `tidb_gogc_tuner_threshold` 从 v6.4.0 版本开始引入 +### tidb_gogc_tuner_threshold New in v6.4.0 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`0.6` - 范围:`[0, 0.9)` -- 这个变量用来控制 GOGC Tuner 自动调节的最大内存阈值,超过阈值后 GOGC Tuner 会停止工作。 +- 此变量指定调整 GOGC 的最大内存阈值。当内存超过此阈值时,GOGC Tuner 停止工作。 -### `tidb_guarantee_linearizability` 从 v5.0 版本开始引入 +### tidb_guarantee_linearizability New in v5.0 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 此变量控制异步提交 (Async Commit) 中提交时间戳的计算方式。默认情况下(使用 `ON` 值),两阶段提交从 PD 服务器请求一个新的时间戳,并使用该时间戳计算最终提交的时间戳,这样可保证所有并发事务可线性化。 -- 如果将该变量值设为 `OFF`,从 PD 获取时间戳的操作会被省掉,这种情况下只保证因果一致性但不保证线性一致性。详情请参考 PingCAP 博文 [Async Commit 原理介绍](https://pingcap.com/zh/blog/async-commit-principle)。 -- 对于需要只保证因果一致性的场景,可将此变量设为 `OFF` 以提升性能。 +- 此变量控制异步提交的 commit TS 的计算方式。默认情况下(值为 `ON`),两阶段提交从 PD 服务器请求一个新的 TS,并使用该 TS 来计算最终的 commit TS。在这种情况下,保证所有并发事务的线性一致性。 +- 如果将此变量设置为 `OFF`,则会跳过从 PD 服务器获取 TS 的过程,但代价是仅保证因果一致性,而不保证线性一致性。有关更多详细信息,请参见博客文章 [Async Commit, the Accelerator for Transaction Commit in TiDB 5.0](https://www.pingcap.com/blog/async-commit-the-accelerator-for-transaction-commit-in-tidb-5-0/)。 +- 对于仅需要因果一致性的场景,您可以将此变量设置为 `OFF` 以提高性能。 -### `tidb_hash_exchange_with_new_collation` +### tidb_hash_exchange_with_new_collation - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 该值表示是否在开启 new collation 的集群里生成 MPP hash partition exchange 算子。`true` 表示生成此算子,`false`表示不生成。 -- 该变量为 TiDB 内部变量,**不推荐设置该变量**。 +- 此变量控制是否在启用新排序规则的集群中生成 MPP 哈希分区交换算子。`true` 表示生成该算子,`false` 表示不生成。 +- 此变量用于 TiDB 的内部操作。**不建议**设置此变量。 -### `tidb_hash_join_concurrency` +### tidb_hash_join_concurrency > **警告:** > -> 从 v5.0 版本开始,该变量被废弃。请使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 进行设置。 +> 自 v5.0 起,此变量已被弃用。请改用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-new-in-v50) 进行设置。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` - 范围:`[1, 256]` - 单位:线程 -- 这个变量用来设置 hash join 算法的并发度。 -- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 +- 此变量用于设置 `hash join` 算法的并发度。 +- 值为 `-1` 表示将使用 `tidb_executor_concurrency` 的值。 -### `tidb_hashagg_final_concurrency` +### tidb_hashagg_final_concurrency > **警告:** > -> 从 v5.0 版本开始,该变量被废弃。请使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 进行设置。 +> 自 v5.0 起,此变量已被弃用。请改用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-new-in-v50) 进行设置。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` - 范围:`[1, 256]` - 单位:线程 -- 这个变量用来设置并行 hash aggregation 算法 final 阶段的执行并发度。对于聚合函数参数不为 distinct 的情况,HashAgg 分为 partial 和 final 阶段分别并行执行。 -- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 +- 此变量用于设置在 `final` 阶段执行并发 `hash aggregation` 算法的并发度。 +- 当聚合函数的参数不是 distinct 时,`HashAgg` 会在两个阶段并发运行,分别是 `partial` 阶段和 `final` 阶段。 +- 值为 `-1` 表示将使用 `tidb_executor_concurrency` 的值。 -### `tidb_hashagg_partial_concurrency` +### tidb_hashagg_partial_concurrency > **警告:** > -> 从 v5.0 版本开始,该变量被废弃。请使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 进行设置。 +> 自 v5.0 起,此变量已被弃用。请改用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-new-in-v50) 进行设置。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` - 范围:`[1, 256]` - 单位:线程 -- 这个变量用来设置并行 hash aggregation 算法 partial 阶段的执行并发度。对于聚合函数参数不为 distinct 的情况,HashAgg 分为 partial 和 final 阶段分别并行执行。 -- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 +- 此变量用于设置在 `partial` 阶段执行并发 `hash aggregation` 算法的并发度。 +- 当聚合函数的参数不是 distinct 时,`HashAgg` 会在两个阶段并发运行,分别是 `partial` 阶段和 `final` 阶段。 +- 值为 `-1` 表示将使用 `tidb_executor_concurrency` 的值。 -### `tidb_historical_stats_duration` 从 v6.6.0 版本开始引入 +### tidb_historical_stats_duration New in v6.6.0 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:Duration -- 默认值:`168h`,即 7 天 -- 这个变量用来控制历史统计信息在存储中的保留时间。 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Duration +- 默认值: `168h`,表示 7 天 +- 此变量控制历史统计信息在存储中保留的时长。 -### `tidb_idle_transaction_timeout` 从 v7.6.0 版本开始引入 +### tidb_idle_transaction_timeout v7.6.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`0` -- 范围:`[0, 31536000]` -- 单位:秒 -- 这个变量用来控制用户会话中事务的空闲超时。当用户会话处于事务状态且空闲时间超过该变量设定的值时,会话会被 Kill 掉。用户会话空闲是指没有正在执行的请求,处于等待请求的状态。 -- 默认值 `0` 表示没有时间限制。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `0` +- 范围: `[0, 31536000]` +- 单位: 秒 +- 此变量控制用户会话中事务的空闲超时时间。当用户会话处于事务状态并且空闲时间超过此变量的值时,TiDB 将终止该会话。空闲用户会话意味着没有活动的请求,并且会话正在等待新的请求。 +- 默认值 `0` 表示无限制。 -### `tidb_ignore_inlist_plan_digest` 从 v7.6.0 版本开始引入 +### tidb_ignore_prepared_cache_close_stmt v6.0.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用来控制 TiDB 在生成执行计划摘要 (Plan Digest) 时,是否忽略不同查询中 `IN` 列表的元素差异。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `OFF` +- 此变量用于设置是否忽略关闭预处理语句缓存的命令。 +- 当此变量设置为 `ON` 时,将忽略 Binary 协议的 `COM_STMT_CLOSE` 命令和文本协议的 [`DEALLOCATE PREPARE`](/sql-statements/sql-statement-deallocate.md) 语句。有关详细信息,请参见 [忽略 `COM_STMT_CLOSE` 命令和 `DEALLOCATE PREPARE` 语句](/sql-prepared-plan-cache.md#ignore-the-com_stmt_close-command-and-the-deallocate-prepare-statement)。 - - 当为默认值 `OFF` 时,TiDB 在生成执行计划摘要时,不会忽略 `IN` 列表中的元素差异(包括元素数量差异)。`IN` 列表的元素差异将导致生成的执行计划摘要不同。 - - 当设置为 `ON` 时,TiDB 会忽略 `IN` 列表中的元素差异(包括元素数量差异),在执行计划摘要中使用 `...` 代替 `IN` 列表中的元素。此时,相同类型的 `IN` 查询会生成相同的执行计划摘要。 +### tidb_ignore_inlist_plan_digest v7.6.0 新增 -### `tidb_ignore_prepared_cache_close_stmt` 从 v6.0.0 版本开始引入 +- 作用域: GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `OFF` +- 此变量控制 TiDB 在生成 Plan Digests 时是否忽略不同查询中 `IN` 列表中的元素差异。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用来设置是否忽略关闭 Prepared Statement 的指令。 -- 如果变量值设为 `ON`,Binary 协议的 `COM_STMT_CLOSE` 信号和文本协议的 [`DEALLOCATE PREPARE`](/sql-statements/sql-statement-deallocate.md) 语句都会被忽略。 + - 当为默认值 `OFF` 时,TiDB 在生成 Plan Digests 时不会忽略 `IN` 列表中的元素差异(包括元素数量的差异)。 `IN` 列表中的元素差异会导致不同的 Plan Digests。 + - 当设置为 `ON` 时,TiDB 会忽略 `IN` 列表中的元素差异(包括元素数量的差异),并使用 `...` 替换 Plan Digests 中 `IN` 列表中的元素。 在这种情况下,TiDB 会为相同类型的 `IN` 查询生成相同的 Plan Digests。 -### `tidb_index_join_batch_size` +### tidb_index_join_batch_size -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 -- 默认值:`25000` -- 范围:`[1, 2147483647]` -- 单位:行 -- 这个变量用来设置 index lookup join 操作的 batch 大小,AP 类应用适合较大的值,TP 类应用适合较小的值。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Integer +- 默认值: `25000` +- 范围: `[1, 2147483647]` +- 单位: 行 +- 此变量用于设置 `index lookup join` 操作的批处理大小。 +- 在 OLAP 场景中使用较大的值,在 OLTP 场景中使用较小的值。 -### `tidb_index_join_double_read_penalty_cost_rate` 从 v6.6.0 版本开始引入 +### tidb_index_join_double_read_penalty_cost_rate v6.6.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 -- 默认值:`0` -- 范围:`[0, 18446744073709551615]` -- 这个变量用来设置是否给选择 index join 增加一些惩罚性的代价,以降低优化器选择 index join 操作的倾向,从而增加选择其他 join 方式的倾向,例如如选择 hash join 和 tiflash join 等。 -- 优化器选择 index join 可能触发较多的回表请求,造成较多的资源开销,此时可以通过设置这个变量,来减少优化器选择 index join 的倾向。 -- 这个变量只有在 [`tidb_cost_model_version`](/system-variables.md#tidb_cost_model_version-从-v620-版本开始引入) 设置为 `2` 时生效。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Float +- 默认值: `0` +- 范围: `[0, 18446744073709551615]` +- 此变量确定是否对索引连接的选择应用惩罚成本,从而降低优化器选择索引连接的可能性,并增加选择替代连接方法(如哈希连接和 tiflash 连接)的可能性。 +- 当选择索引连接时,会触发许多表查找请求,这会消耗过多的资源。 您可以使用此变量来降低优化器选择索引连接的可能性。 +- 此变量仅在 [`tidb_cost_model_version`](/system-variables.md#tidb_cost_model_version-new-in-v620) 变量设置为 `2` 时生效。 -### `tidb_index_lookup_concurrency` +### tidb_index_lookup_concurrency > **警告:** > -> 从 v5.0 版本开始,该变量被废弃。请使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 进行设置。 - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`-1` -- 范围:`[1, 256]` -- 单位:线程 -- 这个变量用来设置 index lookup 操作的并发度,AP 类应用适合较大的值,TP 类应用适合较小的值。 -- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 +> 从 v5.0 开始,此变量已弃用。 请改用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-new-in-v50) 进行设置。 -### `tidb_index_lookup_join_concurrency` +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `-1` +- 范围: `[1, 256]` +- 单位: 线程 +- 此变量用于设置 `index lookup` 操作的并发性。 +- 在 OLAP 场景中使用较大的值,在 OLTP 场景中使用较小的值。 +- 值为 `-1` 表示将使用 `tidb_executor_concurrency` 的值。 + +### tidb_index_lookup_join_concurrency > **警告:** > -> 从 v5.0 版本开始,该变量被废弃。请使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 进行设置。 +> 从 v5.0 开始,此变量已弃用。 请改用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-new-in-v50) 进行设置。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`-1` -- 范围:`[1, 256]` -- 单位:线程 -- 这个变量用来设置 index lookup join 算法的并发度。 -- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `-1` +- 范围: `[1, 256]` +- 单位: 线程 +- 此变量用于设置 `index lookup join` 算法的并发性。 +- 值为 `-1` 表示将使用 `tidb_executor_concurrency` 的值。 -### `tidb_index_merge_intersection_concurrency` 从 v6.5.0 版本开始引入 +### tidb_index_merge_intersection_concurrency v6.5.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 默认值:`-1` -- 范围:`[1, 256]` -- 这个变量用来设置索引合并进行交集操作时的最大并发度,仅在以动态裁剪模式访问分区表时有效。实际并发度为 `tidb_index_merge_intersection_concurrency` 与分区表分区数目两者中较小的值。 -- 默认值 `-1` 表示使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 的值。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 默认值: `-1` +- 范围: `[1, 256]` +- 此变量设置索引合并执行的交集操作的最大并发数。 仅当 TiDB 在动态修剪模式下访问分区表时才有效。 实际并发数是 `tidb_index_merge_intersection_concurrency` 和分区表的分区数的较小值。 +- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 -### `tidb_index_lookup_size` +### tidb_index_lookup_size -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 -- 默认值:`20000` -- 范围:`[1, 2147483647]` -- 单位:行 -- 这个变量用来设置 index lookup 操作的 batch 大小,AP 类应用适合较大的值,TP 类应用适合较小的值。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Integer +- 默认值: `20000` +- 范围: `[1, 2147483647]` +- 单位: 行 +- 此变量用于设置 `index lookup` 操作的批处理大小。 +- 在 OLAP 场景中使用较大的值,在 OLTP 场景中使用较小的值。 -### `tidb_index_serial_scan_concurrency` +### tidb_index_serial_scan_concurrency -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 -- 默认值:`1` -- 范围:`[1, 256]` -- 单位:线程 -- 这个变量用来设置顺序 scan 操作的并发度,AP 类应用适合较大的值,TP 类应用适合较小的值。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Integer +- 默认值: `1` +- 范围: `[1, 256]` +- 单位: 线程 +- 此变量用于设置 `serial scan` 操作的并发性。 +- 在 OLAP 场景中使用较大的值,在 OLTP 场景中使用较小的值。 -### `tidb_init_chunk_size` +### tidb_init_chunk_size -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`32` -- 范围:`[1, 32]` -- 单位:行 -- 这个变量用来设置执行过程中初始 chunk 的行数。默认值是 32,可设置的范围是 1~32。chunk 行数直接影响单个查询所需的内存。可以按照查询中所有的列的总宽度和 chunk 行数来粗略估算单个 chunk 所需内存,并结合执行器的并发数来粗略估算单个查询所需内存总量。建议单个 chunk 内存总量不要超过 16 MiB。 +- 作用域: SESSION | GLOBAL +- 是否持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `32` +- 范围: `[1, 32]` +- 单位: 行 +- 此变量用于设置执行过程中初始 chunk 的行数。 一个 chunk 的行数直接影响单个查询所需的内存量。 您可以通过考虑查询中所有列的总宽度和 chunk 的行数来粗略估计单个 chunk 所需的内存。 将其与执行器的并发性结合起来,您可以粗略估计单个查询所需的总内存。 建议单个 chunk 的总内存不超过 16 MiB。 -### `tidb_isolation_read_engines` 从 v4.0 版本开始引入 +### tidb_isolation_read_engines v4.0 新增 -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 默认值:`tikv,tiflash,tidb` -- 这个变量用于设置 TiDB 在读取数据时可以使用的存储引擎列表。 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 -### `tidb_last_ddl_info` 从 v6.0.0 版本开始引入 +- 作用域: SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 默认值: `tikv,tiflash,tidb` +- 此变量用于设置 TiDB 在读取数据时可以使用的存储引擎列表。 + +### tidb_last_ddl_info v6.0.0 新增 - 作用域:SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 该变量为只读变量,TiDB 内部使用该变量获取当前会话中上一个 DDL 操作的信息。 - - "query":上一个 DDL 查询字符串。 - - "seq_num":每个 DDL 操作的序列号,用于标识 DDL 操作的顺序。 +- 类型:String +- 这是一个只读变量。它在 TiDB 内部用于获取当前会话中最后一次 DDL 操作的信息。 + - "query": 最后一次 DDL 查询字符串。 + - "seq_num": 每个 DDL 操作的序列号。它用于标识 DDL 操作的顺序。 -### `tidb_last_query_info` 从 v4.0.14 版本开始引入 +### tidb_last_query_info v4.0.14 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 这是一个只读变量。用于在 TiDB 内部查询上一条 DML 语句的事务信息。查询的事务信息包括: - - `txn_scope`:事务的作用域,可能为 `global` 或 `local`。 - - `start_ts`:事务开始的时间戳。 - - `for_update_ts`:先前执行的 DML 语句的 `for_update_ts` 信息。这是 TiDB 用于测试的内部术语。通常,你可以忽略此信息。 - - `error`:错误消息(如果有)。 - - `ru_consumption`:执行语句的 [RU](/tidb-resource-control.md#什么是-request-unit-ru) 消耗。 +- 这是一个只读变量。它在 TiDB 内部用于查询最后一条 DML 语句的事务信息。该信息包括: + - `txn_scope`: 事务的作用域,可以是 `global` 或 `local`。 + - `start_ts`: 事务的开始时间戳。 + - `for_update_ts`: 先前执行的 DML 语句的 `for_update_ts`。这是一个 TiDB 内部术语,用于测试。通常,您可以忽略此信息。 + - `error`: 错误信息(如果有)。 + - `ru_consumption`: 执行语句消耗的 [RU](/tidb-resource-control.md#what-is-request-unit-ru)。 -### `tidb_last_txn_info` 从 v4.0.9 版本开始引入 +### tidb_last_txn_info v4.0.9 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 此变量用于获取当前会话中最后一个事务的信息。这是一个只读变量。事务信息包括: - - 事务的范围 - - 开始时间戳和提交时间戳 - - 事务的提交模式,可能是两阶段提交,一阶段提交,或者异步提交 - - 事务从异步提交或一阶段提交到两阶段提交的回退信息 - - 遇到的错误 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:String +- 此变量用于获取当前会话中最后一次事务的信息。这是一个只读变量。事务信息包括: + - 事务作用域。 + - 开始和提交 TS。 + - 事务提交模式,可能是两阶段提交、一阶段提交或异步提交。 + - 从异步提交或一阶段提交回退到两阶段提交的事务信息。 + - 遇到的错误。 -### `tidb_last_plan_replayer_token` 从 v6.3.0 版本开始引入 +### tidb_last_plan_replayer_token v6.3.0 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 -- 这个变量是一个只读变量,用于获取当前会话中最后一个 `PLAN REPLAYER dump` 的结果。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:String +- 此变量是只读的,用于获取当前会话中最后一次 `PLAN REPLAYER DUMP` 执行的结果。 -### `tidb_load_based_replica_read_threshold` 从 v7.0.0 版本开始引入 +### tidb_load_based_replica_read_threshold v7.0.0 新增 + + - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`"1s"` - 范围:`[0s, 1h]` -- 类型:字符串 -- 这个变量用来设置基于负载的 replica read 的触发阈值。当 leader 节点的预估排队时间超过阈值时,TiDB 会优先从 follower 节点读取数据。格式为时间,例如 `"100ms"` 或 `"1s"`。详情见 [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md#打散读热点)。 +- 类型:String +- 此变量用于设置触发基于负载的副本读取的阈值。当 leader 节点的估计队列时间超过阈值时,TiDB 优先从 follower 节点读取数据。格式为时间长度,例如 `"100ms"` 或 `"1s"`。有关更多详细信息,请参阅[解决热点问题](/troubleshoot-hot-spot-issues.md#scatter-read-hotspots)。 + + + + + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`"1s"` +- 范围:`[0s, 1h]` +- 类型:String +- 此变量用于设置触发基于负载的副本读取的阈值。当 leader 节点的估计队列时间超过阈值时,TiDB 优先从 follower 节点读取数据。格式为时间长度,例如 `"100ms"` 或 `"1s"`。有关更多详细信息,请参阅[解决热点问题](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues#scatter-read-hotspots)。 + + -### `tidb_load_binding_timeout` 从 v8.0.0 版本开始引入 +### `tidb_load_binding_timeout` v8.0.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`200` - 范围:`(0, 2147483647]` - 单位:毫秒 -- 这个变量用来控制加载 binding 的超时时间。当加载 binding 的执行时间超过该值时,会停止加载。 +- 此变量用于控制加载绑定的超时时间。如果加载绑定的执行时间超过此值,则加载将停止。 -### `tidb_lock_unchanged_keys` 从 v7.1.1 和 v7.3.0 版本开始引入 +### `tidb_lock_unchanged_keys` v7.1.1 和 v7.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 该变量控制在以下场景是否对某些 key 加锁。设置为 `ON` 时,都加锁,设置为 `OFF` 时,都不加锁。 - - 在 `INSERT IGNORE` 语句和 `REPLACE` 语句中值重复的 key。在 v6.1.6 之前版本中,这些 key 不加锁。这个问题已在 [#42121](https://github.com/pingcap/tidb/issues/42121) 修复。 - - 在 `UPDATE` 语句中值没有改变的唯一索引 key。在 v6.5.2 之前版本中,这些 key 不加锁。这个问题已在 [#36438](https://github.com/pingcap/tidb/issues/36438) 修复。 -- 为保证事务行为的一致性和合理性,不推荐修改该值。如果在升级 TiDB 后因为这两项修复导致严重的性能问题,且可以接受不加锁的行为(见上述 Issue),可以将该变量设置为 `OFF`。 +- 此变量用于控制是否锁定以下场景中的特定键。当值设置为 `ON` 时,这些键将被锁定。当值设置为 `OFF` 时,这些键将不会被锁定。 + - `INSERT IGNORE` 和 `REPLACE` 语句中的重复键。在 v6.1.6 之前,这些键未被锁定。此问题已在 [#42121](https://github.com/pingcap/tidb/issues/42121) 中修复。 + - `UPDATE` 语句中键的值未更改时的唯一键。在 v6.5.2 之前,这些键未被锁定。此问题已在 [#36438](https://github.com/pingcap/tidb/issues/36438) 中修复。 +- 为了保持事务的一致性和合理性,不建议更改此值。如果升级 TiDB 由于这两个修复导致严重的性能问题,并且可以接受没有锁定的行为(请参阅上述问题),则可以将此变量设置为 `OFF`。 + +### tidb_log_file_max_days v5.3.0 新增 -### `tidb_log_file_max_days` 从 v5.3.0 版本开始引入 +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless),此变量是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` - 范围:`[0, 2147483647]` -- 这个变量可以调整当前 TiDB 实例上日志的最大保留天数。默认值是实例配置文件中指定的值,见配置项 [`max-days`](/tidb-configuration-file.md#max-days)。此变量只影响当前 TiDB 实例上的配置,重启后丢失,且配置文件不受影响。 -### `tidb_low_resolution_tso` + + +- 此变量用于设置当前 TiDB 实例上日志保留的最大天数。其值默认为配置文件中 [`max-days`](/tidb-configuration-file.md#max-days) 配置的值。更改变量值仅影响当前 TiDB 实例。TiDB 重启后,变量值将被重置,配置值不受影响。 + + + + + +- 此变量用于设置当前 TiDB 实例上日志保留的最大天数。 + + + +### tidb_low_resolution_tso - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来设置是否启用低精度 TSO 特性。开启该功能之后,TiDB 使用缓存 Timestamp 来读取数据。缓存 Timestamp 默认每 2 秒更新一次。从 v8.0.0 开始,你可以通过 [`tidb_low_resolution_tso_update_interval`](#tidb_low_resolution_tso_update_interval-从-v800-版本开始引入) 配置缓存 Timestamp 的更新时间间隔。 -- 主要场景是在可以容忍读到旧数据的情况下,降低小的只读事务获取 TSO 的开销。 +- 此变量用于设置是否启用低精度 TSO 功能。启用此功能后,TiDB 使用缓存的时间戳读取数据。默认情况下,缓存的时间戳每 2 秒更新一次。从 v8.0.0 开始,您可以通过 [`tidb_low_resolution_tso_update_interval`](#tidb_low_resolution_tso_update_interval-new-in-v800) 配置更新间隔。 +- 主要适用场景是在读取旧数据可以接受的情况下,减少小型只读事务获取 TSO 的开销。 -### `tidb_low_resolution_tso_update_interval` 从 v8.0.0 版本开始引入 +### `tidb_low_resolution_tso_update_interval` v8.0.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`2000` - 范围:`[10, 60000]` -- 这个变量用来设置低精度 TSO 特性中使用的缓存 Timestamp 的更新时间间隔,单位为毫秒。 -- 该变量只在低精度 TSO 特性 [`tidb_low_resolution_tso`](#tidb_low_resolution_tso) 启用时有效。 - -### `tidb_nontransactional_ignore_error` 从 v6.1.0 版本开始引入 - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用来设置是否在非事务语句中立刻返回错误。当设为 `OFF` 时,在碰到第一个报错的 batch 时,非事务 DML 语句即中止,取消其后的所有 batch,返回错误。当设为 `ON` 时,当某个 batch 执行报错时,其后的 batch 会继续执行,直到所有 batch 执行完毕,返回结果时把这些错误合并后返回。 +- 单位:毫秒 +- 此变量用于设置低精度 TSO 功能中使用的缓存时间戳的更新间隔,以毫秒为单位。 +- 仅当启用 [`tidb_low_resolution_tso`](#tidb_low_resolution_tso) 时,此变量才可用。 -### `tidb_max_auto_analyze_time` 从 v6.1.0 版本开始引入 +### tidb_max_auto_analyze_time v6.1.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`43200` - 范围:`[0, 2147483647]` - 单位:秒 -- 这个变量用于指定自动 ANALYZE 的最大执行时间。当执行时间超出指定的时间时,自动 ANALYZE 会被终止。当该变量值为 0 时,自动 ANALYZE 没有最大执行时间的限制。 +- 此变量用于指定自动 `ANALYZE` 任务的最大执行时间。当自动 `ANALYZE` 任务的执行时间超过指定时间时,该任务将被终止。当此变量的值为 `0` 时,自动 `ANALYZE` 任务的最大执行时间没有限制。 -### `tidb_max_bytes_before_tiflash_external_group_by` 从 v7.0.0 版本开始引入 +### tidb_max_bytes_before_tiflash_external_group_by v7.0.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否支持 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`-1` -- 范围:`[-1, 9223372036854775807]` -- 这个变量用于指定 TiFlash 中带有 `GROUP BY` 的 Hash Aggregation 算子的最大内存使用量,单位为 byte,超过该值之后 TiFlash 会触发 Hash Aggregation 算子的落盘。当该变量值为 -1 时,TiDB 不传递该变量给 TiFlash。只有该变量值大于等于 0 时,TiDB 才会传递该变量给 TiFlash。该变量为 0 时表示内存使用无限制,即 TiFlash Hash Aggregation 算子不会触发落盘。详情见 [TiFlash 数据落盘](/tiflash/tiflash-spill-disk.md)。 +- 取值范围:`[-1, 9223372036854775807]` +- 此变量用于指定 TiFlash 中带有 `GROUP BY` 的 Hash Aggregation 算子的最大内存使用量,以字节为单位。当内存使用量超过指定值时,TiFlash 会触发 Hash Aggregation 算子溢写到磁盘。当此变量的值为 `-1` 时,TiDB 不会将此变量传递给 TiFlash。只有当此变量的值大于等于 `0` 时,TiDB 才会将此变量传递给 TiFlash。当此变量的值为 `0` 时,表示内存使用量不受限制,即 TiFlash Hash Aggregation 算子不会触发溢写。详情请参考 [TiFlash 溢写到磁盘](/tiflash/tiflash-spill-disk.md)。 + + + +> **注意:** +> +> - 如果 TiDB 集群有多个 TiFlash 节点,聚合通常在多个 TiFlash 节点上分布式执行。此变量控制单个 TiFlash 节点上聚合算子的最大内存使用量。 +> - 当此变量设置为 `-1` 时,TiFlash 会根据其自身配置项 [`max_bytes_before_external_group_by`](/tiflash/tiflash-configuration.md#tiflash-configuration-parameters) 的值来确定聚合算子的最大内存使用量。 + + + + > **注意:** > -> - 假设一个 TiDB 集群有多个 TiFlash 节点,Aggregation 通常会在多个 TiFlash 节点上分布式执行。该变量控制的是单个 TiFlash 节点中 Aggregation 算子的最大内存使用量。 -> - 当该变量设置为 -1 时,TiFlash 将根据自身配置项 [`max_bytes_before_external_group_by`](/tiflash/tiflash-configuration.md#tiflash-配置参数-1) 的值来决定 Aggregation 算子的最大内存使用量。 +> - 如果 TiDB 集群有多个 TiFlash 节点,聚合通常在多个 TiFlash 节点上分布式执行。此变量控制单个 TiFlash 节点上聚合算子的最大内存使用量。 +> - 当此变量设置为 `-1` 时,TiFlash 会根据其自身配置项 `max_bytes_before_external_group_by` 的值来确定聚合算子的最大内存使用量。 -### `tidb_max_bytes_before_tiflash_external_join` 从 v7.0.0 版本开始引入 + + +### tidb_max_bytes_before_tiflash_external_join v7.0.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否支持 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`-1` -- 范围:`[-1, 9223372036854775807]` -- 这个变量用于指定 TiFlash 中带等值关联条件的 Hash Join 算子的最大内存使用量,单位为 byte,超过该值之后 TiFlash 会触发 Hash Join 算子的落盘。当该变量值为 -1 时,TiDB 不传递该变量给 TiFlash。只有该变量值大于等于 0 时,TiDB 才会传递该变量给 TiFlash。该变量为 0 时表示内存使用无限制,即 TiFlash Hash Join 算子不会触发落盘。详情见 [TiFlash 数据落盘](/tiflash/tiflash-spill-disk.md)。 +- 取值范围:`[-1, 9223372036854775807]` +- 此变量用于指定 TiFlash 中带有 `JOIN` 的 Hash Join 算子的最大内存使用量,以字节为单位。当内存使用量超过指定值时,TiFlash 会触发 Hash Join 算子溢写到磁盘。当此变量的值为 `-1` 时,TiDB 不会将此变量传递给 TiFlash。只有当此变量的值大于等于 `0` 时,TiDB 才会将此变量传递给 TiFlash。当此变量的值为 `0` 时,表示内存使用量不受限制,即 TiFlash Hash Join 算子不会触发溢写。详情请参考 [TiFlash 溢写到磁盘](/tiflash/tiflash-spill-disk.md)。 + + + +> **注意:** +> +> - 如果 TiDB 集群有多个 TiFlash 节点,Join 通常在多个 TiFlash 节点上分布式执行。此变量控制单个 TiFlash 节点上 Join 算子的最大内存使用量。 +> - 当此变量设置为 `-1` 时,TiFlash 会根据其自身配置项 [`max_bytes_before_external_join`](/tiflash/tiflash-configuration.md#tiflash-configuration-parameters) 的值来确定 Join 算子的最大内存使用量。 + + + + > **注意:** > -> - 假设一个 TiDB 集群有多个 TiFlash 节点,Join 通常会在多个 TiFlash 节点上分布式执行。该变量控制的是单个 TiFlash 节点中 Join 算子的最大内存使用量。 -> - 当该变量设置为 -1 时,TiFlash 将根据自身配置项 [`max_bytes_before_external_join`](/tiflash/tiflash-configuration.md#tiflash-配置参数-1) 的值来决定 Join 算子的最大内存使用量。 +> - 如果 TiDB 集群有多个 TiFlash 节点,Join 通常在多个 TiFlash 节点上分布式执行。此变量控制单个 TiFlash 节点上 Join 算子的最大内存使用量。 +> - 当此变量设置为 `-1` 时,TiFlash 会根据其自身配置项 `max_bytes_before_external_join` 的值来确定 Join 算子的最大内存使用量。 + + -### `tidb_max_bytes_before_tiflash_external_sort` 从 v7.0.0 版本开始引入 +### tidb_max_bytes_before_tiflash_external_sort v7.0.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否支持 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`-1` -- 范围:`[-1, 9223372036854775807]` -- 这个变量用于指定 TiFlash 中带 topN 和 sort 算子的最大内存使用量,单位为 byte,超过该值之后 TiFlash 会触发 topN 和 sort 算子的落盘。当该变量值为 -1 时,TiDB 不传递该变量给 TiFlash。只有该变量值大于等于 0 时,TiDB 才会传递该变量给 TiFlash。该变量为 0 时表示内存使用无限制,即 TiFlash topN 和 sort 算子不会触发落盘。详情见 [TiFlash 数据落盘](/tiflash/tiflash-spill-disk.md)。 +- 取值范围:`[-1, 9223372036854775807]` +- 此变量用于指定 TiFlash 中 TopN 和 Sort 算子的最大内存使用量,以字节为单位。当内存使用量超过指定值时,TiFlash 会触发 TopN 和 Sort 算子溢写到磁盘。当此变量的值为 `-1` 时,TiDB 不会将此变量传递给 TiFlash。只有当此变量的值大于等于 `0` 时,TiDB 才会将此变量传递给 TiFlash。当此变量的值为 `0` 时,表示内存使用量不受限制,即 TiFlash TopN 和 Sort 算子不会触发溢写。详情请参考 [TiFlash 溢写到磁盘](/tiflash/tiflash-spill-disk.md)。 + + + +> **注意:** +> +> - 如果 TiDB 集群有多个 TiFlash 节点,TopN 和 Sort 通常在多个 TiFlash 节点上分布式执行。此变量控制单个 TiFlash 节点上 TopN 和 Sort 算子的最大内存使用量。 +> - 当此变量设置为 `-1` 时,TiFlash 会根据其自身配置项 [`max_bytes_before_external_sort`](/tiflash/tiflash-configuration.md#tiflash-configuration-parameters) 的值来确定 TopN 和 Sort 算子的最大内存使用量。 + + + + > **注意:** > -> - 假设一个 TiDB 集群有多个 TiFlash 节点,TopN 和 Sort 通常会在多个 TiFlash 节点中分布式执行。该变量控制的是单个 TiFlash 节点中 TopN 和 Sort 算子的最大内存使用量。 -> - 当该变量设置为 -1 时,TiFlash 将根据自身配置项 [`max_bytes_before_external_sort`](/tiflash/tiflash-configuration.md#tiflash-配置参数-1) 的值来决定 TopN 和 Sort 算子的最大内存使用量。 +> - 如果 TiDB 集群有多个 TiFlash 节点,TopN 和 Sort 通常在多个 TiFlash 节点上分布式执行。此变量控制单个 TiFlash 节点上 TopN 和 Sort 算子的最大内存使用量。 +> - 当此变量设置为 `-1` 时,TiFlash 会根据其自身配置项 `max_bytes_before_external_sort` 的值来确定 TopN 和 Sort 算子的最大内存使用量。 -### `tidb_max_chunk_size` + + +### tidb_max_chunk_size - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否支持 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1024` -- 范围:`[32, 2147483647]` +- 取值范围:`[32, 2147483647]` - 单位:行 -- 这个变量用来设置执行过程中一个 chunk 最大的行数,设置过大可能引起缓存局部性的问题,建议该变量不要超过 65536。chunk 行数直接影响单个查询所需的内存。可以按照查询中所有的列的总宽度和 chunk 行数来粗略估算单个 chunk 所需内存,并结合执行器的并发数来粗略估算单个查询所需内存总量。建议单个 chunk 内存总量不要超过 16 MiB。当查询涉及数据量较大、单个 chunk 无法处理所有数据时,TiDB 会进行多次处理,每次处理时将 chunk 行数翻倍,从 [`tidb_init_chunk_size`](#tidb_init_chunk_size) 开始,直到 chunk 行数达到最大值 `tidb_max_chunk_size`。 +- 此变量用于设置执行过程中一个 Chunk 的最大行数。设置过大的值可能会导致缓存局部性问题。建议此变量的值不大于 65536。一个 Chunk 的行数直接影响单个查询所需的内存量。您可以粗略地估计单个 Chunk 所需的内存,方法是考虑查询中所有列的总宽度和 Chunk 的行数。结合执行器的并发性,您可以粗略估计单个查询所需的总内存。建议单个 Chunk 的总内存不超过 16 MiB。当查询涉及大量数据且单个 Chunk 不足以处理所有数据时,TiDB 会多次处理,每次处理迭代都会使 Chunk 大小加倍,从 [`tidb_init_chunk_size`](#tidb_init_chunk_size) 开始,直到 Chunk 大小达到 `tidb_max_chunk_size` 的值。 -### `tidb_max_delta_schema_count` +### tidb_max_delta_schema_count v2.1.18 和 v3.0.5 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否支持 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1024` -- 范围:`[100, 16384]` -- 这个变量用来设置缓存 schema 版本信息(对应版本修改的相关 table IDs)的个数限制,可设置的范围 100 - 16384。此变量在 2.1.18 及之后版本支持。 +- 取值范围:`[100, 16384]` +- 该变量用于设置允许缓存的最大 schema 版本数(为相应版本修改的表 ID)。取值范围为 100 ~ 16384。 -### `tidb_max_paging_size` 从 v6.3.0 版本开始引入 +### tidb_max_paging_size v6.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`50000` - 范围:`[1, 9223372036854775807]` - 单位:行 -- 这个变量用来设置 coprocessor 协议中 paging size 的最大的行数。请合理设置该值,设置过小,TiDB 与 TiKV 的 RPC 交互会更频繁;设置过大,导数据和全表扫等特定场景会占用更多内存。该变量的默认值对于 OLTP 场景较友好,如果业务只使用了 TiKV 作为存储引擎,当执行偏 OLAP 的负载时,可以考虑将变量值调大,有可能获得更好的性能。 +- 该变量用于设置 Coprocessor 分页请求过程中的最大行数。将其设置为太小的值会增加 TiDB 和 TiKV 之间的 RPC 计数,而将其设置为太大的值在某些情况下会导致过多的内存使用,例如加载数据和全表扫描。此变量的默认值在 OLTP 场景中比在 OLAP 场景中带来更好的性能。如果应用程序仅使用 TiKV 作为存储引擎,请考虑在执行 OLAP 工作负载查询时增加此变量的值,这可能会带来更好的性能。 -### `tidb_max_tiflash_threads` 从 v6.1.0 版本开始引入 +### tidb_max_tiflash_threads v6.1.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` - 范围:`[-1, 256]` - 单位:线程 -- TiFlash 中 request 执行的最大并发度。默认值为 `-1`,表示该系统变量无效,此时最大并发度取决于 TiFlash 配置项 `profiles.default.max_threads` 的设置。`0` 表示由 TiFlash 系统自动设置该值。 +- 该变量用于设置 TiFlash 执行请求的最大并发数。默认值为 `-1`,表示此系统变量无效,最大并发数取决于 TiFlash 配置 `profiles.default.max_threads` 的设置。当值为 `0` 时,TiFlash 会自动配置最大线程数。 -### `tidb_mem_oom_action` 从 v6.1.0 版本开始引入 +### tidb_mem_oom_action v6.1.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`CANCEL` - 可选值:`CANCEL`,`LOG` -- 该变量控制当单个查询使用的内存超过限制 (`tidb_mem_quota_query`) 且不能再利用临时磁盘时,TiDB 所采取的操作。详情见 [TiDB 内存控制](/configure-memory-usage.md)。 -- 该变量默认值为 `CANCEL`,但在 TiDB v4.0.2 及之前的版本中,默认值为 `LOG`。 -- 在 v6.1.0 之前这个开关通过 TiDB 配置文件 (`oom-action`) 进行配置,升级到 v6.1.0 时会自动继承原有设置。 -### `tidb_mem_quota_analyze` 从 v6.1.0 版本开始引入 + + +- 指定当单个 SQL 语句超过 `tidb_mem_quota_query` 指定的内存配额且无法溢出到磁盘时,TiDB 执行的操作。有关详细信息,请参阅 [TiDB 内存控制](/configure-memory-usage.md)。 + + + + + +- 指定当单个 SQL 语句超过 [`tidb_mem_quota_query`](#tidb_mem_quota_query) 指定的内存配额且无法溢出到磁盘时,TiDB 执行的操作。 + + + +- 默认值为 `CANCEL`,但在 TiDB v4.0.2 及更早版本中,默认值为 `LOG`。 +- 此设置以前是一个 `tidb.toml` 选项 (`oom-action`),但从 TiDB v6.1.0 开始更改为系统变量。 + +### tidb_mem_quota_analyze v6.1.0 新增 > **警告:** > -> 目前限制 ANALYZE 的内存使用量为实验特性,在生产环境中使用时可能存在内存统计有误差的情况。 +> 目前,`ANALYZE` 内存配额是一项实验性功能,并且在生产环境中内存统计信息可能不准确。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` +- 范围:`[-1, 9223372036854775807]` - 单位:字节 -- 取值范围:`[-1, 9223372036854775807]` -- 这个变量用来控制 TiDB 更新统计信息时的最大总内存占用,包括用户执行的 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 和 TiDB 后台自动执行的统计信息更新任务。当总的内存占用超过这个阈值时,用户执行的 `ANALYZE` 会被终止退出,并通过错误信息提示用户尝试更小的采样率或稍后重试。如果 TiDB 后台自动执行的统计信息更新任务因内存超限而退出,且使用的采样率高于默认值,则会使用默认采样率重试一次。当该变量值为负数或零时,TiDB 不对更新统计信息的前后台任务进行内存限制。 +- 此变量控制 TiDB 更新统计信息的最大内存使用量。当您手动执行 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 以及 TiDB 在后台自动分析任务时,会发生这种内存使用。当总内存使用量超过此阈值时,用户执行的 `ANALYZE` 将退出,并报告一条错误消息,提醒您尝试降低采样率或稍后重试。如果 TiDB 后台的自动任务因超过内存阈值而退出,并且使用的采样率高于默认值,则 TiDB 将使用默认采样率重试更新。当此变量值为负数或零时,TiDB 不限制手动和自动更新任务的内存使用量。 > **注意:** > -> 只有在 TiDB 的启动配置文件中开启了 `run-auto-analyze` 选项,该 TiDB 集群才会触发 `auto_analyze`。 +> 仅当在 TiDB 启动配置文件中启用了 `run-auto-analyze` 时,才会在 TiDB 集群中触发 `auto_analyze`。 -### `tidb_mem_quota_apply_cache` 从 v5.0 版本开始引入 +### tidb_mem_quota_apply_cache v5.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`33554432` (32 MiB) - 范围:`[0, 9223372036854775807]` - 单位:字节 -- 这个变量用来设置 `Apply` 算子中局部 Cache 的内存使用阈值。 -- `Apply` 算子中局部 Cache 用来加速 `Apply` 算子的计算,该变量可以设置 `Apply` Cache 的内存使用阈值。设置变量值为 `0` 可以关闭 `Apply` Cache 功能。 +- 该变量用于设置 `Apply` 算子中本地缓存的内存使用阈值。 +- `Apply` 算子中的本地缓存用于加速 `Apply` 算子的计算。您可以将变量设置为 `0` 以禁用 `Apply` 缓存功能。 -### `tidb_mem_quota_binding_cache` 从 v6.0.0 版本开始引入 +### tidb_mem_quota_binding_cache v6.0.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`67108864` (64 MiB) +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`67108864` - 范围:`[0, 2147483647]` - 单位:字节 -- 这个变量用来设置存放 `binding` 的缓存的内存使用阈值。 -- 如果一个系统创建或者捕获了过多的绑定,导致绑定所使用的内存空间超过该阈值,TiDB 会在日志中增加警告日志进行提示。这种情况下,缓存无法存放所有可用的绑定,并且无法保证哪些绑定存在于缓存中,因此,可能存在一些查询无法使用可用绑定的情况。此时,可以调大该变量的值,从而保证所有可用绑定都能正常使用。修改变量值以后,需要执行命令 `admin reload bindings` 重新加载绑定,确保变更生效。 +- 该变量用于设置缓存 bindings 所用内存的阈值。 +- 如果系统创建或捕获过多的 bindings,导致过度使用内存空间,TiDB 会在日志中返回警告。在这种情况下,缓存无法容纳所有可用的 bindings 或确定要存储哪些 bindings。因此,某些查询可能会错过它们的 bindings。要解决此问题,您可以增加此变量的值,这将增加用于缓存 bindings 的内存。修改此参数后,您需要运行 `admin reload bindings` 以重新加载 bindings 并验证修改。 -### `tidb_mem_quota_query` +### tidb_mem_quota_query - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1073741824` (1 GiB) - 范围:`[-1, 9223372036854775807]` - 单位:字节 -- 在 v6.1.0 之前的版本中,作用域为 `SESSION`。v6.1.0 及之后的版本,作用域变更为 `SESSION | GLOBAL`。 -- 在 v6.5.0 之前的版本中,该变量用来设置单条查询的内存使用限制,如果单条查询执行过程中使用的内存量超过该阈值,会触发系统变量 [`tidb_mem_oom_action`](#tidb_mem_oom_action-从-v610-版本开始引入) 中指定的行为。 -- 在 v6.5.0 及之后的版本中,该变量用来设置单个会话整体的内存使用限制,如果某个会话执行过程中使用的内存量超过该阈值,会触发系统变量 [`tidb_mem_oom_action`](#tidb_mem_oom_action-从-v610-版本开始引入) 中指定的行为。需要注意的是,自 v6.5.0 版本开始,会话的内存使用量包含会话中事务所消耗的内存。v6.5.0 及之后版本对事务内存的控制行为有所变化,详见 [txn-total-size-limit](/tidb-configuration-file.md#txn-total-size-limit)。 -- 当变量值为 `0` 或 `-1` 时,表示内存阈值为正无穷。此外,当变量值小于 128 时,将默认被设置为 `128`。 -### `tidb_memory_debug_mode_alarm_ratio` + + +- 对于低于 TiDB v6.1.0 的版本,这是一个会话范围变量,并使用 `tidb.toml` 中的 `mem-quota-query` 值作为初始值。从 v6.1.0 开始,`tidb_mem_quota_query` 是一个 `SESSION | GLOBAL` 范围变量。 +- 对于低于 TiDB v6.5.0 的版本,此变量用于设置 **查询** 的内存配额阈值。如果查询在执行期间的内存配额超过阈值,TiDB 将执行由 [`tidb_mem_oom_action`](#tidb_mem_oom_action-new-in-v610) 定义的操作。 +- 对于 TiDB v6.5.0 及更高版本,此变量用于设置 **会话** 的内存配额阈值。如果会话在执行期间的内存配额超过阈值,TiDB 将执行由 [`tidb_mem_oom_action`](#tidb_mem_oom_action-new-in-v610) 定义的操作。请注意,从 TiDB v6.5.0 开始,会话的内存使用量包含会话中事务消耗的内存。有关 TiDB v6.5.0 及更高版本中事务内存使用量的控制行为,请参阅 [`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit)。 +- 当您将变量值设置为 `0` 或 `-1` 时,内存阈值为正无穷大。当您设置的值小于 128 时,该值将默认为 `128`。 + + + + + +- 对于低于 TiDB v6.1.0 的版本,这是一个会话范围变量。从 v6.1.0 开始,`tidb_mem_quota_query` 是一个 `SESSION | GLOBAL` 范围变量。 +- 对于低于 TiDB v6.5.0 的版本,此变量用于设置 **查询** 的内存配额阈值。如果查询在执行期间的内存配额超过阈值,TiDB 将执行由 [`tidb_mem_oom_action`](#tidb_mem_oom_action-new-in-v610) 定义的操作。 +- 对于 TiDB v6.5.0 及更高版本,此变量用于设置**会话**的内存配额阈值。如果会话在执行期间的内存配额超过阈值,TiDB 将执行由 [`tidb_mem_oom_action`](#tidb_mem_oom_action-new-in-v610) 定义的操作。请注意,从 TiDB v6.5.0 开始,会话的内存使用量包含会话中事务消耗的内存。 +- 当您将变量值设置为 `0` 或 `-1` 时,内存阈值为正无穷大。当您设置的值小于 128 时,该值将默认为 `128`。 + + + +### tidb_memory_debug_mode_alarm_ratio - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:浮点型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Float - 默认值:`0` -- 该变量表示在 TiDB memory debug 模式下,允许的内存统计误差值。 -- 该变量用于 TiDB 内部测试,**不推荐修改该变量值**。 +- 此变量表示 TiDB 内存调试模式下允许的内存统计误差值。 +- 此变量用于 TiDB 的内部测试。**不建议**设置此变量。 -### `tidb_memory_debug_mode_min_heap_inuse` +### tidb_memory_debug_mode_min_heap_inuse - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` -- 该变量用于 TiDB 内部测试,**不推荐修改该变量值**,因为开启后会影响 TiDB 的性能。 -- 配置此参数后,TiDB 会进入 memory debug 模式进行内存追踪准确度的分析。TiDB 会在后续执行 SQL 语句的过程中频繁触发 GC,并将实际内存使用和内存统计值做对比。若当前内存使用大于 `tidb_memory_debug_mode_min_heap_inuse` 且内存统计误差超过 `tidb_memory_debug_mode_alarm_ratio`,则会输出相关内存信息到日志和文件中。 +- 此变量用于 TiDB 的内部测试。**不建议**设置此变量。启用此变量会影响 TiDB 的性能。 +- 配置此参数后,TiDB 将进入内存调试模式,以分析内存跟踪的准确性。TiDB 将在后续 SQL 语句的执行过程中频繁触发 GC,并比较实际内存使用量和内存统计信息。如果当前内存使用量大于 `tidb_memory_debug_mode_min_heap_inuse` 且内存统计误差超过 `tidb_memory_debug_mode_alarm_ratio`,TiDB 会将相关的内存信息输出到日志和文件。 -### `tidb_memory_usage_alarm_ratio` +### tidb_memory_usage_alarm_ratio + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:浮点数 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Float - 默认值:`0.7` - 范围:`[0.0, 1.0]` -- 这个变量用于设置触发 tidb-server 内存告警的内存使用比率。默认情况下,当 TiDB 内存使用量超过总内存的 70% 且满足[报警条件](/configure-memory-usage.md#tidb-server-内存占用过高时的报警)时,TiDB 会打印报警日志。 -- 当配置该变量的值为 `0` 或 `1` 时,表示关闭内存阈值报警功能。 -- 当配置该变量为 `0` 到 `1` 之间的值时,表示开启内存阈值报警功能: - - 如果系统变量 [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-从-v640-版本开始引入) 等于 0,则内存报警阈值为 `tidb_memory_usage_alarm_ratio * 系统内存大小`。 - - 如果系统变量 `tidb_server_memory_limit` 被设置为大于 0,则内存报警阈值为 `tidb_memory_usage_alarm_ratio * tidb_server_memory_limit`。 + + +- 此变量设置触发 tidb-server 内存告警的内存使用率。默认情况下,当 TiDB 内存使用量超过其总内存的 70% 并且满足任何 [告警条件](/configure-memory-usage.md#trigger-the-alarm-of-excessive-memory-usage) 时,TiDB 会打印告警日志。 +- 当此变量配置为 `0` 或 `1` 时,表示禁用内存阈值告警功能。 +- 当此变量配置为大于 `0` 且小于 `1` 的值时,表示启用内存阈值告警功能。 + + - 如果系统变量 [`tidb_server_memory_limit`](#tidb_server_memory_limit-new-in-v640) 的值为 `0`,则内存告警阈值为 `tidb_memory-usage-alarm-ratio * 系统内存大小`。 + - 如果系统变量 `tidb_server_memory_limit` 的值设置为大于 0,则内存告警阈值为 `tidb_memory-usage-alarm-ratio * tidb_server_memory_limit`。 + + -### `tidb_memory_usage_alarm_keep_record_num` 从 v6.4.0 版本开始引入 + + +- 此变量设置触发 [tidb-server 内存告警](https://docs.pingcap.com/zh/tidb/stable/configure-memory-usage#trigger-the-alarm-of-excessive-memory-usage) 的内存使用率。 +- 当此变量配置为 `0` 或 `1` 时,表示禁用内存阈值告警功能。 +- 当此变量配置为大于 `0` 且小于 `1` 的值时,表示启用内存阈值告警功能。 + + + +### tidb_memory_usage_alarm_keep_record_num New in v6.4.0 + + + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + + - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`5` - 范围:`[1, 10000]` -- 当 tidb-server 内存占用超过内存报警阈值并触发报警时,TiDB 默认只保留最近 5 次报警时所生成的状态文件。你可以通过该变量调整该次数。 +- 当 tidb-server 内存使用量超过内存告警阈值并触发告警时,TiDB 默认仅保留最近 5 次告警期间生成的状态文件。您可以使用此变量调整此数量。 -### `tidb_merge_join_concurrency` +### tidb_merge_join_concurrency - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer +- 范围:`[1, 256]` - 默认值:`1` -- 取值范围:`[1, 256]` -- 设置 `MergeJoin` 算子执行查询时的并发度。 -- **不推荐设置该变量**,修改该变量值可能会造成数据正确性问题。 +- 此变量设置查询执行时 `MergeJoin` 算子的并发度。 +- **不建议**设置此变量。修改此变量的值可能会导致数据正确性问题。 -### `tidb_merge_partition_stats_concurrency` +### tidb_merge_partition_stats_concurrency - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`1` -- 这个变量用于 TiDB analyze 分区表时,对分区表统计信息进行合并时的并发度。 +- 此变量指定 TiDB 分析分区表时,合并分区表统计信息的并发度。 -### `tidb_enable_async_merge_global_stats` 从 v7.5.0 版本开始引入 +### tidb_enable_async_merge_global_stats New in v7.5.0 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON`。从 v7.5.0 之前版本升级到 v7.5.0 或之后版本时,默认值为 `OFF`。 -- 这个变量用于设置 TiDB 使用异步方式合并统计信息,以避免 OOM 问题。 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:`ON`。当您将 TiDB 从低于 v7.5.0 的版本升级到 v7.5.0 或更高版本时,默认值为 `OFF`。 +- 此变量用于 TiDB 异步合并全局统计信息,以避免 OOM 问题。 -### `tidb_metric_query_range_duration` 从 v4.0 版本开始引入 +### tidb_metric_query_range_duration New in v4.0 + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`60` - 范围:`[10, 216000]` - 单位:秒 -- 这个变量设置了查询 `METRIC_SCHEMA` 时生成的 Prometheus 语句的 range duration。 +- 此变量用于设置查询 `METRICS_SCHEMA` 时生成的 Prometheus 语句的范围持续时间。 + +### tidb_metric_query_step New in v4.0 -### `tidb_metric_query_step` 从 v4.0 版本开始引入 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`60` - 范围:`[10, 216000]` - 单位:秒 -- 这个变量设置了查询 `METRIC_SCHEMA` 时生成的 Prometheus 语句的 step。 +- 此变量用于设置查询 `METRICS_SCHEMA` 时生成的 Prometheus 语句的步长。 -### `tidb_min_paging_size` 从 v6.2.0 版本开始引入 +### tidb_min_paging_size New in v6.2.0 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`128` - 范围:`[1, 9223372036854775807]` - 单位:行 -- 这个变量用来设置 coprocessor 协议中 paging size 的最小的行数。请合理设置该值,设置过小,TiDB 与 TiKV 的 RPC 交互会更频繁;设置过大,IndexLookup 带 Limit 场景会出现性能下降。该变量的默认值对于 OLTP 场景较友好,如果业务只使用了 TiKV 作为存储引擎,当执行偏 OLAP 的负载时,可以考虑将变量值调大,有可能获得更好的性能。 +- 此变量用于设置 coprocessor 分页请求过程中的最小行数。将其设置为太小的值会增加 TiDB 和 TiKV 之间的 RPC 请求计数,而将其设置为太大的值可能会导致使用 IndexLookup with Limit 执行查询时性能下降。此变量的默认值在 OLTP 场景中比在 OLAP 场景中带来更好的性能。如果应用程序仅使用 TiKV 作为存储引擎,请考虑在执行 OLAP 工作负载查询时增加此变量的值,这可能会为您带来更好的性能。 -![Paging size impact on TPCH](/media/paging-size-impact-on-tpch.png) +![分页大小对 TPCH 的影响](/media/paging-size-impact-on-tpch.png) -开启 [`tidb_enable_paging`](#tidb_enable_paging-从-v540-版本开始引入) 时,`tidb_min_paging_size` 和 [`tidb_max_paging_size`](#tidb_max_paging_size-从-v630-版本开始引入) 对 TPCH 的性能影响如上图所示,纵轴是执行时间,越小越好。 +如图所示,当启用 [`tidb_enable_paging`](#tidb_enable_paging-new-in-v540) 时,TPCH 的性能会受到 `tidb_min_paging_size` 和 [`tidb_max_paging_size`](#tidb_max_paging_size-new-in-v630) 设置的影响。纵轴是执行时间,越小越好。 -### `tidb_mpp_store_fail_ttl` +### tidb_mpp_store_fail_ttl - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 类型:Duration - 默认值:`60s` -- 刚重启的 TiFlash 可能不能正常提供服务。为了防止查询失败,TiDB 会限制 tidb-server 向刚重启的 TiFlash 节点发送查询。这个变量表示刚重启的 TiFlash 不被发送请求的时间范围。 +- 新启动的 TiFlash 节点不提供服务。为了防止查询失败,TiDB 限制 tidb-server 向新启动的 TiFlash 节点发送查询。此变量指示新启动的 TiFlash 节点不发送请求的时间范围。 -### `tidb_multi_statement_mode` 从 v4.0.11 版本开始引入 +### tidb_multi_statement_mode v4.0.11 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:枚举 - 默认值:`OFF` - 可选值:`OFF`,`ON`,`WARN` -- 该变量用于控制是否在同一个 `COM_QUERY` 调用中执行多个查询。 -- 为了减少 SQL 注入攻击的影响,TiDB 目前默认不允许在同一 `COM_QUERY` 调用中执行多个查询。该变量可用作早期 TiDB 版本的升级路径选项。该变量值与是否允许多语句行为的对照表如下: - -| 客户端设置 | `tidb_multi_statement_mode` 值 | 是否允许多语句 | -|------------------------|-----------------------------------|--------------------------------| -| Multiple Statements = ON | OFF | 允许 | -| Multiple Statements = ON | ON | 允许 | -| Multiple Statements = ON | WARN | 允许 | -| Multiple Statements = OFF | OFF | 不允许 | -| Multiple Statements = OFF | ON | 允许 | -| Multiple Statements = OFF | WARN | 允许 + 警告提示 | +- 此变量控制是否允许在同一个 `COM_QUERY` 调用中执行多个查询。 +- 为了减少 SQL 注入攻击的影响,TiDB 默认情况下会阻止在同一个 `COM_QUERY` 调用中执行多个查询。此变量旨在用作从早期 TiDB 版本升级路径的一部分。以下行为适用: + +| 客户端设置 | `tidb_multi_statement_mode` 值 | 允许多个语句吗? | +| ------------------------- | --------------------------------- | ------------------------------ | +| Multiple Statements = ON | OFF | 是 | +| Multiple Statements = ON | ON | 是 | +| Multiple Statements = ON | WARN | 是 | +| Multiple Statements = OFF | OFF | 否 | +| Multiple Statements = OFF | ON | 是 | +| Multiple Statements = OFF | WARN | 是 (+ 返回警告) | > **注意:** > -> 只有默认值 `OFF` 才是安全的。如果用户业务是专为早期 TiDB 版本而设计的,那么需要将该变量值设为 `ON`。如果用户业务需要多语句支持,建议用户使用客户端提供的设置,不要使用 `tidb_multi_statement_mode` 变量进行设置。 - +> 只有默认值 `OFF` 才能被认为是安全的。如果您的应用程序是专门为早期版本的 TiDB 设计的,则可能需要设置 `tidb_multi_statement_mode=ON`。如果您的应用程序需要多语句支持,建议使用客户端库提供的设置,而不是 `tidb_multi_statement_mode` 选项。例如: > > * [go-sql-driver](https://github.com/go-sql-driver/mysql#multistatements) (`multiStatements`) > * [Connector/J](https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html) (`allowMultiQueries`) > * PHP [mysqli](https://www.php.net/manual/en/mysqli.quickstart.multiple-statement.php) (`mysqli_multi_query`) -### `tidb_opt_agg_push_down` +### tidb_nontransactional_ignore_error v6.1.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔 - 默认值:`OFF` -- 这个变量用来设置优化器是否执行聚合函数下推到 Join,Projection 和 UnionAll 之前的优化操作。当查询中聚合操作执行很慢时,可以尝试设置该变量为 ON。 +- 此变量指定在非事务 DML 语句中发生错误时是否立即返回错误。 +- 当该值设置为 `OFF` 时,非事务 DML 语句在第一个错误处立即停止并返回错误。所有后续批次都将被取消。 +- 当该值设置为 `ON` 并且批处理中发生错误时,后续批处理将继续执行,直到所有批处理都执行完毕。执行过程中发生的所有错误将一起在结果中返回。 -### `tidb_opt_broadcast_cartesian_join` +### tidb_opt_agg_push_down - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:布尔 +- 默认值:`OFF` +- 此变量用于设置优化器是否执行将聚合函数下推到 Join、Projection 和 UnionAll 之前位置的优化操作。 +- 当查询中的聚合操作速度较慢时,可以将变量值设置为 ON。 + +### tidb_opt_broadcast_cartesian_join + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:整数 - 默认值:`1` - 范围:`[0, 2]` -- 表示是否允许 Broadcast Cartesian Join 算法。 -- 值为 `0` 时表示不允许使用 Broadcast Cartesian Join 算法。值为 `1` 时表示根据 [`tidb_broadcast_join_threshold_count`](#tidb_broadcast_join_threshold_count-从-v50-版本开始引入) 的行数阈值确定是否允许使用 Broadcast Cartesian Join 算法。值为 `2` 时表示总是允许 Broadcast Cartesian Join 算法,即使表的大小超过了该阈值。 -- 该变量是 TiDB 内部使用的变量,**不推荐**修改该变量的值。 +- 指示是否允许 Broadcast Cartesian Join。 +- `0` 表示不允许 Broadcast Cartesian Join。`1` 表示基于 [`tidb_broadcast_join_threshold_count`](#tidb_broadcast_join_threshold_count-new-in-v50) 允许。`2` 表示始终允许,即使表大小超过阈值。 +- 此变量在 TiDB 内部使用,**不**建议修改其值。 -### `tidb_opt_concurrency_factor` +### tidb_opt_concurrency_factor - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:浮点数 - 范围:`[0, 18446744073709551615]` - 默认值:`3.0` -- 表示在 TiDB 中开启一个 Golang goroutine 的 CPU 开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 表示在 TiDB 中启动 Golang goroutine 的 CPU 成本。此变量在 [成本模型](/cost-model.md) 内部使用,**不**建议修改其值。 -### `tidb_opt_copcpu_factor` +### tidb_opt_copcpu_factor - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:浮点数 - 范围:`[0, 18446744073709551615]` - 默认值:`3.0` -- 表示 TiKV 协处理器处理一行数据的 CPU 开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 表示 TiKV Coprocessor 处理一行数据的 CPU 成本。此变量在 [成本模型](/cost-model.md) 内部使用,**不**建议修改其值。 -### `tidb_opt_correlation_exp_factor` +### tidb_opt_correlation_exp_factor - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:整数 - 默认值:`1` - 范围:`[0, 2147483647]` -- 当交叉估算方法不可用时,会采用启发式估算方法。这个变量用来控制启发式方法的行为。当值为 0 时不用启发式估算方法,大于 0 时,该变量值越大,启发式估算方法越倾向 index scan,越小越倾向 table scan。 +- 当基于列顺序相关性估计行数的方法不可用时,将使用启发式估计方法。此变量用于控制启发式方法的行为。 + - 当值为 0 时,不使用启发式方法。 + - 当值大于 0 时: + - 值越大,表示启发式方法中可能使用索引扫描。 + - 值越小,表示启发式方法中可能使用表扫描。 -### `tidb_opt_correlation_threshold` +### tidb_opt_correlation_threshold - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:浮点数 - 默认值:`0.9` - 范围:`[0, 1]` -- 这个变量用来设置优化器启用交叉估算 row count 方法的阈值。如果列和 handle 列之间的顺序相关性超过这个阈值,就会启用交叉估算方法。 -- 交叉估算方法可以简单理解为,利用这个列的直方图来估算 handle 列需要扫的行数。 +- 此变量用于设置阈值,该阈值确定是否启用使用列顺序相关性估计行数。如果当前列与 `handle` 列之间的顺序相关性超过阈值,则启用此方法。 -### `tidb_opt_cpu_factor` +### tidb_opt_cpu_factor - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:浮点数 - 范围:`[0, 2147483647]` - 默认值:`3.0` -- 表示 TiDB 处理一行数据的 CPU 开销。该变量是[代价模型](/cost-model.md)内部使用的变量,不建议修改该变量的值。 +- 表示 TiDB 处理一行数据的 CPU 成本。此变量在 [成本模型](/cost-model.md) 内部使用,**不**建议修改其值。 -### `tidb_opt_derive_topn` 从 v7.0.0 版本开始引入 +### `tidb_opt_derive_topn` v7.0.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:布尔 - 默认值:`OFF` -- 表示是否开启[从窗口函数中推导 TopN 或 Limit](/derive-topn-from-window.md) 的优化规则。 +- 控制是否启用 [从窗口函数推导 TopN 或 Limit](/derive-topn-from-window.md) 的优化规则。 -### `tidb_opt_desc_factor` +### tidb_opt_desc_factor - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:浮点数 - 范围:`[0, 18446744073709551615]` - 默认值:`3.0` -- 表示降序扫描时,TiKV 在磁盘上扫描一行数据的开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 表示 TiKV 以降序扫描磁盘中一行数据的成本。此变量在 [成本模型](/cost-model.md) 内部使用,**不**建议修改其值。 -### `tidb_opt_disk_factor` +### tidb_opt_disk_factor - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 类型:浮点数 - 范围:`[0, 18446744073709551615]` - 默认值:`1.5` -- 表示 TiDB 往临时磁盘读写一个字节数据的 I/O 开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 表示 TiDB 从临时磁盘读取或写入一个字节的数据的 I/O 成本。此变量在 [成本模型](/cost-model.md) 内部使用,**不**建议修改其值。 -### `tidb_opt_distinct_agg_push_down` +### tidb_opt_distinct_agg_push_down - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来设置优化器是否执行带有 `Distinct` 的聚合函数(比如 `select count(distinct a) from t`)下推到 Coprocessor 的优化操作。当查询中带有 `Distinct` 的聚合操作执行很慢时,可以尝试设置该变量为 `1`。 +- 此变量用于设置优化器是否执行将带有 `distinct` 的聚合函数(例如 `select count(distinct a) from t`)下推到 Coprocessor 的优化操作。 +- 当带有 `distinct` 操作的聚合函数在查询中速度较慢时,您可以将变量值设置为 `1`。 -在以下示例中,`tidb_opt_distinct_agg_push_down` 开启前,TiDB 需要从 TiKV 读取所有数据,并在 TiDB 侧执行 `distinct`。`tidb_opt_distinct_agg_push_down` 开启后,`distinct a` 被下推到了 Coprocessor,在 `HashAgg_5` 里新增里一个 `group by` 列 `test.t.a`。 +在以下示例中,在启用 `tidb_opt_distinct_agg_push_down` 之前,TiDB 需要从 TiKV 读取所有数据并在 TiDB 端执行 `distinct`。 启用 `tidb_opt_distinct_agg_push_down` 后,`distinct a` 被下推到 Coprocessor,并且将 `group by` 列 `test.t.a` 添加到 `HashAgg_5`。 ```sql mysql> desc select count(distinct a) from test.t; @@ -3506,210 +4068,220 @@ mysql> desc select count(distinct a) from test.t; 4 rows in set (0.00 sec) ``` -### `tidb_opt_enable_correlation_adjustment` +### tidb_opt_enable_correlation_adjustment - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制优化器是否开启交叉估算。 +- 此变量用于控制优化器是否基于列顺序相关性来估计行数 -### `tidb_opt_enable_hash_join` 从 v6.5.6、v7.1.2 和 v7.4.0 版本开始引入 +### tidb_opt_enable_hash_join v6.5.6、v7.1.2 和 v7.4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 控制优化器是否会选择表的哈希连接。默认打开 (`ON`)。设置为 `OFF` 时,优化器在生成执行计划时会避免选择表的哈希连接,除非没有其他连接方式可用。 -- 如果同时使用了 `tidb_opt_enable_hash_join` 和 `HASH_JOIN` Hint,则 `HASH_JOIN` Hint 优先级更高。即使 `tidb_opt_enable_hash_join` 被设置为 `OFF`,如果在查询中指定了 `HASH_JOIN` Hint,TiDB 优化器仍然会强制执行哈希连接计划。 +- 此变量用于控制优化器是否为表选择哈希连接。 默认值为 `ON`。 如果设置为 `OFF`,则优化器在生成执行计划时会避免选择哈希连接,除非没有其他连接算法可用。 +- 如果同时配置了系统变量 `tidb_opt_enable_hash_join` 和 `HASH_JOIN` hint,则 `HASH_JOIN` hint 优先。 即使 `tidb_opt_enable_hash_join` 设置为 `OFF`,当您在查询中指定 `HASH_JOIN` hint 时,TiDB 优化器仍然会强制执行哈希连接计划。 -### `tidb_opt_enable_non_eval_scalar_subquery` 从 v7.3.0 版本开始引入 +### tidb_opt_enable_non_eval_scalar_subquery v7.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来控制 `EXPLAIN` 语句是否禁止提前执行可以在优化阶段展开的常量子查询。该变量设置为 `OFF` 时,`EXPLAIN` 语句会在优化阶段提前展开子查询。该变量设置为 `ON` 时,`EXPLAIN` 语句不会在优化阶段展开子查询。更多信息请参考[禁止子查询提前展开](/explain-walkthrough.md#禁止子查询提前执行)。 +- 此变量用于控制 `EXPLAIN` 语句是否禁用在优化阶段可以展开的常量子查询的执行。 当此变量设置为 `OFF` 时,`EXPLAIN` 语句会在优化阶段提前展开子查询。 当此变量设置为 `ON` 时,`EXPLAIN` 语句不会在优化阶段展开子查询。 有关更多信息,请参见 [禁用子查询扩展](/explain-walkthrough.md#disable-the-early-execution-of-subqueries)。 -### `tidb_opt_enable_late_materialization` 从 v7.0.0 版本开始引入 +### tidb_opt_enable_late_materialization v7.0.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制是否启用 [TiFlash 延迟物化](/tiflash/tiflash-late-materialization.md)功能。注意在 TiFlash [Fast Scan 模式](/tiflash/use-fastscan.md)下,延迟物化功能暂不可用。 -- 当设置该变量为 `OFF` 关闭 TiFlash 延迟物化功能时,如果 `SELECT` 语句中包含过滤条件(`WHERE` 子句),TiFlash 会先扫描查询所需列的全部数据后再进行过滤。当设置该变量为 `ON` 开启 TiFlash 延迟物化功能时,TiFlash 会先扫描下推到 TableScan 算子的过滤条件相关的列数据,过滤得到符合条件的行后,再扫描这些行的其他列数据,继续后续计算,从而减少 IO 扫描和数据处理的计算量。 +- 此变量用于控制是否启用 [TiFlash 延迟物化](/tiflash/tiflash-late-materialization.md) 功能。 请注意,TiFlash 延迟物化在 [快速扫描模式](/tiflash/use-fastscan.md) 下不起作用。 +- 当此变量设置为 `OFF` 以禁用 TiFlash 延迟物化功能时,为了处理带有过滤条件(`WHERE` 子句)的 `SELECT` 语句,TiFlash 会在过滤之前扫描所需列的所有数据。 当此变量设置为 `ON` 以启用 TiFlash 延迟物化功能时,TiFlash 可以首先扫描与下推到 TableScan 算子的过滤条件相关的列数据,过滤出满足条件的行,然后扫描这些行的其他列的数据以进行进一步计算,从而减少数据处理的 IO 扫描和计算。 -### `tidb_opt_enable_mpp_shared_cte_execution` 从 v7.2.0 版本开始引入 +### tidb_opt_enable_mpp_shared_cte_execution v7.2.0 新增 > **警告:** > -> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 此变量控制的功能是实验性的。 不建议在生产环境中使用它。 此功能可能会更改或删除,恕不另行通知。 如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 该变量控制非递归的[公共表表达式 (CTE)](/sql-statements/sql-statement-with.md) 是否可以在 TiFlash MPP 执行。默认情况下,未开启该变量时,CTE 在 TiDB 执行,相较于开启该功能,执行性能有较大差距。 +- 此变量控制非递归 [公共表表达式 (CTE)](/sql-statements/sql-statement-with.md) 是否可以在 TiFlash MPP 上执行。 默认情况下,当禁用此变量时,CTE 在 TiDB 上执行,与启用此功能相比,性能差距很大。 -### `tidb_opt_enable_fuzzy_binding` 从 v7.6.0 版本开始引入 +### tidb_opt_enable_fuzzy_binding v7.6.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 该变量控制是否开启[跨数据库绑定执行计划](/sql-plan-management.md#跨数据库绑定执行计划-cross-db-binding)功能。 +- 此变量控制是否启用 [跨数据库绑定](/sql-plan-management.md#cross-database-binding) 功能。 -### `tidb_opt_fix_control` 从 v6.5.3 和 v7.1.0 版本开始引入 +### tidb_opt_fix_control v6.5.3 和 v7.1.0 新增 + + - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:字符串 +- 持久化到集群:是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:String - 默认值:`""` -- 这个变量用来控制优化器的一些内部行为。 -- 一部分优化器行为的选择依赖用户场景或 SQL 编写方式。通过设置该变量,你可以更细粒度地控制优化器的行为,并且避免集群升级后优化器行为变化导致的性能回退。 -- 详细介绍请参考 [Optimizer Fix Controls](/optimizer-fix-controls.md)。 +- 此变量用于控制优化器的一些内部行为。 +- 优化器的行为可能因用户场景或 SQL 语句而异。 此变量提供了对优化器更细粒度的控制,并有助于防止升级后由于优化器中的行为更改而导致的性能下降。 +- 有关更详细的介绍,请参见 [优化器修复控制](/optimizer-fix-controls.md)。 -### `tidb_opt_force_inline_cte` 从 v6.3.0 版本开始引入 + -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用来控制是否强制 inline CTE。默认值为 `OFF`,即默认不强制 inline CTE。注意,此时依旧可以通过 `MERGE()` hint 来开启个别 CTE 的 inline。如果设置为 `ON`,则当前 session 中所有查询的 CTE(递归 CTE 除外)都会 inline。 + -### `tidb_opt_advanced_join_hint` 从 v7.0.0 版本开始引入 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 字符串 +- 默认值: `""` +- 此变量用于控制优化器的一些内部行为。 +- 优化器的行为可能因用户场景或 SQL 语句而异。此变量提供了对优化器更细粒度的控制,并有助于防止升级后由于优化器行为更改而导致的性能下降。 +- 有关更详细的介绍,请参阅 [优化器修复控制](/optimizer-fix-controls.md)。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`ON` -- 这个变量用来控制包括 [`HASH_JOIN()` Hint](/optimizer-hints.md#hash_joint1_name--tl_name-)、[`MERGE_JOIN()` Hint](/optimizer-hints.md#merge_joint1_name--tl_name-) 等用于控制连接算法的 Join Method Hint 是否会影响 Join Reorder 的优化过程,包括 [`LEADING()` Hint](/optimizer-hints.md#leadingt1_name--tl_name-) 的使用。默认值为 `ON`,即默认不影响。如果设置为 `OFF`,在一些同时使用 Join Method Hint 和 `LEADING()` Hint 的场景下可能会产生冲突。 + -> **注意:** -> -> v7.0.0 之前的版本行为和将该变量设置为 `OFF` 的行为一致。为确保向前兼容,从旧版本升级到 v7.0.0 及之后版本的集群,该变量会被设置成 `OFF`。为了获取更灵活的 Hint 行为,强烈建议在确保无性能回退的情况下,将该变量切换为 `ON`。 +### tidb_opt_force_inline_cte v6.3.0 新增 -### `tidb_opt_insubq_to_join_and_agg` +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 布尔值 +- 默认值: `OFF` +- 此变量用于控制是否内联整个会话中的公共表表达式 (CTE)。默认值为 `OFF`,表示默认情况下不强制内联 CTE。但是,您仍然可以通过指定 `MERGE()` hint 来内联 CTE。如果变量设置为 `ON`,则此会话中的所有 CTE(递归 CTE 除外)都将被强制内联。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`ON` -- 这个变量用来设置是否开启优化规则:将子查询转成 join 和 aggregation。 +### tidb_opt_advanced_join_hint v7.0.0 新增 + +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 布尔值 +- 默认值: `ON` +- 此变量用于控制 Join Method hint(例如 [`HASH_JOIN()` hint](/optimizer-hints.md#hash_joint1_name--tl_name-) 和 [`MERGE_JOIN()` hint](/optimizer-hints.md#merge_joint1_name--tl_name-))是否影响 Join Reorder 优化过程,包括 [`LEADING()` hint](/optimizer-hints.md#leadingt1_name--tl_name-) 的使用。默认值为 `ON`,表示不影响。如果设置为 `OFF`,则在同时使用 Join Method hint 和 `LEADING()` hint 的某些场景中可能会发生冲突。 + +> **注意:** +> +> v7.0.0 之前的版本的行为与将此变量设置为 `OFF` 的行为一致。为了确保向前兼容性,当您从早期版本升级到 v7.0.0 或更高版本的集群时,此变量设置为 `OFF`。为了获得更灵活的 hint 行为,强烈建议在没有性能下降的情况下将此变量切换为 `ON`。 - 例如,打开这个优化规则后,会将下面子查询做如下变化: +### tidb_opt_insubq_to_join_and_agg - {{< copyable "sql" >}} +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 布尔值 +- 默认值: `ON` +- 此变量用于设置是否启用将子查询转换为 join 和聚合的优化规则。 +- 例如,在启用此优化规则后,子查询将按如下方式转换: ```sql select * from t where t.a in (select aa from t1); ``` - 将子查询转成如下 join: - - {{< copyable "sql" >}} + 子查询转换为 join 如下: ```sql select t.* from t, (select aa from t1 group by aa) tmp_t where t.a = tmp_t.aa; ``` - 如果 t1 在列 `aa` 上有 unique 且 not null 的限制,可以直接改写为如下,不需要添加 aggregation。 - - {{< copyable "sql" >}} + 如果 `t1` 在 `aa` 列中被限制为 `unique` 和 `not null`。您可以使用以下语句,无需聚合。 ```sql select t.* from t, t1 where t.a=t1.aa; ``` -### `tidb_opt_join_reorder_threshold` +### tidb_opt_join_reorder_threshold - 作用域: SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 -- 默认值:`0` -- 范围:`[0, 2147483647]` -- 这个变量用来控制 TiDB Join Reorder 算法的选择。当参与 Join Reorder 的节点个数大于该阈值时,TiDB 选择贪心算法,小于该阈值时 TiDB 选择动态规划 (dynamic programming) 算法。 -- 目前对于 OLTP 的查询,推荐保持默认值。对于 OLAP 的查询,推荐将变量值设为 10~15 来获得 AP 场景下更好的连接顺序。 +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 整数 +- 默认值: `0` +- 范围: `[0, 2147483647]` +- 此变量用于控制 TiDB Join Reorder 算法的选择。当参与 Join Reorder 的节点数大于此阈值时,TiDB 选择贪婪算法,当小于此阈值时,TiDB 选择动态规划算法。 +- 目前,对于 OLTP 查询,建议保持默认值。对于 OLAP 查询,建议将变量值设置为 10~15,以便在 OLAP 场景中获得更好的连接顺序。 -### `tidb_opt_limit_push_down_threshold` +### tidb_opt_limit_push_down_threshold -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 -- 默认值:`100` -- 范围:`[0, 2147483647]` -- 这个变量用来设置将 Limit 和 TopN 算子下推到 TiKV 的阈值。 -- 如果 Limit 或者 TopN 的取值小于等于这个阈值,则 Limit 和 TopN 算子会被强制下推到 TiKV。该变量可以解决部分由于估算误差导致 Limit 或者 TopN 无法被下推的问题。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 整数 +- 默认值: `100` +- 范围: `[0, 2147483647]` +- 此变量用于设置确定是否将 Limit 或 TopN 算子下推到 TiKV 的阈值。 +- 如果 Limit 或 TopN 算子的值小于或等于此阈值,则这些算子将被强制下推到 TiKV。此变量解决了 Limit 或 TopN 算子由于错误估计而无法部分下推到 TiKV 的问题。 -### `tidb_opt_memory_factor` +### tidb_opt_memory_factor -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 -- 范围:`[0, 2147483647]` -- 默认值:`0.001` -- 表示 TiDB 存储一行数据的内存开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 浮点数 +- 范围: `[0, 2147483647]` +- 默认值: `0.001` +- 表示 TiDB 存储一行数据的内存成本。此变量在 [成本模型](/cost-model.md) 中内部使用,**不**建议修改其值。 -### `tidb_opt_mpp_outer_join_fixed_build_side` 从 v5.1.0 版本开始引入 +### tidb_opt_mpp_outer_join_fixed_build_side v5.1.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`OFF` -- 当该变量值为 `ON` 时,左连接始终使用内表作为构建端,右连接始终使用外表作为构建端。将该变量值设为 `OFF` 后,外连接可以灵活选择任意一边表作为构建端。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 布尔值 +- 默认值: `OFF` +- 当变量值为 `ON` 时,左连接算子始终使用内表作为构建端,右连接算子始终使用外表作为构建端。如果将值设置为 `OFF`,则外连接算子可以使用表的任意一侧作为构建端。 -### `tidb_opt_network_factor` +### tidb_opt_network_factor -- 作用域:SESSION | GLOBAL -- 是否持久化 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 -- 范围:`[0, 2147483647]` -- 默认值:`1.0` -- 表示传输 1 比特数据的网络净开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 浮点数 +- 范围: `[0, 2147483647]` +- 默认值: `1.0` +- 表示通过网络传输 1 字节数据的网络成本。此变量在 [成本模型](/cost-model.md) 中内部使用,**不**建议修改其值。 -### `tidb_opt_objective` 从 v7.4.0 版本开始引入 +### tidb_opt_objective v7.4.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:枚举型 -- 默认值:`moderate` -- 可选值:`moderate`、`determinate` -- 该变量用于设置优化器优化目标。`moderate` 与 TiDB v7.4.0 之前版本的默认行为保持一致,优化器会利用更多信息尝试生成更优的计划。`determinate` 则倾向于保守,保持执行计划稳定。 -- 实时统计信息是 TiDB 在运行时根据 DML 语句自动更新的表的总行数以及修改的行数。该变量保持默认值 `moderate` 时,TiDB 会基于实时统计信息来生成执行计划。该变量设为 `determinate` 后,TiDB 在生成执行计划时将不再使用实时统计信息,这会让执行计划相对稳定。 -- 对于长期稳定的 OLTP 业务,或者如果用户对系统已有的执行计划非常确定,则推荐使用 `determinate` 模式减少执行计划跳变的可能。同时还可以结合 [`LOCK STATS`](/sql-statements/sql-statement-lock-stats.md) 来阻止统计信息的更新,进一步稳定执行计划。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 枚举 +- 默认值: `moderate` +- 可选值: `moderate`, `determinate` +- 此变量控制优化器的目标。`moderate` 保持 TiDB v7.4.0 之前版本的默认行为,其中优化器尝试使用更多信息来生成更好的执行计划。`determinate` 模式倾向于更保守,并使执行计划更稳定。 +- 实时统计信息是基于 DML 语句自动更新的总行数和修改的行数。当此变量设置为 `moderate`(默认值)时,TiDB 基于实时统计信息生成执行计划。当此变量设置为 `determinate` 时,TiDB 不使用实时统计信息来生成执行计划,这将使执行计划更稳定。 +- 对于长期稳定的 OLTP 工作负载,或者如果用户对现有的执行计划有信心,建议使用 `determinate` 模式以减少意外执行计划更改的可能性。此外,您可以使用 [`LOCK STATS`](/sql-statements/sql-statement-lock-stats.md) 来防止统计信息被修改并进一步稳定执行计划。 -### `tidb_opt_ordering_index_selectivity_ratio` 从 v8.0.0 版本开始引入 +### tidb_opt_ordering_index_selectivity_ratio v8.0.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 -- 默认值:`-1` -- 范围:`[-1, 1]` -- 当一个索引满足 SQL 语句中的 `ORDER BY` 和 `LIMIT` 子句,但有部分过滤条件未被该索引覆盖时,该系统变量用于控制该索引的估算行数。 -- 该变量适用的场景与系统变量 [`tidb_opt_ordering_index_selectivity_threshold`](#tidb_opt_ordering_index_selectivity_threshold-从-v700-版本开始引入) 相同。 -- 与 `tidb_opt_ordering_index_selectivity_threshold` 的实现不同,该变量采用范围内符合条件的可能行数的比率或百分比。 -- 取值为 `-1`(默认值)或小于 `0` 时,禁用此变量。取值在 `0` 到 `1` 之间时,对应 0% 到 100% 的比率(例如,`0.5` 对应 `50%`)。 -- 在以下示例中,表 `t` 共有 1,000,000 行数据。示例使用相同查询,但应用了不同的 `tidb_opt_ordering_index_selectivity_ratio` 值。示例中的查询包含一个 `WHERE` 子句谓词,该谓词匹配少量行(1,000,000 中的 9,000 行)。存在一个支持 `ORDER BY a` 的索引(索引 `ia`),但是对 `b` 的过滤不在此索引中。根据实际的数据分布,满足 `WHERE` 子句和 `LIMIT 1` 的行可能在扫描非过滤索引时作为第一行访问到,也可能在几乎处理满足所有行后才找到。 -- 每个示例中都使用了一个索引 hint,用于展示对 estRows 的影响。最终计划选择取决于是否存在代价更低的其他计划。 -- 第一个示例使用默认值 `-1`,使用现有的估算公式。默认行为是,在找到符合条件的行之前,会扫描一小部分行进行估算。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: 浮点数 +- 默认值: `-1` +- 范围: `[-1, 1]` +- 此变量控制索引的估计行数,该索引匹配 SQL 语句 `ORDER BY`,当 SQL 语句中存在 `ORDER BY` 和 `LIMIT` 子句,但不包含某些过滤条件时。 +- 这解决了与系统变量 [tidb_opt_ordering_index_selectivity_threshold](#tidb_opt_ordering_index_selectivity_threshold-new-in-v700) 相同的查询模式。 +- 它的实现方式不同,它应用了合格行将被找到的可能范围的比率或百分比。 +- 值为 `-1`(默认)或小于 `0` 会禁用此比率。任何介于 `0` 和 `1` 之间的值都适用 0% 到 100% 的比率(例如,`0.5` 对应于 `50%`)。 +- 在以下示例中,表 `t` 总共有 1,000,000 行。使用相同的查询,但使用 `tidb_opt_ordering_index_selectivity_ratio` 的不同值。示例中的查询包含一个 `WHERE` 子句谓词,该谓词限定了很小百分比的行(1,000,000 行中的 9,000 行)。有一个索引支持 `ORDER BY a`(索引 `ia`),但 `b` 上的过滤器不包含在此索引中。根据实际的数据分布,当扫描非过滤索引时,匹配 `WHERE` 子句和 `LIMIT 1` 的行可能会作为访问的第一行找到,或者最坏的情况是,在几乎所有行都已处理之后找到。 +- 每个示例都使用索引提示来演示对 estRows 的影响。最终的计划选择取决于其他计划的可用性和成本。 +- 第一个示例使用默认值 `-1`,它使用现有的估计公式。默认情况下,在找到合格行之前,会扫描一小部分行进行估计。 ```sql > SET SESSION tidb_opt_ordering_index_selectivity_ratio = -1; @@ -3727,7 +4299,7 @@ mysql> desc select count(distinct a) from test.t; +-----------------------------------+---------+-----------+-----------------------+---------------------------------+ ``` -- 第二个示例使用 `0`,假设在找到符合条件的行之前,将扫描 0% 的行。 +- 第二个示例使用 `0`,它假设在找到合格行之前将扫描 0% 的行。 ```sql > SET SESSION tidb_opt_ordering_index_selectivity_ratio = 0; @@ -3745,7 +4317,7 @@ mysql> desc select count(distinct a) from test.t; +-----------------------------------+---------+-----------+-----------------------+---------------------------------+ ``` -- 第三个示例使用 `0.1`,假设在找到符合条件的行之前,将扫描 10% 的行。这个条件的过滤性较强,只有 1% 的行符合条件,因此最坏情况是找到这 1% 之前需要扫描 99% 的行。99% 中的 10% 大约是 9.9%,该数值会反映在 estRows 中。 +- 第三个示例使用 `0.1`,它假设在找到合格行之前将扫描 10% 的行。此条件具有很高的选择性,只有 1% 的行满足条件。因此,在最坏的情况下,可能需要扫描 99% 的行才能找到符合条件的 1%。99% 的 10% 大约是 9.9%,这反映在 estRows 中。 ```sql > SET SESSION tidb_opt_ordering_index_selectivity_ratio = 0.1; @@ -3763,7 +4335,7 @@ mysql> desc select count(distinct a) from test.t; +-----------------------------------+----------+-----------+-----------------------+---------------------------------+ ``` -- 第四个示例使用 `1.0`,假设在找到符合条件的行之前,将扫描 100% 的行。 +- 第四个示例使用 `1.0`,它假设在找到合格行之前将扫描 100% 的行。 ```sql > SET SESSION tidb_opt_ordering_index_selectivity_ratio = 1; @@ -3781,7 +4353,7 @@ mysql> desc select count(distinct a) from test.t; +-----------------------------------+-----------+-----------+-----------------------+---------------------------------+ ``` -- 第五个示例也使用 `1.0`,但是增加了一个对 `a` 的谓词,限制了最坏情况下的扫描范围,因为 `WHERE a <= 9000` 匹配了索引,大约有 9,000 行符合条件。考虑到 `b` 上的过滤谓词不在索引中,所有大约 9,000 行在找到符合 `b <= 9000` 的行之前都会被扫描。 +- 第五个例子也使用了 `1.0`,但增加了一个关于 `a` 的谓词,在最坏的情况下限制了扫描范围。这是因为 `WHERE a <= 9000` 匹配了索引,大约有 9,000 行符合条件。鉴于 `b` 上的过滤谓词不在索引中,在找到匹配 `b <= 9000` 的行之前,所有大约 9,000 行都被认为是扫描过的。 ```sql > SET SESSION tidb_opt_ordering_index_selectivity_ratio = 1; @@ -3799,19 +4371,19 @@ mysql> desc select count(distinct a) from test.t; +------------------------------------+---------+-----------+-----------------------+------------------------------------+ ``` -### `tidb_opt_ordering_index_selectivity_threshold` 从 v7.0.0 版本开始引入 +### tidb_opt_ordering_index_selectivity_threshold v7.0.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float - 默认值:`0` - 范围:`[0, 1]` -- 用于当 SQL 中存在 `ORDER BY` 和 `LIMIT` 子句且带有过滤条件时,控制优化器选择索引的行为。 -- 对于此类查询,优化器会考虑选择对应的索引来满足 `ORDER BY` 和 `LIMIT` 子句(即使这个索引并不满足任何过滤条件)。但是由于数据分布的复杂性,优化器在这种场景下可能会选择不优的索引。 -- 该变量表示一个阈值。当存在索引能满足过滤条件,且其选择率估算值低于该阈值时,优化器会避免选择用于满足 `ORDER BY` 和 `LIMIT` 的索引,而优先选择用于满足过滤条件的索引。 -- 例如,当把该变量设为 `0` 时,优化器保持默认行为;当设为 `1` 时,优化器总是优先选择满足过滤条件的索引,避免选择满足 `ORDER BY` 和 `LIMIT` 的索引。 -- 在以下示例中,`t` 表共有 1,000,000 行数据。使用 `b` 列上的索引时,其估算行数是大约 8,748 行,因此其选择率估算值大约是 0.0087。默认情况下,优化器选择了 `a` 列上的索引。而将该变量设为 `0.01` 之后,由于 `b` 列上的索引的选择率 (0.0087) 低于 0.01,优化器选择了 `b` 列上的索引。 +- 该变量用于控制优化器在 SQL 语句中存在 `ORDER BY` 和 `LIMIT` 子句以及过滤条件时,如何选择索引。 +- 对于此类查询,优化器会考虑选择相应的索引来满足 `ORDER BY` 和 `LIMIT` 子句(即使此索引不满足任何过滤条件)。但是,由于数据分布的复杂性,优化器在这种情况下可能会选择次优索引。 +- 此变量表示一个阈值。当存在可以满足过滤条件的索引并且其选择性估计低于此阈值时,优化器将避免选择用于满足 `ORDER BY` 和 `LIMIT` 的索引。相反,它会优先选择满足过滤条件的索引。 +- 例如,当变量设置为 `0` 时,优化器保持其默认行为;当它设置为 `1` 时,优化器始终优先选择满足过滤条件的索引,并避免选择同时满足 `ORDER BY` 和 `LIMIT` 子句的索引。 +- 在以下示例中,表 `t` 总共有 1,000,000 行。当使用列 `b` 上的索引时,其估计行数约为 8,748,因此其选择性估计值约为 0.0087。默认情况下,优化器选择列 `a` 上的索引。但是,将此变量设置为 0.01 后,由于列 `b` 上的索引的选择性 (0.0087) 小于 0.01,因此优化器选择列 `b` 上的索引。 ```sql > EXPLAIN SELECT * FROM t WHERE b <= 9000 ORDER BY a LIMIT 1; @@ -3840,15 +4412,15 @@ mysql> desc select count(distinct a) from test.t; +----------------------------------+---------+-----------+----------------------+-------------------------------------+ ``` -### `tidb_opt_prefer_range_scan` 从 v5.0 版本开始引入 +### tidb_opt_prefer_range_scan v5.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 将该变量值设为 `ON` 后,优化器总是偏好区间扫描而不是全表扫描。 -- 在以下示例中,`tidb_opt_prefer_range_scan` 开启前,TiDB 优化器需要执行全表扫描。`tidb_opt_prefer_range_scan` 开启后,优化器选择了索引区间扫描。 +- 将此变量的值设置为 `ON` 后,优化器始终优先选择范围扫描而不是全表扫描。 +- 在以下示例中,在启用 `tidb_opt_prefer_range_scan` 之前,TiDB 优化器执行全表扫描。启用 `tidb_opt_prefer_range_scan` 后,优化器选择索引范围扫描。 ```sql explain select * from t where age=5; @@ -3874,30 +4446,94 @@ explain select * from t where age=5; 3 rows in set (0.00 sec) ``` -### `tidb_opt_projection_push_down` 从 v6.1.0 版本开始引入 +### tidb_opt_prefix_index_single_scan New in v6.4.0 -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`OFF` -- 指定是否允许优化器将 `Projection` 算子下推到 TiKV 或者 TiFlash。 +- Scope: SESSION | GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes +- Default value: `ON` +- 此变量控制 TiDB 优化器是否将一些过滤条件推送到前缀索引,以避免不必要的表查找并提高查询性能。 +- 当此变量值设置为 `ON` 时,一些过滤条件会被推送到前缀索引。假设 `col` 列是表中的索引前缀列。查询中的 `col is null` 或 `col is not null` 条件被视为索引上的过滤条件,而不是表查找的过滤条件,从而避免了不必要的表查找。 -### `tidb_opt_range_max_size` 从 v6.4.0 版本开始引入 +
+tidb_opt_prefix_index_single_scan 的使用示例 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 默认值:`67108864` (64 MiB) -- 取值范围:`[0, 9223372036854775807]` -- 单位:字节 -- 该变量用于指定优化器构造扫描范围的内存用量上限。当该变量为 `0` 时,表示对扫描范围没有内存限制。如果构造精确的扫描范围会超出内存用量限制,优化器会使用更宽松的扫描范围(例如 `[[NULL,+inf]]`)。如果执行计划中未使用精确的扫描范围,可以调大该变量的值让优化器构造精确的扫描范围。 +创建一个带有前缀索引的表: + +```sql +CREATE TABLE t (a INT, b VARCHAR(10), c INT, INDEX idx_a_b(a, b(5))); +``` + +禁用 `tidb_opt_prefix_index_single_scan`: + +```sql +SET tidb_opt_prefix_index_single_scan = 'OFF'; +``` + +对于以下查询,执行计划使用前缀索引 `idx_a_b`,但需要表查找(出现 `IndexLookUp` 算子)。 + +```sql +EXPLAIN FORMAT='brief' SELECT COUNT(1) FROM t WHERE a = 1 AND b IS NOT NULL; ++-------------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ +| HashAgg | 1.00 | root | | funcs:count(Column#8)->Column#5 | +| └─IndexLookUp | 1.00 | root | | | +| ├─IndexRangeScan(Build) | 99.90 | cop[tikv] | table:t, index:idx_a_b(a, b) | range:[1 -inf,1 +inf], keep order:false, stats:pseudo | +| └─HashAgg(Probe) | 1.00 | cop[tikv] | | funcs:count(1)->Column#8 | +| └─Selection | 99.90 | cop[tikv] | | not(isnull(test.t.b)) | +| └─TableRowIDScan | 99.90 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++-------------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ +6 rows in set (0.00 sec) +``` + +启用 `tidb_opt_prefix_index_single_scan`: + +```sql +SET tidb_opt_prefix_index_single_scan = 'ON'; +``` + +启用此变量后,对于以下查询,执行计划使用前缀索引 `idx_a_b`,但不需要表查找。 + +```sql +EXPLAIN FORMAT='brief' SELECT COUNT(1) FROM t WHERE a = 1 AND b IS NOT NULL; ++--------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++--------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ +| StreamAgg | 1.00 | root | | funcs:count(Column#7)->Column#5 | +| └─IndexReader | 1.00 | root | | index:StreamAgg | +| └─StreamAgg | 1.00 | cop[tikv] | | funcs:count(1)->Column#7 | +| └─IndexRangeScan | 99.90 | cop[tikv] | table:t, index:idx_a_b(a, b) | range:[1 -inf,1 +inf], keep order:false, stats:pseudo | ++--------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ +4 rows in set (0.00 sec) +``` + +
+ +### tidb_opt_projection_push_down New in v6.1.0 + +- Scope: SESSION +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes +- Type: Boolean +- Default value: `OFF` +- 指定是否允许优化器将 `Projection` 下推到 TiKV 或 TiFlash coprocessor。 -该变量的使用示例如下: +### tidb_opt_range_max_size New in v6.4.0 + +- Scope: SESSION | GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes +- Default value: `67108864` (64 MiB) +- Scope: `[0, 9223372036854775807]` +- Unit: Bytes +- 此变量用于设置优化器构建扫描范围时使用的内存上限。当变量值为 `0` 时,构建扫描范围没有内存限制。如果构建精确扫描范围消耗的内存超过限制,优化器将使用更宽松的扫描范围(例如 `[[NULL,+inf]]`)。如果执行计划没有使用精确扫描范围,您可以增加此变量的值,以使优化器构建精确扫描范围。 + +此变量的使用示例如下:
tidb_opt_range_max_size 使用示例 -查看该变量的默认值,即优化器构造扫描范围最多使用 64 MiB 内存。 +查看此变量的默认值。从结果可以看出,优化器最多使用 64 MiB 的内存来构建扫描范围。 ```sql SELECT @@tidb_opt_range_max_size; @@ -3916,7 +4552,7 @@ SELECT @@tidb_opt_range_max_size; EXPLAIN SELECT * FROM t use index (idx) WHERE a IN (10,20,30) AND b IN (40,50,60); ``` -在 64 MiB 的内存最大限制约束下,优化器构造出精确的扫描范围 `[10 40,10 40], [10 50,10 50], [10 60,10 60], [20 40,20 40], [20 50,20 50], [20 60,20 60], [30 40,30 40], [30 50,30 50], [30 60,30 60]`,见如下执行计划返回结果。 +在 64 MiB 内存上限内,优化器构建以下精确扫描范围 `[10 40,10 40], [10 50,10 50], [10 60,10 60], [20 40,20 40], [20 50,20 50], [20 60,20 60], [30 40,30 40], [30 50,30 50], [30 60,30 60]`,如下面的执行计划结果所示。 ```sql +-------------------------------+---------+-----------+--------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -3929,7 +4565,7 @@ EXPLAIN SELECT * FROM t use index (idx) WHERE a IN (10,20,30) AND b IN (40,50,60 3 rows in set (0.00 sec) ``` -现将优化器构造扫描范围的内存用量上限设为 1500 字节。 +现在设置优化器构建扫描范围的内存使用上限为 1500 字节。 ```sql SET @@tidb_opt_range_max_size = 1500; @@ -3943,7 +4579,7 @@ Query OK, 0 rows affected (0.00 sec) EXPLAIN SELECT * FROM t USE INDEX (idx) WHERE a IN (10,20,30) AND b IN (40,50,60); ``` -在 1500 字节内存的最大限制约束下,优化器构造出了更宽松的扫描范围 `[10,10], [20,20], [30,30]`,并用 warning 提示用户构造精确的扫描范围所需的内存用量超出了 `tidb_opt_range_max_size` 的限制。 +在 1500 字节的内存限制下,优化器构建了更宽松的扫描范围 `[10,10], [20,20], [30,30]`,并使用警告通知用户构建精确扫描范围所需的内存使用量超过了 `tidb_opt_range_max_size` 的限制。 ```sql +-------------------------------+---------+-----------+--------------------------+-----------------------------------------------------------------+ @@ -3970,7 +4606,7 @@ SHOW WARNINGS; 1 row in set (0.00 sec) ``` -再将优化器构造扫描范围的内存用量上限设为 100 字节。 +然后设置内存使用上限为 100 字节: ```sql set @@tidb_opt_range_max_size = 100; @@ -3984,7 +4620,7 @@ Query OK, 0 rows affected (0.00 sec) EXPLAIN SELECT * FROM t USE INDEX (idx) WHERE a IN (10,20,30) AND b IN (40,50,60); ``` -在 100 字节的内存最大限制约束下,优化器选择了 `IndexFullScan`,并用 warning 提示用户构造精确的扫描范围所需的内存超出了 `tidb_opt_range_max_size` 的限制。 +在 100 字节的内存限制下,优化器选择 `IndexFullScan`,并使用警告通知用户构建精确扫描范围所需的内存超过了 `tidb_opt_range_max_size` 的限制。 ```sql +-------------------------------+----------+-----------+--------------------------+----------------------------------------------------+ @@ -4013,581 +4649,587 @@ SHOW WARNINGS;
-### `tidb_opt_scan_factor` +### tidb_opt_scan_factor - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float - 范围:`[0, 2147483647]` - 默认值:`1.5` -- 表示升序扫描时,TiKV 在磁盘上扫描一行数据的开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 表示 TiKV 从磁盘按升序扫描一行数据的成本。此变量在 [成本模型](/cost-model.md) 内部使用,**不**建议修改其值。 -### `tidb_opt_seek_factor` +### tidb_opt_seek_factor - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float - 范围:`[0, 2147483647]` - 默认值:`20` -- 表示 TiDB 从 TiKV 请求数据的初始开销。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 +- 表示 TiDB 从 TiKV 请求数据的启动成本。此变量在 [成本模型](/cost-model.md) 内部使用,**不**建议修改其值。 -### `tidb_opt_skew_distinct_agg` 从 v6.2.0 版本开始引入 +### tidb_opt_skew_distinct_agg v6.2.0 新增 > **注意:** > -> 开启该变量带来的查询性能优化仅对 TiFlash 有效。 +> 启用此变量进行查询性能优化**仅对 TiFlash 有效**。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来设置优化器是否将带有 `DISTINCT` 的聚合函数(例如 `SELECT b, count(DISTINCT a) FROM t GROUP BY b`)改写为两层聚合函数(例如 `SELECT b, count(a) FROM (SELECT b, a FROM t GROUP BY b, a) t GROUP BY b`)。当聚合列有严重的数据倾斜,且 `DISTINCT` 列有很多不同的值时,这种改写能够避免查询执行过程中的数据倾斜,从而提升查询性能。 +- 此变量设置优化器是否将带有 `DISTINCT` 的聚合函数重写为两级聚合函数,例如将 `SELECT b, COUNT(DISTINCT a) FROM t GROUP BY b` 重写为 `SELECT b, COUNT(a) FROM (SELECT b, a FROM t GROUP BY b, a) t GROUP BY b`。当聚合列存在严重倾斜且 `DISTINCT` 列具有许多不同的值时,此重写可以避免查询执行中的数据倾斜并提高查询性能。 -### `tidb_opt_three_stage_distinct_agg` 从 v6.3.0 版本开始引入 +### tidb_opt_three_stage_distinct_agg v6.3.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean - 默认值:`ON` -- 该变量用于控制在 MPP 模式下是否将 `COUNT(DISTINCT)` 聚合改写为三阶段分布式执行的聚合。 -- 该变量目前仅对只有一个 `COUNT(DISTINCT)` 的聚合生效。 - -### `tidb_opt_tiflash_concurrency_factor` - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:浮点数 -- 范围:`[0, 2147483647]` -- 默认值:`24.0` -- 表示 TiFlash 计算的并发数。该变量是[代价模型](/cost-model.md)内部使用的变量,**不建议**修改该变量的值。 - -## `tidb_opt_use_invisible_indexes` 从 v8.0.0 版本开始引入 - -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用来设置是否允许优化器选择[不可见索引 (Invisible Index)](/sql-statements/sql-statement-create-index.md#不可见索引)。默认情况下,不可见索引由 DML 语句维护,不会被查询优化器使用。当修改变量为 `ON` 时,对该会话中的查询,优化器可以选择不可见索引进行查询优化。 - -### `tidb_opt_write_row_id` - -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用来设置是否允许 `INSERT`、`REPLACE` 和 `UPDATE` 操作 `_tidb_rowid` 列,默认是不允许操作。该选项仅用于 TiDB 工具导数据时使用。 - -### `tidb_optimizer_selectivity_level` - -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 -- 默认值:`0` -- 范围:`[0, 2147483647]` -- 控制优化器估算逻辑的更迭。更改该变量值后,优化器的估算逻辑会产生较大的改变。目前该变量的有效值只有 `0`,不建议设为其它值。 +- 此变量指定是否将 `COUNT(DISTINCT)` 聚合重写为 MPP 模式下的三阶段聚合。 +- 此变量目前适用于仅包含一个 `COUNT(DISTINCT)` 的聚合。 -### `tidb_partition_prune_mode` 从 v5.1 版本开始引入 +### tidb_opt_tiflash_concurrency_factor - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:枚举型 -- 默认值:`dynamic` -- 可选值:`static`、`dynamic`、`static-only`、`dynamic-only` -- 这个变量用来设置是否开启分区表动态裁剪模式。默认值为 `dynamic`。但是注意,`dynamic` 模式仅在表级别汇总统计信息(即 GlobalStats)收集完成的情况下生效。如果选择了 `dynamic` 但 GlobalStats 未收集完成,TiDB 会仍采用 `static` 模式。关于 GlobalStats 更多信息,请参考[动态裁剪模式下的分区表统计信息](/statistics.md#收集动态裁剪模式下的分区表统计信息)。关于动态裁剪模式更多信息,请参考[分区表动态裁剪模式](/partitioned-table.md#动态裁剪模式)。 - -### `tidb_persist_analyze_options` 从 v5.4.0 版本开始引入 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型: Float +- 范围: `[0, 2147483647]` +- 默认值: `24.0` +- 表示 TiFlash 计算的并发数。此变量在内部用于成本模型,不建议修改其值。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON` -- 这个变量用于控制是否开启 [ANALYZE 配置持久化](/statistics.md#持久化-analyze-配置)特性。 +### tidb_opt_use_invisible_indexes v8.0.0 新增 -### `tidb_pessimistic_txn_fair_locking` 从 v7.0.0 版本开始引入 +- 作用域: SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Boolean +- 默认值: `OFF` +- 此变量控制优化器是否可以在当前会话中选择[不可见索引](/sql-statements/sql-statement-create-index.md#invisible-index)进行查询优化。不可见索引由 DML 语句维护,但不会被查询优化器使用。这在您希望在永久删除索引之前进行双重检查的情况下非常有用。当变量设置为 `ON` 时,优化器可以在会话中选择不可见索引进行查询优化。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON` -- 是否对悲观锁启用加强的悲观锁唤醒模型。该模型可严格控制悲观锁单点冲突场景下事务的唤醒顺序,避免无效唤醒,大大降低原有唤醒机制中的随机性对事务延迟带来的不确定性。如果业务场景中遇到了单点悲观锁冲突频繁的情况(如高频更新同一行数据等),并进而引起语句重试频繁、尾延迟高,甚至偶尔发生 `pessimistic lock retry limit reached` 错误,可以尝试开启该变量来解决问题。 -- 对于从 v7.0.0 以前的版本升级到 v7.0.0 或更新版本的 TiDB 集群,该选项默认关闭。 +### tidb_opt_write_row_id > **注意:** > -> - 视具体业务场景的不同,启用该选项可能对存在频繁锁冲突的事务造成一定程度的吞吐下降(平均延迟上升)。 -> - 该选项目前仅对需要上锁单个 key 的语句有效。如果一个语句需要对多行同时上锁,则该选项不会对此类语句生效。 -> - 该功能从 v6.6.0 版本引入。在 v6.6.0 版本中,该功能由变量 [`tidb_pessimistic_txn_aggressive_locking`](https://docs.pingcap.com/zh/tidb/v6.6/system-variables#tidb_pessimistic_txn_aggressive_locking-%E4%BB%8E-v660-%E7%89%88%E6%9C%AC%E5%BC%80%E5%A7%8B%E5%BC%95%E5%85%A5) 控制,默认关闭。 - -### `tidb_placement_mode` 从 v6.0.0 版本开始引入 - -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 -- 默认值:`STRICT` -- 可选值:`STRICT`,`IGNORE` -- 该变量用于控制 DDL 语句是否忽略 [Placement Rules in SQL](/placement-rules-in-sql.md) 指定的放置规则。变量值为 `IGNORE` 时将忽略所有放置规则选项。 -- 该变量可由逻辑转储或逻辑恢复工具使用,确保即使绑定了不合适的放置规则,也始终可以成功创建表。这类似于 mysqldump 将 `SET FOREIGN_KEY_CHECKS=0;` 写入每个转储文件的开头部分。 +> 此 TiDB 变量不适用于 TiDB Cloud。 -### `tidb_plan_cache_invalidation_on_fresh_stats` 从 v7.1.0 版本开始引入 +- 作用域: SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Boolean +- 默认值: `OFF` +- 此变量用于控制是否允许 `INSERT`、`REPLACE` 和 `UPDATE` 语句操作 `_tidb_rowid` 列。此变量只能在使用 TiDB 工具导入数据时使用。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON` -- 该变量用于控制当某张表上的统计信息更新后,与该表相关的 Plan Cache 是否自动失效。 -- 开启此变量有助于 Plan Cache 更有效地利用可用的统计信息生成执行计划,例如: - - 有时 Plan Cache 会在统计信息尚不可用时生成执行计划。开启此变量后,Plan Cache 会在统计信息可用时重新生成执行计划。 - - 当表上数据分布发生变化时,之前的最优执行计划可能对于现在不再是最优的。开启此变量后,Plan Cache 会在重新收集统计信息后重新生成执行计划。 -- 对于从 v7.1.0 以前的版本升级到 v7.1.0 及以上版本的 TiDB 集群,该选项默认关闭 (`OFF`)。 +### tidb_optimizer_selectivity_level -### `tidb_plan_cache_max_plan_size` 从 v7.1.0 版本开始引入 +- 作用域: SESSION +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Integer +- 默认值: `0` +- 范围: `[0, 2147483647]` +- 此变量控制优化器估计逻辑的迭代。更改此变量的值后,优化器的估计逻辑将发生很大变化。目前,`0` 是唯一有效的值。不建议将其设置为其他值。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 默认值:`2097152`(即 2 MiB) -- 取值范围:`[0, 9223372036854775807]`,单位为 Byte。支持带单位的内存格式 "KiB|MiB|GiB|TiB"。`0` 表示表示不设限制。 -- 这个变量用来控制可以缓存的 Prepare 或非 Prepare 语句执行计划的最大大小。超过该值的执行计划将不会被缓存到 Plan Cache 中。详情请参考 [Prepare 语句执行计划缓存](/sql-prepared-plan-cache.md#prepared-plan-cache-的内存管理)和[非 Prepare 语句执行计划缓存](/sql-non-prepared-plan-cache.md#使用方法)。 +### tidb_partition_prune_mode v5.1 新增 -### `tidb_pprof_sql_cpu` 从 v4.0 版本开始引入 - -- 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`0` -- 范围:`[0, 1]` -- 这个变量用来控制是否在 profile 输出中标记出对应的 SQL 语句,用于定位和排查性能问题。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 类型: Enumeration +- 默认值: `dynamic` +- 可选值: `static`, `dynamic`, `static-only`, `dynamic-only` +- 指定分区表使用 `dynamic` 还是 `static` 模式。请注意,只有在收集了完整的表级统计信息或 GlobalStats 后,动态分区才有效。在收集 GlobalStats 之前,TiDB 将使用 `static` 模式。有关 GlobalStats 的详细信息,请参阅[在动态剪枝模式下收集分区表的统计信息](/statistics.md#collect-statistics-of-partitioned-tables-in-dynamic-pruning-mode)。有关动态剪枝模式的详细信息,请参阅[分区表的动态剪枝模式](/partitioned-table.md#dynamic-pruning-mode)。 -### `tidb_opt_prefix_index_single_scan` 从 v6.4.0 版本开始引入 +### tidb_persist_analyze_options v5.4.0 新增 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 -- 默认值:`ON` -- 这个变量用于控制 TiDB 优化器是否将某些过滤条件下推到前缀索引,尽量避免不必要的回表,从而提高查询性能。 -- 将该变量设置为 `ON` 时,会将过滤条件下推到前缀索引。此时,假设一张表中 `col` 列是索引前缀列,查询语句中的 `col is null` 或者 `col is not null` 条件会被归为索引上的过滤条件,而不是回表时的过滤条件,从而避免不必要的回表。 +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `ON` +- 此变量控制是否启用 [ANALYZE 配置持久化](/statistics.md#persist-analyze-configurations)功能。 -
-该变量的使用示例 +### tidb_pessimistic_txn_fair_locking v7.0.0 新增 -创建一张带前缀索引的表: +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `ON` +- 确定是否对悲观事务使用增强的悲观锁唤醒模型。此模型严格控制悲观锁定单点冲突场景中悲观事务的唤醒顺序,以避免不必要的唤醒。它大大降低了现有唤醒机制的随机性带来的不确定性。如果在您的业务场景中遇到频繁的单点悲观锁定冲突(例如,频繁更新同一行数据),从而导致频繁的语句重试、高尾部延迟,甚至偶尔出现 `pessimistic lock retry limit reached` 错误,您可以尝试启用此变量来解决问题。 +- 对于从低于 v7.0.0 的版本升级到 v7.0.0 或更高版本的 TiDB 集群,默认情况下禁用此变量。 -```sql -CREATE TABLE t (a INT, b VARCHAR(10), c INT, INDEX idx_a_b(a, b(5))); -``` +> **注意:** +> +> - 根据具体的业务场景,启用此选项可能会导致频繁锁冲突的事务吞吐量降低(平均延迟增加)。 +> - 此选项仅对需要锁定单个键的语句生效。如果一个语句需要同时锁定多行,则此选项对这些语句无效。 +> - 此功能在 v6.6.0 中由 [`tidb_pessimistic_txn_aggressive_locking`](https://docs.pingcap.com/tidb/v6.6/system-variables#tidb_pessimistic_txn_aggressive_locking-new-in-v660) 变量引入,默认情况下禁用。 -此时关闭 `tidb_opt_prefix_index_single_scan`: +### tidb_placement_mode v6.0.0 新增 -```sql -SET tidb_opt_prefix_index_single_scan = 'OFF'; -``` +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 -对于以下查询,执行计划使用了前缀索引 `idx_a_b` 但需要回表(出现了 `IndexLookUp` 算子)。 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Enumeration +- 默认值: `STRICT` +- 可选值: `STRICT`, `IGNORE` +- 此变量控制 DDL 语句是否忽略 [SQL 中指定的放置规则](/placement-rules-in-sql.md)。当变量值为 `IGNORE` 时,所有放置规则选项都将被忽略。 +- 它旨在供逻辑转储/恢复工具使用,以确保即使分配了无效的放置规则,也可以始终创建表。这类似于 mysqldump 如何在每个转储文件的开头写入 `SET FOREIGN_KEY_CHECKS=0;`。 -```sql -EXPLAIN FORMAT='brief' SELECT COUNT(1) FROM t WHERE a = 1 AND b IS NOT NULL; -+-------------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+-------------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ -| HashAgg | 1.00 | root | | funcs:count(Column#8)->Column#5 | -| └─IndexLookUp | 1.00 | root | | | -| ├─IndexRangeScan(Build) | 99.90 | cop[tikv] | table:t, index:idx_a_b(a, b) | range:[1 -inf,1 +inf], keep order:false, stats:pseudo | -| └─HashAgg(Probe) | 1.00 | cop[tikv] | | funcs:count(1)->Column#8 | -| └─Selection | 99.90 | cop[tikv] | | not(isnull(test.t.b)) | -| └─TableRowIDScan | 99.90 | cop[tikv] | table:t | keep order:false, stats:pseudo | -+-------------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ -6 rows in set (0.00 sec) -``` +### `tidb_plan_cache_invalidation_on_fresh_stats` v7.1.0 新增 -此时打开 `tidb_opt_prefix_index_single_scan`: +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `ON` +- 此变量控制是否在更新相关表的统计信息时自动使计划缓存失效。 +- 启用此变量后,计划缓存可以更充分地利用统计信息来生成执行计划。例如: + - 如果在统计信息可用之前生成执行计划,则计划缓存在统计信息可用后重新生成执行计划。 + - 如果表的数据分布发生变化,导致先前最佳的执行计划变为非最佳,则计划缓存在重新收集统计信息后重新生成执行计划。 +- 对于从低于 v7.1.0 的版本升级到 v7.1.0 或更高版本的 TiDB 集群,默认情况下禁用此变量。 + +### `tidb_plan_cache_max_plan_size` v7.1.0 新增 -```sql -SET tidb_opt_prefix_index_single_scan = 'ON'; -``` +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 是 +- 默认值: `2097152` (即 2 MiB) +- 范围: `[0, 9223372036854775807]`,以字节为单位。也支持带有单位 "KiB|MiB|GiB|TiB" 的内存格式。`0` 表示没有限制。 +- 此变量控制可以缓存在预处理或非预处理计划缓存中的计划的最大大小。如果计划的大小超过此值,则该计划将不会被缓存。有关更多详细信息,请参阅[预处理计划缓存的内存管理](/sql-prepared-plan-cache.md#memory-management-of-prepared-plan-cache)和[非预处理计划缓存](/sql-plan-management.md#usage)。 -开启该变量后,对于以下查询,执行计划使用了前缀索引 `idx_a_b` 且不需要回表。 +### tidb_pprof_sql_cpu v4.0 新增 -```sql -EXPLAIN FORMAT='brief' SELECT COUNT(1) FROM t WHERE a = 1 AND b IS NOT NULL; -+--------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+--------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ -| StreamAgg | 1.00 | root | | funcs:count(Column#7)->Column#5 | -| └─IndexReader | 1.00 | root | | index:StreamAgg | -| └─StreamAgg | 1.00 | cop[tikv] | | funcs:count(1)->Column#7 | -| └─IndexRangeScan | 99.90 | cop[tikv] | table:t, index:idx_a_b(a, b) | range:[1 -inf,1 +inf], keep order:false, stats:pseudo | -+--------------------------+---------+-----------+------------------------------+-------------------------------------------------------+ -4 rows in set (0.00 sec) -``` +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 -
+- 作用域: GLOBAL +- 持久化到集群: 否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `0` +- 范围: `[0, 1]` +- 此变量用于控制是否在 profile 输出中标记相应的 SQL 语句,以识别和排除性能问题。 -### `tidb_prefer_broadcast_join_by_exchange_data_size` 从 v7.1.0 版本开始引入 +### tidb_prefer_broadcast_join_by_exchange_data_size v7.1.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 默认值:`OFF` -- 这个变量用于设定 TiDB 选择 [MPP Hash Join 算法](/tiflash/use-tiflash-mpp-mode.md#mpp-模式的算法支持)时,是否使用最小网络交换的数据量策略。开启该变量后,TiDB 会估算 Broadcast Hash Join 和 Shuffled Hash Join 两种算法所需进行网络交换的数据量,并选择网络交换数据量较小的算法。 -- 该功能开启后 [`tidb_broadcast_join_threshold_count`](#tidb_broadcast_join_threshold_count-从-v50-版本开始引入) 和 [`tidb_broadcast_join_threshold_size`](#tidb_broadcast_join_threshold_size-从-v50-版本开始引入) 将不再生效。 +- 此变量控制 TiDB 在选择 [MPP Hash Join 算法](/tiflash/use-tiflash-mpp-mode.md#algorithm-support-for-the-mpp-mode) 时,是否使用网络传输开销最小的算法。如果启用此变量,TiDB 将分别使用 `Broadcast Hash Join` 和 `Shuffled Hash Join` 估算网络中要交换的数据大小,然后选择较小的一个。 +- 启用此变量后,[`tidb_broadcast_join_threshold_count`](/system-variables.md#tidb_broadcast_join_threshold_count-new-in-v50) 和 [`tidb_broadcast_join_threshold_size`](/system-variables.md#tidb_broadcast_join_threshold_size-new-in-v50) 将不会生效。 -### `tidb_prepared_plan_cache_memory_guard_ratio` 从 v6.1.0 版本开始引入 +### tidb_prepared_plan_cache_memory_guard_ratio v6.1.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:浮点数 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Float - 默认值:`0.1` - 范围:`[0, 1]` -- 这个变量用来控制 Prepared Plan Cache 触发内存保护机制的阈值,具体可见 [Prepared Plan Cache 的内存管理](/sql-prepared-plan-cache.md#prepared-plan-cache-的内存管理)。 -- 在 v6.1.0 之前这个开关通过 TiDB 配置文件 (`prepared-plan-cache.memory-guard-ratio`) 进行配置,升级到 v6.1.0 时会自动继承原有设置。 +- 预处理计划缓存触发内存保护机制的阈值。有关详细信息,请参阅 [预处理计划缓存的内存管理](/sql-prepared-plan-cache.md)。 +- 此设置以前是一个 `tidb.toml` 选项 (`prepared-plan-cache.memory-guard-ratio`),但从 TiDB v6.1.0 开始更改为系统变量。 -### `tidb_prepared_plan_cache_size` 从 v6.1.0 版本开始引入 +### tidb_prepared_plan_cache_size v6.1.0 新增 > **警告:** > -> 从 v7.1.0 开始,该变量被废弃。请使用 [`tidb_session_plan_cache_size`](#tidb_session_plan_cache_size-从-v710-版本开始引入) 进行设置。 +> 从 v7.1.0 开始,此变量已弃用。请改用 [`tidb_session_plan_cache_size`](#tidb_session_plan_cache_size-new-in-v710) 进行设置。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`100` - 范围:`[1, 100000]` -- 这个变量用来控制单个 `SESSION` 的 Prepared Plan Cache 最多能够缓存的计划数量,具体可见 [Prepared Plan Cache 的内存管理](/sql-prepared-plan-cache.md#prepared-plan-cache-的内存管理)。 -- 在 v6.1.0 之前这个开关通过 TiDB 配置文件 (`prepared-plan-cache.capacity`) 进行配置,升级到 v6.1.0 时会自动继承原有设置。 +- 会话中可以缓存的最大计划数。有关详细信息,请参阅 [预处理计划缓存的内存管理](/sql-prepared-plan-cache.md)。 +- 此设置以前是一个 `tidb.toml` 选项 (`prepared-plan-cache.capacity`),但从 TiDB v6.1.0 开始更改为系统变量。 -### `tidb_projection_concurrency` +### tidb_projection_concurrency > **警告:** > -> 从 v5.0 版本开始,该变量被废弃。请使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 进行设置。 +> 从 v5.0 开始,此变量已弃用。请改用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-new-in-v50) 进行设置。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` - 范围:`[-1, 256]` - 单位:线程 -- 这个变量用来设置 `Projection` 算子的并发度。 -- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 +- 此变量用于设置 `Projection` 算子的并发度。 +- 值为 `-1` 表示将使用 `tidb_executor_concurrency` 的值。 -### `tidb_query_log_max_len` +### tidb_query_log_max_len - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`4096` (4 KiB) - 范围:`[0, 1073741824]` - 单位:字节 -- 该变量控制 SQL 语句输出的最大长度。当一条 SQL 语句的输出长度大于 `tidb_query_log_max_len` 时,输出将会被截断。 -- 在 v6.1.0 之前这个开关也可以通过 TiDB 配置文件 (`log.query-log-max-len`) 进行配置,升级到 v6.1.0 后仅可通过系统变量配置。 +- SQL 语句输出的最大长度。当语句的输出长度大于 `tidb_query_log_max_len` 值时,该语句将被截断输出。 +- 此设置以前也可用作 `tidb.toml` 选项 (`log.query-log-max-len`),但从 TiDB v6.1.0 开始仅作为系统变量。 -### `tidb_rc_read_check_ts` 从 v6.0.0 版本开始引入 +### tidb_rc_read_check_ts v6.0.0 新增 > **警告:** > -> - 该特性与 [`replica-read`](#tidb_replica_read-从-v40-版本开始引入) 尚不兼容,开启 `tidb_rc_read_check_ts` 的读请求无法使用 [`replica-read`](#tidb_replica_read-从-v40-版本开始引入),请勿同时开启两项特性。 -> - 如果客户端使用游标操作,建议不开启 `tidb_rc_read_check_ts` 这一特性,避免前一批返回数据已经被客户端使用而语句最终会报错的情况。 -> - 自 v7.0.0 版本开始,该变量对于使用 prepared statement 协议下 cursor fetch read 游标模式不再生效。 +> - 此功能与 [`replica-read`](#tidb_replica_read-new-in-v40) 不兼容。请勿同时启用 `tidb_rc_read_check_ts` 和 `replica-read`。 +> - 如果您的客户端使用游标,则不建议启用 `tidb_rc_read_check_ts`,以防客户端已使用前一批返回的数据,并且该语句最终失败。 +> - 从 v7.0.0 开始,此变量对于使用预处理语句协议的游标提取读取模式不再有效。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量用于优化时间戳的获取,适用于悲观事务 `READ-COMMITTED` 隔离级别下读写冲突较少的场景,开启此变量可以避免获取全局 timestamp 带来的延迟和开销,并优化事务内读语句延迟。 -- 如果读写冲突较为严重,开启此功能会增加额外开销和延迟,造成性能回退。更详细的说明,请参考[读已提交隔离级别 (Read Committed) 文档](/transaction-isolation-levels.md#读已提交隔离级别-read-committed)。 +- 此变量用于优化时间戳获取,适用于读已提交隔离级别且读写冲突很少的场景。启用此变量可以避免获取全局时间戳的延迟和成本,并可以优化事务级别的读取延迟。 +- 如果读写冲突严重,启用此功能将增加获取全局时间戳的成本和延迟,并可能导致性能下降。有关详细信息,请参阅 [读已提交隔离级别](/transaction-isolation-levels.md#read-committed-isolation-level)。 -### `tidb_rc_write_check_ts` 从 v6.3.0 版本开始引入 +### tidb_rc_write_check_ts v6.3.0 新增 > **警告:** > -> 该特性与 [`replica-read`](#tidb_replica_read-从-v40-版本开始引入) 尚不兼容。开启本变量后,客户端发送的所有请求都将无法使用 `replica-read`,因此请勿同时开启 `tidb_rc_write_check_ts` 和 `replica-read`。 +> 此功能目前与 [`replica-read`](#tidb_replica_read-new-in-v40) 不兼容。启用此变量后,客户端发送的所有请求都不能使用 `replica-read`。因此,请勿同时启用 `tidb_rc_write_check_ts` 和 `replica-read`。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量用于优化时间戳的获取,适用于悲观事务 `READ-COMMITTED` 隔离级别下点写冲突较少的场景。开启此变量可以避免点写语句获取全局时间戳带来的延迟和开销。目前该变量适用的点写语句包括 `UPDATE`、`DELETE`、`SELECT ...... FOR UPDATE` 三种类型。点写语句是指将主键或者唯一键作为过滤条件且最终执行算子包含 `POINT-GET` 的写语句。 -- 如果点写冲突较为严重,开启此变量会增加额外开销和延迟,造成性能回退。更详细的说明,请参考[读已提交隔离级别 (Read Committed) 文档](/transaction-isolation-levels.md#读已提交隔离级别-read-committed)。 +- 此变量用于优化时间戳的获取,适用于悲观事务的 `READ-COMMITTED` 隔离级别中点写冲突较少的场景。启用此变量可以避免在执行点写语句期间获取全局时间戳所带来的延迟和开销。目前,此变量适用于三种类型的点写语句:`UPDATE`、`DELETE` 和 `SELECT ...... FOR UPDATE`。点写语句是指使用主键或唯一键作为过滤条件,并且最终执行算子包含 `POINT-GET` 的写语句。 +- 如果点写冲突严重,启用此变量将增加额外的开销和延迟,从而导致性能下降。有关详细信息,请参阅 [读已提交隔离级别](/transaction-isolation-levels.md#read-committed-isolation-level)。 -### `tidb_read_consistency` 从 v5.4.0 版本开始引入 +### tidb_read_consistency v5.4.0 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是(注意当存在[非事务 DML 语句](/non-transactional-dml.md)时,使用 hint 修改该变量的值可能不生效) -- 类型:字符串 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是(请注意,如果存在[非事务性 DML 语句](/non-transactional-dml.md),则使用 hint 修改此变量的值可能不会生效。) +- 类型:String - 默认值:`strict` -- 此变量用于控制自动提交的读语句的读一致性。 -- 如果将变量值设置为 `weak`,则直接跳过读语句遇到的锁,读的执行可能会更快,这就是弱一致性读模式。但在该模式下,事务语义(例如原子性)和分布式一致性(线性一致性)并不能得到保证。 -- 如果用户场景中需要快速返回自动提交的读语句,并且可接受弱一致性的读取结果,则可以使用弱一致性读取模式。 +- 此变量用于控制自动提交读取语句的读取一致性。 +- 如果变量值设置为 `weak`,则读取语句遇到的锁将被直接跳过,并且读取执行可能会更快,这是弱一致性读取模式。但是,事务语义(例如原子性)和分布式一致性(例如线性一致性)无法得到保证。 +- 对于自动提交读取需要快速返回且可以接受弱一致性读取结果的用户场景,可以使用弱一致性读取模式。 -### `tidb_read_staleness` 从 v5.4.0 版本开始引入 +### tidb_read_staleness v5.4.0 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` -- 范围 `[-2147483648, 0]` -- 这个变量用于设置当前会话允许读取的历史数据范围。设置后,TiDB 会从参数允许的范围内选出一个尽可能新的时间戳,并影响后继的所有读操作。比如,如果该变量的值设置为 `-5`,TiDB 会在 5 秒时间范围内,保证 TiKV 拥有对应历史版本数据的情况下,选择尽可能新的一个时间戳。 +- 范围:`[-2147483648, 0]` +- 此变量用于设置 TiDB 在当前会话中可以读取的历史数据的时间范围。设置该值后,TiDB 会从该变量允许的范围内选择一个尽可能新的时间戳,并且所有后续的读取操作都将针对该时间戳执行。例如,如果此变量的值设置为 `-5`,在 TiKV 具有相应历史版本数据的前提下,TiDB 将在 5 秒的时间范围内选择一个尽可能新的时间戳。 -### `tidb_record_plan_in_slow_log` +### tidb_record_plan_in_slow_log + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于控制是否在 slow log 里包含慢查询的执行计划。 +- 此变量用于控制是否将慢查询的执行计划包含在慢日志中。 -### `tidb_redact_log` +### tidb_redact_log + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`OFF` -- 可选值:`OFF`、`ON`、`MARKER` -- 这个变量用于控制在记录 TiDB 日志和慢日志时,是否将 SQL 中的用户信息遮蔽。 -- 默认值为 `OFF`,即对用户输入的信息不做任何处理。 -- 将该变量设置为 `ON` 后,用户输入的信息被遮蔽。假设执行的 SQL 为 `INSERT INTO t VALUES (1,2)`,则日志中记录的 SQL 语句为 `INSERT INTO t VALUES (?,?)`。 -- 将该变量设置为 `MARKER` 后,用户输入的信息被标记符号 `‹ ›` 包裹。假设执行的 SQL 为 `INSERT INTO t VALUES (1,2)`,则日志中记录的 SQL 语句为 `INSERT INTO t VALUES (‹1›,‹2›)`。输入信息中的 `‹` 会转义成 `‹‹`,`›` 会转义成 `››`。基于标记后的日志,你可以在展示日志时决定是否对被标记信息进行脱敏处理。 +- 可选值:`OFF`,`ON`,`MARKER` +- 此变量控制是否隐藏记录到 TiDB 日志和慢日志中的 SQL 语句中的用户信息。 +- 默认值为 `OFF`,表示不对用户信息进行任何处理。 +- 当您将变量设置为 `ON` 时,用户信息将被隐藏。例如,如果执行的 SQL 语句是 `INSERT INTO t VALUES (1,2)`,则该语句在日志中记录为 `INSERT INTO t VALUES (?,?)`。 +- 当您将变量设置为 `MARKER` 时,用户信息将用 `‹ ›` 包裹。例如,如果执行的 SQL 语句是 `INSERT INTO t VALUES (1,2)`,则该语句在日志中记录为 `INSERT INTO t VALUES (‹1›,‹2›)`。如果输入包含 `‹`,则转义为 `‹‹`,`›` 转义为 `››`。基于标记的日志,您可以决定在显示日志时是否对标记的信息进行脱敏。 -### `tidb_regard_null_as_point` 从 v5.4.0 版本开始引入 +### tidb_regard_null_as_point v5.4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用来控制优化器是否可以将包含 null 的等值条件作为前缀条件来访问索引。 -- 该变量默认开启。开启后,该变量可以使优化器减少需要访问的索引数据量,从而提高查询的执行速度。例如,在有多列索引 `index(a, b)` 且查询条件为 `a<=>null and b=1` 的情况下,优化器可以同时使用查询条件中的 `a<=>null` 和 `b=1` 进行索引访问。如果关闭该变量,因为 `a<=>null and b=1` 包含 null 的等值条件,优化器不会使用 `b=1` 进行索引访问。 +- 此变量控制优化器是否可以使用包含 null 等价的查询条件作为索引访问的前缀条件。 +- 默认情况下启用此变量。启用后,优化器可以减少要访问的索引数据量,从而加快查询执行速度。例如,如果查询涉及多列索引 `index(a, b)` 并且查询条件包含 `a<=>null and b=1`,则优化器可以使用查询条件中的 `a<=>null` 和 `b=1` 进行索引访问。如果禁用该变量,由于 `a<=>null and b=1` 包含 null 等价条件,优化器将不使用 `b=1` 进行索引访问。 -### `tidb_remove_orderby_in_subquery` 从 v6.1.0 版本开始引入 +### tidb_remove_orderby_in_subquery v6.1.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:在 v7.2.0 之前版本中为 `OFF`,在 v7.2.0 及之后版本中为 `ON`。 -- 指定是否在子查询中移除 `ORDER BY` 子句。 -- 在 ISO/IEC SQL 标准中,`ORDER BY` 主要用于对顶层查询结果进行排序。对于子查询中的 `ORDER BY`,SQL 标准并不要求子查询结果按 `ORDER BY` 排序。 -- 如果需要对子查询结果排序,通常可以在外层查询中处理,例如使用窗口函数或在外层查询中再次使用 `ORDER BY`。这样做可以确保最终结果集的顺序。 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:v7.2.0 之前的默认值为 `OFF`。 从 v7.2.0 开始,默认值为 `ON`。 +- 指定是否删除子查询中的 `ORDER BY` 子句。 +- 在 ISO/IEC SQL 标准中,`ORDER BY` 主要用于对顶级查询的结果进行排序。 对于子查询,该标准不要求结果按 `ORDER BY` 排序。 +- 要对子查询结果进行排序,通常可以在外部查询中处理它,例如使用窗口函数或在外部查询中再次使用 `ORDER BY`。 这样做可以确保最终结果集的顺序。 -### `tidb_replica_read` 从 v4.0 版本开始引入 +### tidb_replica_read v4.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Enumeration - 默认值:`leader` -- 可选值:`leader`、`follower`、`leader-and-follower`、`prefer-leader`、`closest-replicas`、`closest-adaptive` 和 `learner`。其中,`learner` 从 v6.6.0 开始引入。 -- 这个变量用于控制 TiDB 的 Follower Read 功能的行为。 -- 关于使用方式与实现原理,见 [Follower Read](/follower-read.md)。 +- 可选值:`leader`、`follower`、`leader-and-follower`、`prefer-leader`、`closest-replicas`、`closest-adaptive` 和 `learner`。 `learner` 值在 v6.6.0 中引入。 +- 此变量用于控制 TiDB 从哪里读取数据。 +- 有关用法和实现的更多详细信息,请参见 [Follower read](/follower-read.md)。 + +### tidb_restricted_read_only v5.2.0 新增 -### `tidb_request_source_type` 从 v7.4.0 版本开始引入 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + +- 作用域:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:`OFF` +- `tidb_restricted_read_only` 和 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531) 的行为类似。 在大多数情况下,您应该只使用 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531)。 +- 具有 `SUPER` 或 `SYSTEM_VARIABLES_ADMIN` 权限的用户可以修改此变量。 但是,如果启用了 [安全增强模式](#tidb_enable_enhanced_security),则需要额外的 `RESTRICTED_VARIABLES_ADMIN` 权限才能读取或修改此变量。 +- `tidb_restricted_read_only` 在以下情况下会影响 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531): + - 将 `tidb_restricted_read_only` 设置为 `ON` 会将 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531) 更新为 `ON`。 + - 将 `tidb_restricted_read_only` 设置为 `OFF` 不会更改 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531)。 + - 如果 `tidb_restricted_read_only` 为 `ON`,则无法将 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531) 设置为 `OFF`。 +- 对于 TiDB 的 DBaaS 提供商,如果 TiDB 集群是另一个数据库的下游数据库,为了使 TiDB 集群只读,您可能需要启用 [安全增强模式](#tidb_enable_enhanced_security) 来使用 `tidb_restricted_read_only`,这可以防止您的客户使用 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531) 使集群可写。 为此,您需要启用 [安全增强模式](#tidb_enable_enhanced_security),使用具有 `SYSTEM_VARIABLES_ADMIN` 和 `RESTRICTED_VARIABLES_ADMIN` 权限的管理员用户来控制 `tidb_restricted_read_only`,并让您的数据库用户使用具有 `SUPER` 权限的 root 用户来仅控制 [`tidb_super_read_only`](#tidb_super_read_only-new-in-v531)。 +- 此变量控制整个集群的只读状态。 当变量为 `ON` 时,整个集群中的所有 TiDB 服务器都处于只读模式。 在这种情况下,TiDB 仅执行不修改数据的语句,例如 `SELECT`、`USE` 和 `SHOW`。 对于其他语句(例如 `INSERT` 和 `UPDATE`),TiDB 会拒绝在只读模式下执行这些语句。 +- 使用此变量启用只读模式只能确保整个集群最终进入只读状态。 如果您已更改 TiDB 集群中此变量的值,但该更改尚未传播到其他 TiDB 服务器,则未更新的 TiDB 服务器仍然**不**处于只读模式。 +- TiDB 在执行 SQL 语句之前检查只读标志。 从 v6.2.0 开始,在提交 SQL 语句之前也会检查该标志。 这有助于防止长时间运行的 [自动提交](/transaction-overview.md#autocommit) 语句在服务器置于只读模式后可能修改数据的情况。 +- 启用此变量后,TiDB 按以下方式处理未提交的事务: + - 对于未提交的只读事务,您可以正常提交事务。 + - 对于未提交的非只读事务,将拒绝在这些事务中执行写操作的 SQL 语句。 + - 对于具有修改数据的未提交的只读事务,将拒绝提交这些事务。 +- 启用只读模式后,所有用户(包括具有 `SUPER` 权限的用户)都无法执行可能写入数据的 SQL 语句,除非用户被明确授予 `RESTRICTED_REPLICA_WRITER_ADMIN` 权限。 + +### tidb_request_source_type v7.4.0 新增 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:String - 默认值:`""` -- 可选值:`"ddl"`、`"stats"`、`"br"`、`"lightning"`、`"background"` -- 显式指定当前会话的任务类型,用于[资源管控](/tidb-resource-control.md)识别并控制。如 `SET @@tidb_request_source_type = "background"`。 +- 可选值:`"ddl"`, `"stats"`, `"br"`, `"lightning"`, `"background"` +- 此变量用于显式指定当前会话的任务类型,该类型由 [资源控制](/tidb-resource-control.md) 识别和控制。例如:`SET @@tidb_request_source_type = "background"`。 -### `tidb_retry_limit` +### tidb_retry_limit - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`10` - 范围:`[-1, 9223372036854775807]` -- 这个变量用来设置乐观事务的最大重试次数。一个事务执行中遇到可重试的错误(例如事务冲突、事务提交过慢或表结构变更)时,会根据该变量的设置进行重试。注意当 `tidb_retry_limit = 0` 时,也会禁用自动重试。该变量仅适用于乐观事务,不适用于悲观事务。 +- 此变量用于设置乐观事务的最大重试次数。当事务遇到可重试错误(例如事务冲突、事务提交非常慢或表结构更改)时,将根据此变量重新执行该事务。请注意,将 `tidb_retry_limit` 设置为 `0` 会禁用自动重试。此变量仅适用于乐观事务,不适用于悲观事务。 + +### tidb_row_format_version -### `tidb_row_format_version` +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`2` - 范围:`[1, 2]` -- 控制新保存数据的表数据格式版本。TiDB v4.0 中默认使用版本号为 2 的[新表数据格式](https://github.com/pingcap/tidb/blob/release-8.1/docs/design/2018-07-19-row-format.md)保存新数据。 - -- 但如果从 4.0.0 之前的版本升级到 4.0.0,不会改变表数据格式版本,TiDB 会继续使用版本为 1 的旧格式写入表中,即**只有新创建的集群才会默认使用新表数据格式**。 +- 控制表中新保存数据的格式版本。在 TiDB v4.0 中,默认使用 [新的存储行格式](https://github.com/pingcap/tidb/blob/release-8.1/docs/design/2018-07-19-row-format.md) 版本 `2` 来保存新数据。 +- 如果您从低于 v4.0.0 的 TiDB 版本升级到 v4.0.0 或更高版本,则格式版本不会更改,TiDB 将继续使用版本 `1` 的旧格式将数据写入表,这意味着**只有新创建的集群默认使用新的数据格式**。 +- 请注意,修改此变量不会影响已保存的旧数据,而是仅将相应的版本格式应用于修改此变量后新写入的数据。 -- 需要注意的是修改该变量不会对已保存的老数据产生影响,只会对修改变量后的新写入数据使用对应版本格式保存。 - -### `tidb_runtime_filter_mode` 从 v7.2.0 版本开始引入 +### tidb_runtime_filter_mode v7.2.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Enumeration - 默认值:`OFF` -- 可选值:`OFF`,`LOCAL` -- 控制 Runtime Filter 的模式,即**生成 Filter 算子**和**接收 Filter 算子**之间的关系。当前可设置为两种模式:`OFF`、`LOCAL`。`OFF` 代表关闭 Runtime Filter,`LOCAL` 代表开启 `LOCAL` 模式的 Runtime Filter。详细说明见 [Runtime Filter Mode](/runtime-filter.md#runtime-filter-mode)。 +- 可选值:`OFF`, `LOCAL` +- 控制 Runtime Filter 的模式,即 **Filter Sender operator** 和 **Filter Receiver operator** 之间的关系。有两种模式:`OFF` 和 `LOCAL`。`OFF` 表示禁用 Runtime Filter。`LOCAL` 表示在本地模式下启用 Runtime Filter。有关更多信息,请参见 [Runtime Filter 模式](/runtime-filter.md#runtime-filter-mode)。 -### `tidb_runtime_filter_type` 从 v7.2.0 版本开始引入 +### tidb_runtime_filter_type v7.2.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Enumeration - 默认值:`IN` - 可选值:`IN` -- 控制 Runtime Filter 的类型,即生成的 Filter 算子使用的谓词类型。当前仅支持 `IN`,所以无需更改此设置。详细说明见 [Runtime Filter Type](/runtime-filter.md#runtime-filter-type)。 +- 控制生成的 Filter operator 使用的谓词类型。目前,仅支持一种类型:`IN`。有关更多信息,请参见 [Runtime Filter 类型](/runtime-filter.md#runtime-filter-type)。 + +### tidb_scatter_region -### `tidb_scatter_region` +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- TiDB 默认会在建表时为新表分裂 Region。开启该变量后,会在建表语句执行时,同步打散刚分裂出的 Region。适用于批量建表后紧接着批量写入数据,能让刚分裂出的 Region 先在 TiKV 分散而不用等待 PD 进行调度。为了保证后续批量写入数据的稳定性,建表语句会等待打散 Region 完成后再返回建表成功,建表语句执行时间会是该变量关闭时的数倍。 -- 如果建表时设置了 `SHARD_ROW_ID_BITS` 和 `PRE_SPLIT_REGIONS`,建表成功后会均匀切分出指定数量的 Region。 +- 默认情况下,在 TiDB 中创建新表时,会拆分 Region。启用此变量后,新拆分的 Region 会在执行 `CREATE TABLE` 语句期间立即分散。这适用于在批量创建表后需要批量写入数据的场景,因为新拆分的 Region 可以预先分散在 TiKV 中,而不必等待 PD 调度。为了确保批量写入数据的持续稳定性,只有在 Region 成功分散后,`CREATE TABLE` 语句才会返回成功。这使得语句的执行时间比禁用此变量时长数倍。 +- 请注意,如果在创建表时已设置 `SHARD_ROW_ID_BITS` 和 `PRE_SPLIT_REGIONS`,则在创建表后会均匀拆分指定数量的 Region。 -### `tidb_schema_cache_size` 从 v8.0.0 版本开始引入 +### tidb_schema_cache_size v8.0.0 新增 > **警告:** > -> 当前版本中该变量控制的功能尚未生效,请保留默认值。 +> 此变量控制的功能在当前 TiDB 版本中尚未生效。请勿更改默认值。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` - 范围:`[0, 9223372036854775807]` -- 这个变量用来控制 TiDB schema 信息缓存的大小。单位为 byte。默认值为 `0`,表示不打开缓存限制功能。开启该功能后,TiDB 将使用该变量的值做为可用的内存上限,并使用 Least Recently Used (LRU) 算法缓存所需的表,有效降低 schema 信息占用的内存。 +- 此变量控制 TiDB 中 schema 缓存的大小。单位是字节。默认值为 `0`,表示未启用缓存限制功能。启用此功能后,TiDB 使用您设置的值作为最大可用内存限制,并使用最近最少使用 (LRU) 算法来缓存所需的表,从而有效减少 schema 信息占用的内存。 -### `tidb_schema_version_cache_limit` 从 v7.4.0 版本开始引入 +### tidb_schema_version_cache_limit v7.4.0 新增 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`16` -- 取值范围:`[2, 255]` -- 该变量用于限制 TiDB 实例可以缓存多少个历史版本的表结构信息。默认值为 `16`,即默认缓存 16 个历史版本的表结构信息。 -- 一般不需要修改该变量。当使用 [Stale Read](/stale-read.md) 功能且 DDL 执行非常频繁时,会导致表结构信息的版本号变更非常频繁,进而导致 Stale Read 在获取 Snapshot 的表结构信息时,可能会因为未命中表结构信息的缓存而需要消耗大量时间重新构建该信息。此时可以适当调大 `tidb_schema_version_cache_limit` 的值(例如 `32` )来避免表结构信息的缓存不命中的问题。 -- 修改该变量会使 TiDB 的内存占用轻微上升。使用时请注意 TiDB 的内存占用,避免出现 OOM 问题。 +- 范围:`[2, 255]` +- 此变量限制了 TiDB 实例中可以缓存的历史 schema 版本的数量。默认值为 `16`,表示 TiDB 默认缓存 16 个历史 schema 版本。 +- 通常,您不需要修改此变量。当使用 [Stale Read](/stale-read.md) 功能并且频繁执行 DDL 操作时,会导致 schema 版本非常频繁地更改。因此,当 Stale Read 尝试从快照中获取 schema 信息时,由于 schema 缓存未命中,可能需要花费大量时间来重建信息。在这种情况下,您可以增加 `tidb_schema_version_cache_limit` 的值(例如,`32`)以避免 schema 缓存未命中的问题。 +- 修改此变量会导致 TiDB 的内存使用量略有增加。监控 TiDB 的内存使用情况以避免 OOM 问题。 -### `tidb_server_memory_limit` 从 v6.4.0 版本开始引入 +### tidb_server_memory_limit v6.4.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`80%` -- 取值范围: - - 你可以将该变量值设为百分比格式,表示内存用量占总内存的百分比,取值范围为 `[1%, 99%]`。 - - 你还可以将变量值设为内存大小,取值范围为 `0` 以及 `[536870912, 9223372036854775807]`,单位为 Byte。支持带单位的内存格式 "KiB|MiB|GiB|TiB"。`0` 值表示不设内存限制。 - - 当设置的内存值小于 512 MiB 且不为 0 时,TiDB 将会使用 512 MiB 作为替代。 -- 该变量指定 TiDB 实例的内存限制。TiDB 会在内存用量达到该限制时,对当前内存用量最高的 SQL 语句进行取消 (Cancel) 操作。在该 SQL 语句被成功 Cancel 掉后,TiDB 会尝试调用 Golang GC 立刻回收内存,以最快速度缓解内存压力。 -- 只有内存使用大于 `tidb_server_memory_limit_sess_min_size` 的 SQL 语句会被选定为最优先被 Cancel 的 SQL 语句。 -- 目前 TiDB 一次只能 Cancel 一条 SQL 语句。如果 TiDB 完全 Cancel 掉一条 SQL 语句并回收资源后,内存使用仍然大于该变量所设限制,TiDB 会开始下一次 Cancel 操作。 +- 范围: + - 您可以设置百分比格式的值,这意味着内存使用量相对于总内存的百分比。取值范围为 `[1%, 99%]`。 + - 您也可以设置内存大小的值。取值范围为 `0` 和 `[536870912, 9223372036854775807]`(以字节为单位)。支持带有单位 "KiB|MiB|GiB|TiB" 的内存格式。`0` 表示没有内存限制。 + - 如果此变量设置为小于 512 MiB 但不为 `0` 的内存大小,则 TiDB 使用 512 MiB 作为实际大小。 +- 此变量指定 TiDB 实例的内存限制。当 TiDB 的内存使用量达到限制时,TiDB 会取消当前运行的内存使用量最高的 SQL 语句。成功取消 SQL 语句后,TiDB 会尝试调用 Golang GC 以立即回收内存,从而尽快缓解内存压力。 +- 只有内存使用量超过 [`tidb_server_memory_limit_sess_min_size`](/system-variables.md#tidb_server_memory_limit_sess_min_size-new-in-v640) 限制的 SQL 语句才会被优先选择取消。 +- 目前,TiDB 每次只会取消一个 SQL 语句。在 TiDB 完全取消一个 SQL 语句并回收资源后,如果内存使用量仍然大于此变量设置的限制,TiDB 才会开始下一个取消操作。 -### `tidb_server_memory_limit_gc_trigger` 从 v6.4.0 版本开始引入 +### tidb_server_memory_limit_gc_trigger New in v6.4.0 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`70%` -- 取值范围:`[50%, 99%]` -- TiDB 尝试触发 GC 的阈值。当 TiDB 的内存使用达到 `tidb_server_memory_limit` 值 \* `tidb_server_memory_limit_gc_trigger` 值时,则会主动触发一次 Golang GC。在一分钟之内只会主动触发一次 GC。 +- 范围:`[50%, 99%]` +- TiDB 尝试触发 GC 的阈值。当 TiDB 的内存使用量达到 `tidb_server_memory_limit` \* `tidb_server_memory_limit_gc_trigger` 的值时,TiDB 将主动触发 Golang GC 操作。一分钟内只会触发一次 GC 操作。 + +### tidb_server_memory_limit_sess_min_size New in v6.4.0 -### `tidb_server_memory_limit_sess_min_size` 从 v6.4.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`134217728`(即 128 MiB) -- 取值范围:`[128, 9223372036854775807]`,单位为 Byte。支持带单位的内存格式 "KiB|MiB|GiB|TiB"。 -- 开启内存限制后,TiDB 会终止当前实例上内存用量最高的 SQL 语句。本变量指定此情况下 SQL 语句被终止的最小内存用量。如果 TiDB 实例的内存超限是由许多内存使用量不明显的会话导致的,可以适当调小该变量值,使得更多会话成为 Cancel 的对象。 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`134217728` (即 128 MiB) +- 范围:`[128, 9223372036854775807]`,单位为字节。也支持带有单位 "KiB|MiB|GiB|TiB" 的内存格式。 +- 启用内存限制后,TiDB 将终止当前实例上内存使用量最高的 SQL 语句。此变量指定要终止的 SQL 语句的最小内存使用量。如果超过限制的 TiDB 实例的内存使用量是由太多内存使用量低的会话引起的,您可以适当降低此变量的值,以允许取消更多会话。 -### `tidb_service_scope` 从 v7.4.0 版本开始引入 +### tidb_service_scope New in v7.4.0 + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:String - 默认值:"" -- 可选值:长度小于或等于 64 的字符串,可用合法字符包括数字 `0-9`、字母 `a-zA-Z`、下划线 `_` 和连字符 `-` -- 该变量是一个实例级别的变量,用于控制 [TiDB 分布式执行框架](/tidb-distributed-execution-framework.md) 下各 TiDB 节点的服务范围。分布式执行框架会根据该变量的值决定将分布式任务调度到哪些 TiDB 节点上执行,具体规则请参考[任务调度](/tidb-distributed-execution-framework.md#任务调度)。 +- 可选值:长度不超过 64 个字符的字符串。有效字符包括数字 `0-9`、字母 `a-zA-Z`、下划线 `_` 和连字符 `-`。 +- 此变量是一个实例级别的系统变量。您可以使用它来控制 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) 下每个 TiDB 节点的 Service Scope。DXF 根据此变量的值确定可以将哪些 TiDB 节点调度来执行分布式任务。有关具体规则,请参见[任务调度](/tidb-distributed-execution-framework.md#task-scheduling)。 -### `tidb_session_alias` 从 v7.4.0 版本开始引入 +### tidb_session_alias New in v7.4.0 - 作用域:SESSION - 是否持久化到集群:否 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:字符串 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 默认值:"" -- 用来自定义当前会话相关日志中 `session_alias` 列的值,方便故障定位时识别该会话。此设置会对语句执行过程中涉及的多个节点的日志生效(包括 TiKV)。此变量限制长度最大为 64 个字符,超出的部分将会被自动截断。如果变量值的末尾存在空格,也会被自动去除。 +- 您可以使用此变量自定义与当前会话相关的日志中 `session_alias` 列的值,这有助于在问题排查中识别会话。此设置会影响语句执行涉及的多个节点(包括 TiKV)的日志。此变量的最大长度限制为 64 个字符,任何超过长度的字符都将被自动截断。值末尾的空格也会被自动删除。 -### `tidb_session_plan_cache_size` 从 v7.1.0 版本开始引入 +### tidb_session_plan_cache_size New in v7.1.0 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`100` - 范围:`[1, 100000]` -- 这个变量用来控制 Plan Cache 最多能够缓存的计划数量。其中,[Prepare 语句执行计划缓存](/sql-prepared-plan-cache.md)和[非 Prepare 语句执行计划缓存](/sql-non-prepared-plan-cache.md)共用一个缓存。 -- 从旧版本升级到 v7.1.0 及之后的版本,`tidb_session_plan_cache_size` 的值与 [`tidb_prepared_plan_cache_size`](#tidb_prepared_plan_cache_size-从-v610-版本开始引入) 保持一致。 +- 此变量控制可以缓存的最大计划数。[Prepared plan cache](/sql-prepared-plan-cache.md) 和 [non-prepared plan cache](/sql-non-prepared-plan-cache.md) 共享同一个缓存。 +- 当您从早期版本升级到 v7.1.0 或更高版本时,此变量的值与 [`tidb_prepared_plan_cache_size`](#tidb_prepared_plan_cache_size-new-in-v610) 保持相同。 -### `tidb_shard_allocate_step` 从 v5.0 版本开始引入 +### tidb_shard_allocate_step New in v5.0 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`9223372036854775807` - 范围:`[1, 9223372036854775807]` -- 该变量设置为 [`AUTO_RANDOM`](/auto-random.md) 或 [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md) 属性列分配的最大连续 ID 数。通常,`AUTO_RANDOM` ID 或带有 `SHARD_ROW_ID_BITS` 属性的行 ID 在一个事务中是增量和连续的。你可以使用该变量来解决大事务场景下的热点问题。 +- 此变量控制为 [`AUTO_RANDOM`](/auto-random.md) 或 [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md) 属性分配的连续 ID 的最大数量。通常,`AUTO_RANDOM` ID 或 `SHARD_ROW_ID_BITS` 注释的行 ID 在一个事务中是递增且连续的。您可以使用此变量来解决大型事务场景中的热点问题。 + +### tidb_simplified_metrics -### `tidb_simplified_metrics` +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 该变量开启后,TiDB 将不会收集或记录 Grafana 面板未使用到的 metrics。 +- 启用此变量后,TiDB 不会收集或记录 Grafana 面板中未使用的指标。 -### `tidb_skip_ascii_check` 从 v5.0 版本开始引入 +### tidb_skip_ascii_check New in v5.0 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来设置是否校验 ASCII 字符的合法性。 -- 校验 ASCII 字符会损耗些许性能。当你确认输入的字符串为有效的 ASCII 字符时,可以将其设置为 `ON`。 +- 此变量用于设置是否跳过 ASCII 验证。 +- 验证 ASCII 字符会影响性能。当您确定输入字符是有效的 ASCII 字符时,可以将变量值设置为 `ON`。 -### `tidb_skip_isolation_level_check` +### tidb_skip_isolation_level_check - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 开启这个开关之后,如果对 `tx_isolation` 赋值一个 TiDB 不支持的隔离级别,不会报错,有助于兼容其他设置了(但不依赖于)不同隔离级别的应用。 +- 启用此开关后,如果将 TiDB 不支持的隔离级别分配给 `tx_isolation`,则不会报告错误。这有助于提高与设置(但不依赖于)不同隔离级别的应用程序的兼容性。 ```sql tidb> set tx_isolation='serializable'; @@ -4599,846 +5241,1107 @@ tidb> set tx_isolation='serializable'; Query OK, 0 rows affected, 1 warning (0.00 sec) ``` -### `tidb_skip_missing_partition_stats` 从 v7.3.0 版本开始引入 +### tidb_skip_missing_partition_stats New in v7.3.0 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 分区表在开启[动态裁剪模式](/partitioned-table.md#动态裁剪模式)时,TiDB 会汇总各个分区的统计信息生成 GlobalStats。这个变量用于控制当分区统计信息缺失时生成 GlobalStats 的行为。 +- 在[动态分区裁剪模式](/partitioned-table.md#dynamic-pruning-mode)下访问分区表时,TiDB 会聚合每个分区的统计信息以生成 GlobalStats。此变量控制在缺少分区统计信息时 GlobalStats 的生成。 - - 当开启该变量时,TiDB 生成 GlobalStats 时会跳过缺失的分区统计信息,不影响 GlobalStats 生成。 - - 当关闭该变量时,遇到缺失的分区统计信息,TiDB 会停止生成 GlobalStats。 + - 如果此变量为 `ON`,TiDB 在生成 GlobalStats 时会跳过缺少的分区统计信息,因此 GlobalStats 的生成不受影响。 + - 如果此变量为 `OFF`,TiDB 在检测到任何缺少的分区统计信息时会停止生成 GlobalStats。 -### `tidb_skip_utf8_check` +### tidb_skip_utf8_check - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来设置是否校验 UTF-8 字符的合法性。 -- 校验 UTF-8 字符会损耗些许性能。当你确认输入的字符串为有效的 UTF-8 字符时,可以将其设置为 `ON`。 +- 此变量用于设置是否跳过 UTF-8 验证。 +- 验证 UTF-8 字符会影响性能。当您确定输入字符是有效的 UTF-8 字符时,可以将此变量值设置为 `ON`。 > **注意:** > -> 跳过字符检查可能会使 TiDB 检测不到应用写入的非法 UTF-8 字符,进一步导致执行 `ANALYZE` 时解码错误,以及引入其他未知的编码问题。如果应用不能保证写入字符串的合法性,不建议跳过该检查。 +> 如果跳过字符检查,TiDB 可能无法检测到应用程序写入的非法 UTF-8 字符,导致执行 `ANALYZE` 时出现解码错误,并引入其他未知的编码问题。如果您的应用程序无法保证写入字符串的有效性,则不建议跳过字符检查。 + +### tidb_slow_log_threshold -### `tidb_slow_log_threshold` +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 - 作用域:GLOBAL -- 是否持久化到集群:否,仅作用于当前连接的 TiDB 实例 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否持久化到集群:否,仅适用于您当前连接的 TiDB 实例。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`300` -- 类型:整数型 - 范围:`[-1, 9223372036854775807]` - 单位:毫秒 -- 输出慢日志的耗时阈值,默认为 300 ms。如果查询耗时大于这个值,会视作一个慢查询,并记录到慢查询日志。注意,当日志的输出级别 [`log.level`](/tidb-configuration-file.md#level) 是 `"debug"` 时,所有查询都会记录到慢日志,不受该变量的限制。 +- 此变量输出慢日志消耗时间的阈值,默认设置为 300 毫秒。当查询消耗的时间大于此值时,此查询被认为是慢查询,其日志将输出到慢查询日志。请注意,当 [`log.level`](https://docs.pingcap.com/zh/tidb/v8.1/tidb-configuration-file#level) 的输出级别为 `"debug"` 时,所有查询都会记录在慢查询日志中,而与此变量的设置无关。 + +### tidb_slow_query_file + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + +- 作用域:SESSION +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:"" +- 查询 `INFORMATION_SCHEMA.SLOW_QUERY` 时,只会解析配置文件中 `slow-query-file` 设置的慢查询日志名称。默认的慢查询日志名称是 "tidb-slow.log"。要解析其他日志,请将 `tidb_slow_query_file` 会话变量设置为特定的文件路径,然后查询 `INFORMATION_SCHEMA.SLOW_QUERY` 以基于设置的文件路径解析慢查询日志。 + + + +有关详细信息,请参阅[识别慢查询](/identify-slow-queries.md)。 + + + +### tidb_slow_txn_log_threshold v7.0.0 新增 + +- 作用域:SESSION +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Unsigned integer +- 默认值:`0` +- 范围:`[0, 9223372036854775807]` +- 单位:毫秒 +- 此变量设置慢事务日志记录的阈值。当事务的执行时间超过此阈值时,TiDB 会记录有关该事务的详细信息。当该值设置为 `0` 时,此功能将被禁用。 -### `tidb_slow_query_file` +### tidb_snapshot - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 查询 `INFORMATION_SCHEMA.SLOW_QUERY` 只会解析配置文件中 `slow-query-file` 设置的慢日志文件名,默认是 "tidb-slow.log"。但如果想要解析其他的日志文件,可以通过设置 session 变量 `tidb_slow_query_file` 为具体的文件路径,然后查询 `INFORMATION_SCHEMA.SLOW_QUERY` 就会按照设置的路径去解析慢日志文件。更多详情可以参考 [SLOW_QUERY 文档](/identify-slow-queries.md)。 +- 此变量用于设置会话读取数据的时间点。例如,当您将变量设置为 "2017-11-11 20:20:20" 或像 "400036290571534337" 这样的 TSO 编号时,当前会话会读取该时刻的数据。 + +### tidb_source_id v6.5.0 新增 + +- 作用域:GLOBAL +- 是否持久化到集群:是 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`1` +- 范围:`[1, 15]` + + + +- 此变量用于在[双向复制](/ticdc/ticdc-bidirectional-replication.md)集群中配置不同的集群 ID。 -### `tidb_slow_txn_log_threshold` 从 v7.0.0 版本开始引入 + -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:无符号整数型 -- 默认值:`0` -- 范围:`[0, 9223372036854775807]` -- 单位:毫秒 -- 用于设置慢事务日志阈值。当事务执行时间超过该阈值时,TiDB 会在日志中记录该事务的详细信息。设置为 `0` 时,表示关闭该功能。 + -### `tidb_snapshot` +- 此变量用于在[双向复制](https://docs.pingcap.com/zh/tidb/stable/ticdc-bidirectional-replication)集群中配置不同的集群 ID。 -- 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:"" -- 这个变量用来设置当前会话期待读取的历史数据所处时刻。比如当设置为 `"2017-11-11 20:20:20"` 时或者一个 TSO 数字 "400036290571534337",当前会话将能读取到该时刻的数据。 + -### `tidb_source_id` 从 v6.5.0 版本开始引入 +### tidb_stats_cache_mem_quota v6.1.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值: `1` -- 范围:`[1, 15]` -- 这个变量用来设置在[双向复制](/ticdc/ticdc-bidirectional-replication.md)系统内不同集群的 ID。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 单位:Byte +- 默认值:`0`,表示内存配额自动设置为 TiDB 实例总内存大小的一半。 +- 范围:`[0, 1099511627776]` +- 此变量设置 TiDB 统计信息缓存的内存配额。 -### `tidb_stats_cache_mem_quota` 从 v6.1.0 版本开始引入 +### tidb_stats_load_pseudo_timeout v5.4.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 单位:字节 -- 默认值:`0`,表示自动设置统计信息缓存的内存使用上限为总内存的一半。 -- 范围:`[0, 1099511627776]` -- 这个变量用于控制 TiDB 统计信息缓存的内存使用上限。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean +- 默认值:`ON` +- 此变量控制当 SQL 优化等待同步加载完整列统计信息的时间达到超时时,TiDB 的行为。默认值 `ON` 表示 SQL 优化在超时后恢复使用伪统计信息。如果此变量设置为 `OFF`,则 SQL 执行在超时后失败。 + +### tidb_stats_load_sync_wait v5.4.0 新增 -### `tidb_stats_load_sync_wait` 从 v5.4.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/zh/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`100` -- 单位:毫秒 - 范围:`[0, 2147483647]` -- 这个变量用于控制是否开启统计信息的同步加载模式(为 `0` 代表不开启,即为异步加载模式),以及开启的情况下,SQL 执行同步加载完整统计信息等待多久后会超时。更多信息,请参考[统计信息的加载](/statistics.md#加载统计信息)。 +- 单位:毫秒 +- 此变量控制是否启用同步加载统计信息功能。值 `0` 表示该功能已禁用。要启用该功能,您可以将此变量设置为 SQL 优化最多可以等待同步加载完整列统计信息的超时时间(以毫秒为单位)。有关详细信息,请参阅[加载统计信息](/statistics.md#load-statistics)。 -### `tidb_stats_load_pseudo_timeout` 从 v5.4.0 版本开始引入 +### tidb_stmt_summary_enable_persistent v6.6.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON` -- 这个变量用于控制统计信息同步加载超时后,SQL 是执行失败(`OFF`),还是退回使用 pseudo 的统计信息(`ON`)。 + -### `tidb_stmt_summary_enable_persistent` 从 v6.6.0 版本开始引入 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + + > **警告:** > -> statements summary 持久化目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 语句摘要持久化是一项实验性功能。不建议在生产环境中使用它。此功能可能会更改或删除,恕不另行通知。如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 只读变量。表示是否开启 [statement summary tables 持久化](/statement-summary-tables.md#持久化-statements-summary)。该变量的值与配置文件中 [`tidb_stmt_summary_enable_persistent`](/tidb-configuration-file.md#tidb_stmt_summary_enable_persistent-从-v660-版本开始引入) 的取值相同。 +- 此变量是只读的。它控制是否启用[语句摘要持久化](/statement-summary-tables.md#persist-statements-summary)。 + + + +- 此变量的值与配置项 [`tidb_stmt_summary_enable_persistent`](/tidb-configuration-file.md#tidb_stmt_summary_enable_persistent-new-in-v660) 的值相同。 + + + +### tidb_stmt_summary_filename v6.6.0 新增 + + + +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 -### `tidb_stmt_summary_filename` 从 v6.6.0 版本开始引入 + > **警告:** > -> statements summary 持久化目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 语句摘要持久化是一项实验性功能。不建议在生产环境中使用它。此功能可能会更改或删除,恕不另行通知。如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:字符串 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:String - 默认值:`"tidb-statements.log"` -- 只读变量。表示当开启 [statement summary tables 持久化](/statement-summary-tables.md#持久化-statements-summary)后持久化数据所写入的文件。该变量的值与配置文件中 [`tidb_stmt_summary_filename`](/tidb-configuration-file.md#tidb_stmt_summary_filename-从-v660-版本开始引入) 的取值相同。 +- 此变量是只读的。它指定在启用[语句摘要持久化](/statement-summary-tables.md#persist-statements-summary)时,持久数据写入的文件。 -### `tidb_stmt_summary_file_max_backups` 从 v6.6.0 版本开始引入 + -> **警告:** +- 此变量的值与配置项 [`tidb_stmt_summary_filename`](/tidb-configuration-file.md#tidb_stmt_summary_filename-new-in-v660) 的值相同。 + + + +### tidb_stmt_summary_file_max_backups v6.6.0 新增 + + + +> **注意:** > -> statements summary 持久化目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 此 TiDB 变量不适用于 TiDB Cloud。 + + + +> **警告:** + +> 语句摘要持久化是一项实验性功能。不建议在生产环境中使用。此功能可能会更改或删除,恕不另行通知。如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` -- 只读变量。表示当开启 [statement summary tables 持久化](/statement-summary-tables.md#持久化-statements-summary)后持久化数据文件的最大数量限制。该变量的值与配置文件中 [`tidb_stmt_summary_file_max_backups`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_backups-从-v660-版本开始引入) 的取值相同。 +- 此变量为只读。它指定启用[语句摘要持久化](/statement-summary-tables.md#persist-statements-summary)时可以持久化的最大数据文件数。 + + + +- 此变量的值与配置项 [`tidb_stmt_summary_file_max_backups`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_backups-new-in-v660) 的值相同。 + + + +### tidb_stmt_summary_file_max_days v6.6.0 新增 + + -### `tidb_stmt_summary_file_max_days` 从 v6.6.0 版本开始引入 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + + > **警告:** > -> statements summary 持久化目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 语句摘要持久化是一项实验性功能。不建议在生产环境中使用。此功能可能会更改或删除,恕不另行通知。如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`3` - 单位:天 -- 只读变量。表示当开启 [statement summary tables 持久化](/statement-summary-tables.md#持久化-statements-summary)后持久化数据文件所保留的最大天数。该变量的值与配置文件中 [`tidb_stmt_summary_file_max_days`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_days-从-v660-版本开始引入) 的取值相同。 +- 此变量为只读。它指定启用[语句摘要持久化](/statement-summary-tables.md#persist-statements-summary)时,持久数据文件保留的最长天数。 + + + +- 此变量的值与配置项 [`tidb_stmt_summary_file_max_days`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_days-new-in-v660) 的值相同。 + + + +### tidb_stmt_summary_file_max_size v6.6.0 新增 + + -### `tidb_stmt_summary_file_max_size` 从 v6.6.0 版本开始引入 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + + > **警告:** > -> statements summary 持久化目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 语句摘要持久化是一项实验性功能。不建议在生产环境中使用。此功能可能会更改或删除,恕不另行通知。如果您发现错误,可以在 GitHub 上报告 [issue](https://github.com/pingcap/tidb/issues)。 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`64` - 单位:MiB -- 只读变量。表示当开启 [statement summary tables 持久化](/statement-summary-tables.md#持久化-statements-summary)后持久化数据单个文件的大小限制。该变量的值与配置文件中 [`tidb_stmt_summary_file_max_size`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_size-从-v660-版本开始引入) 的取值相同。 +- 此变量为只读。它指定启用[语句摘要持久化](/statement-summary-tables.md#persist-statements-summary)时,持久数据文件的最大大小。 + + -### `tidb_stmt_summary_history_size` 从 v4.0 版本开始引入 +- 此变量的值与配置项 [`tidb_stmt_summary_file_max_size`](/tidb-configuration-file.md#tidb_stmt_summary_file_max_size-new-in-v660) 的值相同。 + + + +### tidb_stmt_summary_history_size v4.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`24` - 范围:`[0, 255]` -- 这个变量设置了 [statement summary tables](/statement-summary-tables.md) 的历史记录容量。 +- 此变量用于设置[语句摘要表](/statement-summary-tables.md)的历史容量。 -### `tidb_stmt_summary_internal_query` 从 v4.0 版本开始引入 +### tidb_stmt_summary_internal_query v4.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`OFF` -- 这个变量用来控制是否在 [statement summary tables](/statement-summary-tables.md) 中包含 TiDB 内部 SQL 的信息。 +- 此变量用于控制是否在[语句摘要表](/statement-summary-tables.md)中包含 TiDB 的 SQL 信息。 + +### tidb_stmt_summary_max_sql_length v4.0 新增 -### `tidb_stmt_summary_max_sql_length` 从 v4.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`4096` - 范围:`[0, 2147483647]` - 单位:字节 -- 这个变量用来控制 [Statement Summary Tables](/statement-summary-tables.md) 和 [TiDB Dashboard](/dashboard/dashboard-intro.md) 中显示的 SQL 字符串长度。 -### `tidb_stmt_summary_max_stmt_count` 从 v4.0 版本开始引入 + + +- 此变量用于控制[语句摘要表](/statement-summary-tables.md)和 [TiDB Dashboard](/dashboard/dashboard-intro.md) 中 SQL 字符串的长度。 + + + + + +- 此变量用于控制[语句摘要表](/statement-summary-tables.md) 中 SQL 字符串的长度。 + + + +### tidb_stmt_summary_max_stmt_count v4.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`3000` - 范围:`[1, 32767]` -- 这个变量用于限制 [`statements_summary`](/statement-summary-tables.md#statements_summary) 和 [`statements_summary_history`](/statement-summary-tables.md#statements_summary_history) 这两张表在内存中可存储的 SQL digest 总数。 +- 此变量用于限制 [`statements_summary`](/statement-summary-tables.md#statements_summary) 和 [`statements_summary_history`](/statement-summary-tables.md#statements_summary_history) 表可以在内存中总共存储的 SQL 摘要的数量。 -> **注意:** + + +> **注意:** > -> 当启用 [`tidb_stmt_summary_enable_persistent`](/statement-summary-tables.md#持久化-statements-summary) 时,`tidb_stmt_summary_max_stmt_count` 仅限制 [`statements_summary`](/statement-summary-tables.md#statements_summary) 表在内存中可存储的 SQL digest 数量。 +> 当启用 [`tidb_stmt_summary_enable_persistent`](/statement-summary-tables.md#persist-statements-summary) 时,`tidb_stmt_summary_max_stmt_count` 仅限制 [`statements_summary`](/statement-summary-tables.md#statements_summary) 表可以在内存中存储的 SQL 摘要的数量。 -### `tidb_stmt_summary_refresh_interval` 从 v4.0 版本开始引入 + + +### tidb_stmt_summary_refresh_interval v4.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1800` - 范围:`[1, 2147483647]` - 单位:秒 -- 这个变量设置了 [statement summary tables](/statement-summary-tables.md) 的刷新时间。 +- 此变量用于设置[语句摘要表](/statement-summary-tables.md)的刷新时间。 -### `tidb_store_batch_size` +### tidb_store_batch_size - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`4` - 范围:`[0, 25000]` -- 设置 `IndexLookUp` 算子回表时多个 Coprocessor Task 的 batch 大小。`0` 代表不使用 batch。当 `IndexLookUp` 算子的回表 Task 数量特别多,出现极长的慢查询时,可以适当调大该参数以加速查询。 +- 此变量用于控制 `IndexLookUp` 算子的 Coprocessor Tasks 的批量大小。 `0` 表示禁用批量处理。当任务数量相对较大且出现慢查询时,您可以增加此变量以优化查询。 + +### tidb_store_limit v3.0.4 和 v4.0 新增 + +- 作用域:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer +- 默认值:`0` +- 范围:`[0, 9223372036854775807]` +- 此变量用于限制 TiDB 可以同时发送到 TiKV 的最大请求数。 0 表示没有限制。 -### `tidb_streamagg_concurrency` +### tidb_streamagg_concurrency - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1` -- 设置 `StreamAgg` 算子执行查询时的并发度。 -- **不推荐设置该变量**,修改该变量值可能会造成数据正确性问题。 +- 此变量设置查询执行时 `StreamAgg` 算子的并发度。 +- **不建议**设置此变量。修改变量值可能会导致数据正确性问题。 + +### tidb_super_read_only v5.3.1 新增 + +- 作用域:GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `OFF` +- `tidb_super_read_only` 旨在作为 MySQL 变量 `super_read_only` 的替代品来实现。但是,由于 TiDB 是一个分布式数据库,`tidb_super_read_only` 不会在执行后立即使数据库变为只读,而是最终变为只读。 +- 具有 `SUPER` 或 `SYSTEM_VARIABLES_ADMIN` 权限的用户可以修改此变量。 +- 此变量控制整个集群的只读状态。当变量为 `ON` 时,整个集群中的所有 TiDB 服务器都处于只读模式。在这种情况下,TiDB 仅执行不修改数据的语句,例如 `SELECT`、`USE` 和 `SHOW`。对于其他语句,例如 `INSERT` 和 `UPDATE`,TiDB 会拒绝在只读模式下执行这些语句。 +- 使用此变量启用只读模式只能确保整个集群最终进入只读状态。如果您已在 TiDB 集群中更改了此变量的值,但该更改尚未传播到其他 TiDB 服务器,则未更新的 TiDB 服务器仍然**不是**处于只读模式。 +- TiDB 在执行 SQL 语句之前检查只读标志。从 v6.2.0 开始,在提交 SQL 语句之前也会检查该标志。这有助于防止长时间运行的 [auto commit](/transaction-overview.md#autocommit) 语句在服务器进入只读模式后修改数据的情况。 +- 启用此变量后,TiDB 通过以下方式处理未提交的事务: + - 对于未提交的只读事务,您可以正常提交事务。 + - 对于未提交的非只读事务,将拒绝在这些事务中执行写操作的 SQL 语句。 + - 对于具有修改数据的未提交只读事务,将拒绝提交这些事务。 +- 启用只读模式后,所有用户(包括具有 `SUPER` 权限的用户)都无法执行可能写入数据的 SQL 语句,除非该用户被明确授予 `RESTRICTED_REPLICA_WRITER_ADMIN` 权限。 +- 当 [`tidb_restricted_read_only`](#tidb_restricted_read_only-new-in-v520) 系统变量设置为 `ON` 时,`tidb_super_read_only` 在某些情况下会受到 [`tidb_restricted_read_only`](#tidb_restricted_read_only-new-in-v520) 的影响。有关详细影响,请参阅 [`tidb_restricted_read_only`](#tidb_restricted_read_only-new-in-v520) 的描述。 + +### tidb_sysdate_is_now v6.0.0 新增 -### `tidb_top_sql_max_meta_count` 从 v6.0.0 版本开始引入 +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `OFF` +- 此变量用于控制 `SYSDATE` 函数是否可以被 `NOW` 函数替换。此配置项与 MySQL 选项 [`sysdate-is-now`](https://dev.mysql.com/doc/refman/8.0/en/server-options.html#option_mysqld_sysdate-is-now) 具有相同的效果。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`5000` -- 范围:`[1, 10000]` -- 这个变量用于控制 [Top SQL](/dashboard/top-sql.md) 每分钟最多收集 SQL 语句类型的数量。 +### tidb_sysproc_scan_concurrency v6.5.0 新增 -### `tidb_top_sql_max_time_series_count` 从 v6.0.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`100` -- 范围:`[1, 5000]` -- 这个变量用于控制 [Top SQL](/dashboard/top-sql.md) 每分钟保留消耗负载最大的前多少条 SQL(即 Top N) 的数据。 +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `1` +- 范围: `[1, 4294967295]`。v7.5.0 及更早版本的最大值为 `256`。 +- 此变量用于设置 TiDB 执行内部 SQL 语句(例如自动更新统计信息)时执行的扫描操作的并发性。 + +### tidb_table_cache_lease v6.0.0 新增 + +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `3` +- 范围: `[1, 10]` +- 单位: 秒 +- 此变量用于控制 [缓存表](/cached-tables.md) 的租约时间,默认值为 `3`。此变量的值会影响对缓存表的修改。对缓存表进行修改后,最长的等待时间可能是 `tidb_table_cache_lease` 秒。如果表是只读的或可以接受较高的写入延迟,则可以增加此变量的值,以增加缓存表的有效时间并减少租约续订的频率。 + +### tidb_tmp_table_max_size v5.3.0 新增 + +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `67108864` +- 范围: `[1048576, 137438953472]` +- 单位: 字节 +- 此变量用于设置单个[临时表](/temporary-tables.md)的最大大小。任何大小大于此变量值的临时表都会导致错误。 + +### tidb_top_sql_max_meta_count v6.0.0 新增 > **注意:** > -> TiDB Dashboard 中的 Top SQL 页面目前只显示消耗负载最多的 5 类 SQL 查询,这与 `tidb_top_sql_max_time_series_count` 的配置无关。 +> 此 TiDB 变量不适用于 TiDB Cloud。 -### `tidb_store_limit` 从 v3.0.4 和 v4.0 版本开始引入 +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `5000` +- 范围: `[1, 10000]` -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`0` -- 范围:`[0, 9223372036854775807]` -- 这个变量用于限制 TiDB 同时向 TiKV 发送的请求的最大数量,0 表示没有限制。 + -### `tidb_super_read_only` 从 v5.3.1 版本开始引入 +- 此变量用于控制 [Top SQL](/dashboard/top-sql.md) 每分钟收集的 SQL 语句类型的最大数量。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值: `OFF`。 -- `tidb_super_read_only` 用于实现对 MySQL 变量 `super_read_only` 的替代。然而,由于 TiDB 是一个分布式数据库,开启 `tidb_super_read_only` 后数据库各个 TiDB 服务器进入只读模式的时刻不是强一致的,而是最终一致的。 -- 拥有 `SUPER` 或 `SYSTEM_VARIABLES_ADMIN` 权限的用户可以修改该变量。 -- 该变量可以控制整个集群的只读状态。开启后(即该值为 `ON`),整个集群中的 TiDB 服务器都将进入只读状态,只有 `SELECT`、`USE`、`SHOW` 等不会修改数据的语句才能被执行,其他如 `INSERT`、`UPDATE` 等语句会被拒绝执行。 -- 该变量开启只读模式只保证整个集群最终进入只读模式,当变量修改状态还没被同步到其他 TiDB 服务器时,尚未同步的 TiDB 仍然停留在非只读模式。 -- 在执行 SQL 语句之前,TiDB 会检查集群的只读标志。从 v6.2.0 起,在提交 SQL 语句之前,TiDB 也会检查该标志,从而防止在服务器被置于只读模式后某些长期运行的 [auto commit](/transaction-overview.md#自动提交) 语句可能修改数据的情况。 -- 在变量开启时,对于尚未提交的事务: - - 如果有尚未提交的只读事务,可正常提交该事务。 - - 如果尚未提交的事务为非只读事务,在事务内执行写入的 SQL 语句会被拒绝。 - - 如果尚未提交的事务已经有数据改动,其提交也会被拒绝。 -- 当集群开启只读模式后,所有用户(包括 `SUPER` 用户)都无法执行可能写入数据的 SQL 语句,除非该用户被显式地授予了 `RESTRICTED_REPLICA_WRITER_ADMIN` 权限。 -- 当系统变量 [`tidb_restricted_read_only`](#tidb_restricted_read_only-从-v520-版本开始引入) 为 `ON` 时,`tidb_super_read_only` 的值会受到 [`tidb_restricted_read_only`](#tidb_restricted_read_only-从-v520-版本开始引入) 的影响。详情请参见[`tidb_restricted_read_only`](#tidb_restricted_read_only-从-v520-版本开始引入) 中的描述。 - -### `tidb_sysdate_is_now` 从 v6.0.0 版本开始引入 + -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`OFF` -- 这个变量用于控制 `SYSDATE` 函数能否替换为 `NOW` 函数,其效果与 MYSQL 中的 [`sysdate-is-now`](https://dev.mysql.com/doc/refman/8.0/en/server-options.html#option_mysqld_sysdate-is-now) 一致。 + -### `tidb_sysproc_scan_concurrency` 从 v6.5.0 版本开始引入 +- 此变量用于控制 [Top SQL](https://docs.pingcap.com/tidb/stable/top-sql) 每分钟收集的 SQL 语句类型的最大数量。 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`1` -- 范围:`[1, 4294967295]`,v7.5.0 及之前版本最大值为 `256`。 -- 这个变量用来设置 TiDB 执行内部 SQL 语句(例如统计信息自动更新)时 scan 操作的并发度。 + -### `tidb_table_cache_lease` 从 v6.0.0 版本开始引入 +### tidb_top_sql_max_time_series_count v6.0.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`3` -- 范围:`[1, 10]` -- 单位:秒 -- 这个变量用来控制[缓存表](/cached-tables.md)的 lease 时间,默认值是 3 秒。该变量值的大小会影响缓存表的修改。在缓存表上执行修改操作后,最长可能出现 `tidb_table_cache_lease` 变量值时长的等待。如果业务表为只读表,或者能接受很高的写入延迟,则可以将该变量值调大,从而增加缓存的有效时间,减少 lease 续租的频率。 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 -### `tidb_tmp_table_max_size` 从 v5.3 版本开始引入 +> **注意:** +> +> 目前,TiDB Dashboard 中的 Top SQL 页面仅显示对负载贡献最大的前 5 种 SQL 查询类型,这与 `tidb_top_sql_max_time_series_count` 的配置无关。 -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 -- 默认值:`67108864` -- 范围:`[1048576, 137438953472]` -- 单位:字节 -- 这个变量用于限制单个[临时表](/temporary-tables.md)的最大大小,临时表超出该大小后报错。 +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Integer +- 默认值: `100` +- 范围: `[1, 5000]` -### `tidb_track_aggregate_memory_usage` + -- 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 -- 默认值:`ON` -- 本变量控制 TiDB 是否跟踪聚合函数的内存使用情况。 +- 此变量用于控制 [Top SQL](/dashboard/top-sql.md) 每分钟可以记录的对负载贡献最大的 SQL 语句的数量(即前 N 个)。 + + + + + +- 此变量用于控制 [Top SQL](https://docs.pingcap.com/tidb/stable/top-sql) 每分钟可以记录的对负载贡献最大的 SQL 语句的数量(即前 N 个)。 + + + +### tidb_track_aggregate_memory_usage + +- 作用域: SESSION | GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Boolean +- 默认值: `ON` +- 此变量控制 TiDB 是否跟踪聚合函数的内存使用情况。 > **警告:** > -> 如果禁用该变量,TiDB 可能无法准确跟踪内存使用情况,并且无法控制对应 SQL 语句的内存使用。 +> 如果禁用此变量,TiDB 可能无法准确跟踪内存使用情况,并且无法控制相应 SQL 语句的内存使用情况。 -### `tidb_tso_client_batch_max_wait_time` 从 v5.3.0 版本开始引入 +### tidb_tso_client_batch_max_wait_time v5.3.0 新增 -- 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:浮点数 -- 默认值:`0` -- 范围:`[0, 10]` -- 单位:毫秒 -- 这个变量用来设置 TiDB 向 PD 请求 TSO 时进行一次攒批操作的最大等待时长。默认值为 `0`,即不进行额外的等待。 -- 在向 PD 获取 TSO 请求时,TiDB 使用的 PD Client 会一次尽可能多地收集同一时刻的 TSO 请求,将其攒批合并成一个 RPC 请求后再发送给 PD,从而减轻 PD 的压力。 -- 将这个变量值设置为非 0 后,TiDB 会在每一次攒批结束前进行一个最大时长为其值的等待,目的是为了收集到更多的 TSO 请求,从而提高攒批效果。 -- 适合调高这个变量值的场景: - * PD leader 因高压力的 TSO 请求而达到 CPU 瓶颈,导致 TSO RPC 请求的延迟较高。 - * 集群中 TiDB 实例的数量不多,但每一台 TiDB 实例上的并发量较高。 -- 在实际使用中,推荐将该变量尽可能设置为一个较小的值。 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 + +- 作用域: GLOBAL +- 持久化到集群: 是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): 否 +- 类型: Float +- 默认值: `0` +- 范围: `[0, 10]` +- 单位: 毫秒 +- 此变量用于设置 TiDB 从 PD 请求 TSO 时,批量操作的最大等待时间。默认值为 `0`,表示没有额外的等待时间。 +- 每次从 PD 获取 TSO 请求时,TiDB 使用的 PD Client 会尽可能多地收集同时收到的 TSO 请求。然后,PD Client 将收集到的请求批量合并为一个 RPC 请求,并将其发送到 PD。这有助于减轻 PD 的压力。 +- 将此变量设置为大于 `0` 的值后,TiDB 会在每次批量合并结束前等待此值的最大持续时间。这是为了收集更多的 TSO 请求并提高批量操作的效果。 +- 增加此变量值的场景: + * 由于 TSO 请求的压力过大,PD leader 的 CPU 达到瓶颈,导致 TSO RPC 请求的延迟较高。 + * 集群中的 TiDB 实例不多,但每个 TiDB 实例都处于高并发状态。 +- 建议将此变量设置为尽可能小的值。 > **注意:** > -> 如果 PD leader 的 TSO RPC 延迟升高,但其现象并非由 CPU 使用率达到瓶颈而导致(可能存在网络等问题),此时,调高 `tidb_tso_client_batch_max_wait_time` 可能会导致 TiDB 的语句执行延迟上升,影响集群的 QPS 表现。 +> 假设 TSO RPC 延迟增加的原因不是 PD leader 的 CPU 使用率瓶颈(例如网络问题)。在这种情况下,增加 `tidb_tso_client_batch_max_wait_time` 的值可能会增加 TiDB 中的执行延迟,并影响集群的 QPS 性能。 + +### tidb_ttl_delete_rate_limit v6.5.0 新增 -### `tidb_ttl_delete_rate_limit` 从 v6.5.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`0` - 范围:`[0, 9223372036854775807]` -- 这个变量用来对每个 TiDB 节点的 TTL 删除操作进行限流。其值代表了在 TTL 任务中单个节点每秒允许 `DELETE` 语句执行的最大次数。当此变量设置为 `0` 时,则表示不做限制。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 此变量用于限制每个 TiDB 节点上 TTL 作业中 `DELETE` 语句的速率。该值表示 TTL 作业中单个节点每秒允许的最大 `DELETE` 语句数。当此变量设置为 `0` 时,不应用任何限制。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 + +### tidb_ttl_delete_batch_size v6.5.0 新增 -### `tidb_ttl_delete_batch_size` 从 v6.5.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`100` - 范围:`[1, 10240]` -- 这个变量用于设置 TTL 任务中单个删除事务中允许删除的最大行数。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 此变量用于设置 TTL 作业中单个 `DELETE` 事务中可以删除的最大行数。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 + +### tidb_ttl_delete_worker_count v6.5.0 新增 -### `tidb_ttl_delete_worker_count` 从 v6.5.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`4` - 范围:`[1, 256]` -- 这个变量用于设置每个 TiDB 节点上 TTL 删除任务的最大并发数。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 此变量用于设置每个 TiDB 节点上 TTL 作业的最大并发数。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 + +### tidb_ttl_job_enable v6.5.0 新增 -### `tidb_ttl_job_enable` 从 v6.5.0 版本开始引入 +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`ON` -- 类型:布尔型 -- 这个变量用于控制是否启动 TTL 后台清理任务。如果设置为 `OFF`,所有具有 TTL 属性的表会自动停止对过期数据的清理。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 类型:Boolean +- 此变量用于控制是否启用 TTL 作业。如果设置为 `OFF`,则所有具有 TTL 属性的表都会自动停止清理过期数据。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 -### `tidb_ttl_scan_batch_size` 从 v6.5.0 版本开始引入 +### tidb_ttl_scan_batch_size v6.5.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`500` - 范围:`[1, 10240]` -- 这个变量用于设置 TTL 任务中用来扫描过期数据的每个 `SELECT` 语句的 `LIMIT` 的值。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 此变量用于设置 TTL 作业中用于扫描过期数据的每个 `SELECT` 语句的 `LIMIT` 值。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 -### `tidb_ttl_scan_worker_count` 从 v6.5.0 版本开始引入 +### tidb_ttl_scan_worker_count v6.5.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`4` - 范围:`[1, 256]` -- 这个变量用于设置每个 TiDB 节点 TTL 扫描任务的最大并发数。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 此变量用于设置每个 TiDB 节点上 TTL 扫描作业的最大并发数。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 -### `tidb_ttl_job_schedule_window_start_time` 从 v6.5.0 版本开始引入 +### tidb_ttl_job_schedule_window_start_time v6.5.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:时间 -- 是否持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Time +- 持久化到集群:是 - 默认值:`00:00 +0000` -- 这个变量用于控制 TTL 后台清理任务的调度窗口的起始时间。请谨慎调整此参数,过小的窗口有可能会造成过期数据的清理无法完成。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 此变量用于控制后台 TTL 作业的调度窗口的开始时间。修改此变量的值时,请注意,较小的窗口可能会导致过期数据清理失败。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 -### `tidb_ttl_job_schedule_window_end_time` 从 v6.5.0 版本开始引入 +### tidb_ttl_job_schedule_window_end_time v6.5.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:时间 -- 是否持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Time +- 持久化到集群:是 - 默认值:`23:59 +0000` -- 这个变量用于控制 TTL 后台清理任务的调度窗口的结束时间。请谨慎调整此参数,过小的窗口有可能会造成过期数据的清理无法完成。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 此变量用于控制后台 TTL 作业的调度窗口的结束时间。修改此变量的值时,请注意,较小的窗口可能会导致过期数据清理失败。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 -### `tidb_ttl_running_tasks` 从 v7.0.0 版本开始引入 +### tidb_ttl_running_tasks v7.0.0 新增 + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`-1` -- 范围:`-1` 或 `[1, 256]` -- 这个变量用于限制整个集群内 TTL 任务的并发量。`-1` 表示与 TiKV 节点的数量相同。更多信息,请参考 [Time to Live](/time-to-live.md)。 +- 范围:`-1` 和 `[1, 256]` +- 指定整个集群中正在运行的 TTL 任务的最大数量。 `-1` 表示 TTL 任务的数量等于 TiKV 节点的数量。有关更多信息,请参阅 [Time to Live](/time-to-live.md)。 -### `tidb_txn_assertion_level` 从 v6.0.0 版本开始引入 +### tidb_txn_assertion_level v6.0.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`FAST` -- 可选值:`OFF`,`FAST`,`STRICT` -- 这个变量用于设置 assertion 级别。assertion 是一项在事务提交过程中进行的数据索引一致性校验,它对正在写入的 key 是否存在进行检查。如果不符则说明数据索引不一致,会导致事务 abort。详见[数据索引一致性报错](/troubleshoot-data-inconsistency-errors.md)。 -- 对于新创建的 v6.0.0 及以上的集群,默认值为 `FAST`。对于升级版本的集群,如果升级前是低于 v6.0.0 的版本,升级后默认值为 `OFF`。 +- 可能的值:`OFF`、`FAST`、`STRICT` +- 此变量用于控制断言级别。断言是数据和索引之间的一致性检查,用于检查正在写入的键在事务提交过程中是否存在。有关更多信息,请参阅 [解决数据和索引不一致问题](/troubleshoot-data-inconsistency-errors.md)。 + + - `OFF`:禁用此检查。 + - `FAST`:启用大多数检查项,几乎不影响性能。 + - `STRICT`:启用所有检查项,当系统工作负载较高时,对悲观事务性能有轻微影响。 - - `OFF`: 关闭该检查。 - - `FAST`: 开启大多数检查项,对性能几乎无影响。 - - `STRICT`: 开启全部检查项,当系统负载较高时,对悲观事务的性能有较小影响。 +- 对于 v6.0.0 或更高版本的新集群,默认值为 `FAST`。对于从低于 v6.0.0 的版本升级的现有集群,默认值为 `OFF`。 -### `tidb_txn_commit_batch_size` 从 v6.2.0 版本开始引入 +### tidb_txn_commit_batch_size v6.2.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`16384` - 范围:`[1, 1073741824]` - 单位:字节 -- 这个变量用于控制 TiDB 向 TiKV 发送的事务提交请求的批量大小。如果业务负载的大部分事务都有大量的写操作,适当调大该变量可以提高批处理的效果。但需要注意的是,设置过大将会超过 TiKV 的 [`raft-entry-max-size`](/tikv-configuration-file.md#raft-entry-max-size) 限制,导致提交失败。 -### `tidb_txn_entry_size_limit` 从 v7.6.0 版本开始引入 + -- 作用域:GLOBAL | SESSION +- 此变量用于控制 TiDB 发送到 TiKV 的事务提交请求的批量大小。如果应用程序工作负载中的大多数事务都有大量的写入操作,则将此变量调整为更大的值可以提高批量处理的性能。但是,如果此变量设置得太大并超过 TiKV 的 [`raft-entry-max-size`](/tikv-configuration-file.md#raft-entry-max-size) 限制,则提交可能会失败。 + + + + + +- 此变量用于控制 TiDB 发送到 TiKV 的事务提交请求的批量大小。如果应用程序工作负载中的大多数事务都有大量的写入操作,则将此变量调整为更大的值可以提高批量处理的性能。但是,如果此变量设置得太大并超过 TiKV 的单个日志的最大大小限制(默认为 8 MiB),则提交可能会失败。 + + + +### tidb_txn_entry_size_limit v7.6.0 新增 + +- 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`0` - 范围:`[0, 125829120]` - 单位:字节 -- 这个变量用于动态修改 TiDB 配置项 [`performance.txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v4010-和-v500-版本开始引入),其含义与对应配置项相同,即用于限制 TiDB 单行数据的大小。该变量默认值为 `0`,表示默认使用配置项的值。当设置为非 `0` 值时,优先使用该变量的值作为 `txn-entry-size-limit` 的值。 + + + +- 此变量用于动态修改 TiDB 配置项 [`performance.txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-new-in-v4010-and-v500)。它限制 TiDB 中单行数据的大小,与配置项等效。此变量的默认值为 `0`,表示 TiDB 默认使用配置项 `txn-entry-size-limit` 的值。当此变量设置为非零值时,`txn-entry-size-limit` 也会设置为相同的值。 + + + + + +- 此变量用于动态修改 TiDB 配置项 [`performance.txn-entry-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-entry-size-limit-new-in-v4010-and-v500)。它限制 TiDB 中单行数据的大小,与配置项等效。此变量的默认值为 `0`,表示 TiDB 默认使用配置项 `txn-entry-size-limit` 的值。当此变量设置为非零值时,`txn-entry-size-limit` 也会设置为相同的值。 + + > **注意:** > -> 使用 SESSION 作用域修改该变量时仅影响当前用户会话,不会影响 TiDB 的内部会话。这可能导致 TiDB 内部事务的单行数据大小超过配置项的限制,从而导致事务失败。如需在线调高限制,建议优先使用 GLOBAL 作用域修改该变量。 +> 使用 SESSION 作用域修改此变量只会影响当前用户会话,而不会影响 TiDB 内部会话。如果 TiDB 内部事务的条目大小超过配置项的限制,则可能会导致事务失败。因此,要动态增加限制,建议使用 GLOBAL 作用域修改变量。 -### `tidb_txn_mode` +### tidb_txn_mode + +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless),此变量为只读。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:枚举 - 默认值:`pessimistic` - 可选值:`pessimistic`,`optimistic` -- 这个变量用于设置事务模式。TiDB v3.0 支持了悲观事务,自 v3.0.8 开始,默认使用[悲观事务模式](/pessimistic-transaction.md)。 -- 但如果从 3.0.7 及之前的版本升级到 >= 3.0.8 的版本,不会改变默认事务模式,即**只有新创建的集群才会默认使用悲观事务模式**。 -- 将该变量设置为 "optimistic" 或 "" 时,将会使用[乐观事务模式](/optimistic-transaction.md)。 +- 此变量用于设置事务模式。TiDB 3.0 支持悲观事务。自 TiDB 3.0.8 起,默认启用[悲观事务模式](/pessimistic-transaction.md)。 +- 如果您将 TiDB 从 v3.0.7 或更早版本升级到 v3.0.8 或更高版本,则默认事务模式不会更改。**只有新创建的集群默认使用悲观事务模式**。 +- 如果此变量设置为 "optimistic" 或 "",则 TiDB 使用[乐观事务模式](/optimistic-transaction.md)。 -### `tidb_use_plan_baselines` 从 v4.0 版本开始引入 +### tidb_use_plan_baselines v4.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔 - 默认值:`ON` -- 这个变量用于控制是否开启执行计划绑定功能,默认打开,可通过赋值 `OFF` 来关闭。关于执行计划绑定功能的使用可以参考[执行计划绑定文档](/sql-plan-management.md#创建绑定)。 +- 此变量用于控制是否启用执行计划绑定功能。默认情况下启用,可以通过分配 `OFF` 值来禁用。有关执行计划绑定的使用,请参见[执行计划绑定](/sql-plan-management.md#create-a-binding)。 -### `tidb_wait_split_region_finish` +### tidb_wait_split_region_finish + +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless),此变量为只读。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:布尔 - 默认值:`ON` -- 由于打散 Region 的时间可能比较长,主要由 PD 调度以及 TiKV 的负载情况所决定。这个变量用来设置在执行 `SPLIT REGION` 语句时,是否同步等待所有 Region 都打散完成后再返回结果给客户端。 - - 默认 `ON` 代表等待打散完成后再返回结果 - - `OFF` 代表不等待 Region 打散完成就返回。 -- 需要注意的是,在 Region 打散期间,对正在打散 Region 上的写入和读取的性能会有一定影响,对于批量写入、导数据等场景,还是建议等待 Region 打散完成后再开始导数据。 +- 通常,分散 Region 需要很长时间,这取决于 PD 调度和 TiKV 负载。此变量用于设置在执行 `SPLIT REGION` 语句时,是否在所有 Region 完全分散后将结果返回给客户端: + - `ON` 要求 `SPLIT REGIONS` 语句等待直到所有 Region 都被分散。 + - `OFF` 允许 `SPLIT REGIONS` 语句在完成分散所有 Region 之前返回。 +- 请注意,在分散 Region 时,正在分散的 Region 的写入和读取性能可能会受到影响。在批量写入或数据导入场景中,建议在 Region 分散完成后导入数据。 -### `tidb_wait_split_region_timeout` +### tidb_wait_split_region_timeout + +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless),此变量为只读。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`300` - 范围:`[1, 2147483647]` - 单位:秒 -- 这个变量用来设置 `SPLIT REGION` 语句的执行超时时间,默认值是 300 秒,如果超时还未完成,就返回一个超时错误。 +- 此变量用于设置执行 `SPLIT REGION` 语句的超时时间。如果语句在指定的时间值内未完全执行,则返回超时错误。 -### `tidb_window_concurrency` 从 v4.0 版本开始引入 +### tidb_window_concurrency v4.0 新增 > **警告:** > -> 从 v5.0 版本开始,该变量被废弃。请使用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-从-v50-版本开始引入) 进行设置。 +> 自 v5.0 起,此变量已弃用。请改用 [`tidb_executor_concurrency`](#tidb_executor_concurrency-new-in-v50) 进行设置。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:整数 - 默认值:`-1` - 范围:`[1, 256]` - 单位:线程 -- 这个变量用于设置 window 算子的并行度。 -- 默认值 `-1` 表示使用 `tidb_executor_concurrency` 的值。 +- 此变量用于设置窗口算子的并发度。 +- 值为 `-1` 表示将使用 `tidb_executor_concurrency` 的值。 -### `tiflash_fastscan` 从 v6.3.0 版本开始引入 +### tiflash_fastscan v6.3.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 默认值:`OFF` -- 类型:布尔型 -- 如果开启 [FastScan 功能](/tiflash/use-fastscan.md)(设置为 `ON` 时),TiFlash 可以提供更高效的查询性能,但不保证查询结果的精度和数据一致性。 +- 类型:布尔 +- 如果启用 [FastScan](/tiflash/use-fastscan.md)(设置为 `ON`),TiFlash 提供更高效的查询性能,但不保证查询结果的准确性或数据一致性。 -### `tiflash_fine_grained_shuffle_batch_size` 从 v6.2.0 版本开始引入 +### tiflash_fine_grained_shuffle_batch_size v6.2.0 新增 - 作用域:SESSION | GLOBAL -- 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 - 默认值:`8192` - 范围:`[1, 18446744073709551615]` -- 细粒度 shuffle 功能开启时,下推到 TiFlash 的窗口函数可以并行执行。该变量控制发送端发送数据的攒批大小。 -- 对性能影响:如果该值设置过小,例如极端值 1,会导致每个 Block 都进行一次网络传输。如果设置过大,例如极端值整个表的行数,会导致接收端大部分时间都在等待数据,无法流水线计算。可以观察 TiFlash 接收端收到的行数分布情况,如果大部分线程接收的行数很少,例如只有几百行,可以增加该值以达到减少网络开销的目的。 +- 启用 Fine Grained Shuffle 后,下推到 TiFlash 的窗口函数可以并行执行。此变量控制发送方发送的数据的批量大小。 +- 性能影响:根据您的业务需求设置合理的大小。不正确的设置会影响性能。如果该值设置得太小,例如 `1`,会导致每个 Block 进行一次网络传输。如果该值设置得太大,例如表的总行数,会导致接收端花费大部分时间等待数据,流水线计算无法工作。要设置合适的值,您可以观察 TiFlash 接收器接收到的行数分布。如果大多数线程只接收到少量行,例如几百行,您可以增加此值以减少网络开销。 -### `tiflash_fine_grained_shuffle_stream_count` 从 v6.2.0 版本开始引入 +### tiflash_fine_grained_shuffle_stream_count v6.2.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:是 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer - 默认值:`0` - 范围:`[-1, 1024]` -- 当窗口函数下推到 TiFlash 执行时,可以通过该变量控制窗口函数执行的并行度。不同取值含义: +- 当窗口函数下推到 TiFlash 执行时,可以使用此变量来控制窗口函数执行的并发级别。可能的值如下: - * -1: 表示不使用细粒度 shuffle 功能,下推到 TiFlash 的窗口函数以单线程方式执行 - * 0: 表示使用细粒度 shuffle 功能。如果 [`tidb_max_tiflash_threads`](/system-variables.md#tidb_max_tiflash_threads-从-v610-版本开始引入) 有效(大于 0),则 `tiflash_fine_grained_shuffle_stream_count` 会自动取值为 [`tidb_max_tiflash_threads`](/system-variables.md#tidb_max_tiflash_threads-从-v610-版本开始引入),否则会根据 TiFlash 计算节点的 CPU 资源自动推算。最终在 TiFlash 上窗口函数的实际并发度为:min(`tiflash_fine_grained_shuffle_stream_count`,TiFlash 节点物理线程数) - * 大于 0: 表示使用细粒度 shuffle 功能,下推到 TiFlash 的窗口函数会以多线程方式执行,并发度为: min(`tiflash_fine_grained_shuffle_stream_count`, TiFlash 节点物理线程数) -- 理论上窗口函数的性能会随着该值的增加线性提升。但是如果设置的值超过实际的物理线程数,反而会导致性能下降。 + * -1:禁用 Fine Grained Shuffle 功能。下推到 TiFlash 的窗口函数在单线程中执行。 + * 0:启用 Fine Grained Shuffle 功能。如果 [`tidb_max_tiflash_threads`](/system-variables.md#tidb_max_tiflash_threads-new-in-v610) 设置为有效值(大于 0),则 `tiflash_fine_grained_shuffle_stream_count` 设置为 [`tidb_max_tiflash_threads`](/system-variables.md#tidb_max_tiflash_threads-new-in-v610) 的值。否则,它会根据 TiFlash 计算节点的 CPU 资源自动估算。TiFlash 上窗口函数的实际并发级别为:min(`tiflash_fine_grained_shuffle_stream_count`,TiFlash 节点上的物理线程数)。 + * 大于 0 的整数:启用 Fine Grained Shuffle 功能。下推到 TiFlash 的窗口函数在多个线程中执行。并发级别为:min(`tiflash_fine_grained_shuffle_stream_count`,TiFlash 节点上的物理线程数)。 +- 理论上,窗口函数的性能会随着此值的增加而线性增长。但是,如果该值超过实际的物理线程数,反而会导致性能下降。 -### `tiflash_mem_quota_query_per_node` 从 v7.4.0 版本开始引入 +### tiflash_mem_quota_query_per_node v7.4.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` - 范围:`[-1, 9223372036854775807]` -- 用于设置单个查询在单个 TiFlash 节点上的内存使用上限,超过该限制时 TiFlash 会报错并终止该查询。`-1` 或者 `0` 表示无限制。当该变量的值大于 `0` 且 [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-从-v740-版本开始引入) 也设置为有效值时,TiFlash 将启用[查询级别的落盘机制](/tiflash/tiflash-spill-disk.md#查询级别的落盘)。 +- 此变量限制了 TiFlash 节点上查询的最大内存使用量。当查询的内存使用量超过此限制时,TiFlash 会返回错误并终止查询。将此变量设置为 `-1` 或 `0` 表示没有限制。当此变量设置为大于 `0` 的值,并且 [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-new-in-v740) 设置为有效值时,TiFlash 会启用 [查询级别的溢写](/tiflash/tiflash-spill-disk.md#query-level-spilling)。 -### `tiflash_query_spill_ratio` 从 v7.4.0 版本开始引入 +### tiflash_query_spill_ratio v7.4.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:浮点数 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Float - 默认值:`0.7` - 范围:`[0, 0.85]` -- 用于控制 TiFlash [查询级别的落盘](/tiflash/tiflash-spill-disk.md#查询级别的落盘)机制的阈值:`0` 表示关闭查询级别的自动落盘机制;大于 `0` 时,如果查询使用的内存超过 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-从-v740-版本开始引入) * `tiflash_query_spill_ratio`,TiFlash 会触发查询级别的落盘,即将查询中支持落盘的算子的数据按需进行落盘。 +- 此变量控制 TiFlash [查询级别溢写](/tiflash/tiflash-spill-disk.md#query-level-spilling) 的阈值。`0` 表示禁用自动查询级别溢写。当此变量大于 `0` 且查询的内存使用量超过 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-new-in-v740) * `tiflash_query_spill_ratio` 时,TiFlash 会触发查询级别的溢写,根据需要溢写查询中支持的算子的数据。 > **注意:** > -> - 该变量只在 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-从-v740-版本开始引入) 大于 `0` 时生效,即如果 [tiflash_mem_quota_query_per_node](/system-variables.md#tiflash_mem_quota_query_per_node-从-v740-版本开始引入) 为 `0` 或 `-1`,即使 `tiflash_query_spill_ratio` 大于 `0` 也不会启用查询级别的落盘机制。 -> - 当 TiFlash 查询级别的落盘机制开启时,TiFlash 单个算子的落盘阈值会自动失效,即如果 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-从-v740-版本开始引入) 和 `tiflash_query_spill_ratio` 均大于 0, [tidb_max_bytes_before_tiflash_external_sort](/system-variables.md#tidb_max_bytes_before_tiflash_external_sort-从-v700-版本开始引入)、[tidb_max_bytes_before_tiflash_external_group_by](/system-variables.md#tidb_max_bytes_before_tiflash_external_group_by-从-v700-版本开始引入)、[tidb_max_bytes_before_tiflash_external_join](/system-variables.md#tidb_max_bytes_before_tiflash_external_join-从-v700-版本开始引入) 这三个变量会自动失效,等效于被设置为 `0`。 +> - 此变量仅在 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-new-in-v740) 大于 `0` 时生效。换句话说,如果 [tiflash_mem_quota_query_per_node](/system-variables.md#tiflash_mem_quota_query_per_node-new-in-v740) 为 `0` 或 `-1`,即使 `tiflash_query_spill_ratio` 大于 `0`,也不会启用查询级别的溢写。 +> - 启用 TiFlash 查询级别溢写后,各个 TiFlash 算子的溢写阈值会自动失效。换句话说,如果 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-new-in-v740) 和 `tiflash_query_spill_ratio` 都大于 0,则三个变量 [tidb_max_bytes_before_tiflash_external_sort](/system-variables.md#tidb_max_bytes_before_tiflash_external_sort-new-in-v700)、[tidb_max_bytes_before_tiflash_external_group_by](/system-variables.md#tidb_max_bytes_before_tiflash_external_group_by-new-in-v700) 和 [tidb_max_bytes_before_tiflash_external_join](/system-variables.md#tidb_max_bytes_before_tiflash_external_join-new-in-v700) 会自动失效,相当于将它们设置为 `0`。 -### `tiflash_replica_read` 从 v7.3.0 版本开始引入 +### tiflash_replica_read v7.3.0 新增 -- 作用范围:SESSION | GLOBAL -- 持久化至集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +> **注意:** +> +> 此 TiDB 变量不适用于 TiDB Cloud。 + +- 作用域:SESSION | GLOBAL +- 是否持久化到集群:是 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`all_replicas` -- 可选值:`all_replicas`、`closest_adaptive`、`closest_replicas` -- 该变量用于设置当查询需要使用 TiFlash 引擎时,TiFlash 副本的选择策略。 - - `all_replicas` 表示使用所有的 TiFlash 副本进行分析计算。 - - `closest_adaptive` 表示尽量使用与当前发起查询请求的 TiDB 节点相同区域的 TiFlash 副本进行分析计算。如果此区域的 TiFlash 副本未包含查询所需的全部数据,则再使用其他区域的 TiFlash 副本及对应的 TiFlash 节点。 - - `closest_replicas` 表示仅使用与发起当前查询请求的 TiDB 节点相同区域的 TiFlash 副本进行分析计算。如果此区域的 TiFlash 副本未包含查询所需的全部数据,则查询将报错。 +- 可选值:`all_replicas`、`closest_adaptive` 或 `closest_replicas` +- 此变量用于设置查询需要 TiFlash 引擎时选择 TiFlash 副本的策略。 + - `all_replicas` 表示使用所有可用的 TiFlash 副本进行分析计算。 + - `closest_adaptive` 表示优先使用与发起查询的 TiDB 节点位于同一区域的 TiFlash 副本。如果此区域中的副本不包含所有必需的数据,则查询将涉及来自其他区域的 TiFlash 副本及其相应的 TiFlash 节点。 + - `closest_replicas` 表示仅使用与发起查询的 TiDB 节点位于同一区域的 TiFlash 副本。如果此区域中的副本不包含所有必需的数据,则查询将返回错误。 + + > **注意:** > -> - 如果 TiDB 节点未设置[区域属性](/schedule-replicas-by-topology-labels.md#设置-tidb-的-labels可选),并且 TiFlash 副本选择策略不是 `all_replicas` 时,TiFlash 引擎将忽略 TiFlash 副本选择策略,使用所有 TiFlash 副本进行 TiFlash 查询,并且返回警告 `The variable tiflash_replica_read is ignored`。 -> - 如果 TiFlash 节点未设置[区域属性](/schedule-replicas-by-topology-labels.md#设置-tikv-和-tiflash-的-labels),则将其视为不属于任何区域的节点。 +> - 如果 TiDB 节点未配置 [区域属性](/schedule-replicas-by-topology-labels.md#optional-configure-labels-for-tidb) 且 `tiflash_replica_read` 未设置为 `all_replicas`,则 TiFlash 将忽略副本选择策略。相反,它将使用所有 TiFlash 副本进行查询并返回 `The variable tiflash_replica_read is ignored.` 警告。 +> - 如果 TiFlash 节点未配置 [区域属性](/schedule-replicas-by-topology-labels.md#configure-labels-for-tikv-and-tiflash),则它们被视为不属于任何区域的节点。 -### `tikv_client_read_timeout` 从 v7.4.0 版本开始引入 + + +### tikv_client_read_timeout v7.4.0 新增 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`0` - 范围:`[0, 2147483647]` - 单位:毫秒 -- 该变量用于设置查询语句中 TiDB 发送 TiKV RPC 读请求的超时时间。当 TiDB 集群在网络不稳定或 TiKV 的 I/O 延迟抖动严重的环境下,且用户对查询 SQL 的延迟比较敏感时,可以通过设置 `tikv_client_read_timeout` 调小 TiKV RPC 读请求的超时时间,这样当某个 TiKV 节点出现 I/O 延迟抖动时,TiDB 侧可以快速超时并重新发送 TiKV RPC 请求给下一个 TiKV Region Peer 所在的 TiKV 节点。如果所有 TiKV Region Peer 都请求超时,则会用默认的超时时间(通常是 40 秒)进行新一轮的重试。 -- 你也可以在查询语句中使用 Optimizer Hint `/*+ SET_VAR(TIKV_CLIENT_READ_TIMEOUT=N) */` 来设置 TiDB 发送 TiKV RPC 读请求的超时时间。当同时设置了 Optimizer Hint 和该系统变量时,Optimizer Hint 的优先级更高。 -- 默认值 `0` 表示使用默认的超时时间(通常是 40 秒)。 +- 您可以使用 `tikv_client_read_timeout` 设置 TiDB 在查询中发送 TiKV RPC 读取请求的超时时间。当 TiDB 集群处于网络不稳定或 TiKV I/O 延迟抖动严重的环境中,并且您的应用程序对 SQL 查询的延迟敏感时,您可以设置 `tikv_client_read_timeout` 以减少 TiKV RPC 读取请求的超时时间。在这种情况下,当 TiKV 节点出现 I/O 延迟抖动时,TiDB 可以快速超时并将 RPC 请求重新发送到下一个 TiKV Region Peer 所在的 TiKV 节点。如果所有 TiKV Region Peer 的请求都超时,TiDB 将使用默认超时时间(通常为 40 秒)重试。 +- 你也可以在查询中使用优化器提示 `/*+ SET_VAR(TIKV_CLIENT_READ_TIMEOUT=N) */` 来设置 TiDB 向 TiKV 发送 RPC 读取请求的超时时间。如果同时设置了优化器提示和此系统变量,则优化器提示的优先级更高。 +- 默认值 `0` 表示使用默认超时时间(通常为 40 秒)。 > **注意:** > -> - 一个普通查询通常耗时几毫秒,但偶尔可能会出现某个 TiKV 节点的网络不稳定或 I/O 抖动,导致查询耗时超过 1 秒甚至 10 秒。此时,你可以尝试在查询语句中使用 Optimizer Hint `/*+ SET_VAR(TIKV_CLIENT_READ_TIMEOUT=100) */` 将 TiKV RPC 读请求超时设置为 100 毫秒,这样即使遇到某个 TiKV 节点查询慢,也可以快速超时然后重新发送 RPC 请求给下一个 TiKV Region Peer 所在的 TiKV 节点。由于两个 TiKV 节点同时出现 I/O 抖动的概率较低,所以该查询语句的耗时通常可以预期在几毫秒到 110 毫秒之间。 -> - 不建议将 `tikv_client_read_timeout` 的值设置的太小(例如,1 毫秒),否则 TiDB 集群在负载压力较大时会很容易导致请求超时,然后重试会进一步增加 TiDB 集群的压力。 -> - 如需为不同类型的查询语句设置不同的超时时间,建议使用 Optimizer Hint。 +> - 通常,一个常规查询只需要几毫秒,但偶尔当 TiKV 节点处于不稳定的网络或出现 I/O 抖动时,查询可能需要超过 1 秒甚至 10 秒。在这种情况下,你可以使用优化器提示 `/*+ SET_VAR(TIKV_CLIENT_READ_TIMEOUT=100) */` 为特定查询设置 TiKV RPC 读取请求超时时间为 100 毫秒。这样,即使 TiKV 节点的响应速度很慢,TiDB 也可以快速超时,然后将 RPC 请求重新发送到下一个 TiKV Region Peer 所在的 TiKV 节点。由于两个 TiKV 节点同时出现 I/O 抖动的概率很低,因此查询通常可以在几毫秒到 110 毫秒内完成。 +> - 不要为 `tikv_client_read_timeout` 设置太小的值(例如,1 毫秒)。否则,当 TiDB 集群的工作负载很高时,请求可能很容易超时,随后的重试会进一步增加 TiDB 集群的负载。 +> - 如果需要为不同类型的查询设置不同的超时值,建议使用优化器提示。 -### `time_zone` +### time_zone - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`SYSTEM` -- 数据库所使用的时区。这个变量值可以写成时区偏移的形式,如 '-8:00',也可以写成一个命名时区,如 'America/Los_Angeles'。 -- 默认值 `SYSTEM` 表示时区应当与系统主机的时区相同。系统的时区可通过 [`system_time_zone`](#system_time_zone) 获取。 +- 此变量返回当前时区。值可以指定为偏移量,例如 '-8:00',或者指定为命名时区,例如 'America/Los_Angeles'。 +- 值 `SYSTEM` 表示时区应与系统主机相同,可通过 [`system_time_zone`](#system_time_zone) 变量获得。 -### `timestamp` +### timestamp - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:浮点数 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Float - 默认值:`0` -- 取值范围:`[0, 2147483647]` -- 一个 Unix 时间戳。变量值非空时,表示 `CURRENT_TIMESTAMP()`、`NOW()` 等函数的时间戳。该变量通常用于数据恢复或数据复制。 +- 范围:`[0, 2147483647]` +- 此变量的非空值表示用作 `CURRENT_TIMESTAMP()`、`NOW()` 和其他函数的时间戳的 UNIX epoch。此变量可能用于数据恢复或复制。 -### `transaction_isolation` +### transaction_isolation - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:枚举 - 默认值:`REPEATABLE-READ` -- 可选值:`READ-UNCOMMITTED`,`READ-COMMITTED`,`REPEATABLE-READ`,`SERIALIZABLE` -- 这个变量用于设置事务隔离级别。TiDB 为了兼容 MySQL,支持可重复读 (`REPEATABLE-READ`),但实际的隔离级别是快照隔离。详情见[事务隔离级别](/transaction-isolation-levels.md)。 +- 可选值:`READ-UNCOMMITTED`、`READ-COMMITTED`、`REPEATABLE-READ`、`SERIALIZABLE` +- 此变量设置事务隔离级别。TiDB 声明 `REPEATABLE-READ` 是为了与 MySQL 兼容,但实际的隔离级别是快照隔离。有关更多详细信息,请参阅[事务隔离级别](/transaction-isolation-levels.md)。 -### `tx_isolation` +### tx_isolation -这个变量是 `transaction_isolation` 的别名。 +此变量是 `transaction_isolation` 的别名。 -### `tx_isolation_one_shot` +### tx_isolation_one_shot > **注意:** > -> 该变量仅用于 TiDB 内部实现,不推荐设置该变量。 +> 此变量在 TiDB 内部使用。不建议你使用它。 -在 TiDB 内部实现中,TiDB 解释器会将 `SET TRANSACTION ISOLATION LEVEL [READ COMMITTED| REPEATABLE READ | ...]` 语句转化为 `SET @@SESSION.TX_ISOLATION_ONE_SHOT = [READ COMMITTED| REPEATABLE READ | ...]`。 +在内部,TiDB 解析器将 `SET TRANSACTION ISOLATION LEVEL [READ COMMITTED| REPEATABLE READ | ...]` 语句转换为 `SET @@SESSION.TX_ISOLATION_ONE_SHOT = [READ COMMITTED| REPEATABLE READ | ...]`。 -### `tx_read_ts` +### tx_read_ts - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:"" -- 在 Stale Read 场景下,该会话变量用于帮助记录 Stable Read TS 值。 -- 该变量仅用于 TiDB 内部实现,**不推荐设置该变量**。 +- 在 Stale Read 场景中,此会话变量用于帮助记录 Stable Read 时间戳值。 +- 此变量用于 TiDB 的内部操作。**不建议**设置此变量。 + +### txn_scope -### `txn_scope` +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`global` - 可选值:`global` 和 `local` -- 该变量用于设置当前会话下事务为全局事务(设为 `global`)还是局部事务(设为 `local`)。 -- 该变量仅用于 TiDB 内部实现,**不推荐设置该变量**。 +- 此变量用于设置当前会话事务是全局事务还是本地事务。 +- 此变量用于 TiDB 的内部操作。**不建议**设置此变量。 -### `validate_password.check_user_name` 从 v6.5.0 版本开始引入 +### validate_password.check_user_name v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`ON` -- 类型:布尔型 -- 该变量是密码复杂度策略检查中的一个检查项,用于进行密码与用户名匹配检查。只有 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 开启时,该变量才生效。 -- 当该变量生效且为 `ON` 时,如果设置账户密码,TiDB 会将密码与当前会话账户的用户名部分(不包含主机名部分)进行比较,如果匹配则拒绝该密码。 -- 该变量独立于 [validate_password.policy](/system-variables.md#validate_passwordpolicy-从-v650-版本开始引入),即不受密码复杂度检测强度的控制。 +- 类型:Boolean +- 此变量是密码复杂度检查中的一个检查项。它检查密码是否与用户名匹配。此变量仅在启用 [`validate_password.enable`](#validate_passwordenable-new-in-v650) 时生效。 +- 当此变量生效并设置为 `ON` 时,如果你设置密码,TiDB 会将密码与用户名(不包括主机名)进行比较。如果密码与用户名匹配,则密码将被拒绝。 +- 此变量独立于 [`validate_password.policy`](#validate_passwordpolicy-new-in-v650),不受密码复杂度检查级别的限制。 -### `validate_password.dictionary` 从 v6.5.0 版本开始引入 +### validate_password.dictionary v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:"" -- 类型:字符串 -- 该变量是密码复杂度策略检查中的一个检查项,用于进行密码与字典字符串匹配检查。只有当 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 开启且 [validate_password.policy](/system-variables.md#validate_passwordpolicy-从-v650-版本开始引入) 设置为 `2` (STRONG) 时,该变量才生效。 -- 该变量是一个长字符串,长度不超过 1024,字符串内容可包含一个或多个在密码中不允许出现的单词,每个单词之间采用英文分号(`;`)分隔。 -- 默认情况下,该变量为空值,不执行字典检查。要进行字典检查,该变量值必须包含待匹配的单词。配置了该变量后,在设置账户密码时,TiDB 会将长度为 4 到 100 的密码的每个子字符串与该变量中配置的单词进行比较。任何匹配都会导致密码被拒绝。比较不区分大小写。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`""` +- 类型:String +- 此变量是密码复杂度检查中的一个检查项。它检查密码是否与字典匹配。此变量仅在启用 [`validate_password.enable`](#validate_passwordenable-new-in-v650) 且 [`validate_password.policy`](#validate_passwordpolicy-new-in-v650) 设置为 `2` (STRONG) 时生效。 +- 此变量是一个不超过 1024 个字符的字符串。它包含一个密码中不能存在的单词列表。每个单词用分号 (`;`) 分隔。 +- 默认情况下,此变量设置为空字符串,这意味着不执行字典检查。要执行字典检查,你需要将要匹配的单词包含在字符串中。如果配置了此变量,当你设置密码时,TiDB 会将密码的每个子字符串(长度为 4 到 100 个字符)与字典中的单词进行比较。如果密码的任何子字符串与字典中的单词匹配,则密码将被拒绝。比较不区分大小写。 -### `validate_password.enable` 从 v6.5.0 版本开始引入 +### validate_password.enable v6.5.0 新增 + +> **注意:** +> +> 此变量始终为 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 启用。 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`OFF` -- 类型:布尔型 -- 该变量是密码复杂度策略检查的开关。该变量设置为 `ON` 后,当设置账户密码时,TiDB 才会进行密码复杂度的各项检查。 +- 类型:Boolean +- 此变量控制是否执行密码复杂度检查。如果此变量设置为 `ON`,则在设置密码时,TiDB 会执行密码复杂度检查。 -### `validate_password.length` 从 v6.5.0 版本开始引入 +### validate_password.length v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`8` -- 范围:`[0, 2147483647]` -- 该变量是密码复杂度策略检查中的一个检查项,用于限定密码的最小长度,默认最小长度为 8。只有 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 开启时,该变量才生效。 -- 设置该变量时有最小值要求,最小值由其他几个相关的系统变量控制,即该变量的值不能设置为小于此表达式的值:`validate_password.number_count + validate_password.special_char_count + (2 * validate_password.mixed_case_count)`。 -- 当用户修改 `validate_password.number_count`、`validate_password.special_char_count`、`validate_password.mixed_case_count` 后导致表达式的值大于 `validate_password.length` 时,`validate_password.length` 将自动被修改为满足表达式的最小值。 +- 范围:对于 TiDB Self-Managed 和 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 为 `[0, 2147483647]`,对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 为 `[8, 2147483647]` +- 此变量是密码复杂度检查中的一个检查项。它检查密码长度是否足够。默认情况下,最小密码长度为 `8`。此变量仅在启用 [`validate_password.enable`](#validate_passwordenable-new-in-v650) 时生效。 +- 此变量的值不得小于表达式:`validate_password.number_count + validate_password.special_char_count + (2 * validate_password.mixed_case_count)`。 +- 如果你修改了 `validate_password.number_count`、`validate_password.special_char_count` 或 `validate_password.mixed_case_count` 的值,使得表达式的值大于 `validate_password.length`,那么 `validate_password.length` 的值会自动更改以匹配表达式的值。 -### `validate_password.mixed_case_count` 从 v6.5.0 版本开始引入 +### validate_password.mixed_case_count v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1` -- 范围:`[0, 2147483647]` -- 该变量是密码复杂度策略检查中的一个检查项,用于限定密码中至少需要包含多少个大写字符和小写字符。只有当 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 开启且 [validate_password.policy](/system-variables.md#validate_passwordpolicy-从-v650-版本开始引入) 大于或等于 `1` (MEDIUM) 时,该变量才生效。 -- 对于给定的 `validate_password.mixed_case_count` 值,密码中的小写字符数和大写字符数都不能少于该值。例如,值为 1 时,密码中至少需要 1 个小写字母,至少需要 1 个大写字母。 +- 范围:TiDB Self-Managed 和 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 为 `[0, 2147483647]`,[TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 为 `[1, 2147483647]` +- 此变量是密码复杂度检查中的一个检查项。它检查密码是否包含足够的大写和小写字母。此变量仅在启用 [`validate_password.enable`](#validate_passwordenable-new-in-v650) 且 [`validate_password.policy`](#validate_passwordpolicy-new-in-v650) 设置为 `1` (MEDIUM) 或更大时生效。 +- 密码中的大写字母数量和小写字母数量都不能少于 `validate_password.mixed_case_count` 的值。例如,当该变量设置为 `1` 时,密码必须至少包含一个大写字母和一个小写字母。 -### `validate_password.number_count` 从 v6.5.0 版本开始引入 +### validate_password.number_count v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1` -- 范围:`[0, 2147483647]` -- 该变量是密码复杂度策略检查中的一个检查项,用于限定密码中至少需要包含多少个数字字符。只有当 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 开启且 [validate_password.policy](/system-variables.md#validate_passwordpolicy-从-v650-版本开始引入) 大于或等于 `1` (MEDIUM) 时,该变量才生效。 +- 范围:TiDB Self-Managed 和 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 为 `[0, 2147483647]`,[TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 为 `[1, 2147483647]` +- 此变量是密码复杂度检查中的一个检查项。它检查密码是否包含足够的数字。此变量仅在启用 [`validate_password.enable`](#password_reuse_interval-new-in-v650) 且 [`validate_password.policy`](#validate_passwordpolicy-new-in-v650) 设置为 `1` (MEDIUM) 或更大时生效。 -### `validate_password.policy` 从 v6.5.0 版本开始引入 +### validate_password.policy v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:枚举型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Enumeration - 默认值:`1` -- 可选值:`[0, 1, 2]` -- 该变量是[密码复杂度策略检查](/password-management.md#密码复杂度策略)的强度策略,该变量影响其他密码复杂度系统变量(前缀为 `validate_password`)在密码检查时是否生效,但是 `validate_password.check_user_name` 除外。只有 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 开启时,该变量才生效。 -- 该变量可以使用数值 0、1、2 或相应的符号值 LOW、MEDIUM、STRONG,密码强度策略对应的检查项如下: - - 0 或者 LOW:检查密码长度。 - - 1 或者 MEDIUM:检查密码长度,检查密码中数字、小写字符、大写字符、特殊字符数量。 - - 2 或者 STRONG:检查密码长度,检查密码中数字、小写字符、大写字符、特殊字符数量,检查密码字典匹配。 +- 可选值:TiDB Self-Managed 和 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 为 `0`、`1` 和 `2`;[TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 为 `1` 和 `2` +- 此变量控制密码复杂度检查的策略。此变量仅在启用 [`validate_password.enable`](#password_reuse_interval-new-in-v650) 时生效。此变量的值决定了除了 `validate_password.check_user_name` 之外,其他 `validate-password` 变量是否在密码复杂度检查中生效。 +- 此变量的值可以是 `0`、`1` 或 `2`(分别对应于 LOW、MEDIUM 或 STRONG)。不同的策略级别有不同的检查: + - 0 或 LOW:密码长度。 + - 1 或 MEDIUM:密码长度、大写和小写字母、数字和特殊字符。 + - 2 或 STRONG:密码长度、大写和小写字母、数字、特殊字符和字典匹配。 -### `validate_password.special_char_count` 从 v6.5.0 版本开始引入 +### validate_password.special_char_count v6.5.0 新增 - 作用域:GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`1` -- 范围:`[0, 2147483647]` -- 该变量是密码[复杂度策略检查](/password-management.md#密码复杂度策略)中的一个检查项,用于限定密码中至少需要包含多少个特殊字符。只有当 [`validate_password.enable`](/system-variables.md#validate_passwordenable-从-v650-版本开始引入) 开启且 [validate_password.policy](/system-variables.md#validate_passwordpolicy-从-v650-版本开始引入) 大于或等于 `1` (MEDIUM) 时,该变量才生效。 +- 范围:TiDB Self-Managed 和 [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-dedicated) 为 `[0, 2147483647]`,[TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 为 `[1, 2147483647]` +- 此变量是密码复杂度检查中的一个检查项。它检查密码是否包含足够的特殊字符。此变量仅在启用 [`validate_password.enable`](#password_reuse_interval-new-in-v650) 且 [`validate_password.policy`](#validate_passwordpolicy-new-in-v650) 设置为 `1` (MEDIUM) 或更大时生效。 -### `version` +### version - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 默认值:`8.0.11-TiDB-(tidb version)` -- 这个变量的值是 MySQL 的版本和 TiDB 的版本,例如 '8.0.11-TiDB-v8.1.2'。 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 默认值:`8.0.11-TiDB-`(tidb 版本) +- 此变量返回 MySQL 版本,后跟 TiDB 版本。例如 '8.0.11-TiDB-v8.1.2'。 -### `version_comment` +### version_comment - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:(string) -- 这个变量的值是 TiDB 版本号的其他信息,例如 'TiDB Server (Apache License 2.0) Community Edition, MySQL 8.0 compatible'。 +- 此变量返回有关 TiDB 版本的其他详细信息。例如,'TiDB Server (Apache License 2.0) Community Edition, MySQL 8.0 compatible'。 -### `version_compile_os` +### version_compile_machine - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:(string) -- 这个变量值是 TiDB 所在操作系统的名称。 +- 此变量返回 TiDB 运行所在的 CPU 架构的名称。 -### `version_compile_machine` +### version_compile_os - 作用域:NONE -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:(string) -- 这个变量值是运行 TiDB 的 CPU 架构的名称。 +- 此变量返回 TiDB 运行所在的 OS 的名称。 -### `wait_timeout` +### wait_timeout + +> **注意:** +> +> 此变量对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 是只读的。 - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:整数型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Integer - 默认值:`28800` - 范围:`[0, 31536000]` - 单位:秒 -- 这个变量表示用户会话的空闲超时。`0` 代表没有时间限制。 +- 此变量控制用户会话的空闲超时。零值表示无限制。 -### `warning_count` +### warning_count - 作用域:SESSION -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 - 默认值:`0` -- 这个只读变量表示之前执行语句中出现的警告数。 +- 此只读变量指示先前执行的语句中发生的警告数量。 -### `windowing_use_high_precision` +### windowing_use_high_precision - 作用域:SESSION | GLOBAL - 是否持久化到集群:是 -- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否 -- 类型:布尔型 +- 是否适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):否 +- 类型:Boolean - 默认值:`ON` -- 这个变量用于控制计算[窗口函数](/functions-and-operators/window-functions.md)时是否采用高精度模式。 +- 此变量控制在计算 [窗口函数](/functions-and-operators/window-functions.md) 时是否使用高精度模式。 diff --git a/table-attributes.md b/table-attributes.md index 49bc7468a262..ce4151eef448 100644 --- a/table-attributes.md +++ b/table-attributes.md @@ -1,126 +1,148 @@ --- title: 表属性 -summary: 介绍 TiDB 的 `ATTRIBUTES` 使用方法。 +summary: 了解如何使用 TiDB 的表属性功能。 --- # 表属性 -表属性是 TiDB 从 5.3.0 版本开始引入的新特性,用于为表或分区添加特定的属性,以对表或分区执行相应属性对应的操作,例如可以利用表属性控制 Region 的合并。 +表属性功能在 TiDB v5.3.0 中引入。使用此功能,你可以为表或分区添加特定属性,以执行与这些属性相对应的操作。例如,你可以使用表属性来控制 Region 合并行为。 -> **注意:** -> -> - 目前 TiDB 仅支持为表或分区添加 `merge_option` 属性,用于控制 Region 合并。该属性仅能处理部分热点问题。如需了解更多的热点问题处理相关内容,请参阅 [TiDB 热点问题处理](/troubleshoot-hot-spot-issues.md)。 -> - 当使用 TiDB Binlog 或 TiCDC 进行同步或者使用 BR 进行增量备份时,同步和备份会跳过设置表属性的 DDL 语句。如需在下游或者备份集群使用表属性,需要在下游或者备份集群手动执行该 DDL 语句以设置表属性。 + -## 使用方法 +目前,TiDB 仅支持为表或分区添加 `merge_option` 属性来控制 Region 合并行为。`merge_option` 属性只是处理热点问题的一部分。更多信息,请参考[热点问题处理](/troubleshoot-hot-spot-issues.md)。 -表属性为 `key=value` 的形式,多个属性需要用逗号分隔。具体示例如下,其中 `t` 为所要修改的表名,`p` 为所要修改的分区名,`[]`内部为可选项。 + -+ 设置表或分区属性 + + +目前,TiDB 仅支持为表或分区添加 `merge_option` 属性来控制 Region 合并行为。`merge_option` 属性只是处理热点问题的一部分。 + + + +> **注意:** +> +> - 当你使用 TiDB Binlog 或 TiCDC 执行复制,或使用 BR 执行增量备份时,复制或备份操作会跳过设置表属性的 DDL 语句。要在下游或备份集群中使用表属性,你需要在下游或备份集群中手动执行 DDL 语句。 + +## 用法 + +表属性的形式为 `key=value`。多个属性之间用逗号分隔。在以下示例中,`t` 是要修改的表名,`p` 是要修改的分区名。`[]` 中的项为可选项。 + ++ 为表或分区设置属性: ```sql ALTER TABLE t [PARTITION p] ATTRIBUTES [=] 'key=value[, key1=value1...]'; ``` -+ 重置表或分区属性 ++ 重置表或分区的属性: ```sql ALTER TABLE t [PARTITION p] ATTRIBUTES [=] DEFAULT; ``` -+ 查看全部表及分区属性 ++ 查看所有表和分区的属性: ```sql SELECT * FROM information_schema.attributes; ``` -+ 查看某一张表或分区配置的属性 ++ 查看表或分区配置的属性: ```sql SELECT * FROM information_schema.attributes WHERE id='schema/t[/p]'; ``` -+ 查看拥有某属性的所有表及分区 ++ 查看具有特定属性的所有表和分区: ```sql SELECT * FROM information_schema.attributes WHERE attributes LIKE '%key%'; ``` -## 覆盖关系 +## 属性覆盖规则 -为分区表配置的属性会对表的所有分区生效。一种例外情况是,如果分区表和分区都配置了相同属性但属性值不同,分区属性将覆盖分区表属性。例如,当分区表 `t` 配置属性 `key=value`,同时分区 `p` 配置属性 `key=value1` 时: +为表配置的属性对该表的所有分区都生效。但有一个例外:如果表和分区配置了相同的属性但属性值不同,分区属性会覆盖表属性。例如,假设表 `t` 配置了 `key=value` 属性,分区 `p` 配置了 `key=value1`。 ```sql ALTER TABLE t ATTRIBUTES[=]'key=value'; ALTER TABLE t PARTITION p ATTRIBUTES[=]'key=value1'; ``` -分区 `p` 实际生效的属性为 `key=value1`。 +在这种情况下,`key=value1` 是在 `p1` 分区上实际生效的属性。 -## 使用表属性控制 Region 合并 +## 使用表属性控制 Region 合并行为 ### 使用场景 -当写入或读取数据存在热点时,可以使用表属性控制 Region 合并,通过为表或分区添加 `merge_option` 属性,将其设置为 `deny` 来解决。以下介绍了两种使用场景。 +如果存在写热点或读热点,你可以使用表属性来控制 Region 合并行为。你可以首先为表或分区添加 `merge_option` 属性,然后将其值设置为 `deny`。以下是两种场景。 -#### 新建表或分区的写入热点问题 +#### 新建表或分区的写热点 -在对某张新建表或某个新建分区写入数据存在热点问题时,通常需要使用分裂打散 Region 的操作避免写入热点,但由于新建表或分区的分裂操作实际产生的是空 Region,如果分裂打散操作距离写入存在一定时间间隔,则 Region 可能会被合并,从而导致无法真正规避写入热点问题。此时可以为表或分区添加 `merge_option` 属性,设置为 `deny` 来解决问题。 +如果在向新建的表或分区写入数据时出现热点问题,通常需要拆分和打散 Region。但是,如果拆分/打散操作与写入之间存在一定的时间间隔,这些操作并不能真正避免写热点。这是因为在创建表或分区时执行的拆分操作会产生空的 Region,所以如果存在时间间隔,拆分的 Region 可能会被合并。要处理这种情况,你可以为表或分区添加 `merge_option` 属性,并将属性值设置为 `deny`。 -#### 只读场景下周期性读热点问题 +#### 只读场景中的周期性读热点 -在只读场景下,如果是通过手动分裂 Region 缓解某张表或分区的周期性读热点问题,且不希望热点消失后手动分裂的 Region 被合并。此时可以为表或分区添加 `merge_option` 属性,设置为 `deny` 来解决问题。 +假设在只读场景中,你尝试通过手动拆分 Region 来减少表或分区上出现的周期性读热点,并且你不希望手动拆分的 Region 在热点问题解决后被合并。在这种情况下,你可以为表或分区添加 `merge_option` 属性,并将其值设置为 `deny`。 -### 使用方法 +### 用法 -使用方法如下,其中 `t` 为所要修改的表名,`p` 为所要修改的分区名。 - -+ 禁止属于某个表的 Region 被合并 ++ 防止表的 Region 合并: ```sql ALTER TABLE t ATTRIBUTES 'merge_option=deny'; ``` -+ 允许属于某个表的 Region 被合并 ++ 允许合并属于表的 Region: ```sql ALTER TABLE t ATTRIBUTES 'merge_option=allow'; ``` -+ 重置某个表的属性 ++ 重置表的属性: ```sql ALTER TABLE t ATTRIBUTES DEFAULT; ``` -+ 禁止属于某个分区的 Region 被合并 ++ 防止分区的 Region 合并: ```sql ALTER TABLE t PARTITION p ATTRIBUTES 'merge_option=deny'; ``` -+ 允许属于某个分区的 Region 被合并 ++ 允许合并属于分区的 Region: ```sql - ALTER TABLE t PARTITION p attributes 'merge_option=allow'; + ALTER TABLE t PARTITION p ATTRIBUTES 'merge_option=allow'; ``` -+ 查看所有配置了 `merge_option` 属性的表或分区 ++ 查看所有配置了 `merge_option` 属性的表或分区: ```sql SELECT * FROM information_schema.attributes WHERE attributes LIKE '%merge_option%'; ``` -### 覆盖关系 +### 属性覆盖规则 ```sql ALTER TABLE t ATTRIBUTES 'merge_option=deny'; ALTER TABLE t PARTITION p ATTRIBUTES 'merge_option=allow'; ``` -同时配置上述两个属性时,实际分区 `p` 的 Region 可以被合并。当分区的属性被重置时,分区 `p` 则会继承表 `t` 的属性,Region 无法被合并。 +当同时配置上述两个属性时,属于分区 `p` 的 Region 实际上可以被合并。当重置分区的属性时,分区 `p` 会继承表 `t` 的属性,Region 不能被合并。 + + + +> **注意:** +> +> - 对于带有分区的表,如果仅在表级别配置了 `merge_option` 属性,即使 `merge_option=allow`,该表默认仍会根据实际分区数量拆分为多个 Region。要合并所有 Region,你需要[重置表的属性](#用法)。 +> - 使用 `merge_option` 属性时,你需要注意 PD 配置参数 [`split-merge-interval`](/pd-configuration-file.md#split-merge-interval)。假设未配置 `merge_option` 属性。在这种情况下,如果 Region 满足条件,Region 可以在 `split-merge-interval` 指定的间隔后合并。如果配置了 `merge_option` 属性,PD 会根据 `merge_option` 配置在指定间隔后决定是否合并 Region。 + + + + + +> **注意:** +> +> - 对于带有分区的表,如果仅在表级别配置了 `merge_option` 属性,即使 `merge_option=allow`,该表默认仍会根据实际分区数量拆分为多个 Region。要合并所有 Region,你需要[重置表的属性](#用法)。 +> - 假设未配置 `merge_option` 属性。在这种情况下,如果 Region 满足条件,Region 可以在一小时后合并。如果配置了 `merge_option` 属性,PD 会根据 `merge_option` 配置在一小时后决定是否合并 Region。 -> **注意:** -> -> - 如果目前只存在分区表的属性,即使配置 `merge_option=allow`,分区也会默认按照实际分区数量切分成多个 Region。如需合并所有 Region,则需要[重置该分区表的属性](#使用方法)。 -> - 使用该属性需要注意 PD 的参数 [`split-merge-interval`](/pd-configuration-file.md#split-merge-interval) 的配置。如果没有配置 `merge_option`,Region 在超过 `split-merge-interval` 指定的时间后满足条件即可合并。如果配置了 `merge_option`,则超过指定时间后会根据 `merge_option` 的配置情况再决定是否可以合并。 + diff --git a/table-filter.md b/table-filter.md index 8f624beee57d..0a32cf302adb 100644 --- a/table-filter.md +++ b/table-filter.md @@ -1,21 +1,23 @@ --- -title: 表库过滤 -summary: 在 TiDB 数据迁移工具中使用表库过滤功能。 +title: 表过滤器 +summary: TiDB 工具中表过滤器功能的使用。 --- -# 表库过滤 +# 表过滤器 -TiDB 数据迁移工具默认情况下作用于所有数据库,但实际使用中,往往只需要作用于其中的部分子集。例如,用户只想处理 `foo*` 和 `bar*` 形式的表,而无需对其他表进行操作。 +TiDB 迁移工具默认操作所有数据库,但通常只需要处理其中的一部分。例如,你可能只想处理形如 `foo*` 和 `bar*` 的 schema,而不需要其他的。 -从 TiDB 4.0 起,所有 TiDB 数据迁移工具都使用一个通用的过滤语法来定义子集。本文档介绍如何使用表库过滤功能。 +从 TiDB 4.0 开始,所有 TiDB 迁移工具共享一个通用的过滤器语法来定义子集。本文描述如何使用表过滤器功能。 -## 使用表库过滤 +## 使用方法 -### 命令行 +### 命令行界面 -在命令行中使用多个 `-f` 或 `--filter` 参数,即可在 TiDB 数据迁移工具中应用表库过滤规则。每个过滤规则均采用 `db.table` 形式,支持通配符(详情见[下一节](#使用通配符))。以下为各个工具中的使用示例: +可以使用多个 `-f` 或 `--filter` 命令行参数对工具应用表过滤器。每个过滤器的形式为 `db.table`,其中每个部分都可以是通配符(在[下一节](#通配符)中进一步解释)。以下列出了示例用法。 -* [BR](/br/br-snapshot-manual.md#使用表库过滤功能备份多张表的数据): + + +* [BR](/br/backup-and-restore-overview.md): ```shell tiup br backup full -f 'foo*.*' -f 'bar*.*' -s 'local:///tmp/backup' @@ -25,21 +27,37 @@ TiDB 数据迁移工具默认情况下作用于所有数据库,但实际使用 tiup br restore full -f 'foo*.*' -f 'bar*.*' -s 'local:///tmp/backup' ``` -* [Dumpling](/dumpling-overview.md): + + +* [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview): ```shell tiup dumpling -f 'foo*.*' -f 'bar*.*' -P 3306 -o /tmp/data/ ``` + + * [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md): ```shell tiup tidb-lightning -f 'foo*.*' -f 'bar*.*' -d /tmp/data/ --backend tidb ``` + + + + +* [TiDB Lightning](https://docs.pingcap.com/tidb/stable/tidb-lightning-overview): + + ```shell + tiup tidb-lightning -f 'foo*.*' -f 'bar*.*' -d /tmp/data/ --backend tidb + ``` + + + ### TOML 配置文件 -在 TOML 文件中,表库过滤规则以[字符串数组](https://toml.io/cn/v1.0.0-rc.1#%E6%95%B0%E7%BB%84)的形式指定。以下为各个工具中的使用示例: +TOML 文件中的表过滤器被指定为[字符串数组](https://toml.io/en/v1.0.0-rc.1#section-15)。以下列出了示例用法。 * TiDB Lightning: @@ -48,6 +66,8 @@ TiDB 数据迁移工具默认情况下作用于所有数据库,但实际使用 filter = ['foo*.*', 'bar*.*'] ``` + + * [TiCDC](/ticdc/ticdc-overview.md): ```toml @@ -59,11 +79,13 @@ TiDB 数据迁移工具默认情况下作用于所有数据库,但实际使用 dispatcher = 'ts' ``` -## 表库过滤语法 + -### 直接使用表名 +## 语法 -每条表库过滤规则由“库”和“表”组成,两部分之间以英文句号 (`.`) 分隔。只有表名与规则完全相符的表才会被接受。 +### 普通表名 + +每个表过滤器规则由一个"schema 模式"和一个"表模式"组成,用点号 (`.`) 分隔。完全限定名称匹配规则的表会被接受。 ``` db1.tbl1 @@ -71,24 +93,24 @@ db2.tbl2 db3.tbl3 ``` -表名只由有效的[标识符](/schema-object-names.md)组成,例如: +普通名称必须只包含有效的[标识符字符](/schema-object-names.md),例如: * 数字(`0` 到 `9`) * 字母(`a` 到 `z`,`A` 到 `Z`) * `$` * `_` -* 非 ASCII 字符(`U+0080` 到 `U+10FFFF`) +* 非 ASCII 字符(U+0080 到 U+10FFFF) -其他 ASCII 字符均为保留字。部分标点符号有特殊含义,详情见下一节。 +所有其他 ASCII 字符都是保留的。某些标点符号具有特殊含义,将在下一节中描述。 -### 使用通配符 +### 通配符 -表名的两个部分均支持使用通配符(详情见 [fnmatch(3)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13) )。 +名称的每个部分都可以是 [fnmatch(3)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13) 中描述的通配符符号: -* `*`:匹配零个或多个字符。 -* `?`:匹配一个字符。 -* `[a-z]`:匹配 "a" 和 "z" 之间的一个字符。 -* `[!a-z]`:匹配不在 "a" 和 "z" 之间的一个字符。 +* `*` — 匹配零个或多个字符 +* `?` — 匹配一个字符 +* `[a-z]` — 匹配一个在 "a" 到 "z" 范围内的字符(包含边界) +* `[!a-z]` — 匹配一个不在 "a" 到 "z" 范围内的字符 ``` db[0-9].tbl[0-9a-f][0-9a-f] @@ -96,87 +118,87 @@ data.* *.backup_* ``` -此处,“字符”指的是一个 Unicode 码位,例如: +这里的"字符"指 Unicode 码点,例如: -* `U+00E9` "é" 是 1 个字符。 -* `U+0065,U+0301` "é" 是 2 个字符。 -* `U+1F926 U+1F3FF U+200D U+2640 U+FE0F` "🤦🏿‍♀️" 是 5 个字符。 +* U+00E9 (é) 是 1 个字符。 +* U+0065 U+0301 (é) 是 2 个字符。 +* U+1F926 U+1F3FF U+200D U+2640 U+FE0F (🤦🏿‍♀️) 是 5 个字符。 -### 使用文件导入 +### 文件导入 -如需导入一个文件作为过滤规则,请在规则的开头加上一个 “@” 来指定文件名。库表过滤解析器将导入文件中的每一行都解析为一条额外的过滤规则。 +要将文件作为过滤器规则导入,在规则开头加上 `@` 来指定文件名。表过滤器解析器将导入文件的每一行作为额外的过滤器规则。 -例如,`config/filter.txt` 文件有以下内容: +例如,如果文件 `config/filter.txt` 有以下内容: ``` employees.* *.WorkOrder ``` -以下两条表库过滤命令是等价的: +以下两种调用方式是等效的: ```bash tiup dumpling -f '@config/filter.txt' tiup dumpling -f 'employees.*' -f '*.WorkOrder' ``` -导入的文件里不能使用过滤规则导入另一个文件。 +过滤器文件不能再导入其他文件。 -### 注释与空行 +### 注释和空行 -导入的过滤规则文件中,每一行开头和结尾的空格都会被去除。此外,空行(空字符串)也将被忽略。 +在过滤器文件中,每行的前导和尾随空白都会被删除。此外,空行(空字符串)会被忽略。 -行首的 `#` 表示该行是注释,会被忽略。而不在行首的 `#` 则会被认为是语法错误。 +行首的 `#` 标记为注释并被忽略。不在行首的 `#` 被视为语法错误。 ``` -# 这是一行注释 -db.table # 这一部分不是注释,且可能引起错误 +# 这行是注释 +db.table # 但这部分不是注释,可能会导致错误 ``` -### 排除规则 +### 排除 -在一条过滤规则的开头加上 `!`,则表示符合这条规则的表不会被 TiDB 数据迁移工具处理。通过应用排除规则,库表过滤可以作为屏蔽名单来使用。 +规则开头的 `!` 表示其后的模式用于排除表不被处理。这实际上将过滤器转变为阻止列表。 ``` *.* -#^ 注意:必须先添加 *.* 规则来包括所有表 +#^ 注意:必须先添加 *.* 以包含所有表 !*.Password !employees.salaries ``` ### 转义字符 -如果需要将特殊字符转化为标识符,可以在特殊字符前加上反斜杠 `\`。 +要将特殊字符转换为标识符字符,在其前面加上反斜杠 `\`。 ``` db\.with\.dots.* ``` -为了简化语法并向上兼容,**不支持**下列字符序列: +为了简单和未来的兼容性,以下序列是禁止的: -- 在行尾去除空格后使用 `\`(使用 `[ ]` 来匹配行尾的空格)。 -- 在 `\` 后使用数字或字母 (`[0-9a-zA-Z]`)。特别是类似 C 的转义序列,如 `\0`、`\r`、`\n`、`\t` 等序列,目前在表库过滤规则中无意义。 +* 在删除空白后行尾的 `\`(使用 `[ ]` 来匹配行尾的字面空白)。 +* `\` 后跟任何 ASCII 字母数字字符(`[0-9a-zA-Z]`)。特别是,C 风格的转义序列如 `\0`、`\r`、`\n` 和 `\t` 目前没有意义。 -### 引号包裹的标识符 +### 引用标识符 -除了 `\` 之外,还可以用 `"` 和 `` ` `` 来控制特殊字符。 +除了 `\`,特殊字符也可以通过使用 `"` 或 `` ` `` 引用来抑制。 ``` "db.with.dots"."tbl\1" `db.with.dots`.`tbl\2` ``` -也可以通过输入两次引号,将引号包含在标识符内。 +引号可以通过在标识符中重复自身来包含。 ``` "foo""bar".`foo``bar` -# 等价于: +# 等效于: foo\"bar.foo\`bar ``` -用引号包裹的标识符不可以跨越多行。 +引用的标识符不能跨多行。 -用引号只包裹标识符的一部分是无效的,例如: +部分引用标识符是无效的: ``` "this is "invalid*.* @@ -184,56 +206,64 @@ foo\"bar.foo\`bar ### 正则表达式 -如果你需要使用较复杂的过滤规则,可以将每个匹配模型写为正则表达式,以 `/` 为分隔符: +如果需要非常复杂的规则,每个模式可以写成用 `/` 分隔的正则表达式: ``` /^db\d{2,}$/./^tbl\d{2,}$/ ``` -这类正则表示使用 [Go dialect](https://pkg.go.dev/regexp/syntax?tab=doc)。只要标识符中有一个子字符串与正则表达式匹配,则视为匹配该模型。例如,`/b/` 匹配 `db01`。 +这些正则表达式使用 [Go 方言](https://pkg.go.dev/regexp/syntax?tab=doc)。如果标识符包含匹配正则表达式的子字符串,则该模式匹配。例如,`/b/` 匹配 `db01`。 + +> **注意:** +> +> 正则表达式中的每个 `/` 都必须转义为 `\/`,包括在 `[…]` 内。你不能在 `\Q…\E` 之间放置未转义的 `/`。 + +## 多个规则 + + > **注意:** > -> 正则表达式中的每一个 `/` 都需要转义为 `\/`,包括在 `[...]` 里面的 `/`。不允许在 `\Q...\E` 之间放置一个未转义的 `/`。 +> 本节不适用于 TiDB Cloud。目前,TiDB Cloud 仅支持一个表过滤器规则。 -## 使用多个过滤规则 + -当表的名称与过滤列表中所有规则均不匹配时,默认情况下这些表被忽略。 +当表名不匹配过滤器列表中的任何规则时,默认行为是忽略这些未匹配的表。 -要建立一个屏蔽名单,必须使用显式的 `*.*` 作为第一条过滤规则,否则所有表均被排除。 +要构建阻止列表,必须将 `*.*` 作为第一条规则显式使用,否则所有表都将被排除。 ```bash -# 所有表均被过滤掉 +# 每个表都会被过滤掉 tiup dumpling -f '!*.Password' -# 只有 “Password” 表被过滤掉,其余表仍保留 +# 只有 "Password" 表被过滤掉,其余的都包含在内 tiup dumpling -f '*.*' -f '!*.Password' ``` -如果一个表的名称与过滤列表中的多个规则匹配,则以最后匹配的规则为准。例如: +在过滤器列表中,如果表名匹配多个模式,最后一个匹配决定结果。例如: ``` -# rule 1 +# 规则 1 employees.* -# rule 2 +# 规则 2 !*.dep* -# rule 3 +# 规则 3 *.departments ``` 过滤结果如下: -| 表名 | 规则 1 | 规则 2 | 规则 3 | 结果 | +| 表名 | 规则 1 | 规则 2 | 规则 3 | 结果 | |-----------------------|--------|--------|--------|------------------| -| irrelevant.table | | | | 默认(拒绝) | -| employees.employees | ✓ | | | 规则 1(接受) | -| employees.dept_emp | ✓ | ✓ | | 规则 2(拒绝) | -| employees.departments | ✓ | ✓ | ✓ | 规则 3(接受) | -| else.departments | | ✓ | ✓ | 规则 3(接受) | +| irrelevant.table | | | | 默认(拒绝) | +| employees.employees | ✓ | | | 规则 1(接受) | +| employees.dept_emp | ✓ | ✓ | | 规则 2(拒绝) | +| employees.departments | ✓ | ✓ | ✓ | 规则 3(接受) | +| else.departments | | ✓ | ✓ | 规则 3(接受) | > **注意:** > -> 在 TiDB 数据迁移工具的默认配置中,系统库总是被排除。系统库有以下六个: +> 在 TiDB 工具中,系统 schema 在默认配置中始终被排除。系统 schema 包括: > > * `INFORMATION_SCHEMA` > * `PERFORMANCE_SCHEMA` diff --git a/temporary-tables.md b/temporary-tables.md index c9d2f81e9970..e8e37bedba52 100644 --- a/temporary-tables.md +++ b/temporary-tables.md @@ -1,52 +1,52 @@ --- title: 临时表 -summary: 了解 TiDB 中的临时表功能,使用临时表存储业务中间数据,减少表管理开销,并提升性能。 +summary: 了解 TiDB 中的临时表功能,以及如何使用临时表存储应用程序的中间数据,从而减少表管理开销并提高性能。 --- # 临时表 -TiDB 在 v5.3.0 版本中引入了临时表功能。该功能针对业务中间计算结果的临时存储问题,让用户免于频繁地建表和删表等操作。用户可将业务上的中间计算数据存入临时表,用完数据后 TiDB 自动清理回收临时表。这避免了用户业务过于复杂,减少了表管理开销,并提升了性能。 +临时表功能在 TiDB v5.3.0 中引入。此功能解决了临时存储应用程序中间结果的问题,使你不必频繁创建和删除表。你可以将中间计算数据存储在临时表中。当不再需要中间数据时,TiDB 会自动清理和回收临时表。这避免了用户应用程序过于复杂,减少了表管理开销,并提高了性能。 -本文介绍了 TiDB 临时表的使用场景、临时表类型、使用示例、限制临时表内存占用的方法、与其他 TiDB 功能的兼容性限制。 +本文介绍临时表的使用场景和类型,提供使用示例和如何限制临时表内存使用的说明,并解释与其他 TiDB 功能的兼容性限制。 ## 使用场景 -TiDB 临时表主要应用于以下业务场景: +你可以在以下场景中使用 TiDB 临时表: -- 缓存业务的中间临时数据,计算完成后将数据转储至普通表,临时表会自动释放。 -- 短期内对同一数据进行多次 DML 操作。例如在电商购物车应用中,添加、修改、删除商品及完成结算,并移除购物车信息。 -- 快速批量导入中间临时数据,提升导入临时数据的性能。 -- 批量更新数据。将数据批量导入到数据库的临时表,修改完成后再导出到文件。 +- 缓存应用程序的中间临时数据。计算完成后,数据被转储到普通表中,临时表自动释放。 +- 在短时间内对相同数据执行多个 DML 操作。例如,在电子商务购物车应用中,添加、修改和删除产品,完成支付,并删除购物车信息。 +- 快速批量导入中间临时数据以提高临时数据导入的性能。 +- 批量更新数据。将数据批量导入数据库中的临时表,修改数据后将数据导出到文件。 ## 临时表类型 -TiDB 的临时表分为本地临时表和全局临时表: +TiDB 中的临时表分为两种类型:本地临时表和全局临时表。 -- 本地临时表的表定义和表内数据只对当前会话可见,适用于暂存会话内的中间数据。 -- 全局临时表的表定义对整个 TiDB 集群可见,表内数据只对当前事务可见,适用于暂存事务内的中间数据。 +- 对于本地临时表,表定义和表中的数据仅对当前会话可见。这种类型适合临时存储会话中的中间数据。 +- 对于全局临时表,表定义对整个 TiDB 集群可见,而表中的数据仅对当前事务可见。这种类型适合临时存储事务中的中间数据。 ## 本地临时表 -本地临时表的语义与 MySQL 临时表一致,它有以下特性: +TiDB 中本地临时表的语义与 MySQL 临时表一致。特点如下: -- 本地临时表的表定义不持久化,只在创建该表的会话内可见,其他会话无法访问该本地临时表 -- 不同会话可以创建同名的本地临时表,各会话只会读写该会话内创建的本地临时表 -- 本地临时表的数据对会话内的所有事务可见 -- 在会话结束后,该会话创建的本地临时表会被自动删除 -- 本地临时表可以与普通表同名,此时在 DDL 和 DML 语句中,普通表被隐藏,直到本地临时表被删除 +- 本地临时表的表定义不是持久的。本地临时表仅对创建该表的会话可见,其他会话无法访问该表。 +- 你可以在不同的会话中创建同名的本地临时表,每个会话只能读取和写入在该会话中创建的本地临时表。 +- 本地临时表的数据对会话中的所有事务可见。 +- 会话结束后,在该会话中创建的本地临时表会自动删除。 +- 本地临时表可以与普通表同名。在这种情况下,在 DDL 和 DML 语句中,普通表会被隐藏,直到本地临时表被删除。 -用户可通过 `CREATE TEMPORARY TABLE` 语句创建本地临时表,通过 `DROP TABLE` 或 `DROP TEMPORARY TABLE` 语句删除本地临时表。 +要创建本地临时表,你可以使用 `CREATE TEMPORARY TABLE` 语句。要删除本地临时表,你可以使用 `DROP TABLE` 或 `DROP TEMPORARY TABLE` 语句。 -不同于 MySQL,TiDB 本地临时表都是外部表,SQL 语句不会创建内部临时表。 +与 MySQL 不同,TiDB 中的本地临时表都是外部表,在执行 SQL 语句时不会自动创建内部临时表。 ### 本地临时表使用示例 > **注意:** > -> - 使用 TiDB 中的临时表前,注意临时表[与其他 TiDB 功能的兼容性限制](#与其他-tidb-功能的兼容性限制)以及[与 MySQL 临时表的兼容性](#与-mysql-临时表的兼容性)。 -> - 如果在 v5.3.0 升级前创建了本地临时表,这些临时表实际为普通表,在升级后也会被 TiDB 当成普通表处理。 +> - 在 TiDB 中使用临时表之前,请注意[与其他 TiDB 功能的兼容性限制](#与其他-tidb-功能的兼容性限制)和[与 MySQL 临时表的兼容性](#与-mysql-临时表的兼容性)。 +> - 如果你在早于 TiDB v5.3.0 的集群上创建了本地临时表,这些表实际上是普通表,并且在集群升级到 TiDB v5.3.0 或更高版本后仍被视为普通表。 -假设已存在普通表 `users`: +假设有一个普通表 `users`: {{< copyable "sql" >}} @@ -58,7 +58,7 @@ CREATE TABLE users ( ); ``` -在会话 A 中创建本地临时表 `users`,不会有名字冲突。会话 A 访问 `users` 时,访问的是本地临时表 `users`。 +在会话 A 中,创建本地临时表 `users` 不会与普通表 `users` 冲突。当会话 A 访问 `users` 表时,它访问的是本地临时表 `users`。 {{< copyable "sql" >}} @@ -75,7 +75,7 @@ CREATE TEMPORARY TABLE users ( Query OK, 0 rows affected (0.01 sec) ``` -此时将数据插入 `users`,插入到的是会话 A 中的本地临时表 `users`。 +如果你向 `users` 插入数据,数据会插入到会话 A 中的本地临时表 `users`。 {{< copyable "sql" >}} @@ -102,7 +102,7 @@ SELECT * FROM users; 1 row in set (0.00 sec) ``` -在会话 B 中创建本地临时表 `users`,不会与普通表 `users` 冲突,也不会与会话 A 中的本地临时表 `users` 冲突。会话 B 内访问 `users` 时,访问的是会话 B 内创建的本地临时表 `users` 数据。 +在会话 B 中,创建本地临时表 `users` 不会与普通表 `users` 或会话 A 中的本地临时表 `users` 冲突。当会话 B 访问 `users` 表时,它访问的是会话 B 中的本地临时表 `users`。 {{< copyable "sql" >}} @@ -119,7 +119,7 @@ CREATE TEMPORARY TABLE users ( Query OK, 0 rows affected (0.01 sec) ``` -此时将数据插入 `users`,插入到的是会话 B 中的本地临时表 `users`。 +如果你向 `users` 插入数据,数据会插入到会话 B 中的本地临时表 `users`。 {{< copyable "sql" >}} @@ -148,41 +148,41 @@ SELECT * FROM users; ### 与 MySQL 临时表的兼容性 -TiDB 本地临时表的以下特性与限制与 MySQL 一致: +TiDB 本地临时表与 MySQL 临时表具有以下相同的特性和限制: -- 创建、删除本地临时表时,不会自动提交当前事务 -- 删除本地临时表所在的 schema 后,临时表不会被删除,仍然可以读写 -- 创建本地临时表需要 `CREATE TEMPORARY TABLES` 权限,随后对该表的所有操作不需要权限 -- 本地临时表不支持外键和分区表 -- 不支持基于本地临时表创建视图 -- `SHOW [FULL] TABLES` 不显示本地临时表 +- 创建或删除本地临时表时,当前事务不会自动提交。 +- 删除本地临时表所在的 schema 后,临时表不会被删除,仍然可读可写。 +- 创建本地临时表需要 `CREATE TEMPORARY TABLES` 权限。对表的所有后续操作不需要任何权限。 +- 本地临时表不支持外键和分区表。 +- 不支持基于本地临时表创建视图。 +- `SHOW [FULL] TABLES` 不显示本地临时表。 -TiDB 本地临时表与 MySQL 临时表有以下方面不兼容: +TiDB 本地临时表与 MySQL 临时表在以下方面不兼容: -- TiDB 本地临时表不支持 `ALTER TABLE` -- TiDB 本地临时表忽略 `ENGINE` 表选项,始终在 TiDB 内存中暂存临时表数据,并且有[内存限制](#限制临时表的内存占用) -- 当声明存储引擎为 `MEMORY` 时,TiDB 本地临时表没有 `MEMORY` 存储引擎的限制 -- 当声明存储引擎为 `INNODB` 或 `MYISAM` 时,TiDB 本地临时表忽略 InnoDB 临时表特有的系统变量 -- MySQL 不允许在同一条 SQL 中多次引用同一张临时表,而 TiDB 本地临时表没有该限制 -- MySQL 中用于显示临时表的 `information_schema.INNODB_TEMP_TABLE_INFO` 表在 TiDB 中不存在。TiDB 暂无用于显示本地临时表的系统表。 -- TiDB 没有内部临时表,MySQL 针对内部临时表的系统变量对 TiDB 不生效 +- TiDB 本地临时表不支持 `ALTER TABLE`。 +- TiDB 本地临时表忽略 `ENGINE` 表选项,始终使用 TiDB 内存存储临时表数据,并有[内存限制](#限制临时表的内存使用)。 +- 当声明 `MEMORY` 作为存储引擎时,TiDB 本地临时表不受 `MEMORY` 存储引擎的限制。 +- 当声明 `INNODB` 或 `MYISAM` 作为存储引擎时,TiDB 本地临时表忽略 InnoDB 临时表特有的系统变量。 +- MySQL 不允许在同一个 SQL 语句中多次引用同一个临时表。TiDB 本地临时表没有这个限制。 +- MySQL 中显示临时表的系统表 `information_schema.INNODB_TEMP_TABLE_INFO` 在 TiDB 中不存在。目前,TiDB 没有显示本地临时表的系统表。 +- TiDB 没有内部临时表。MySQL 中用于内部临时表的系统变量对 TiDB 不起作用。 ## 全局临时表 -全局临时表是 TiDB 的扩展功能,它有以下特性: +全局临时表是 TiDB 的扩展功能。特点如下: -- 全局临时表的表定义会持久化,对所有会话可见 -- 全局临时表的数据只对当前的事务内可见,事务结束后数据自动清空 -- 全局临时表不能与普通表同名 +- 全局临时表的表定义是持久的,对所有会话可见。 +- 全局临时表的数据仅在当前事务中可见。事务结束时,数据会自动清除。 +- 全局临时表不能与普通表同名。 -用户可通过 `CREATE GLOBAL TEMPORARY TABLE` 语句创建全局临时表,语句末尾要加上 `ON COMMIT DELETE ROWS`。可通过 `DROP TABLE` 或 `DROP GLOBAL TEMPORARY TABLE` 语句删除全局临时表。 +要创建全局临时表,你可以使用以 `ON COMMIT DELETE ROWS` 结尾的 `CREATE GLOBAL TEMPORARY TABLE` 语句。要删除全局临时表,你可以使用 `DROP TABLE` 或 `DROP GLOBAL TEMPORARY TABLE` 语句。 ### 全局临时表使用示例 > **注意:** > -> - 使用 TiDB 中的临时表前,注意临时表[与其他 TiDB 功能的兼容性限制](#与其他-tidb-功能的兼容性限制)。 -> - 如果在 v5.3.0 或以上版本中创建了全局临时表,这些临时表在降级后会被当作普通表处理,导致数据错误。 +> - 在 TiDB 中使用临时表之前,请注意[与其他 TiDB 功能的兼容性限制](#与其他-tidb-功能的兼容性限制)。 +> - 如果你在 TiDB v5.3.0 或更高版本的集群上创建了全局临时表,当集群降级到早于 v5.3.0 的版本时,这些表会被作为普通表处理。在这种情况下,会发生数据错误。 在会话 A 中创建全局临时表 `users`: @@ -238,7 +238,7 @@ SELECT * FROM users; 1 row in set (0.00 sec) ``` -事务结束后数据自动被清空: +事务结束后,数据会自动清除: {{< copyable "sql" >}} @@ -260,7 +260,7 @@ SELECT * FROM users; Empty set (0.00 sec) ``` -会话 A 创建了 `users` 后,会话 B 也可以读写该表: +在会话 A 中创建 `users` 后,会话 B 也可以读取和写入 `users` 表: {{< copyable "sql" >}} @@ -274,15 +274,15 @@ Empty set (0.00 sec) > **注意:** > -> 如果事务是自动提交的,插入的数据在 SQL 语句执行结束后会被自动清空,导致后续 SQL 执行查找不到结果。因此应该使用非自动提交的事务读写全局临时表。 +> 如果事务自动提交,SQL 语句执行后,插入的数据会自动清除,后续的 SQL 执行无法使用这些数据。因此,你应该使用非自动提交事务来读取和写入全局临时表。 -## 限制临时表的内存占用 +## 限制临时表的内存使用 -无论定义表时声明的 `ENGINE` 是哪种存储引擎,本地临时表和全局临时表的数据都只暂存在 TiDB 实例的内存中,不持久化。 +无论在定义表时声明哪种存储引擎作为 `ENGINE`,本地临时表和全局临时表的数据都只存储在 TiDB 实例的内存中。这些数据不会持久化。 -为了避免内存溢出,用户可通过系统变量 [`tidb_tmp_table_max_size`](/system-variables.md#tidb_tmp_table_max_size-从-v53-版本开始引入) 限制每张临时表的大小。当临时表大小超过限制后 TiDB 会报错。`tidb_tmp_table_max_size` 的默认值是 `64MB`。 +为了避免内存溢出,你可以使用 [`tidb_tmp_table_max_size`](/system-variables.md#tidb_tmp_table_max_size-new-in-v530) 系统变量来限制每个临时表的大小。一旦临时表大于 `tidb_tmp_table_max_size` 阈值,TiDB 就会报错。`tidb_tmp_table_max_size` 的默认值是 `64MB`。 -例如,将每张临时表的大小限制为 `256MB`: +例如,将临时表的最大大小设置为 `256MB`: {{< copyable "sql" >}} @@ -292,38 +292,38 @@ SET GLOBAL tidb_tmp_table_max_size=268435456; ## 与其他 TiDB 功能的兼容性限制 -以下是本地临时表和全局临时表都不支持的功能: +TiDB 中的本地临时表和全局临时表与以下 TiDB 功能**不**兼容: -- 不支持 `AUTO_RANDOM` 列 -- 不支持 `SHARD_ROW_ID_BITS` 和 `PRE_SPLIT_REGIONS` 表选项 -- 不支持分区表 -- 不支持 `SPLIT REGION` 语句 -- 不支持 `ADMIN CHECK TABLE` 和 `ADMIN CHECKSUM TABLE` 语句 -- 不支持 `FLASHBACK TABLE` 和 `RECOVER TABLE` 语句 -- 不支持以临时表为源表执行 `CREATE TABLE LIKE` 语句 -- 不支持 Stale Read -- 不支持外键 -- 不支持 SQL binding -- 不支持添加 TiFlash 副本 -- 不支持在临时表上创建视图 -- 不支持 Placement Rules -- 包含临时表的执行计划不会被 prepared plan cache 缓存 +- `AUTO_RANDOM` 列 +- `SHARD_ROW_ID_BITS` 和 `PRE_SPLIT_REGIONS` 表选项 +- 分区表 +- `SPLIT REGION` 语句 +- `ADMIN CHECK TABLE` 和 `ADMIN CHECKSUM TABLE` 语句 +- `FLASHBACK TABLE` 和 `RECOVER TABLE` 语句 +- 基于临时表执行 `CREATE TABLE LIKE` 语句 +- Stale Read +- 外键 +- SQL 绑定 +- TiFlash 副本 +- 在临时表上创建视图 +- Placement Rules +- 涉及临时表的执行计划不会被 `prepare plan cache` 缓存。 -以下是只有本地临时表不支持的功能: +TiDB 中的本地临时表**不**支持以下功能: -- 不支持通过系统变量 `tidb_snapshot` 读取历史数据 +- 使用 `tidb_snapshot` 系统变量读取历史数据。 -## TiDB 数据迁移工具支持 +## TiDB 迁移工具支持 -本地临时表只对当前会话可见,因此本地临时表不会被 TiDB 数据迁移工具导出、备份、同步。 +本地临时表不会被 TiDB 迁移工具导出、备份或复制,因为这些表仅对当前会话可见。 -全局临时表的表定义全局可见,因此全局临时表的表定义会被 TiDB 数据迁移工具导出、备份、同步,但不导出数据。 +全局临时表会被 TiDB 迁移工具导出、备份和复制,因为表定义是全局可见的。注意,表上的数据不会被导出。 > **注意:** > -> - TiCDC 必须使用 v5.3.0 及以上版本同步,否则下游集群的表定义错误 -> - BR 必须使用 v5.3.0 及以上版本备份,否则备份后的表定义错误 -> - 导入的集群、恢复后的集群、同步的下游集群需要支持全局临时表,否则报错 +> - 使用 TiCDC 复制临时表需要 TiCDC v5.3.0 或更高版本。否则,下游表的表定义会出错。 +> - 使用 BR 备份临时表需要 BR v5.3.0 或更高版本。否则,备份的临时表的表定义会出错。 +> - 导出集群、数据恢复后的集群和复制的下游集群都应该支持全局临时表。否则,会报错。 ## 另请参阅 diff --git a/tidb-architecture.md b/tidb-architecture.md index 9a06ce881533..bbda769e8a7a 100644 --- a/tidb-architecture.md +++ b/tidb-architecture.md @@ -1,30 +1,55 @@ --- -title: TiDB 整体架构 -summary: 了解 TiDB 的整体架构。 +title: TiDB 架构 +summary: TiDB 平台的关键架构组件 --- -# TiDB 整体架构 +# TiDB 架构 -推荐先观看以下视频(时长约 14 分钟),快速了解 TiDB 的整体架构。 +与传统的单机数据库相比,TiDB 具有以下优势: - +* 采用分布式架构,具有灵活的弹性扩展能力。 +* 完全兼容 MySQL 协议以及 MySQL 的常用特性和语法。在许多情况下,将应用程序迁移到 TiDB 时,无需更改任何代码。 +* 支持高可用,当少数副本发生故障时可自动故障转移;对应用程序透明。 +* 支持 ACID 事务,适用于需要强一致性的场景,如银行转账。 -与传统的单机数据库相比,TiDB 具有以下优势: + + +* 提供丰富的[数据迁移工具](/migration-overview.md)系列,用于数据迁移、复制或备份。 + + + +作为一个分布式数据库,TiDB 由多个组件组成。这些组件相互通信,形成一个完整的 TiDB 系统。架构如下: + +![TiDB 架构](/media/tidb-architecture-v6.png) + +## TiDB 服务器 + +[TiDB 服务器](/tidb-computing.md)是一个无状态的 SQL 层,向外部提供 MySQL 协议的连接端点。TiDB 服务器接收 SQL 请求,执行 SQL 解析和优化,最终生成分布式执行计划。它可以水平扩展,通过 TiProxy、Linux Virtual Server (LVS)、HAProxy、ProxySQL 或 F5 等负载均衡组件向外部提供统一的接口。它不存储数据,仅用于计算和 SQL 分析,将实际的数据读取请求传输到 TiKV 节点(或 TiFlash 节点)。 + +## Placement Driver (PD) 服务器 + +[PD 服务器](/tidb-scheduling.md)是整个集群的元数据管理组件。它存储每个 TiKV 节点的实时数据分布元数据和整个 TiDB 集群的拓扑结构,提供 TiDB Dashboard 管理界面,并为分布式事务分配事务 ID。PD 服务器是整个 TiDB 集群的"大脑",因为它不仅存储集群的元数据,还根据 TiKV 节点实时报告的数据分布状态向特定的 TiKV 节点发送数据调度命令。此外,PD 服务器至少由三个节点组成,具有高可用性。建议部署奇数个 PD 节点。 + +## 存储服务器 + +### TiKV 服务器 + +[TiKV 服务器](/tidb-storage.md)负责存储数据。TiKV 是一个分布式事务型键值存储引擎。 + + + +[Region](/glossary.md#regionpeerraft-group) 是存储数据的基本单位。每个 Region 存储特定键范围(Key Range)的数据,这是一个从 StartKey 到 EndKey 的左闭右开区间。 + + -* 纯分布式架构,拥有良好的扩展性,支持弹性的扩缩容 -* 支持 SQL,对外暴露 MySQL 的网络协议,并兼容大多数 MySQL 的语法,在大多数场景下可以直接替换 MySQL -* 默认支持高可用,在少数副本失效的情况下,数据库本身能够自动进行数据修复和故障转移,对业务透明 -* 支持 ACID 事务,对于一些有强一致需求的场景友好,例如:银行转账 -* 具有丰富的工具链生态,覆盖数据迁移、同步、备份等多种场景 + -在内核设计上,TiDB 分布式数据库将整体架构拆分成了多个模块,各模块之间互相通信,组成完整的 TiDB 系统。对应的架构图如下: +[Region](/tidb-cloud/tidb-cloud-glossary.md#region) 是存储数据的基本单位。每个 Region 存储特定键范围(Key Range)的数据,这是一个从 StartKey 到 EndKey 的左闭右开区间。 -![architecture](/media/tidb-architecture-v6.png) + -- [TiDB Server](/tidb-computing.md):SQL 层,对外暴露 MySQL 协议的连接 endpoint,负责接受客户端的连接,执行 SQL 解析和优化,最终生成分布式执行计划。TiDB 层本身是无状态的,实践中可以启动多个 TiDB 实例,通过负载均衡组件(如 TiProxy、LVS、HAProxy、ProxySQL 或 F5)对外提供统一的接入地址,客户端的连接可以均匀地分摊在多个 TiDB 实例上以达到负载均衡的效果。TiDB Server 本身并不存储数据,只是解析 SQL,将实际的数据读取请求转发给底层的存储节点 TiKV(或 TiFlash)。 +每个 TiKV 节点中存在多个 Region。TiKV API 在键值对级别上原生支持分布式事务,并默认支持快照隔离级别。这是 TiDB 在 SQL 级别支持分布式事务的核心。TiDB 服务器在处理 SQL 语句后,将 SQL 执行计划转换为对 TiKV API 的实际调用。因此,数据存储在 TiKV 中。TiKV 中的所有数据自动维护多个副本(默认为三个副本),因此 TiKV 具有原生的高可用性并支持自动故障转移。 -- [PD (Placement Driver) Server](/tidb-scheduling.md):整个 TiDB 集群的元信息管理模块,负责存储每个 TiKV 节点实时的数据分布情况和集群的整体拓扑结构,提供 TiDB Dashboard 管控界面,并为分布式事务分配事务 ID。PD 不仅存储元信息,同时还会根据 TiKV 节点实时上报的数据分布状态,下发数据调度命令给具体的 TiKV 节点,可以说是整个集群的“大脑”。此外,PD 本身也是由至少 3 个节点构成,拥有高可用的能力。建议部署奇数个 PD 节点。 +### TiFlash 服务器 -- 存储节点 - - [TiKV Server](/tidb-storage.md):负责存储数据,从外部看 TiKV 是一个分布式的提供事务的 Key-Value 存储引擎。存储数据的基本单位是 Region,每个 Region 负责存储一个 Key Range(从 StartKey 到 EndKey 的左闭右开区间)的数据,每个 TiKV 节点会负责多个 Region。TiKV 的 API 在 KV 键值对层面提供对分布式事务的原生支持,默认提供了 SI (Snapshot Isolation) 的隔离级别,这也是 TiDB 在 SQL 层面支持分布式事务的核心。TiDB 的 SQL 层做完 SQL 解析后,会将 SQL 的执行计划转换为对 TiKV API 的实际调用。所以,数据都存储在 TiKV 中。另外,TiKV 中的数据都会自动维护多副本(默认为三副本),天然支持高可用和自动故障转移。 - - [TiFlash](/tiflash/tiflash-overview.md):TiFlash 是一类特殊的存储节点。和普通 TiKV 节点不一样的是,在 TiFlash 内部,数据是以列式的形式进行存储,主要的功能是为分析型的场景加速。 +[TiFlash 服务器](/tiflash/tiflash-overview.md)是一种特殊类型的存储服务器。与普通的 TiKV 节点不同,TiFlash 按列存储数据,主要用于加速分析处理。 diff --git a/tidb-cloud/ai-feature-concepts.md b/tidb-cloud/ai-feature-concepts.md new file mode 100644 index 000000000000..4160638171f3 --- /dev/null +++ b/tidb-cloud/ai-feature-concepts.md @@ -0,0 +1,50 @@ +--- +title: AI 功能 +summary: 了解 TiDB Cloud 的 AI 功能。 +--- + +# AI 功能 + +TiDB Cloud 中的 AI 功能使您能够充分利用先进技术进行数据探索、搜索和集成。从自然语言驱动的 SQL 查询生成到高性能向量搜索,TiDB 将数据库功能与现代 AI 功能相结合,为创新应用提供动力。通过支持流行的 AI 框架、嵌入模型以及与 ORM 库的无缝集成,TiDB 为语义搜索和 AI 驱动的分析等用例提供了一个多功能平台。 + +本文档重点介绍这些 AI 功能以及它们如何增强 TiDB 体验。 + +## Chat2Query(Beta) + +Chat2Query 是集成在 SQL 编辑器中的 AI 驱动功能,可帮助用户使用自然语言指令生成、调试或重写 SQL 查询。更多信息,请参见[使用 AI 辅助的 SQL 编辑器探索数据](/tidb-cloud/explore-data-with-chat2query.md)。 + +此外,TiDB Cloud 为 TiDB Cloud Serverless 集群提供 Chat2Query API。启用后,TiDB Cloud 将自动在数据服务中创建一个名为 Chat2Query 的系统数据应用和一个 Chat2Data 端点。您可以调用此端点,通过提供指令让 AI 生成并执行 SQL 语句。更多信息,请参见[开始使用 Chat2Query API](/tidb-cloud/use-chat2query-api.md)。 + +## 向量搜索(Beta) + +向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。 + +与依赖精确关键词匹配和词频的传统全文搜索不同,向量搜索将各种数据类型(如文本、图像或音频)转换为高维向量,并基于这些向量之间的相似度进行查询。这种搜索方法捕捉数据的语义含义和上下文信息,从而更准确地理解用户意图。 + +即使搜索词与数据库中的内容不完全匹配,向量搜索仍然可以通过分析数据的语义提供符合用户意图的结果。例如,对"会游泳的动物"进行全文搜索只会返回包含这些确切关键词的结果。相比之下,向量搜索可以返回其他会游泳的动物的结果,如鱼或鸭子,即使这些结果不包含确切的关键词。 + +更多信息,请参见[向量搜索(Beta)概述](/tidb-cloud/vector-search-overview.md)。 + +## AI 集成 + +### AI 框架 + +TiDB 官方支持多个流行的 AI 框架,使您能够轻松地将基于这些框架开发的 AI 应用程序与 TiDB 向量搜索集成。 + +有关支持的 AI 框架列表,请参见[向量搜索集成概述](/tidb-cloud/vector-search-integration-overview.md#ai-frameworks)。 + +### 嵌入模型和服务 + +向量嵌入(也称为嵌入)是一个数字序列,用于在高维空间中表示现实世界的对象。它捕捉非结构化数据(如文档、图像、音频和视频)的含义和上下文。 + +嵌入模型是将数据转换为[向量嵌入](/tidb-cloud/vector-search-overview.md#vector-embedding)的算法。选择合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。 + +TiDB 向量搜索支持存储最多 16383 维的向量,可以适应大多数嵌入模型。对于非结构化文本数据,您可以在 [Massive Text Embedding Benchmark (MTEB) 排行榜](https://huggingface.co/spaces/mteb/leaderboard)上找到性能最佳的文本嵌入模型。 + +### 对象关系映射(ORM)库 + +对象关系映射(ORM)库是一种工具,通过允许开发人员像处理编程语言中的对象一样处理数据库记录,从而促进应用程序和关系数据库之间的交互。 + +TiDB 允许您将向量搜索与 ORM 库集成,以便与传统关系数据一起管理向量数据。这种集成对于需要存储和查询 AI 模型生成的向量嵌入的应用程序特别有用。通过使用 ORM 库,开发人员可以无缝地与存储在 TiDB 中的向量数据交互,利用数据库的功能执行最近邻搜索等复杂的向量操作。 + +有关支持的 ORM 库列表,请参见[向量搜索集成概述](/tidb-cloud/vector-search-integration-overview.md#object-relational-mapping-orm-libraries)。 diff --git a/tidb-cloud/api-overview.md b/tidb-cloud/api-overview.md new file mode 100644 index 000000000000..a77f65165cf8 --- /dev/null +++ b/tidb-cloud/api-overview.md @@ -0,0 +1,32 @@ +--- +title: TiDB Cloud API 概述 +summary: 了解什么是 TiDB Cloud API,其特性以及如何使用 API 管理你的 TiDB Cloud 集群。 +--- + +# TiDB Cloud API 概述(Beta) + +> **注意:** +> +> TiDB Cloud API 目前处于 beta 阶段。 + +TiDB Cloud API 是一个 [REST 接口](https://en.wikipedia.org/wiki/Representational_state_transfer),为你提供了以编程方式访问和管理 TiDB Cloud 中管理对象的能力。通过这个 API,你可以自动且高效地管理项目、集群、备份、恢复、导入、计费以及 [Data Service](/tidb-cloud/data-service-overview.md) 中的资源。 + +该 API 具有以下特性: + +- **JSON 实体。** 所有实体都以 JSON 格式表示。 +- **仅支持 HTTPS。** 你只能通过 HTTPS 访问 API,确保所有通过网络发送的数据都使用 TLS 加密。 +- **基于密钥的访问和摘要认证。** 在访问 TiDB Cloud API 之前,你必须生成一个 API 密钥,参考 [API 密钥管理](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication/API-key-management)。所有请求都通过 [HTTP 摘要认证](https://en.wikipedia.org/wiki/Digest_access_authentication) 进行认证,确保 API 密钥永远不会在网络上传输。 + +要开始使用 TiDB Cloud API,请参考 TiDB Cloud API 文档中的以下资源: + +- [入门指南](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Get-Started) +- [认证](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication) +- [速率限制](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Rate-Limiting) +- API 完整参考 + - v1beta1 + - [计费](https://docs.pingcap.com/tidbcloud/api/v1beta1/billing) + - [Data Service](https://docs.pingcap.com/tidbcloud/api/v1beta1/dataservice) + - [IAM](https://docs.pingcap.com/tidbcloud/api/v1beta1/iam) + - [MSP(已弃用)](https://docs.pingcap.com/tidbcloud/api/v1beta1/msp) + - [v1beta](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Project) +- [更新日志](https://docs.pingcap.com/tidbcloud/api/v1beta#section/API-Changelog) diff --git a/tidb-cloud/architecture-concepts.md b/tidb-cloud/architecture-concepts.md new file mode 100644 index 000000000000..e33b6b3d6e42 --- /dev/null +++ b/tidb-cloud/architecture-concepts.md @@ -0,0 +1,104 @@ +--- +title: 架构 +summary: 了解 TiDB Cloud 的架构概念。 +--- + +# 架构 + +TiDB Cloud 是一个全托管的数据库即服务(DBaaS),它将开源 HTAP(混合事务和分析处理)数据库 [TiDB](https://docs.pingcap.com/tidb/stable/overview) 的灵活性和强大功能带到了 AWS、Azure 和 Google Cloud 平台。 + +TiDB 兼容 MySQL,这使得迁移和使用现有应用程序变得容易,同时提供无缝扩展能力,可以处理从小型工作负载到大规模高性能集群的各种场景。它在一个系统中同时支持事务处理(OLTP)和分析处理(OLAP)工作负载,简化了运维并实现了实时数据洞察。 + +TiDB Cloud 提供两种部署选项:**TiDB Cloud Serverless**,用于自动扩展、成本效益高的工作负载,以及 **TiDB Cloud Dedicated**,用于具有专用资源和高级功能的企业级应用。TiDB Cloud 让您能够轻松扩展数据库、处理复杂的管理任务,并专注于开发可靠、高性能的应用程序。 + +## TiDB Cloud Serverless + +TiDB Cloud Serverless 是一个全托管的无服务器解决方案,提供与传统 TiDB 类似的 HTAP 功能,同时提供自动扩展功能,以减轻用户在容量规划和管理复杂性方面的负担。它包含一个基础使用的免费层级,对超出免费限制的使用采用基于消费的计费方式。TiDB Cloud Serverless 提供两种高可用性选项以满足不同的运维需求。 + +默认情况下,使用可用区高可用性选项的集群将所有组件都部署在同一个可用区内,这样可以降低网络延迟。 + +![TiDB Cloud Serverless 可用区高可用性](/media/tidb-cloud/serverless-zonal-high-avaliability-aws.png) + +对于需要最大基础设施隔离和冗余的应用,区域高可用性选项会将节点分布在多个可用区中。 + +![TiDB Cloud Serverless 区域高可用性](/media/tidb-cloud/serverless-regional-high-avaliability-aws.png) + +## TiDB Cloud Dedicated + +TiDB Cloud Dedicated 专为关键业务而设计,提供跨多个可用区的高可用性、水平扩展和完整的 HTAP 功能。 + +它基于隔离的云资源构建,如 VPC、虚拟机、托管 Kubernetes 服务和云存储,充分利用主要云服务提供商的基础设施。TiDB Cloud Dedicated 集群支持完整的 TiDB 功能集,支持快速扩展、可靠备份、在特定 VPC 中部署以及地理级别的灾难恢复。 + +![TiDB Cloud Dedicated 架构](/media/tidb-cloud/tidb-cloud-dedicated-architecture.png) + +## TiDB Cloud 控制台 + +[TiDB Cloud 控制台](https://tidbcloud.com/)是 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 的基于 Web 的管理界面。它提供了管理集群、导入或迁移数据、监控性能指标、配置备份、设置安全控制以及与其他云服务集成的工具,所有这些都可以在一个用户友好的平台上完成。 + +## TiDB Cloud CLI(Beta) + +TiDB Cloud CLI(`ticloud`)允许您通过简单的命令直接从终端管理 TiDB Cloud Serverless 和 TiDB Cloud Dedicated。您可以执行以下任务: + +- 创建、删除和列出集群。 +- 向集群导入数据。 +- 从集群导出数据。 + +更多信息,请参见 [TiDB Cloud CLI 参考](/tidb-cloud/cli-reference.md)。 + +## TiDB Cloud API(Beta) + +TiDB Cloud API 是一个基于 REST 的接口,提供了对 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 资源进行编程访问的能力。它支持自动化和高效处理任务,如管理项目、集群、备份、恢复、数据导入、计费以及 [TiDB Cloud 数据服务](/tidb-cloud/data-service-overview.md)中的其他资源。 + +更多信息,请参见 [TiDB Cloud API 概述](/tidb-cloud/api-overview.md)。 + +## 节点 + +在 TiDB Cloud 中,每个集群由 TiDB、TiKV 和 TiFlash 节点组成。 + +- 在 TiDB Cloud Dedicated 集群中,您可以根据性能需求完全管理专用 TiDB、TiKV 和 TiFlash 节点的数量和大小。更多信息,请参见[可扩展性](/tidb-cloud/scalability-concepts.md)。 +- 在 TiDB Cloud Serverless 集群中,TiDB、TiKV 和 TiFlash 节点的数量和大小是自动管理的。这确保了无缝扩展,无需用户处理节点配置或管理任务。 + +### TiDB 节点 + +[TiDB 节点](/tidb-computing.md)是一个无状态的 SQL 层,使用 MySQL 兼容的端点连接应用程序。它处理 SQL 查询的解析、优化和创建分布式执行计划等任务。 + +您可以部署多个 TiDB 节点以实现水平扩展并管理更高的工作负载。这些节点与负载均衡器(如 TiProxy 或 HAProxy)配合使用,提供无缝接口。TiDB 节点本身不存储数据——它们将数据请求转发到 TiKV 节点进行行式存储或 TiFlash 节点进行列式存储。 + +### TiKV 节点 + +[TiKV 节点](/tikv-overview.md)是 TiDB 架构中数据存储的核心,作为分布式事务性键值存储引擎,提供可靠性、可扩展性和高可用性。 + +**主要特性:** + +- **基于 Region 的数据存储** + + - 数据被划分为多个 [Region](https://docs.pingcap.com/tidb/dev/glossary#regionpeerraft-group),每个 Region 覆盖特定的键范围(左闭右开区间:从 `StartKey` 到 `EndKey`)。 + - 每个 TiKV 节点中共存多个 Region,确保高效的数据分布。 + +- **事务支持** + + - TiKV 节点在键值层面提供原生分布式事务支持,默认隔离级别为快照隔离。 + - TiDB 节点将 SQL 执行计划转换为对 TiKV 节点 API 的调用,实现无缝的 SQL 级事务支持。 + +- **高可用性** + + - TiKV 节点中的所有数据都会被复制(默认三副本)以确保持久性。 + - TiKV 确保原生高可用性并支持自动故障转移,防止节点故障。 + +- **可扩展性和可靠性** + + - TiKV 节点设计用于处理不断扩大的数据集,同时保持分布式一致性和容错性。 + +### TiFlash 节点 + +[TiFlash 节点](/tiflash/tiflash-overview.md)是 TiDB 架构中的一种专门存储节点。与普通的 TiKV 节点不同,TiFlash 采用列式存储模型,专为分析加速而设计。 + +**主要特性:** + +- **列式存储** + + TiFlash 节点以列式格式存储数据,这使其针对分析查询进行了优化,显著提高了读密集型工作负载的性能。 + +- **向量搜索索引支持** + + 向量搜索索引功能使用表的 TiFlash 副本,支持高级搜索功能,提高复杂分析场景的效率。 diff --git a/tidb-cloud/backup-and-restore-concepts.md b/tidb-cloud/backup-and-restore-concepts.md new file mode 100644 index 000000000000..6508337ccbe8 --- /dev/null +++ b/tidb-cloud/backup-and-restore-concepts.md @@ -0,0 +1,42 @@ +--- +title: 备份和恢复 +summary: 了解 TiDB Cloud 的备份和恢复概念。 +--- + +# 备份和恢复 + +TiDB Cloud 备份和恢复功能旨在通过使您能够备份和恢复集群数据来保护您的数据并确保业务连续性。 + +## 自动备份 + +对于 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 集群,默认情况下会自动进行快照备份,并根据您的备份保留策略进行存储。 + +更多信息,请参见以下内容: + +- [TiDB Cloud Serverless 集群的自动备份](/tidb-cloud/backup-and-restore-serverless.md#automatic-backups) +- [TiDB Cloud Dedicated 集群的自动备份](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup) + +## 手动备份 + +手动备份是 TiDB Cloud Dedicated 的一项功能,使您能够根据需要将数据备份到已知状态,然后随时恢复到该状态。 + +更多信息,请参见[执行手动备份](/tidb-cloud/backup-and-restore.md#perform-a-manual-backup)。 + +## 双区域备份 + +双区域备份是 TiDB Cloud Dedicated 的一项功能,使您能够将备份从集群所在区域复制到另一个不同的区域。启用后,所有备份都会自动复制到指定区域。这提供了跨区域数据保护和灾难恢复能力。估计约 99% 的数据可以在一小时内复制到次要区域。 + +更多信息,请参见[开启双区域备份](/tidb-cloud/backup-and-restore.md#turn-on-dual-region-backup)。 + +## 时间点恢复 + +时间点恢复是一项功能,使您能够将任意时间点的数据恢复到新集群。您可以使用它来: + +- 降低灾难恢复中的 RPO。 +- 通过恢复到错误事件发生之前的时间点来解决数据写入错误的情况。 +- 审计业务的历史数据。 + +如果您想执行时间点恢复,请注意以下事项: + +- 对于 TiDB Cloud Serverless 集群,时间点恢复仅适用于可扩展集群,不适用于免费集群。更多信息,请参见[恢复模式](/tidb-cloud/backup-and-restore-serverless.md#restore-mode)。 +- 对于 TiDB Cloud Dedicated 集群,您需要提前[启用 PITR](/tidb-cloud/backup-and-restore.md#turn-on-point-in-time-restore)。 diff --git a/tidb-cloud/backup-and-restore-serverless.md b/tidb-cloud/backup-and-restore-serverless.md new file mode 100644 index 000000000000..b8b3cc58c0b0 --- /dev/null +++ b/tidb-cloud/backup-and-restore-serverless.md @@ -0,0 +1,159 @@ +--- +title: 备份和恢复 TiDB Cloud Serverless 数据 +summary: 了解如何备份和恢复 TiDB Cloud Serverless 集群。 +aliases: ['/tidbcloud/restore-deleted-tidb-cluster'] +--- + +# 备份和恢复 TiDB Cloud Serverless 数据 + +本文介绍如何在 TiDB Cloud 上备份和恢复 TiDB Cloud Serverless 集群数据。 + +> **提示:** +> +> 要了解如何备份和恢复 TiDB Cloud Dedicated 集群数据,请参阅[备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md)。 + +## 查看备份页面 + +1. 在[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称进入其概览页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 在左侧导航栏中,点击**数据** > **备份**。 + +## 自动备份 + +TiDB Cloud Serverless 自动备份你的集群数据,允许你从备份快照恢复数据,以在发生灾难时最大限度地减少数据丢失。 + +### 了解备份设置 + +免费集群和可扩展集群的自动备份设置有所不同,如下表所示: + +| 备份设置 | 免费集群 | 可扩展集群 | +|------------------|--------------|------------------| +| 备份周期 | 每日 | 每日 | +| 备份保留期 | 1 天 | 14 天 | +| 备份时间 | 固定时间 | 可配置 | + +- **备份周期**是进行备份的频率。 + +- **备份保留期**是备份保留的时间。过期的备份无法恢复。 + +- **备份时间**是开始调度备份的时间。注意,最终的备份时间可能会晚于配置的备份时间。 + + - 免费集群:备份时间是随机固定的时间。 + - 可扩展集群:你可以将备份时间配置为每半小时。默认值是随机固定的时间。 + +### 配置备份设置 + +要为可扩展集群设置备份时间,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**备份设置**。这将打开**备份设置**窗口,你可以根据需求配置自动备份设置。 + +3. 在**备份时间**中,为每日集群备份安排一个开始时间。 + +4. 点击**确认**。 + +## 恢复 + +TiDB Cloud Serverless 集群提供恢复功能,帮助在意外数据丢失或损坏时恢复数据。 + +### 恢复模式 + +TiDB Cloud Serverless 支持集群的快照恢复和时间点恢复。 + +- **快照恢复**:从特定备份快照恢复集群。 + +- **时间点恢复(beta)**:将集群恢复到特定时间点。 + + - 免费集群:不支持。 + - 可扩展集群:可以恢复到过去 14 天内的任意时间点,但不能早于集群创建时间或晚于当前时间减去一分钟。 + +### 恢复目标 + +TiDB Cloud Serverless 支持原地恢复和恢复到新集群。 + +**原地恢复** + +恢复到当前集群将覆盖现有数据。请注意以下事项: + +- 一旦开始恢复,现有连接将被终止。 +- 在恢复过程中,集群将不可用,新的连接将被阻止。 +- 恢复将影响 `mysql` 架构中的表。对用户凭据、权限或系统变量的任何更改都将恢复到备份时的状态。 + +**恢复到新集群** + +创建并恢复到新集群。请注意以下事项: + +- 源集群的用户凭据和权限不会恢复到新集群。 + +### 恢复超时 + +恢复过程通常在几分钟内完成。如果恢复时间超过三小时,将自动取消。取消恢复的结果取决于目标: + +- **原地恢复**:集群状态从**恢复中**变为**可用**,集群变为可访问。 +- **恢复到新集群**:新集群被删除,源集群保持不变。 + +如果取消恢复后数据损坏且无法恢复,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +### 执行恢复 + +要恢复你的 TiDB Cloud Serverless 集群,请按照以下步骤操作: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**恢复**。设置窗口显示。 + +3. 在**恢复模式**中,你可以选择从特定备份恢复或从任意时间点恢复。 + + +
+ + 要从选定的备份快照恢复,请执行以下步骤: + + 1. 点击**快照恢复**。 + 2. 选择要恢复的备份快照。 + +
+
+ + 要将可扩展集群恢复到特定时间点,请执行以下步骤: + + 1. 点击**时间点恢复**。 + 2. 选择要恢复到的日期和时间。 + +
+
+ +4. 在**目标**中,你可以选择恢复到新集群或原地恢复。 + + +
+ + 要恢复到新集群,请执行以下步骤: + + 1. 点击**恢复到新集群**。 + 2. 为新集群输入名称。 + 3. 为新集群选择集群方案。 + 4. 如果你选择可扩展集群,请设置每月支出限额,然后根据需要配置高级设置。否则,跳过此步骤。 + +
+
+ + 要原地恢复,点击**原地恢复**。 + +
+
+ +5. 点击**恢复**开始恢复过程。 + +一旦恢复过程开始,集群状态将变为**恢复中**。集群将保持不可用状态,直到恢复完成且状态变为**可用**。 + +## 限制 + +- 如果启用了 TiFlash 副本,在恢复后它将在一段时间内不可用,因为数据需要在 TiFlash 中重建。 +- TiDB Cloud Serverless 集群不支持手动备份。 +- 默认情况下,数据量超过 1 TiB 的集群不支持恢复到新集群。如需处理更大的数据集,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 diff --git a/tidb-cloud/backup-and-restore.md b/tidb-cloud/backup-and-restore.md new file mode 100644 index 000000000000..a9cc057acf99 --- /dev/null +++ b/tidb-cloud/backup-and-restore.md @@ -0,0 +1,274 @@ +--- +title: 备份和恢复 TiDB Cloud Dedicated 数据 +summary: 了解如何备份和恢复 TiDB Cloud Dedicated 集群。 +aliases: ['/tidbcloud/restore-deleted-tidb-cluster'] +--- + +# 备份和恢复 TiDB Cloud Dedicated 数据 + +本文档介绍如何在 TiDB Cloud 上备份和恢复 TiDB Cloud Dedicated 集群数据。TiDB Cloud Dedicated 支持自动备份和手动备份。您还可以将备份数据恢复到新集群,或从回收站恢复已删除的集群。 + +> **提示** +> +> 要了解如何备份和恢复 TiDB Cloud Serverless 集群数据,请参阅[备份和恢复 TiDB Cloud Serverless 数据](/tidb-cloud/backup-and-restore-serverless.md)。 + +## 限制 + +- 对于 v6.2.0 或更高版本的集群,TiDB Cloud Dedicated 默认支持从备份中恢复用户账号和 SQL 绑定。 +- TiDB Cloud Dedicated 不支持恢复存储在 `mysql` 架构中的系统变量。 +- 建议您先导入数据,然后执行**手动**快照备份,最后启用时间点恢复。因为通过 TiDB Cloud 控制台导入的数据**不会**生成变更日志,无法自动检测和备份。更多信息,请参阅[从云存储将 CSV 文件导入到 TiDB Cloud Dedicated](/tidb-cloud/import-csv-files.md)。 +- 如果多次开启和关闭时间点恢复,您只能选择最近一次启用时间点恢复后的可恢复范围内的时间点。早期的可恢复范围将无法访问。 +- 请勿同时修改**时间点恢复**和**双区域备份**的开关。 + +## 备份 + +### 查看备份页面 + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面上,点击目标集群的名称以进入其概览页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 在左侧导航栏中,点击**数据** > **备份**。 + +### 开启自动备份 + +TiDB Cloud Dedicated 支持[快照备份](https://docs.pingcap.com/tidb/stable/br-snapshot-guide)和[日志备份](https://docs.pingcap.com/tidb/stable/br-pitr-guide)。快照备份使您能够将数据恢复到备份点。默认情况下,快照备份会根据您的备份保留策略自动进行并存储。您可以随时禁用自动备份。 + +#### 开启时间点恢复 + +> **注意** +> +> 时间点恢复功能支持 v6.4.0 或更高版本的 TiDB Cloud Dedicated 集群。 + +此功能支持将任意时间点的数据恢复到新集群。您可以使用它来: + +- 降低灾难恢复的 RPO。 +- 通过恢复到错误事件发生前的时间点来解决数据写入错误的情况。 +- 审计业务的历史数据。 + +强烈建议开启此功能。成本与快照备份相同。更多信息,请参阅[数据备份成本](https://www.pingcap.com/tidb-dedicated-pricing-details#backup-storage-cost)。 + +要为 TiDB Cloud Dedicated 集群开启此功能,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**备份设置**。 + +3. 将**自动备份**开关切换为**开启**。 + +4. 将**时间点恢复**开关切换为**开启**。 + + > **警告** + > + > 时间点恢复仅在下一次备份任务完成后生效。要使其更早生效,您可以在启用后[手动执行备份](#执行手动备份)。 + +5. 点击**保存**以保存更改。 + +#### 配置备份计划 + +TiDB Cloud Dedicated 支持每日和每周备份计划。默认情况下,备份计划设置为每日。您可以选择一天或一周中的特定时间开始快照备份。 + +要为 TiDB Cloud Dedicated 集群配置备份计划,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**备份设置**。 + +3. 将**自动备份**开关切换为**开启**。 + +4. 按如下配置备份计划: + + - 在**备份周期**中,点击**每日备份**或**每周备份**选项卡。对于**每周备份**,您需要指定备份的星期几。 + + > **警告** + > + > - 启用每周备份时,时间点恢复功能默认开启且无法禁用。 + > - 如果您将备份周期从每周更改为每日,时间点恢复功能将保持其原始设置。如果需要,您可以手动禁用它。 + + - 在**备份时间**中,为每日或每周集群备份安排开始时间。 + + 如果您未指定首选备份时间,TiDB Cloud 会分配默认备份时间,即集群所在区域时区的凌晨 2:00。 + + > **注意** + > + > - 当数据导入作业正在进行时,备份作业会自动延迟。在数据导入或集群扩展期间**请勿**运行手动备份。 + + - 在**备份保留**中,配置最短备份数据保留期。默认期限为 7 天。为了最大限度地减少对业务的影响,建议在工作负载较低的时段安排自动备份。 + + > **注意** + > + > - 除最新的自动备份外,所有超过保留期的自动备份都将被删除。最新的自动备份不会被删除,除非您手动删除它。这确保了在发生意外删除时,您可以恢复集群数据。 + > - 删除集群后,保留期内的自动备份将移至回收站。 + +### 开启双区域备份 + +> **注意:** +> +> - 目前,双区域备份功能仅适用于托管在 AWS 和 Google Cloud 上的集群。 +> - 托管在 Google Cloud 上的 TiDB Cloud Dedicated 集群与 Google Cloud Storage 无缝协作。与 Google Cloud Storage 类似,**TiDB Cloud Dedicated 仅支持在相同的多区域代码内进行双区域配对,就像 Google 双区域存储一样**。例如,在亚洲,目前您必须将东京和大阪配对在一起以进行双区域存储。更多信息,请参阅[双区域](https://cloud.google.com/storage/docs/locations#location-dr)。 + +TiDB Cloud Dedicated 支持通过将备份从集群区域复制到另一个不同区域来实现双区域备份。启用此功能后,所有备份都会自动复制到指定区域。这提供了跨区域数据保护和灾难恢复能力。估计约 99% 的数据可以在一小时内复制到次要区域。 + +双区域备份成本包括备份存储使用费和跨区域数据传输费。更多信息,请参阅[数据备份成本](https://www.pingcap.com/tidb-dedicated-pricing-details#backup-storage-cost)。 + +要为 TiDB Cloud Dedicated 集群开启双区域备份,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**备份设置**。 + +3. 将**双区域备份**开关切换为**开启**。 + +4. 从**次要区域**下拉列表中,选择一个区域来存储备份文件。 + +5. 点击**保存**以保存更改。 + +### 关闭自动备份 + +> **注意** +> +> 关闭自动备份也会默认关闭时间点恢复。 + +要关闭 TiDB Cloud Dedicated 集群的自动备份,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**备份设置**。 + +3. 将**自动备份**开关切换为**关闭**。 + +4. 点击**保存**以保存更改。 + +### 关闭双区域备份 + +> **提示** +> +> 禁用双区域备份不会立即删除次要区域中的备份。这些备份将根据备份保留计划稍后清理。要立即删除它们,您可以手动[删除备份](#删除备份)。 + +要关闭 TiDB Cloud Dedicated 集群的双区域备份,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**备份设置**。 + +3. 将**双区域备份**开关切换为**关闭**。 + +4. 点击**保存**以保存更改。 + +### 执行手动备份 + +手动备份是用户发起的备份,使您能够根据需要将数据备份到已知状态,然后随时恢复到该状态。 + +> **注意** +> +> - 手动备份将无限期保留,直到您选择手动删除它们或您的账户关闭。 +> - TiDB Cloud Dedicated 集群删除后,其现有的手动备份将移至回收站,并保留在那里直到手动删除或您的账户关闭。 + +要对 TiDB Cloud Dedicated 集群应用手动备份,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 在右上角,点击 **...** > **手动备份**。 + +3. 在显示的对话框中,输入**名称**。 + +4. 点击**确认**。然后您的集群数据将被备份。 + +### 删除备份 + +#### 删除备份文件 + +要删除 TiDB Cloud Dedicated 集群的现有备份文件,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 找到要删除的相应备份文件,在**操作**列中点击 **...** > **删除**。 + +#### 删除正在运行的备份作业 + +要删除 TiDB Cloud Dedicated 集群的正在运行的备份作业,请按照与[**删除备份文件**](#删除备份文件)类似的过程操作。 + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 找到处于**等待中**或**运行中**状态的正在运行的备份作业,在**操作**列中点击 **...** > **删除**。 + +## 恢复 + +### 将数据恢复到新集群 + +> **注意** +> +> 从备份恢复 TiDB 集群时,恢复过程会保留原始时区设置而不覆盖它。 + +要从备份将 TiDB Cloud Dedicated 集群数据恢复到新集群,请执行以下步骤: + +1. 导航到集群的[**备份**](#查看备份页面)页面。 + +2. 点击**恢复**。设置窗口显示。 + +3. 在**恢复模式**中,选择**从区域恢复**,表示备份存储的区域。 + + > **注意** + > + > - **从区域恢复**的默认值与备份集群相同。 + +4. 在**恢复模式**中,选择将任意时间点的数据或选定的备份恢复到新集群。 + + +
+ + 要将备份保留期内任意时间点的数据恢复到新集群,请确保**备份设置**中的**时间点恢复**已开启,然后执行以下步骤: + + - 点击**选择时间点**。 + - 选择要恢复到的**日期**和**时间**。 + +
+ +
+ + 要将选定的备份恢复到新集群,请执行以下步骤: + + - 点击**选择备份名称**。 + - 选择要恢复到的备份。 + +
+
+ +5. 在**恢复到区域**中,选择与**备份设置**中配置的**主要区域**相同的区域。 + +6. 在**恢复**窗口中,您还可以根据需要进行以下更改: + + - 设置集群名称。 + - 更新集群的端口号。 + - 增加集群的节点数量、vCPU 和 RAM,以及存储。 + +7. 点击**恢复**。 + + 集群恢复过程开始,并显示**密码设置**对话框。 + +8. 在**密码设置**对话框中,设置连接集群的 root 密码,然后点击**保存**。 + +### 恢复已删除的集群 + +> **注意:** +> +> 您无法将已删除的集群恢复到任意时间点。您只能选择自动或手动备份进行恢复。 + +要从回收站恢复已删除的集群,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **回收站**。 +3. 在**回收站**页面上,找到要恢复的集群,在**操作**列中点击 **...**,然后点击**备份**。 +4. 在**备份**页面上,找到所需的备份时间,在**操作**列中点击 **...**,然后点击**恢复**。 +5. 在**恢复**页面上,为新集群指定一个名称,然后根据需要进行以下更改: + + - 更新集群的端口号。 + - 增加集群的节点数量、vCPU 和 RAM,以及存储。 + +6. 在**摘要**部分,检查恢复信息,然后点击**恢复**。 + + 集群恢复过程开始,并显示**密码设置**对话框。 + +7. 在**密码设置**对话框中,设置连接集群的 root 密码,然后点击**保存**。 diff --git a/tidb-cloud/branch-github-integration.md b/tidb-cloud/branch-github-integration.md new file mode 100644 index 000000000000..f6e9bb377038 --- /dev/null +++ b/tidb-cloud/branch-github-integration.md @@ -0,0 +1,170 @@ +--- +title: 集成 TiDB Cloud Serverless 分支功能(Beta)与 GitHub +summary: 了解如何将 TiDB Cloud Serverless 分支功能与 GitHub 集成。 +--- + +# 集成 TiDB Cloud Serverless 分支功能(Beta)与 GitHub + +> **注意:** +> +> 此集成基于 [TiDB Cloud Serverless 分支功能](/tidb-cloud/branch-overview.md)构建。在阅读本文档之前,请确保您已熟悉 TiDB Cloud Serverless 分支功能。 + +如果您使用 GitHub 进行应用程序开发,您可以将 TiDB Cloud Serverless 分支功能集成到 GitHub CI/CD 流程中,这样您就可以使用分支自动测试您的拉取请求,而不会影响生产数据库。 + +在集成过程中,系统会提示您安装 [TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) GitHub 应用程序。该应用程序可以根据 GitHub 仓库中的拉取请求自动管理 TiDB Cloud Serverless 分支。例如,当您创建拉取请求时,应用程序会为您的 TiDB Cloud Serverless 集群创建相应的分支,您可以在其中独立开发新功能或修复错误,而不会影响生产数据库。 + +本文档涵盖以下主题: + +1. 如何将 TiDB Cloud Serverless 分支功能与 GitHub 集成 +2. TiDB Cloud Branching 应用程序的工作原理 +3. 如何构建基于分支的 CI 工作流,使用分支而不是生产集群来测试每个拉取请求 + +## 开始之前 + +在进行集成之前,请确保您具备以下条件: + +- GitHub 账号 +- 用于您应用程序的 GitHub 仓库 +- [TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md) + +## 将 TiDB Cloud Serverless 分支功能与 GitHub 仓库集成 + +要将 TiDB Cloud Serverless 分支功能与 GitHub 仓库集成,请按照以下步骤操作: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 + +2. 在左侧导航栏中点击**分支**。 + +3. 在**分支**页面的右上角,点击**连接到 GitHub**。 + + - 如果您尚未登录 GitHub,系统会要求您先登录 GitHub。 + - 如果这是您第一次使用此集成,系统会要求您授权 **TiDB Cloud Branching** 应用程序。 + + + +4. 在**连接到 GitHub**对话框中,从**GitHub 账号**下拉列表中选择一个 GitHub 账号。 + + 如果列表中没有您的账号,请点击**安装其他账号**,然后按照屏幕上的说明安装账号。 + +5. 从**GitHub 仓库**下拉列表中选择您的目标仓库。如果列表较长,您可以通过输入名称来搜索仓库。 + +6. 点击**连接**以建立 TiDB Cloud Serverless 集群与 GitHub 仓库之间的连接。 + + + +## TiDB Cloud Branching 应用程序行为 + +将 TiDB Cloud Serverless 集群连接到 GitHub 仓库后,[TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) GitHub 应用程序可以自动管理该仓库中每个拉取请求对应的 TiDB Cloud Serverless 分支。以下列出了拉取请求变更的默认行为: + +| 拉取请求变更 | TiDB Cloud Branching 应用程序行为 | +|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 创建拉取请求 | 当您在仓库中创建拉取请求时,[TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) 应用程序会为您的 TiDB Cloud Serverless 集群创建一个分支。当 `branch.mode` 设置为 `reset` 时,分支名称遵循 `${github_branch_name}_${pr_id}` 格式。当 `branch.mode` 设置为 `reserve` 时,分支名称遵循 `${github_branch_name}_${pr_id}_${commit_sha}` 格式。请注意,分支数量有[限制](/tidb-cloud/branch-overview.md#limitations-and-quotas)。 | +| 向拉取请求推送新提交 | 当 `branch.mode` 设置为 `reset` 时,每次您向仓库的拉取请求推送新提交时,[TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) 应用程序都会重置 TiDB Cloud Serverless 分支。当 `branch.mode` 设置为 `reserve` 时,应用程序会为最新提交创建一个新分支。 | +| 关闭或合并拉取请求 | 当您关闭或合并拉取请求时,[TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) 应用程序会删除该拉取请求的分支。 | +| 重新打开拉取请求 | 当您重新打开拉取请求时,[TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) 应用程序会为该拉取请求的最新提交创建一个分支。 | + +## 配置 TiDB Cloud Branching 应用程序 + +要配置 [TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) 应用程序的行为,您可以在仓库的根目录中添加一个 `tidbcloud.yml` 文件,然后根据以下说明将所需的配置添加到该文件中。 + +### branch.blockList + +**类型:** 字符串数组。**默认值:** `[]`。 + +指定禁止 TiDB Cloud Branching 应用程序使用的 GitHub 分支,即使它们在 `allowList` 中。 + +```yaml +github: + branch: + blockList: + - ".*_doc" + - ".*_blackList" +``` + +### branch.allowList + +**类型:** 字符串数组。**默认值:** `[.*]`。 + +指定允许 TiDB Cloud Branching 应用程序使用的 GitHub 分支。 + +```yaml +github: + branch: + allowList: + - ".*_db" +``` + +### branch.mode + +**类型:** 字符串。**默认值:** `reset`。 + +指定 TiDB Cloud Branching 应用程序如何处理分支更新: + +- 如果设置为 `reset`,TiDB Cloud Branching 应用程序将使用最新数据更新现有分支。 +- 如果设置为 `reserve`,TiDB Cloud Branching 应用程序将为您的最新提交创建一个新分支。 + +```yaml +github: + branch: + mode: reset +``` + +### branch.autoDestroy + +**类型:** 布尔值。**默认值:** `true`。 + +如果设置为 `false`,当拉取请求被关闭或合并时,TiDB Cloud Branching 应用程序将不会删除 TiDB Cloud Serverless 分支。 + +```yaml +github: + branch: + autoDestroy: true +``` + +## 创建分支 CI 工作流 + +使用分支的最佳实践之一是创建分支 CI 工作流。通过该工作流,您可以在合并拉取请求之前使用 TiDB Cloud Serverless 分支而不是生产集群来测试您的代码。您可以在[这里](https://github.com/shiyuhang0/tidbcloud-branch-gorm-example)找到一个实际示例。 + +以下是创建工作流的主要步骤: + +1. [将 TiDB Cloud Serverless 分支功能与您的 GitHub 仓库集成](#将-tidb-cloud-serverless-分支功能与-github-仓库集成)。 + +2. 获取分支连接信息。 + + 您可以使用 [wait-for-tidbcloud-branch](https://github.com/tidbcloud/wait-for-tidbcloud-branch) action 来等待 TiDB Cloud Serverless 分支就绪并获取分支的连接信息。 + + 示例用法: + + ```yaml + steps: + - name: Wait for TiDB Cloud Serverless branch to be ready + uses: tidbcloud/wait-for-tidbcloud-branch@v0 + id: wait-for-branch + with: + token: ${{ secrets.GITHUB_TOKEN }} + public-key: ${{ secrets.TIDB_CLOUD_API_PUBLIC_KEY }} + private-key: ${{ secrets.TIDB_CLOUD_API_PRIVATE_KEY }} + + - name: Test with TiDB Cloud Serverless branch + run: | + echo "The host is ${{ steps.wait-for-branch.outputs.host }}" + echo "The user is ${{ steps.wait-for-branch.outputs.user }}" + echo "The password is ${{ steps.wait-for-branch.outputs.password }}" + ``` + + - `token`:GitHub 会自动创建一个 [GITHUB_TOKEN](https://docs.github.com/en/actions/security-guides/automatic-token-authentication) 密钥。您可以直接使用它。 + - `public-key` 和 `private-key`:TiDB Cloud [API 密钥](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication/API-Key-Management)。 + +3. 修改您的测试代码。 + + 修改您的测试代码以接受来自 GitHub Actions 的连接信息。例如,您可以通过环境变量接受连接信息,如[实际示例](https://github.com/shiyuhang0/tidbcloud-branch-gorm-example)所示。 + +## 下一步 + +通过以下示例了解如何使用分支 GitHub 集成: + +- [branching-gorm-example](https://github.com/tidbcloud/branching-gorm-example) +- [branching-django-example](https://github.com/tidbcloud/branching-django-example) +- [branching-rails-example](https://github.com/tidbcloud/branching-rails-example) + +您也可以在不使用分支 GitHub 集成的情况下构建分支 CI/CD 工作流。例如,您可以使用 [`setup-tidbcloud-cli`](https://github.com/tidbcloud/setup-tidbcloud-cli) 和 GitHub Actions 来自定义您的 CI/CD 工作流。 diff --git a/tidb-cloud/branch-manage.md b/tidb-cloud/branch-manage.md new file mode 100644 index 000000000000..d75218741b0d --- /dev/null +++ b/tidb-cloud/branch-manage.md @@ -0,0 +1,99 @@ +--- +title: 管理 TiDB Cloud Serverless 分支 +summary: 了解如何管理 TiDB Cloud Serverless 分支。 +--- + +# 管理 TiDB Cloud Serverless 分支 + +本文档介绍如何使用 [TiDB Cloud 控制台](https://tidbcloud.com) 管理 TiDB Cloud Serverless 分支。如需使用 TiDB Cloud CLI 进行管理,请参阅 [`ticloud branch`](/tidb-cloud/ticloud-branch-create.md)。 + +## 所需权限 + +- 要[创建分支](#创建分支)或[连接到分支](#连接到分支),你必须具有组织的 `Organization Owner` 角色或目标项目的 `Project Owner` 角色。 +- 要[查看项目中集群的分支](#查看分支),你必须属于该项目。 + +有关权限的更多信息,请参阅[用户角色](/tidb-cloud/manage-user-access.md#user-roles)。 + +## 创建分支 + +> **注意:** +> +> 你只能为 2023 年 7 月 5 日之后创建的 TiDB Cloud Serverless 集群创建分支。更多限制请参阅[限制和配额](/tidb-cloud/branch-overview.md#limitations-and-quotas)。 + +要创建分支,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 +2. 在左侧导航栏中点击**分支**。 +3. 在**分支**页面的右上角,点击**创建分支**。此时会显示一个对话框。 + + 或者,要从现有父分支创建分支,找到目标父分支所在的行,然后在**操作**列中点击 **...** > **创建分支**。 + +4. 在**创建分支**对话框中,配置以下选项: + + - **名称**:输入分支的名称。 + - **父分支**:选择原始集群或现有分支。`main` 代表当前集群。 + - **包含数据截至**:选择以下其中一项: + - **当前时间点**:从当前状态创建分支。 + - **指定日期和时间**:从指定时间创建分支。 + +5. 点击**创建**。 + +根据集群中的数据大小,分支创建将在几分钟内完成。 + +## 查看分支 + +要查看集群的分支,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 +2. 在左侧导航栏中点击**分支**。 + + 集群的分支列表将显示在右侧窗格中。 + +## 连接到分支 + +要连接到分支,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 +2. 在左侧导航栏中点击**分支**。 +3. 在要连接的目标分支所在行中,点击**操作**列中的 **...**。 +4. 在下拉列表中点击**连接**。此时会显示连接信息对话框。 +5. 点击**生成密码**或**重置密码**以创建或重置 root 密码。 +6. 使用连接信息连接到分支。 + +或者,你也可以从集群概览页面获取连接字符串: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 +2. 点击右上角的**连接**。 +3. 在`分支`下拉列表中选择要连接的分支。 +4. 点击**生成密码**或**重置密码**以创建或重置 root 密码。 +5. 使用连接信息连接到分支。 + +## 删除分支 + +要删除分支,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 +2. 在左侧导航栏中点击**分支**。 +3. 在要删除的目标分支所在行中,点击**操作**列中的 **...**。 +4. 在下拉列表中点击**删除**。 +5. 确认删除。 + +## 重置分支 + +重置分支会将其与父分支的最新数据同步。 + +> **注意:** +> +> 此操作不可逆。在重置分支之前,请确保已备份任何重要数据。 + +要重置分支,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 +2. 在左侧导航栏中点击**分支**。 +3. 在要重置的目标分支所在行中,点击**操作**列中的 **...**。 +4. 在下拉列表中点击**重置**。 +5. 确认重置。 + +## 下一步 + +- [将 TiDB Cloud Serverless 分支集成到 GitHub CI/CD 流程中](/tidb-cloud/branch-github-integration.md) diff --git a/tidb-cloud/branch-overview.md b/tidb-cloud/branch-overview.md new file mode 100644 index 000000000000..a6c2d65d77a2 --- /dev/null +++ b/tidb-cloud/branch-overview.md @@ -0,0 +1,53 @@ +--- +title: TiDB Cloud Serverless 分支(Beta)概述 +summary: 了解 TiDB Cloud Serverless 分支的概念。 +--- + +# TiDB Cloud Serverless 分支(Beta)概述 + +TiDB Cloud 允许您为 TiDB Cloud Serverless 集群创建分支。集群的分支是一个独立的实例,包含从原始集群分叉的数据副本。它提供了一个隔离的环境,让您可以自由实验而不用担心影响原始集群。 + +通过 TiDB Cloud Serverless 分支,开发人员可以并行工作,快速迭代新功能,在不影响生产数据库的情况下排查问题,并在需要时轻松回滚更改。此功能简化了开发和部署过程,同时确保生产数据库具有高度的稳定性和可靠性。 + +## 实现方式 + +创建集群的分支时,分支中的数据会在特定时间点从原始集群或其父分支分叉。这意味着之后在父分支或子分支中所做的更改不会相互同步。 + +为确保快速且无缝的分支创建,TiDB Cloud Serverless 使用写时复制技术在原始集群及其分支之间共享数据。此过程通常在几分钟内完成,用户无法察觉,确保不会影响原始集群的性能。 + +## 使用场景 + +您可以轻松快速地创建分支以获得隔离的数据环境。在以下场景中,当多个开发人员或团队需要独立工作、测试更改、修复错误、尝试新功能或推出更新而不影响生产数据库时,分支特别有用。 + +- 功能开发:开发人员可以在隔离环境中开发新功能,而不会影响生产数据库。每个功能都可以有自己的分支,允许快速迭代和实验,而不会影响其他正在进行的工作。 + +- 错误修复:开发人员可以创建专门用于修复特定错误的分支,测试修复方案,然后在验证后合并回去,而不会给生产数据库带来新的问题。 + +- 实验:在开发新功能或进行更改时,开发人员可以创建分支来尝试不同的方法或配置。这使他们能够比较各种选项,收集数据,并在更改合并到生产数据库之前做出明智的决定。 + +- 性能优化:有时会进行数据库更改以提高性能。通过分支,开发人员可以在隔离环境中实验和微调各种配置、索引或算法,以找到最有效的解决方案。 + +- 测试和暂存:团队可以创建用于测试和暂存的分支。它为质量保证、用户验收测试或暂存定制提供了一个受控环境,然后再将更改合并到生产数据库中。 + +- 并行开发:不同的团队或开发人员可以同时处理不同的项目。每个项目都可以有自己的分支,实现独立开发和实验,同时仍然能够将更改合并回生产数据库。 + +## 限制和配额 + +目前,TiDB Cloud Serverless 分支处于 beta 阶段,免费使用。 + +- 对于 TiDB Cloud 中的每个组织,默认情况下您最多可以在所有集群中创建五个 TiDB Cloud Serverless 分支。集群的分支将在与集群相同的区域中创建,您不能为受限集群或大于 100 GiB 的集群创建分支。 + +- 对于免费集群的每个分支,允许 10 GiB 存储空间。对于可扩展集群的每个分支,允许 100 GiB 存储空间。一旦达到存储限制,此分支上的读写操作将被限制,直到您减少存储空间。 + +- 如果您的集群有带 TiFlash 副本的表,这些副本在您创建新分支后将暂时不可用,因为 TiFlash 需要重建副本数据。 + +- 当从特定时间点[创建分支](/tidb-cloud/branch-manage.md#create-a-branch)时: + + - 对于免费集群的分支,您可以选择过去 24 小时内的任何时间。 + - 对于可扩展集群的分支,您可以选择过去 14 天内的任何时间。 + +如果您需要更多配额,请[联系 TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +## 下一步 + +- [了解如何管理分支](/tidb-cloud/branch-manage.md) diff --git a/tidb-cloud/built-in-monitoring.md b/tidb-cloud/built-in-monitoring.md new file mode 100644 index 000000000000..c9bea10af332 --- /dev/null +++ b/tidb-cloud/built-in-monitoring.md @@ -0,0 +1,129 @@ +--- +title: TiDB Cloud 内置指标 +summary: 了解如何查看 TiDB Cloud 内置指标并理解这些指标的含义。 +--- + +# TiDB Cloud 内置指标 + +TiDB Cloud 在指标页面上收集和显示集群的一整套标准指标。通过查看这些指标,您可以轻松识别性能问题并确定当前的数据库部署是否满足您的需求。 + +## 查看指标页面 + +要在**指标**页面上查看指标,请执行以下步骤: + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面上,点击目标集群的名称进入其概览页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 在左侧导航栏中,点击**监控** > **指标**。 + +## 指标保留策略 + +对于 TiDB Cloud Dedicated 集群和 TiDB Cloud Serverless 集群,指标数据保留 7 天。 + +## TiDB Cloud Dedicated 集群的指标 + +以下部分说明了 TiDB Cloud Dedicated 集群的**指标**页面上的指标。 + +### 概览 + +| 指标名称 | 标签 | 描述 | +| :------------| :------| :-------------------------------------------- | +| Database Time by SQL types | database time, {SQL type} | database time:每秒总数据库时间。
{SQL type}:每秒 SQL 语句消耗的数据库时间,按 SQL 类型收集,如 `SELECT`、`INSERT` 和 `UPDATE`。 | +| Query Per Second | {SQL type} | 所有 TiDB 实例中每秒执行的 SQL 语句数量,按 SQL 类型收集,如 `SELECT`、`INSERT` 和 `UPDATE`。 | +| Query Duration | avg-{SQL type}, 99-{SQL type} | 从客户端向 TiDB 发送请求到 TiDB 执行请求并将结果返回给客户端的持续时间。通常,客户端请求以 SQL 语句的形式发送;但是,此持续时间可以包括执行 `COM_PING`、`COM_SLEEP`、`COM_STMT_FETCH` 和 `COM_SEND_LONG_DATA` 等命令的时间。TiDB 支持多查询,这意味着客户端可以一次发送多个 SQL 语句,如 `select 1; select 1; select 1;`。在这种情况下,此查询的总执行时间包括所有 SQL 语句的执行时间。 | +| Failed Queries | All, {Error type} @ {instance} | 每分钟在每个 TiDB 实例上根据 SQL 语句执行错误的错误类型统计(如语法错误和主键冲突)。它包含错误发生的模块和错误代码。 | +| Command Per Second | Query, StmtExecute, and StmtPrepare | 所有 TiDB 实例每秒处理的命令数量,基于命令类型。 | +| Queries Using Plan Cache OPS | hit, miss | hit:所有 TiDB 实例中每秒使用计划缓存的查询数量。
miss:所有 TiDB 实例中每秒未命中计划缓存的查询数量。 | +| Transaction Per Second | {types}-{transaction model} | 每秒执行的事务数量。 | +| Transaction Duration | avg-{transaction model}, 99-{transaction model} | 事务的平均或 99 百分位持续时间。 | +| Connection Count | All, active connection | All:到所有 TiDB 实例的连接数量。
Active connections:到所有 TiDB 实例的活动连接数量。 | +| Disconnection Count | {instance}-{result} | 每个 TiDB 实例断开连接的客户端数量。 | + +### 高级 + +| 指标名称 | 标签 | 描述 | +| :------------| :------| :-------------------------------------------- | +| Average Idle Connection Duration | avg-in-txn, avg-not-in-txn | 连接空闲持续时间表示连接处于空闲状态的持续时间。
avg-in-txn:连接在事务内时的平均空闲持续时间。
avg-not-in-txn:连接不在事务内时的平均空闲持续时间。 | +| Get Token Duration | avg, 99 | 获取 SQL 语句令牌所消耗的平均或 99 百分位持续时间。 | +| Parse Duration | avg, 99 | 解析 SQL 语句所消耗的平均或 99 百分位持续时间。 | +| Compile Duration | avg, 99 | 将解析的 SQL AST 编译为执行计划所消耗的平均或 99 百分位持续时间。 | +| Execute Duration | avg, 99 | 执行 SQL 语句执行计划所消耗的平均或 99 百分位持续时间。 | +| Average TiDB KV Request Duration | {Request Type} | 所有 TiDB 实例中执行 KV 请求所消耗的平均时间,基于请求类型,如 `Get`、`Prewrite` 和 `Commit`。 | +| Average TiKV gRPC Duration | {Request Type} | 所有 TiKV 实例中执行 gRPC 请求所消耗的平均时间,基于请求类型,如 `kv_get`、`kv_prewrite` 和 `kv_commit`。 | +| Average / P99 PD TSO Wait/RPC Duration | wait-avg/99, rpc-avg/99 | Wait:所有 TiDB 实例中等待 PD 返回 TSO 的平均或 99 百分位持续时间。
RPC:所有 TiDB 实例中从发送 TSO 请求到 PD 到接收 TSO 的平均时间或 99 百分位持续时间。 | +| Average / P99 Storage Async Write Duration | avg, 99 | 异步写入所消耗的平均或 99 百分位持续时间。平均存储异步写入持续时间 = 平均存储持续时间 + 平均应用持续时间。 | +| Average / P99 Store Duration | avg, 99 | 异步写入期间存储循环所消耗的平均或 99 百分位持续时间。 | +| Average / P99 Apply Duration | avg, 99 | 异步写入期间应用循环所消耗的平均或 99 百分位持续时间。 | +| Average / P99 Append Log Duration | avg, 99 | Raft 追加日志所消耗的平均或 99 百分位持续时间。 | +| Average / P99 Commit Log Duration | avg, 99 | Raft 提交日志所消耗的平均或 99 百分位持续时间。 | +| Average / P99 Apply Log Duration | avg, 99 | Raft 应用日志所消耗的平均或 99 百分位持续时间。 | + +### 服务器 + +| 指标名称 | 标签 | 描述 | +| :------------| :------| :-------------------------------------------- | +| TiDB Uptime | node | 每个 TiDB 节点自上次重启以来的运行时间。 | +| TiDB CPU Usage | node, limit | 每个 TiDB 节点的 CPU 使用统计或上限。 | +| TiDB Memory Usage | node, limit | 每个 TiDB 节点的内存使用统计或上限。 | +| TiKV Uptime | node | 每个 TiKV 节点自上次重启以来的运行时间。 | +| TiKV CPU Usage | node, limit | 每个 TiKV 节点的 CPU 使用统计或上限。 | +| TiKV Memory Usage | node, limit | 每个 TiKV 节点的内存使用统计或上限。 | +| TiKV IO Bps | node-write, node-read | 每个 TiKV 节点读写的每秒总输入/输出字节数。 | +| TiKV Storage Usage | node, limit | 每个 TiKV 节点的存储使用统计或上限。 | +| TiFlash Uptime | node | 每个 TiFlash 节点自上次重启以来的运行时间。 | +| TiFlash CPU Usage | node, limit | 每个 TiFlash 节点的 CPU 使用统计或上限。 | +| TiFlash Memory Usage | node, limit | 每个 TiFlash 节点的内存使用统计或上限。 | +| TiFlash IO MBps | node-write, node-read | 每个 TiFlash 节点读写的总字节数。 | +| TiFlash Storage Usage | node, limit | 每个 TiFlash 节点的存储使用统计或上限。 | + +## TiDB Cloud Serverless 集群的指标 + +**指标**页面为 TiDB Cloud Serverless 集群提供了两个标签页: + +- **集群状态**:显示集群级别的主要指标。 +- **数据库状态**:显示数据库级别的主要指标。 + +### 集群状态 + +下表说明了**集群状态**标签页下的集群级别主要指标。 + +| 指标名称 | 标签 | 描述 | +| :------------| :------| :-------------------------------------------- | +| Request Units | RU per second | 请求单元(RU)是用于跟踪查询或事务资源消耗的度量单位。除了您运行的查询外,后台活动也会消耗请求单元,因此当 QPS 为 0 时,每秒请求单元可能不为零。 | +| Used Storage Size | Row-based storage, Columnar storage | 行存储的大小和列存储的大小。 | +| Query Per Second | All, {SQL type} | 每秒执行的 SQL 语句数量,按 SQL 类型收集,如 `SELECT`、`INSERT` 和 `UPDATE`。 | +| Average Query Duration | All, {SQL type} | 从客户端向 TiDB Cloud Serverless 集群发送请求到集群执行请求并将结果返回给客户端的持续时间。 | +| Failed Query | All | 每秒 SQL 语句执行错误的数量。 | +| Transaction Per Second | All | 每秒执行的事务数量。 | +| Average Transaction Duration | All | 事务的平均执行持续时间。 | +| Total Connection | All | 到 TiDB Cloud Serverless 集群的连接数量。 | + +### 数据库状态 + +下表说明了**数据库状态**标签页下的数据库级别主要指标。 + +| 指标名称 | 标签 | 描述 | +| :------------| :------| :-------------------------------------------- | +| QPS Per DB | All, {Database name} | 每个数据库每秒执行的 SQL 语句数量,按 SQL 类型收集,如 `SELECT`、`INSERT` 和 `UPDATE`。 | +| Average Query Duration Per DB | All, {Database name} | 从客户端向数据库发送请求到数据库执行请求并将结果返回给客户端的持续时间。| +| Failed Query Per DB | All, {Database name} | 每个数据库每秒根据 SQL 语句执行错误的错误类型统计。| + +## 常见问题 + +**1. 为什么此页面上的某些面板是空的?** + +如果面板没有提供任何指标,可能的原因如下: + +- 相应集群的工作负载没有触发此指标。例如,在没有失败查询的情况下,失败查询指标始终为空。 +- 集群版本较低。您需要升级到最新版本的 TiDB 才能看到这些指标。 + +如果排除了所有这些原因,您可以联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)进行故障排查。 + +**2. 为什么在罕见情况下指标可能不连续?** + +在某些罕见情况下,指标可能会丢失,例如当指标系统承受高压力时。 + +如果您遇到此问题,可以联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)进行故障排查。 diff --git a/tidb-cloud/changefeed-overview.md b/tidb-cloud/changefeed-overview.md new file mode 100644 index 000000000000..4562e6ffe8ff --- /dev/null +++ b/tidb-cloud/changefeed-overview.md @@ -0,0 +1,109 @@ +--- +title: Changefeed +summary: TiDB Cloud changefeed 帮助你将数据从 TiDB Cloud 流式传输到其他数据服务。 +--- + +# Changefeed + +TiDB Cloud changefeed 帮助你将数据从 TiDB Cloud 流式传输到其他数据服务。目前,TiDB Cloud 支持将数据流式传输到 Apache Kafka、MySQL、TiDB Cloud 和云存储。 + +> **注意:** +> +> - 目前,TiDB Cloud 每个集群最多允许 100 个 changefeed。 +> - 目前,TiDB Cloud 每个 changefeed 最多允许 100 个表过滤规则。 +> - 对于 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless),changefeed 功能不可用。 + +## 查看 Changefeed 页面 + +要访问 changefeed 功能,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **Changefeed**。此时会显示 changefeed 页面。 + +在 **Changefeed** 页面上,你可以创建 changefeed,查看现有 changefeed 列表,以及操作现有的 changefeed(如扩缩容、暂停、恢复、编辑和删除 changefeed)。 + +## 创建 changefeed + +要创建 changefeed,请参考以下教程: + +- [导出到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md) +- [导出到 MySQL](/tidb-cloud/changefeed-sink-to-mysql.md) +- [导出到 TiDB Cloud](/tidb-cloud/changefeed-sink-to-tidb-cloud.md) +- [导出到云存储](/tidb-cloud/changefeed-sink-to-cloud-storage.md) + +## 查询 Changefeed RCU + +1. 导航到目标 TiDB 集群的 [**Changefeed**](#查看-changefeed-页面) 页面。 +2. 找到要查询的相应 changefeed,然后在**操作**列中点击 **...** > **查看**。 +3. 你可以在页面的**规格**区域看到当前的 TiCDC 复制容量单位(RCU)。 + +## 扩缩容 changefeed + +你可以通过扩容或缩容 changefeed 来更改其 TiCDC 复制容量单位(RCU)。 + +> **注意:** +> +> - 要扩缩容集群的 changefeed,请确保该集群的所有 changefeed 都是在 2023 年 3 月 28 日之后创建的。 +> - 如果集群有在 2023 年 3 月 28 日之前创建的 changefeed,则该集群的现有 changefeed 和新创建的 changefeed 都不支持扩容或缩容。 + +1. 导航到目标 TiDB 集群的 [**Changefeed**](#查看-changefeed-页面) 页面。 +2. 找到要扩缩容的相应 changefeed,然后在**操作**列中点击 **...** > **扩缩容**。 +3. 选择新的规格。 +4. 点击**提交**。 + +完成扩缩容过程大约需要 10 分钟(在此期间 changefeed 正常工作),切换到新规格需要几秒钟(在此期间 changefeed 将自动暂停和恢复)。 + +## 暂停或恢复 changefeed + +1. 导航到目标 TiDB 集群的 [**Changefeed**](#查看-changefeed-页面) 页面。 +2. 找到要暂停或恢复的相应 changefeed,然后在**操作**列中点击 **...** > **暂停/恢复**。 + +## 编辑 changefeed + +> **注意:** +> +> TiDB Cloud 目前仅允许编辑处于暂停状态的 changefeed。 + +1. 导航到目标 TiDB 集群的 [**Changefeed**](#查看-changefeed-页面) 页面。 +2. 找到要暂停的 changefeed,然后在**操作**列中点击 **...** > **暂停**。 +3. 当 changefeed 状态变为 `已暂停` 时,点击 **...** > **编辑**以编辑相应的 changefeed。 + + TiDB Cloud 默认填充 changefeed 配置。你可以修改以下配置: + + - Apache Kafka 导出:所有配置。 + - MySQL 导出:**MySQL 连接**、**表过滤器**和**事件过滤器**。 + - TiDB Cloud 导出:**TiDB Cloud 连接**、**表过滤器**和**事件过滤器**。 + - 云存储导出:**存储端点**、**表过滤器**和**事件过滤器**。 + +4. 编辑配置后,点击 **...** > **恢复**以恢复相应的 changefeed。 + +## 删除 changefeed + +1. 导航到目标 TiDB 集群的 [**Changefeed**](#查看-changefeed-页面) 页面。 +2. 找到要删除的相应 changefeed,然后在**操作**列中点击 **...** > **删除**。 + +## Changefeed 计费 + +要了解 TiDB Cloud 中 changefeed 的计费情况,请参见 [Changefeed 计费](/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md)。 + +## Changefeed 状态 + +复制任务的状态表示复制任务的运行状态。在运行过程中,复制任务可能因错误而失败,被手动暂停、恢复,或达到指定的 `TargetTs`。这些行为可能导致复制任务状态的变化。 + +状态说明如下: + +- `CREATING`:正在创建复制任务。 +- `RUNNING`:复制任务正常运行,checkpoint-ts 正常推进。 +- `EDITING`:正在编辑复制任务。 +- `PAUSING`:正在暂停复制任务。 +- `PAUSED`:复制任务已暂停。 +- `RESUMING`:正在恢复复制任务。 +- `DELETING`:正在删除复制任务。 +- `DELETED`:复制任务已删除。 +- `WARNING`:复制任务返回警告。由于一些可恢复的错误,复制无法继续。处于此状态的 changefeed 会一直尝试恢复,直到状态转为 `RUNNING`。处于此状态的 changefeed 会阻塞 [GC 操作](https://docs.pingcap.com/tidb/stable/garbage-collection-overview)。 +- `FAILED`:复制任务失败。由于某些错误,复制任务无法恢复且无法自动恢复。如果在增量数据的垃圾回收(GC)之前解决了问题,你可以手动恢复失败的 changefeed。增量数据的默认生存时间(TTL)为 24 小时,这意味着 GC 机制不会删除 changefeed 中断后 24 小时内的任何数据。 diff --git a/tidb-cloud/changefeed-sink-to-apache-kafka.md b/tidb-cloud/changefeed-sink-to-apache-kafka.md new file mode 100644 index 000000000000..7e17d043f4ad --- /dev/null +++ b/tidb-cloud/changefeed-sink-to-apache-kafka.md @@ -0,0 +1,112 @@ +--- +title: 同步数据到 Apache Kafka +summary: 本文档说明如何创建 changefeed 将数据从 TiDB Cloud 同步到 Apache Kafka。它包括限制、前提条件以及为 Apache Kafka 配置 changefeed 的步骤。该过程涉及设置网络连接、为 Kafka ACL 授权添加权限以及配置 changefeed 规格。 +--- + +# 同步数据到 Apache Kafka + +本文档描述如何创建 changefeed 将数据从 TiDB Cloud 同步到 Apache Kafka。 + +> **注意:** +> +> - 要使用 changefeed 功能,请确保你的 TiDB Cloud Dedicated 集群版本是 v6.1.3 或更高版本。 +> - 对于 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless),changefeed 功能不可用。 + +## 限制 + +- 对于每个 TiDB Cloud 集群,你最多可以创建 100 个 changefeed。 +- 目前,TiDB Cloud 不支持上传自签名 TLS 证书来连接 Kafka broker。 +- 由于 TiDB Cloud 使用 TiCDC 建立 changefeed,它具有与 TiCDC 相同的[限制](https://docs.pingcap.com/tidb/stable/ticdc-overview#unsupported-scenarios)。 +- 如果要复制的表没有主键或非空唯一索引,在某些重试场景中,由于复制过程中缺少唯一约束,可能会导致下游插入重复数据。 +- 如果你选择 Private Link 或 Private Service Connect 作为网络连接方式,请确保你的 TiDB 集群版本满足以下要求: + + - 对于 v6.5.x:版本 v6.5.9 或更高版本 + - 对于 v7.1.x:版本 v7.1.4 或更高版本 + - 对于 v7.5.x:版本 v7.5.1 或更高版本 + - 对于 v8.1.x:支持所有 v8.1.x 及更高版本 +- 如果你想使用 Debezium 作为数据格式,请确保你的 TiDB 集群版本是 v8.1.0 或更高版本。 +- 对于 Kafka 消息的分区分布,请注意以下事项: + + - 如果你想通过指定索引名称将变更日志按主键或索引值分发到 Kafka 分区,请确保你的 TiDB 集群版本是 v7.5.0 或更高版本。 + - 如果你想将变更日志按列值分发到 Kafka 分区,请确保你的 TiDB 集群版本是 v7.5.0 或更高版本。 + +## 前提条件 + +在创建 changefeed 将数据同步到 Apache Kafka 之前,你需要完成以下前提条件: + +- 设置网络连接 +- 为 Kafka ACL 授权添加权限 + +### 网络 + +确保你的 TiDB 集群可以连接到 Apache Kafka 服务。你可以选择以下连接方式之一: + +- Private Connect:适用于避免 VPC CIDR 冲突并满足安全合规要求,但会产生额外的[私有数据链路成本](/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md#私有数据链路成本)。 +- VPC 对等连接:适用于成本效益高的选项,但需要管理潜在的 VPC CIDR 冲突和安全考虑。 +- 公共 IP:适用于快速设置。 + + +
+ +Private Connect 利用云提供商的 **Private Link** 或 **Private Service Connect** 技术,使你的 VPC 中的资源能够使用私有 IP 地址连接到其他 VPC 中的服务,就像这些服务直接托管在你的 VPC 中一样。 + +TiDB Cloud 目前仅支持自托管 Kafka 的 Private Connect。它不支持直接集成 MSK、Confluent Kafka 或其他 Kafka SaaS 服务。要通过 Private Connect 连接到这些 Kafka SaaS 服务,你可以部署 [kafka-proxy](https://github.com/grepplabs/kafka-proxy) 作为中介,有效地将 Kafka 服务公开为自托管 Kafka。有关详细示例,请参见[在 Google Cloud 中使用 Kafka-proxy 设置自托管 Kafka Private Service Connect](/tidb-cloud/setup-self-hosted-kafka-private-service-connect.md#使用-kafka-proxy-设置自托管-kafka-private-service-connect)。这种设置在所有 Kafka SaaS 服务中都类似。 + +- 如果你的 Apache Kafka 服务托管在 AWS 中,请按照[在 AWS 中设置自托管 Kafka Private Link 服务](/tidb-cloud/setup-aws-self-hosted-kafka-private-link-service.md)确保网络连接正确配置。设置完成后,在 TiDB Cloud 控制台中提供以下信息以创建 changefeed: + + - Kafka 广播监听器模式中的 ID + - 端点服务名称 + - 引导端口 + +- 如果你的 Apache Kafka 服务托管在 Google Cloud 中,请按照[在 Google Cloud 中设置自托管 Kafka Private Service Connect](/tidb-cloud/setup-self-hosted-kafka-private-service-connect.md)确保网络连接正确配置。设置完成后,在 TiDB Cloud 控制台中提供以下信息以创建 changefeed: + + - Kafka 广播监听器模式中的 ID + - 服务附件 + - 引导端口 + +- 如果你的 Apache Kafka 服务托管在 Azure 中,请按照[在 Azure 中设置自托管 Kafka Private Link 服务](/tidb-cloud/setup-azure-self-hosted-kafka-private-link-service.md)确保网络连接正确配置。设置完成后,在 TiDB Cloud 控制台中提供以下信息以创建 changefeed: + + - Kafka 广播监听器模式中的 ID + - Private Link 服务的别名 + - 引导端口 + +
+
+ +如果你的 Apache Kafka 服务在没有互联网访问的 AWS VPC 中,请执行以下步骤: + +1. [设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md),连接 Apache Kafka 服务的 VPC 和你的 TiDB 集群。 +2. 修改与 Apache Kafka 服务关联的安全组的入站规则。 + + 你必须将你的 TiDB Cloud 集群所在区域的 CIDR 添加到入站规则中。CIDR 可以在 **VPC 对等连接**页面找到。这样做可以允许流量从你的 TiDB 集群流向 Kafka broker。 + +3. 如果 Apache Kafka URL 包含主机名,你需要允许 TiDB Cloud 能够解析 Apache Kafka broker 的 DNS 主机名。 + + 1. 按照[为 VPC 对等连接启用 DNS 解析](https://docs.aws.amazon.com/vpc/latest/peering/vpc-peering-dns.html)中的步骤操作。 + 2. 启用**接受者 DNS 解析**选项。 + +如果你的 Apache Kafka 服务在没有互联网访问的 Google Cloud VPC 中,请执行以下步骤: + +1. [设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md),连接 Apache Kafka 服务的 VPC 和你的 TiDB 集群。 +2. 修改 Apache Kafka 所在 VPC 的入站防火墙规则。 + + 你必须将你的 TiDB Cloud 集群所在区域的 CIDR 添加到入站防火墙规则中。CIDR 可以在 **VPC 对等连接**页面找到。这样做可以允许流量从你的 TiDB 集群流向 Kafka broker。 + +
+
+ +如果你想为你的 Apache Kafka 服务提供公共 IP 访问,请为所有 Kafka broker 分配公共 IP 地址。 + +不建议在生产环境中使用公共 IP。 + +
+
+ +### Kafka ACL 授权 + +要允许 TiDB Cloud changefeed 将数据同步到 Apache Kafka 并自动创建 Kafka 主题,请确保在 Kafka 中添加了以下权限: + +- 为 Kafka 中的主题资源类型添加了 `Create` 和 `Write` 权限。 +- 为 Kafka 中的集群资源类型添加了 `DescribeConfigs` 权限。 + +例如,如果你的 Kafka 集群在 Confluent Cloud 中,你可以参见 Confluent 文档中的[资源](https://docs.confluent.io/platform/current/kafka/authorization.html#resources)和[添加 ACL](https://docs.confluent.io/platform/current/kafka/authorization.html#adding-acls)了解更多信息。 diff --git a/tidb-cloud/changefeed-sink-to-apache-pulsar.md b/tidb-cloud/changefeed-sink-to-apache-pulsar.md new file mode 100644 index 000000000000..80183ca5195e --- /dev/null +++ b/tidb-cloud/changefeed-sink-to-apache-pulsar.md @@ -0,0 +1,189 @@ +--- +title: 导出到 Apache Pulsar +summary: 本文档说明如何创建 changefeed 将数据从 TiDB Cloud 流式传输到 Apache Pulsar。它包括限制、前提条件以及为 Apache Pulsar 配置 changefeed 的步骤。该过程涉及设置网络连接和配置 changefeed 规格。 +--- + +# 导出到 Apache Pulsar + +本文档描述如何创建 changefeed 将数据从 TiDB Cloud 流式传输到 Apache Pulsar。 + +> **注意:** +> +> - 要使用 changefeed 功能将数据复制到 Apache Pulsar,请确保你的 TiDB Cloud Dedicated 集群版本为 v7.5.1 或更高版本。 +> - 对于 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless),changefeed 功能不可用。 + +## 限制 + +- 每个 TiDB Cloud 集群最多可以创建 100 个 changefeed。 +- 目前,TiDB Cloud 不支持上传自签名 TLS 证书来连接 Pulsar broker。 +- 由于 TiDB Cloud 使用 TiCDC 建立 changefeed,因此它具有与 [TiCDC 相同的限制](https://docs.pingcap.com/tidb/stable/ticdc-overview#unsupported-scenarios)。 +- 如果要复制的表没有主键或非空唯一索引,在某些重试场景下,复制过程中缺少唯一约束可能导致下游插入重复数据。 +- 目前,TiCDC 不会自动创建 Pulsar 主题。在向主题发送事件之前,请确保该主题在 Pulsar 中存在。 + +## 前提条件 + +在创建 changefeed 将数据流式传输到 Apache Pulsar 之前,你需要完成以下前提条件: + +- 设置网络连接 +- 添加 Pulsar ACL 授权的权限 +- 在 Apache Pulsar 中手动创建主题,或在 Apache Pulsar broker 配置中启用 [`allowAutoTopicCreation`](https://pulsar.apache.org/reference/#/4.0.x/config/reference-configuration-broker?id=allowautotopiccreation) + +### 网络 + +确保你的 TiDB 集群可以连接到 Apache Pulsar 服务。你可以选择以下连接方法之一: + +- VPC 对等连接:需要进行网络规划以避免潜在的 VPC CIDR 冲突,并考虑安全问题。 +- 公共 IP:适用于 Pulsar 公布公共 IP 的设置。此方法不建议在生产环境中使用,需要仔细考虑安全问题。 + + +
+ +如果你的 Apache Pulsar 服务位于没有互联网访问的 AWS VPC 中,请执行以下步骤: + +1. 在 Apache Pulsar 服务的 VPC 和你的 TiDB 集群之间[设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)。 +2. 修改与 Apache Pulsar 服务关联的安全组的入站规则。 + + 你必须将 TiDB Cloud 集群所在区域的 CIDR 添加到入站规则中。可以在 **VPC 对等连接**页面找到 CIDR。这样做可以允许流量从你的 TiDB 集群流向 Pulsar broker。 + +3. 如果 Apache Pulsar URL 包含主机名,你需要允许 TiDB Cloud 解析 Apache Pulsar broker 的 DNS 主机名。 + + 1. 按照[为 VPC 对等连接启用 DNS 解析](https://docs.aws.amazon.com/vpc/latest/peering/vpc-peering-dns.html)中的步骤操作。 + 2. 启用**接受者 DNS 解析**选项。 + +如果你的 Apache Pulsar 服务位于没有互联网访问的 Google Cloud VPC 中,请执行以下步骤: + +1. 在 Apache Pulsar 服务的 VPC 和你的 TiDB 集群之间[设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)。 +2. 修改 Apache Pulsar 所在 VPC 的入站防火墙规则。 + + 你必须将 TiDB Cloud 集群所在区域的 CIDR 添加到入站防火墙规则中。可以在 **VPC 对等连接**页面找到 CIDR。这样做可以允许流量从你的 TiDB 集群流向 Pulsar broker。 + +
+
+ +如果你想为 Apache Pulsar 服务提供公共 IP 访问,请为所有 Pulsar broker 分配公共 IP 地址。 + +**不建议**在生产环境中使用公共 IP。 + +
+
+ +### 在 Apache Pulsar 中创建主题 + +目前,TiCDC 不会自动创建 Pulsar 主题。你需要在创建 changefeed 之前在 Pulsar 中创建所需的主题。主题的数量和命名取决于你首选的分发模式: + +- 要将所有 Pulsar 消息分发到单个主题:创建一个具有你首选名称的主题。 +- 要将每个表的 Pulsar 消息分发到专用主题,为每个要复制的表创建格式为 `<主题前缀><数据库名称><分隔符><表名称><主题后缀>` 的主题。 +- 要将数据库的 Pulsar 消息分发到专用主题,为每个要复制的数据库创建格式为 `<主题前缀><数据库名称><主题后缀>` 的主题。 + +根据你的配置,你可能还需要一个用于非行事件(如架构更改)的默认主题。 + +更多信息,请参见 Apache Pulsar 文档中的[如何创建主题](https://pulsar.apache.org/docs/4.0.x/tutorials-topic/)。 + +## 步骤 1. 打开 Apache Pulsar 的 Changefeed 页面 + +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com)。 +2. 导航到将作为 changefeed 事件源的 TiDB 集群的概览页面,然后在左侧导航栏中点击**数据** > **Changefeed**。 +3. 点击**创建 Changefeed**。 + +## 步骤 2. 配置 changefeed 目标 + +1. 在**目标**部分,选择 **Pulsar**。 +2. 在**连接**部分,输入以下信息: + + - **目标协议**:选择 **Pulsar** 或 **Pulsar+SSL**。 + - **连接方式**:根据你计划如何连接到 Pulsar 端点,选择 **VPC 对等连接**或**公共**。 + - **Pulsar Broker**:输入 Pulsar broker 的端点。使用冒号分隔端口和域名或 IP 地址,例如 `example.org:6650`。 + +3. 在**认证**部分,根据你的 Pulsar 认证配置选择 **Auth Type** 选项。根据你的选择输入所需的凭据信息。 +4. 可选:在**高级设置**部分,配置其他设置: + + - **压缩**:为此 changefeed 中的数据选择可选的压缩算法。 + - **每批最大消息数**和**最大发布延迟**:指定发送到 Pulsar 的事件消息的批处理。**每批最大消息数**设置每批的最大消息数,而**最大发布延迟**设置发送批次前的最大等待时间。 + - **连接超时**:调整建立到 Pulsar 的 TCP 连接的超时时间。 + - **操作超时**:调整使用 TiCDC Pulsar 客户端启动操作的超时时间。 + - **发送超时**:调整 TiCDC Pulsar 生产者发送消息的超时时间。 + +5. 点击**下一步**以测试网络连接。如果测试成功,你将进入下一步。 + +## 步骤 3. 配置 changefeed 复制 + +1. 自定义**表过滤器**以过滤要复制的表。有关规则语法,请参考[表过滤规则](/table-filter.md)。 + + - **过滤规则**:你可以在此列中设置过滤规则。默认有一个规则 `*.*`,表示复制所有表。当你添加新规则时,TiDB Cloud 会查询 TiDB 中的所有表,并仅在右侧框中显示匹配规则的表。你最多可以添加 100 个过滤规则。 + - **具有有效键的表**:此列显示具有有效键(包括主键或唯一索引)的表。 + - **没有有效键的表**:此列显示缺少主键或唯一键的表。这些表在复制过程中会带来挑战,因为缺少唯一标识符可能会导致下游处理重复事件时数据不一致。为确保数据一致性,建议在开始复制之前为这些表添加唯一键或主键。或者,你可以添加过滤规则来排除这些表。例如,你可以使用规则 `"!test.tbl1"` 排除表 `test.tbl1`。 + +2. 自定义**事件过滤器**以过滤要复制的事件。 + + - **匹配表**:你可以在此列中设置事件过滤器将应用于哪些表。规则语法与前面的**表过滤器**区域使用的语法相同。每个 changefeed 最多可以添加 10 个事件过滤规则。 + - **忽略的事件**:你可以设置事件过滤器将从 changefeed 中排除的事件类型。 + +3. 在**开始复制位置**区域,选择 changefeed 开始将数据复制到 Pulsar 的起点: + + - **从现在开始复制**:changefeed 将从当前点开始复制数据。 + - **从特定 TSO 开始复制**:changefeed 将从指定的 [TSO](/tso.md) 开始复制数据。指定的 TSO 必须在[垃圾回收安全点](/read-historical-data.md#tidb-如何管理数据版本)内。 + - **从特定时间开始复制**:changefeed 将从指定的时间戳开始复制数据。指定的时间戳必须在垃圾回收安全点内。 + +4. 在**数据格式**区域,选择你想要的 Pulsar 消息格式。 + + - Canal-JSON 是一种易于解析的纯 JSON 文本格式。更多信息,请参见 [TiCDC Canal-JSON 协议](https://docs.pingcap.com/tidb/stable/ticdc-canal-json/)。 + + - 要在 Pulsar 消息正文中添加 TiDB 扩展字段,请启用 **TiDB 扩展**选项。更多信息,请参见 [TiCDC Canal-JSON 协议中的 TiDB 扩展字段](https://docs.pingcap.com/tidb/stable/ticdc-canal-json/#tidb-extension-field)。 + +5. 在**主题分发**区域,选择分发模式,然后根据模式填写主题名称配置。 + + 分发模式控制 changefeed 如何将事件消息分发到 Pulsar 主题,可以将所有消息发送到一个主题,或按表或按数据库发送到特定主题。 + + > **注意:** + > + > 当你选择 Pulsar 作为下游时,changefeed 不会自动创建主题。你必须提前创建所需的主题。 + + - **将所有变更日志发送到一个指定的 Pulsar 主题** + + 如果你希望 changefeed 将所有消息发送到单个 Pulsar 主题,请选择此模式。你可以在**主题名称**字段中指定主题名称。 + + - **按表将变更日志分发到 Pulsar 主题** + + 如果你希望 changefeed 将每个表的所有 Pulsar 消息发送到专用的 Pulsar 主题,请选择此模式。你可以通过设置**主题前缀**、数据库名称和表名称之间的**分隔符**以及**主题后缀**来为表指定主题名称。例如,如果你将分隔符设置为 `_`,Pulsar 消息将被发送到格式为 `<主题前缀><数据库名称>_<表名称><主题后缀>` 的主题。你需要提前在 Pulsar 上创建这些主题。 + + 对于非行事件(如创建架构事件)的变更日志,你可以在**默认主题名称**字段中指定主题名称。changefeed 将非行事件发送到此主题以收集此类变更日志。 + + - **按数据库将变更日志分发到 Pulsar 主题** + + 如果你希望 changefeed 将每个数据库的所有 Pulsar 消息发送到专用的 Pulsar 主题,请选择此模式。你可以通过设置**主题前缀**和**主题后缀**来为数据库指定主题名称。 + + 对于非行事件(如已解析的 Ts 事件)的变更日志,你可以在**默认主题名称**字段中指定主题名称。changefeed 将非行事件发送到此主题以收集此类变更日志。 + + 由于 Pulsar 支持多租户,如果租户和命名空间与默认值不同,你可能还需要设置 **Pulsar 租户**和 **Pulsar 命名空间**。 + +6. 在**分区分发**区域,你可以决定将 Pulsar 消息发送到哪个分区。你可以定义**所有表使用单个分区调度器**或**不同表使用不同的分区调度器**。TiDB Cloud 提供四个规则选项来将变更事件分发到 Pulsar 分区: + + - **主键或唯一索引** + + 如果你希望 changefeed 将表的 Pulsar 消息发送到不同的分区,请选择此分发方法。行变更日志的主键或索引值决定将变更日志发送到哪个分区。此分发方法提供更好的分区平衡,并确保行级有序性。 + + - **表** + + 如果你希望 changefeed 将表的 Pulsar 消息发送到一个 Pulsar 分区,请选择此分发方法。行变更日志的表名决定将变更日志发送到哪个分区。此分发方法确保表有序性,但可能导致分区不平衡。 + + - **时间戳** + + 如果你希望 changefeed 根据时间戳将 Pulsar 消息发送到不同的 Pulsar 分区,请选择此分发方法。行变更日志的 commitTs 决定将变更日志发送到哪个分区。此分发方法提供更好的分区平衡,并确保每个分区内的有序性。但是,数据项的多个更改可能会被发送到不同的分区,不同消费者的消费进度可能不同,这可能导致数据不一致。因此,消费者需要在消费之前按 commitTs 对来自多个分区的数据进行排序。 + + - **列值** + + 如果你希望 changefeed 将表的 Pulsar 消息发送到不同的分区,请选择此分发方法。行变更日志的指定列值将决定将变更日志发送到哪个分区。此分发方法确保每个分区内的有序性,并保证具有相同列值的变更日志被发送到同一个分区。 + +7. 点击**下一步**。 + +## 步骤 4. 配置规格并审查 + +1. 在**规格和名称**部分: + + - 为 changefeed 指定[复制容量单位(RCU)](/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md)的数量。 + - 为 changefeed 输入名称。 + +2. 审查所有 changefeed 配置。 + + - 如果发现问题,你可以返回前面的步骤解决问题。 + - 如果没有问题,你可以点击**提交**创建 changefeed。 diff --git a/tidb-cloud/changefeed-sink-to-cloud-storage.md b/tidb-cloud/changefeed-sink-to-cloud-storage.md new file mode 100644 index 000000000000..4154cacc78c2 --- /dev/null +++ b/tidb-cloud/changefeed-sink-to-cloud-storage.md @@ -0,0 +1,168 @@ +--- +title: 导出数据到云存储 +summary: 本文介绍如何创建 changefeed 将数据从 TiDB Cloud 流式传输到 Amazon S3 或 GCS。包括限制、目标配置步骤、复制和规格配置,以及启动复制过程。 +--- + +# 导出数据到云存储 + +本文介绍如何创建 changefeed 将数据从 TiDB Cloud 流式传输到云存储。目前支持 Amazon S3 和 GCS。 + +> **注意:** +> +> - 要将数据流式传输到云存储,请确保您的 TiDB 集群版本为 v7.1.1 或更高版本。要将 TiDB Cloud Dedicated 集群升级到 v7.1.1 或更高版本,请[联系 TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 +> - 对于 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,changefeed 功能不可用。 + +## 限制 + +- 每个 TiDB Cloud 集群最多可以创建 100 个 changefeed。 +- 由于 TiDB Cloud 使用 TiCDC 建立 changefeed,因此它具有与 TiCDC 相同的[限制](https://docs.pingcap.com/tidb/stable/ticdc-overview#unsupported-scenarios)。 +- 如果要复制的表没有主键或非空唯一索引,在某些重试场景下,由于缺少唯一约束,可能会导致下游插入重复数据。 + +## 步骤 1. 配置目标 + +导航到目标 TiDB 集群的集群概览页面。在左侧导航栏中点击**数据** > **Changefeed**,点击**创建 Changefeed**,然后选择 **Amazon S3** 或 **GCS** 作为目标。配置过程根据您选择的目标而有所不同。 + + +
+ +对于 **Amazon S3**,填写 **S3 端点**区域:`S3 URI`、`Access Key ID` 和 `Secret Access Key`。确保 S3 存储桶与您的 TiDB 集群在同一区域。 + +![s3_endpoint](/media/tidb-cloud/changefeed/sink-to-cloud-storage-s3-endpoint.jpg) + +
+
+ +对于 **GCS**,在填写 **GCS 端点**之前,您需要先授予 GCS 存储桶访问权限。请按照以下步骤操作: + +1. 在 TiDB Cloud 控制台中,记录**服务账号 ID**,该 ID 将用于授予 TiDB Cloud 访问您的 GCS 存储桶的权限。 + + ![gcs_endpoint](/media/tidb-cloud/changefeed/sink-to-cloud-storage-gcs-endpoint.png) + +2. 在 Google Cloud 控制台中,为您的 GCS 存储桶创建 IAM 角色。 + + 1. 登录 [Google Cloud 控制台](https://console.cloud.google.com/)。 + 2. 转到[角色](https://console.cloud.google.com/iam-admin/roles)页面,然后点击**创建角色**。 + + ![创建角色](/media/tidb-cloud/changefeed/sink-to-cloud-storage-gcs-create-role.png) + + 3. 为角色输入名称、描述、ID 和角色启动阶段。角色创建后,角色名称无法更改。 + 4. 点击**添加权限**。将以下权限添加到角色,然后点击**添加**。 + + - storage.buckets.get + - storage.objects.create + - storage.objects.delete + - storage.objects.get + - storage.objects.list + - storage.objects.update + + ![添加权限](/media/tidb-cloud/changefeed/sink-to-cloud-storage-gcs-assign-permission.png) + +3. 转到[存储桶](https://console.cloud.google.com/storage/browser)页面,选择您希望 TiDB Cloud 访问的 GCS 存储桶。请注意,GCS 存储桶必须与您的 TiDB 集群在同一区域。 + +4. 在**存储桶详情**页面,点击**权限**标签,然后点击**授予访问权限**。 + + ![授予存储桶访问权限](/media/tidb-cloud/changefeed/sink-to-cloud-storage-gcs-grant-access-1.png) + +5. 填写以下信息以授予存储桶访问权限,然后点击**保存**。 + + - 在**新主体**字段中,粘贴您之前记录的目标 TiDB 集群的**服务账号 ID**。 + - 在**选择角色**下拉列表中,输入您刚刚创建的 IAM 角色名称,然后从筛选结果中选择该名称。 + + > **注意:** + > + > 要移除 TiDB Cloud 的访问权限,只需移除您已授予的访问权限即可。 + +6. 在**存储桶详情**页面,点击**对象**标签。 + + - 要获取存储桶的 gsutil URI,点击复制按钮并添加 `gs://` 作为前缀。例如,如果存储桶名称为 `test-sink-gcs`,则 URI 为 `gs://test-sink-gcs/`。 + + ![获取存储桶 URI](/media/tidb-cloud/changefeed/sink-to-cloud-storage-gcs-uri01.png) + + - 要获取文件夹的 gsutil URI,打开文件夹,点击复制按钮,并添加 `gs://` 作为前缀。例如,如果存储桶名称为 `test-sink-gcs`,文件夹名称为 `changefeed-xxx`,则 URI 为 `gs://test-sink-gcs/changefeed-xxx/`。 + + ![获取存储桶 URI](/media/tidb-cloud/changefeed/sink-to-cloud-storage-gcs-uri02.png) + +7. 在 TiDB Cloud 控制台中,转到 Changefeed 的**配置目标**页面,并填写**存储桶 gsutil URI** 字段。 + +
+
+ +点击**下一步**以建立从 TiDB Cloud Dedicated 集群到 Amazon S3 或 GCS 的连接。TiDB Cloud 将自动测试并验证连接是否成功。 + +- 如果成功,您将进入下一步配置。 +- 如果失败,将显示连接错误,您需要处理该错误。错误解决后,点击**下一步**重试连接。 + +## 步骤 2. 配置复制 + +1. 自定义**表过滤器**以过滤要复制的表。有关规则语法,请参考[表过滤规则](https://docs.pingcap.com/tidb/stable/ticdc-filter#changefeed-log-filters)。 + + ![changefeed 的表过滤器](/media/tidb-cloud/changefeed/sink-to-s3-02-table-filter.jpg) + + - **过滤规则**:您可以在此列设置过滤规则。默认有一个规则 `*.*`,表示复制所有表。添加新规则时,TiDB Cloud 会查询 TiDB 中的所有表,并在右侧框中仅显示匹配规则的表。您最多可以添加 100 个过滤规则。 + - **具有有效键的表**:此列显示具有有效键(包括主键或唯一索引)的表。 + - **没有有效键的表**:此列显示缺少主键或唯一键的表。这些表在复制过程中会带来挑战,因为缺少唯一标识符可能会导致在处理下游重复事件时出现数据不一致。为确保数据一致性,建议在开始复制之前为这些表添加唯一键或主键。或者,您可以使用过滤规则排除这些表。例如,您可以使用规则 `"!test.tbl1"` 排除表 `test.tbl1`。 + +2. 自定义**事件过滤器**以过滤要复制的事件。 + + - **匹配表**:您可以在此列设置事件过滤器将应用于哪些表。规则语法与前面的**表过滤器**区域使用的语法相同。每个 changefeed 最多可以添加 10 个事件过滤规则。 + - **忽略的事件**:您可以设置事件过滤器将从 changefeed 中排除哪些类型的事件。 + +3. 在**开始复制位置**区域,选择以下复制位置之一: + + - 从现在开始复制 + - 从特定 [TSO](https://docs.pingcap.com/tidb/stable/glossary#tso) 开始复制 + - 从特定时间开始复制 + +4. 在**数据格式**区域,选择 **CSV** 或 **Canal-JSON** 格式。 + + +
+ + 要配置 **CSV** 格式,请填写以下字段: + + - **二进制编码方法**:二进制数据的编码方法。您可以选择 **base64**(默认)或 **hex**。如果要与 AWS DMS 集成,请使用 **hex**。 + - **日期分隔符**:根据年、月、日轮换数据,或选择不轮换。 + - **分隔符**:指定用于分隔 CSV 文件中值的字符。逗号(`,`)是最常用的分隔符。 + - **引号**:指定用于包围包含分隔符或特殊字符的值的字符。通常使用双引号(`"`)作为引号字符。 + - **空值/空值**:指定如何在 CSV 文件中表示空值或空值。这对于正确处理和解释数据很重要。 + - **包含提交时间戳**:控制是否在 CSV 行中包含 [`commit-ts`](https://docs.pingcap.com/tidb/stable/ticdc-sink-to-cloud-storage#replicate-change-data-to-storage-services)。 + +
+
+ + Canal-JSON 是一种纯 JSON 文本格式。要配置它,请填写以下字段: + + - **日期分隔符**:根据年、月、日轮换数据,或选择不轮换。 + - **启用 TiDB 扩展**:启用此选项后,TiCDC 会发送 [WATERMARK 事件](https://docs.pingcap.com/tidb/stable/ticdc-canal-json#watermark-event)并在 Canal-JSON 消息中添加 [TiDB 扩展字段](https://docs.pingcap.com/tidb/stable/ticdc-canal-json#tidb-extension-field)。 + +
+
+ +5. 在**刷新参数**区域,您可以配置两个项目: + + - **刷新间隔**:默认设置为 60 秒,可在 2 秒到 10 分钟范围内调整; + - **文件大小**:默认设置为 64 MB,可在 1 MB 到 512 MB 范围内调整。 + + ![刷新参数](/media/tidb-cloud/changefeed/sink-to-cloud-storage-flush-parameters.jpg) + + > **注意:** + > + > 这两个参数将影响每个数据库表在云存储中生成的对象数量。如果有大量表,使用相同的配置将增加生成的对象数量,从而增加调用云存储 API 的成本。因此,建议根据您的恢复点目标(RPO)和成本要求适当配置这些参数。 + +## 步骤 3. 配置规格 + +点击**下一步**以配置您的 changefeed 规格。 + +1. 在 **Changefeed 规格**区域,指定 changefeed 将使用的复制容量单位(RCU)数量。 +2. 在 **Changefeed 名称**区域,为 changefeed 指定一个名称。 + +## 步骤 4. 查看配置并开始复制 + +点击**下一步**以查看 changefeed 配置。 + +- 如果您已验证所有配置都正确,点击**创建**以继续创建 changefeed。 +- 如果您需要修改任何配置,点击**上一步**返回并进行必要的更改。 + +导出将很快开始,您将看到导出状态从**创建中**变为**运行中**。 + +点击 changefeed 的名称以转到其详情页面。在此页面上,您可以查看有关 changefeed 的更多信息,包括检查点状态、复制延迟和其他相关指标。 diff --git a/tidb-cloud/changefeed-sink-to-mysql.md b/tidb-cloud/changefeed-sink-to-mysql.md new file mode 100644 index 000000000000..0468c084e776 --- /dev/null +++ b/tidb-cloud/changefeed-sink-to-mysql.md @@ -0,0 +1,143 @@ +--- +title: 同步到 MySQL +summary: 本文档介绍如何使用同步到 MySQL 的 changefeed 将数据从 TiDB Cloud 流式传输到 MySQL。它包括限制、前提条件以及创建 MySQL sink 进行数据复制的步骤。该过程涉及设置网络连接、将现有数据加载到 MySQL 以及在 MySQL 中创建目标表。完成前提条件后,用户可以创建 MySQL sink 以将数据复制到 MySQL。 +--- + +# 同步到 MySQL + +本文档介绍如何使用**同步到 MySQL** changefeed 将数据从 TiDB Cloud 流式传输到 MySQL。 + +> **注意:** +> +> - 要使用 changefeed 功能,请确保你的 TiDB Cloud Dedicated 集群版本为 v6.1.3 或更高版本。 +> - 对于 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless),changefeed 功能不可用。 + +## 限制 + +- 对于每个 TiDB Cloud 集群,你最多可以创建 100 个 changefeed。 +- 因为 TiDB Cloud 使用 TiCDC 建立 changefeed,所以它具有与 [TiCDC 相同的限制](https://docs.pingcap.com/tidb/stable/ticdc-overview#unsupported-scenarios)。 +- 如果要复制的表没有主键或非空唯一索引,在某些重试场景下,由于缺少唯一约束,可能会导致下游插入重复数据。 + +## 前提条件 + +在创建 changefeed 之前,你需要完成以下前提条件: + +- 设置网络连接 +- 导出并加载现有数据到 MySQL(可选) +- 如果你不加载现有数据,只想将增量数据复制到 MySQL,则需要在 MySQL 中创建相应的目标表 + +### 网络 + +确保你的 TiDB 集群可以连接到 MySQL 服务。 + +如果你的 MySQL 服务在没有公共互联网访问的 AWS VPC 中,请执行以下步骤: + +1. 在 MySQL 服务的 VPC 和你的 TiDB 集群之间[设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)。 +2. 修改 MySQL 服务关联的安全组的入站规则。 + + 你必须将[你的 TiDB Cloud 集群所在区域的 CIDR](/tidb-cloud/set-up-vpc-peering-connections.md#prerequisite-set-a-cidr-for-a-region) 添加到入站规则中。这样可以允许流量从你的 TiDB 集群流向 MySQL 实例。 + +3. 如果 MySQL URL 包含主机名,你需要允许 TiDB Cloud 能够解析 MySQL 服务的 DNS 主机名。 + + 1. 按照[为 VPC 对等连接启用 DNS 解析](https://docs.aws.amazon.com/vpc/latest/peering/modify-peering-connections.html#vpc-peering-dns)中的步骤操作。 + 2. 启用**接受者 DNS 解析**选项。 + +如果你的 MySQL 服务在没有公共互联网访问的 Google Cloud VPC 中,请执行以下步骤: + +1. 如果你的 MySQL 服务是 Google Cloud SQL,你必须在 Google Cloud SQL 实例关联的 VPC 中暴露一个 MySQL 端点。你可能需要使用 Google 开发的 [**Cloud SQL Auth proxy**](https://cloud.google.com/sql/docs/mysql/sql-proxy)。 +2. 在 MySQL 服务的 VPC 和你的 TiDB 集群之间[设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)。 +3. 修改 MySQL 所在 VPC 的入站防火墙规则。 + + 你必须将[你的 TiDB Cloud 集群所在区域的 CIDR](/tidb-cloud/set-up-vpc-peering-connections.md#prerequisite-set-a-cidr-for-a-region) 添加到入站防火墙规则中。这样可以允许流量从你的 TiDB 集群流向 MySQL 端点。 + +### 加载现有数据(可选) + +**同步到 MySQL** 连接器只能在某个时间戳之后将增量数据从你的 TiDB 集群同步到 MySQL。如果你的 TiDB 集群中已经有数据,你可以在启用**同步到 MySQL**之前将 TiDB 集群的现有数据导出并加载到 MySQL 中。 + +要加载现有数据: + +1. 将 [tidb_gc_life_time](https://docs.pingcap.com/tidb/stable/system-variables#tidb_gc_life_time-new-in-v50) 延长至超过以下两个操作的总时间,这样 TiDB 就不会对这段时间内的历史数据进行垃圾回收。 + + - 导出和导入现有数据的时间 + - 创建**同步到 MySQL**的时间 + + 例如: + + {{< copyable "sql" >}} + + ```sql + SET GLOBAL tidb_gc_life_time = '720h'; + ``` + +2. 使用 [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview) 从你的 TiDB 集群导出数据,然后使用社区工具(如 [mydumper/myloader](https://centminmod.com/mydumper.html))将数据加载到 MySQL 服务。 + +3. 从 [Dumpling 导出的文件](https://docs.pingcap.com/tidb/stable/dumpling-overview#format-of-exported-files)中,从元数据文件获取 MySQL sink 的起始位置: + + 以下是一个示例元数据文件的部分内容。`SHOW MASTER STATUS` 的 `Pos` 是现有数据的 TSO,也是 MySQL sink 的起始位置。 + + ``` + Started dump at: 2020-11-10 10:40:19 + SHOW MASTER STATUS: + Log: tidb-binlog + Pos: 420747102018863124 + Finished dump at: 2020-11-10 10:40:20 + ``` + +### 在 MySQL 中创建目标表 + +如果你不加载现有数据,你需要在 MySQL 中手动创建相应的目标表来存储来自 TiDB 的增量数据。否则,数据将不会被复制。 + +## 创建 MySQL sink + +完成前提条件后,你可以将数据同步到 MySQL。 + +1. 导航到目标 TiDB 集群的集群概览页面,然后在左侧导航栏中点击**数据** > **Changefeed**。 + +2. 点击**创建 Changefeed**,并选择 **MySQL** 作为**目标**。 + +3. 在 **MySQL 连接**中填写 MySQL 端点、用户名和密码。 + +4. 点击**下一步**以测试 TiDB 是否可以成功连接到 MySQL: + + - 如果可以,你将进入下一步配置。 + - 如果不可以,将显示连接错误,你需要处理该错误。错误解决后,再次点击**下一步**。 + +5. 自定义**表过滤器**以过滤要复制的表。有关规则语法,请参考[表过滤规则](/table-filter.md)。 + + - **过滤规则**:你可以在此列中设置过滤规则。默认有一个规则 `*.*`,表示复制所有表。当你添加新规则时,TiDB Cloud 会查询 TiDB 中的所有表,并在右侧框中只显示匹配规则的表。你最多可以添加 100 个过滤规则。 + - **具有有效键的表**:此列显示具有有效键(包括主键或唯一索引)的表。 + - **没有有效键的表**:此列显示缺少主键或唯一键的表。这些表在复制过程中会带来挑战,因为缺少唯一标识符可能会导致下游处理重复事件时数据不一致。为确保数据一致性,建议在开始复制之前为这些表添加唯一键或主键。或者,你可以添加过滤规则来排除这些表。例如,你可以使用规则 `"!test.tbl1"` 来排除表 `test.tbl1`。 + +6. 自定义**事件过滤器**以过滤要复制的事件。 + + - **匹配表**:你可以在此列中设置事件过滤器将应用于哪些表。规则语法与前面的**表过滤器**区域使用的语法相同。每个 changefeed 最多可以添加 10 个事件过滤规则。 + - **忽略的事件**:你可以设置事件过滤器将从 changefeed 中排除哪些类型的事件。 + +7. 在**开始复制位置**中,配置 MySQL sink 的起始位置。 + + - 如果你已经使用 Dumpling [加载了现有数据](#加载现有数据可选),选择**从特定 TSO 开始复制**,并填写你从 Dumpling 导出的元数据文件中获取的 TSO。 + - 如果上游 TiDB 集群中没有任何数据,选择**从现在开始复制**。 + - 否则,你可以通过选择**从特定时间开始复制**来自定义开始时间点。 + +8. 点击**下一步**以配置你的 changefeed 规格。 + + - 在 **Changefeed 规格**区域,指定 changefeed 要使用的复制容量单位(RCU)数量。 + - 在 **Changefeed 名称**区域,为 changefeed 指定一个名称。 + +9. 点击**下一步**以审查 changefeed 配置。 + + 如果你确认所有配置都正确,请检查跨区域复制的合规性,然后点击**创建**。 + + 如果你想修改某些配置,点击**上一步**返回上一个配置页面。 + +10. sink 很快就会启动,你可以看到 sink 的状态从**创建中**变为**运行中**。 + + 点击 changefeed 名称,你可以看到有关 changefeed 的更多详细信息,如检查点、复制延迟和其他指标。 + +11. 如果你已经使用 Dumpling [加载了现有数据](#加载现有数据可选),你需要在创建 sink 后将 GC 时间恢复为原始值(默认值为 `10m`): + +{{< copyable "sql" >}} + +```sql +SET GLOBAL tidb_gc_life_time = '10m'; +``` diff --git a/tidb-cloud/changefeed-sink-to-tidb-cloud.md b/tidb-cloud/changefeed-sink-to-tidb-cloud.md new file mode 100644 index 000000000000..1d894c9174cb --- /dev/null +++ b/tidb-cloud/changefeed-sink-to-tidb-cloud.md @@ -0,0 +1,107 @@ +--- +title: 同步到 TiDB Cloud +summary: 本文档介绍如何将数据从 TiDB Cloud Dedicated 集群流式传输到 TiDB Cloud Serverless 集群。该功能对 changefeed 数量和可用区域有限制。前提条件包括延长 tidb_gc_life_time、备份数据以及获取 TiDB Cloud sink 的起始位置。要创建 TiDB Cloud sink,需要导航到集群概览页面、建立连接、自定义表和事件过滤器、填写开始复制位置、指定 changefeed 规格、审查配置并创建 sink。最后,将 tidb_gc_life_time 恢复为原始值。 +--- + +# 同步到 TiDB Cloud + +本文档介绍如何将数据从 TiDB Cloud Dedicated 集群流式传输到 TiDB Cloud Serverless 集群。 + +> **注意:** +> +> 要使用 Changefeed 功能,请确保你的 TiDB Cloud Dedicated 集群版本为 v6.1.3 或更高版本。 + +## 限制 + +- 对于每个 TiDB Cloud 集群,你最多可以创建 100 个 changefeed。 +- 因为 TiDB Cloud 使用 TiCDC 建立 changefeed,所以它具有与 [TiCDC 相同的限制](https://docs.pingcap.com/tidb/stable/ticdc-overview#unsupported-scenarios)。 +- 如果要复制的表没有主键或非空唯一索引,在某些重试场景下,由于缺少唯一约束,可能会导致下游插入重复数据。 +- **同步到 TiDB Cloud** 功能仅适用于 2022 年 11 月 9 日之后创建的、位于以下 AWS 区域的 TiDB Cloud Dedicated 集群: + + - AWS 俄勒冈(us-west-2) + - AWS 法兰克福(eu-central-1) + - AWS 新加坡(ap-southeast-1) + - AWS 东京(ap-northeast-1) + +- 源 TiDB Cloud Dedicated 集群和目标 TiDB Cloud Serverless 集群必须在同一个项目和同一个区域中。 +- **同步到 TiDB Cloud** 功能仅支持通过私有端点进行网络连接。当你创建 changefeed 将数据从 TiDB Cloud Dedicated 集群流式传输到 TiDB Cloud Serverless 集群时,TiDB Cloud 将自动在两个集群之间设置私有端点连接。 + +## 前提条件 + +**同步到 TiDB Cloud** 连接器只能在某个 [TSO](https://docs.pingcap.com/tidb/stable/glossary#tso) 之后将增量数据从 TiDB Cloud Dedicated 集群同步到 TiDB Cloud Serverless 集群。 + +在创建 changefeed 之前,你需要从源 TiDB Cloud Dedicated 集群导出现有数据并将数据加载到目标 TiDB Cloud Serverless 集群。 + +1. 将 [tidb_gc_life_time](https://docs.pingcap.com/tidb/stable/system-variables#tidb_gc_life_time-new-in-v50) 延长至超过以下两个操作的总时间,这样 TiDB 就不会对这段时间内的历史数据进行垃圾回收。 + + - 导出和导入现有数据的时间 + - 创建**同步到 TiDB Cloud**的时间 + + 例如: + + ```sql + SET GLOBAL tidb_gc_life_time = '720h'; + ``` + +2. 使用 [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview) 从你的 TiDB Cloud Dedicated 集群导出数据,然后使用 [TiDB Cloud Serverless 导入](/tidb-cloud/import-csv-files-serverless.md)将数据加载到目标 TiDB Cloud Serverless 集群。 + +3. 从 [Dumpling 导出的文件](https://docs.pingcap.com/tidb/stable/dumpling-overview#format-of-exported-files)中,从元数据文件获取 TiDB Cloud sink 的起始位置: + + 以下是一个示例元数据文件的部分内容。`SHOW MASTER STATUS` 的 `Pos` 是现有数据的 TSO,也是 TiDB Cloud sink 的起始位置。 + + ``` + Started dump at: 2023-03-28 10:40:19 + SHOW MASTER STATUS: + Log: tidb-binlog + Pos: 420747102018863124 + Finished dump at: 2023-03-28 10:40:20 + ``` + +## 创建 TiDB Cloud sink + +完成前提条件后,你可以将数据同步到目标 TiDB Cloud Serverless 集群。 + +1. 导航到目标 TiDB 集群的集群概览页面,然后在左侧导航栏中点击**数据** > **Changefeed**。 + +2. 点击**创建 Changefeed**,并选择 **TiDB Cloud** 作为目标。 + +3. 在 **TiDB Cloud 连接**区域,选择目标 TiDB Cloud Serverless 集群,然后填写目标集群的用户名和密码。 + +4. 点击**下一步**以建立两个 TiDB 集群之间的连接,并测试 changefeed 是否可以成功连接它们: + + - 如果可以,你将进入下一步配置。 + - 如果不可以,将显示连接错误,你需要处理该错误。错误解决后,再次点击**下一步**。 + +5. 自定义**表过滤器**以过滤要复制的表。有关规则语法,请参考[表过滤规则](/table-filter.md)。 + + - **过滤规则**:你可以在此列中设置过滤规则。默认有一个规则 `*.*`,表示复制所有表。当你添加新规则时,TiDB Cloud 会查询 TiDB 中的所有表,并在右侧框中只显示匹配规则的表。你最多可以添加 100 个过滤规则。 + - **具有有效键的表**:此列显示具有有效键(包括主键或唯一索引)的表。 + - **没有有效键的表**:此列显示缺少主键或唯一键的表。这些表在复制过程中会带来挑战,因为缺少唯一标识符可能会导致下游处理重复事件时数据不一致。为确保数据一致性,建议在开始复制之前为这些表添加唯一键或主键。或者,你可以添加过滤规则来排除这些表。例如,你可以使用规则 `"!test.tbl1"` 来排除表 `test.tbl1`。 + +6. 自定义**事件过滤器**以过滤要复制的事件。 + + - **匹配表**:你可以在此列中设置事件过滤器将应用于哪些表。规则语法与前面的**表过滤器**区域使用的语法相同。每个 changefeed 最多可以添加 10 个事件过滤规则。 + - **忽略的事件**:你可以设置事件过滤器将从 changefeed 中排除哪些类型的事件。 + +7. 在**开始复制位置**区域,填写你从 Dumpling 导出的元数据文件中获取的 TSO。 + +8. 点击**下一步**以配置你的 changefeed 规格。 + + - 在 **Changefeed 规格**区域,指定 changefeed 要使用的复制容量单位(RCU)数量。 + - 在 **Changefeed 名称**区域,为 changefeed 指定一个名称。 + +9. 点击**下一步**以审查 changefeed 配置。 + + 如果你确认所有配置都正确,请检查跨区域复制的合规性,然后点击**创建**。 + + 如果你想修改某些配置,点击**上一步**返回上一个配置页面。 + +10. sink 很快就会启动,你可以看到 sink 的状态从**创建中**变为**运行中**。 + + 点击 changefeed 名称,你可以看到有关 changefeed 的更多详细信息,如检查点、复制延迟和其他指标。 + +11. 在创建 sink 后,将 [tidb_gc_life_time](https://docs.pingcap.com/tidb/stable/system-variables#tidb_gc_life_time-new-in-v50) 恢复为原始值(默认值为 `10m`): + + ```sql + SET GLOBAL tidb_gc_life_time = '10m'; + ``` diff --git a/tidb-cloud/cli-reference.md b/tidb-cloud/cli-reference.md new file mode 100644 index 000000000000..efeef763240d --- /dev/null +++ b/tidb-cloud/cli-reference.md @@ -0,0 +1,129 @@ +--- +title: TiDB Cloud CLI 参考 +summary: 提供 TiDB Cloud CLI 的概述。 +--- + +# TiDB Cloud CLI 参考(Beta) + +> **注意:** +> +> TiDB Cloud CLI 目前处于 beta 阶段。 + +TiDB Cloud CLI 是一个命令行界面,允许你通过几行命令在终端中操作 TiDB Cloud。在 TiDB Cloud CLI 中,你可以轻松管理 TiDB Cloud 集群、向集群导入数据以及执行更多操作。 + +## 开始之前 + +请确保首先[设置你的 TiDB Cloud CLI 环境](/tidb-cloud/get-started-with-cli.md)。安装 `ticloud` CLI 后,你就可以通过命令行管理 TiDB Cloud 集群。 + +## 可用命令 + +下表列出了 TiDB Cloud CLI 的可用命令。 + +要在终端中使用 `ticloud` CLI,运行 `ticloud [command] [subcommand]`。如果你使用的是 [TiUP](https://docs.pingcap.com/tidb/stable/tiup-overview),请使用 `tiup cloud [command] [subcommand]`。 + +| 命令 | 子命令 | 描述 | +|-----------------------|-----------------------------------------------------------------------|------------------------------------------------| +| auth | login, logout, whoami | 登录和登出 | +| serverless (别名: s) | create, delete, describe, list, update, spending-limit, region, shell | 管理 TiDB Cloud Serverless 集群 | +| serverless branch | create, delete, describe, list, shell | 管理 TiDB Cloud Serverless 分支 | +| serverless import | cancel, describe, list, start | 管理 TiDB Cloud Serverless 导入任务 | +| serverless export | create, describe, list, cancel, download | 管理 TiDB Cloud Serverless 导出任务 | +| serverless sql-user | create, list, delete, update | 管理 TiDB Cloud Serverless SQL 用户 | +| ai | - | 与 TiDB Bot 聊天 | +| completion | bash, fish, powershell, zsh | 为指定的 shell 生成补全脚本 | +| config | create, delete, describe, edit, list, set, use | 配置用户配置文件 | +| project | list | 管理项目 | +| upgrade | - | 将 CLI 更新到最新版本 | +| help | auth, config, serverless, ai, project, upgrade, help, completion | 查看任何命令的帮助 | + +## 命令模式 + +TiDB Cloud CLI 为某些命令提供了两种模式,方便使用: + +- 交互模式 + + 你可以运行不带标志的命令(如 `ticloud config create`),CLI 会提示你输入。 + +- 非交互模式 + + 运行命令时必须提供所有必需的参数和标志,如 `ticloud config create --profile-name --public-key --private-key `。 + +## 用户配置文件 + +对于 TiDB Cloud CLI,用户配置文件是与用户相关的属性集合,包括配置文件名称、公钥、私钥和 OAuth 令牌。要使用 TiDB Cloud CLI,你必须有一个用户配置文件。 + +### 使用 TiDB Cloud API 密钥创建用户配置文件 + +使用 [`ticloud config create`](/tidb-cloud/ticloud-config-create.md) 创建用户配置文件。 + +### 使用 OAuth 令牌创建用户配置文件 + +使用 [`ticloud auth login`](/tidb-cloud/ticloud-auth-login.md) 将 OAuth 令牌分配给当前配置文件。如果不存在配置文件,将自动创建一个名为 `default` 的配置文件。 + +> **注意:** +> +> 在上述两种方法中,TiDB Cloud API 密钥优先于 OAuth 令牌。如果当前配置文件中两者都可用,将使用 API 密钥。 + +### 列出所有用户配置文件 + +使用 [`ticloud config list`](/tidb-cloud/ticloud-config-list.md) 列出所有用户配置文件。 + +示例输出如下: + +``` +Profile Name +default (active) +dev +staging +``` + +在此示例输出中,用户配置文件 `default` 当前处于活动状态。 + +### 描述用户配置文件 + +使用 [`ticloud config describe`](/tidb-cloud/ticloud-config-describe.md) 获取用户配置文件的属性。 + +示例输出如下: + +```json +{ + "private-key": "xxxxxxx-xxx-xxxxx-xxx-xxxxx", + "public-key": "Uxxxxxxx" +} +``` + +### 设置用户配置文件中的属性 + +使用 [`ticloud config set`](/tidb-cloud/ticloud-config-set.md) 设置用户配置文件中的属性。 + +### 切换到另一个用户配置文件 + +使用 [`ticloud config use`](/tidb-cloud/ticloud-config-use.md) 切换到另一个用户配置文件。 + +示例输出如下: + +``` +Current profile has been changed to default +``` + +### 编辑配置文件 + +使用 [`ticloud config edit`](/tidb-cloud/ticloud-config-edit.md) 打开配置文件进行编辑。 + +### 删除用户配置文件 + +使用 [`ticloud config delete`](/tidb-cloud/ticloud-config-delete.md) 删除用户配置文件。 + +## 全局标志 + +下表列出了 TiDB Cloud CLI 的全局标志。 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|---------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动用户配置文件。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/configure-ip-access-list.md b/tidb-cloud/configure-ip-access-list.md new file mode 100644 index 000000000000..8133441e2486 --- /dev/null +++ b/tidb-cloud/configure-ip-access-list.md @@ -0,0 +1,30 @@ +--- +title: 配置 IP 访问列表 +summary: 了解如何配置允许访问 TiDB Cloud Dedicated 集群的 IP 地址。 +--- + +# 配置 IP 访问列表 + +对于 TiDB Cloud 中的每个 TiDB Cloud Dedicated 集群,您可以配置 IP 访问列表来过滤尝试访问集群的互联网流量,其工作方式类似于防火墙访问控制列表。配置完成后,只有 IP 地址在 IP 访问列表中的客户端和应用程序才能连接到您的 TiDB Cloud Dedicated 集群。 + +> **注意:** +> +> 本文适用于 [**TiDB Cloud Dedicated**](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。有关配置 **TiDB Cloud Serverless** IP 访问列表的说明,请参见[为公共端点配置 TiDB Cloud Serverless 防火墙规则](/tidb-cloud/configure-serverless-firewall-rules-for-public-endpoints.md)。 + +要为 TiDB Cloud Dedicated 集群配置 IP 访问列表,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称以进入其概览页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 在左侧导航栏中,点击**设置** > **网络**。 +3. 在**网络**页面上,点击**添加 IP 地址**。 +4. 在显示的对话框中,选择以下选项之一: + + - **允许来自任何地方的访问**:允许所有 IP 地址访问 TiDB Cloud。此选项将您的集群完全暴露在互联网上,风险很高。 + - **使用 IP 地址**(推荐):您可以添加允许通过 SQL 客户端访问 TiDB Cloud 的 IP 和 CIDR 地址列表。 + +5. 如果您选择**使用 IP 地址**,请添加 IP 地址或 CIDR 范围,并可选择添加描述。对于每个 TiDB Cloud Dedicated 集群,您最多可以添加 100 个 IP 地址。 +6. 点击**确认**以保存更改。 diff --git a/tidb-cloud/configure-maintenance-window.md b/tidb-cloud/configure-maintenance-window.md new file mode 100644 index 000000000000..8e50c165b046 --- /dev/null +++ b/tidb-cloud/configure-maintenance-window.md @@ -0,0 +1,95 @@ +--- +title: 配置维护时间窗口 +summary: 了解如何为您的集群配置维护时间窗口。 +--- + +# 配置维护时间窗口 + +维护时间窗口是一个指定的时间段,在此期间自动执行计划内维护任务,如操作系统更新、安全补丁和基础设施升级,以确保 TiDB Cloud 服务的可靠性、安全性和性能。 + +在维护时间窗口期间,维护工作会逐个在 TiDB Cloud Dedicated 集群上执行,因此整体影响最小。虽然可能会出现临时的连接中断或 QPS 波动,但集群仍然可用,现有的数据导入、备份、恢复、迁移和复制任务仍可正常运行。 + +通过配置维护时间窗口,您可以轻松安排和管理维护任务,以最大限度地减少维护影响。例如,您可以将维护时间窗口的开始时间设置为避开应用程序工作负载的高峰时段。 + +> **注意:** +> +> 维护时间窗口功能仅适用于 [TiDB Cloud Dedicated 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 维护时间窗口期间允许和不允许的操作 + +在维护时间窗口期间,某些操作是允许的,而某些操作是不允许的。 + +- 允许的操作: + + - SQL 操作 + - 创建集群 + - 删除集群 + - 创建备份任务 + - 恢复集群 + - 访问集群页面 + +- 不允许的操作: + + - 修改、暂停或恢复集群 + - 在 TiDB Cloud 控制台中更改安全设置 + - 创建私有链接或配置 VPC 对等连接 + - 创建导入任务、迁移任务或变更数据捕获任务 + - 调整迁移任务或变更数据捕获任务的规格 + +## 获取维护时间窗口通知 + +为了避免潜在的中断,了解维护计划并相应地规划您的操作很重要。 + +对于每个维护时间窗口,TiDB Cloud 会在以下时间点向所有项目成员发送四封电子邮件通知: + +- 维护时间窗口开始前两周(不包括紧急维护任务) +- 维护时间窗口开始前 72 小时 +- 维护时间窗口开始时 +- 维护时间窗口完成时 + +## 查看和配置维护时间窗口 + +定期维护确保执行必要的更新,以保护 TiDB Cloud 免受安全威胁、性能问题和不可靠性的影响。因此,维护时间窗口默认启用且无法禁用。 + +> **注意:** +> +> - 对于您首次注册 TiDB Cloud 时自动创建的默认项目,维护时间窗口在每周三 03:00 AM 开始(基于您的 TiDB Cloud 组织的时区)。 +> - 对于您创建的新项目,您可以在项目设置期间为维护时间窗口设置自定义开始时间。 + +您可以按照以下步骤将开始时间修改为您的首选时间或在截止日期前重新安排维护任务: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到您的目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **维护**。 +3. 在**维护**页面上,查看维护信息。 + + - 如果显示任何维护任务,请查看描述、计划开始时间和截止日期。维护任务将在指定时间开始。 + + - 如果没有维护数据,则表示最近没有计划维护任务。 + +4. (可选)点击**维护时间窗口设置**以修改维护时间窗口的开始时间。请注意,只有在该周计划有维护时间窗口时,才会在指定的开始时间执行维护。 + +5. 要重新安排特定维护任务,请在**操作**列中点击 **...** > **重新安排**,并在截止日期前选择新时间。 + + 如果您需要将维护任务重新安排到截止日期之后,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md#tidb-cloud-support)寻求帮助。 + +## 常见问题 + +- 什么是维护任务? + + 维护任务通常包括操作系统更新、安全补丁和基础设施升级。 + +- 我可以禁用维护时间窗口吗? + + 不可以。维护时间窗口默认启用且无法禁用。您可以修改维护时间窗口的开始时间或在截止日期前重新安排维护任务。更多信息,请参见[查看和配置维护时间窗口](#查看和配置维护时间窗口)。 + +- 维护时间窗口持续多长时间? + + 这取决于具体情况。对于每个项目,维护会逐个在符合条件的 TiDB 集群上执行。维护持续时间因集群数量、集群数据大小和要执行的维护任务而异。 + +- 维护任务会在任何状态的集群上执行吗? + + 不会。TiDB Cloud 在对集群执行维护任务之前会检查集群状态。 + + - 如果集群处于**创建中**或**已暂停**状态,则不需要维护任务。 + - 如果集群正在运行自动或手动备份,维护将延迟并等待当前备份成功完成后触发。请注意,对于数据量大的集群,备份过程可能需要很长时间,例如 12 小时。为了最大限度地减少对集群的影响,建议仔细设置备份和维护时间窗口的开始时间。 + - 如果集群处于任何其他状态,维护任务将按计划开始。 diff --git a/tidb-cloud/configure-security-settings.md b/tidb-cloud/configure-security-settings.md new file mode 100644 index 000000000000..0d3035f2e13e --- /dev/null +++ b/tidb-cloud/configure-security-settings.md @@ -0,0 +1,27 @@ +--- +title: 配置集群密码设置 +summary: 了解如何配置连接到集群的 root 密码。 +--- + +# 配置集群密码设置 + +对于 TiDB Cloud Dedicated 集群,你可以配置 root 密码和允许的 IP 地址来连接到你的集群。 + +> **注意:** +> +> 对于 TiDB Cloud Serverless 集群,本文档不适用,你可以参考 [TiDB Cloud Serverless 的 TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md)。 + +1. 在 TiDB Cloud 控制台中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 在目标集群所在行,点击 **...** 并选择**密码设置**。 +3. 设置连接到集群的 root 密码,然后点击**保存**。 + + 你可以点击**自动生成密码**生成随机密码。生成的密码不会再次显示,因此请将密码保存在安全的位置。 + +> **提示:** +> +> 如果你正在查看集群的概览页面,也可以点击页面右上角的 **...**,选择**密码设置**,并配置这些设置。 diff --git a/tidb-cloud/configure-serverless-firewall-rules-for-public-endpoints.md b/tidb-cloud/configure-serverless-firewall-rules-for-public-endpoints.md new file mode 100644 index 000000000000..9da5f00b59e6 --- /dev/null +++ b/tidb-cloud/configure-serverless-firewall-rules-for-public-endpoints.md @@ -0,0 +1,58 @@ +--- +title: 为 TiDB Cloud Serverless 公共端点配置防火墙规则 +summary: 了解如何安全地配置和管理 TiDB Cloud Serverless 集群的公共访问防火墙规则。 +--- + +# 为 TiDB Cloud Serverless 公共端点配置防火墙规则 + +本文档介绍 TiDB Cloud Serverless 的公共连接选项。你将了解通过互联网安全管理 TiDB Cloud Serverless 集群访问的关键概念。 + +> **注意:** +> +> 本文档适用于 **TiDB Cloud Serverless**。有关配置 **TiDB Cloud Dedicated** IP 访问列表的说明,请参阅[为 TiDB Cloud Dedicated 配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md)。 + +## 公共端点 + +在 TiDB Cloud Serverless 集群上配置公共访问允许通过公共端点访问集群。也就是说,可以通过互联网访问集群。公共端点是一个可公开解析的 DNS 地址。"授权网络"是指你选择允许访问集群的 IP 地址范围。这些权限通过**防火墙规则**强制执行。 + +### 公共访问的特点 + +- 只有指定的 IP 地址可以访问 TiDB Cloud Serverless。 + - 默认情况下,允许所有 IP 地址(`0.0.0.0 - 255.255.255.255`)。 + - 你可以在集群创建后更新允许的 IP 地址。 +- 你的集群有一个可公开解析的 DNS 名称。 +- 进出集群的网络流量通过**公共互联网**而不是私有网络路由。 + +### 防火墙规则 + +通过**防火墙规则**授予对 IP 地址的访问权限。如果连接尝试来自未经批准的 IP 地址,客户端将收到错误。 + +你最多可以创建 200 条 IP 防火墙规则。 + +### 允许 AWS 访问 + +你可以通过参考官方 [AWS IP 地址列表](https://docs.aws.amazon.com/vpc/latest/userguide/aws-ip-ranges.html)启用来自**所有 AWS IP 地址**的访问。 + +TiDB Cloud 定期更新此列表,并使用保留的 IP 地址 **169.254.65.87** 代表所有 AWS IP 地址。 + +## 创建和管理防火墙规则 + +本节介绍如何管理 TiDB Cloud Serverless 集群的防火墙规则。使用公共端点时,对 TiDB Cloud Serverless 集群的连接仅限于防火墙规则中指定的 IP 地址。 + +要向 TiDB Cloud Serverless 集群添加防火墙规则,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称以进入其概览页面。 + +2. 在左侧导航栏中,点击**设置** > **网络**。 + +3. 在**网络**页面上,如果**公共端点**已禁用,请启用它。在**授权网络**中,点击**+ 添加当前 IP**。这将自动创建一条包含你的计算机公共 IP 地址(由 TiDB Cloud 感知)的防火墙规则。 + + > **注意:** + > + > 在某些情况下,TiDB Cloud 控制台观察到的 IP 地址与访问互联网时使用的 IP 地址不同。因此,你可能需要更改起始和结束 IP 地址,以使规则按预期运行。你可以使用搜索引擎或其他在线工具检查自己的 IP 地址。例如,搜索"我的 IP 是什么"。 + +4. 点击**添加规则**以添加更多地址范围。在显示的窗口中,你可以指定单个 IP 地址或 IP 地址范围。如果要将规则限制为单个 IP 地址,请在**起始 IP 地址**和**结束 IP 地址**字段中输入相同的 IP 地址。打开防火墙后,管理员、用户和应用程序可以访问你的 TiDB Cloud Serverless 集群上拥有有效凭据的任何数据库。点击**提交**以添加防火墙规则。 + +## 下一步 + +- [通过公共端点连接到 TiDB Cloud Serverless](/tidb-cloud/connect-via-standard-connection-serverless.md) diff --git a/tidb-cloud/connect-to-tidb-cluster-serverless.md b/tidb-cloud/connect-to-tidb-cluster-serverless.md new file mode 100644 index 000000000000..fee74aa89a4b --- /dev/null +++ b/tidb-cloud/connect-to-tidb-cluster-serverless.md @@ -0,0 +1,62 @@ +--- +title: 连接到 TiDB Cloud Serverless 集群 +summary: 了解如何通过不同方法连接到 TiDB Cloud Serverless 集群。 +--- + +# 连接到 TiDB Cloud Serverless 集群 + +本文档介绍如何连接到 TiDB Cloud Serverless 集群。 + +> **提示:** +> +> 如需了解如何连接到 TiDB Cloud Dedicated 集群,请参阅[连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/connect-to-tidb-cluster.md)。 + +## 连接方法 + +在 TiDB Cloud 上创建 Serverless 集群后,你可以通过以下方法之一连接到集群: + +- 直接连接 + + 直接连接是指通过 TCP 的 MySQL 原生连接系统。你可以使用任何支持 MySQL 连接的工具(如 [MySQL 客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html))连接到 TiDB Cloud Serverless 集群。 + +- [数据服务(测试版)](/tidb-cloud/data-service-overview.md) + + TiDB Cloud 提供数据服务功能,使你能够通过自定义 API 端点使用 HTTPS 请求连接到 TiDB Cloud Serverless 集群。与直接连接不同,数据服务通过 RESTful API 而不是原始 SQL 访问 TiDB Cloud Serverless 数据。 + +- [Serverless 驱动(测试版)](/tidb-cloud/serverless-driver.md) + + TiDB Cloud 为 JavaScript 提供 Serverless 驱动,使你能够在边缘环境中以与直接连接相同的体验连接到 TiDB Cloud Serverless 集群。 + +在上述连接方法中,你可以根据需求选择合适的方法: + +| 连接方法 | 用户界面 | 使用场景 | +|-------------------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 直接连接 | SQL/ORM | 长期运行的环境,如 Java、Node.js 和 Python。 | +| 数据服务 | RESTful API | 所有浏览器和应用程序交互。 | +| Serverless 驱动 | SQL/ORM | Serverless 和边缘环境,如 [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions) 和 [Cloudflare Workers](https://workers.cloudflare.com/)。 | + +## 网络 + +TiDB Cloud Serverless 有两种网络连接类型: + +- [私有端点](/tidb-cloud/set-up-private-endpoint-connections-serverless.md)(推荐) + + 私有端点连接提供一个私有端点,允许你 VPC 中的 SQL 客户端通过 AWS PrivateLink 安全地访问服务。AWS PrivateLink 提供高度安全的单向访问数据库服务,并简化了网络管理。 + +- [公共端点](/tidb-cloud/connect-via-standard-connection-serverless.md) + + 标准连接暴露一个公共端点,因此你可以从笔记本电脑通过 SQL 客户端连接到 TiDB 集群。 + + TiDB Cloud Serverless 要求使用 [TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md),这确保了从应用程序到 TiDB 集群的数据传输安全。 + +下表显示了不同连接方法可以使用的网络: + +| 连接方法 | 网络 | 说明 | +|--------------------------|----------------------------|----------------------------------------------------------------------------------------------------------| +| 直接连接 | 公共或私有端点 | 直接连接可以通过公共和私有端点进行。 | +| 数据服务(测试版) | / | 通过数据服务(测试版)访问 TiDB Cloud Serverless 不需要指定网络类型。 | +| Serverless 驱动(测试版) | 公共端点 | Serverless 驱动仅支持通过公共端点连接。 | + +## 下一步 + +成功连接到 TiDB 集群后,你可以[使用 TiDB 探索 SQL 语句](/basic-sql-operations.md)。 diff --git a/tidb-cloud/connect-to-tidb-cluster.md b/tidb-cloud/connect-to-tidb-cluster.md new file mode 100644 index 000000000000..8668be87a7be --- /dev/null +++ b/tidb-cloud/connect-to-tidb-cluster.md @@ -0,0 +1,50 @@ +--- +title: 连接到您的 TiDB Cloud Dedicated 集群 +summary: 了解如何通过不同方法连接到您的 TiDB Cloud Dedicated 集群。 +--- + +# 连接到您的 TiDB Cloud Dedicated 集群 + +本文档介绍连接到您的 TiDB Cloud Dedicated 集群的方法。 + +> **提示:** +> +> 要了解如何连接到 TiDB Cloud Serverless 集群,请参见[连接到您的 TiDB Cloud Serverless 集群](/tidb-cloud/connect-to-tidb-cluster-serverless.md)。 + +在 TiDB Cloud 上创建 TiDB Cloud Dedicated 集群后,您可以通过以下方法之一连接到它: + +- 直接连接 + + 直接连接使用基于 TCP 的 MySQL 原生连接系统。您可以使用任何支持 MySQL 连接的工具连接到您的 TiDB Cloud Dedicated 集群,例如 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)。TiDB Cloud 还提供 [SQL Shell](/tidb-cloud/connect-via-sql-shell.md),使您能够尝试 TiDB SQL,快速测试 TiDB 与 MySQL 的兼容性,并管理用户权限。 + + TiDB Cloud Dedicated 提供三种网络连接类型: + + - [公共连接](/tidb-cloud/connect-via-standard-connection.md) + + 公共连接暴露一个带有流量过滤器的公共端点,因此您可以通过笔记本电脑上的 SQL 客户端连接到您的 TiDB 集群。您可以使用 TLS 连接到您的 TiDB 集群,这确保了从您的应用程序到 TiDB 集群的数据传输安全。更多信息,请参见[通过公共连接连接到 TiDB Cloud Dedicated](/tidb-cloud/connect-via-standard-connection.md)。 + + - 私有端点(推荐) + + 私有端点连接提供一个私有端点,允许您 VPC 中的 SQL 客户端安全地访问 TiDB Cloud Dedicated 集群。这使用不同云服务提供商提供的私有链接服务,通过简化的网络管理提供高度安全的单向数据库服务访问。 + + - 对于托管在 AWS 上的 TiDB Cloud Dedicated 集群,私有端点连接使用 AWS PrivateLink。更多信息,请参见[通过 AWS PrivateLink 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections.md)。 + - 对于托管在 Azure 上的 TiDB Cloud Dedicated 集群,私有端点连接使用 Azure Private Link。更多信息,请参见[通过 Azure Private Link 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md)。 + - 对于托管在 Google Cloud 上的 TiDB Cloud Dedicated 集群,私有端点连接使用 Google Cloud Private Service Connect。更多信息,请参见[通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 + + - [VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md) + + 如果您想要更低的延迟和更高的安全性,请设置 VPC 对等连接,并通过您云账户中相应云服务提供商的虚拟机实例使用私有端点进行连接。更多信息,请参见[通过 VPC 对等连接连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-vpc-peering-connections.md)。 + +- [内置 SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md) + + > **注意:** + > + > 要在 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群上使用 SQL 编辑器,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + + 如果您的集群托管在 AWS 上,且集群的 TiDB 版本是 v6.5.0 或更高版本,您可以在 [TiDB Cloud 控制台](https://tidbcloud.com/)中使用 AI 辅助的 SQL 编辑器来最大化您的数据价值。 + + 在 SQL 编辑器中,您可以手动编写 SQL 查询,或者在 macOS 上简单地按 + I(在 Windows 或 Linux 上按 Control + I)来指示 [Chat2Query (beta)](/tidb-cloud/tidb-cloud-glossary.md#chat2query) 自动生成 SQL 查询。这使您无需本地 SQL 客户端即可对数据库运行 SQL 查询。您可以直观地以表格或图表形式查看查询结果,并轻松检查查询日志。 + +## 下一步 + +成功连接到您的 TiDB 集群后,您可以[使用 TiDB 探索 SQL 语句](/basic-sql-operations.md)。 diff --git a/tidb-cloud/connect-via-sql-shell.md b/tidb-cloud/connect-via-sql-shell.md new file mode 100644 index 000000000000..ebc43e38d75c --- /dev/null +++ b/tidb-cloud/connect-via-sql-shell.md @@ -0,0 +1,24 @@ +--- +title: 通过 SQL Shell 连接 +summary: 了解如何通过 SQL Shell 连接到您的 TiDB 集群。 +--- + +# 通过 SQL Shell 连接 + +在 TiDB Cloud SQL Shell 中,您可以尝试 TiDB SQL,快速测试 TiDB 与 MySQL 的兼容性,并管理数据库用户权限。 + +> **注意:** +> +> 您不能使用 SQL Shell 连接到 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。要连接到您的 TiDB Cloud Serverless 集群,请参见[连接到 TiDB Cloud Serverless 集群](/tidb-cloud/connect-to-tidb-cluster-serverless.md)。 + +要使用 SQL shell 连接到您的 TiDB 集群,请执行以下步骤: + +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其集群概览页面,然后在左侧导航栏中点击**设置** > **网络**。 +3. 在**网络**页面上,点击右上角的 **Web SQL Shell**。 +4. 在提示的**输入密码**行中,输入当前集群的 root 密码。然后您的应用程序就连接到了 TiDB 集群。 diff --git a/tidb-cloud/connect-via-standard-connection-serverless.md b/tidb-cloud/connect-via-standard-connection-serverless.md new file mode 100644 index 000000000000..9a7cf82378d4 --- /dev/null +++ b/tidb-cloud/connect-via-standard-connection-serverless.md @@ -0,0 +1,68 @@ +--- +title: 通过公共端点连接到 TiDB Cloud Serverless +summary: 了解如何通过公共端点连接到您的 TiDB Cloud Serverless 集群。 +--- + +# 通过公共端点连接到 TiDB Cloud Serverless + +本文介绍如何通过公共端点从您的计算机使用 SQL 客户端连接到 TiDB Cloud Serverless 集群,以及如何禁用公共端点。 + +## 通过公共端点连接 + +> **提示:** +> +> 要了解如何通过公共端点连接到 TiDB Cloud Dedicated 集群,请参见[通过公共连接连接到 TiDB Cloud Dedicated](/tidb-cloud/connect-via-standard-connection.md)。 + +要通过公共端点连接到 TiDB Cloud Serverless 集群,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示连接对话框。 + +3. 在对话框中,保持连接类型的默认设置为 `Public`,并选择您首选的连接方法和操作系统以获取相应的连接字符串。 + + > **注意:** + > + > - 将连接类型保持为 `Public` 意味着通过标准 TLS 连接进行连接。更多信息,请参见[到 TiDB Cloud Serverless 的 TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md)。 + > - 如果您在**连接类型**下拉列表中选择**私有端点**,则表示通过私有端点进行连接。更多信息,请参见[通过私有端点连接到 TiDB Cloud Serverless](/tidb-cloud/set-up-private-endpoint-connections-serverless.md)。 + +4. TiDB Cloud Serverless 允许您为集群创建[分支](/tidb-cloud/branch-overview.md)。创建分支后,您可以通过**分支**下拉列表选择连接到该分支。`main` 代表集群本身。 + +5. 如果您还没有设置密码,点击**生成密码**生成随机密码。生成的密码不会再次显示,因此请将密码保存在安全的位置。 + +6. 使用连接字符串连接到您的集群。 + + > **注意:** + > + > 当您连接到 TiDB Cloud Serverless 集群时,必须在用户名中包含集群的前缀,并用引号将名称括起来。更多信息,请参见[用户名前缀](/tidb-cloud/select-cluster-tier.md#用户名前缀)。 + > 您的客户端 IP 必须在集群公共端点的允许 IP 规则中。更多信息,请参见[为公共端点配置 TiDB Cloud Serverless 防火墙规则](/tidb-cloud/configure-serverless-firewall-rules-for-public-endpoints.md)。 + +## 禁用公共端点 + +如果您不需要使用 TiDB Cloud Serverless 集群的公共端点,可以禁用它以防止来自互联网的连接: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 在左侧导航栏中,点击**设置** > **网络**。 + +3. 在**网络**页面上,点击**禁用**。将显示确认对话框。 + +4. 在确认对话框中点击**禁用**。 + +禁用公共端点后,连接对话框中**连接类型**下拉列表中的 `Public` 条目将被禁用。如果用户仍然尝试从公共端点访问集群,他们将收到错误。 + +> **注意:** +> +> 禁用公共端点不会影响现有连接。它只会阻止来自互联网的新连接。 + +禁用后,您可以重新启用公共端点: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 在左侧导航栏中,点击**设置** > **网络**。 + +3. 在**网络**页面上,点击**启用**。 + +## 下一步 + +成功连接到 TiDB 集群后,您可以[使用 TiDB 探索 SQL 语句](/basic-sql-operations.md)。 diff --git a/tidb-cloud/connect-via-standard-connection.md b/tidb-cloud/connect-via-standard-connection.md new file mode 100644 index 000000000000..641d19ae2bce --- /dev/null +++ b/tidb-cloud/connect-via-standard-connection.md @@ -0,0 +1,44 @@ +--- +title: 通过公共连接连接到 TiDB Cloud Dedicated +summary: 了解如何通过公共连接连接到 TiDB Cloud 集群。 +--- + +# 通过公共连接连接到 TiDB Cloud Dedicated + +本文档介绍如何通过公共连接连接到 TiDB Cloud Dedicated 集群。公共连接暴露了一个带有流量过滤器的公共端点,因此你可以通过笔记本电脑上的 SQL 客户端连接到 TiDB Cloud Dedicated 集群。 + +> **提示:** +> +> 要了解如何通过公共连接连接到 TiDB Cloud Serverless 集群,请参阅[通过公共端点连接到 TiDB Cloud Serverless](/tidb-cloud/connect-via-standard-connection-serverless.md)。 + +## 前提条件:配置 IP 访问列表 + +对于公共连接,TiDB Cloud Dedicated 只允许来自 IP 访问列表中地址的客户端连接。如果你尚未配置 IP 访问列表,请在首次连接之前按照[配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md)中的步骤进行配置。 + +## 连接到集群 + +要通过公共连接连接到 TiDB Cloud Dedicated 集群,请执行以下步骤: + +1. 打开目标集群的概览页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称以进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个连接对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**。 + + 如果你尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md)中的步骤进行配置,然后再进行首次连接。 + +4. 点击 **CA 证书**下载用于 TLS 连接到 TiDB 集群的 CA 证书。CA 证书默认支持 TLS 1.2 版本。 + +5. 选择你喜欢的连接方式,然后参考选项卡上的连接字符串和示例代码连接到你的集群。 + +## 下一步 + +成功连接到 TiDB 集群后,你可以[使用 TiDB 探索 SQL 语句](/basic-sql-operations.md)。 diff --git a/tidb-cloud/connected-ai-chat-in-im.md b/tidb-cloud/connected-ai-chat-in-im.md new file mode 100644 index 000000000000..12f9802a6e9a --- /dev/null +++ b/tidb-cloud/connected-ai-chat-in-im.md @@ -0,0 +1,16 @@ +--- +title: "Connected:即时通讯中的 AI 聊天" +summary: 介绍即时通讯(IM)中 AI 聊天的详细信息。 +--- + +# Connected:即时通讯中的 AI 聊天 + +由 PingCAP 提供支持的即时通讯(IM)中的 AI 聊天,是一项将 TiDB AI 助手聊天机器人邀请到特定 IM 频道进行初步技术支持和咨询的服务。该服务基于 [TiDB 向量搜索](/tidb-cloud/vector-search-overview.md)构建的 Graph RAG(检索增强生成)技术。 + +## 限制 + +目前,[Slack](https://slack.com/) 和 [Lark](https://www.larksuite.com/)(飞书)的工单支持功能需要申请才能使用。如果你对尝试此功能感兴趣,请通过 support@pingcap.com 联系 TiDB Cloud 支持团队,或联系你的技术客户经理(TAM)。 + +## 示例 + +![ai-chat-example](/media/tidb-cloud/connected-ai-chat-example.png) diff --git a/tidb-cloud/connected-care-detail.md b/tidb-cloud/connected-care-detail.md new file mode 100644 index 000000000000..9f7e4c91ce6b --- /dev/null +++ b/tidb-cloud/connected-care-detail.md @@ -0,0 +1,144 @@ +--- +title: Connected Care 详细信息 +summary: 介绍 TiDB Cloud 的 Connected Care 支持服务的详细信息。 +--- + +# Connected Care 详细信息 + +本文提供了 [Connected Care](/tidb-cloud/connected-care-overview.md) 支持服务的详细信息。 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
支持计划BasicDeveloperEnterprisePremium
功能和服务适合个人入门项目,通过活跃的社区和 AI 支持为您提供基本支持需求。适合开发和测试阶段,提供直接连接和无限技术支持访问,帮助您开启云端之旅。专为生产工作负载设计,通过高级监控、及时警报和全天候快速响应,为您提供无缝体验。为关键业务工作负载打造,通过指定的技术客户经理提供最快的响应时间、主动支持和专属连接。
初始响应时间-S1:4 个工作小时S1:1 小时S1:30 分钟
-S2:8 个工作小时S2:2 小时S2:1 小时
-S3:12 个工作小时S3:8 个工作小时S3:4 个工作小时
-S4:24 个工作小时S4:24 个工作小时S4:24 个工作小时
服务账单和账户支持账单和账户支持账单和账户支持账单和账户支持
-工单技术支持工单技术支持工单技术支持
-端到端数据库指导端到端数据库指导端到端数据库指导
--Connected:高级监控的诊所服务Connected:高级监控的诊所服务
--Connected:即时通讯中的 AI 聊天Connected:即时通讯中的 AI 聊天
--Connected:TiDB Cloud 警报的即时通讯订阅(通过 SlackZoomConnected:TiDB Cloud 警报的即时通讯订阅(通过 SlackZoom
--Connected:即时通讯工单创建和更新订阅(通过 SlackLarkConnected:即时通讯工单创建和更新订阅(通过 SlackLark
---Connected:支持工单的即时通讯交互(通过 SlackLark
---技术客户经理
客户资源文档文档文档文档
常见问题常见问题常见问题常见问题
社区工作空间社区工作空间社区工作空间社区工作空间
TiDB.AITiDB.AITiDB.AITiDB.AI
-知识库知识库知识库
+ +- 工作时间:当地时间周一至周五上午 9 点至下午 6 点 +- IM:即时通讯。目前支持 [Slack](https://slack.com/) 和 [Lark](https://www.larksuite.com/)。我们计划在未来支持 [Microsoft Teams](https://www.microsoft.com/en-us/microsoft-teams/group-chat-software)。 +- [Clinic](https://clinic.pingcap.com/):一个现代化的监控服务,为您的 TiDB Cloud 集群提供高级监控和诊断功能。 diff --git a/tidb-cloud/connected-care-overview.md b/tidb-cloud/connected-care-overview.md new file mode 100644 index 000000000000..8c98fd14024f --- /dev/null +++ b/tidb-cloud/connected-care-overview.md @@ -0,0 +1,102 @@ +--- +title: Connected Care 概述 +summary: 介绍新一代 TiDB Cloud 支持服务 - Connected Care。 +aliases: ['/tidbcloud/connected-care-announcement'] +--- + +# Connected Care 概述 + +随着各种规模的客户继续在 TiDB Cloud 上扩展用例和运营,TiDB Cloud 致力于重新构想其支持服务,以适应客户不断发展的需求。为了提供更大的价值和无缝体验,TiDB Cloud 很高兴宣布在 **2025 年 2 月 17 日**推出新的支持服务 **Connected Care**。 + +作为此次转型的一部分,从 **2025 年 2 月 17 日**起,当前的支持计划将不再提供购买,并被归类为传统支持计划。但是,TiDB Cloud 将继续为订阅传统计划的客户提供全面支持,直至其各自的[退役日期](#迁移到-connected-care)。 + +为确保平稳过渡并获取最新功能,TiDB Cloud 鼓励客户迁移并采用 Connected Care 服务。 + +## Connected Care + +Connected Care 服务旨在通过现代通信工具、主动支持和先进的 AI 功能加强您与 TiDB Cloud 的连接,提供无缝和以客户为中心的体验。 + +在 Connected Care 服务中,有四种支持计划:**Basic**、**Developer**(对应传统的 **Standard** 计划)、**Enterprise** 和 **Premium**。 + +> **注意** +> +> 虽然 **Basic**、**Enterprise** 和 **Premium** 支持计划使用与传统计划相同的计划名称,但它们指的是具有不同服务承诺的不同计划。 + +下表概述了 Connected Care 服务中的每个支持计划。更多信息,请参见 [Connected Care 详情](/tidb-cloud/connected-care-detail.md)。 + +| 支持计划 | Basic | Developer | Enterprise | Premium | +|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------|:---------------------------------------------|:-----------------------------------------------|:------------------------------------------| +| 推荐工作负载 | 个人或入门项目 | 开发中的工作负载 | 生产中的工作负载 | 生产中的关键业务工作负载 | +| 账单和账户支持 | ✔ | ✔ | ✔ | ✔ | +| 技术支持 | - | ✔ | ✔ | ✔ | +| 初始响应时间 | - | 工作时间 | 7x24 | 7x24 | +| [Connected:诊所服务](/tidb-cloud/tidb-cloud-clinic.md) | - | - | ✔ | ✔ | +| [Connected:即时通讯中的 AI 聊天](/tidb-cloud/connected-ai-chat-in-im.md) | - | - | ✔ | ✔ | +| Connected:TiDB Cloud 告警的即时通讯订阅([Slack](/tidb-cloud/monitor-alert-slack.md)、[Zoom](/tidb-cloud/monitor-alert-zoom.md)) | - | - | ✔ | ✔ | +| Connected:工单创建和更新订阅([Slack](/tidb-cloud/connected-slack-ticket-creation.md)、[Lark](/tidb-cloud/connected-lark-ticket-creation.md)) | - | - | ✔ | ✔ | +| Connected:支持工单的即时通讯交互([Slack](/tidb-cloud/connected-slack-ticket-interaction.md)、[Lark](/tidb-cloud/connected-lark-ticket-interaction.md)) | - | - | - | ✔ | +| 技术客户经理 | - | - | - | ✔ | + +> **注意** +> +> 所有四种支持计划的客户都可以访问 [PingCAP 支持门户](https://tidb.support.pingcap.com/)进行服务请求。 + +## 传统支持服务与 Connected Care 支持服务的区别 + +Connected Care 服务中的支持计划引入了一套全新的功能,如下所示: + +- Connected:诊所服务 + + 此功能提供先进的监控和诊断服务 Clinic,旨在帮助您通过详细分析和可操作的见解快速识别性能问题、优化数据库并提高整体性能。更多信息,请参见 [Connected:诊所服务](/tidb-cloud/tidb-cloud-clinic.md)。 + +- Connected:即时通讯中的 AI 聊天 + + 此功能使您能够通过即时通讯(IM)工具与 AI 助手聊天,立即获得问题的答案。更多信息,请参见 [Connected:即时通讯中的 AI 聊天](/tidb-cloud/connected-ai-chat-in-im.md)。 + +- Connected:TiDB Cloud 告警的即时通讯订阅 + + 此功能为您提供了一种通过即时通讯工具订阅告警通知的简便方法,让您随时了解重要更新。更多信息,请参见[通过 Slack 订阅](/tidb-cloud/monitor-alert-slack.md)和[通过 Zoom 订阅](/tidb-cloud/monitor-alert-zoom.md)。 + +- Connected:工单创建和更新订阅 + + 此功能使您能够通过即时通讯工具创建支持工单并订阅工单更新。更多信息,请参见[通过 Slack 创建工单和订阅工单更新](/tidb-cloud/connected-slack-ticket-creation.md)和[通过 Lark 创建工单和订阅工单更新](/tidb-cloud/connected-lark-ticket-creation.md)。 + +- Connected:支持工单的即时通讯交互 + + 此功能使您能够通过即时通讯工具快速创建和处理支持工单,实现流畅的沟通。更多信息,请参见[通过 Slack 与支持工单交互](/tidb-cloud/connected-slack-ticket-interaction.md)和[通过 Lark 与支持工单交互](/tidb-cloud/connected-lark-ticket-interaction.md)。 + +通过这些新功能,Connected Care 服务为不同客户需求提供更好的连接性、更个性化的支持和更具成本效益的解决方案。 + +- 新的 **Enterprise** 和 **Premium** 计划:通过 Clinic 中的高级监控服务、TiDB Cloud 告警的即时通讯订阅、工单更新的即时通讯订阅、即时通讯中的 AI 聊天以及支持工单的即时通讯交互,将客户与现代通信工具和先进的 AI 功能连接起来。 + +- 新的 **Developer** 计划:客户除了享有与 **Basic** 计划相同的社区和 [TiDB.AI](https://tidb.ai/) 帮助外,还可以直接获得无限制的技术支持。 + +- 新的 **Basic** 计划:客户将被引导加入活跃的社区渠道,在那里他们可以与其他社区成员互动,并与 [TiDB.AI](https://tidb.ai/) 进行技术交流。 + +## 迁移到 Connected Care + +下表列出了传统支持计划的关闭时间表: + +| 支持计划 | 关闭日期 | +|:----------------------------------------|:--------------| +| 传统 **Basic** 计划 | 2025 年 2 月 17 日 | +| 传统 **Standard** 计划 | 2025 年 2 月 17 日 | +| 传统 **Enterprise** 和 **Premium** 计划 | 2026 年 1 月 15 日 | + +一旦传统支持计划关闭,TiDB Cloud 将不再支持它。如果您在相关关闭日期之前没有迁移到 Connected Care 中的任何支持计划,您将自动迁移到 Connected Care 中的 **Basic** 支持计划。 + +## 常见问题 + +### 如何查看或更改我当前的支持计划? + +在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,点击左下角的**支持**。将显示**支持**页面,您当前的支持计划会用 **CURRENT** 标签突出显示。 + +您可以在**支持**页面上迁移到新的支持计划,但 **Premium** 支持计划除外。要升级到 **Premium** 计划,请[联系销售](https://www.pingcap.com/contact-us)。 + +### 我需要为类似的服务支付更多费用吗? + +虽然新的 Connected Care 服务提供了更全面和功能更丰富的支持体验,但定价仍与之前的产品保持一致。TiDB Cloud 仍然致力于提供更多价值,以更好地支持您的发展历程。 + +### 传统 **Basic** 计划关闭后,我如何获得技术支持? + +您仍然可以获得[账单和账户支持](/tidb-cloud/tidb-cloud-support.md#create-an-account-or-billing-support-ticket)。对于技术支持,请考虑购买 Connected Care 服务中的支持计划。建议您从包含一个月免费试用的 **Developer** 计划开始。 diff --git a/tidb-cloud/connected-lark-ticket-creation.md b/tidb-cloud/connected-lark-ticket-creation.md new file mode 100644 index 000000000000..9e619f3d4537 --- /dev/null +++ b/tidb-cloud/connected-lark-ticket-creation.md @@ -0,0 +1,42 @@ +--- +title: 通过 Lark 创建工单和订阅工单更新 +summary: 介绍 Lark 工单创建和更新订阅的详细信息。 +--- + +# 通过 Lark 创建工单和订阅工单更新 + +对于订阅了 **Enterprise** [支持计划](/tidb-cloud/connected-care-detail.md)的客户,TiDB Cloud 在 [Lark](https://www.larksuite.com/) 中提供了一个名为 **PingCAP Support Bot** 的工单机器人,用于管理支持工单系统中的工单创建和更新。 + +> **注意:** +> +> Lark 的工单支持功能需要申请才能使用。如果您有兴趣尝试此功能,请通过 support@pingcap.com 联系 TiDB Cloud 支持团队,或联系您的技术客户经理(TAM)。 + +## 创建支持工单 + +在 **Customer Support Group** Lark 群组中,在消息中输入 `@PingCAP Support Bot create ticket`。然后,**PingCAP Support Bot** 将回复一个用于创建工单的 Lark 消息卡片。 + +![lark-ticket-creation-1](/media/tidb-cloud/connected-lark-ticket-creation-1.png) + +填写必填字段并点击**提交**。提交后,卡片将更新为**工单已提交**,表示您的请求正在处理中。 + +![lark-ticket-creation-2](/media/tidb-cloud/connected-lark-ticket-creation-2.png) + +支持工单创建后,**工单已提交**卡片将更新为**支持工单已创建**卡片,提供工单名称和查看工单的链接。 + +![lark-ticket-creation-3](/media/tidb-cloud/connected-lark-ticket-creation-3.png) + +## 订阅工单更新 + +每当 PingCAP 支持工程师在工单上发表评论时,**PingCAP Support Bot** 将向 Lark 群组发送一个**工单新评论**卡片。 + +![connected-lark-ticket-creation-4](/media/tidb-cloud/connected-lark-ticket-creation-4.png) + +## 常见问题 + +- 如何查看我的工单状态? + + 使用创建工单时使用的电子邮件地址登录 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/user/requests)。您可以查看当前账户的所有历史工单及其状态。 + +## 联系支持 + +如需帮助或有任何问题,请通过 support@pingcap.com 联系我们的支持团队。 diff --git a/tidb-cloud/connected-lark-ticket-interaction.md b/tidb-cloud/connected-lark-ticket-interaction.md new file mode 100644 index 000000000000..f2a46824c3b9 --- /dev/null +++ b/tidb-cloud/connected-lark-ticket-interaction.md @@ -0,0 +1,32 @@ +--- +title: 通过飞书与支持工单互动 +summary: 介绍支持工单的飞书互动详细信息 +--- + +# 通过飞书与支持工单互动 + +对于订阅了**高级**[支持计划](/tidb-cloud/connected-care-detail.md)的客户,TiDB Cloud 在[飞书](https://www.larksuite.com/)中提供了一个名为 **PingCAP Support Bot** 的工单机器人,以支持更全面的支持工单互动和管理。 + +> **注意:** +> +> 飞书的工单支持功能需要申请才能使用。如果你对尝试此功能感兴趣,请通过 support@pingcap.com 联系 TiDB Cloud 支持团队,或联系你的技术客户经理(TAM)。 + +## 与支持工单互动 + +如果启用了支持工单互动功能,**PingCAP Support Bot** 会将**支持工单已创建**消息卡片转换为一个线程来管理工单互动。 + +![lark-ticket-interaction-1](/media/tidb-cloud/connected-lark-ticket-interaction-1.png) + +当 PingCAP 支持工程师在工单上发表评论时,评论会自动同步到线程中。 + +当任何人在线程中发表评论时,评论会同步回相应的支持工单。 + +## 常见问题 + +- 如何查看我的工单状态? + + 使用创建工单时使用的电子邮件地址登录 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/user/requests)。你可以查看当前账户的所有历史工单及其状态。 + +## 联系支持 + +如需帮助或有任何问题,请通过 support@pingcap.com 联系我们的支持团队。 diff --git a/tidb-cloud/connected-slack-ticket-creation.md b/tidb-cloud/connected-slack-ticket-creation.md new file mode 100644 index 000000000000..8c54afcad3c4 --- /dev/null +++ b/tidb-cloud/connected-slack-ticket-creation.md @@ -0,0 +1,44 @@ +--- +title: 在 Slack 中创建工单和订阅工单更新 +summary: 介绍在 Slack 中创建工单和订阅工单更新的详细信息。 +--- + +# 在 Slack 中创建工单和订阅工单更新 + +对于订阅了**企业版**[支持计划](/tidb-cloud/connected-care-detail.md)的客户,TiDB Cloud 在 [Slack](https://slack.com/) 中提供了一个名为 **PingCAP Support Bot** 的工单机器人,以支持快速创建工单。 + +> **注意:** +> +> Slack 的工单支持功能需要申请才能使用。如果你对尝试此功能感兴趣,请通过 support@pingcap.com 联系 TiDB Cloud 支持团队,或联系你的技术客户经理(TAM)。 + +## 创建支持工单 + +在 Slack 支持频道中,你只需要在消息中提及 **PingCAP Support Bot** 并描述问题。然后,工单机器人会向你发送一条带有**提出请求**按钮的消息。 + +![slack-ticket-creation-1](/media/tidb-cloud/connected-slack-ticket-creation-1.png) + +点击**提出请求**打开表单,根据问题填写表单,然后点击**创建**提交工单。 + +![slack-ticket-creation-2](/media/tidb-cloud/connected-slack-ticket-creation-2.png) + +成功创建工单后,机器人会回复工单链接。你可以点击链接在 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/portals)查看工单详情。 + +![slack-ticket-creation-3](/media/tidb-cloud/connected-slack-ticket-creation-3.png) + +![slack-ticket-creation-4](/media/tidb-cloud/connected-slack-ticket-creation-4.png) + +## 订阅工单更新 + +**企业版**支持计划支持在 Slack 中订阅工单更新。当支持工程师回复工单时,工单更新消息会出现在 Slack 频道中。该消息包括工单标题、工单链接和最新评论内容等信息。 + +![slack-ticket-creation-5](/media/tidb-cloud/connected-slack-ticket-creation-5.png) + +## 常见问题 + +- 如何查看我的工单状态? + + 使用创建工单时使用的电子邮件地址登录 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/user/requests)。你可以查看当前账户的所有历史工单及其状态。 + +## 联系支持 + +如需帮助或有任何问题,请通过 support@pingcap.com 联系我们的支持团队。 diff --git a/tidb-cloud/connected-slack-ticket-interaction.md b/tidb-cloud/connected-slack-ticket-interaction.md new file mode 100644 index 000000000000..03831b44afdd --- /dev/null +++ b/tidb-cloud/connected-slack-ticket-interaction.md @@ -0,0 +1,52 @@ +--- +title: 通过 Slack 与支持工单交互 +summary: 介绍 Slack 支持工单交互的详细信息。 +--- + +# 通过 Slack 与支持工单交互 + +对于订阅了 **Premium** [支持计划](/tidb-cloud/connected-care-detail.md)的客户,TiDB Cloud 在 [Slack](https://slack.com/) 中提供了一个名为 **PingCAP Support Bot** 的工单机器人,以支持更全面的支持工单交互和管理。 + +> **注意:** +> +> Slack 的工单支持功能需要申请才能使用。如果您有兴趣尝试此功能,请通过 support@pingcap.com 联系 TiDB Cloud 支持团队,或联系您的技术客户经理(TAM)。 + +您可以使用 **PingCAP Support Bot** 在 Slack 中创建支持工单: + +![在 Slack 中创建支持工单](/media/tidb-cloud/connected-slack-ticket-interaction-creation.gif) + +您也可以直接在 Slack 中回复支持工单: + +![在 Slack 中回复支持工单](/media/tidb-cloud/connected-slack-ticket-interaction-reply.gif) + +## 与支持工单交互 + +在 Slack 支持频道中,您只需要在消息中提及 **PingCAP Support Bot** 并描述问题。然后,机器人会向您发送一条带有**提出请求**按钮的消息。 + +![slack-ticket-interaction-1](/media/tidb-cloud/connected-slack-ticket-interaction-1.png) + +点击**提出请求**打开表单,根据问题填写表单,然后点击**创建**提交工单。 + +![slack-ticket-interaction-2](/media/tidb-cloud/connected-slack-ticket-interaction-2.png) + +提交后,机器人会在消息线程中发送一条确认消息,其中包含工单链接。 + +![slack-ticket-interaction-3](/media/tidb-cloud/connected-slack-ticket-interaction-3.png) + +对于订阅了 **Premium** [支持计划](/tidb-cloud/connected-care-detail.md)的客户,支持 Slack 和工单系统之间的双向信息同步。 + +支持工程师在工单上的评论将同步到 Slack 消息线程中,用户无需跳转到支持门户即可查看。用户可以直接在此消息线程中回复,这些回复将同步到工单系统。 + +通过这种方式,订阅了 **Premium** 支持计划的客户无需离开 Slack 即可快速创建、响应和管理工单。 + +![slack-ticket-interaction-4](/media/tidb-cloud/connected-slack-ticket-interaction-4.png) + +## 常见问题 + +- 如何查看我的工单状态? + + 使用创建工单时使用的电子邮件地址登录 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/user/requests)。您可以查看当前账户的所有历史工单及其状态。 + +## 联系支持 + +如需帮助或有任何问题,请通过 support@pingcap.com 联系我们的支持团队。 diff --git a/tidb-cloud/cppo-customer.md b/tidb-cloud/cppo-customer.md new file mode 100644 index 000000000000..70396f32d8e3 --- /dev/null +++ b/tidb-cloud/cppo-customer.md @@ -0,0 +1,32 @@ +--- +title: 代理商的客户 +summary: 了解如何成为代理商的客户。 +--- + +# 代理商的客户 + +代理商的客户通过 AWS Marketplace 中的代理商订阅 TiDB Cloud 服务。 + +与直接的 TiDB Cloud 客户不同,代理商的客户通过 AWS Marketplace 而不是直接向 PingCAP 支付账单。但是,对于 AWS Marketplace Channel Partner Private Offer (CPPO) 和直接 TiDB Cloud 客户来说,TiDB Cloud 控制台中的所有其他日常操作都是相同的。 + +本文档概述了如何查看未来和历史账单。 + +## 从直接 TiDB Cloud 账户迁移到代理商的客户账户 + +> **提示:** +> +> 直接客户是直接从 PingCAP 购买 TiDB Cloud 并向其支付账单的最终客户。 + +如果你目前是拥有 TiDB Cloud 账户的直接客户,你可以请你的代理商将你的账户迁移到代理商的客户账户。 + +迁移将在未来某个月的第一天生效。请与你的代理商讨论确定具体的生效日期。 + +在迁移生效当天,你将收到电子邮件通知。 + +## 查看你的未来账单 + +作为代理商的客户,你的账单将通过 AWS Marketplace 处理和支付。 + +## 查看你的历史账单 + +如果你已经从直接 TiDB Cloud 账户迁移到代理商的客户账户,你仍然可以访问迁移之前的账单历史记录。要查看这些记录,请在 TiDB Cloud 控制台中转到**计费** > **账单** > **历史记录**。 diff --git a/tidb-cloud/create-tidb-cluster-serverless.md b/tidb-cloud/create-tidb-cluster-serverless.md new file mode 100644 index 000000000000..40f6ed553808 --- /dev/null +++ b/tidb-cloud/create-tidb-cluster-serverless.md @@ -0,0 +1,53 @@ +--- +title: 创建 TiDB Cloud Serverless 集群 +summary: 了解如何创建 TiDB Cloud Serverless 集群。 +--- + +# 创建 TiDB Cloud Serverless 集群 + +本文档介绍如何在 [TiDB Cloud 控制台](https://tidbcloud.com/)中创建 TiDB Cloud Serverless 集群。 + +> **提示:** +> +> 要了解如何创建 TiDB Cloud Dedicated 集群,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +## 开始之前 + +如果您还没有 TiDB Cloud 账户,请点击[此处](https://tidbcloud.com/signup)注册账户。 + +- 您可以使用电子邮件和密码注册,这样您就可以使用 TiDB Cloud 管理您的密码,也可以使用您的 Google、GitHub 或 Microsoft 账户注册。 +- 对于 AWS Marketplace 用户,您也可以通过 AWS Marketplace 注册。为此,在 [AWS Marketplace](https://aws.amazon.com/marketplace) 中搜索 `TiDB Cloud`,订阅 TiDB Cloud,然后按照屏幕上的说明设置您的 TiDB Cloud 账户。 +- 对于 Azure Marketplace 用户,您也可以通过 Azure Marketplace 注册。为此,在 [Azure Marketplace](https://azuremarketplace.microsoft.com) 中搜索 `TiDB Cloud`,订阅 TiDB Cloud,然后按照屏幕上的说明设置您的 TiDB Cloud 账户。 +- 对于 Google Cloud Marketplace 用户,您也可以通过 Google Cloud Marketplace 注册。为此,在 [Google Cloud Marketplace](https://console.cloud.google.com/marketplace) 中搜索 `TiDB Cloud`,订阅 TiDB Cloud,然后按照屏幕上的说明设置您的 TiDB Cloud 账户。 + +## 步骤 + +如果您是 `Organization Owner` 或 `Project Owner` 角色,您可以按照以下步骤创建 TiDB Cloud Serverless 集群: + +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),然后导航到[**集群**](https://tidbcloud.com/project/clusters)页面。 + +2. 点击**创建集群**。 + +3. 在**创建集群**页面上,默认选择 **Serverless**。 + +4. TiDB Cloud Serverless 的云服务提供商是 AWS。您可以选择要托管集群的 AWS 区域。 + +5. 如有必要,更新默认的集群名称。 + +6. 选择集群方案。TiDB Cloud Serverless 提供两种[集群方案](/tidb-cloud/select-cluster-tier.md#cluster-plans):**免费集群**和**可扩展集群**。您可以从免费集群开始,随着需求增长再升级到可扩展集群。要创建可扩展集群,您需要指定**每月支出限额**并添加信用卡。 + + > **注意:** + > + > 对于 TiDB Cloud 中的每个组织,默认情况下您最多可以创建五个[免费集群](/tidb-cloud/select-cluster-tier.md#free-cluster-plan)。要创建更多 TiDB Cloud Serverless 集群,您需要添加信用卡并创建[可扩展集群](/tidb-cloud/select-cluster-tier.md#scalable-cluster-plan)。 + +7. 点击**创建**。 + + 集群创建过程开始,您的 TiDB Cloud 集群将在大约 30 秒内创建完成。 + +## 下一步 + +集群创建完成后,按照[通过公共端点连接到 TiDB Cloud Serverless](/tidb-cloud/connect-via-standard-connection-serverless.md)中的说明为您的集群创建密码。 + +> **注意:** +> +> 如果您不设置密码,将无法连接到集群。 diff --git a/tidb-cloud/create-tidb-cluster.md b/tidb-cloud/create-tidb-cluster.md new file mode 100644 index 000000000000..298037aa04d5 --- /dev/null +++ b/tidb-cloud/create-tidb-cluster.md @@ -0,0 +1,96 @@ +--- +title: 创建 TiDB Cloud Dedicated 集群 +summary: 了解如何创建 TiDB Cloud Dedicated 集群。 +--- + +# 创建 TiDB Cloud Dedicated 集群 + +本教程将指导您注册并创建 TiDB Cloud Dedicated 集群。 + +> **提示:** +> +> 如需了解如何创建 TiDB Cloud Serverless 集群,请参阅[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)。 + +## 开始之前 + +如果您还没有 TiDB Cloud 账号,请点击[此处](https://tidbcloud.com/signup)注册账号。 + +- 您可以使用电子邮件和密码注册,这样可以通过 TiDB Cloud 管理密码,也可以使用 Google、GitHub 或 Microsoft 账号注册。 +- 对于 AWS Marketplace 用户,您也可以通过 AWS Marketplace 注册。只需在 [AWS Marketplace](https://aws.amazon.com/marketplace) 中搜索 `TiDB Cloud`,订阅 TiDB Cloud,然后按照屏幕上的说明设置您的 TiDB Cloud 账号。 +- 对于 Azure Marketplace 用户,您也可以通过 Azure Marketplace 注册。只需在 [Azure Marketplace](https://azuremarketplace.microsoft.com) 中搜索 `TiDB Cloud`,订阅 TiDB Cloud,然后按照屏幕上的说明设置您的 TiDB Cloud 账号。 +- 对于 Google Cloud Marketplace 用户,您也可以通过 Google Cloud Marketplace 注册。只需在 [Google Cloud Marketplace](https://console.cloud.google.com/marketplace) 中搜索 `TiDB Cloud`,订阅 TiDB Cloud,然后按照屏幕上的说明设置您的 TiDB Cloud 账号。 + +## (可选)步骤 1. 使用默认项目或创建新项目 + +登录 [TiDB Cloud 控制台](https://tidbcloud.com/)后,您会有一个默认的[项目](/tidb-cloud/tidb-cloud-glossary.md#project)。当您的组织中只有一个项目时,您的集群将在该项目中创建。有关项目的更多信息,请参阅[组织和项目](/tidb-cloud/manage-user-access.md#organizations-and-projects)。 + +如果您是组织所有者,可以根据需要按照以下步骤重命名默认项目或为集群创建新项目: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,点击左上角的组合框。将显示您的默认组织和项目。 + +2. 点击您组织的名称,然后点击左侧导航栏中的**项目**。 + +3. 在**项目**页面上,执行以下操作之一: + + - 要重命名默认项目,请在**操作**列中点击 **...** > **重命名**。 + - 要创建项目,请点击**创建新项目**,输入项目名称,然后点击**确认**。 + +4. 要转到项目的集群列表页面,请在**项目**页面上点击项目名称。 + +## 步骤 2. 创建 TiDB Cloud Dedicated 集群 + +如果您是`组织所有者`或`项目所有者`角色,可以按照以下步骤创建 TiDB Cloud Dedicated 集群: + +1. 导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击**创建集群**。 + +3. 在**创建集群**页面上,选择 **Dedicated**,然后按如下配置集群信息: + + 1. 选择云服务提供商和区域。 + + > **注意:** + > + > - 目前,Azure 上的 TiDB Cloud Dedicated 支持处于公开预览阶段。 + > - 如果您通过 [AWS Marketplace](https://aws.amazon.com/marketplace) 注册了 TiDB Cloud,云服务提供商为 AWS,且无法在 TiDB Cloud 中更改。 + > - 如果您通过 [Azure Marketplace](https://azuremarketplace.microsoft.com) 注册了 TiDB Cloud,云服务提供商为 Azure Cloud,且无法在 TiDB Cloud 中更改。 + > - 如果您通过 [Google Cloud Marketplace](https://console.cloud.google.com/marketplace) 注册了 TiDB Cloud,云服务提供商为 Google Cloud,且无法在 TiDB Cloud 中更改。 + + 2. 分别为 TiDB、TiKV 和 TiFlash(可选)配置[集群大小](/tidb-cloud/size-your-cluster.md)。 + 3. 如有必要,更新默认的集群名称和端口号。 + 4. 如果尚未为该区域配置 CIDR,则需要设置 CIDR。如果您没有看到**项目 CIDR**字段,则表示该区域已配置 CIDR。 + + > **注意:** + > + > - 当在此区域创建第一个集群时,TiDB Cloud 将使用此 CIDR 创建一个 VPC。同一项目在此区域的所有后续集群都将使用此 VPC。 + > - 设置 CIDR 时,避免与应用程序所在 VPC 的 CIDR 发生冲突。VPC 创建后无法修改 CIDR。 + +4. 确认右侧的集群和计费信息。 + +5. 如果您尚未添加付款方式,请点击右下角的**添加信用卡**。 + + > **注意:** + > + > 如果您通过 [AWS Marketplace](https://aws.amazon.com/marketplace)、[Azure Marketplace](https://azuremarketplace.microsoft.com) 或 [Google Cloud Marketplace](https://console.cloud.google.com/marketplace) 注册了 TiDB Cloud,您可以直接通过 AWS 账号、Azure 账号或 Google Cloud 账号付款,但无法在 TiDB Cloud 控制台中添加付款方式或下载发票。 + +6. 点击**创建**。 + + 您的 TiDB Cloud 集群将在大约 20 到 30 分钟内创建完成。 + +## 步骤 3. 设置 root 密码 + +集群创建完成后,按照以下步骤设置 root 密码: + +1. 在集群概览页面的右上角,点击 **...** 并选择**密码设置**。 + +2. 设置连接集群的 root 密码,然后点击**保存**。 + + 您可以点击**自动生成密码**生成随机密码。生成的密码不会再次显示,请将密码保存在安全的位置。 + +## 下一步 + +在 TiDB Cloud 上创建集群后,您可以通过[连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/connect-to-tidb-cluster.md)中提供的方法连接到集群。 diff --git a/tidb-cloud/csv-config-for-import-data.md b/tidb-cloud/csv-config-for-import-data.md new file mode 100644 index 000000000000..daffbfd89ad6 --- /dev/null +++ b/tidb-cloud/csv-config-for-import-data.md @@ -0,0 +1,76 @@ +--- +title: 导入数据的 CSV 配置 +summary: 了解如何在 TiDB Cloud 上使用导入数据服务的 CSV 配置。 +--- + +# 导入数据的 CSV 配置 + +本文档介绍 TiDB Cloud 上导入数据服务的 CSV 配置。 + +以下是在 TiDB Cloud 上使用导入数据服务导入 CSV 文件时的 CSV 配置窗口。更多信息,请参见[从云存储导入 CSV 文件到 TiDB Cloud Dedicated](/tidb-cloud/import-csv-files.md)。 + +![CSV 配置](/media/tidb-cloud/import-data-csv-config.png) + +## 分隔符(Separator) + +- 定义:定义字段分隔符。可以是一个或多个字符,但不能为空。 + +- 常用值: + + * `,` 用于 CSV(逗号分隔值)。如上图所示,"1"、"Michael" 和 "male" 代表三个字段。 + * `"\t"` 用于 TSV(制表符分隔值)。 + +- 默认值:`,` + +## 定界符(Delimiter) + +- 定义:定义用于引用的定界符。如果**定界符**为空,则所有字段都不带引号。 + +- 常用值: + + * `'"'` 使用双引号引用字段。如上图所示,`"Michael","male"` 代表两个字段。注意两个字段之间必须有 `,`。如果数据是 `"Michael""male"`(没有 `,`),导入任务将无法解析。如果数据是 `"Michael,male"`(只有一个双引号),它将被解析为一个字段。 + * `''` 禁用引用。 + +- 默认值:`"` + +## 反斜杠转义(Backslash escape) + +- 定义:是否将字段内的反斜杠解析为转义字符。如果**反斜杠转义**为 `True`,则识别并转换以下序列: + + | 序列 | 转换为 | + |----------|--------------------------| + | `\0` | 空字符 (`U+0000`) | + | `\b` | 退格 (`U+0008`) | + | `\n` | 换行 (`U+000A`) | + | `\r` | 回车 (`U+000D`) | + | `\t` | 制表符 (`U+0009`) | + | `\Z` | Windows EOF (`U+001A`) | + + 在所有其他情况下(例如,`\"`),反斜杠会被去除,只留下下一个字符(`"`)在字段中。剩下的字符没有特殊作用(例如,定界符),只是一个普通字符。引用不影响反斜杠是否被解析为转义字符。 + + 以下面的字段为例: + + - 如果值为 `True`,`"nick name is \"Mike\""` 将被解析为 `nick name is "Mike"` 并写入目标表。 + - 如果值为 `False`,它将被解析为三个字段:`"nick name is \"` 、`Mike\` 和 `""`。但由于字段之间没有分隔,无法正确解析。 + + 对于标准的 CSV 文件,如果要记录的字段中有双引号字符,需要使用两个双引号进行转义。在这种情况下,使用 `Backslash escape = True` 会导致解析错误,而使用 `Backslash escape = False` 则可以正确解析。一个典型的场景是导入的字段包含 JSON 内容。标准的 CSV JSON 字段通常存储如下: + + `"{""key1"":""val1"", ""key2"": ""val2""}"` + + 在这种情况下,你可以设置 `Backslash escape = False`,字段将被正确转义并存储到数据库中,如下所示: + + `{"key1": "val1", "key2": "val2"}` + + 如果 CSV 源文件的内容以以下方式保存为 JSON,则考虑设置 `Backslash escape = True`。但这不是 CSV 的标准格式。 + + `"{\"key1\": \"val1\", \"key2\":\"val2\" }"` + +- 默认值:`True` + +## 空值(NULL value) + +- 定义:定义 CSV 文件中表示 `NULL` 值的字符串。 + +- 默认值:`\N` + +- 控制台不支持自定义空值。你可以使用 [TiDB Cloud CLI](/tidb-cloud/get-started-with-cli.md) 代替。更多信息,请参见 [`ticloud serverless import start`](/tidb-cloud/ticloud-import-start.md)。 diff --git a/tidb-cloud/data-service-api-key.md b/tidb-cloud/data-service-api-key.md new file mode 100644 index 000000000000..693d7daa7d7c --- /dev/null +++ b/tidb-cloud/data-service-api-key.md @@ -0,0 +1,162 @@ +--- +title: Data Service 中的 API 密钥 +summary: 了解如何为 Data App 创建、编辑和删除 API 密钥。 +--- + +# Data Service 中的 API 密钥 + +TiDB Cloud Data API 支持[基本认证](https://en.wikipedia.org/wiki/Basic_access_authentication)和[摘要认证](https://en.wikipedia.org/wiki/Digest_access_authentication)。 + +- [基本认证](https://en.wikipedia.org/wiki/Basic_access_authentication)使用非加密的 base64 编码来传输你的公钥和私钥。HTTPS 确保传输安全。更多信息,请参见 [RFC 7617 - The 'Basic' HTTP Authentication Scheme](https://datatracker.ietf.org/doc/html/rfc7617)。 +- [摘要认证](https://en.wikipedia.org/wiki/Digest_access_authentication)通过在网络传输前对你的公钥、私钥、服务器提供的 nonce 值、HTTP 方法和请求的 URI 进行哈希处理,提供了额外的安全层。这样可以加密私钥,防止其以明文形式传输。更多信息,请参见 [RFC 7616 - HTTP Digest Access Authentication](https://datatracker.ietf.org/doc/html/rfc7616)。 + +> **注意:** +> +> Data Service 中的 Data API 密钥与 [TiDB Cloud API](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication) 中使用的密钥不同。Data API 密钥用于访问 TiDB Cloud 集群中的数据,而 TiDB Cloud API 密钥用于管理项目、集群、备份、恢复和导入等资源。 + +## API 密钥概述 + +- API 密钥包含一个公钥和一个私钥,它们作为认证所需的用户名和密码。私钥仅在密钥创建时显示。 +- 每个 API 密钥仅属于一个 Data App,用于访问 TiDB Cloud 集群中的数据。 +- 你必须在每个请求中提供正确的 API 密钥。否则,TiDB Cloud 将返回 `401` 错误。 + +## 速率限制 + +请求配额受以下速率限制: + +- TiDB Cloud Data Service 默认允许每个 API 密钥每分钟最多 100 个请求(rpm)。 + + 你可以在[创建](#创建-api-密钥)或[编辑](#编辑-api-密钥) API 密钥时编辑其速率限制。支持的值范围是从 `1` 到 `1000`。如果你每分钟的请求超过速率限制,API 将返回 `429` 错误。要获得每个 API 密钥每分钟超过 1000 个请求的配额,你可以向我们的支持团队[提交请求](https://tidb.support.pingcap.com/)。 + + 每个 API 请求都会返回以下有关限制的标头。 + + - `X-Ratelimit-Limit-Minute`:每分钟允许的请求数。 + - `X-Ratelimit-Remaining-Minute`:当前分钟内剩余的请求数。当它达到 `0` 时,API 将返回 `429` 错误并指示你超过了速率限制。 + - `X-Ratelimit-Reset`:当前速率限制重置的时间(以秒为单位)。 + + 如果你超过速率限制,将返回如下错误响应: + + ```bash + HTTP/2 429 + date: Mon, 05 Sep 2023 02:50:52 GMT + content-type: application/json + content-length: 420 + x-debug-trace-id: 202309040250529dcdf2055e7b2ae5e9 + x-ratelimit-reset: 8 + x-ratelimit-remaining-minute: 0 + x-ratelimit-limit-minute: 10 + x-kong-response-latency: 1 + server: kong/2.8.1 + + {"type":"","data":{"columns":[],"rows":[],"result":{"latency":"","row_affect":0,"code":49900007,"row_count":0,"end_ms":0,"limit":0,"message":"API key rate limit exceeded. The limit can be increased up to 1000 requests per minute per API key in TiDB Cloud console. For an increase in quota beyond 1000 rpm, please contact us: https://tidb.support.pingcap.com/","start_ms":0}}} + ``` + +- TiDB Cloud Data Service 允许每个 Chat2Query Data App 每天最多 100 个请求。 + +## API 密钥过期 + +默认情况下,API 密钥永不过期。但是,出于安全考虑,你可以在[创建](#创建-api-密钥)或[编辑](#编辑-api-密钥) API 密钥时为其指定过期时间。 + +- API 密钥仅在其过期时间之前有效。一旦过期,使用该密钥的所有请求都将失败并返回 `401` 错误,响应类似如下: + + ```bash + HTTP/2 401 + date: Mon, 05 Sep 2023 02:50:52 GMT + content-type: application/json + content-length: 420 + x-debug-trace-id: 202309040250529dcdf2055e7b2ae5e9 + x-kong-response-latency: 1 + server: kong/2.8.1 + + {"data":{"result":{"start_ms":0,"end_ms":0,"latency":"","row_affect":0,"limit":0,"code":49900002,"message":"API Key is no longer valid","row_count":0},"columns":[],"rows":[]},"type":""} + ``` + +- 你也可以手动使 API 密钥过期。详细步骤,请参见[使单个 API 密钥过期](#使单个-api-密钥过期)和[使所有 API 密钥过期](#使所有-api-密钥过期)。一旦你手动使 API 密钥过期,过期将立即生效。 + +- 你可以在目标 Data App 的**认证**区域查看 API 密钥的状态和过期时间。 + +- 一旦过期,API 密钥就无法再次激活或编辑。 + +## 管理 API 密钥 + +以下部分描述如何为 Data App 创建、编辑、删除和使 API 密钥过期。 + +### 创建 API 密钥 + +要为 Data App 创建 API 密钥,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**认证**区域,点击**创建 API 密钥**。 +4. 在**创建 API 密钥**对话框中,执行以下操作: + + 1. (可选)为你的 API 密钥输入描述。 + 2. 为你的 API 密钥选择角色。 + + 角色用于控制 API 密钥是否可以读取或写入链接到 Data App 的集群数据。你可以选择 `ReadOnly` 或 `ReadAndWrite` 角色: + + - `ReadOnly`:仅允许 API 密钥读取数据,如 `SELECT`、`SHOW`、`USE`、`DESC` 和 `EXPLAIN` 语句。 + - `ReadAndWrite`:允许 API 密钥读取和写入数据。你可以使用此 API 密钥执行所有 SQL 语句,如 DML 和 DDL 语句。 + + 3. (可选)为你的 API 密钥设置所需的速率限制。 + + 如果你每分钟的请求超过速率限制,API 将返回 `429` 错误。要获得每个 API 密钥每分钟超过 1000 个请求(rpm)的配额,你可以向我们的支持团队[提交请求](https://tidb.support.pingcap.com/)。 + + 4. (可选)为你的 API 密钥设置所需的过期时间。 + + 默认情况下,API 密钥永不过期。如果你想为 API 密钥指定过期时间,点击**在此时间后过期**,选择一个时间单位(`分钟`、`天`或`月`),然后填写该时间单位的所需数字。 + +5. 点击**下一步**。将显示公钥和私钥。 + + 确保你已将私钥复制并保存在安全的位置。离开此页面后,你将无法再次获取完整的私钥。 + +6. 点击**完成**。 + +### 编辑 API 密钥 + +> **注意**: +> +> 你无法编辑已过期的密钥。 + +要编辑 API 密钥的描述或速率限制,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**认证**区域,找到**操作**列,然后在要更改的 API 密钥行中点击 **...** > **编辑**。 +4. 更新 API 密钥的描述、角色、速率限制或过期时间。 +5. 点击**更新**。 + +### 删除 API 密钥 + +> **注意:** +> +> 在删除 API 密钥之前,请确保该 API 密钥未被任何 Data App 使用。 + +要删除 Data App 的 API 密钥,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在 **API 密钥**区域,找到**操作**列,然后在要删除的 API 密钥行中点击 **...** > **删除**。 +4. 在显示的对话框中,确认删除。 + +### 使单个 API 密钥过期 + +> **注意**: +> +> 你无法使已过期的密钥过期。 + +要使 Data App 的 API 密钥过期,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**认证**区域,找到**操作**列,然后在要使其过期的 API 密钥行中点击 **...** > **立即过期**。 +4. 在显示的对话框中,确认过期。 + +### 使所有 API 密钥过期 + +要使 Data App 的所有 API 密钥过期,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**认证**区域,点击**全部过期**。 +4. 在显示的对话框中,确认过期。 diff --git a/tidb-cloud/data-service-app-config-files.md b/tidb-cloud/data-service-app-config-files.md new file mode 100644 index 000000000000..3c0894541510 --- /dev/null +++ b/tidb-cloud/data-service-app-config-files.md @@ -0,0 +1,229 @@ +--- +title: Data App 配置文件 +summary: 本文档描述了 TiDB Cloud 中 Data App 的配置文件。 +--- + +# Data App 配置文件 + +本文档描述了 TiDB Cloud 中 [Data App](/tidb-cloud/tidb-cloud-glossary.md#data-app) 的配置文件。 + +如果你已经[将你的 Data App 连接到 GitHub](/tidb-cloud/data-service-manage-github-connection.md),你可以在 GitHub 上的指定目录中找到你的 Data App 的配置文件,如下所示: + +``` +├── <你的 Data App 目录> +│ ├── data_sources +│ │ └── cluster.json +│ ├── dataapp_config.json +│ ├── http_endpoints +│ │ ├── config.json +│ │ └── sql +│ │ ├── -.sql +│ │ ├── -.sql +│ │ └── -.sql +``` + +## 数据源配置 + +Data App 的数据源来自其链接的 TiDB 集群。你可以在 `data_sources/cluster.json` 中找到数据源配置。 + +``` +├── <你的 Data App 目录> +│ ├── data_sources +│ │ └── cluster.json +``` + +对于每个 Data App,你可以链接一个或多个 TiDB 集群。 + +以下是 `cluster.json` 的示例配置。在此示例中,此 Data App 有两个链接的集群。 + +```json +[ + { + "cluster_id": <集群 ID1> + }, + { + "cluster_id": <集群 ID2> + } +] +``` + +字段说明如下: + +| 字段 | 类型 | 说明 | +|---------|---------|--------------| +| `cluster_id` | Integer | 你的 TiDB 集群的 ID。你可以从集群的 URL 获取它。例如,如果你的集群 URL 是 `https://tidbcloud.com/clusters/1234567891234567890/overview`,你的集群 ID 是 `1234567891234567890`。 | + +## Data App 配置 + +Data App 的属性包含 App ID、名称和类型。你可以在 `dataapp_config.json` 文件中找到这些属性。 + +``` +├── <你的 Data App 目录> +│ ├── dataapp_config.json +``` + +以下是 `dataapp_config.json` 的示例配置。 + +```json +{ + "app_id": "", + "app_name": "", + "app_type": "dataapi", + "app_version": "", + "description": "" +} +``` + +每个字段的说明如下: + +| 字段 | 类型 | 说明 | +|------------|--------|--------------------| +| `app_id` | String | Data App ID。除非你的 `dataapp_config.json` 文件是从另一个 Data App 复制的,并且你想将其更新为当前 Data App 的 ID,否则不要更改此字段。否则,由此修改触发的部署将失败。 | +| `app_name` | String | Data App 名称。 | +| `app_type` | String | Data App 类型,只能是 `"dataapi"`。 | +| `app_version` | String | Data App 版本,格式为 `".."`。例如,`"1.0.0"`。 | +| `description` | String | Data App 描述。 | + +## HTTP 端点配置 + +在你的 Data App 目录中,你可以在 `http_endpoints/config.json` 中找到端点配置,在 `http_endpoints/sql/-.sql` 中找到 SQL 文件。 + +``` +├── <你的 Data App 目录> +│ ├── http_endpoints +│ │ ├── config.json +│ │ └── sql +│ │ ├── -.sql +│ │ ├── -.sql +│ │ └── -.sql +``` + +### 端点配置 + +对于每个 Data App,可以有一个或多个端点。你可以在 `http_endpoints/config.json` 中找到 Data App 的所有端点的配置。 + +以下是 `config.json` 的示例配置。在此示例中,此 Data App 有两个端点。 + +```json +[ + { + "name": "<端点名称1>", + "description": "<端点描述1>", + "method": "", + "endpoint": "<端点路径1>", + "data_source": { + "cluster_id": <集群 ID1> + }, + "params": [], + "settings": { + "timeout": <端点超时时间>, + "row_limit": <最大行数>, + "enable_pagination": <0 | 1>, + "cache_enabled": <0 | 1>, + "cache_ttl": <生存时间周期> + }, + "tag": "Default", + "batch_operation": <0 | 1>, + "sql_file": "", + "type": "sql_endpoint", + "return_type": "json" + }, + { + "name": "<端点名称2>", + "description": "<端点描述2>", + "method": "", + "endpoint": "<端点路径2>", + "data_source": { + "cluster_id": <集群 ID2> + }, + "params": [ + { + "name": "<参数名称>", + "type": "<参数类型>", + "required": <0 | 1>, + "default": "<参数默认值>", + "description": "<参数描述>", + "is_path_parameter": + } + ], + "settings": { + "timeout": <端点超时时间>, + "row_limit": <最大行数>, + "enable_pagination": <0 | 1>, + "cache_enabled": <0 | 1>, + "cache_ttl": <生存时间周期> + }, + "tag": "Default", + "batch_operation": <0 | 1>, + "sql_file": "", + "type": "sql_endpoint", + "return_type": "json" + } +] +``` + +每个字段的说明如下: + +| 字段 | 类型 | 说明 | +|---------------|--------|-------------| +| `name` | String | 端点名称。 | +| `description` | String | (可选)端点描述。 | +| `method` | String | 端点的 HTTP 方法。你可以使用 `GET` 检索数据,使用 `POST` 创建或插入数据,使用 `PUT` 更新或修改数据,使用 `DELETE` 删除数据。 | +| `endpoint` | String | Data App 中端点的唯一路径。路径中只允许使用字母、数字、下划线(`_`)和斜杠(`/`),必须以斜杠(`/`)开头,以字母、数字或下划线(`_`)结尾。例如,`/my_endpoint/get_id`。路径长度必须小于 64 个字符。| +| `cluster_id` | String | 端点使用的 TiDB 集群的 ID。你可以从 TiDB 集群的 URL 获取它。例如,如果你的集群 URL 是 `https://tidbcloud.com/clusters/1234567891234567890/overview`,集群 ID 是 `1234567891234567890`。 | +| `params` | Array | 端点使用的参数。通过定义参数,你可以通过端点动态替换查询中的参数值。在 `params` 中,你可以定义一个或多个参数。对于每个参数,你需要定义其 `name`、`type`、`required` 和 `default` 字段。如果你的端点不需要任何参数,你可以将 `params` 留空,如 `"params": []`。 | +| `params.name` | String | 参数的名称。名称只能包含字母、数字和下划线(`_`),且必须以字母或下划线(`_`)开头。**不要**使用 `page` 和 `page_size` 作为参数名称,这些是为请求结果分页保留的。 | +| `params.type` | String | 参数的数据类型。支持的值有 `string`、`number`、`integer`、`boolean` 和 `array`。使用 `string` 类型参数时,不需要添加引号(`'` 或 `"`)。例如,`foo` 对于 `string` 类型是有效的,会被处理为 `"foo"`,而 `"foo"` 会被处理为 `"\"foo\""` 。 | +| `params.required` | Integer | 指定请求中是否必须包含该参数。支持的值为 `0`(不必须)和 `1`(必须)。默认值为 `0`。 | +| `params.enum` | String | (可选)指定参数的值选项。此字段仅在 `params.type` 设置为 `string`、`number` 或 `integer` 时有效。要指定多个值,可以用逗号(`,`)分隔。 | +| `params.default` | String | 参数的默认值。确保值与你指定的参数类型匹配。否则,端点将返回错误。`ARRAY` 类型参数的默认值是一个字符串,你可以使用逗号(`,`)分隔多个值。 | +| `params.description` | String | 参数的描述。 | +| `params.is_path_parameter` | Boolean | 指定参数是否为路径参数。如果设置为 `true`,请确保 `endpoint` 字段包含相应的参数占位符;否则,将导致部署失败。相反,如果 `endpoint` 字段包含相应的参数占位符但此字段设置为 `false`,也会导致部署失败。 | +| `settings.timeout` | Integer | 端点的超时时间(以毫秒为单位),默认为 `30000`。你可以将其设置为 `1` 到 `60000` 之间的整数。 | +| `settings.row_limit` | Integer | 端点可以操作或返回的最大行数,默认为 `1000`。当 `batch_operation` 设置为 `0` 时,你可以将其设置为 `1` 到 `2000` 之间的整数。当 `batch_operation` 设置为 `1` 时,你可以将其设置为 `1` 到 `100` 之间的整数。 | +| `settings.enable_pagination` | Integer | 控制是否为请求返回的结果启用分页。支持的值为 `0`(禁用)和 `1`(启用)。默认值为 `0`。 | +| `settings.cache_enabled` | Integer | 控制是否在指定的生存时间(TTL)期间内缓存你的 `GET` 请求返回的响应。支持的值为 `0`(禁用)和 `1`(启用)。默认值为 `0`。 | +| `settings.cache_ttl` | Integer | 当 `settings.cache_enabled` 设置为 `1` 时,缓存响应的生存时间(TTL)期限(以秒为单位)。你可以将其设置为 30 到 600 之间的整数。在 TTL 期间内,如果你再次发出相同的 `GET` 请求,Data Service 将直接返回缓存的响应,而不是再次从目标数据库获取数据,这样可以提高你的查询性能。 | +| `tag` | String | 端点的标签。默认值为 `"Default"`。 | +| `batch_operation` | Integer | 控制是否启用端点以批处理模式运行。支持的值为 `0`(禁用)和 `1`(启用)。当设置为 `1` 时,你可以在单个请求中操作多行。要启用此选项,请确保请求方法为 `POST` 或 `PUT`。 | +| `sql_file` | String | 端点的 SQL 文件目录。例如,`"sql/GET-v1.sql"`。 | +| `type` | String | 端点的类型。预定义的系统端点值为 `"system-data"`,其他端点值为 `"sql_endpoint"`。 | +| `return_type` | String | 端点的响应格式,只能是 `"json"`。 | + +### SQL 文件配置 + +端点的 SQL 文件指定了通过端点查询数据的 SQL 语句。你可以在 `http_endpoints/sql/` 目录中找到 Data App 的端点 SQL 文件。每个端点都应该有一个对应的 SQL 文件。 + +SQL 文件的名称格式为 `-.sql`,其中 `` 和 `` 必须与 [`http_endpoints/config.json`](#端点配置) 中的 `method` 和 `endpoint` 配置匹配。 + +在 SQL 文件中,你可以编写表连接查询、复杂查询和聚合函数等语句。以下是一个示例 SQL 文件。 + +```sql +/* 入门: +在输入 SQL 语句之前,输入 "USE {database};"。 +输入 "--你的问题" + Enter 可以在 TiDB Cloud 控制台中尝试 AI 生成的 SQL 查询。 +声明参数的格式为 "Where id = ${arg}"。 +*/ +USE sample_data; +SELECT + rank, + company_name, +FROM + global_fortune_500_2018_2022 +WHERE + country = ${country}; +``` + +编写 SQL 文件时,请注意以下事项: + +- 在 SQL 文件的开头,你需要在 SQL 语句中指定数据库。例如,`USE database_name;`。 + +- 要定义端点的参数,你可以将其作为变量占位符(如 `${variable-name}`)插入到 SQL 语句中。 + + 在上述示例中,`${country}` 用作端点的参数。使用此参数,你可以在端点 curl 命令中指定所需的国家/地区进行查询。 + + > **注意:** + > + > - 参数名称区分大小写。 + > - 参数不能是表名或列名。 + > - SQL 文件中的参数名称必须与 [`http_endpoints/config.json`](#端点配置) 中配置的参数名称匹配。 diff --git a/tidb-cloud/data-service-concepts.md b/tidb-cloud/data-service-concepts.md new file mode 100644 index 000000000000..dec9d97cf9c5 --- /dev/null +++ b/tidb-cloud/data-service-concepts.md @@ -0,0 +1,48 @@ +--- +title: 数据服务(Beta) +summary: 了解 TiDB Cloud 的数据服务概念。 +--- + +# 数据服务(Beta) + +TiDB Cloud [数据服务(beta)](https://tidbcloud.com/project/data-service)是一个完全托管的低代码后端即服务解决方案,它简化了后端应用程序开发,使开发人员能够快速构建高度可扩展、安全的数据驱动应用程序。 + +数据服务使你能够通过自定义 API 端点使用 HTTPS 请求访问 TiDB Cloud 数据。此功能使用无服务器架构来处理计算资源和弹性扩展,因此你可以专注于端点中的查询逻辑,而无需担心基础设施或维护成本。 + +更多信息,请参阅 [TiDB Cloud 数据服务(Beta)概述](/tidb-cloud/data-service-overview.md)。 + +## 数据应用 + +[数据服务(beta)](https://tidbcloud.com/project/data-service)中的数据应用是一组可用于访问特定应用程序数据的端点的集合。通过创建数据应用,你可以对端点进行分组,并使用 API 密钥配置授权设置来限制对端点的访问。这样,你可以确保只有授权用户才能访问和操作你的数据,使你的应用程序更加安全。 + +更多信息,请参阅[管理数据应用](/tidb-cloud/data-service-manage-data-app.md)。 + +## 数据应用端点 + +[数据服务(beta)](https://tidbcloud.com/project/data-service)中的端点是一个可以自定义来执行 SQL 语句的 Web API。你可以为 SQL 语句指定参数,例如在 `WHERE` 子句中使用的值。当客户端调用端点并在请求 URL 中为参数提供值时,端点会使用提供的参数执行相应的 SQL 语句,并将结果作为 HTTP 响应的一部分返回。 + +更多信息,请参阅[管理端点](/tidb-cloud/data-service-manage-endpoint.md)。 + +## Chat2Query API + +在 TiDB Cloud 中,Chat2Query API 是一个 RESTful 接口,通过提供指令,使你能够使用 AI 生成和执行 SQL 语句。然后,API 会为你返回查询结果。 + +更多信息,请参阅[开始使用 Chat2Query API](/tidb-cloud/use-chat2query-api.md)。 + +## AI 集成 + +将第三方工具与你的数据应用集成可以通过第三方工具提供的高级自然语言处理和人工智能(AI)功能来增强你的应用程序。这种集成使你的应用程序能够执行更复杂的任务并提供智能解决方案。 + +目前,你可以在 TiDB Cloud 控制台中集成第三方工具,如 GPTs 和 Dify。 + +更多信息,请参阅[将数据应用与第三方工具集成](/tidb-cloud/data-service-integrations.md)。 + +## 配置即代码 + +TiDB Cloud 提供了配置即代码(Configuration as Code,CaC)方法,使用 JSON 语法将你的整个数据应用配置表示为代码。 + +通过将你的数据应用连接到 GitHub,TiDB Cloud 可以使用 CaC 方法,将你的数据应用配置作为[配置文件](/tidb-cloud/data-service-app-config-files.md)推送到你首选的 GitHub 仓库和分支。 + +如果为你的 GitHub 连接启用了自动同步和部署,你还可以通过在 GitHub 上更新配置文件来修改你的数据应用。将配置文件更改推送到 GitHub 后,新的配置将自动部署到 TiDB Cloud。 + +更多信息,请参阅[使用 GitHub 自动部署数据应用](/tidb-cloud/data-service-manage-github-connection.md)。 diff --git a/tidb-cloud/data-service-custom-domain.md b/tidb-cloud/data-service-custom-domain.md new file mode 100644 index 000000000000..a85dae7d432f --- /dev/null +++ b/tidb-cloud/data-service-custom-domain.md @@ -0,0 +1,72 @@ +--- +title: Data Service 中的自定义域名 +summary: 了解如何使用自定义域名访问 TiDB Cloud Data Service 中的 Data App。 +--- + +# Data Service 中的自定义域名 + +TiDB Cloud Data Service 提供默认域名 `.data.tidbcloud.com` 来访问每个 Data App 的端点。为了增强个性化和灵活性,你可以为你的 Data App 配置自定义域名,而不是使用默认域名。 + +本文档描述如何在你的 Data App 中管理自定义域名。 + +## 开始之前 + +在为你的 Data App 配置自定义域名之前,请注意以下事项: + +- 自定义域名请求出于安全考虑仅支持 HTTPS。一旦你成功配置自定义域名,系统会自动应用 "Let's Encrypt" 证书。 +- 你的自定义域名在 TiDB Cloud Data Service 中必须是唯一的。 +- 每个默认域名(由集群所在区域决定)只能配置一个自定义域名。 + +## 管理自定义域名 + +以下部分描述如何为 Data App 创建、编辑和删除自定义域名。 + +### 创建自定义域名 + +要为 Data App 创建自定义域名,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**管理自定义域名**区域,点击**添加自定义域名**。 +4. 在**添加自定义域名**对话框中,执行以下操作: + 1. 选择要替换的默认域名。 + 2. 输入你想要的自定义域名。 + 3. 可选:配置自定义路径作为端点的前缀。如果**自定义路径**留空,则使用默认路径。 +5. 预览你的**基础 URL** 以确保它符合你的预期。如果看起来正确,点击**保存**。 +6. 按照 **DNS 设置**对话框中的说明,在你的 DNS 提供商中为默认域名添加 `CNAME` 记录。 + +自定义域名最初处于**待验证**状态,系统会验证你的 DNS 设置。一旦 DNS 验证成功,你的自定义域名状态将更新为**成功**。 + +> **注意:** +> +> 根据你的 DNS 提供商,DNS 记录验证可能需要长达 24 小时。如果自定义域名超过 24 小时仍未验证,它将处于**已过期**状态。在这种情况下,你只能删除自定义域名并重试。 + +在你的自定义域名状态设置为**成功**后,你就可以使用它来访问你的端点。TiDB Cloud Data Service 提供的代码示例会自动更新为你的自定义域名和路径。更多信息,请参见[调用端点](/tidb-cloud/data-service-manage-endpoint.md#调用端点)。 + +### 编辑自定义域名 + +> **注意:** +> +> 完成以下更改后,之前的自定义域名和自定义路径将立即失效。如果你修改自定义域名,则需要等待新的 DNS 记录验证。 + +要编辑 Data App 的自定义域名,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**管理自定义域名**区域,找到**操作**列,然后在要编辑的自定义域名行中点击 **编辑**。 +4. 在显示的对话框中,更新自定义域名或自定义路径。 +5. 预览你的**基础 URL** 以确保它符合你的预期。如果看起来正确,点击**保存**。 +6. 如果你更改了自定义域名,请按照 **DNS 设置**对话框中的说明,在你的 DNS 提供商中为默认域名添加 `CNAME` 记录。 + +### 删除自定义域名 + +> **注意:** +> +> 在删除自定义域名之前,请确保该自定义域名不再使用。 + +要删除 Data App 的自定义域名,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**管理自定义域名**区域,找到**操作**列,然后在要删除的自定义域名行中点击 **删除**。 +4. 在显示的对话框中,确认删除。 diff --git a/tidb-cloud/data-service-get-started.md b/tidb-cloud/data-service-get-started.md new file mode 100644 index 000000000000..335c248ae599 --- /dev/null +++ b/tidb-cloud/data-service-get-started.md @@ -0,0 +1,304 @@ +--- +title: 数据服务入门 +summary: 了解如何使用 TiDB Cloud 数据服务通过 HTTPS 请求访问数据。 +--- + +# 数据服务入门 + +数据服务(beta)使您能够通过自定义 API 端点使用 HTTPS 请求访问 TiDB Cloud 数据,让您可以无缝集成任何支持 HTTPS 的应用程序或服务。 + +> **提示:** +> +> TiDB Cloud 为 TiDB 集群提供 Chat2Query API。启用后,TiDB Cloud 将自动在数据服务中创建一个名为 **Chat2Query** 的系统数据应用和一个 Chat2Data 端点。您可以调用此端点,通过提供指令让 AI 生成并执行 SQL 语句。 +> +> 更多信息,请参阅[Chat2Query API 入门](/tidb-cloud/use-chat2query-api.md)。 + +本文介绍如何通过创建数据应用、开发、测试、部署和调用端点,快速开始使用 TiDB Cloud 数据服务(beta)。数据应用是一组端点的集合,您可以使用这些端点访问特定应用程序的数据。 + +## 开始之前 + +在创建数据应用之前,请确保您已创建了一个 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。如果您还没有,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)中的步骤创建一个。 + +## 从示例数据应用开始 + +创建示例数据应用是开始使用数据服务的最佳方式。如果您的项目还没有任何数据应用,可以按照**数据服务**页面上的屏幕说明创建一个示例数据应用,并使用此应用探索数据服务功能。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,点击左侧导航栏中的 **数据服务**。 + +2. 在**数据服务**页面,点击**创建示例数据应用**。将显示一个对话框。 + +3. 在对话框中,根据需要更新应用名称,选择您希望数据应用访问的集群,然后点击**创建**。 + + 创建过程需要几秒钟。 + + > **注意:** + > + > 如果您当前的项目中没有集群,可以在**链接数据源**下拉列表中点击**创建新集群**先创建一个。 + +4. 示例数据应用自动创建后,您可以在左侧窗格中看到应用名称和端点列表,中间窗格中显示端点的 SQL 语句,右侧显示使用示例数据应用的说明。 + +5. 按照右侧的说明选择一个端点并使用 curl 命令调用该端点。 + +## 从您自己的数据应用开始 + +要开始使用数据服务,您也可以创建自己的数据应用,然后按照以下步骤开发、测试、部署和调用端点。 + +### 步骤 1. 创建数据应用 + +要创建数据应用,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,点击左侧导航栏中的 **数据服务**。 + +2. 在项目的[**数据服务**](https://tidbcloud.com/project/data-service)页面,点击左侧窗格中的 **创建数据应用**。 + + > **提示:** + > + > 如果这是您项目中的第一个数据应用,请点击页面中间的**创建数据应用**。 + +3. 在**创建数据应用**对话框中,输入名称、描述,并选择您希望数据应用访问的集群。 + + > **注意:** + > + > 默认情况下,数据应用类型为**标准数据应用**。如果您想创建 **Chat2Query 数据应用**,请参考 [Chat2Query API 入门](/tidb-cloud/use-chat2query-api.md)而不是本文档。 + +4. (可选)要自动将数据应用的端点部署到您首选的 GitHub 仓库和分支,请启用**连接到 GitHub**,然后执行以下操作: + + 1. 点击**在 GitHub 上安装**,然后按照屏幕说明在目标仓库上安装 **TiDB Cloud Data Service** 应用。 + 2. 返回 TiDB Cloud 控制台,然后点击**授权**以授权访问 GitHub 上的应用。 + 3. 指定要保存数据应用配置文件的目标仓库、分支和目录。 + + > **注意:** + > + > - 目录必须以斜杠 (`/`) 开头。例如,`/mydata`。如果您指定的目录在目标仓库和分支中不存在,将自动创建。 + > - 仓库、分支和目录的组合标识了配置文件的路径,在数据应用中必须是唯一的。如果您指定的路径已被另一个数据应用使用,您需要指定一个新路径。否则,当前数据应用在 TiDB Cloud 控制台中配置的端点将覆盖您指定路径中的文件。 + +5. 点击**创建数据应用**。将显示[**数据服务**](https://tidbcloud.com/project/data-service)详情页面。 + +6. 如果您已配置将数据应用连接到 GitHub,请检查您指定的 GitHub 目录。您会发现[数据应用配置文件](/tidb-cloud/data-service-app-config-files.md)已由 `tidb-cloud-data-service` 提交到该目录,这意味着您的数据应用已成功连接到 GitHub。 + + 对于您的新数据应用,默认启用了**自动同步和部署**和**审核草稿**,这样您就可以轻松地在 TiDB Cloud 控制台和 GitHub 之间同步数据应用更改,并在部署前审核更改。有关 GitHub 集成的更多信息,请参阅[使用 GitHub 自动部署数据应用更改](/tidb-cloud/data-service-manage-github-connection.md)。 + +### 步骤 2. 开发端点 + +端点是一个可以自定义执行 SQL 语句的 Web API。 + +要创建新端点,找到新创建的数据应用,然后点击应用名称右侧的 **+** **创建端点**。 + +#### 配置属性 + +在右侧窗格中,点击**属性**选项卡并为端点设置属性,例如: + +- **路径**:用户访问端点的路径。请求方法和路径的组合在数据应用中必须是唯一的。 + +- **端点 URL**:(只读)URL 根据相应集群所在的区域、数据应用的服务 URL 和端点的路径自动生成。例如,如果端点的路径是 `/my_endpoint/get_id`,则端点 URL 为 `https://.data.tidbcloud.com/api/v1beta/app//endpoint/my_endpoint/get_id`。 + +- **请求方法**:端点的 HTTP 方法。您可以使用 `GET` 检索数据,使用 `POST` 创建或插入数据,使用 `PUT` 更新或修改数据,使用 `DELETE` 删除数据。 + +有关端点属性的更多信息,请参阅[配置属性](/tidb-cloud/data-service-manage-endpoint.md#configure-properties)。 + +#### 编写 SQL 语句 + +您可以在 SQL 编辑器(即页面中间的窗格)中为端点自定义 SQL 语句。 + +1. 选择集群。 + + > **注意:** + > + > 下拉列表中只显示链接到数据应用的集群。要管理链接的集群,请参阅[管理链接的集群](/tidb-cloud/data-service-manage-data-app.md#manage-linked-data-sources)。 + + 在 SQL 编辑器的上部,从下拉列表中选择要执行 SQL 语句的集群。然后,您可以在右侧窗格的**架构**选项卡中查看此集群的所有数据库。 + +2. 编写 SQL 语句。 + + 在查询或修改数据之前,您需要先在 SQL 语句中指定数据库。例如,`USE database_name;`。 + + 在 SQL 编辑器中,您可以编写表连接查询、复杂查询和聚合函数等语句。您也可以简单地输入 `--` 后跟您的指令,让 AI 自动生成 SQL 语句。 + + > **注意:** + > + > 要尝试 TiDB Cloud 的 AI 功能,您需要允许 PingCAP 和 Amazon Bedrock 使用您的代码片段进行研究和服务改进。更多信息,请参阅[启用或禁用 AI 生成 SQL 查询](/tidb-cloud/explore-data-with-chat2query.md#enable-or-disable-ai-to-generate-sql-queries)。 + + 要定义参数,您可以在 SQL 语句中插入变量占位符,如 `${ID}`。例如,`SELECT * FROM table_name WHERE id = ${ID}`。然后,您可以点击右侧窗格的**参数**选项卡来更改参数定义和测试值。 + + > **注意:** + > + > - 参数名称区分大小写。 + > - 参数不能用作表名或列名。 + + - 在**定义**部分,您可以指定客户端调用端点时是否需要参数、数据类型和参数的默认值。 + - 在**测试值**部分,您可以为参数设置测试值。测试值在运行 SQL 语句或测试端点时使用。如果您没有设置测试值,将使用默认值。 + - 更多信息,请参阅[配置参数](/tidb-cloud/data-service-manage-endpoint.md#configure-parameters)。 + +3. 运行 SQL 语句。 + + 如果您在 SQL 语句中插入了参数,请确保您已在右侧窗格的**参数**选项卡中设置了测试值或默认值。否则,将返回错误。 + + +
+ + 对于 macOS: + + - 如果编辑器中只有一条语句,要运行它,请按 **⌘ + Enter** 或点击 **运行**。 + + - 如果编辑器中有多条语句,要按顺序运行其中一条或几条语句,请将光标放在目标语句上或用光标选择目标语句的行,然后按 **⌘ + Enter** 或点击**运行**。 + + - 要按顺序运行编辑器中的所有语句,请按 **⇧ + ⌘ + Enter**,或用光标选择所有语句的行并点击**运行**。 + +
+ +
+ + 对于 Windows 或 Linux: + + - 如果编辑器中只有一条语句,要运行它,请按 **Ctrl + Enter** 或点击 **运行**。 + + - 如果编辑器中有多条语句,要按顺序运行其中一条或几条语句,请将光标放在目标语句上或用光标选择目标语句的行,然后按 **Ctrl + Enter** 或点击**运行**。 + + - 要按顺序运行编辑器中的所有语句,请按 **Shift + Ctrl + Enter**,或用光标选择所有语句的行并点击**运行**。 + +
+
+ + 运行语句后,您可以在页面底部的**结果**选项卡中立即看到查询结果。 + +### 步骤 3. 测试端点(可选) + +配置端点后,您可以在部署之前测试端点,以验证它是否按预期工作。 + +要测试端点,请点击右上角的**测试**或按 **F5**。 + +然后,您可以在页面底部的 **HTTP 响应**选项卡中看到响应。有关响应的更多信息,请参阅[端点的响应](/tidb-cloud/data-service-manage-endpoint.md#response)。 + +### 步骤 4. 部署端点 + +要部署端点,请执行以下步骤: + +1. 在端点详情页面,点击右上角的**部署**。 + +2. 点击**部署**确认部署。如果端点成功部署,您将看到**端点已部署**的提示。 + + 要查看部署历史记录,您可以点击左侧窗格中的数据应用名称,然后点击右侧窗格中的**部署**选项卡。 + +### 步骤 5. 调用端点 + +您可以通过发送 HTTPS 请求来调用端点。在调用端点之前,您需要先获取数据应用的 API 密钥。 + +#### 1. 创建 API 密钥 + +1. 在[**数据服务**](https://tidbcloud.com/project/data-service)页面的左侧窗格中,点击数据应用的名称以查看其详情。 +2. 在**身份验证**区域,点击**创建 API 密钥**。 +3. 在**创建 API 密钥**对话框中,执行以下操作: + + 1. (可选)为您的 API 密钥输入描述。 + 2. 为您的 API 密钥选择角色。 + + 角色用于控制 API 密钥是否可以读取或写入链接到数据应用的集群数据。您可以选择 `ReadOnly` 或 `ReadAndWrite` 角色: + + - `ReadOnly`:仅允许 API 密钥读取数据,如 `SELECT`、`SHOW`、`USE`、`DESC` 和 `EXPLAIN` 语句。 + - `ReadAndWrite`:允许 API 密钥读取和写入数据。您可以使用此 API 密钥执行所有 SQL 语句,如 DML 和 DDL 语句。 + + 3. (可选)为您的 API 密钥设置所需的速率限制。 + +4. 点击**下一步**。将显示公钥和私钥。 + + 确保您已将私钥复制并保存在安全的位置。离开此页面后,您将无法再次获取完整的私钥。 + +5. 点击**完成**。 + +有关 API 密钥的更多信息,请参阅[数据服务中的 API 密钥](/tidb-cloud/data-service-api-key.md)。 + +#### 2. 获取代码示例 + +TiDB Cloud 生成代码示例以帮助您调用端点。要获取代码示例,请执行以下步骤: + +1. 在[**数据服务**](https://tidbcloud.com/project/data-service)页面的左侧窗格中,点击端点的名称,然后点击右上角的 **...** > **代码示例**。将显示**代码示例**对话框。 + +2. 在对话框中,选择要用于调用端点的集群和数据库,然后复制代码示例。 + + 以下是 curl 代码示例: + + +
+ + 要调用端点的草稿版本,您需要添加 `endpoint-type: draft` 头: + + ```bash + curl --digest --user ':' \ + --request GET 'https://.data.tidbcloud.com/api/v1beta/app//endpoint/' \ + --header 'endpoint-type: draft' + ``` + +
+ +
+ + 在检查线上环境的代码示例之前,您必须先部署端点。 + + 要调用端点的当前线上版本,请使用以下命令: + + ```bash + curl --digest --user ':' \ + --request GET 'https://.data.tidbcloud.com/api/v1beta/app//endpoint/' + ``` + +
+
+ + > **注意:** + > + > - 通过请求区域域名 `.data.tidbcloud.com`,您可以直接访问 TiDB 集群所在区域的端点。 + > - 或者,您也可以请求全局域名 `data.tidbcloud.com` 而不指定区域。这样,TiDB Cloud 将在内部将请求重定向到目标区域,但这可能会导致额外的延迟。如果您选择这种方式,请确保在调用端点时在 curl 命令中添加 `--location-trusted` 选项。 + +#### 3. 使用代码示例 + +将代码示例粘贴到您的应用程序中并运行。然后,您可以获取端点的响应。 + +- 您需要将 `` 和 `` 占位符替换为您的 API 密钥。 +- 如果端点包含参数,请在调用端点时指定参数值。 + +调用端点后,您可以看到 JSON 格式的响应。以下是一个示例: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [ + { + "col": "id", + "data_type": "BIGINT", + "nullable": false + }, + { + "col": "type", + "data_type": "VARCHAR", + "nullable": false + } + ], + "rows": [ + { + "id": "20008295419", + "type": "CreateEvent" + } + ], + "result": { + "code": 200, + "message": "Query OK!", + "start_ms": 1678965476709, + "end_ms": 1678965476839, + "latency": "130ms", + "row_count": 1, + "row_affect": 0, + "limit": 50 + } + } +} +``` + +有关响应的更多信息,请参阅[端点的响应](/tidb-cloud/data-service-manage-endpoint.md#response)。 + +## 了解更多 + +- [数据服务概述](/tidb-cloud/data-service-overview.md) +- [Chat2Query API 入门](/tidb-cloud/use-chat2query-api.md) +- [管理数据应用](/tidb-cloud/data-service-manage-data-app.md) +- [管理端点](/tidb-cloud/data-service-manage-endpoint.md) diff --git a/tidb-cloud/data-service-integrations.md b/tidb-cloud/data-service-integrations.md new file mode 100644 index 000000000000..ab68c1f2e78a --- /dev/null +++ b/tidb-cloud/data-service-integrations.md @@ -0,0 +1,40 @@ +--- +title: 将 Data App 与第三方工具集成 +summary: 了解如何在 TiDB Cloud 控制台中将 TiDB Cloud Data App 与第三方工具(如 GPTs 和 Dify)集成。 +--- + +# 将 Data App 与第三方工具集成 + +将第三方工具与你的 Data App 集成可以通过第三方工具提供的高级自然语言处理和人工智能(AI)功能来增强你的应用程序。这种集成使你的应用程序能够执行更复杂的任务并提供智能解决方案。 + +本文档介绍如何在 TiDB Cloud 控制台中将 Data App 与第三方工具(如 GPTs 和 Dify)集成。 + +## 将 Data App 与 GPTs 集成 + +你可以将 Data App 与 [GPTs](https://openai.com/blog/introducing-gpts) 集成,为你的应用程序增加智能功能。 + +要将 Data App 与 GPTs 集成,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App,点击目标 Data App 的名称,然后点击**集成**标签。 +3. 在**与 GPTs 集成**区域,点击**获取配置**。 + + ![获取配置](/media/tidb-cloud/data-service/GPTs1.png) + +4. 在显示的对话框中,你可以看到以下字段: + + a. **API 规范 URL**:复制 Data App 的 OpenAPI 规范的 URL。更多信息,请参见[使用 OpenAPI 规范](/tidb-cloud/data-service-manage-data-app.md#use-the-openapi-specification)。 + + b. **API 密钥**:输入 Data App 的 API 密钥。如果你还没有 API 密钥,点击**创建 API 密钥**来创建一个。更多信息,请参见[创建 API 密钥](/tidb-cloud/data-service-api-key.md#create-an-api-key)。 + + c. **API 密钥编码**:复制与你提供的 API 密钥等效的 base64 编码字符串。 + + ![GPTs 对话框](/media/tidb-cloud/data-service/GPTs2.png) + +5. 在你的 GPT 配置中使用复制的 API 规范 URL 和编码后的 API 密钥。 + +## 将 Data App 与 Dify 集成 + +你可以将 Data App 与 [Dify](https://docs.dify.ai/guides/tools) 集成,为你的应用程序增加智能功能,如向量距离计算、高级相似度搜索和向量分析。 + +要将 Data App 与 Dify 集成,请按照与 [GPTs 集成](#将-data-app-与-gpts-集成)相同的步骤操作。唯一的区别是在**集成**标签页上,你需要在**与 Dify 集成**区域点击**获取配置**。 diff --git a/tidb-cloud/data-service-manage-data-app.md b/tidb-cloud/data-service-manage-data-app.md new file mode 100644 index 000000000000..73f5216e5d07 --- /dev/null +++ b/tidb-cloud/data-service-manage-data-app.md @@ -0,0 +1,178 @@ +--- +title: 管理 Data App +summary: 了解如何在 TiDB Cloud 控制台中创建、查看、修改和删除 Data App。 +--- + +# 管理 Data App + +Data Service (beta) 中的 Data App 是一组用于访问特定应用程序数据的端点集合。你可以使用 API 密钥配置授权设置,以限制对 Data App 中端点的访问。 + +本文档介绍如何在 TiDB Cloud 控制台中管理你的 Data Apps。在 [**Data Service**](https://tidbcloud.com/project/data-service) 页面,你可以管理所有 Data Apps、端点和 API 密钥。 + +## 创建 Data App + +要为你的项目创建 Data App,请执行以下步骤: + +1. 在项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面,点击左侧窗格中的 **Create DataApp**。 + + > **提示:** + > + > 如果这是你项目中的第一个 Data App,请点击页面中间的 **Create Data App**。 + +2. 输入名称、描述,并选择你希望 Data App 访问的集群。 + + > **注意:** + > + > 默认情况下,Data App 类型为 **Standard Data App**。如果你想创建 **Chat2Query Data App**,请参考 [Chat2Query API 入门](/tidb-cloud/use-chat2query-api.md),而不是本文档。 + +3. (可选)要将 Data App 的端点自动部署到你首选的 GitHub 仓库和分支,请启用 **Connect to GitHub**,然后执行以下操作: + + 1. 点击 **Install on GitHub**,然后按照屏幕上的说明将 **TiDB Cloud Data Service** 作为应用程序安装到你的目标仓库。 + 2. 点击 **Authorize** 以授权访问 GitHub 上的应用程序。 + 3. 指定要保存 Data App 配置文件的目标仓库、分支和目录。 + + > **注意:** + > + > - 目录必须以斜杠(`/`)开头。例如,`/mydata`。如果你指定的目录在目标仓库和分支中不存在,它将自动创建。 + > - 仓库、分支和目录的组合标识了配置文件的路径,该路径在 Data Apps 中必须是唯一的。如果你指定的路径已被另一个 Data App 使用,你需要指定一个新路径。否则,当前 Data App 在 TiDB Cloud 控制台中配置的端点将覆盖你指定路径中的文件。 + > - 如果你指定的路径包含从另一个 Data App 复制的配置文件,并且你想将这些文件导入到当前 Data App,请参阅[导入现有 Data App 的配置](/tidb-cloud/data-service-manage-github-connection.md#import-configurations-of-an-existing-data-app)。 + +4. 点击 **Create Data App**。 + + 新创建的 Data App 将添加到列表顶部。系统会为新的 Data App 创建一个默认的 `untitled endpoint`。 + +5. 如果你已配置将 Data App 连接到 GitHub,请检查你指定的 GitHub 目录。你会发现 [Data App 配置文件](/tidb-cloud/data-service-app-config-files.md)已由 `tidb-cloud-data-service` 提交到该目录,这表示你的 Data App 已成功连接到 GitHub。 + + 对于你的新 Data App,默认启用 **Auto Sync & Deployment** 和 **Review Draft**,以便你可以轻松地在 TiDB Cloud 控制台和 GitHub 之间同步 Data App 更改,并在部署前审查更改。有关 GitHub 集成的更多信息,请参阅[使用 GitHub 自动部署 Data App 更改](/tidb-cloud/data-service-manage-github-connection.md)。 + +## 配置 Data App + +你可以编辑 Data App 的名称、版本或描述,并管理其 GitHub 连接、链接的数据源、API 密钥、端点和部署。 + +### 编辑 Data App 属性 + +你可以编辑 Data App 的名称、版本和描述。要编辑 Data App 属性,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在 **Data App Properties** 区域,点击 ,修改 App 名称、版本或描述,然后点击 **Confirm**。 + +### 管理 GitHub 连接 + +有关更多信息,请参阅[使用 GitHub 自动部署](/tidb-cloud/data-service-manage-github-connection.md)。 + +### 管理链接的数据源 + +你可以为 Data App 添加或删除链接的集群。 + +要将集群链接到 Data App,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App 并点击其名称以查看详细信息。 +3. 在 **Linked Data Sources** 区域,点击 **Add Cluster**。 +4. 在显示的对话框中,从列表中选择一个集群,然后点击 **Add**。 + +要从 Data App 中删除链接的集群,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App 并点击其名称以查看详细信息。 +3. 在 **Linked Data Sources** 区域,找到要从 Data App 中删除的目标链接集群,然后在 **Action** 列中点击 **Delete**。 +4. 在显示的对话框中确认删除。 + + 删除链接的集群后,该集群不会被删除,但 Data App 中的现有端点将无法访问它。 + +### 管理 API 密钥 + +有关更多信息,请参阅[管理 API 密钥](/tidb-cloud/data-service-api-key.md)。 + +### 管理端点 + +有关更多信息,请参阅[管理端点](/tidb-cloud/data-service-manage-endpoint.md)。 + +### 管理自定义域名 + +有关更多信息,请参阅[管理自定义域名](/tidb-cloud/data-service-custom-domain.md)。 + +### 管理部署 + +要管理部署,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App 并点击其名称以查看详细信息。 +3. 在 **Deployment Configuration** 区域,点击 **Config**。将显示部署配置对话框。 +4. 在对话框中,选择你想要的 **Auto Sync & Deployment** 和 **Review Draft** 设置。 + + - **Auto Sync & Deployment** + + - 此选项仅在你的 Data App 连接到 GitHub 时才能启用。有关更多信息,请参阅[使用 GitHub 自动部署](/tidb-cloud/data-service-manage-github-connection.md)。 + - 启用后,在你指定的 GitHub 目录中所做的更改可以自动部署到 TiDB Cloud,在 TiDB Cloud 控制台中所做的更改也可以推送到 GitHub。你可以在 Data App 部署历史记录中找到相应的部署和提交信息。 + - 禁用后,在你指定的 GitHub 目录中所做的更改将**不会**部署到 TiDB Cloud,在 TiDB Cloud 控制台中所做的更改也将**不会**推送到 GitHub。 + + - **Review Draft** + + - 启用后,你可以在部署前审查在 TiDB Cloud 控制台中所做的 Data App 更改。根据审查结果,你可以选择部署或放弃更改。 + - 禁用后,在 TiDB Cloud 控制台中所做的 Data App 更改将直接部署。 + +5. 在 **Action** 列中,你可以根据需要编辑或重新部署更改。 + +## 使用 OpenAPI 规范 + +Data Service (beta) 支持为每个 Data App 生成 OpenAPI 规范 3.0,使你能够以标准化格式与端点交互。你可以使用此规范生成标准化的 OpenAPI 文档、客户端 SDK 和服务器存根。 + +### 下载 OpenAPI 规范 + +要以 JSON 或 YAML 格式下载 Data App 的 OpenAPI 规范,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在 **API Specification** 区域,点击 **Download** 并选择 **JSON** 或 **YAML**。 + + 如果这是你第一次下载 OpenAPI 规范,系统会提示你授权请求。 + +4. 然后,OpenAPI 规范将下载到你的本地计算机。 + +### 查看 OpenAPI 文档 + +Data Service (beta) 为每个 Data App 提供自动生成的 OpenAPI 文档。在文档中,你可以查看端点、参数和响应,并试用端点。 + +要访问 OpenAPI 文档,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在页面右上角,点击 **View API Docs**。 + + 如果这是你第一次使用 OpenAPI 规范,系统会提示你授权请求。 + +4. 然后,OpenAPI 文档将在新标签页中打开。在文档中,你可以查看以下信息: + + - Data App 名称、版本和描述。 + - 按标签分组的端点。 + +5. (可选)要试用端点,请执行以下步骤: + + 1. 点击 **Authorize** 并在显示的对话框中输入你的 Data App 公钥作为 **Username** 和私钥作为 **Password**。 + + 有关更多信息,请参阅[管理 API 密钥](/tidb-cloud/data-service-api-key.md)。 + + 2. 找到目标端点,提供所需参数,然后点击 **Try it out**。你可以在 **Response body** 区域查看响应。 + + 有关如何使用 OpenAPI 文档的更多信息,请参阅 [Swagger UI](https://swagger.io/tools/swagger-ui/)。 + +## 删除 Data App + +> **注意:** +> +> 在删除 Data App 之前,请确保所有端点都未上线。否则,你将无法删除 Data App。要取消部署端点,请参考[取消部署端点](/tidb-cloud/data-service-manage-endpoint.md#undeploy-an-endpoint)。 + +要删除 Data App,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App 并点击其名称以查看详细信息。 +3. 在 **Danger Zone** 区域,点击 **Delete Data App**。将显示确认对话框。 +4. 输入你的 `//`,然后点击 **I understand, delete**。 + + 一旦 Data App 被删除,Data App 中的现有端点和 API 密钥也将被删除。如果此 Data App 已连接到 GitHub,删除 App 不会删除相应 GitHub 仓库中的文件。 + +## 了解更多 + +- [在 Postman 中运行 Data App](/tidb-cloud/data-service-postman-integration.md) diff --git a/tidb-cloud/data-service-manage-endpoint.md b/tidb-cloud/data-service-manage-endpoint.md new file mode 100644 index 000000000000..4a9710360cc1 --- /dev/null +++ b/tidb-cloud/data-service-manage-endpoint.md @@ -0,0 +1,547 @@ +--- +title: 管理端点 +summary: 了解如何在 TiDB Cloud 控制台中创建、开发、测试、部署和删除 Data App 中的端点。 +--- + +# 管理端点 + +Data Service(测试版)中的端点是一个可以自定义执行 SQL 语句的 Web API。你可以为 SQL 语句指定参数,例如在 `WHERE` 子句中使用的值。当客户端调用端点并在请求 URL 中提供参数值时,端点会使用提供的参数执行 SQL 语句,并将结果作为 HTTP 响应的一部分返回。 + +本文介绍如何在 TiDB Cloud 控制台中管理 Data App 中的端点。 + +## 开始之前 + +- 在创建端点之前,请确保以下内容: + + - 你已创建集群和 Data App。更多信息,请参见[创建 Data App](/tidb-cloud/data-service-manage-data-app.md#create-a-data-app)。 + - 端点将要操作的数据库、表和列已经存在于目标集群中。 + +- 在调用端点之前,请确保你已在 Data App 中创建了 API 密钥。更多信息,请参见[创建 API 密钥](/tidb-cloud/data-service-api-key.md#create-an-api-key)。 + +## 创建端点 + +在 Data Service 中,你可以自动生成端点、手动创建端点或添加预定义的系统端点。 + +> **提示:** +> +> 你也可以从 SQL Editor 中的 SQL 文件创建端点。更多信息,请参见[从 SQL 文件生成端点](/tidb-cloud/explore-data-with-chat2query.md#generate-an-endpoint-from-a-sql-file)。 + +### 自动生成端点 + +在 TiDB Cloud Data Service 中,你可以按以下方式一次性自动生成一个或多个端点: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App,点击 App 名称右侧的 **+**,然后点击**自动生成端点**。此时会显示端点生成对话框。 +3. 在对话框中,执行以下操作: + + 1. 为要生成的端点选择目标集群、数据库和表。 + + > **注意:** + > + > **表**下拉列表仅包含至少有一列的用户定义表,不包括系统表和没有列定义的表。 + + 2. 为要生成的端点选择至少一个 HTTP 操作(如 `GET(检索)`、`POST(创建)`和 `PUT(更新)`)。 + + 对于你选择的每个操作,TiDB Cloud Data Service 将生成一个相应的端点。如果你选择批量操作(如 `POST(批量创建)`),生成的端点允许你在单个请求中操作多行数据。 + + 如果你选择的表包含[向量数据类型](/tidb-cloud/vector-search-data-types.md),你可以启用**向量搜索操作**选项并选择向量距离函数,以生成一个向量搜索端点,该端点会根据你选择的距离函数自动计算向量距离。支持的[向量距离函数](/tidb-cloud/vector-search-functions-and-operators.md)包括: + + - `VEC_L2_DISTANCE`(默认):计算两个向量之间的 L2 距离(欧几里得距离)。 + - `VEC_COSINE_DISTANCE`:计算两个向量之间的余弦距离。 + - `VEC_NEGATIVE_INNER_PRODUCT`:使用两个向量之间内积的负值计算距离。 + - `VEC_L1_DISTANCE`:计算两个向量之间的 L1 距离(曼哈顿距离)。 + + 3. (可选)为操作配置超时时间和标签。所有生成的端点将自动继承配置的属性,可以根据需要稍后修改。 + 4. (可选)**自动部署端点**选项(默认禁用)控制是否启用生成端点的直接部署。启用时,将跳过草稿审查过程,生成的端点将立即部署,无需进一步手动审查或批准。 + +4. 点击**生成**。 + + 生成的端点显示在端点列表的顶部。 + +5. 检查新端点的生成端点名称、SQL 语句、属性和参数。 + + - 端点名称:生成的端点名称采用 `/<选择的表名>` 格式,请求方法(如 `GET`、`POST` 和 `PUT`)显示在端点名称之前。例如,如果选择的表名是 `sample_table` 且选择的操作是 `POST(创建)`,生成的端点显示为 `POST /sample_table`。 + + - 如果选择了批量操作,TiDB Cloud Data Service 会在生成的端点名称后附加 `/bulk`。例如,如果选择的表名是 `/sample_table` 且选择的操作是 `POST(批量创建)`,生成的端点显示为 `POST /sample_table/bulk`。 + - 如果选择了 `POST(向量相似度搜索)`,TiDB Cloud Data Service 会在生成的端点名称后附加 `/vector_search`。例如,如果选择的表名是 `/sample_table` 且选择的操作是 `POST(向量相似度搜索)`,生成的端点显示为 `POST /sample_table/vector_search`。 + - 如果已经存在具有相同请求方法和端点名称的端点,TiDB Cloud Data Service 会在生成的端点名称后附加 `_dump_<随机字母>`。例如,`/sample_table_dump_EUKRfl`。 + + - SQL 语句:TiDB Cloud Data Service 根据表列规范和选择的端点操作自动编写生成端点的 SQL 语句。你可以点击端点名称在页面中间部分查看其 SQL 语句。 + - 端点属性:TiDB Cloud Data Service 根据你的选择自动配置端点路径、请求方法、超时时间和标签。你可以在页面右侧窗格中找到这些属性。 + - 端点参数:TiDB Cloud Data Service 自动为生成的端点配置参数。你可以在页面右侧窗格中找到这些参数。 + +6. 如果你想修改生成端点的详细信息,如名称、SQL 语句、属性或参数,请参考[开发端点](#开发端点)中提供的说明。 + +### 手动创建端点 + +要手动创建端点,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App,点击 App 名称右侧的 **+**,然后点击**创建端点**。 +3. 如有必要,更新默认名称。新创建的端点将添加到端点列表的顶部。 +4. 根据[开发端点](#开发端点)中的说明配置新端点。 + +### 添加预定义系统端点 + +Data Service 提供了一个包含预定义系统端点的端点库,你可以直接将这些端点添加到你的 Data App 中,从而减少端点开发的工作量。目前,该库仅包含 `/system/query` 端点,该端点允许你通过简单地在预定义的 `sql` 参数中传递语句来执行任何 SQL 语句。 + +要将预定义系统端点添加到你的 Data App 中,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 + +2. 在左侧窗格中,找到目标 Data App,点击 App 名称右侧的 **+**,然后点击**管理端点库**。 + + 此时会显示端点库管理对话框。目前,对话框中仅提供**执行查询**(即 `/system/query` 端点)。 + +3. 要将 `/system/query` 端点添加到你的 Data App 中,将**执行查询**开关切换到**已添加**。 + + > **提示:** + > + > 要从你的 Data App 中删除已添加的预定义端点,将**执行查询**开关切换到**已删除**。 + +4. 点击**保存**。 + + > **注意:** + > + > - 点击**保存**后,添加或删除的端点会立即部署到生产环境,这使得添加的端点立即可访问,删除的端点立即不可访问。 + > - 如果当前 App 中已存在具有相同路径和方法的非预定义端点,系统端点的创建将失败。 + + 添加的系统提供的端点将显示在端点列表的顶部。 + +5. 检查新端点的端点名称、SQL 语句、属性和参数。 + + > **注意:** + > + > `/system/query` 端点功能强大且通用,但可能具有破坏性。请谨慎使用,并确保查询是安全的且经过充分考虑,以防止意外后果。 + + - 端点名称:端点名称和路径为 `/system/query`,请求方法为 `POST`。 + - SQL 语句:`/system/query` 端点不附带任何 SQL 语句。你可以在页面中间部分找到 SQL 编辑器,并在其中编写所需的 SQL 语句。请注意,为 `/system/query` 端点编写的 SQL 语句将保存在 SQL 编辑器中,以便你下次可以进一步开发和测试,但不会保存在端点配置中。 + - 端点属性:在页面右侧窗格的**属性**标签页中,你可以找到端点属性。与其他自定义端点不同,系统端点只能自定义 `timeout` 和 `max rows` 属性。 + - 端点参数:在页面右侧窗格的**参数**标签页中,你可以找到端点参数。`/system/query` 端点的参数是自动配置的,不能修改。 + +## 开发端点 + +对于每个端点,你可以编写要在 TiDB 集群上执行的 SQL 语句,为 SQL 语句定义参数,或管理名称和版本。 + +> **注意:** +> +> 如果你已将 Data App 连接到 GitHub 并启用了**自动同步和部署**,你也可以使用 GitHub 更新端点配置。你在 GitHub 中所做的任何更改都将自动部署在 TiDB Cloud Data Service 中。更多信息,请参见[使用 GitHub 自动部署](/tidb-cloud/data-service-manage-github-connection.md)。 + +### 配置属性 + +在端点详情页面的右侧窗格中,你可以点击**属性**标签页来查看和配置端点的属性。 + +#### 基本属性 + +- **路径**:用户用来访问端点的路径。 + +#### 高级属性 + +- **超时时间(毫秒)**:端点的超时时间,以毫秒为单位。 +- **最大行数**:端点可以操作或返回的最大行数。 +- **标签**:用于标识一组端点的标签。 +- **分页**:此属性仅在请求方法为 `GET` 且端点的最后一个 SQL 语句是 `SELECT` 操作时可用。当启用**分页**时,你可以在调用端点时通过指定 `page` 和 `page_size` 作为查询参数来对结果进行分页,例如 `https://.data.tidbcloud.com/api/v1beta/app//endpoint/my_endpoint/get_id?page=<页码>&page_size=<每页大小>`。更多信息,请参见[调用端点](#调用端点)。 + + > **注意:** + > + > - 如果你在请求中不包含 `page` 和 `page_size` 参数,默认行为是在单个页面上返回**最大行数**属性中指定的最大行数。 + > - `page_size` 必须小于或等于**最大行数**属性。否则,将返回错误。 + +- **缓存响应**:此属性仅在请求方法为 `GET` 时可用。当启用**缓存响应**时,TiDB Cloud Data Service 可以在指定的生存时间(TTL)期间内缓存你的 `GET` 请求返回的响应。 +- **生存时间(秒)**:此属性仅在启用**缓存响应**时可用。你可以使用它来指定缓存响应的生存时间(TTL)期间,以秒为单位。在 TTL 期间内,如果你再次发出相同的 `GET` 请求,Data Service 会直接返回缓存的响应,而不是再次从目标数据库获取数据,这提高了你的查询性能。 +- **批量操作**:此属性仅在请求方法为 `POST` 或 `PUT` 时可见。当启用**批量操作**时,你可以在单个请求中操作多行数据。例如,在[调用端点](#调用端点)时,你可以通过在 curl 命令的 `--data-raw` 选项中将数据对象数组放入对象的 `items` 字段来在单个 `POST` 请求中插入多行数据。 + + > **注意:** + > + > 启用**批量操作**的端点支持请求体的数组和对象格式:`[{dataObject1}, {dataObject2}]` 和 `{items: [{dataObject1}, {dataObject2}]}`。为了更好地与其他系统兼容,建议使用对象格式 `{items: [{dataObject1}, {dataObject2}]}`。 + +### 编写 SQL 语句 + +在端点详情页面的 SQL 编辑器中,你可以编写和运行端点的 SQL 语句。你也可以简单地输入 `--` 后跟你的指令,让 AI 自动生成 SQL 语句。 + +1. 选择集群。 + + > **注意:** + > + > 下拉列表中只显示链接到 Data App 的集群。要管理链接的集群,请参见[管理链接的数据源](/tidb-cloud/data-service-manage-data-app.md#manage-linked-data-sources)。 + + 在 SQL 编辑器的上部,从下拉列表中选择你想要执行 SQL 语句的集群。然后,你可以在右侧窗格的**架构**标签页中查看此集群的所有数据库。 + +2. 根据你的端点类型,执行以下操作之一来选择数据库: + + - 预定义系统端点:在 SQL 编辑器的上部,从下拉列表中选择目标数据库。 + - 其他端点:在 SQL 编辑器中编写 SQL 语句来指定目标数据库。例如,`USE database_name;`。 + +3. 编写 SQL 语句。 + + 在 SQL 编辑器中,你可以编写诸如表连接查询、复杂查询和聚合函数等语句。你也可以简单地输入 `--` 后跟你的指令,让 AI 自动生成 SQL 语句。 + + 要定义参数,你可以在 SQL 语句中将其作为变量占位符插入,如 `${ID}`。例如,`SELECT * FROM table_name WHERE id = ${ID}`。然后,你可以点击右侧窗格的**参数**标签页来更改参数定义和测试值。更多信息,请参见[参数](#配置参数)。 + + 在定义数组参数时,参数会自动转换为 SQL 语句中的多个逗号分隔值。为确保 SQL 语句有效,你需要在某些 SQL 语句(如 `IN`)中在参数周围添加括号(`()`)。例如,如果你定义一个测试值为 `1,2,3` 的数组参数 `ID`,使用 `SELECT * FROM table_name WHERE id IN (${ID})` 来查询数据。 + + > **注意:** + > + > - 参数名称区分大小写。 + > - 参数不能用作表名或列名。 + +4. 运行 SQL 语句。 + + 如果你在 SQL 语句中插入了参数,请确保你已在右侧窗格的**参数**标签页中为参数设置了测试值或默认值。否则,将返回错误。 + + +
+ + 对于 macOS: + + - 如果编辑器中只有一个语句,要运行它,请按 **⌘ + Enter** 或点击 **运行**。 + + - 如果编辑器中有多个语句,要按顺序运行其中一个或多个语句,请将光标放在目标语句上或用光标选择目标语句的行,然后按 **⌘ + Enter** 或点击**运行**。 + + - 要按顺序运行编辑器中的所有语句,请按 **⇧ + ⌘ + Enter**,或用光标选择所有语句的行并点击**运行**。 + +
+ +
+ + 对于 Windows 或 Linux: + + - 如果编辑器中只有一个语句,要运行它,请按 **Ctrl + Enter** 或点击 **运行**。 + + - 如果编辑器中有多个语句,要按顺序运行其中一个或多个语句,请将光标放在目标语句上或用光标选择目标语句的行,然后按 **Ctrl + Enter** 或点击**运行**。 + + - 要按顺序运行编辑器中的所有语句,请按 **Shift + Ctrl + Enter**,或用光标选择所有语句的行并点击**运行**。 + +
+
+ + 运行语句后,你可以在页面底部的**结果**标签页中立即看到查询结果。 + + > **注意:** + > + > 返回的结果大小限制为 8 MiB。 + +### 配置参数 + +在端点详情页面的右侧窗格中,你可以点击**参数**标签页来查看和管理端点中使用的参数。 + +在**定义**部分,你可以查看和管理参数的以下属性: + +- 参数名称:名称只能包含字母、数字和下划线(`_`),并且必须以字母或下划线(`_`)开头。**不要**使用 `page` 和 `page_size` 作为参数名称,这些是为请求结果分页保留的。 +- **必需**:指定参数在请求中是否是必需的。对于路径参数,配置是必需的且不能修改。对于其他参数,默认配置是不必需的。 +- **类型**:指定参数的数据类型。对于路径参数,只支持 `STRING` 和 `INTEGER`。对于其他参数,支持 `STRING`、`NUMBER`、`INTEGER`、`BOOLEAN` 和 `ARRAY`。 + + 使用 `STRING` 类型参数时,不需要添加引号(`'` 或 `"`)。例如,`foo` 对于 `STRING` 类型是有效的,并被处理为 `"foo"`,而 `"foo"` 被处理为 `"\"foo\""`。 + +- **枚举值**:(可选)指定参数的有效值,仅在参数类型为 `STRING`、`INTEGER` 或 `NUMBER` 时可用。 + + - 如果将此字段留空,参数可以是指定类型的任何值。 + - 要指定多个有效值,可以用逗号(`,`)分隔它们。例如,如果你将参数类型设置为 `STRING` 并将此字段指定为 `foo, bar`,则参数值只能是 `foo` 或 `bar`。 + +- **项目类型**:指定 `ARRAY` 类型参数的项目类型。 +- **默认值**:指定参数的默认值。 + + - 对于 `ARRAY` 类型,你需要用逗号(`,`)分隔多个值。 + - 确保值可以转换为参数的类型。否则,端点将返回错误。 + - 如果你没有为参数设置测试值,在测试端点时将使用默认值。 +- **位置**:指示参数的位置。此属性不能修改。 + - 对于路径参数,此属性为 `Path`。 + - 对于其他参数,如果请求方法为 `GET` 或 `DELETE`,此属性为 `Query`。如果请求方法为 `POST` 或 `PUT`,此属性为 `Body`。 + +在**测试值**部分,你可以查看和设置测试参数。这些值在你测试端点时用作参数值。确保值可以转换为参数的类型。否则,端点将返回错误。 + +### 重命名 + +要重命名端点,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其端点。 +3. 找到要重命名的端点,点击 **...** > **重命名**,然后为端点输入新名称。 + +> **注意:** +> +> 预定义系统端点不支持重命名。 + +## 测试端点 + +要测试端点,请执行以下步骤: + +> **提示:** +> +> 如果你已将 Data App 导入到 Postman,你也可以在 Postman 中测试 Data App 的端点。更多信息,请参见[在 Postman 中运行 Data App](/tidb-cloud/data-service-postman-integration.md)。 + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其端点。 +3. 点击要测试的端点的名称以查看其详细信息。 +4. (可选)如果端点包含参数,你需要在测试之前设置测试值。 + + 1. 在端点详情页面的右侧窗格中,点击**参数**标签页。 + 2. 展开**测试值**部分并为参数设置测试值。 + + 如果你没有为参数设置测试值,将使用默认值。 + +5. 点击右上角的**测试**。 + + > **提示:** + > + > 或者,你也可以按 F5 来测试端点。 + +测试端点后,你可以在页面底部看到 JSON 格式的响应。有关 JSON 响应的更多信息,请参考[端点的响应](#响应)。 + +## 部署端点 + +> **注意:** +> +> 如果你已将 Data App 连接到 GitHub 并启用了**自动同步和部署**,你在 GitHub 中所做的任何 Data App 更改都将自动部署在 TiDB Cloud Data Service 中。更多信息,请参见[使用 GitHub 自动部署](/tidb-cloud/data-service-manage-github-connection.md)。 + +要部署端点,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其端点。 +3. 找到要部署的端点,点击端点名称以查看其详细信息,然后点击右上角的**部署**。 +4. 如果为你的 Data App 启用了**审查草稿**,将显示一个对话框供你审查所做的更改。你可以根据审查决定是否放弃更改。 +5. 点击**部署**确认部署。如果端点成功部署,你将收到**端点已部署**提示。 + + 在端点详情页面的右侧窗格中,你可以点击**部署**标签页查看部署历史。 + +## 调用端点 + +要调用端点,你可以向端点的未部署草稿版本或已部署在线版本发送 HTTPS 请求。 + +> **提示:** +> +> 如果你已将 Data App 导入到 Postman,你也可以在 Postman 中调用 Data App 的端点。更多信息,请参见[在 Postman 中运行 Data App](/tidb-cloud/data-service-postman-integration.md)。 + +### 前提条件 + +在调用端点之前,你需要创建 API 密钥。更多信息,请参考[创建 API 密钥](/tidb-cloud/data-service-api-key.md#create-an-api-key)。 + +### 请求 + +TiDB Cloud Data Service 生成代码示例来帮助你调用端点。要获取代码示例,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其端点。 +3. 找到要调用的端点并点击 **...** > **代码示例**。此时会显示**代码示例**对话框。 + + > **提示:** + > + > 或者,你也可以点击端点名称以查看其详细信息,然后点击右上角的 **...** > **代码示例**。 + +4. 在对话框中,选择你要用来调用端点的环境和认证方法,然后复制代码示例。 + + > **注意:** + > + > - 代码示例是根据端点的属性和参数生成的。 + > - 目前,TiDB Cloud Data Service 仅提供 curl 代码示例。 + + - 环境:根据你的需要选择**测试环境**或**在线环境**。**在线环境**仅在你部署端点后可用。 + - 认证方法:选择**基本认证**或**摘要认证**。 + - **基本认证**以 base64 编码文本的形式传输你的 API 密钥。 + - **摘要认证**以加密形式传输你的 API 密钥,这更安全。 + + 与**基本认证**相比,**摘要认证**的 curl 代码包含一个额外的 `--digest` 选项。 + + 以下是启用**批量操作**并使用**摘要认证**的 `POST` 请求的 curl 代码片段示例: + + +
+ + 要调用端点的草稿版本,你需要添加 `endpoint-type: draft` 头: + + ```bash + curl --digest --user ':' \ + --request POST 'https://.data.tidbcloud.com/api/v1beta/app//endpoint/' \ + --header 'content-type: application/json'\ + --header 'endpoint-type: draft' + --data-raw '{ + "items": [ + { + "age": "${age}", + "career": "${career}" + } + ] + }' + ``` + +
+ +
+ + 你必须先部署端点,然后才能在在线环境中查看代码示例。 + + 要调用端点的当前在线版本,使用以下命令: + + ```bash + curl --digest --user ':' \ + --request POST 'https://.data.tidbcloud.com/api/v1beta/app//endpoint/' \ + --header 'content-type: application/json'\ + --data-raw '{ + "items": [ + { + "age": "${age}", + "career": "${career}" + } + ] + }' + ``` + +
+
+ + > **注意:** + > + > - 通过请求区域域名 `.data.tidbcloud.com`,你可以直接访问 TiDB 集群所在区域的端点。 + > - 或者,你也可以请求全局域名 `data.tidbcloud.com` 而不指定区域。这样,TiDB Cloud Data Service 将在内部将请求重定向到目标区域,但这可能会导致额外的延迟。如果你选择这种方式,请确保在调用端点时在 curl 命令中添加 `--location-trusted` 选项。 + +5. 将代码示例粘贴到你的应用程序中,根据需要编辑示例,然后运行它。 + + - 你需要将 `` 和 `` 占位符替换为你的 API 密钥。更多信息,请参考[管理 API 密钥](/tidb-cloud/data-service-api-key.md)。 + - 如果你的端点的请求方法为 `GET` 且为端点启用了**分页**,你可以通过用所需的值更新 `page=<页码>` 和 `page_size=<每页大小>` 的值来对结果进行分页。例如,要获取每页 10 项的第二页,使用 `page=2` 和 `page_size=10`。 + - 如果你的端点的请求方法为 `POST` 或 `PUT`,根据你要操作的数据行填写 `--data-raw` 选项。 + + - 对于启用了**批量操作**的端点,`--data-raw` 选项接受一个包含数据对象数组的 `items` 字段的对象,这样你可以使用一个端点操作多行数据。 + - 对于未启用**批量操作**的端点,`--data-raw` 选项只接受一个数据对象。 + + - 如果端点包含参数,在调用端点时指定参数值。 + +### 响应 + +调用端点后,你可以看到 JSON 格式的响应。更多信息,请参见 [Data Service 的响应和状态码](/tidb-cloud/data-service-response-and-status-code.md)。 + +## 取消部署端点 + +> **注意:** +> +> 如果你已[将 Data App 连接到 GitHub](/tidb-cloud/data-service-manage-github-connection.md) 并启用了**自动同步和部署**,取消部署此 Data App 的端点也会删除 GitHub 上此端点的配置。 + +要取消部署端点,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其端点。 +3. 找到要取消部署的端点,点击 **...** > **取消部署**。 +4. 点击**取消部署**确认取消部署。 + +## 删除端点 + +> **注意:** +> +> 在删除端点之前,请确保端点不在线。否则,无法删除端点。要取消部署端点,请参考[取消部署端点](#取消部署端点)。 + +要删除端点,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其端点。 +3. 点击要删除的端点的名称,然后点击右上角的 **...** > **删除**。 +4. 点击**删除**确认删除。 + + - 路径长度必须小于 64 个字符。 + - 请求方法和路径的组合在 Data App 内必须是唯一的。 + - 路径中只允许使用字母、数字、下划线(`_`)、斜杠(`/`)和用大括号括起来的参数(如 `{var}`)。每个路径必须以斜杠(`/`)开头,以字母、数字或下划线(`_`)结尾。例如,`/my_endpoint/get_id`。 + - 对于用 `{ }` 括起来的参数,只允许使用字母、数字和下划线(`_`)。每个用 `{ }` 括起来的参数必须以字母或下划线(`_`)开头。 + + > **注意:** + > + > - 在路径中,每个参数必须在单独的层级中,不支持前缀或后缀。 + > + > 有效路径:```/var/{var}``` 和 ```/{var}``` + > + > 无效路径:```/var{var}``` 和 ```/{var}var``` + > + > - 具有相同方法和前缀的路径可能会冲突,如以下示例: + > + > ```GET /var/{var1}``` + > + > ```GET /var/{var2}``` + > + > 这两个路径会相互冲突,因为 `GET /var/123` 与两者都匹配。 + > + > - 带参数的路径优先级低于不带参数的路径。例如: + > + > ```GET /var/{var1}``` + > + > ```GET /var/123``` + > + > 这两个路径不会冲突,因为 `GET /var/123` 优先。 + > + > - 路径参数可以直接在 SQL 中使用。更多信息,请参见[配置参数](#配置参数)。 + +- **端点 URL**:(只读)默认 URL 根据相应集群所在的区域、Data App 的服务 URL 和端点的路径自动生成。例如,如果端点的路径是 `/my_endpoint/get_id`,则端点 URL 是 `https://.data.tidbcloud.com/api/v1beta/app//endpoint/my_endpoint/get_id`。要为 Data App 配置自定义域名,请参见 [Data Service 中的自定义域名](/tidb-cloud/data-service-custom-domain.md)。 + +- **请求方法**:端点的 HTTP 方法。支持以下方法: + + - `GET`:用于查询或检索数据,如 `SELECT` 语句。 + - `POST`:用于插入或创建数据,如 `INSERT` 语句。 + - `PUT`:用于更新或修改数据,如 `UPDATE` 语句。 + - `DELETE`:用于删除数据,如 `DELETE` 语句。 + +- **描述**(可选):端点的描述。 + +# 管理端点 + +Data Service(测试版)中的端点是一个可以自定义执行 SQL 语句的 Web API。你可以为 SQL 语句指定参数,例如在 `WHERE` 子句中使用的值。当客户端调用端点并在请求 URL 中提供参数值时,端点会使用提供的参数执行 SQL 语句,并将结果作为 HTTP 响应的一部分返回。 + +本文介绍如何在 TiDB Cloud 控制台中管理 Data App 中的端点。 + +## 开始之前 + +- 在创建端点之前,请确保以下内容: + + - 你已创建集群和 Data App。更多信息,请参见[创建 Data App](/tidb-cloud/data-service-manage-data-app.md#create-a-data-app)。 + - 端点将要操作的数据库、表和列已经存在于目标集群中。 + +- 在调用端点之前,请确保你已在 Data App 中创建了 API 密钥。更多信息,请参见[创建 API 密钥](/tidb-cloud/data-service-api-key.md#create-an-api-key)。 + +## 创建端点 + +在 Data Service 中,你可以自动生成端点、手动创建端点或添加预定义的系统端点。 + +> **提示:** +> +> 你也可以从 SQL Editor 中的 SQL 文件创建端点。更多信息,请参见[从 SQL 文件生成端点](/tidb-cloud/explore-data-with-chat2query.md#generate-an-endpoint-from-a-sql-file)。 + +### 自动生成端点 + +在 TiDB Cloud Data Service 中,你可以按以下方式一次性自动生成一个或多个端点: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,找到目标 Data App,点击 App 名称右侧的 **+**,然后点击**自动生成端点**。此时会显示端点生成对话框。 +3. 在对话框中,执行以下操作: + + 1. 为要生成的端点选择目标集群、数据库和表。 + + > **注意:** + > + > **表**下拉列表仅包含至少有一列的用户定义表,不包括系统表和没有列定义的表。 + + 2. 为要生成的端点选择至少一个 HTTP 操作(如 `GET(检索)`、`POST(创建)`和 `PUT(更新)`)。 + + 对于你选择的每个操作,TiDB Cloud Data Service 将生成一个相应的端点。如果你选择批量操作(如 `POST(批量创建)`),生成的端点允许你在单个请求中操作多行数据。 + + 如果你选择的表包含[向量数据类型](/tidb-cloud/vector-search-data-types.md),你可以启用**向量搜索操作**选项并选择向量距离函数,以生成一个向量搜索端点,该端点会根据你选择的距离函数自动计算向量距离。支持的[向量距离函数](/tidb-cloud/vector-search-functions-and-operators.md)包括: + + - `VEC_L2_DISTANCE`(默认):计算两个向量之间的 L2 距离(欧几里得距离)。 + - `VEC_COSINE_DISTANCE`:计算两个向量之间的余弦距离。 + - `VEC_NEGATIVE_INNER_PRODUCT`:使用两个向量之间内积的负值计算距离。 + - `VEC_L1_DISTANCE`:计算两个向量之间的 L1 距离(曼哈顿距离)。 + + 3. (可选)为操作配置超时时间和标签。所有生成的端点将自动继承配置的属性,可以根据需要稍后修改。 + 4. (可选)**自动部署端点**选项(默认禁用)控制是否启用生成端点的直接部署。启用时,将跳过草稿审查过程,生成的端点将立即部署,无需进一步手动审查或批准。 + +4. 点击**生成**。 + + 生成的端点显示在端点列表的顶部。 + +5. 检查新端点的生成端点名称、SQL 语句、属性和参数。 + + - 端点名称:生成的端点名称采用 `/<选择的表名>` 格式,请求方法(如 `GET`、`POST` 和 `PUT`)显示在端点名称之前。例如,如果选择的表名是 `sample_table` 且选择的操作是 `POST(创建)`,生成的端点显示为 `POST /sample_table`。 + + - 如果选择了批量操作,TiDB Cloud Data Service 会在生成的端点名称后附加 `/bulk`。例如,如果选择的表名是 `/sample_table` 且选择的操作是 `POST(批量创建)`,生成的端点显示为 `POST /sample_table/bulk`。 + - 如果选择了 `POST(向量相似度搜索)`,TiDB Cloud Data Service 会在生成的端点名称后附加 `/vector_search`。例如,如果选择的表名是 `/sample_table` 且选择的操作是 `POST(向量相似度搜索)`,生成的端点显示为 `POST /sample_table/vector_search`。 + - 如果已经存在具有相同请求方法和端点名称的端点,TiDB Cloud Data Service 会在生成的端点名称后附加 `_dump_<随机字母>`。例如,`/sample_table_dump_EUKRfl`。 + + - SQL 语句:TiDB Cloud Data Service 根据表列规范和选择的端点操作自动编写生成端点的 SQL 语句。你可以点击端点名称在页面中间部分查看其 SQL 语句。 + - 端点属性:TiDB Cloud Data Service 根据你的选择自动配置端点路径、请求方法、超时时间和标签。你可以在页面右侧窗格中找到这些属性。 + - 端点参数:TiDB Cloud Data Service 自动为生成的端点配置参数。你可以在页面右侧窗格中找到这些参数。 + +6. 如果你想修改生成端点的详细信息,如名称、SQL 语句、属性或参数,请参考[开发端点](#开发端点)中提供的说明。 diff --git a/tidb-cloud/data-service-manage-github-connection.md b/tidb-cloud/data-service-manage-github-connection.md new file mode 100644 index 000000000000..f629e5517e94 --- /dev/null +++ b/tidb-cloud/data-service-manage-github-connection.md @@ -0,0 +1,162 @@ +--- +title: 使用 GitHub 自动部署 Data App +summary: 了解如何使用 GitHub 自动部署 Data App。 +--- + +# 使用 GitHub 自动部署 Data App + +TiDB Cloud 提供了一种配置即代码(Configuration as Code,CaC)的方法,使用 JSON 语法将整个 Data App 配置表示为代码。 + +通过将 Data App 连接到 GitHub,TiDB Cloud 可以使用 CaC 方法,将你的 Data App 配置作为[配置文件](/tidb-cloud/data-service-app-config-files.md)推送到你指定的 GitHub 仓库和分支。 + +如果为你的 GitHub 连接启用了**自动同步和部署**,你还可以通过在 GitHub 上更新配置文件来修改 Data App。将配置文件更改推送到 GitHub 后,新的配置将自动部署到 TiDB Cloud。 + +本文档介绍如何使用 GitHub 自动部署 Data App 以及如何管理 GitHub 连接。 + +## 开始之前 + +在将 Data App 连接到 GitHub 之前,请确保你具有以下条件: + +- GitHub 账户。 +- 带有目标分支的 GitHub 仓库。 + +> **注意:** +> +> GitHub 仓库用于在将 Data App 连接到它后存储 [Data App 配置文件](/tidb-cloud/data-service-app-config-files.md)。如果配置文件中的信息(如集群 ID 和端点 URL)比较敏感,请确保使用私有仓库而不是公共仓库。 + +## 步骤 1. 将 Data App 连接到 GitHub + +你可以在创建 App 时将 Data App 连接到 GitHub。更多信息,请参见[创建 Data App](/tidb-cloud/data-service-manage-data-app.md)。 + +如果你在创建 App 时没有启用 GitHub 连接,你仍然可以按照以下方式启用它: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**设置**标签页上,点击**连接到 GitHub**区域中的**连接**。将显示连接设置对话框。 +4. 在对话框中,执行以下步骤: + + 1. 点击**在 GitHub 上安装**,然后按照屏幕上的说明将 **TiDB Cloud Data Service** 作为应用程序安装在目标仓库上。 + 2. 点击**授权**以授权访问 GitHub 上的应用程序。 + 3. 指定要存储 Data App 配置文件的目标仓库、分支和目录。 + + > **注意:** + > + > - 目录必须以斜杠 (`/`) 开头。例如,`/mydata`。如果你指定的目录在目标仓库和分支中不存在,它将自动创建。 + > - 仓库、分支和目录的组合标识了配置文件的路径,该路径在 Data App 之间必须是唯一的。如果你指定的路径已被另一个 Data App 使用,你需要指定一个新路径。否则,当前 Data App 在 TiDB Cloud 控制台中配置的端点将覆盖你指定路径中的文件。 + > - 如果你指定的路径包含从另一个 Data App 复制的配置文件,并且你想将这些文件导入到当前 Data App,请参见[导入现有 Data App 的配置](#导入现有-data-app-的配置)。 + + 4. 要允许在 TiDB Cloud 控制台或 GitHub 中所做的 Data App 更改相互同步,请启用**配置自动同步和部署**。 + + - 启用后,在你指定的 GitHub 目录中所做的更改可以自动部署到 TiDB Cloud,在 TiDB Cloud 控制台中所做的更改也可以推送到 GitHub。你可以在 Data App 部署历史记录中找到相应的部署和提交信息。 + - 禁用后,在你指定的 GitHub 目录中所做的更改将**不会**部署到 TiDB Cloud,在 TiDB Cloud 控制台中所做的更改也将**不会**推送到 GitHub。 + +5. 点击**确认连接**。 + +## 步骤 2. 将 Data App 配置与 GitHub 同步 + +如果在[创建 Data App](/tidb-cloud/data-service-manage-data-app.md) 时启用了 GitHub 连接,TiDB Cloud 会在 App 创建后立即将此 Data App 的配置文件推送到 GitHub。 + +如果在创建 App 后启用了 GitHub 连接,你需要执行部署操作以将 Data App 配置与 GitHub 同步。例如,你可以点击**部署**标签页,然后为此 Data App 重新部署一个部署。 + +部署操作后,检查你指定的 GitHub 目录。你会发现 Data App 配置文件已由 `tidb-cloud-data-service` 提交到该目录,这意味着你的 Data App 已成功连接到 GitHub。目录结构如下: + +``` +├── <你在 GitHub 上的 Data App 目录> +│ ├── data_sources +│ │ └── cluster.json # 指定链接的集群。 +│ ├── dataapp_config.json # 指定 Data APP ID、名称、类型、版本和描述。 +│ ├── http_endpoints +│ │ ├── config.json # 指定端点。 +│ │ └── sql # 包含端点的 SQL 文件。 +│ │ ├── -.sql +│ │ ├── -.sql +│ │ └── -.sql +``` + +## 步骤 3. 修改 Data App + +启用**自动同步和部署**后,你可以使用 GitHub 或 TiDB Cloud 控制台修改 Data App。 + +- [选项 1:通过在 GitHub 上更新文件修改 Data App](#选项-1通过在-github-上更新文件修改-data-app) +- [选项 2:在 TiDB Cloud 控制台中修改 Data App](#选项-2在-tidb-cloud-控制台中修改-data-app) + +> **注意:** +> +> 如果你同时在 GitHub 和 TiDB Cloud 控制台上修改了 Data App,要解决冲突,你可以选择放弃在控制台中所做的更改,或让控制台更改覆盖 GitHub 更改。 + +### 选项 1:通过在 GitHub 上更新文件修改 Data App + +更新配置文件时,请注意以下事项: + +| 文件目录 | 注意事项 | +| ---------|---------| +| `data_source/cluster.json` | 更新此文件时,请确保你有权访问链接的集群。你可以从集群 URL 获取集群 ID。例如,如果集群 URL 是 `https://tidbcloud.com/clusters/1234567891234567890/overview`,则集群 ID 是 `1234567891234567890`。 | +| `http_endpoints/config.json` | 修改端点时,请确保遵循[HTTP 端点配置](/tidb-cloud/data-service-app-config-files.md#http-endpoint-configuration)中描述的规则。 | +| `http_endpoints/sql/method-.sql`| 要在 `http_endpoints/sql` 目录中添加或删除 SQL 文件,你还需要更新相应的端点配置。 | +| `datapp_config.json` | 除非你的 `dataapp_config.json` 文件是从另一个 Data App 复制的,并且你想将其更新为当前 Data App 的 ID,否则不要更改此文件中的 `app_id` 字段。否则,由此修改触发的部署将失败。 | + +有关这些文件中字段配置的更多信息,请参见 [Data App 配置文件](/tidb-cloud/data-service-app-config-files.md)。 + +文件更改提交并推送后,TiDB Cloud 将自动使用 GitHub 上的最新更改部署 Data App。你可以在部署历史记录中查看部署状态和提交信息。 + +### 选项 2:在 TiDB Cloud 控制台中修改 Data App + +在 TiDB Cloud 控制台中[修改 Data App 端点](/tidb-cloud/data-service-manage-endpoint.md)(如修改端点)后,你可以按照以下方式审查并将更改部署到 GitHub: + +1. 点击右上角的**部署**。将显示一个对话框,供你审查所做的更改。 +2. 根据你的审查,执行以下操作之一: + + - 如果你仍想基于当前草稿进行进一步更改,关闭此对话框并进行更改。 + - 如果你想将当前更改恢复到上次部署,点击**放弃草稿**。 + - 如果当前更改看起来没问题,写一个更改描述(可选),然后点击**部署并推送到 GitHub**。部署状态将显示在顶部横幅中。 + +如果部署成功,在 TiDB Cloud 控制台中所做的更改将自动推送到 GitHub。 + +## 导入现有 Data App 的配置 + +要将现有 Data App 的配置导入到新的 Data App,请执行以下步骤: + +1. 将现有 Data App 的配置文件复制到 GitHub 上的新分支或目录。 +2. 在项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面上,[创建一个新的 Data App](/tidb-cloud/data-service-manage-data-app.md#create-a-data-app),不要连接到 GitHub。 +3. 启用**自动同步和部署**,[将新的 Data App 连接到 GitHub](#步骤-1-将-data-app-连接到-github)。为新的 Data App 指定目标仓库、分支和目录时,使用包含复制的配置文件的新路径。 +4. 获取新 Data App 的 ID 和名称。你可以在左侧窗格中点击新 Data App 的名称,在右侧窗格的 **Data App 属性**区域中获取 App ID 和名称。 +5. 在 GitHub 上的新路径中,将 `datapp_config.json` 文件中的 `app_id` 和 `app_name` 更新为你获取的 ID 和名称,然后推送更改。 + + 将文件更改推送到 GitHub 后,TiDB Cloud 将自动使用最新更改部署新的 Data App。 + +6. 要查看从 GitHub 导入的配置,请刷新 TiDB Cloud 控制台的网页。 + + 你还可以在部署历史记录中查看部署状态和提交信息。 + +## 编辑 GitHub 连接 + +如果你想编辑 Data App 的 GitHub 连接(如切换仓库、分支和目录),请执行以下步骤。 + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**连接到 GitHub**区域中,点击 。将显示连接设置对话框。 +4. 在对话框中,修改 Data App 的仓库、分支和目录。 + + > **注意:** + > + > - 目录必须以斜杠 (`/`) 开头。例如,`/mydata`。如果你指定的目录在目标仓库和分支中不存在,它将自动创建。 + > - 仓库、分支和目录的组合标识了配置文件的路径,该路径在 Data App 之间必须是唯一的。如果你指定的路径已被另一个 Data App 使用,你需要指定一个新路径。否则,当前 Data App 在 TiDB Cloud 控制台中配置的端点将覆盖你指定路径中的文件。 + > - 如果你指定的路径包含从另一个 Data App 复制的配置文件,并且你想将这些文件导入到当前 Data App,请参见[导入现有 Data App 的配置](#导入现有-data-app-的配置)。 + +5. 要允许在 TiDB Cloud 控制台或 GitHub 中所做的 Data App 更改相互同步,请启用**配置自动同步和部署**。 + + - 启用后,在你指定的 GitHub 目录中所做的更改可以自动部署到 TiDB Cloud,在 TiDB Cloud 控制台中所做的更改也可以推送到 GitHub。你可以在 Data App 部署历史记录中找到相应的部署和提交信息。 + - 禁用后,在你指定的 GitHub 目录中所做的更改将**不会**部署到 TiDB Cloud,在 TiDB Cloud 控制台中所做的更改也将**不会**推送到 GitHub。 + +6. 点击**确认连接**。 + +## 移除 GitHub 连接 + +如果你不再想将 Data App 连接到 GitHub,请执行以下步骤: + +1. 导航到项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。 +2. 在左侧窗格中,点击目标 Data App 的名称以查看其详细信息。 +3. 在**设置**标签页上,点击**连接到 GitHub**区域中的**断开连接**。 +4. 点击**断开连接**以确认断开连接。 + +断开连接操作后,你的 Data App 配置文件将保留在 GitHub 目录中,但不会再由 `tidb-cloud-data-service` 同步。 diff --git a/tidb-cloud/data-service-oas-with-nextjs.md b/tidb-cloud/data-service-oas-with-nextjs.md new file mode 100644 index 000000000000..ed94f2251427 --- /dev/null +++ b/tidb-cloud/data-service-oas-with-nextjs.md @@ -0,0 +1,209 @@ +--- +title: 将数据应用的 OpenAPI 规范与 Next.js 一起使用 +summary: 了解如何使用数据应用的 OpenAPI 规范生成客户端代码并开发 Next.js 应用程序。 +--- + +# 将数据应用的 OpenAPI 规范与 Next.js 一起使用 + +本文介绍如何使用[数据应用](/tidb-cloud/tidb-cloud-glossary.md#data-app)的 OpenAPI 规范生成客户端代码并开发 Next.js 应用程序。 + +## 开始之前 + +在将 OpenAPI 规范与 Next.js 一起使用之前,请确保你具有以下条件: + +- 一个 TiDB 集群。更多信息,请参见[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)或[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 +- [Node.js](https://nodejs.org/en/download) +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) +- [yarn](https://yarnpkg.com/getting-started/install) + +本文以 TiDB Cloud Serverless 集群为例。 + +## 步骤 1. 准备数据 + +首先,在你的 TiDB 集群中创建一个 `test.repository` 表并向其中插入一些示例数据。以下示例插入一些由 PingCAP 开发的开源项目作为演示数据。 + +要执行 SQL 语句,你可以使用 [TiDB Cloud 控制台](https://tidbcloud.com)中的 [SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)。 + +```sql +-- 选择数据库 +USE test; + +-- 创建表 +CREATE TABLE repository ( + id int NOT NULL PRIMARY KEY AUTO_INCREMENT, + name varchar(64) NOT NULL, + url varchar(256) NOT NULL +); + +-- 向表中插入一些示例数据 +INSERT INTO repository (name, url) +VALUES ('tidb', 'https://github.com/pingcap/tidb'), + ('tikv', 'https://github.com/tikv/tikv'), + ('pd', 'https://github.com/tikv/pd'), + ('tiflash', 'https://github.com/pingcap/tiflash'); +``` + +## 步骤 2. 创建数据应用 + +插入数据后,在 [TiDB Cloud 控制台](https://tidbcloud.com)中导航到[**数据服务**](https://tidbcloud.com/project/data-service)页面。创建一个链接到你的 TiDB 集群的数据应用,为该数据应用创建一个 API 密钥,然后在数据应用中创建一个 `GET /repositories` 端点。此端点的对应 SQL 语句如下,它从 `test.repository` 表中获取所有行: + +```sql +SELECT * FROM test.repository; +``` + +更多信息,请参见[开始使用数据服务](/tidb-cloud/data-service-get-started.md)。 + +## 步骤 3. 生成客户端代码 + +以下以 Next.js 为例,演示如何使用数据应用的 OpenAPI 规范生成客户端代码。 + +1. 创建一个名为 `hello-repos` 的 Next.js 项目。 + + 要使用官方模板创建 Next.js 项目,请使用以下命令,并在提示时保持所有默认选项: + + ```shell + yarn create next-app hello-repos + ``` + + 使用以下命令切换到新创建的项目目录: + + ```shell + cd hello-repos + ``` + +2. 安装依赖。 + + 本文使用 [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) 从 OpenAPI 规范自动生成 API 客户端库。 + + 要将 OpenAPI Generator 安装为开发依赖项,请运行以下命令: + + ```shell + yarn add @openapitools/openapi-generator-cli --dev + ``` + +3. 下载 OpenAPI 规范并将其保存为 `oas/doc.json`。 + + 1. 在 TiDB Cloud [**数据服务**](https://tidbcloud.com/project/data-service)页面,点击左侧窗格中的数据应用名称以查看应用设置。 + 2. 在 **API 规范**区域,点击**下载**,选择 JSON 格式,如果出现提示,点击**授权**。 + 3. 将下载的文件保存为 `hello-repos` 项目目录中的 `oas/doc.json`。 + + 更多信息,请参见[下载 OpenAPI 规范](/tidb-cloud/data-service-manage-data-app.md#下载-openapi-规范)。 + + `oas/doc.json` 文件的结构如下: + + ```json + { + "openapi": "3.0.3", + "components": { + "schemas": { + "getRepositoriesResponse": { + "properties": { + "data": { + "properties": { + "columns": { ... }, + "result": { ... }, + "rows": { + "items": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + } + ... + "paths": { + "/repositories": { + "get": { + "operationId": "getRepositories", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/getRepositoriesResponse" + } + } + }, + "description": "OK" + }, + ... + ``` + +4. 生成客户端代码: + + ```shell + yarn run openapi-generator-cli generate -i oas/doc.json --generator-name typescript-fetch -o gen/api + ``` + + 此命令使用 `oas/doc.json` 规范作为输入生成客户端代码,并将客户端代码输出到 `gen/api` 目录。 + +## 步骤 4. 开发你的 Next.js 应用程序 + +你可以使用生成的客户端代码开发你的 Next.js 应用程序。 + +1. 在 `hello-repos` 项目目录中,创建一个包含以下变量的 `.env.local` 文件,然后将变量值设置为你的数据应用的公钥和私钥。 + + ``` + TIDBCLOUD_DATA_SERVICE_PUBLIC_KEY=YOUR_PUBLIC_KEY + TIDBCLOUD_DATA_SERVICE_PRIVATE_KEY=YOUR_PRIVATE_KEY + ``` + + 要为数据应用创建 API 密钥,请参见[创建 API 密钥](/tidb-cloud/data-service-api-key.md#创建-api-密钥)。 + +2. 在 `hello-repos` 项目目录中,用以下代码替换 `app/page.tsx` 的内容,该代码从 `GET /repositories` 端点获取数据并渲染它: + + ```js + import {DefaultApi, Configuration} from "../gen/api" + + export default async function Home() { + const config = new Configuration({ + username: process.env.TIDBCLOUD_DATA_SERVICE_PUBLIC_KEY, + password: process.env.TIDBCLOUD_DATA_SERVICE_PRIVATE_KEY, + }); + const apiClient = new DefaultApi(config); + const resp = await apiClient.getRepositories(); + return ( +
+ +
+ ) + } + ``` + + > **注意:** + > + > 如果你的数据应用链接的集群位于不同的区域,你将在下载的 OpenAPI 规范文件的 `servers` 部分看到多个项目。在这种情况下,你还需要在 `config` 对象中配置端点路径,如下所示: + > + > ```js + > const config = new Configuration({ + > username: process.env.TIDBCLOUD_DATA_SERVICE_PUBLIC_KEY, + > password: process.env.TIDBCLOUD_DATA_SERVICE_PRIVATE_KEY, + > basePath: "https://${YOUR_REGION}.data.dev.tidbcloud.com/api/v1beta/app/${YOUR_DATA_APP_ID}/endpoint" + > }); + > ``` + > + > 确保将 `basePath` 替换为你的数据应用的实际端点路径。要获取 `${YOUR_REGION}` 和 `{YOUR_DATA_APP_ID}`,请查看端点**属性**面板中的**端点 URL**。 + +## 步骤 5. 预览你的 Next.js 应用程序 + +> **注意:** +> +> 在预览之前,请确保已安装并正确配置所有必需的依赖项。 + +要在本地开发服务器中预览你的应用程序,请运行以下命令: + +```shell +yarn dev +``` + +然后,你可以在浏览器中打开 [http://localhost:3000](http://localhost:3000),看到从 `test.repository` 数据库显示的数据。 diff --git a/tidb-cloud/data-service-overview.md b/tidb-cloud/data-service-overview.md new file mode 100644 index 000000000000..f0ebe0013f68 --- /dev/null +++ b/tidb-cloud/data-service-overview.md @@ -0,0 +1,40 @@ +--- +title: TiDB Cloud 数据服务(Beta)概述 +summary: 了解 TiDB Cloud 中的数据服务及其应用场景。 +--- + +# TiDB Cloud 数据服务(Beta)概述 + +TiDB Cloud [数据服务(beta)](https://tidbcloud.com/project/data-service)是一个完全托管的低代码后端即服务解决方案,它简化了后端应用程序开发,使开发人员能够快速构建高度可扩展、安全的数据驱动应用程序。 + +数据服务使你能够通过使用自定义 API 端点的 HTTPS 请求访问 TiDB Cloud 数据。此功能使用无服务器架构来处理计算资源和弹性扩展,因此你可以专注于端点中的查询逻辑,而无需担心基础设施或维护成本。 + +> **注意:** +> +> 数据服务适用于 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。要在 TiDB Cloud Dedicated 集群中使用数据服务,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +数据服务中的端点是一个可以自定义执行 SQL 语句的 Web API。你可以为 SQL 语句指定参数,例如在 `WHERE` 子句中使用的值。当客户端调用端点并在请求 URL 中为参数提供值时,端点会使用提供的参数执行相应的 SQL 语句,并将结果作为 HTTP 响应的一部分返回。 + +为了更有效地管理端点,你可以使用数据应用。数据服务中的数据应用是一组可用于访问特定应用程序数据的端点的集合。通过创建数据应用,你可以对端点进行分组,并使用 API 密钥配置授权设置来限制对端点的访问。这样,你可以确保只有授权用户才能访问和操作你的数据,使你的应用程序更加安全。 + +> **提示:** +> +> TiDB Cloud 为 TiDB 集群提供了 Chat2Query API。启用后,TiDB Cloud 将在数据服务中自动创建一个名为 **Chat2Query** 的系统数据应用和一个 Chat2Data 端点。你可以调用此端点,通过提供指令让 AI 生成并执行 SQL 语句。 +> +> 更多信息,请参见[开始使用 Chat2Query API](/tidb-cloud/use-chat2query-api.md)。 + +## 应用场景 + +数据服务允许你将 TiDB Cloud 与任何支持 HTTPS 的应用程序或服务无缝集成。以下是一些典型的使用场景: + +- 从移动或 Web 应用程序直接访问 TiDB 集群的数据库。 +- 使用无服务器边缘函数调用端点,避免数据库连接池导致的可扩展性问题。 +- 通过使用数据服务作为数据源将 TiDB Cloud 与数据可视化项目集成。这避免了暴露数据库连接用户名和密码,使你的 API 更安全且更易于使用。 +- 从不支持 MySQL 接口的环境连接到数据库。这为你访问数据提供了更多的灵活性和选择。 + +## 下一步 + +- [开始使用数据服务](/tidb-cloud/data-service-get-started.md) +- [开始使用 Chat2Query API](/tidb-cloud/use-chat2query-api.md) +- [管理数据应用](/tidb-cloud/data-service-manage-data-app.md) +- [管理端点](/tidb-cloud/data-service-manage-endpoint.md) diff --git a/tidb-cloud/data-service-postman-integration.md b/tidb-cloud/data-service-postman-integration.md new file mode 100644 index 000000000000..b545e6d2f910 --- /dev/null +++ b/tidb-cloud/data-service-postman-integration.md @@ -0,0 +1,89 @@ +--- +title: 在 Postman 中运行数据应用 +summary: 了解如何在 Postman 中运行数据应用。 +--- + +# 在 Postman 中运行数据应用 + +[Postman](https://www.postman.com/) 是一个 API 平台,它简化了 API 生命周期并增强了协作,以实现更快更好的 API 开发。 + +在 TiDB Cloud [数据服务](https://tidbcloud.com/project/data-service)中,你可以轻松地将数据应用导入到 Postman,并利用 Postman 的丰富工具来增强你的 API 开发体验。 + +本文档描述如何将数据应用导入到 Postman 以及如何在 Postman 中运行数据应用。 + +## 开始之前 + +在将数据应用导入到 Postman 之前,请确保你具有以下条件: + +- 一个 [Postman](https://www.postman.com/) 账户 +- 一个 [Postman 桌面应用](https://www.postman.com/downloads)(可选)。或者,你可以使用 Postman 网页版而无需下载应用。 +- 一个至少具有一个定义完善的[端点](/tidb-cloud/data-service-manage-endpoint.md)的[数据应用](/tidb-cloud/data-service-manage-data-app.md)。只有满足以下要求的端点才能导入到 Postman: + + - 已选择目标集群。 + - 已配置端点路径和请求方法。 + - 已编写 SQL 语句。 + +- 数据应用的 [API 密钥](/tidb-cloud/data-service-api-key.md#创建-api-密钥)。 + +## 步骤 1. 将数据应用导入到 Postman + +要将数据应用导入到 Postman,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,导航到项目的[**数据服务**](https://tidbcloud.com/project/data-service)页面。 +2. 在左侧窗格中,点击目标数据应用的名称以查看其详细信息。 +3. 在页面右上角,点击**在 Postman 中运行**。此时会显示一个包含导入说明的对话框。 + + > **注意:** + > + > - 如果数据应用缺少定义完善的端点(已配置目标集群、路径、请求方法和 SQL 语句),则该数据应用的**在 Postman 中运行**按钮将保持禁用状态。 + > - Chat2Query 数据应用不提供**在 Postman 中运行**功能。 + +4. 按照对话框中提供的步骤导入数据应用: + + 1. 根据你的偏好,选择**在 Postman 网页版中运行**或**在 Postman 桌面版中运行**以打开你的 Postman 工作区,然后选择目标工作区。 + + - 如果你尚未登录 Postman,请按照屏幕上的说明先登录 Postman。 + - 如果你点击了**在 Postman 桌面版中运行**,请按照屏幕上的说明启动 Postman 桌面应用。 + + 2. 在 Postman 中的目标工作区页面上,点击左侧导航菜单中的**导入**。 + 3. 从 TiDB Cloud 对话框中复制数据应用 URL,然后将 URL 粘贴到 Postman 中进行导入。 + +5. 粘贴 URL 后,Postman 会自动将数据应用作为新的[集合](https://learning.postman.com/docs/collections/collections-overview)导入。集合的名称格式为 `TiDB Data Service - <你的应用名称>`。 + + 在集合中,已部署的端点被分组在 **Deployed** 文件夹下,未部署的端点被分组在 **Draft** 文件夹下。 + +## 步骤 2. 在 Postman 中配置数据应用的 API 密钥 + +在 Postman 中运行导入的数据应用之前,你需要在 Postman 中配置数据应用的 API 密钥,步骤如下: + +1. 在 Postman 的左侧导航菜单中,点击 `TiDB Data Service - <你的应用名称>` 以在右侧打开一个标签页。 +2. 在 `TiDB Data Service - <你的应用名称>` 标签页下,点击 **Variables** 标签。 +3. 在变量表中,在 **Current value** 列中输入数据应用的公钥和私钥。 +4. 在 `TiDB Data Service - <你的应用名称>` 标签页的右上角,点击**保存**。 + +## 步骤 3. 在 Postman 中运行数据应用 + +要在 Postman 中运行数据应用,请执行以下步骤: + +1. 在 Postman 的左侧导航窗格中,展开 **Deployed** 或 **Draft** 文件夹,然后点击你的端点名称以在右侧打开一个标签页。 +2. 在 `<你的端点名称>` 标签页下,你可以按以下方式调用端点: + + - 对于没有参数的端点,你可以直接点击**发送**来调用它。 + - 对于有参数的端点,你需要先填写参数值,然后点击**发送**。 + + - 对于 `GET` 或 `DELETE` 请求,在 **Query Params** 表中填写参数值。 + - 对于 `POST` 或 `PUT` 请求,点击 **Body** 标签,然后将参数值作为 JSON 对象填写。如果在 TiDB Cloud 数据服务中为端点启用了**批量操作**,则将参数值作为 JSON 对象数组填写到 `items` 字段中。 + +3. 在下方窗格中查看响应。 + +4. 如果你想使用不同的参数值再次调用端点,可以相应地编辑参数值,然后再次点击**发送**。 + +要了解更多关于 Postman 的使用方法,请参见 [Postman 文档](https://learning.postman.com/docs)。 + +## 处理数据应用中的新变更 + +将数据应用导入到 Postman 后,TiDB Cloud 数据服务不会自动将数据应用的新变更同步到 Postman。 + +如果你想让任何新变更在 Postman 中反映出来,你必须再次[按照导入流程](#步骤-1-将数据应用导入到-postman)操作。由于集合名称在 Postman 工作区中是唯一的,你可以使用最新的数据应用替换之前导入的应用,或者将最新的数据应用作为新集合导入。 + +此外,重新导入数据应用后,你还需要在 Postman 中再次[为新导入的应用配置 API 密钥](#步骤-2-在-postman-中配置数据应用的-api-密钥)。 diff --git a/tidb-cloud/data-service-response-and-status-code.md b/tidb-cloud/data-service-response-and-status-code.md new file mode 100644 index 000000000000..a4bdcce2a913 --- /dev/null +++ b/tidb-cloud/data-service-response-and-status-code.md @@ -0,0 +1,380 @@ +--- +title: Data Service 的响应和 HTTP 状态码 +summary: 本文档描述了 TiDB Cloud 中 Data Service 的响应和 HTTP 状态码。 +--- + +# Data Service 的响应和 HTTP 状态码 + +当你调用 [Data Service](/tidb-cloud/data-service-overview.md) 中定义的 API 端点时,Data Service 会返回一个 HTTP 响应。理解这个响应的结构和状态码的含义对于解释 Data Service 端点返回的数据至关重要。 + +本文档描述了 TiDB Cloud 中 Data Service 的响应和状态码。 + +## 响应 + +Data Service 返回带有 JSON 主体的 HTTP 响应。 + +> **注意:** +> +> 当你调用包含多个 SQL 语句的端点时,Data Service 会逐个执行这些语句,但在 HTTP 响应中只返回最后一个语句的执行结果。 + +响应主体包含以下字段: + +- `type`:_string_。此端点的类型。值可能是 `"sql_endpoint"` 或 `"chat2data_endpoint"`。不同的端点返回不同类型的响应。 +- `data`:_object_。执行结果,包括三个部分: + + - `columns`:_array_。返回字段的架构信息。 + - `rows`:_array_。以 `key:value` 格式返回的结果。 + + 当为端点启用**批处理操作**且端点的最后一个 SQL 语句是 `INSERT` 或 `UPDATE` 操作时,请注意以下事项: + + - 端点的返回结果还将包括每行的 `"message"` 和 `"success"` 字段,以指示其响应和状态。 + - 如果目标表的主键列配置为 `auto_increment`,端点的返回结果还将包括每行的 `"auto_increment_id"` 字段。对于 `INSERT` 操作,此字段的值是自增 ID,对于其他操作(如 `UPDATE`),此字段的值是 `null`。 + + - `result`:_object_。SQL 语句的执行相关信息,包括成功/失败状态、执行时间、返回的行数和用户配置。 + +以下是一个示例响应: + + +
+ +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [ + { + "auto_increment_id": "270001", + "index": "0", + "message": "Row insert successfully", + "success": "true" + }, + { + "auto_increment_id": "270002", + "index": "1", + "message": "Row insert successfully", + "success": "true" + } + ], + "result": { + "code": 200, + "message": "Query OK, 2 rows affected (8.359 sec)", + "start_ms": 1689593360560, + "end_ms": 1689593368919, + "latency": "8.359s", + "row_count": 2, + "row_affect": 2, + "limit": 500 + } + } +} +``` + +
+ +
+ +```json +{ + "type": "chat2data_endpoint", + "data": { + "columns": [ + { + "col": "id", + "data_type": "BIGINT", + "nullable": false + }, + { + "col": "type", + "data_type": "VARCHAR", + "nullable": false + } + ], + "rows": [ + { + "id": "20008295419", + "type": "CreateEvent" + } + ], + "result": { + "code": 200, + "message": "Query OK!", + "start_ms": 1678965476709, + "end_ms": 1678965476839, + "latency": "130ms", + "row_count": 1, + "row_affect": 0, + "limit": 50 + "sql": "select id,type from sample_data.github_events limit 1;", + "ai_latency": "30ms" + } + } +} +``` + +
+
+ +## 状态码 + +### 200 + +如果 HTTP 状态码为 `200` 且 `data.result.code` 字段也显示 `200`,这表示 SQL 语句执行成功。否则,TiDB Cloud 无法执行你的端点中定义的 SQL 语句。你可以查看 `code` 和 `message` 字段以获取详细信息。 + +以下是一个示例响应: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 1146, + "message": "table not found", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +### 400 + +此状态码表示参数检查失败。 + +以下是一个示例响应: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 400, + "message": "param check failed! {detailed error}", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +### 401 + +此状态码表示由于缺少权限导致认证失败。 + +以下是一个示例响应: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 401, + "message": "auth failed", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +### 404 + +此状态码表示由于无法找到指定的端点导致认证失败。 + +以下是一个示例响应: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 404, + "message": "endpoint not found", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +### 405 + +此状态码表示请求使用了不允许的方法。请注意,Data Service 仅支持 `GET` 和 `POST`。 + +以下是一个示例响应: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 405, + "message": "method not allowed", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +### 408 + +此状态码表示请求超过了端点的超时时间。要修改端点的超时时间,请参见[配置属性](/tidb-cloud/data-service-manage-endpoint.md#配置属性)。 + +以下是一个示例响应: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 408, + "message": "request timeout.", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +### 429 + +此状态码表示请求超过了 API 密钥的速率限制。要获取更多配额,你可以向我们的支持团队[提交请求](https://tidb.support.pingcap.com/)。 + +以下是一个示例响应: + + +
+ +```json +{ + "type": "", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 49900007, + "message": "The request exceeded the limit of 100 times per apikey per minute. For more quota, please contact us: https://tidb.support.pingcap.com/", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +
+ +
+ +```json +{ + "type": "chat2data_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 429, + "message": "The AI request exceeded the limit of 100 times per day. For more quota, please contact us: https://tidb.support.pingcap.com/", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +
+
+ +### 500 + +此状态码表示请求遇到了内部错误。这个错误可能有多种原因。 + +一个可能的原因是由于无法连接到认证服务器导致认证失败。 + +以下是一个示例响应: + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 500, + "message": "internal error! defaultPermissionHelper: rpc error: code = DeadlineExceeded desc = context deadline exceeded", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +这也可能与无法连接 TiDB Cloud 集群有关。你需要参考 `message` 进行故障排除。 + +```json +{ + "type": "sql_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 500, + "message": "internal error! {detailed error}", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` diff --git a/tidb-cloud/data-streaming-concepts.md b/tidb-cloud/data-streaming-concepts.md new file mode 100644 index 000000000000..2e0eb89a2b1d --- /dev/null +++ b/tidb-cloud/data-streaming-concepts.md @@ -0,0 +1,22 @@ +--- +title: 数据流 +summary: 了解 TiDB Cloud 的数据流概念。 +--- + +# 数据流 + +TiDB Cloud 允许你将数据变更从 TiDB 集群流式传输到其他系统,如 Kafka、MySQL 和对象存储。 + +目前,TiDB Cloud 支持将数据流式传输到 Apache Kafka、MySQL、TiDB Cloud 和云存储。 + +## Changefeed + +TiDB Cloud changefeed 是一个持续的数据流,帮助你将数据变更从 TiDB Cloud 复制到其他数据服务。 + +在 TiDB Cloud 控制台的 **Changefeed** 页面,你可以创建 changefeed、查看现有 changefeed 列表,以及操作现有的 changefeed(如扩展、暂停、恢复、编辑和删除 changefeed)。 + +默认情况下,复制仅包括增量数据变更。如果需要复制现有数据,必须在启动 changefeed 之前手动将其导出并加载到目标系统中。 + +在 TiDB Cloud 中,可以通过定义表过滤器(指定要复制的表)和事件过滤器(包含或排除特定类型的事件,如 INSERT 或 DELETE)来定制复制。 + +更多信息,请参见 [Changefeed](/tidb-cloud/changefeed-overview.md)。 diff --git a/tidb-cloud/database-schema-concepts.md b/tidb-cloud/database-schema-concepts.md new file mode 100644 index 000000000000..c323493d29d4 --- /dev/null +++ b/tidb-cloud/database-schema-concepts.md @@ -0,0 +1,176 @@ +--- +title: 数据库模式 +summary: 了解 TiDB Cloud 的数据库模式概念。 +--- + +# 数据库模式 + +数据库模式定义了数据库、表、列、索引和其他对象中数据的结构和组织方式。 + +本文档介绍了数据库模式的关键概念,如数据库、表、列、数据类型、约束和索引。同时还介绍了高级功能,如用于无缝管理中间数据的临时表、用于高效近似最近邻(ANN)搜索的向量索引,以及用于提高读取性能的缓存表。 + +## 数据库 + +TiDB 中的数据库是表和索引等对象的集合。 + +### 系统数据库 + +系统数据库是 TiDB 创建的用于存储系统表的默认数据库。TiDB 提供以下系统数据库: + +- [`INFORMATION_SCHEMA`](/information-schema/information-schema.md) + +- [`mysql`](/mysql-schema/mysql-schema.md) + +- [`performance_schema`](/performance-schema/performance-schema.md) + +- [`sys`](/sys-schema/sys-schema.md) + +### `test` 数据库 + +TiDB 自带一个名为 `test` 的默认数据库。但是,建议您创建自己的数据库,而不是使用 `test` 数据库。 + +## 表 + +表是[数据库](/develop/dev-guide-schema-design-overview.md#database)中相关数据的集合。 + +每个表由行和列组成。行中的每个值都属于特定的列。每列只允许单一数据类型。为了进一步限定列,您可以添加一些[约束](/constraints.md)。为了加速计算,您可以添加[生成列](/generated-columns.md)。 + +### 系统表 + +- `mysql` 模式包含 TiDB 系统表。其设计类似于 MySQL 中的 `mysql` 模式,其中像 `mysql.user` 这样的表可以直接编辑。它还包含一些 MySQL 的扩展表。 + +- Information Schema 提供了一种查看系统元数据的 ANSI 标准方式。除了为 MySQL 兼容性包含的表外,TiDB 还提供了许多自定义的 `INFORMATION_SCHEMA` 表。许多 `INFORMATION_SCHEMA` 表都有相应的 `SHOW` 命令。查询 `INFORMATION_SCHEMA` 的好处是可以在表之间进行连接。 + +- Performance Schema。TiDB 实现了性能模式表以实现 MySQL 兼容性。 + +### 缓存表 + +TiDB 为经常访问但很少更新的小型热点表引入了[缓存表](/cached-tables.md)功能。使用此功能时,整个表的数据会加载到 TiDB 服务器的内存中,TiDB 直接从内存中获取表数据而无需访问 TiKV,从而提高读取性能。 + +### 临时表 + +临时表功能解决了应用程序临时存储中间结果的问题,使您无需频繁创建和删除表。您可以将中间计算数据存储在临时表中。当不再需要中间数据时,TiDB 会自动清理和回收临时表。这避免了用户应用程序过于复杂,减少了表管理开销,并提高了性能。 + +### 分区表 + +在 TiDB 中,[分区](/partitioned-table.md)使您能够将一个大表划分为一个或多个称为分区的可管理部分。每个分区都是独立的,可以单独管理。 + +## 列 + +列从属于表。每个表至少有一列。列通过将每行中的值划分为单一数据类型的小单元,为表提供结构。 + +更多信息,请参见[定义列](/develop/dev-guide-create-table.md#define-columns)。 + +## 生成列 + +TiDB 允许您将 JSON 数据类型中的数据提取为[生成列](/generated-columns.md)。 + +与普通列不同,生成列的值是由列定义中的表达式计算得出的。在插入或更新生成列时,您不能分配值,只能使用 `DEFAULT`。 + +生成列有两种类型:虚拟列和存储列。虚拟生成列不占用存储空间,在读取时计算。存储生成列在写入(插入或更新)时计算,并占用存储空间。与虚拟生成列相比,存储生成列具有更好的读取性能,但占用更多磁盘空间。 + +## 数据类型 + +TiDB 支持除 `SPATIAL` 类型外的所有 MySQL 数据类型。这包括所有[数值类型](/data-type-numeric.md)、[字符串类型](/data-type-string.md)、[日期和时间类型](/data-type-date-and-time.md)以及 [JSON 类型](/data-type-json.md)。 + +## 索引 + +索引是表中选定列的副本。您可以使用[表](/develop/dev-guide-schema-design-overview.md#table)的一个或多个列创建索引。通过索引,TiDB 可以快速定位数据,而无需每次都搜索表中的每一行,这大大提高了查询性能。 + +有两种常见的索引类型: + +- 主键:主键列上的索引。 + +- 二级索引:非主键列上的索引 + +### 唯一索引 + +TiDB 中的唯一索引在一个或多个列上强制实施唯一性,确保表中没有两行在索引列中具有相同的值。这种约束提供了一种维护数据完整性的方法,防止重复值,使唯一索引非常适合那些自然应该是唯一的字段,如电子邮件地址、用户名或产品代码。 + +### 主键索引 + +主键索引是表中一个或多个列上的唯一索引,作为每行的主要标识符。在 TiDB 中,每个表必须有一个主键,可以由用户显式定义,如果未指定主键,则由 TiDB 隐式定义。 + +### 复合索引 + +复合索引是在表的两个或多个列上构建的索引,对于按多个字段过滤或排序数据的查询特别有用。例如,在人员表中创建一个包含 `last_name` 和 `first_name` 的复合索引,允许 TiDB 基于两个名字快速定位记录。 + +### 不可见索引 + +不可见索引是存在于数据库中但对查询优化器隐藏的索引,这意味着它们在查询计划中被忽略。在 TiDB 中,不可见索引对于测试和调试很有用,允许您评估索引对性能的影响而无需完全删除它。 + +从 TiDB v8.0.0 开始,您可以通过修改 [`tidb_opt_use_invisible_indexes`](/system-variables.md#tidb_opt_use_invisible_indexes-new-in-v800) 系统变量使优化器选择不可见索引。 + +### 聚簇索引 + +在聚簇索引中,"聚簇"指的是数据存储的组织方式,而不是一组数据库服务器的协同工作。一些数据库管理系统将聚簇索引称为索引组织表(IOT)。 + +此功能控制包含主键的表中数据的存储方式。它使 TiDB 能够以一种可以提高某些查询性能的方式组织表。 + +更多信息,请参见[聚簇索引](/clustered-indexes.md)。 + +### 二级索引 + +二级索引是 TiDB 集群中的一个逻辑对象。您可以简单地将其视为 TiDB 用来提高查询性能的一种数据排序方式。在 TiDB 中,创建二级索引是一个在线操作,不会阻塞表上的任何数据读写操作。对于每个索引,TiDB 为表中的每一行创建引用,并按选定的列对引用进行排序,而不是直接对数据进行排序。 + +有关二级索引的更多信息,请参见[二级索引](https://docs.pingcap.com/tidb/stable/tidb-best-practices#secondary-index)。 + +在 TiDB 中,您可以[向现有表添加二级索引](/develop/dev-guide-create-secondary-indexes.md#add-a-secondary-index-to-an-existing-table)或[在创建新表时创建二级索引](/develop/dev-guide-create-secondary-indexes.md#create-a-secondary-index-when-creating-a-new-table)。 + +### 向量索引 + +对于以下 TiDB 部署选项,TiDB 支持向量数据类型和向量搜索索引。 + +- TiDB Cloud Serverless + +- TiDB Self-Managed v8.4.0 或更高版本 + +在 TiDB 中,向量索引是一种专门设计的索引,用于在包含向量数据的列上进行高效的近似最近邻(ANN)搜索。向量索引,特别是 HNSW(分层可导航小世界)算法,允许 K-最近邻(KNN)搜索快速识别向量空间中最接近的数据点。这显著提高了查询性能,使结果能够在毫秒级内返回,相比暴力搜索方法有很大提升。 + +向量索引依赖 TiFlash 副本进行数据存储和搜索功能。在创建和使用向量索引之前,请确保集群中有可用的 TiFlash 节点。 + +## 约束 + +TiDB 支持几乎与 MySQL 相同的约束。 + +### NOT NULL 约束 + +`NOT NULL` 约束确保列不能包含 `NULL` 值。 + +当列被定义为 `NOT NULL` 约束时,TiDB 确保任何尝试在该列中插入或更新 `NULL` 值的行都会导致错误。这种行为与 MySQL 的 `NOT NULL` 约束实现一致。 + +### CHECK 约束 + +`CHECK` 约束限制表中列的值必须满足您指定的条件。当向表中添加 `CHECK` 约束时,TiDB 在插入或更新数据时检查是否满足约束。如果不满足约束,则返回错误。 + +### 主键约束 + +与 MySQL 一样,TiDB 中的主键约束包含唯一约束,即创建主键约束等同于具有唯一约束。此外,TiDB 的其他主键约束也与 MySQL 类似。 + +### 唯一键约束 + +唯一约束意味着唯一索引和主键列中的所有非空值都是唯一的。 + +### FOREIGN KEY 约束 + +外键是一个数据库约束,通过将一个表(子表)中的列链接到另一个表(父表)中的列来强制两个表之间的引用完整性。这确保子表中外键列的值与父表中主键或唯一键列的值匹配。例如,`orders` 表中的记录可能有一个链接到 `customers` 表中客户的外键,这确保每个订单都与有效的客户关联。 + +从 v6.6.0 开始,TiDB 支持外键约束作为实验性功能。此功能允许相关数据的跨表引用,并通过强制引用完整性帮助维护数据一致性。但是,需要注意的是,由于可能存在性能问题,特别是在大数据量的情况下,此功能是实验性的,不建议在生产环境中使用。 + +更多信息,请参见[外键约束](/foreign-key.md)。 + +## 视图 + +视图作为一个虚拟表,其模式由创建视图的 `SELECT` 语句定义。使用视图有以下好处: + +- 仅向用户公开安全的字段和数据,以确保底层表中存储的敏感字段和数据的安全性。 + +- 将经常出现的复杂查询定义为视图,使复杂查询更简单和方便。 + +更多信息,请参见[视图](/views.md)。 + +## 序列 + +序列是一个数据库对象,设计用于根据指定的规则集生成一系列数字。此功能在需要唯一标识符的场景中特别有用,例如在创建数据库表的主键时。 + +更多信息,请参见[序列](/sql-statements/sql-statement-create-sequence.md)。 diff --git a/tidb-cloud/dedicated-external-storage.md b/tidb-cloud/dedicated-external-storage.md new file mode 100644 index 000000000000..cabece64dfcd --- /dev/null +++ b/tidb-cloud/dedicated-external-storage.md @@ -0,0 +1,243 @@ +--- +title: 为 TiDB Cloud Dedicated 配置外部存储访问 +summary: 了解如何配置 Amazon Simple Storage Service (Amazon S3)、Google Cloud Storage (GCS) 和 Azure Blob Storage 访问。 +aliases: ['/tidb-cloud/config-s3-and-gcs-access'] +--- + +# 为 TiDB Cloud Dedicated 配置外部存储访问 + +如果你的源数据存储在 Amazon S3 存储桶、Azure Blob Storage 容器或 Google Cloud Storage (GCS) 存储桶中,在将数据导入或迁移到 TiDB Cloud 之前,你需要配置对这些存储桶的跨账户访问。本文档介绍如何为 TiDB Cloud Dedicated 集群进行此配置。 + +如果你需要为 TiDB Cloud Serverless 集群配置这些外部存储,请参阅[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md)。 + +## 配置 Amazon S3 访问 + +要允许 TiDB Cloud Dedicated 集群访问你的 Amazon S3 存储桶中的源数据,可以使用以下任一方法为集群配置存储桶访问: + +- [使用 Role ARN](#使用-role-arn-配置-amazon-s3-访问)(推荐):使用 Role ARN 访问你的 Amazon S3 存储桶。 +- [使用 AWS 访问密钥](#使用-aws-访问密钥配置-amazon-s3-访问):使用 IAM 用户的访问密钥访问你的 Amazon S3 存储桶。 + +### 使用 Role ARN 配置 Amazon S3 访问 + +按照以下步骤为 TiDB Cloud 配置存储桶访问并获取 Role ARN: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,获取目标 TiDB 集群对应的 TiDB Cloud 账户 ID 和外部 ID。 + + 1. 导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + + 3. 选择**从云存储导入数据**,然后点击 **Amazon S3**。 + + 4. 在**从 Amazon S3 导入数据**页面,点击 **Role ARN** 下的链接。此时会显示**添加新的 Role ARN** 对话框。 + + 5. 展开**手动创建 Role ARN**以获取 TiDB Cloud 账户 ID 和 TiDB Cloud 外部 ID。记下这些 ID 以供后续使用。 + +2. 在 AWS 管理控制台中,为你的 Amazon S3 存储桶创建托管策略。 + + 1. 登录 AWS 管理控制台,打开 Amazon S3 控制台:[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。 + 2. 在**存储桶**列表中,选择包含源数据的存储桶名称,然后点击**复制 ARN**以获取你的 S3 存储桶 ARN(例如,`arn:aws:s3:::tidb-cloud-source-data`)。记下存储桶 ARN 以供后续使用。 + + ![复制存储桶 ARN](/media/tidb-cloud/copy-bucket-arn.png) + + 3. 打开 IAM 控制台:[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/),在左侧导航栏中点击**策略**,然后点击**创建策略**。 + + ![创建策略](/media/tidb-cloud/aws-create-policy.png) + + 4. 在**创建策略**页面,点击 **JSON** 选项卡。 + 5. 复制以下访问策略模板并将其粘贴到策略文本字段中。 + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion" + ], + "Resource": "<你的 S3 存储桶 ARN>/<源数据目录>/*" + }, + { + "Sid": "VisualEditor1", + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetBucketLocation" + ], + "Resource": "<你的 S3 存储桶 ARN>" + } + ] + } + ``` + + 在策略文本字段中,将以下配置更新为你自己的值。 + + - `"Resource": "<你的 S3 存储桶 ARN>/<源数据目录>/*"` + + 例如,如果你的源数据存储在 `tidb-cloud-source-data` 存储桶的根目录中,使用 `"Resource": "arn:aws:s3:::tidb-cloud-source-data/*"`。如果你的源数据存储在存储桶的 `mydata` 目录中,使用 `"Resource": "arn:aws:s3:::tidb-cloud-source-data/mydata/*"`。确保在目录末尾添加 `/*`,以便 TiDB Cloud 可以访问此目录中的所有文件。 + + - `"Resource": "<你的 S3 存储桶 ARN>"` + + 例如,`"Resource": "arn:aws:s3:::tidb-cloud-source-data"`。 + + - 如果你启用了带有客户管理密钥加密的 AWS Key Management Service 密钥(SSE-KMS),请确保策略中包含以下配置。`"arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f"` 是存储桶的示例 KMS 密钥。 + + ```json + { + "Sid": "AllowKMSkey", + "Effect": "Allow", + "Action": [ + "kms:Decrypt" + ], + "Resource": "arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f" + } + ``` + + 如果你的存储桶中的对象是从另一个加密存储桶复制的,KMS 密钥值需要包含两个存储桶的密钥。例如,`"Resource": ["arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f","arn:aws:kms:ap-northeast-1:495580073302:key/0d7926a7-6ecc-4bf7-a9c1-a38f0faec0cd"]`。 + + 6. 点击**下一步**。 + 7. 设置策略名称,添加策略标签(可选),然后点击**创建策略**。 + +3. 在 AWS 管理控制台中,为 TiDB Cloud 创建访问角色并获取角色 ARN。 + + 1. 在 IAM 控制台 [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 中,点击左侧导航栏中的**角色**,然后点击**创建角色**。 + + ![创建角色](/media/tidb-cloud/aws-create-role.png) + + 2. 填写以下信息以创建角色: + + - 在**可信实体类型**下,选择 **AWS 账户**。 + - 在 **AWS 账户**下,选择**其他 AWS 账户**,然后将 TiDB Cloud 账户 ID 粘贴到**账户 ID**字段中。 + - 在**选项**下,点击**需要外部 ID**以避免[混淆代理问题](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html),然后将 TiDB Cloud 外部 ID 粘贴到**外部 ID**字段中。如果创建角色时没有"需要外部 ID",任何拥有你的 S3 存储桶 URI 和 IAM 角色 ARN 的人都可能访问你的 Amazon S3 存储桶。如果创建角色时同时使用账户 ID 和外部 ID,只有在同一项目和同一区域中运行的 TiDB 集群才能访问存储桶。 + + 3. 点击**下一步**打开策略列表,选择你刚刚创建的策略,然后点击**下一步**。 + 4. 在**角色详细信息**下,为角色设置名称,然后点击右下角的**创建角色**。创建角色后,将显示角色列表。 + 5. 在角色列表中,点击你刚刚创建的角色名称进入其摘要页面,然后复制角色 ARN。 + + ![复制 AWS 角色 ARN](/media/tidb-cloud/aws-role-arn.png) + +4. 在 TiDB Cloud 控制台中,转到获取 TiDB Cloud 账户 ID 和外部 ID 的**数据导入**页面,然后将角色 ARN 粘贴到 **Role ARN** 字段中。 + +### 使用 AWS 访问密钥配置 Amazon S3 访问 + +建议使用 IAM 用户(而不是 AWS 账户根用户)创建访问密钥。 + +按照以下步骤配置访问密钥: + +1. 创建具有以下策略的 IAM 用户: + + - `AmazonS3ReadOnlyAccess` + - [`CreateOwnAccessKeys`(必需)和 `ManageOwnAccessKeys`(可选)](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#access-keys_required-permissions) + + 建议这些策略仅适用于存储源数据的存储桶。 + + 有关更多信息,请参阅[创建 IAM 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console)。 + +2. 使用你的 AWS 账户 ID 或账户别名以及 IAM 用户名和密码登录 [IAM 控制台](https://console.aws.amazon.com/iam)。 + +3. 创建访问密钥。有关详细信息,请参阅[为 IAM 用户创建访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey)。 + +> **注意:** +> +> TiDB Cloud 不会存储你的访问密钥。建议在导入完成后[删除访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey)。 + +## 配置 GCS 访问 + +要允许 TiDB Cloud 访问你的 GCS 存储桶中的源数据,你需要为存储桶配置 GCS 访问。一旦为项目中的一个 TiDB 集群完成配置,该项目中的所有 TiDB 集群都可以访问该 GCS 存储桶。 + +1. 在 TiDB Cloud 控制台中,获取目标 TiDB 集群的 Google Cloud 服务账户 ID。 + + 1. 导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + + 3. 选择**从云存储导入数据**,然后点击 **Google Cloud Storage**。 + + 4. 点击**显示 Google Cloud 服务账户 ID**,然后复制服务账户 ID 以供后续使用。 + +2. 在 Google Cloud 控制台中,为你的 GCS 存储桶创建 IAM 角色。 + + 1. 登录 [Google Cloud 控制台](https://console.cloud.google.com/)。 + 2. 转到[角色](https://console.cloud.google.com/iam-admin/roles)页面,然后点击**创建角色**。 + + ![创建角色](/media/tidb-cloud/gcp-create-role.png) + + 3. 为角色输入名称、描述、ID 和角色启动阶段。角色名称在创建后不能更改。 + 4. 点击**添加权限**。 + 5. 为角色添加以下只读权限,然后点击**添加**。 + + - storage.buckets.get + - storage.objects.get + - storage.objects.list + + 你可以将权限名称复制到**输入属性名称或值**字段作为筛选查询,然后在筛选结果中选择该名称。要添加这三个权限,你可以在权限名称之间使用 **OR**。 + + ![添加权限](/media/tidb-cloud/gcp-add-permissions.png) + +3. 转到[存储桶](https://console.cloud.google.com/storage/browser)页面,点击你希望 TiDB Cloud 访问的 GCS 存储桶的名称。 + +4. 在**存储桶详情**页面,点击**权限**选项卡,然后点击**授予访问权限**。 + + ![授予存储桶访问权限](/media/tidb-cloud/gcp-bucket-permissions.png) + +5. 填写以下信息以授予对存储桶的访问权限,然后点击**保存**。 + + - 在**新主体**字段中,粘贴目标 TiDB 集群的 Google Cloud 服务账户 ID。 + - 在**选择角色**下拉列表中,输入你刚刚创建的 IAM 角色名称,然后从筛选结果中选择该名称。 + + > **注意:** + > + > 要删除对 TiDB Cloud 的访问权限,你可以简单地删除你已授予的访问权限。 + +6. 在**存储桶详情**页面,点击**对象**选项卡。 + + 如果你想复制文件的 gsutil URI,选择该文件,点击**打开对象溢出菜单**,然后点击**复制 gsutil URI**。 + + ![获取存储桶 URI](/media/tidb-cloud/gcp-bucket-uri01.png) + + 如果你想使用文件夹的 gsutil URI,打开该文件夹,然后点击文件夹名称后面的复制按钮以复制文件夹名称。之后,你需要在名称开头添加 `gs://`,在末尾添加 `/` 以获取文件夹的正确 URI。 + + 例如,如果文件夹名称是 `tidb-cloud-source-data`,你需要使用 `gs://tidb-cloud-source-data/` 作为 URI。 + + ![获取存储桶 URI](/media/tidb-cloud/gcp-bucket-uri02.png) + +7. 在 TiDB Cloud 控制台中,转到获取 Google Cloud 服务账户 ID 的**数据导入**页面,然后将 GCS 存储桶 gsutil URI 粘贴到**存储桶 gsutil URI** 字段中。例如,粘贴 `gs://tidb-cloud-source-data/`。 + +## 配置 Azure Blob Storage 访问 + +要允许 TiDB Cloud Dedicated 访问你的 Azure Blob 容器,你需要为容器配置 Azure Blob 访问。你可以使用账户 SAS 令牌配置容器访问: + +1. 在 [Azure Storage 账户](https://portal.azure.com/#browse/Microsoft.Storage%2FStorageAccounts)页面,点击容器所属的存储账户。 + +2. 在存储账户的导航栏中,点击**安全性 + 网络** > **共享访问签名**。 + + ![sas-position](/media/tidb-cloud/dedicated-external-storage/azure-sas-position.png) + +3. 在**共享访问签名**页面,按照以下步骤创建具有必要权限的[账户 SAS 令牌](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview): + + 1. 在**允许的服务**下,选择**Blob**。 + 2. 在**允许的资源类型**下,选择**容器**和**对象**。 + 3. 在**允许的权限**下,选择所需的权限。例如,将数据导入到 TiDB Cloud Dedicated 需要**读取**和**列出**权限。 + 4. 根据需要调整**开始和到期日期/时间**。出于安全考虑,建议设置与数据导入时间表相符的到期日期。 + 5. 保留其他设置的默认值。 + + ![sas-create](/media/tidb-cloud/dedicated-external-storage/azure-sas-create.png) + +4. 点击**生成 SAS 和连接字符串**以生成 SAS 令牌。 + +5. 复制生成的 **SAS 令牌**。在 TiDB Cloud 中配置数据导入时,你将需要此令牌字符串。 + +> **注意:** +> +> 在开始数据导入之前,请测试连接和权限,以确保 TiDB Cloud Dedicated 可以访问指定的 Azure Blob 容器和文件。 diff --git a/tidb-cloud/delete-tidb-cluster.md b/tidb-cloud/delete-tidb-cluster.md new file mode 100644 index 000000000000..300a04594ef1 --- /dev/null +++ b/tidb-cloud/delete-tidb-cluster.md @@ -0,0 +1,42 @@ +--- +title: 删除 TiDB 集群 +summary: 了解如何删除 TiDB 集群。 +--- + +# 删除 TiDB 集群 + +本文介绍如何在 TiDB Cloud 上删除 TiDB 集群。 + +你可以随时通过执行以下步骤删除集群: + +1. 导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 +2. 在要删除的目标集群所在行,点击 **...**。 + + > **提示:** + > + > 或者,你也可以点击目标集群的名称进入其概览页面,然后点击右上角的 **...**。 + +3. 在下拉菜单中点击**删除**。 +4. 在集群删除窗口中,确认删除: + + - 如果你至少有一个手动或自动备份,你可以看到备份数量和备份的收费政策。点击**继续**并输入 `<组织名称>/<项目名称>/<集群名称>`。 + - 如果你没有任何备份,只需输入 `<组织名称>/<项目名称>/<集群名称>`。 + + 如果你想在将来某个时候恢复集群,请确保你有集群的备份。否则,你将无法再恢复它。有关如何备份 TiDB Cloud Dedicated 集群的更多信息,请参见[备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md)。 + + > **注意:** + > + > [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)不支持删除后恢复数据。如果你想删除 TiDB Cloud Serverless 集群并在将来恢复其数据,请参见[从 TiDB Cloud Serverless 导出数据](/tidb-cloud/serverless-export.md)以导出数据作为备份。 + +5. 点击**我明白,删除它**。 + + 一旦已备份的 TiDB Cloud Dedicated 集群被删除,该集群的现有备份文件将被移至回收站。 + + - 自动备份将在保留期结束后过期并自动删除。如果你不修改,默认保留期为 7 天。 + - 手动备份将保留在回收站中,直到手动删除。 + + > **注意:** + > + > 请注意,备份将继续产生费用,直到被删除。 + + 如果你想从回收站恢复 TiDB Cloud Dedicated 集群,请参见[恢复已删除的集群](/tidb-cloud/backup-and-restore.md#restore-a-deleted-cluster)。 diff --git a/tidb-cloud/dev-guide-bi-looker-studio.md b/tidb-cloud/dev-guide-bi-looker-studio.md new file mode 100644 index 000000000000..e4a0c21c2c4e --- /dev/null +++ b/tidb-cloud/dev-guide-bi-looker-studio.md @@ -0,0 +1,137 @@ +--- +title: 使用 Looker Studio 连接 TiDB Cloud Serverless +summary: 了解如何使用 Looker Studio 连接 TiDB Cloud Serverless。 +--- + +# 使用 Looker Studio 连接 TiDB Cloud Serverless + +TiDB 是一个兼容 MySQL 的数据库,TiDB Cloud Serverless 是一个全托管的 TiDB 服务,而 [Looker Studio](https://lookerstudio.google.com/) 是一个免费的基于 Web 的 BI 工具,可以可视化来自各种来源的数据。 + +在本教程中,您可以学习如何使用 Looker Studio 连接到 TiDB Cloud Serverless 集群。 + +> **注意:** +> +> 本教程中的大多数步骤也适用于 TiDB Cloud Dedicated。但是,对于 TiDB Cloud Dedicated,您需要注意以下事项: +> +> - 按照[从文件导入数据到 TiDB Cloud](/tidb-cloud/tidb-cloud-migration-overview.md#import-data-from-files-to-tidb-cloud) 导入您的数据集。 +> - 按照[连接到 TiDB Cloud Dedicated](/tidb-cloud/connect-via-standard-connection.md) 获取集群的连接信息。连接到 TiDB Cloud Dedicated 时,您需要允许来自 `142.251.74.0/23` 的访问。有关来自 Looker Studio 的连接的更多信息,请参见 [Looker Studio 文档](https://support.google.com/looker-studio/answer/7088031#zippy=%2Cin-this-article)。 + +## 前提条件 + +要完成本教程,您需要: + +- 一个 Google 账号 +- 一个 TiDB Cloud Serverless 集群 + +**如果您还没有 TiDB Cloud Serverless 集群,可以按照以下方式创建:** + +- [创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#step-1-create-a-tidb-cloud-serverless-cluster) + +## 步骤 1. 导入数据集 + +您可以导入 TiDB Cloud Serverless 交互式教程中提供的标准普尔 500 指数数据集。 + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,点击右下角的 **?**。将显示**帮助**对话框。 + +2. 在对话框中,点击**交互式教程**,然后点击 **S&P 500 分析**。 + +3. 选择您的 TiDB Cloud Serverless 集群,然后点击**导入数据集**将标准普尔 500 指数数据集导入到您的集群。 + +4. 导入状态变为**已导入**后,点击**退出教程**关闭此对话框。 + +如果在导入过程中遇到任何问题,您可以按照以下方式取消此导入任务: + +1. 在[**集群**](https://tidbcloud.com/project/clusters)页面,点击您的 TiDB Cloud Serverless 集群的名称进入其概览页面。 +2. 在左侧导航栏中,点击**数据** > **导入**。 +3. 找到名为 **sp500-insight** 的导入任务,点击**操作**列中的 **...**,然后点击**取消**。 + +## 步骤 2. 获取集群的连接信息 + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示连接对话框。 + +3. 在连接对话框中,将**连接方式**设置为 `General`,然后点击**生成密码**创建随机密码。 + + > **提示:** + > + > 如果您之前已经创建了密码,请使用原始密码或点击**重置密码**生成新密码。 + +4. 下载 [CA 证书](https://letsencrypt.org/certs/isrgrootx1.pem)。 + + > **提示:** + > + > TiDB Cloud Serverless 要求客户端和集群之间建立安全的 TLS 连接,因此您需要在 Looker Studio 的连接设置中使用此 CA 证书。 + +## 步骤 3. 使用 Looker Studio 连接到 TiDB 集群 + +1. 登录 [Looker Studio](https://lookerstudio.google.com/),然后在左侧导航栏中点击**创建** > **报告**。 + +2. 在显示的页面上,搜索并选择 **MySQL** 连接器,然后点击**授权**。 + +3. 在**基本**设置面板中,配置连接参数。 + + - **主机名或 IP**:输入 TiDB Cloud Serverless 连接对话框中的 `HOST` 参数。 + - **端口(可选)**:输入 TiDB Cloud Serverless 连接对话框中的 `PORT` 参数。 + - **数据库**:输入要连接的数据库。对于本教程,输入 `sp500insight`。 + - **用户名**:输入 TiDB Cloud Serverless 连接对话框中的 `USERNAME` 参数。 + - **密码**:输入 TiDB Cloud Serverless 连接对话框中的 `PASSWORD` 参数。 + - **启用 SSL**:选中此选项,然后点击 **MySQL SSL 客户端配置文件**右侧的上传图标,上传从[步骤 2](#步骤-2-获取集群的连接信息) 下载的 CA 文件。 + + ![Looker Studio:为 TiDB Cloud Serverless 配置连接设置](/media/tidb-cloud/looker-studio-configure-connection.png) + +4. 点击**验证**。 + +如果验证成功,您可以看到数据库中的表。 + +## 步骤 4. 创建简单图表 + +现在,您可以使用 TiDB 集群作为数据源,并使用数据创建简单的图表。 + +1. 在右侧面板中,点击**自定义查询**。 + + ![Looker Studio:自定义查询](/media/tidb-cloud/looker-studio-custom-query.png) + +2. 将以下代码复制到**输入自定义查询**区域,然后点击右下角的**添加**。 + + ```sql + SELECT sector, + COUNT(*) AS companies, + ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC ) AS companies_ranking, + SUM(market_cap) AS total_market_cap, + ROW_NUMBER() OVER (ORDER BY SUM(market_cap) DESC ) AS total_market_cap_ranking, + SUM(revenue_growth * weight) / SUM(weight) AS avg_revenue_growth, + ROW_NUMBER() OVER (ORDER BY SUM(revenue_growth * weight) / SUM(weight) DESC ) AS avg_revenue_growth_ranking + FROM companies + LEFT JOIN index_compositions ic ON companies.stock_symbol = ic.stock_symbol + GROUP BY sector + ORDER BY 5 ASC; + ``` + + 如果看到**您即将向此报告添加数据**对话框,请点击**添加到报告**。然后,报告中将显示一个表格。 + +3. 在报告的工具栏中,点击**添加图表**,然后在 `折线图` 类别中选择 `组合图表`。 + +4. 在右侧的**图表**设置面板中,配置以下参数: + + - 在**设置**标签页中: + - **维度**:`sector`。 + - **指标**:`companies` 和 `total_market_cap`。 + - 在**样式**标签页中: + - 系列 #1:选择 `折线图` 选项和 `右` 轴。 + - 系列 #2:选择 `柱状图` 选项和 `左` 轴。 + - 其他字段保持默认值。 + +然后,您可以看到类似如下的组合图表: + +![Looker Studio:简单的组合图表](/media/tidb-cloud/looker-studio-simple-chart.png) + +## 下一步 + +- 从 [Looker Studio 帮助](https://support.google.com/looker-studio)了解更多 Looker Studio 的用法。 +- 通过[开发者指南](/develop/dev-guide-overview.md)中的章节了解 TiDB 应用程序开发的最佳实践,例如[插入数据](/develop/dev-guide-insert-data.md)、[更新数据](/develop/dev-guide-update-data.md)、[删除数据](/develop/dev-guide-delete-data.md)、[单表读取](/develop/dev-guide-get-data-from-single-table.md)、[事务](/develop/dev-guide-transaction-overview.md)和 [SQL 性能优化](/develop/dev-guide-optimize-sql-overview.md)。 +- 通过专业的 [TiDB 开发者课程](https://www.pingcap.com/education/)学习,并在通过考试后获得 [TiDB 认证](https://www.pingcap.com/education/certification/)。 + +## 需要帮助? + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 diff --git a/tidb-cloud/dev-guide-wordpress.md b/tidb-cloud/dev-guide-wordpress.md new file mode 100644 index 000000000000..e94e81858e8e --- /dev/null +++ b/tidb-cloud/dev-guide-wordpress.md @@ -0,0 +1,108 @@ +--- +title: 使用 WordPress 连接 TiDB Cloud Serverless +summary: 了解如何使用 TiDB Cloud Serverless 运行 WordPress。本教程提供分步指导,帮助您在几分钟内运行 WordPress + TiDB Cloud Serverless。 +--- + +# 使用 WordPress 连接 TiDB Cloud Serverless + +TiDB 是一个兼容 MySQL 的数据库,TiDB Cloud Serverless 是一个全托管的 TiDB 产品,而 [WordPress](https://github.com/WordPress) 是一个免费的开源内容管理系统(CMS),让用户可以创建和管理网站。WordPress 使用 PHP 编写,并使用 MySQL 数据库。 + +在本教程中,您可以学习如何免费使用 TiDB Cloud Serverless 运行 WordPress。 + +> **注意:** +> +> 除了 TiDB Cloud Serverless 外,本教程也适用于 TiDB Cloud Dedicated 和 TiDB Self-Managed 集群。但是,为了成本效益,强烈建议使用 TiDB Cloud Serverless 运行 WordPress。 + +## 前提条件 + +要完成本教程,您需要: + +- 一个 TiDB Cloud Serverless 集群。如果您还没有,请按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建您自己的 TiDB Cloud 集群。 + +## 使用 TiDB Cloud Serverless 运行 WordPress + +本节演示如何使用 TiDB Cloud Serverless 运行 WordPress。 + +### 步骤 1:克隆 WordPress 示例仓库 + +在终端窗口中运行以下命令来克隆示例代码仓库: + +```shell +git clone https://github.com/Icemap/wordpress-tidb-docker.git +cd wordpress-tidb-docker +``` + +### 步骤 2:安装依赖 + +1. 示例仓库需要 [Docker](https://www.docker.com/) 和 [Docker Compose](https://docs.docker.com/compose/) 来启动 WordPress。如果您已经安装了它们,可以跳过这一步。强烈建议在 Linux 环境(如 Ubuntu)中运行您的 WordPress。运行以下命令安装 Docker 和 Docker Compose: + + ```shell + sudo sh install.sh + ``` + +2. 示例仓库包含 [TiDB 兼容性插件](https://github.com/pingcap/wordpress-tidb-plugin)作为子模块。运行以下命令更新子模块: + + ```shell + git submodule update --init --recursive + ``` + +### 步骤 3:配置连接信息 + +配置 WordPress 数据库与 TiDB Cloud Serverless 的连接。 + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示连接对话框。 + +3. 确保连接对话框中的配置与您的操作环境匹配。 + + - **连接类型**设置为 `Public`。 + - **连接工具**设置为 `WordPress`。 + - **操作系统**设置为 `Debian/Ubuntu/Arch`。 + - **数据库**设置为您想要使用的数据库—例如 `test`。 + +4. 点击**生成密码**创建随机密码。 + + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码或点击**重置密码**生成新密码。 + +5. 运行以下命令复制 `.env.example` 并将其重命名为 `.env`: + + ```shell + cp .env.example .env + ``` + +6. 将相应的连接字符串复制并粘贴到 `.env` 文件中。示例结果如下: + + ```dotenv + TIDB_HOST='{HOST}' # 例如 gateway01.ap-northeast-1.prod.aws.tidbcloud.com + TIDB_PORT='4000' + TIDB_USER='{USERNAME}' # 例如 xxxxxx.root + TIDB_PASSWORD='{PASSWORD}' + TIDB_DB_NAME='test' + ``` + + 请确保将占位符 `{}` 替换为从连接对话框获得的连接参数。默认情况下,您的 TiDB Cloud Serverless 附带一个 `test` 数据库。如果您已经在 TiDB Cloud Serverless 集群中创建了另一个数据库,您可以将 `test` 替换为您的数据库名称。 + +7. 保存 `.env` 文件。 + +### 步骤 4:使用 TiDB Cloud Serverless 启动 WordPress + +1. 执行以下命令将 WordPress 作为 Docker 容器运行: + + ```shell + docker compose up -d + ``` + +2. 如果您在本地机器上启动容器,请访问 [localhost](http://localhost/) 设置您的 WordPress 站点;如果 WordPress 在远程机器上运行,请访问 `http://`。 + +### 步骤 5:确认数据库连接 + +1. 在 TiDB Cloud 控制台上关闭集群的连接对话框,并打开 **SQL 编辑器**页面。 +2. 在左侧的**模式**标签下,点击您连接到 WordPress 的数据库。 +3. 确认您现在可以在该数据库的表列表中看到 WordPress 表(如 `wp_posts` 和 `wp_comments`)。 + +## 需要帮助? + +在 [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) 或 [Slack](https://slack.tidb.io/invite?team=tidb-community&channel=everyone&ref=pingcap-docs) 上询问社区,或[提交支持工单](https://tidb.support.pingcap.com/)。 diff --git a/tidb-cloud/explore-data-with-chat2query.md b/tidb-cloud/explore-data-with-chat2query.md new file mode 100644 index 000000000000..e53013d56004 --- /dev/null +++ b/tidb-cloud/explore-data-with-chat2query.md @@ -0,0 +1,190 @@ +--- +title: 使用 AI 辅助 SQL 编辑器探索数据 +summary: 了解如何在 TiDB Cloud 控制台中使用 AI 辅助 SQL 编辑器,以最大化数据价值。 +--- + +# 使用 AI 辅助 SQL 编辑器探索数据 + +你可以使用 [TiDB Cloud 控制台](https://tidbcloud.com/) 中内置的 AI 辅助 SQL 编辑器来最大化数据价值。 + +在 SQL 编辑器中,你可以手动编写 SQL 查询,也可以在 macOS 上按 + I(或在 Windows 或 Linux 上按 Control + I)来指示 [Chat2Query (beta)](/tidb-cloud/tidb-cloud-glossary.md#chat2query) 自动生成 SQL 查询。这使你无需本地 SQL 客户端即可对数据库运行 SQL 查询。你可以直观地以表格或图表形式查看查询结果,并轻松查看查询日志。 + +## 使用场景 + +SQL 编辑器的推荐使用场景如下: + +- 利用 Chat2Query 的 AI 功能即时生成、调试或重写复杂的 SQL 查询。 +- 快速测试 TiDB 的 MySQL 兼容性。 +- 使用自己的数据集轻松探索 TiDB 中的 SQL 功能。 + +## 限制 + +- AI 生成的 SQL 查询可能不是 100% 准确,你可能需要对其进行优化。 +- SQL 编辑器仅支持 v6.5.0 或更高版本且托管在 AWS 上的 TiDB 集群。 +- SQL 编辑器默认适用于 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。要在 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群上使用 SQL 编辑器和 Chat2Query,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +## 访问 SQL 编辑器 + +1. 转到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的下拉框在组织、项目和集群之间切换。 + +2. 点击集群名称,然后在左侧导航栏中点击 **SQL 编辑器**。 + + > **注意:** + > + > 在以下情况下,**SQL 编辑器**入口显示为灰色且不可点击: + > + > - 你的 TiDB Cloud Dedicated 集群版本早于 v6.5.0。要使用 SQL 编辑器,你需要联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)升级集群。 + > - 你的 TiDB Cloud Dedicated 集群刚刚创建,SQL 编辑器的运行环境仍在准备中。在这种情况下,等待几分钟后 Chat2Query 就会可用。 + > - 你的 TiDB Cloud Dedicated 集群已[暂停](/tidb-cloud/pause-or-resume-tidb-cluster.md)。 + +## 启用或禁用 AI 生成 SQL 查询 + +PingCAP 将用户数据的隐私和安全视为首要任务。SQL 编辑器中的 Chat2Query AI 功能只需要访问数据库架构来生成 SQL 查询,而不需要访问你的数据本身。更多信息,请参见 [Chat2Query 隐私常见问题](https://www.pingcap.com/privacy-policy/privacy-chat2query)。 + +当你首次访问 Chat2Query 时,会出现一个对话框,询问是否允许 PingCAP 和 Amazon Bedrock 使用你的代码片段来研究和改进服务。 + +- 要启用 AI 生成 SQL 查询,选中复选框并点击**保存并开始使用**。 +- 要禁用 AI 生成 SQL 查询,直接关闭此对话框。 + +首次访问后,你仍然可以按照以下方式更改 AI 设置: + +- 要启用 AI,点击 Chat2Query 右上角的**启用 AI 功能进行数据探索**。 +- 要禁用 AI,点击 [TiDB Cloud 控制台](https://tidbcloud.com/) 左下角的 ,点击**账户设置**,点击 **AI 和隐私**标签,然后禁用 **AI 驱动的数据探索**选项。 + +## 编写和运行 SQL 查询 + +在 SQL 编辑器中,你可以使用自己的数据集编写和运行 SQL 查询。 + +1. 编写 SQL 查询。 + + +
+ + 对于 macOS: + + - 如果启用了 AI,只需按 **⌘ + I** 后输入你的指令并按 **Enter** 键,即可让 AI 自动生成 SQL 查询。 + + 对于 Chat2Query 生成的 SQL 查询,点击**接受**以接受查询并继续编辑。如果查询不符合你的要求,点击**放弃**以拒绝它。或者,点击**重新生成**以从 Chat2Query 请求新的查询。 + + - 如果禁用了 AI,手动编写 SQL 查询。 + +
+ +
+ + 对于 Windows 或 Linux: + + - 如果启用了 AI,只需按 **Ctrl + I** 后输入你的指令并按 **Enter** 键,即可让 AI 自动生成 SQL 查询。 + + 对于 Chat2Query 生成的 SQL 查询,点击**接受**以接受查询并继续编辑。如果查询不符合你的要求,点击**放弃**以拒绝它。或者,点击**重新生成**以从 Chat2Query 请求新的查询。 + + - 如果禁用了 AI,手动编写 SQL 查询。 + +
+
+ +2. 运行 SQL 查询。 + + +
+ + 对于 macOS: + + - 如果编辑器中只有一个查询,要运行它,按 **⌘ + Enter** 或点击 **运行**。 + + - 如果编辑器中有多个查询,要按顺序运行其中一个或多个查询,用光标选择目标查询的行,然后按 **⌘ + Enter** 或点击**运行**。 + + - 要按顺序运行编辑器中的所有查询,按 **⇧ + ⌘ + Enter**,或用光标选择所有查询的行并点击**运行**。 + +
+ +
+ + 对于 Windows 或 Linux: + + - 如果编辑器中只有一个查询,要运行它,按 **Ctrl + Enter** 或点击 **运行**。 + + - 如果编辑器中有多个查询,要按顺序运行其中一个或多个查询,用光标选择目标查询的行,然后按 **Ctrl + Enter** 或点击**运行**。 + + - 要按顺序运行编辑器中的所有查询,按 **Shift + Ctrl + Enter**,或用光标选择所有查询的行并点击**运行**。 + +
+
+ +运行查询后,你可以立即在页面底部看到查询日志和结果。 + +> **注意:** +> +> 返回结果的大小限制为 8 MiB。 + +## 使用 Chat2Query 重写 SQL 查询 + +在 SQL 编辑器中,你可以使用 Chat2Query 重写现有的 SQL 查询,以优化性能、修复错误或满足其他特定要求。 + +1. 用光标选择要重写的 SQL 查询行。 + +2. 使用操作系统对应的键盘快捷键调用 Chat2Query 进行重写: + + - macOS 上按 + I + - Windows 或 Linux 上按 Control + I + + 提供指令后按 **Enter** 键让 AI 处理重写。 + +3. 调用 Chat2Query 后,你可以看到建议的重写内容和以下选项: + + - **接受**:点击此项以接受建议的重写并继续编辑。 + - **放弃**:如果建议的重写不符合你的期望,点击此项。 + - **重新生成**:点击此项以根据你的反馈或额外指令从 Chat2Query 请求另一个重写。 + +> **注意:** +> +> Chat2Query 使用 AI 算法来提供优化和修正建议。建议在最终确定查询之前仔细审查这些建议。 + +## 管理 SQL 文件 + +在 SQL 编辑器中,你可以将 SQL 查询保存在不同的 SQL 文件中,并按以下方式管理 SQL 文件: + +- 要添加 SQL 文件,点击 **SQL 文件**标签上的 **+**。 +- 要重命名 SQL 文件,将光标移到文件名上,点击文件名旁边的 **...**,然后选择**重命名**。 +- 要删除 SQL 文件,将光标移到文件名上,点击文件名旁边的 **...**,然后选择**删除**。注意,当 **SQL 文件**标签上只有一个 SQL 文件时,你无法删除它。 + +## 通过 API 访问 Chat2Query + +除了通过 UI 访问 Chat2Query 外,你还可以通过 API 访问 Chat2Query。要实现这一点,你需要先创建一个 Chat2Query Data App。 + +在 Chat2Query 中,你可以按以下方式访问或创建 Chat2Query Data App: + +1. 点击右上角的 **...**,然后点击**通过 API 访问 Chat2Query**。 +2. 在显示的对话框中,执行以下操作之一: + + - 要创建新的 Chat2Query Data App,点击**新建 Chat2Query Data App**。 + - 要访问现有的 Chat2Query Data App,点击目标 Data App 的名称。 + +更多信息,请参见[开始使用 Chat2Query API](/tidb-cloud/use-chat2query-api.md)。 + +## 从 SQL 文件生成端点 + +对于 TiDB 集群,TiDB Cloud 提供了 [Data Service (beta)](/tidb-cloud/data-service-overview.md) 功能,使你能够使用自定义 API 端点通过 HTTPS 请求访问 TiDB Cloud 数据。在 SQL 编辑器中,你可以通过以下步骤从 SQL 文件生成 Data Service (beta) 的端点: + +1. 将光标移到文件名上,点击文件名旁边的 **...**,然后选择**生成端点**。 +2. 在**生成端点**对话框中,选择要为其生成端点的 Data App 并输入端点名称。 +3. 点击**生成**。端点生成后,将显示其详细信息页面。 + +更多信息,请参见[管理端点](/tidb-cloud/data-service-manage-endpoint.md)。 + +## 管理 SQL 编辑器设置 + +在 SQL 编辑器中,你可以更改以下设置: + +- 查询结果中的最大行数 +- 是否在**架构**标签上显示系统数据库架构 + +要更改设置,请执行以下步骤: + +1. 在 **SQL 编辑器**右上角,点击 **...** 并选择**设置**。 +2. 根据需要更改设置。 +3. 点击**保存**。 diff --git a/tidb-cloud/get-started-with-cli.md b/tidb-cloud/get-started-with-cli.md new file mode 100644 index 000000000000..f30c09ddb83d --- /dev/null +++ b/tidb-cloud/get-started-with-cli.md @@ -0,0 +1,174 @@ +--- +title: TiDB Cloud CLI 快速入门 +summary: 了解如何通过 TiDB Cloud CLI 管理 TiDB Cloud 资源。 +--- + +# TiDB Cloud CLI 快速入门 + +TiDB Cloud 提供命令行界面(CLI)[`ticloud`](https://github.com/tidbcloud/tidbcloud-cli),让你可以通过几行命令在终端中与 TiDB Cloud 交互。例如,你可以使用 `ticloud` 轻松执行以下操作: + +- 创建、删除和列出你的集群。 +- 向集群导入数据。 +- 从集群导出数据。 + +> **注意:** +> +> TiDB Cloud CLI 目前处于 beta 阶段。 + +## 开始之前 + +- 拥有 TiDB Cloud 账户。如果没有,请[注册免费试用](https://tidbcloud.com/free-trial)。 + +## 安装 + + +
+ +对于 macOS 或 Linux,你可以使用以下任一方法安装 `ticloud`: + +- 通过脚本安装(推荐) + + ```shell + curl https://raw.githubusercontent.com/tidbcloud/tidbcloud-cli/main/install.sh | sh + ``` + +- 通过 [TiUP](https://tiup.io/) 安装 + + ```shell + tiup install cloud + ``` + +- 手动安装 + + 从[发布页面](https://github.com/tidbcloud/tidbcloud-cli/releases/latest)下载预编译的二进制文件,并将其复制到所需的安装位置。 + +- 在 GitHub Actions 中安装 + + 要在 GitHub Action 中设置 `ticloud`,请使用 [`setup-tidbcloud-cli`](https://github.com/tidbcloud/setup-tidbcloud-cli)。 + +如果你没有 MySQL 命令行客户端,请安装它。你可以通过包管理器安装: + +- 基于 Debian 的发行版: + + ```shell + sudo apt-get install mysql-client + ``` + +- 基于 RPM 的发行版: + + ```shell + sudo yum install mysql + ``` + +- macOS: + + ```shell + brew install mysql-client + ``` + +
+ +
+ +对于 Windows,你可以使用以下任一方法安装 `ticloud`: + +- 手动安装 + + 从[发布页面](https://github.com/tidbcloud/tidbcloud-cli/releases/latest)下载预编译的二进制文件,并将其复制到所需的安装位置。 + +- 在 GitHub Actions 中安装 + + 要在 GitHub Actions 中设置 `ticloud`,请使用 [`setup-tidbcloud-cli`](https://github.com/tidbcloud/setup-tidbcloud-cli)。 + +如果你没有 MySQL 命令行客户端,请安装它。你可以参考 [MySQL Installer for Windows](https://dev.mysql.com/doc/refman/8.0/en/mysql-installer.html) 中的安装说明。要在 Windows 上启动 `ticloud connect`,你需要将包含 `mysql.exe` 的目录添加到 PATH 环境变量中。 + +
+
+ +## 快速入门 + +[TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 是开始使用 TiDB Cloud 的最佳方式。在本节中,你将学习如何使用 TiDB Cloud CLI 创建 TiDB Cloud Serverless 集群。 + +### 创建用户配置文件或登录 TiDB Cloud + +在使用 TiDB Cloud CLI 创建集群之前,你需要创建用户配置文件或登录 TiDB Cloud。 + +- 使用你的 [TiDB Cloud API 密钥](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication/API-Key-Management)创建用户配置文件: + + ```shell + ticloud config create + ``` + + > **警告:** + > + > 配置文件名称**不能**包含 `.`。 + +- 通过身份验证登录 TiDB Cloud: + + ```shell + ticloud auth login + ``` + + 登录成功后,OAuth 令牌将分配给当前配置文件。如果不存在配置文件,令牌将分配给名为 `default` 的配置文件。 + +> **注意:** +> +> 在上述两种方法中,TiDB Cloud API 密钥优先于 OAuth 令牌。如果两者都可用,将使用 API 密钥。 + +### 创建 TiDB Cloud Serverless 集群 + +要创建 TiDB Cloud Serverless 集群,请输入以下命令,然后按照 CLI 提示提供所需信息: + +```shell +ticloud serverless create +``` + +## 使用 TiDB Cloud CLI + +查看所有可用命令: + +```shell +ticloud --help +``` + +验证你是否使用最新版本: + +```shell +ticloud version +``` + +如果不是,请更新到最新版本: + +```shell +ticloud update +``` + +### 通过 TiUP 使用 TiDB Cloud CLI + +TiDB Cloud CLI 也可以通过 [TiUP](https://tiup.io/) 使用,组件名称为 `cloud`。 + +查看所有可用命令: + +```shell +tiup cloud --help +``` + +使用 `tiup cloud ` 运行命令。例如: + +```shell +tiup cloud serverless create +``` + +通过 TiUP 更新到最新版本: + +```shell +tiup update cloud +``` + +## 下一步 + +查看 [CLI 参考](/tidb-cloud/cli-reference.md)以探索 TiDB Cloud CLI 的更多功能。 + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/high-availability-with-multi-az.md b/tidb-cloud/high-availability-with-multi-az.md new file mode 100644 index 000000000000..f26ed33452c5 --- /dev/null +++ b/tidb-cloud/high-availability-with-multi-az.md @@ -0,0 +1,22 @@ +--- +title: TiDB Cloud Dedicated 中的高可用性 +summary: TiDB Cloud Dedicated 通过多可用区部署支持高可用性。 +--- + +# TiDB Cloud Dedicated 中的高可用性 + +TiDB 使用 Raft 共识算法确保数据在 Raft 组中的存储具有高可用性和安全复制。数据在存储节点之间冗余复制,并放置在不同的可用区中,以防止机器或数据中心故障。通过自动故障转移,TiDB 确保您的服务始终在线。 + +TiDB Cloud Dedicated 集群由三个主要组件组成:TiDB 节点、TiKV 节点和 TiFlash 节点。TiDB Cloud Dedicated 中各组件的高可用性实现如下: + +* **TiDB 节点** + + TiDB 仅用于计算,不存储数据。它支持水平扩展。TiDB Cloud Dedicated 将 TiDB 节点均匀部署到区域内的不同可用区。当用户执行 SQL 请求时,请求首先通过部署在多个可用区的负载均衡器,然后负载均衡器将请求分发到不同的 TiDB 节点执行。建议每个 TiDB Cloud Dedicated 集群至少有两个 TiDB 节点以实现高可用性。 + +* **TiKV 节点** + + [TiKV](https://docs.pingcap.com/tidb/stable/tikv-overview) 是 TiDB Cloud Dedicated 集群的行存储层,支持水平扩展。TiDB Cloud Dedicated 集群的最小 TiKV 节点数为 3。TiDB Cloud Dedicated 将 TiKV 节点均匀部署到您选择的区域中的所有可用区(至少 3 个)以实现持久性和高可用性。在典型的 3 副本设置中,您的数据在所有可用区的 TiKV 节点之间均匀分布,并持久化到每个 TiKV 节点的磁盘中。 + +* **TiFlash 节点** + + [TiFlash](https://docs.pingcap.com/tidb/stable/tiflash-overview) 作为 TiKV 的列式存储扩展,是使 TiDB 成为混合事务/分析处理(HTAP)数据库的关键组件。在 TiFlash 中,列式副本根据 Raft Learner 共识算法异步复制。TiDB Cloud Dedicated 将 TiFlash 节点均匀部署到区域内的不同可用区。建议在每个 TiDB Cloud Dedicated 集群中至少配置两个 TiFlash 节点,并在生产环境中为数据创建至少两个副本以实现高可用性。 diff --git a/tidb-cloud/import-csv-files-serverless.md b/tidb-cloud/import-csv-files-serverless.md new file mode 100644 index 000000000000..20867ed405d9 --- /dev/null +++ b/tidb-cloud/import-csv-files-serverless.md @@ -0,0 +1,313 @@ +--- +title: 从 Amazon S3、GCS、Azure Blob Storage 或阿里云 OSS 导入 CSV 文件到 TiDB Cloud Serverless +summary: 了解如何从 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务(OSS)导入 CSV 文件到 TiDB Cloud Serverless。 +--- + +# 从 Amazon S3、GCS、Azure Blob Storage 或阿里云 OSS 导入 CSV 文件到 TiDB Cloud Serverless + +本文档描述如何从 Amazon Simple Storage Service (Amazon S3)、Google Cloud Storage (GCS)、Azure Blob Storage 或阿里云对象存储服务(OSS)导入 CSV 文件到 TiDB Cloud Serverless。 + +## 限制 + +- 为确保数据一致性,TiDB Cloud Serverless 仅允许将 CSV 文件导入到空表中。如果要将数据导入到已包含数据的现有表中,你可以按照本文档将数据导入到临时空表中,然后使用 `INSERT SELECT` 语句将数据复制到目标现有表中。 + +## 步骤 1. 准备 CSV 文件 + +1. 如果 CSV 文件大于 256 MB,建议将其拆分为较小的文件,每个文件大小约为 256 MB。 + + TiDB Cloud Serverless 支持导入非常大的 CSV 文件,但在处理大小约为 256 MB 的多个输入文件时性能最佳。这是因为 TiDB Cloud Serverless 可以并行处理多个文件,从而大大提高导入速度。 + +2. 按以下方式命名 CSV 文件: + + - 如果 CSV 文件包含整个表的所有数据,请按 `${db_name}.${table_name}.csv` 格式命名文件,导入数据时将映射到 `${db_name}.${table_name}` 表。 + - 如果一个表的数据分散在多个 CSV 文件中,请在这些 CSV 文件后附加数字后缀。例如,`${db_name}.${table_name}.000001.csv` 和 `${db_name}.${table_name}.000002.csv`。数字后缀可以不连续但必须按升序排列。你还需要在数字前添加额外的零以确保所有后缀长度相同。 + - TiDB Cloud Serverless 支持导入以下格式的压缩文件:`.gzip`、`.gz`、`.zstd`、`.zst` 和 `.snappy`。如果要导入压缩的 CSV 文件,请按 `${db_name}.${table_name}.${suffix}.csv.${compress}` 格式命名文件,其中 `${suffix}` 是可选的,可以是任何整数,如 '000001'。例如,如果要将 `trips.000001.csv.gz` 文件导入到 `bikeshare.trips` 表,你需要将文件重命名为 `bikeshare.trips.000001.csv.gz`。 + + > **注意:** + > + > - 为获得更好的性能,建议将每个压缩文件的大小限制在 100 MiB 以内。 + > - Snappy 压缩文件必须采用[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他变体的 Snappy 压缩。 + > - 对于未压缩的文件,如果在某些情况下无法按照上述规则更新 CSV 文件名(例如,CSV 文件链接也被其他程序使用),你可以保持文件名不变,并在[步骤 4](#步骤-4-将-csv-文件导入到-tidb-cloud-serverless) 中使用**映射设置**将源数据导入到单个目标表。 + +## 步骤 2. 创建目标表架构 + +由于 CSV 文件不包含架构信息,在将数据从 CSV 文件导入到 TiDB Cloud Serverless 之前,你需要使用以下任一方法创建表架构: + +- 方法 1:在 TiDB Cloud Serverless 中,为源数据创建目标数据库和表。 + +- 方法 2:在存放 CSV 文件的 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务目录中,按以下方式为源数据创建目标表架构文件: + + 1. 为源数据创建数据库架构文件。 + + 如果你的 CSV 文件遵循[步骤 1](#步骤-1-准备-csv-文件) 中的命名规则,则数据库架构文件对数据导入是可选的。否则,数据库架构文件是必需的。 + + 每个数据库架构文件必须采用 `${db_name}-schema-create.sql` 格式,并包含一个 `CREATE DATABASE` DDL 语句。通过此文件,TiDB Cloud Serverless 将在导入数据时创建 `${db_name}` 数据库来存储数据。 + + 例如,如果你创建一个包含以下语句的 `mydb-scehma-create.sql` 文件,TiDB Cloud Serverless 将在导入数据时创建 `mydb` 数据库。 + + ```sql + CREATE DATABASE mydb; + ``` + + 2. 为源数据创建表架构文件。 + + 如果你没有在存放 CSV 文件的 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务目录中包含表架构文件,TiDB Cloud Serverless 在导入数据时将不会为你创建相应的表。 + + 每个表架构文件必须采用 `${db_name}.${table_name}-schema.sql` 格式,并包含一个 `CREATE TABLE` DDL 语句。通过此文件,TiDB Cloud Serverless 将在导入数据时在 `${db_name}` 数据库中创建 `${db_table}` 表。 + + 例如,如果你创建一个包含以下语句的 `mydb.mytable-schema.sql` 文件,TiDB Cloud Serverless 将在导入数据时在 `mydb` 数据库中创建 `mytable` 表。 + + ```sql + CREATE TABLE mytable ( + ID INT, + REGION VARCHAR(20), + COUNT INT ); + ``` + + > **注意:** + > + > 每个 `${db_name}.${table_name}-schema.sql` 文件应该只包含一个 DDL 语句。如果文件包含多个 DDL 语句,只有第一个语句会生效。 + +## 步骤 3. 配置跨账户访问 + +要允许 TiDB Cloud Serverless 访问 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务存储桶中的 CSV 文件,请执行以下操作之一: + +- 如果你的 CSV 文件位于 Amazon S3 中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#配置-amazon-s3-访问)。 + + 你可以使用 AWS 访问密钥或 Role ARN 来访问存储桶。完成后,请记下访问密钥(包括访问密钥 ID 和密钥)或 Role ARN 值,因为你将在[步骤 4](#步骤-4-将-csv-文件导入到-tidb-cloud-serverless) 中需要它。 + +- 如果你的 CSV 文件位于 GCS 中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#配置-gcs-访问)。 + +- 如果你的 CSV 文件位于 Azure Blob Storage 中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#配置-azure-blob-storage-访问)。 + +- 如果你的 CSV 文件位于阿里云对象存储服务(OSS)中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#配置阿里云对象存储服务-oss-访问)。 + +## 步骤 4. 将 CSV 文件导入到 TiDB Cloud Serverless + +要将 CSV 文件导入到 TiDB Cloud Serverless,请执行以下步骤: + + +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Amazon S3**。 + +3. 在**从 Amazon S3 导入数据**页面,为源 CSV 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **CSV**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `s3://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`s3://sampledata/ingest/TableName.01.csv`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `s3://[bucket_name]/[data_source_folder]/`。例如,`s3://sampledata/ingest/`。 + - **存储桶访问**:你可以使用 AWS Role ARN 或 AWS 访问密钥来访问存储桶。更多信息,请参见[配置 Amazon S3 访问](/tidb-cloud/serverless-external-storage.md#配置-amazon-s3-访问)。 + - **AWS Role ARN**:输入 AWS Role ARN 值。 + - **AWS 访问密钥**:输入 AWS 访问密钥 ID 和 AWS 密钥。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 CSV 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保其格式为 `s3://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`s3://sampledata/ingest/TableName.01.csv`。 + + 你还可以使用通配符来匹配源文件。例如: + + - `s3://[bucket_name]/[data_source_folder]/my-data?.csv`:该文件夹中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将导入到同一个目标表中。 + + - `s3://[bucket_name]/[data_source_folder]/my-data*.csv`:该文件夹中以 `my-data` 开头的所有 CSV 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Google Cloud Storage**。 + +3. 在**从 Google Cloud Storage 导入数据**页面,为源 CSV 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **CSV**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `[gcs|gs]://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`[gcs|gs]://sampledata/ingest/TableName.01.csv`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `[gcs|gs]://[bucket_name]/[data_source_folder]/`。例如,`[gcs|gs]://sampledata/ingest/`。 + - **存储桶访问**:你可以使用服务账号密钥来访问存储桶。更多信息,请参见[配置 GCS 访问](/tidb-cloud/serverless-external-storage.md#配置-gcs-访问)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 CSV 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保其格式为 `[gcs|gs]://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`[gcs|gs]://sampledata/ingest/TableName.01.csv`。 + + 你还可以使用通配符来匹配源文件。例如: + + - `[gcs|gs]://[bucket_name]/[data_source_folder]/my-data?.csv`:该文件夹中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将导入到同一个目标表中。 + + - `[gcs|gs]://[bucket_name]/[data_source_folder]/my-data*.csv`:该文件夹中以 `my-data` 开头的所有 CSV 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Azure Blob Storage**。 + +3. 在**从 Azure Blob Storage 导入数据**页面,为源 CSV 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **CSV**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `[azure|https]://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`[azure|https]://sampledata/ingest/TableName.01.csv`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `[azure|https]://[bucket_name]/[data_source_folder]/`。例如,`[azure|https]://sampledata/ingest/`。 + - **存储桶访问**:你可以使用共享访问签名(SAS)令牌来访问存储桶。更多信息,请参见[配置 Azure Blob Storage 访问](/tidb-cloud/serverless-external-storage.md#配置-azure-blob-storage-访问)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 CSV 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保其格式为 `[azure|https]://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`[azure|https]://sampledata/ingest/TableName.01.csv`。 + + 你还可以使用通配符来匹配源文件。例如: + + - `[azure|https]://[bucket_name]/[data_source_folder]/my-data?.csv`:该文件夹中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将导入到同一个目标表中。 + + - `[azure|https]://[bucket_name]/[data_source_folder]/my-data*.csv`:该文件夹中以 `my-data` 开头的所有 CSV 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击**阿里云 OSS**。 + +3. 在**从阿里云 OSS 导入数据**页面,为源 CSV 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **CSV**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `oss://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`oss://sampledata/ingest/TableName.01.csv`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `oss://[bucket_name]/[data_source_folder]/`。例如,`oss://sampledata/ingest/`。 + - **存储桶访问**:你可以使用 AccessKey 对来访问存储桶。更多信息,请参见[配置阿里云对象存储服务(OSS)访问](/tidb-cloud/serverless-external-storage.md#配置阿里云对象存储服务-oss-访问)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 CSV 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保其格式为 `oss://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`oss://sampledata/ingest/TableName.01.csv`。 + + 你还可以使用通配符来匹配源文件。例如: + + - `oss://[bucket_name]/[data_source_folder]/my-data?.csv`:该文件夹中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将导入到同一个目标表中。 + + - `oss://[bucket_name]/[data_source_folder]/my-data*.csv`:该文件夹中以 `my-data` 开头的所有 CSV 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +运行导入任务时,如果检测到任何不支持或无效的转换,TiDB Cloud Serverless 会自动终止导入作业并报告导入错误。 + +如果遇到导入错误,请执行以下操作: + +1. 删除部分导入的表。 +2. 检查表架构文件。如果有任何错误,请更正表架构文件。 +3. 检查 CSV 文件中的数据类型。 +4. 重新尝试导入任务。 + +## 故障排除 + +### 解决数据导入过程中的警告 + +点击**开始导入**后,如果看到类似 `can't find the corresponding source files` 的警告消息,请通过提供正确的源文件、根据[数据导入命名约定](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件或使用**高级设置**进行更改来解决此问题。 + +解决这些问题后,你需要重新导入数据。 + +### 导入的表中行数为零 + +导入进度显示**已完成**后,检查导入的表。如果行数为零,表示没有数据文件与你输入的存储桶 URI 匹配。在这种情况下,请通过提供正确的源文件、根据[数据导入命名约定](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件或使用**高级设置**进行更改来解决此问题。之后,重新导入这些表。 diff --git a/tidb-cloud/import-csv-files.md b/tidb-cloud/import-csv-files.md new file mode 100644 index 000000000000..65eff146427f --- /dev/null +++ b/tidb-cloud/import-csv-files.md @@ -0,0 +1,243 @@ +--- +title: 从云存储将 CSV 文件导入到 TiDB Cloud Dedicated +summary: 了解如何从 Amazon S3、GCS 或 Azure Blob Storage 将 CSV 文件导入到 TiDB Cloud Dedicated。 +aliases: ['/tidbcloud/migrate-from-amazon-s3-or-gcs','/tidbcloud/migrate-from-aurora-bulk-import'] +--- + +# 从云存储将 CSV 文件导入到 TiDB Cloud Dedicated + +本文档介绍如何从 Amazon Simple Storage Service (Amazon S3)、Google Cloud Storage (GCS) 或 Azure Blob Storage 将 CSV 文件导入到 TiDB Cloud Dedicated。 + +## 限制 + +- 为确保数据一致性,TiDB Cloud 仅允许将 CSV 文件导入到空表中。如果要将数据导入到已包含数据的现有表中,你可以按照本文档将数据导入到临时空表中,然后使用 `INSERT SELECT` 语句将数据复制到目标现有表中。 + +- 如果 TiDB Cloud Dedicated 集群有[变更数据捕获](/tidb-cloud/changefeed-overview.md)或启用了[时间点恢复](/tidb-cloud/backup-and-restore.md#turn-on-point-in-time-restore),则无法向该集群导入数据(**导入数据**按钮将被禁用),因为当前的数据导入功能使用[物理导入模式](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode)。在此模式下,导入的数据不会生成变更日志,因此变更数据捕获和时间点恢复无法检测到导入的数据。 + +## 步骤 1. 准备 CSV 文件 + +1. 如果 CSV 文件大于 256 MB,建议将其拆分为较小的文件,每个文件大小约为 256 MB。 + + TiDB Cloud 支持导入非常大的 CSV 文件,但对于大小约为 256 MB 的多个输入文件性能最佳。这是因为 TiDB Cloud 可以并行处理多个文件,这可以大大提高导入速度。 + +2. 按以下方式命名 CSV 文件: + + - 如果 CSV 文件包含整个表的所有数据,请按 `${db_name}.${table_name}.csv` 格式命名文件,该文件在导入数据时会映射到 `${db_name}.${table_name}` 表。 + - 如果一个表的数据分散在多个 CSV 文件中,请在这些 CSV 文件后面添加数字后缀。例如,`${db_name}.${table_name}.000001.csv` 和 `${db_name}.${table_name}.000002.csv`。数字后缀可以不连续,但必须按升序排列。你还需要在数字前添加额外的零,以确保所有后缀的长度相同。 + - TiDB Cloud 支持导入以下格式的压缩文件:`.gzip`、`.gz`、`.zstd`、`.zst` 和 `.snappy`。如果你想导入压缩的 CSV 文件,请按 `${db_name}.${table_name}.${suffix}.csv.${compress}` 格式命名文件,其中 `${suffix}` 是可选的,可以是任何整数,如 '000001'。例如,如果你想将 `trips.000001.csv.gz` 文件导入到 `bikeshare.trips` 表,你需要将文件重命名为 `bikeshare.trips.000001.csv.gz`。 + + > **注意:** + > + > - 你只需要压缩数据文件,不需要压缩数据库或表结构文件。 + > - 为了获得更好的性能,建议将每个压缩文件的大小限制在 100 MiB。 + > - Snappy 压缩文件必须采用[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他变体的 Snappy 压缩。 + > - 对于未压缩的文件,如果在某些情况下无法按照上述规则更新 CSV 文件名(例如,CSV 文件链接也被你的其他程序使用),你可以保持文件名不变,并使用[步骤 4](#步骤-4-将-csv-文件导入到-tidb-cloud) 中的**映射设置**将源数据导入到单个目标表。 + +## 步骤 2. 创建目标表结构 + +由于 CSV 文件不包含结构信息,在将数据从 CSV 文件导入到 TiDB Cloud 之前,你需要使用以下任一方法创建表结构: + +- 方法 1:在 TiDB Cloud 中,为你的源数据创建目标数据库和表。 + +- 方法 2:在存放 CSV 文件的 Amazon S3、GCS 或 Azure Blob Storage 目录中,为你的源数据创建目标表结构文件,如下所示: + + 1. 为你的源数据创建数据库结构文件。 + + 如果你的 CSV 文件遵循[步骤 1](#步骤-1-准备-csv-文件) 中的命名规则,则数据库结构文件对于数据导入是可选的。否则,数据库结构文件是必需的。 + + 每个数据库结构文件必须采用 `${db_name}-schema-create.sql` 格式,并包含一个 `CREATE DATABASE` DDL 语句。通过此文件,TiDB Cloud 将在导入数据时创建 `${db_name}` 数据库来存储你的数据。 + + 例如,如果你创建一个包含以下语句的 `mydb-scehma-create.sql` 文件,TiDB Cloud 将在导入数据时创建 `mydb` 数据库。 + + {{< copyable "sql" >}} + + ```sql + CREATE DATABASE mydb; + ``` + + 2. 为你的源数据创建表结构文件。 + + 如果你没有在存放 CSV 文件的 Amazon S3、GCS 或 Azure Blob Storage 目录中包含表结构文件,TiDB Cloud 在导入数据时将不会为你创建相应的表。 + + 每个表结构文件必须采用 `${db_name}.${table_name}-schema.sql` 格式,并包含一个 `CREATE TABLE` DDL 语句。通过此文件,TiDB Cloud 将在导入数据时在 `${db_name}` 数据库中创建 `${db_table}` 表。 + + 例如,如果你创建一个包含以下语句的 `mydb.mytable-schema.sql` 文件,TiDB Cloud 将在 `mydb` 数据库中创建 `mytable` 表。 + + {{< copyable "sql" >}} + + ```sql + CREATE TABLE mytable ( + ID INT, + REGION VARCHAR(20), + COUNT INT ); + ``` + + > **注意:** + > + > 每个 `${db_name}.${table_name}-schema.sql` 文件应该只包含一个 DDL 语句。如果文件包含多个 DDL 语句,只有第一个语句生效。 + +## 步骤 3. 配置跨账户访问 + +要允许 TiDB Cloud 访问 Amazon S3 存储桶、GCS 存储桶或 Azure Blob Storage 容器中的 CSV 文件,请执行以下操作之一: + +- 如果你的 CSV 文件位于 Amazon S3 中,[配置 Amazon S3 访问](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)。 + + 你可以使用 AWS 访问密钥或角色 ARN 来访问你的存储桶。完成后,请记下访问密钥(包括访问密钥 ID 和密钥)或角色 ARN 值,因为你将在[步骤 4](#步骤-4-将-csv-文件导入到-tidb-cloud) 中需要它。 + +- 如果你的 CSV 文件位于 GCS 中,[配置 GCS 访问](/tidb-cloud/dedicated-external-storage.md#configure-gcs-access)。 + +- 如果你的 CSV 文件位于 Azure Blob Storage 中,[配置 Azure Blob Storage 访问](/tidb-cloud/dedicated-external-storage.md#configure-azure-blob-storage-access)。 + +## 步骤 4. 将 CSV 文件导入到 TiDB Cloud + +要将 CSV 文件导入到 TiDB Cloud,请执行以下步骤: + + +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 Amazon S3 导入数据**页面,提供以下信息: + + - **包含结构文件**:如果源文件夹包含目标表结构文件(如 `${db_name}-schema-create.sql`),选择**是**。否则,选择**否**。 + - **数据格式**:选择 **CSV**。 + - **编辑 CSV 配置**:如有必要,根据你的 CSV 文件配置选项。你可以设置分隔符和定界符字符,指定是否使用反斜杠作为转义字符,以及指定你的文件是否包含标题行。 + - **文件夹 URI**:以 `s3://[bucket_name]/[data_source_folder]/` 格式输入源文件夹 URI。路径必须以 `/` 结尾。例如,`s3://mybucket/myfolder/`。 + - **存储桶访问**:你可以使用 AWS IAM 角色 ARN 或 AWS 访问密钥来访问你的存储桶。 + - **AWS 角色 ARN**(推荐):输入 AWS IAM 角色 ARN 值。如果你还没有存储桶的 IAM 角色,可以通过点击**点击此处使用 AWS CloudFormation 创建新角色**并按照屏幕上的说明使用提供的 AWS CloudFormation 模板创建。或者,你可以手动为存储桶创建 IAM 角色 ARN。 + - **AWS 访问密钥**:输入 AWS 访问密钥 ID 和 AWS 密钥。 + - 有关两种方法的详细说明,请参见[配置 Amazon S3 访问](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**来自定义各个目标表与其对应 CSV 文件的映射。对于每个目标数据库和表: + + - **目标数据库**:从列表中选择相应的数据库名称。 + - **目标表**:从列表中选择相应的表名称。 + - **源文件 URI 和名称**:输入源文件的完整 URI,包括文件夹和文件名,确保其格式为 `s3://[bucket_name]/[data_source_folder]/[file_name].csv`。你也可以使用通配符(`?` 和 `*`)来匹配多个文件。例如: + - `s3://mybucket/myfolder/my-data1.csv`:`myfolder` 中名为 `my-data1.csv` 的单个 CSV 文件将导入到目标表中。 + - `s3://mybucket/myfolder/my-data?.csv`:`myfolder` 中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将导入到同一个目标表中。 + - `s3://mybucket/myfolder/my-data*.csv`:`myfolder` 中以 `my-data` 开头的所有 CSV 文件(如 `my-data10.csv` 和 `my-data100.csv`)将导入到同一个目标表中。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 Google Cloud Storage 导入数据**页面,为源 CSV 文件提供以下信息: + + - **包含结构文件**:如果源文件夹包含目标表结构文件(如 `${db_name}-schema-create.sql`),选择**是**。否则,选择**否**。 + - **数据格式**:选择 **CSV**。 + - **编辑 CSV 配置**:如有必要,根据你的 CSV 文件配置选项。你可以设置分隔符和定界符字符,指定是否使用反斜杠作为转义字符,以及指定你的文件是否包含标题行。 + - **文件夹 URI**:以 `gs://[bucket_name]/[data_source_folder]/` 格式输入源文件夹 URI。路径必须以 `/` 结尾。例如,`gs://sampledata/ingest/`。 + - **Google Cloud 服务账号 ID**:TiDB Cloud 在此页面上提供了一个唯一的服务账号 ID(如 `example-service-account@your-project.iam.gserviceaccount.com`)。你必须在 Google Cloud 项目中为你的 GCS 存储桶授予此服务账号 ID 必要的 IAM 权限(如"Storage Object Viewer")。更多信息,请参见[配置 GCS 访问](/tidb-cloud/dedicated-external-storage.md#configure-gcs-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**来自定义各个目标表与其对应 CSV 文件的映射。对于每个目标数据库和表: + + - **目标数据库**:从列表中选择相应的数据库名称。 + - **目标表**:从列表中选择相应的表名称。 + - **源文件 URI 和名称**:输入源文件的完整 URI,包括文件夹和文件名,确保其格式为 `gs://[bucket_name]/[data_source_folder]/[file_name].csv`。你也可以使用通配符(`?` 和 `*`)来匹配多个文件。例如: + - `gs://mybucket/myfolder/my-data1.csv`:`myfolder` 中名为 `my-data1.csv` 的单个 CSV 文件将导入到目标表中。 + - `gs://mybucket/myfolder/my-data?.csv`:`myfolder` 中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将导入到同一个目标表中。 + - `gs://mybucket/myfolder/my-data*.csv`:`myfolder` 中以 `my-data` 开头的所有 CSV 文件(如 `my-data10.csv` 和 `my-data100.csv`)将导入到同一个目标表中。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 Azure Blob Storage 导入数据**页面,提供以下信息: + + - **包含结构文件**:如果源文件夹包含目标表结构文件(如 `${db_name}-schema-create.sql`),选择**是**。否则,选择**否**。 + - **数据格式**:选择 **CSV**。 + - **编辑 CSV 配置**:如有必要,根据你的 CSV 文件配置选项。你可以设置分隔符和定界符字符,指定是否使用反斜杠作为转义字符,以及指定你的文件是否包含标题行。 + - **文件夹 URI**:使用格式 `https://[account_name].blob.core.windows.net/[container_name]/[data_source_folder]/` 输入源文件所在的 Azure Blob Storage URI。路径必须以 `/` 结尾。例如,`https://myaccount.blob.core.windows.net/mycontainer/myfolder/`。 + - **SAS 令牌**:输入账户 SAS 令牌,以允许 TiDB Cloud 访问你的 Azure Blob Storage 容器中的源文件。如果你还没有,可以通过点击**点击此处使用 Azure ARM 模板创建新令牌**并按照屏幕上的说明使用提供的 Azure ARM 模板创建。或者,你可以手动创建账户 SAS 令牌。更多信息,请参见[配置 Azure Blob Storage 访问](/tidb-cloud/dedicated-external-storage.md#configure-azure-blob-storage-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**来自定义各个目标表与其对应 CSV 文件的映射。对于每个目标数据库和表: + + - **目标数据库**:从列表中选择相应的数据库名称。 + - **目标表**:从列表中选择相应的表名称。 + - **源文件 URI 和名称**:输入源文件的完整 URI,包括文件夹和文件名,确保其格式为 `https://[account_name].blob.core.windows.net/[container_name]/[data_source_folder]/[file_name].csv`。你也可以使用通配符(`?` 和 `*`)来匹配多个文件。例如: + - `https://myaccount.blob.core.windows.net/mycontainer/myfolder/my-data1.csv`:`myfolder` 中名为 `my-data1.csv` 的单个 CSV 文件将导入到目标表中。 + - `https://myaccount.blob.core.windows.net/mycontainer/myfolder/my-data?.csv`:`myfolder` 中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将导入到同一个目标表中。 + - `https://myaccount.blob.core.windows.net/mycontainer/myfolder/my-data*.csv`:`myfolder` 中以 `my-data` 开头的所有 CSV 文件(如 `my-data10.csv` 和 `my-data100.csv`)将导入到同一个目标表中。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +当你运行导入任务时,如果检测到任何不支持或无效的转换,TiDB Cloud 会自动终止导入作业并报告导入错误。你可以在**状态**字段中查看详细信息。 + +如果遇到导入错误,请执行以下操作: + +1. 删除部分导入的表。 +2. 检查表结构文件。如果有任何错误,请更正表结构文件。 +3. 检查 CSV 文件中的数据类型。 +4. 重试导入任务。 + +## 故障排除 + +### 解决数据导入过程中的警告 + +点击**开始导入**后,如果看到类似 `can't find the corresponding source files` 的警告消息,请通过提供正确的源文件、根据[数据导入的命名规范](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件,或使用**高级设置**进行更改来解决此问题。 + +解决这些问题后,你需要重新导入数据。 + +### 导入的表中行数为零 + +当导入进度显示**已完成**后,检查导入的表。如果行数为零,这意味着没有数据文件与你输入的存储桶 URI 匹配。在这种情况下,请通过提供正确的源文件、根据[数据导入的命名规范](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件,或使用**高级设置**进行更改来解决此问题。之后,重新导入这些表。 diff --git a/tidb-cloud/import-parquet-files-serverless.md b/tidb-cloud/import-parquet-files-serverless.md new file mode 100644 index 000000000000..bf4a8f21f012 --- /dev/null +++ b/tidb-cloud/import-parquet-files-serverless.md @@ -0,0 +1,345 @@ +--- +title: 从 Amazon S3、GCS、Azure Blob Storage 或阿里云 OSS 导入 Apache Parquet 文件到 TiDB Cloud Serverless +summary: 了解如何从 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务(OSS)导入 Apache Parquet 文件到 TiDB Cloud Serverless。 +--- + +# 从 Amazon S3、GCS、Azure Blob Storage 或阿里云 OSS 导入 Apache Parquet 文件到 TiDB Cloud Serverless + +你可以将未压缩和 Snappy 压缩的 [Apache Parquet](https://parquet.apache.org/) 格式数据文件导入到 TiDB Cloud Serverless。本文档描述了如何从 Amazon Simple Storage Service (Amazon S3)、Google Cloud Storage (GCS)、Azure Blob Storage 或阿里云对象存储服务(OSS)将 Parquet 文件导入到 TiDB Cloud Serverless。 + +> **注意:** +> +> - TiDB Cloud Serverless 仅支持将 Parquet 文件导入到空表中。要将数据导入到已包含数据的现有表中,你可以按照本文档将数据导入到临时空表中,然后使用 `INSERT SELECT` 语句将数据复制到目标现有表中。 +> - Snappy 压缩文件必须采用[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他变体的 Snappy 压缩。 + +## 步骤 1. 准备 Parquet 文件 + +> **注意:** +> +> 目前,TiDB Cloud Serverless 不支持导入包含以下任何数据类型的 Parquet 文件。如果要导入的 Parquet 文件包含此类数据类型,你需要首先使用[支持的数据类型](#支持的数据类型)(例如 `STRING`)重新生成 Parquet 文件。或者,你可以使用 AWS Glue 等服务轻松转换数据类型。 +> +> - `LIST` +> - `NEST STRUCT` +> - `BOOL` +> - `ARRAY` +> - `MAP` + +1. 如果 Parquet 文件大于 256 MB,建议将其拆分为较小的文件,每个文件大小约为 256 MB。 + + TiDB Cloud Serverless 支持导入非常大的 Parquet 文件,但对于大小约为 256 MB 的多个输入文件性能最佳。这是因为 TiDB Cloud Serverless 可以并行处理多个文件,从而大大提高导入速度。 + +2. 按照以下方式命名 Parquet 文件: + + - 如果 Parquet 文件包含整个表的所有数据,请按 `${db_name}.${table_name}.parquet` 格式命名文件,导入数据时将映射到 `${db_name}.${table_name}` 表。 + - 如果一个表的数据分散在多个 Parquet 文件中,请在这些 Parquet 文件后面添加数字后缀。例如,`${db_name}.${table_name}.000001.parquet` 和 `${db_name}.${table_name}.000002.parquet`。数字后缀可以不连续,但必须按升序排列。你还需要在数字前添加额外的零,以确保所有后缀长度相同。 + + > **注意:** + > + > 如果在某些情况下无法按照上述规则更新 Parquet 文件名(例如,Parquet 文件链接也被其他程序使用),你可以保持文件名不变,并在[步骤 4](#步骤-4-将-parquet-文件导入到-tidb-cloud-serverless) 中使用**映射设置**将源数据导入到单个目标表。 + +## 步骤 2. 创建目标表架构 + +由于 Parquet 文件不包含架构信息,在将数据从 Parquet 文件导入到 TiDB Cloud Serverless 之前,你需要使用以下任一方法创建表架构: + +- 方法 1:在 TiDB Cloud Serverless 中,为源数据创建目标数据库和表。 + +- 方法 2:在存放 Parquet 文件的 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务目录中,按以下方式为源数据创建目标表架构文件: + + 1. 为源数据创建数据库架构文件。 + + 如果你的 Parquet 文件遵循[步骤 1](#步骤-1-准备-parquet-文件) 中的命名规则,则数据库架构文件对于数据导入是可选的。否则,数据库架构文件是必需的。 + + 每个数据库架构文件必须采用 `${db_name}-schema-create.sql` 格式,并包含一个 `CREATE DATABASE` DDL 语句。使用此文件,TiDB Cloud Serverless 将在导入数据时创建 `${db_name}` 数据库来存储你的数据。 + + 例如,如果你创建一个包含以下语句的 `mydb-scehma-create.sql` 文件,TiDB Cloud Serverless 将在导入数据时创建 `mydb` 数据库。 + + ```sql + CREATE DATABASE mydb; + ``` + + 2. 为源数据创建表架构文件。 + + 如果你没有在存放 Parquet 文件的 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务目录中包含表架构文件,TiDB Cloud Serverless 在导入数据时将不会为你创建相应的表。 + + 每个表架构文件必须采用 `${db_name}.${table_name}-schema.sql` 格式,并包含一个 `CREATE TABLE` DDL 语句。使用此文件,TiDB Cloud Serverless 将在导入数据时在 `${db_name}` 数据库中创建 `${db_table}` 表。 + + 例如,如果你创建一个包含以下语句的 `mydb.mytable-schema.sql` 文件,TiDB Cloud Serverless 将在导入数据时在 `mydb` 数据库中创建 `mytable` 表。 + + ```sql + CREATE TABLE mytable ( + ID INT, + REGION VARCHAR(20), + COUNT INT ); + ``` + + > **注意:** + > + > 每个 `${db_name}.${table_name}-schema.sql` 文件应该只包含一个 DDL 语句。如果文件包含多个 DDL 语句,只有第一个语句生效。 + +## 步骤 3. 配置跨账户访问 + +要允许 TiDB Cloud Serverless 访问 Amazon S3、GCS、Azure Blob Storage 或阿里云对象存储服务存储桶中的 Parquet 文件,请执行以下操作之一: + +- 如果你的 Parquet 文件位于 Amazon S3 中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#configure-amazon-s3-access)。 + + 你可以使用 AWS 访问密钥或 Role ARN 访问存储桶。完成后,请记下访问密钥(包括访问密钥 ID 和密钥)或 Role ARN 值,因为你将在[步骤 4](#步骤-4-将-parquet-文件导入到-tidb-cloud-serverless) 中需要它。 + +- 如果你的 Parquet 文件位于 GCS 中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#configure-gcs-access)。 + +- 如果你的 Parquet 文件位于 Azure Blob Storage 中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#configure-azure-blob-storage-access)。 + +- 如果你的 Parquet 文件位于阿里云对象存储服务(OSS)中,[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md#configure-alibaba-cloud-object-storage-service-oss-access)。 + +## 步骤 4. 将 Parquet 文件导入到 TiDB Cloud Serverless + +要将 Parquet 文件导入到 TiDB Cloud Serverless,请执行以下步骤: + + +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Amazon S3**。 + +3. 在**从 Amazon S3 导入数据**页面,为源 Parquet 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **Parquet**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `s3://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`s3://sampledata/ingest/TableName.01.parquet`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `s3://[bucket_name]/[data_source_folder]/`。例如,`s3://sampledata/ingest/`。 + - **存储桶访问**:你可以使用 AWS Role ARN 或 AWS 访问密钥访问存储桶。更多信息,请参阅[配置 Amazon S3 访问](/tidb-cloud/serverless-external-storage.md#configure-amazon-s3-access)。 + - **AWS Role ARN**:输入 AWS Role ARN 值。 + - **AWS 访问密钥**:输入 AWS 访问密钥 ID 和 AWS 密钥。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 Parquet 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保使用以下格式 `s3://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`s3://sampledata/ingest/TableName.01.parquet`。 + + 你还可以使用通配符匹配源文件。例如: + + - `s3://[bucket_name]/[data_source_folder]/my-data?.parquet`:该文件夹中以 `my-data` 开头后跟一个字符的所有 Parquet 文件(如 `my-data1.parquet` 和 `my-data2.parquet`)将导入到同一个目标表中。 + + - `s3://[bucket_name]/[data_source_folder]/my-data*.parquet`:该文件夹中以 `my-data` 开头的所有 Parquet 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Google Cloud Storage**。 + +3. 在**从 Google Cloud Storage 导入数据**页面,为源 Parquet 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **Parquet**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `[gcs|gs]://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`[gcs|gs]://sampledata/ingest/TableName.01.parquet`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `[gcs|gs]://[bucket_name]/[data_source_folder]/`。例如,`[gcs|gs]://sampledata/ingest/`。 + - **存储桶访问**:你可以使用 GCS IAM 角色访问存储桶。更多信息,请参阅[配置 GCS 访问](/tidb-cloud/serverless-external-storage.md#configure-gcs-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 Parquet 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保使用以下格式 `[gcs|gs]://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`[gcs|gs]://sampledata/ingest/TableName.01.parquet`。 + + 你还可以使用通配符匹配源文件。例如: + + - `[gcs|gs]://[bucket_name]/[data_source_folder]/my-data?.parquet`:该文件夹中以 `my-data` 开头后跟一个字符的所有 Parquet 文件(如 `my-data1.parquet` 和 `my-data2.parquet`)将导入到同一个目标表中。 + + - `[gcs|gs]://[bucket_name]/[data_source_folder]/my-data*.parquet`:该文件夹中以 `my-data` 开头的所有 Parquet 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Azure Blob Storage**。 + +3. 在**从 Azure Blob Storage 导入数据**页面,为源 Parquet 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **Parquet**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `[azure|https]://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`[azure|https]://sampledata/ingest/TableName.01.parquet`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `[azure|https]://[bucket_name]/[data_source_folder]/`。例如,`[azure|https]://sampledata/ingest/`。 + - **存储桶访问**:你可以使用共享访问签名(SAS)令牌访问存储桶。更多信息,请参阅[配置 Azure Blob Storage 访问](/tidb-cloud/serverless-external-storage.md#configure-azure-blob-storage-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 Parquet 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保使用以下格式 `[azure|https]://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`[azure|https]://sampledata/ingest/TableName.01.parquet`。 + + 你还可以使用通配符匹配源文件。例如: + + - `[azure|https]://[bucket_name]/[data_source_folder]/my-data?.parquet`:该文件夹中以 `my-data` 开头后跟一个字符的所有 Parquet 文件(如 `my-data1.parquet` 和 `my-data2.parquet`)将导入到同一个目标表中。 + + - `[azure|https]://[bucket_name]/[data_source_folder]/my-data*.parquet`:该文件夹中以 `my-data` 开头的所有 Parquet 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击**阿里云 OSS**。 + +3. 在**从阿里云 OSS 导入数据**页面,为源 Parquet 文件提供以下信息: + + - **导入文件数量**:根据需要选择**单个文件**或**多个文件**。 + - **包含架构文件**:此字段仅在导入多个文件时可见。如果源文件夹包含目标表架构,选择**是**。否则,选择**否**。 + - **数据格式**:选择 **Parquet**。 + - **文件 URI** 或**文件夹 URI**: + - 导入单个文件时,按以下格式输入源文件 URI 和名称 `oss://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`oss://sampledata/ingest/TableName.01.parquet`。 + - 导入多个文件时,按以下格式输入源文件 URI 和名称 `oss://[bucket_name]/[data_source_folder]/`。例如,`oss://sampledata/ingest/`。 + - **存储桶访问**:你可以使用 AccessKey 对访问存储桶。更多信息,请参阅[配置阿里云对象存储服务(OSS)访问](/tidb-cloud/serverless-external-storage.md#configure-alibaba-cloud-object-storage-service-oss-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 Parquet 文件定义自定义映射规则。之后,将使用提供的自定义映射规则重新扫描数据源文件。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保使用以下格式 `oss://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`oss://sampledata/ingest/TableName.01.parquet`。 + + 你还可以使用通配符匹配源文件。例如: + + - `oss://[bucket_name]/[data_source_folder]/my-data?.parquet`:该文件夹中以 `my-data` 开头后跟一个字符的所有 Parquet 文件(如 `my-data1.parquet` 和 `my-data2.parquet`)将导入到同一个目标表中。 + + - `oss://[bucket_name]/[data_source_folder]/my-data*.parquet`:该文件夹中以 `my-data` 开头的所有 Parquet 文件将导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*`。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +运行导入任务时,如果检测到任何不支持或无效的转换,TiDB Cloud Serverless 会自动终止导入作业并报告导入错误。 + +如果遇到导入错误,请执行以下操作: + +1. 删除部分导入的表。 +2. 检查表架构文件。如果有任何错误,请更正表架构文件。 +3. 检查 Parquet 文件中的数据类型。 + + 如果 Parquet 文件包含任何不支持的数据类型(例如 `NEST STRUCT`、`ARRAY` 或 `MAP`),你需要使用[支持的数据类型](#支持的数据类型)(例如 `STRING`)重新生成 Parquet 文件。 + +4. 重试导入任务。 + +## 支持的数据类型 + +下表列出了可以导入到 TiDB Cloud Serverless 的支持的 Parquet 数据类型。 + +| Parquet 基本类型 | Parquet 逻辑类型 | TiDB 或 MySQL 中的类型 | +|---|---|---| +| DOUBLE | DOUBLE | DOUBLE
FLOAT | +| FIXED_LEN_BYTE_ARRAY(9) | DECIMAL(20,0) | BIGINT UNSIGNED | +| FIXED_LEN_BYTE_ARRAY(N) | DECIMAL(p,s) | DECIMAL
NUMERIC | +| INT32 | DECIMAL(p,s) | DECIMAL
NUMERIC | +| INT32 | N/A | INT
MEDIUMINT
YEAR | +| INT64 | DECIMAL(p,s) | DECIMAL
NUMERIC | +| INT64 | N/A | BIGINT
INT UNSIGNED
MEDIUMINT UNSIGNED | +| INT64 | TIMESTAMP_MICROS | DATETIME
TIMESTAMP | +| BYTE_ARRAY | N/A | BINARY
BIT
BLOB
CHAR
LINESTRING
LONGBLOB
MEDIUMBLOB
MULTILINESTRING
TINYBLOB
VARBINARY | +| BYTE_ARRAY | STRING | ENUM
DATE
DECIMAL
GEOMETRY
GEOMETRYCOLLECTION
JSON
LONGTEXT
MEDIUMTEXT
MULTIPOINT
MULTIPOLYGON
NUMERIC
POINT
POLYGON
SET
TEXT
TIME
TINYTEXT
VARCHAR | +| SMALLINT | N/A | INT32 | +| SMALLINT UNSIGNED | N/A | INT32 | +| TINYINT | N/A | INT32 | +| TINYINT UNSIGNED | N/A | INT32 | + +## 故障排除 + +### 解决数据导入过程中的警告 + +点击**开始导入**后,如果看到类似 `can't find the corresponding source files` 的警告消息,请通过提供正确的源文件、根据[数据导入命名约定](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件或使用**高级设置**进行更改来解决此问题。 + +解决这些问题后,你需要重新导入数据。 + +### 导入的表中行数为零 + +导入进度显示**已完成**后,检查导入的表。如果行数为零,则表示没有数据文件与你输入的存储桶 URI 匹配。在这种情况下,请通过提供正确的源文件、根据[数据导入命名约定](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件或使用**高级设置**进行更改来解决此问题。之后,重新导入这些表。 diff --git a/tidb-cloud/import-parquet-files.md b/tidb-cloud/import-parquet-files.md new file mode 100644 index 000000000000..bb056d9cb5cc --- /dev/null +++ b/tidb-cloud/import-parquet-files.md @@ -0,0 +1,270 @@ +--- +title: 从云存储导入 Apache Parquet 文件到 TiDB Cloud Dedicated +summary: 了解如何从 Amazon S3、GCS 或 Azure Blob Storage 导入 Apache Parquet 文件到 TiDB Cloud Dedicated。 +--- + +# 从云存储导入 Apache Parquet 文件到 TiDB Cloud Dedicated + +本文介绍如何从 Amazon Simple Storage Service (Amazon S3)、Google Cloud Storage (GCS) 或 Azure Blob Storage 导入 Apache Parquet 文件到 TiDB Cloud Dedicated。你可以导入未压缩的 Parquet 文件或使用 [Google Snappy](https://github.com/google/snappy) 压缩的 Parquet 文件。不支持其他 Parquet 压缩编解码器。 + +## 限制 + +- 为确保数据一致性,TiDB Cloud 只允许将 Parquet 文件导入到空表中。要将数据导入到已包含数据的现有表中,你可以按照本文档将数据导入到临时空表中,然后使用 `INSERT SELECT` 语句将数据复制到目标现有表中。 + +- 如果 TiDB Cloud Dedicated 集群有 [changefeed](/tidb-cloud/changefeed-overview.md) 或启用了[时间点恢复](/tidb-cloud/backup-and-restore.md#turn-on-point-in-time-restore),则无法向该集群导入数据(**导入数据**按钮将被禁用),因为当前的数据导入功能使用[物理导入模式](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode)。在此模式下,导入的数据不会生成变更日志,因此 changefeed 和时间点恢复无法检测到导入的数据。 + +## 步骤 1. 准备 Parquet 文件 + +> **注意:** +> +> 目前,TiDB Cloud 不支持导入包含以下任何数据类型的 Parquet 文件。如果要导入的 Parquet 文件包含此类数据类型,你需要首先使用[支持的数据类型](#支持的数据类型)(例如 `STRING`)重新生成 Parquet 文件。或者,你可以使用 AWS Glue 等服务轻松转换数据类型。 +> +> - `LIST` +> - `NEST STRUCT` +> - `BOOL` +> - `ARRAY` +> - `MAP` + +1. 如果 Parquet 文件大于 256 MB,建议将其拆分为较小的文件,每个文件大小约为 256 MB。 + + TiDB Cloud 支持导入非常大的 Parquet 文件,但在处理大小约为 256 MB 的多个输入文件时性能最佳。这是因为 TiDB Cloud 可以并行处理多个文件,从而大大提高导入速度。 + +2. 按以下方式命名 Parquet 文件: + + - 如果 Parquet 文件包含整个表的所有数据,请按 `${db_name}.${table_name}.parquet` 格式命名文件,该文件在导入数据时会映射到 `${db_name}.${table_name}` 表。 + - 如果一个表的数据分散在多个 Parquet 文件中,请在这些 Parquet 文件后附加数字后缀。例如,`${db_name}.${table_name}.000001.parquet` 和 `${db_name}.${table_name}.000002.parquet`。数字后缀可以不连续,但必须按升序排列。你还需要在数字前添加额外的零,以确保所有后缀长度相同。 + + > **注意:** + > + > - 如果在某些情况下无法按照上述规则更新 Parquet 文件名(例如,Parquet 文件链接也被你的其他程序使用),你可以保持文件名不变,并在[步骤 4](#步骤-4-将-parquet-文件导入到-tidb-cloud) 中使用**映射设置**将源数据导入到单个目标表中。 + > - Snappy 压缩文件必须采用[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他变体的 Snappy 压缩。 + +## 步骤 2. 创建目标表架构 + +由于 Parquet 文件不包含架构信息,在将数据从 Parquet 文件导入到 TiDB Cloud 之前,你需要使用以下任一方法创建表架构: + +- 方法 1:在 TiDB Cloud 中,为源数据创建目标数据库和表。 + +- 方法 2:在存放 Parquet 文件的 Amazon S3、GCS 或 Azure Blob Storage 目录中,按以下方式为源数据创建目标表架构文件: + + 1. 为源数据创建数据库架构文件。 + + 如果你的 Parquet 文件遵循[步骤 1](#步骤-1-准备-parquet-文件) 中的命名规则,则数据导入时数据库架构文件是可选的。否则,数据库架构文件是必需的。 + + 每个数据库架构文件必须采用 `${db_name}-schema-create.sql` 格式,并包含一个 `CREATE DATABASE` DDL 语句。通过此文件,TiDB Cloud 将在导入数据时创建 `${db_name}` 数据库来存储你的数据。 + + 例如,如果你创建一个包含以下语句的 `mydb-scehma-create.sql` 文件,TiDB Cloud 将在导入数据时创建 `mydb` 数据库。 + + {{< copyable "sql" >}} + + ```sql + CREATE DATABASE mydb; + ``` + + 2. 为源数据创建表架构文件。 + + 如果你没有在存放 Parquet 文件的 Amazon S3、GCS 或 Azure Blob Storage 目录中包含表架构文件,TiDB Cloud 在导入数据时将不会为你创建相应的表。 + + 每个表架构文件必须采用 `${db_name}.${table_name}-schema.sql` 格式,并包含一个 `CREATE TABLE` DDL 语句。通过此文件,TiDB Cloud 将在导入数据时在 `${db_name}` 数据库中创建 `${db_table}` 表。 + + 例如,如果你创建一个包含以下语句的 `mydb.mytable-schema.sql` 文件,TiDB Cloud 将在 `mydb` 数据库中创建 `mytable` 表。 + + {{< copyable "sql" >}} + + ```sql + CREATE TABLE mytable ( + ID INT, + REGION VARCHAR(20), + COUNT INT ); + ``` + + > **注意:** + > + > 每个 `${db_name}.${table_name}-schema.sql` 文件应该只包含一个 DDL 语句。如果文件包含多个 DDL 语句,只有第一个语句会生效。 + +## 步骤 3. 配置跨账户访问 + +要允许 TiDB Cloud 访问 Amazon S3 存储桶、GCS 存储桶或 Azure Blob Storage 容器中的 Parquet 文件,请执行以下操作之一: + +- 如果你的 Parquet 文件位于 Amazon S3 中,[配置 Amazon S3 访问](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)。 + + 你可以使用 AWS 访问密钥或 Role ARN 访问你的存储桶。完成后,请记下访问密钥(包括访问密钥 ID 和密钥)或 Role ARN 值,因为你将在[步骤 4](#步骤-4-将-parquet-文件导入到-tidb-cloud) 中需要它。 + +- 如果你的 Parquet 文件位于 GCS 中,[配置 GCS 访问](/tidb-cloud/dedicated-external-storage.md#configure-gcs-access)。 + +- 如果你的 Parquet 文件位于 Azure Blob Storage 中,[配置 Azure Blob Storage 访问](/tidb-cloud/dedicated-external-storage.md#configure-azure-blob-storage-access)。 + +## 步骤 4. 将 Parquet 文件导入到 TiDB Cloud + +要将 Parquet 文件导入到 TiDB Cloud,请执行以下步骤: + + +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 Amazon S3 导入数据**页面上,提供以下信息: + + - **包含架构文件**:如果源文件夹包含目标表架构文件(如 `${db_name}-schema-create.sql`),选择**是**。否则,选择**否**。 + - **数据格式**:选择 **Parquet**。 + - **文件夹 URI**:以 `s3://[bucket_name]/[data_source_folder]/` 格式输入源文件夹 URI。路径必须以 `/` 结尾。例如,`s3://sampledata/ingest/`。 + - **存储桶访问**:你可以使用 AWS IAM 角色 ARN 或 AWS 访问密钥访问你的存储桶。 + - **AWS Role ARN**(推荐):输入 AWS IAM 角色 ARN 值。如果你还没有存储桶的 IAM 角色,可以通过点击**点击此处使用 AWS CloudFormation 创建新角色**并按照屏幕上的说明使用提供的 AWS CloudFormation 模板创建。或者,你可以手动为存储桶创建 IAM 角色 ARN。 + - **AWS 访问密钥**:输入 AWS 访问密钥 ID 和 AWS 密钥。 + - 有关两种方法的详细说明,请参见[配置 Amazon S3 访问](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**来自定义各个目标表与其对应 Parquet 文件的映射。对于每个目标数据库和表: + + - **目标数据库**:从列表中选择相应的数据库名称。 + - **目标表**:从列表中选择相应的表名称。 + - **源文件 URI 和名称**:输入源文件的完整 URI,包括文件夹和文件名,确保其格式为 `s3://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`s3://sampledata/ingest/TableName.01.parquet`。你也可以使用通配符(`?` 和 `*`)匹配多个文件。例如: + - `s3://[bucket_name]/[data_source_folder]/my-data1.parquet`:`[data_source_folder]` 中名为 `my-data1.parquet` 的单个 Parquet 文件将被导入到目标表中。 + - `s3://[bucket_name]/[data_source_folder]/my-data?.parquet`:`[data_source_folder]` 中以 `my-data` 开头后跟一个字符的所有 Parquet 文件(如 `my-data1.parquet` 和 `my-data2.parquet`)将被导入到同一个目标表中。 + - `s3://[bucket_name]/[data_source_folder]/my-data*.parquet`:`[data_source_folder]` 中以 `my-data` 开头的所有 Parquet 文件(如 `my-data10.parquet` 和 `my-data100.parquet`)将被导入到同一个目标表中。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 GCS 导入数据**页面上,为源 Parquet 文件提供以下信息: + + - **包含架构文件**:如果源文件夹包含目标表架构文件(如 `${db_name}-schema-create.sql`),选择**是**。否则,选择**否**。 + - **数据格式**:选择 **Parquet**。 + - **文件夹 URI**:以 `gs://[bucket_name]/[data_source_folder]/` 格式输入源文件夹 URI。路径必须以 `/` 结尾。例如,`gs://sampledata/ingest/`。 + - **Google Cloud 服务账号 ID**:TiDB Cloud 在此页面上提供唯一的服务账号 ID(如 `example-service-account@your-project.iam.gserviceaccount.com`)。你必须在 Google Cloud 项目中为你的 GCS 存储桶授予此服务账号 ID 必要的 IAM 权限(如 "Storage Object Viewer")。更多信息,请参见[配置 GCS 访问](/tidb-cloud/dedicated-external-storage.md#configure-gcs-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**来自定义各个目标表与其对应 Parquet 文件的映射。对于每个目标数据库和表: + + - **目标数据库**:从列表中选择相应的数据库名称。 + - **目标表**:从列表中选择相应的表名称。 + - **源文件 URI 和名称**:输入源文件的完整 URI,包括文件夹和文件名,确保其格式为 `gs://[bucket_name]/[data_source_folder]/[file_name].parquet`。例如,`gs://sampledata/ingest/TableName.01.parquet`。你也可以使用通配符(`?` 和 `*`)匹配多个文件。例如: + - `gs://[bucket_name]/[data_source_folder]/my-data1.parquet`:`[data_source_folder]` 中名为 `my-data1.parquet` 的单个 Parquet 文件将被导入到目标表中。 + - `gs://[bucket_name]/[data_source_folder]/my-data?.parquet`:`[data_source_folder]` 中以 `my-data` 开头后跟一个字符的所有 Parquet 文件(如 `my-data1.parquet` 和 `my-data2.parquet`)将被导入到同一个目标表中。 + - `gs://[bucket_name]/[data_source_folder]/my-data*.parquet`:`[data_source_folder]` 中以 `my-data` 开头的所有 Parquet 文件(如 `my-data10.parquet` 和 `my-data100.parquet`)将被导入到同一个目标表中。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 Azure Blob Storage 导入数据**页面上,提供以下信息: + + - **包含架构文件**:如果源文件夹包含目标表架构文件(如 `${db_name}-schema-create.sql`),选择**是**。否则,选择**否**。 + - **数据格式**:选择 **Parquet**。 + - **文件夹 URI**:使用格式 `https://[account_name].blob.core.windows.net/[container_name]/[data_source_folder]/` 输入源文件所在的 Azure Blob Storage URI。路径必须以 `/` 结尾。例如,`https://myaccount.blob.core.windows.net/mycontainer/data-ingestion/`。 + - **SAS 令牌**:输入账户 SAS 令牌以允许 TiDB Cloud 访问你的 Azure Blob Storage 容器中的源文件。如果你还没有,可以通过点击**点击此处使用 Azure ARM 模板创建新令牌**并按照屏幕上的说明使用提供的 Azure ARM 模板创建。或者,你可以手动创建账户 SAS 令牌。更多信息,请参见[配置 Azure Blob Storage 访问](/tidb-cloud/dedicated-external-storage.md#configure-azure-blob-storage-access)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**来自定义各个目标表与其对应 Parquet 文件的映射。对于每个目标数据库和表: + + - **目标数据库**:从列表中选择相应的数据库名称。 + - **目标表**:从列表中选择相应的表名称。 + - **源文件 URI 和名称**:输入源文件的完整 URI,包括文件夹和文件名,确保其格式为 `https://[account_name].blob.core.windows.net/[container_name]/[data_source_folder]/[file_name].parquet`。例如,`https://myaccount.blob.core.windows.net/mycontainer/data-ingestion/TableName.01.parquet`。你也可以使用通配符(`?` 和 `*`)匹配多个文件。例如: + - `https://[account_name].blob.core.windows.net/[container_name]/[data_source_folder]/my-data1.parquet`:`[data_source_folder]` 中名为 `my-data1.parquet` 的单个 Parquet 文件将被导入到目标表中。 + - `https://[account_name].blob.core.windows.net/[container_name]/[data_source_folder]/my-data?.parquet`:`[data_source_folder]` 中以 `my-data` 开头后跟一个字符的所有 Parquet 文件(如 `my-data1.parquet` 和 `my-data2.parquet`)将被导入到同一个目标表中。 + - `https://[account_name].blob.core.windows.net/[container_name]/[data_source_folder]/my-data*.parquet`:`[data_source_folder]` 中以 `my-data` 开头的所有 Parquet 文件(如 `my-data10.parquet` 和 `my-data100.parquet`)将被导入到同一个目标表中。 + +6. 点击**开始导入**。 + +7. 当导入进度显示**已完成**时,检查导入的表。 + +
+ +
+ +运行导入任务时,如果检测到任何不支持或无效的转换,TiDB Cloud 会自动终止导入作业并报告导入错误。你可以在**状态**字段中查看详细信息。 + +如果遇到导入错误,请执行以下操作: + +1. 删除部分导入的表。 +2. 检查表架构文件。如果有任何错误,请更正表架构文件。 +3. 检查 Parquet 文件中的数据类型。 + + 如果 Parquet 文件包含任何不支持的数据类型(例如 `NEST STRUCT`、`ARRAY` 或 `MAP`),你需要使用[支持的数据类型](#支持的数据类型)(例如 `STRING`)重新生成 Parquet 文件。 + +4. 重试导入任务。 + +## 支持的数据类型 + +下表列出了可以导入到 TiDB Cloud 的支持的 Parquet 数据类型。 + +| Parquet 基本类型 | Parquet 逻辑类型 | TiDB 或 MySQL 中的类型 | +|---|---|---| +| DOUBLE | DOUBLE | DOUBLE
FLOAT | +| FIXED_LEN_BYTE_ARRAY(9) | DECIMAL(20,0) | BIGINT UNSIGNED | +| FIXED_LEN_BYTE_ARRAY(N) | DECIMAL(p,s) | DECIMAL
NUMERIC | +| INT32 | DECIMAL(p,s) | DECIMAL
NUMERIC | +| INT32 | N/A | INT
MEDIUMINT
YEAR | +| INT64 | DECIMAL(p,s) | DECIMAL
NUMERIC | +| INT64 | N/A | BIGINT
INT UNSIGNED
MEDIUMINT UNSIGNED | +| INT64 | TIMESTAMP_MICROS | DATETIME
TIMESTAMP | +| BYTE_ARRAY | N/A | BINARY
BIT
BLOB
CHAR
LINESTRING
LONGBLOB
MEDIUMBLOB
MULTILINESTRING
TINYBLOB
VARBINARY | +| BYTE_ARRAY | STRING | ENUM
DATE
DECIMAL
GEOMETRY
GEOMETRYCOLLECTION
JSON
LONGTEXT
MEDIUMTEXT
MULTIPOINT
MULTIPOLYGON
NUMERIC
POINT
POLYGON
SET
TEXT
TIME
TINYTEXT
VARCHAR | +| SMALLINT | N/A | INT32 | +| SMALLINT UNSIGNED | N/A | INT32 | +| TINYINT | N/A | INT32 | +| TINYINT UNSIGNED | N/A | INT32 | + +## 故障排除 + +### 解决数据导入期间的警告 + +点击**开始导入**后,如果看到类似 `can't find the corresponding source files` 的警告消息,请通过提供正确的源文件、按照[数据导入命名约定](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件或使用**高级设置**进行更改来解决此问题。 + +解决这些问题后,你需要重新导入数据。 + +### 导入的表中行数为零 + +导入进度显示**已完成**后,检查导入的表。如果行数为零,则表示没有数据文件与你输入的存储桶 URI 匹配。在这种情况下,请通过提供正确的源文件、按照[数据导入命名约定](/tidb-cloud/naming-conventions-for-data-import.md)重命名现有文件或使用**高级设置**进行更改来解决此问题。之后,重新导入这些表。 diff --git a/tidb-cloud/import-sample-data-serverless.md b/tidb-cloud/import-sample-data-serverless.md new file mode 100644 index 000000000000..1eaa1d5a8955 --- /dev/null +++ b/tidb-cloud/import-sample-data-serverless.md @@ -0,0 +1,94 @@ +--- +title: 导入示例数据到 TiDB Cloud Serverless +summary: 了解如何通过 UI 将示例数据导入到 TiDB Cloud Serverless。 +--- + +# 导入示例数据到 TiDB Cloud Serverless + +本文介绍如何通过 UI 将示例数据导入到 TiDB Cloud Serverless。使用的示例数据是 Capital Bikeshare 的系统数据,根据 Capital Bikeshare 数据许可协议发布。在导入示例数据之前,你需要有一个 TiDB 集群。 + +> **注意:** +> +> TiDB Cloud Serverless 目前仅支持从 Amazon S3 导入示例数据。 + +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Amazon S3**。 + +3. 在**从 Amazon S3 导入数据**页面上,配置以下源数据信息: + + - **导入文件数量**:对于示例数据,选择**多个文件**。 + - **包含架构文件**:对于示例数据,选择**是**。 + - **数据格式**:选择 **SQL**。 + - **文件夹 URI** 或**文件 URI**:输入示例数据 URI `s3://tidbcloud-sample-data/data-ingestion/`。 + - **存储桶访问**:对于示例数据,你只能使用 Role ARN 访问其存储桶。对于你自己的数据,你可以使用 AWS 访问密钥或 Role ARN 访问你的存储桶。 + - **AWS Role ARN**:输入 `arn:aws:iam::801626783489:role/import-sample-access`。 + - **AWS 访问密钥**:对于示例数据,跳过此选项。 + +4. 点击**连接** > **开始导入**。 + +当数据导入进度显示**已完成**时,你已成功将示例数据和数据库架构导入到 TiDB Cloud Serverless 中的数据库。 + +连接到集群后,你可以在终端中运行一些查询来检查结果,例如: + +1. 获取起始站为 "12th & U St NW" 的行程记录: + + ```sql + use bikeshare; + ``` + + ```sql + select * from `trips` where start_station_name='12th & U St NW' limit 10; + ``` + + ```sql + +-----------------+---------------+---------------------+---------------------+--------------------+------------------+-------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | ride_id | rideable_type | started_at | ended_at | start_station_name | start_station_id | end_station_name | end_station_id | start_lat | start_lng | end_lat | end_lng | member_casual | + +-----------------+---------------+---------------------+---------------------+--------------------+------------------+-------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | E291FF5018 | classic_bike | 2021-01-02 11:12:38 | 2021-01-02 11:23:47 | 12th & U St NW | 31268 | 7th & F St NW / National Portrait Gallery | 31232 | 38.916786 | -77.02814 | 38.89728 | -77.022194 | member | + | E76F3605D0 | docked_bike | 2020-09-13 00:44:11 | 2020-09-13 00:59:38 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | casual | + | FFF0B75414 | docked_bike | 2020-09-28 16:47:53 | 2020-09-28 16:57:30 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | casual | + | C3F2C16949 | docked_bike | 2020-09-13 00:42:03 | 2020-09-13 00:59:43 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | casual | + | 1C7EC91629 | docked_bike | 2020-09-28 16:47:49 | 2020-09-28 16:57:26 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | member | + | A3A38BCACA | classic_bike | 2021-01-14 09:52:53 | 2021-01-14 10:00:51 | 12th & U St NW | 31268 | 10th & E St NW | 31256 | 38.916786 | -77.02814 | 38.895912 | -77.02606 | member | + | EC4943257E | electric_bike | 2021-01-28 10:06:52 | 2021-01-28 10:16:28 | 12th & U St NW | 31268 | 10th & E St NW | 31256 | 38.916843 | -77.028206 | 38.89607 | -77.02608 | member | + | D4070FBFA7 | classic_bike | 2021-01-12 09:50:51 | 2021-01-12 09:59:41 | 12th & U St NW | 31268 | 10th & E St NW | 31256 | 38.916786 | -77.02814 | 38.895912 | -77.02606 | member | + | 6EABEF3CAB | classic_bike | 2021-01-09 15:00:43 | 2021-01-09 15:18:30 | 12th & U St NW | 31268 | 1st & M St NE | 31603 | 38.916786 | -77.02814 | 38.905697 | -77.005486 | member | + | 2F5CC89018 | electric_bike | 2021-01-02 01:47:07 | 2021-01-02 01:58:29 | 12th & U St NW | 31268 | 3rd & H St NE | 31616 | 38.916836 | -77.02815 | 38.90074 | -77.00219 | member | + +-----------------+---------------+---------------------+---------------------+--------------------+------------------+-------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + ``` + +2. 获取电动自行车的行程记录: + + ```sql + use bikeshare; + ``` + + ```sql + select * from `trips` where rideable_type="electric_bike" limit 10; + ``` + + ```sql + +------------------+---------------+---------------------+---------------------+----------------------------------------+------------------+-------------------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | ride_id | rideable_type | started_at | ended_at | start_station_name | start_station_id | end_station_name | end_station_id | start_lat | start_lng | end_lat | end_lng | member_casual | + +------------------+---------------+---------------------+---------------------+----------------------------------------+------------------+-------------------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | AF15B12839DA4367 | electric_bike | 2021-01-23 14:50:46 | 2021-01-23 14:59:55 | Columbus Circle / Union Station | 31623 | 15th & East Capitol St NE | 31630 | 38.8974 | -77.00481 | 38.890 | 76.98354 | member | + | 7173E217338C4752 | electric_bike | 2021-01-15 08:28:38 | 2021-01-15 08:33:49 | 37th & O St NW / Georgetown University | 31236 | 34th St & Wisconsin Ave NW | 31226 | 38.907825 | -77.071655 | 38.916 | -77.0683 | member | + | E665505ED621D1AB | electric_bike | 2021-01-05 13:25:47 | 2021-01-05 13:35:58 | N Lynn St & Fairfax Dr | 31917 | 34th St & Wisconsin Ave NW | 31226 | 38.89359 | -77.07089 | 38.916 | 77.06829 | member | + | 646AFE266A6375AF | electric_bike | 2021-01-16 00:08:10 | 2021-01-16 00:35:58 | 7th St & Massachusetts Ave NE | 31647 | 34th St & Wisconsin Ave NW | 31226 | 38.892235 | -76.996025 | 38.91 | 7.068245 | member | + | 40CDDA0378E45736 | electric_bike | 2021-01-03 11:14:50 | 2021-01-03 11:26:04 | N Lynn St & Fairfax Dr | 31917 | 34th St & Wisconsin Ave NW | 31226 | 38.893734 | -77.07096 | 38.916 | 7.068275 | member | + | E0A7DDB0CE680C01 | electric_bike | 2021-01-05 18:18:17 | 2021-01-05 19:04:11 | Maine Ave & 7th St SW | 31609 | Smithsonian-National Mall / Jefferson Dr & 12th St SW | 31248 | 38.878727 | -77.02304 | 38.8 | 7.028755 | casual | + | 71BDF35029AF0039 | electric_bike | 2021-01-07 10:23:57 | 2021-01-07 10:59:43 | 10th & K St NW | 31263 | East West Hwy & Blair Mill Rd | 32019 | 38.90279 | -77.02633 | 38.990 | 77.02937 | member | + | D5EACDF488260A61 | electric_bike | 2021-01-13 20:57:23 | 2021-01-13 21:04:19 | 8th & H St NE | 31661 | 15th & East Capitol St NE | 31630 | 38.89985 | -76.994835 | 38.88 | 76.98345 | member | + | 211D449363FB7EE3 | electric_bike | 2021-01-15 17:22:02 | 2021-01-15 17:35:49 | 7th & K St NW | 31653 | 15th & East Capitol St NE | 31630 | 38.90216 | -77.0211 | 38.88 | 76.98357 | casual | + | CE667578A7291701 | electric_bike | 2021-01-15 16:55:12 | 2021-01-15 17:38:26 | East West Hwy & 16th St | 32056 | East West Hwy & Blair Mill Rd | 32019 | 38.995674 | -77.03868 | 38.990 | 77.02953 | casual | + +------------------+---------------+---------------------+---------------------+----------------------------------------+------------------+-------------------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + ``` diff --git a/tidb-cloud/import-sample-data.md b/tidb-cloud/import-sample-data.md new file mode 100644 index 000000000000..c79bbaf16854 --- /dev/null +++ b/tidb-cloud/import-sample-data.md @@ -0,0 +1,150 @@ +--- +title: 导入示例数据到 TiDB Cloud Dedicated +summary: 了解如何通过 UI 将示例数据导入到 TiDB Cloud Dedicated。 +--- + +# 导入示例数据到 TiDB Cloud Dedicated + +本文介绍如何通过 UI 将示例数据导入到 TiDB Cloud Dedicated。使用的示例数据是 Capital Bikeshare 的系统数据,根据 Capital Bikeshare 数据许可协议发布。在导入示例数据之前,你需要有一个 TiDB 集群。 + + +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 Amazon S3 导入数据**页面上,配置以下源数据信息: + + - **包含架构文件**:对于示例数据,选择**是**。 + - **数据格式**:选择 **SQL**。 + - **文件夹 URI** 或**文件 URI**:输入示例数据 URI `s3://tidbcloud-sample-data/data-ingestion/`。 + - **存储桶访问**:对于示例数据,你只能使用 Role ARN 访问其存储桶。对于你自己的数据,你可以使用 AWS 访问密钥或 Role ARN 访问你的存储桶。 + - **AWS Role ARN**:输入 `arn:aws:iam::801626783489:role/import-sample-access`。 + - **AWS 访问密钥**:对于示例数据,跳过此选项。 + +4. 点击**连接** > **开始导入**。 + +
+
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 GCS 导入数据**页面上,配置以下源数据信息: + + - **包含架构文件**:对于示例数据,选择**是**。 + - **数据格式**:选择 **SQL**。 + - **文件夹 URI** 或**文件 URI**:输入示例数据 URI `gs://tidbcloud-samples-us-west1/`。 + - **存储桶访问**:你可以使用 GCS IAM 角色访问你的存储桶。更多信息,请参见[配置 GCS 访问](/tidb-cloud/dedicated-external-storage.md#configure-gcs-access)。 + + 如果存储桶的区域与你的集群不同,请确认跨区域合规性。 + +4. 点击**连接** > **开始导入**。 + +
+ +
+ +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**。 + +3. 在**从 Azure Blob Storage 导入数据**页面上,配置以下源数据信息: + + - **包含架构文件**:对于示例数据,选择**是**。 + - **数据格式**:选择 **SQL**。 + - **文件夹 URI**:输入示例数据 URI `https://tcidmsampledata.blob.core.windows.net/sql/`。 + - **SAS 令牌**: + - 对于示例数据,使用以下 **SAS 令牌**:`sv=2015-04-05&ss=b&srt=co&sp=rl&se=2099-03-01T00%3A00%3A01.0000000Z&sig=cQHvaofmVsUJEbgyf4JFkAwTJGsFOmbQHx03GvVMrNc%3D`。 + - 对于你自己的数据,你可以使用 SAS 令牌访问你的 Azure Blob Storage。更多信息,请参见[配置 Azure Blob Storage 访问](/tidb-cloud/dedicated-external-storage.md#configure-azure-blob-storage-access)。 + + 如果存储账户的区域与你的集群不同,请确认跨区域合规性。 + +4. 点击**连接** > **开始导入**。 + +
+
+ +当数据导入进度显示**已完成**时,你已成功将示例数据和数据库架构导入到 TiDB Cloud 中的数据库。 + +连接到集群后,你可以在终端中运行一些查询来检查结果,例如: + +1. 获取起始站为 "12th & U St NW" 的行程记录: + + ```sql + use bikeshare; + ``` + + ```sql + select * from `trips` where start_station_name='12th & U St NW' limit 10; + ``` + + ```sql + +-----------------+---------------+---------------------+---------------------+--------------------+------------------+-------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | ride_id | rideable_type | started_at | ended_at | start_station_name | start_station_id | end_station_name | end_station_id | start_lat | start_lng | end_lat | end_lng | member_casual | + +-----------------+---------------+---------------------+---------------------+--------------------+------------------+-------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | E291FF5018 | classic_bike | 2021-01-02 11:12:38 | 2021-01-02 11:23:47 | 12th & U St NW | 31268 | 7th & F St NW / National Portrait Gallery | 31232 | 38.916786 | -77.02814 | 38.89728 | -77.022194 | member | + | E76F3605D0 | docked_bike | 2020-09-13 00:44:11 | 2020-09-13 00:59:38 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | casual | + | FFF0B75414 | docked_bike | 2020-09-28 16:47:53 | 2020-09-28 16:57:30 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | casual | + | C3F2C16949 | docked_bike | 2020-09-13 00:42:03 | 2020-09-13 00:59:43 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | casual | + | 1C7EC91629 | docked_bike | 2020-09-28 16:47:49 | 2020-09-28 16:57:26 | 12th & U St NW | 31268 | 17th St & Massachusetts Ave NW | 31267 | 38.916786 | -77.02814 | 38.908142 | -77.03836 | member | + | A3A38BCACA | classic_bike | 2021-01-14 09:52:53 | 2021-01-14 10:00:51 | 12th & U St NW | 31268 | 10th & E St NW | 31256 | 38.916786 | -77.02814 | 38.895912 | -77.02606 | member | + | EC4943257E | electric_bike | 2021-01-28 10:06:52 | 2021-01-28 10:16:28 | 12th & U St NW | 31268 | 10th & E St NW | 31256 | 38.916843 | -77.028206 | 38.89607 | -77.02608 | member | + | D4070FBFA7 | classic_bike | 2021-01-12 09:50:51 | 2021-01-12 09:59:41 | 12th & U St NW | 31268 | 10th & E St NW | 31256 | 38.916786 | -77.02814 | 38.895912 | -77.02606 | member | + | 6EABEF3CAB | classic_bike | 2021-01-09 15:00:43 | 2021-01-09 15:18:30 | 12th & U St NW | 31268 | 1st & M St NE | 31603 | 38.916786 | -77.02814 | 38.905697 | -77.005486 | member | + | 2F5CC89018 | electric_bike | 2021-01-02 01:47:07 | 2021-01-02 01:58:29 | 12th & U St NW | 31268 | 3rd & H St NE | 31616 | 38.916836 | -77.02815 | 38.90074 | -77.00219 | member | + +-----------------+---------------+---------------------+---------------------+--------------------+------------------+-------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + ``` + +2. 获取电动自行车的行程记录: + + ```sql + use bikeshare; + ``` + + ```sql + select * from `trips` where rideable_type="electric_bike" limit 10; + ``` + + ```sql + +------------------+---------------+---------------------+---------------------+----------------------------------------+------------------+-------------------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | ride_id | rideable_type | started_at | ended_at | start_station_name | start_station_id | end_station_name | end_station_id | start_lat | start_lng | end_lat | end_lng | member_casual | + +------------------+---------------+---------------------+---------------------+----------------------------------------+------------------+-------------------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + | AF15B12839DA4367 | electric_bike | 2021-01-23 14:50:46 | 2021-01-23 14:59:55 | Columbus Circle / Union Station | 31623 | 15th & East Capitol St NE | 31630 | 38.8974 | -77.00481 | 38.890 | 76.98354 | member | + | 7173E217338C4752 | electric_bike | 2021-01-15 08:28:38 | 2021-01-15 08:33:49 | 37th & O St NW / Georgetown University | 31236 | 34th St & Wisconsin Ave NW | 31226 | 38.907825 | -77.071655 | 38.916 | -77.0683 | member | + | E665505ED621D1AB | electric_bike | 2021-01-05 13:25:47 | 2021-01-05 13:35:58 | N Lynn St & Fairfax Dr | 31917 | 34th St & Wisconsin Ave NW | 31226 | 38.89359 | -77.07089 | 38.916 | 77.06829 | member | + | 646AFE266A6375AF | electric_bike | 2021-01-16 00:08:10 | 2021-01-16 00:35:58 | 7th St & Massachusetts Ave NE | 31647 | 34th St & Wisconsin Ave NW | 31226 | 38.892235 | -76.996025 | 38.91 | 7.068245 | member | + | 40CDDA0378E45736 | electric_bike | 2021-01-03 11:14:50 | 2021-01-03 11:26:04 | N Lynn St & Fairfax Dr | 31917 | 34th St & Wisconsin Ave NW | 31226 | 38.893734 | -77.07096 | 38.916 | 7.068275 | member | + | E0A7DDB0CE680C01 | electric_bike | 2021-01-05 18:18:17 | 2021-01-05 19:04:11 | Maine Ave & 7th St SW | 31609 | Smithsonian-National Mall / Jefferson Dr & 12th St SW | 31248 | 38.878727 | -77.02304 | 38.8 | 7.028755 | casual | + | 71BDF35029AF0039 | electric_bike | 2021-01-07 10:23:57 | 2021-01-07 10:59:43 | 10th & K St NW | 31263 | East West Hwy & Blair Mill Rd | 32019 | 38.90279 | -77.02633 | 38.990 | 77.02937 | member | + | D5EACDF488260A61 | electric_bike | 2021-01-13 20:57:23 | 2021-01-13 21:04:19 | 8th & H St NE | 31661 | 15th & East Capitol St NE | 31630 | 38.89985 | -76.994835 | 38.88 | 76.98345 | member | + | 211D449363FB7EE3 | electric_bike | 2021-01-15 17:22:02 | 2021-01-15 17:35:49 | 7th & K St NW | 31653 | 15th & East Capitol St NE | 31630 | 38.90216 | -77.0211 | 38.88 | 76.98357 | casual | + | CE667578A7291701 | electric_bike | 2021-01-15 16:55:12 | 2021-01-15 17:38:26 | East West Hwy & 16th St | 32056 | East West Hwy & Blair Mill Rd | 32019 | 38.995674 | -77.03868 | 38.990 | 77.02953 | casual | + +------------------+---------------+---------------------+---------------------+----------------------------------------+------------------+-------------------------------------------------------+----------------+-----------+------------+-----------+------------+---------------+ + ``` diff --git a/tidb-cloud/import-with-mysql-cli-serverless.md b/tidb-cloud/import-with-mysql-cli-serverless.md new file mode 100644 index 000000000000..e48214eed080 --- /dev/null +++ b/tidb-cloud/import-with-mysql-cli-serverless.md @@ -0,0 +1,111 @@ +--- +title: 通过 MySQL CLI 导入数据到 TiDB Cloud Serverless +summary: 了解如何通过 MySQL CLI 导入数据到 TiDB Cloud Serverless。 +--- + +# 通过 MySQL CLI 导入数据到 TiDB Cloud Serverless + +本文介绍如何通过 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)将数据导入到 TiDB Cloud Serverless。你可以从 SQL 文件或 CSV 文件导入数据。以下各节提供从每种类型文件导入数据的分步说明。 + +## 前提条件 + +在通过 MySQL CLI 导入数据到 TiDB Cloud Serverless 之前,你需要满足以下前提条件: + +- 你可以访问你的 TiDB Cloud Serverless 集群。如果没有,请按照[构建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)中的说明创建一个。 +- 在本地计算机上安装 MySQL CLI。 + +## 步骤 1. 连接到你的 TiDB Cloud Serverless 集群 + +连接到你的 TiDB 集群。 + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示连接对话框。 + +3. 确保连接对话框中的配置与你的操作环境匹配。 + + - **连接类型**设置为 `Public`。 + - **连接方式**设置为 `MySQL CLI`。 + - **操作系统**与你的环境匹配。 + +4. 点击**生成密码**创建随机密码。 + + > **提示:** + > + > 如果你之前已经创建了密码,可以使用原始密码或点击**重置密码**生成新密码。 + +## 步骤 2. 定义表并插入示例数据 + +在导入数据之前,你需要准备表结构并向其中插入实际的示例数据。以下是一个可用于创建表和插入示例数据的 SQL 文件(`product_data.sql`)示例: + +```sql +-- 在你的 TiDB 数据库中创建表 +CREATE TABLE products ( + product_id INT PRIMARY KEY, + product_name VARCHAR(255), + price DECIMAL(10, 2) +); + +-- 向表中插入示例数据 +INSERT INTO products (product_id, product_name, price) VALUES + (1, 'Laptop', 999.99), + (2, 'Smartphone', 499.99), + (3, 'Tablet', 299.99); +``` + +## 步骤 3. 从 SQL 或 CSV 文件导入数据 + +你可以从 SQL 文件或 CSV 文件导入数据。以下各节提供从每种类型文件导入数据的分步说明。 + + +
+ +执行以下操作从 SQL 文件导入数据: + +1. 提供包含要导入数据的实际 SQL 文件(例如 `product_data.sql`)。此 SQL 文件必须包含带有实际数据的 `INSERT` 语句。 + +2. 使用以下命令从 SQL 文件导入数据: + + ```bash + mysql --comments --connect-timeout 150 -u '' -h -P 4000 -D test --ssl-mode=VERIFY_IDENTITY --ssl-ca= -p < product_data.sql + ``` + +> **注意:** +> +> 此处使用的默认数据库名称是 `test`,你可以手动创建自己的数据库或在 SQL 文件中使用 `CREATE DATABASE` 命令。 + +
+
+ +执行以下操作从 CSV 文件导入数据: + +1. 在 TiDB 中创建与你的数据导入需求相匹配的数据库和架构。 + +2. 提供包含要导入数据的示例 CSV 文件(例如 `product_data.csv`)。以下是 CSV 文件的示例: + + **product_data.csv:** + + ```csv + product_id,product_name,price + 4,Laptop,999.99 + 5,Smartphone,499.99 + 6,Tablet,299.99 + ``` + +3. 使用以下命令从 CSV 文件导入数据: + + ```bash + mysql --comments --connect-timeout 150 -u '' -h -P 4000 -D test --ssl-mode=VERIFY_IDENTITY --ssl-ca= -p -e "LOAD DATA LOCAL INFILE '' INTO TABLE products + FIELDS TERMINATED BY ',' + LINES TERMINATED BY '\n' + IGNORE 1 LINES (product_id, product_name, price);" + ``` + + 确保将路径、表名(本例中为 `products`)、``、``、``、``、`` 和其他占位符替换为你的实际信息,并根据需要将示例 CSV 数据替换为你的实际数据集。 + +> **注意:** +> +> 有关 `LOAD DATA LOCAL INFILE` 的更多语法详情,请参见 [`LOAD DATA`](/sql-statements/sql-statement-load-data.md)。 + +
+
diff --git a/tidb-cloud/import-with-mysql-cli.md b/tidb-cloud/import-with-mysql-cli.md new file mode 100644 index 000000000000..d49b4851b2be --- /dev/null +++ b/tidb-cloud/import-with-mysql-cli.md @@ -0,0 +1,107 @@ +--- +title: 使用 MySQL CLI 导入数据到 TiDB Cloud Dedicated +summary: 了解如何使用 MySQL CLI 导入数据到 TiDB Cloud Dedicated。 +--- + +# 使用 MySQL CLI 导入数据到 TiDB Cloud Dedicated + +本文档介绍如何使用 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html)将数据导入到 TiDB Cloud Dedicated。你可以从 SQL 文件或 CSV 文件导入数据。以下部分提供了从每种类型文件导入数据的分步说明。 + +## 前提条件 + +在使用 MySQL CLI 向 TiDB Cloud Dedicated 导入数据之前,你需要满足以下前提条件: + +- 你可以访问你的 TiDB Cloud Dedicated 集群。如果没有,请按照[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)中的说明创建一个。 +- 在本地计算机上安装 MySQL CLI。 + +## 步骤 1. 连接到你的 TiDB Cloud Dedicated 集群 + +连接到你的 TiDB 集群。 + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 在左侧导航栏中,点击**设置** > **网络**。 + +3. 在**网络**页面的 **IP 访问列表**区域,点击**添加 IP 地址**。 + +4. 在对话框中,选择**允许从任何地方访问**,然后点击**确认**。 + +5. 在右上角,点击**连接**打开连接信息对话框。 + + 有关如何获取连接字符串的更多详细信息,请参见[通过公共连接连接到 TiDB Cloud Dedicated](/tidb-cloud/connect-via-standard-connection.md)。 + +## 步骤 2. 定义表并插入示例数据 + +在导入数据之前,你需要准备表结构并向其中插入实际的示例数据。以下是一个可用于创建表和插入示例数据的 SQL 文件(`product_data.sql`)示例: + +```sql +-- 在你的 TiDB 数据库中创建表 +CREATE TABLE products ( + product_id INT PRIMARY KEY, + product_name VARCHAR(255), + price DECIMAL(10, 2) +); + +-- 向表中插入示例数据 +INSERT INTO products (product_id, product_name, price) VALUES + (1, 'Laptop', 999.99), + (2, 'Smartphone', 499.99), + (3, 'Tablet', 299.99); +``` + +## 步骤 3. 从 SQL 或 CSV 文件导入数据 + +你可以从 SQL 文件或 CSV 文件导入数据。以下部分提供了从每种类型文件导入数据的分步说明。 + + +
+ +按照以下步骤从 SQL 文件导入数据: + +1. 提供一个包含要导入数据的实际 SQL 文件(例如,`product_data.sql`)。此 SQL 文件必须包含带有实际数据的 `INSERT` 语句。 + +2. 使用以下命令从 SQL 文件导入数据: + + ```bash + mysql --comments --connect-timeout 150 -u '' -h -P 4000 -D test --ssl-mode=VERIFY_IDENTITY --ssl-ca= -p < product_data.sql + ``` + +> **注意:** +> +> 这里使用的默认数据库名称是 `test`,你可以手动创建自己的数据库或在 SQL 文件中使用 `CREATE DATABASE` 命令。 + +
+
+ +按照以下步骤从 CSV 文件导入数据: + +1. 在 TiDB 中创建与你的数据导入需求相匹配的数据库和架构。 + +2. 提供一个包含要导入数据的示例 CSV 文件(例如,`product_data.csv`)。以下是 CSV 文件的示例: + + **product_data.csv:** + + ```csv + product_id,product_name,price + 4,Laptop,999.99 + 5,Smartphone,499.99 + 6,Tablet,299.99 + ``` + +3. 使用以下命令从 CSV 文件导入数据: + + ```bash + mysql --comments --connect-timeout 150 -u '' -h -P 4000 -D test --ssl-mode=VERIFY_IDENTITY --ssl-ca= -p -e "LOAD DATA LOCAL INFILE '' INTO TABLE products + FIELDS TERMINATED BY ',' + LINES TERMINATED BY '\n' + IGNORE 1 LINES (product_id, product_name, price);" + ``` + +4. 确保将路径、表名(本例中为 `products`)、``、``、``、``、`` 和其他占位符替换为你的实际信息,并根据需要将示例 CSV 数据替换为你的实际数据集。 + +> **注意:** +> +> 有关 `LOAD DATA LOCAL INFILE` 的更多语法详情,请参见 [`LOAD DATA`](/sql-statements/sql-statement-load-data.md)。 + +
+
diff --git a/tidb-cloud/index-insight.md b/tidb-cloud/index-insight.md new file mode 100644 index 000000000000..d20b3b1e36d7 --- /dev/null +++ b/tidb-cloud/index-insight.md @@ -0,0 +1,170 @@ +--- +title: 索引洞察(Beta) +summary: 了解如何使用 TiDB Cloud 中的索引洞察功能并获取慢查询的索引建议。 +--- + +# 索引洞察(Beta) + +TiDB Cloud 中的索引洞察(beta)功能通过为未有效使用索引的慢查询提供索引建议,提供了强大的查询性能优化能力。本文档将指导您完成启用和有效使用索引洞察功能的步骤。 + +> **注意:** +> +> 索引洞察目前处于 beta 阶段,仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +## 简介 + +索引洞察功能为您提供以下好处: + +- 增强查询性能:索引洞察识别慢查询并为其建议适当的索引,从而加快查询执行速度,减少响应时间,提升用户体验。 +- 成本效益:通过使用索引洞察优化查询性能,减少了对额外计算资源的需求,使您能够更有效地使用现有基础设施。这可能带来运营成本的节省。 +- 简化优化过程:索引洞察简化了索引改进的识别和实施过程,消除了手动分析和猜测的需要。因此,您可以通过准确的索引建议节省时间和精力。 +- 提高应用效率:通过使用索引洞察优化数据库性能,运行在 TiDB Cloud 上的应用程序可以处理更大的工作负载并同时服务更多用户,这使应用程序的扩展操作更加高效。 + +## 使用方法 + +本节介绍如何启用索引洞察功能并获取慢查询的推荐索引。 + +### 开始之前 + +在启用索引洞察功能之前,请确保您已创建 TiDB Cloud Dedicated 集群。如果您还没有,请按照[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)中的步骤创建一个。 + +### 步骤 1:启用索引洞察 + +1. 导航到 TiDB Cloud Dedicated 集群的[**诊断**](/tidb-cloud/tune-performance.md#查看诊断页面)页面。 + +2. 点击**索引洞察 BETA** 标签。将显示**索引洞察概览**页面。 + +3. 要使用索引洞察功能,您需要创建一个专用的 SQL 用户,该用户用于触发该功能并接收索引建议。以下 SQL 语句创建一个具有所需权限的新 SQL 用户,包括 `information_schema` 和 `mysql` 的读取权限,以及所有数据库的 `PROCESS` 和 `REFERENCES` 权限。将 `'index_insight_user'` 和 `'random_password'` 替换为您的值。 + + ```sql + CREATE user 'index_insight_user'@'%' IDENTIFIED by 'random_password'; + GRANT SELECT ON information_schema.* TO 'index_insight_user'@'%'; + GRANT SELECT ON mysql.* TO 'index_insight_user'@'%'; + GRANT PROCESS, REFERENCES ON *.* TO 'index_insight_user'@'%'; + FLUSH PRIVILEGES; + ``` + + > **注意:** + > + > 要连接到您的 TiDB Cloud Dedicated 集群,请参见[连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/connect-to-tidb-cluster.md)。 + +4. 输入在前面步骤中创建的 SQL 用户的用户名和密码。然后,点击**激活**开始激活过程。 + +### 步骤 2:手动触发索引洞察 + +要获取慢查询的索引建议,您可以通过点击**索引洞察概览**页面右上角的**检查**来手动触发索引洞察功能。 + +然后,该功能开始扫描过去三小时的慢查询。扫描完成后,它会根据分析提供索引建议列表。 + +### 步骤 3:查看索引建议 + +要查看特定索引建议的详细信息,请从列表中点击洞察。将显示**索引洞察详情**页面。 + +在此页面上,您可以找到索引建议、相关慢查询、执行计划和相关指标。这些信息可帮助您更好地理解性能问题并评估实施索引建议的潜在影响。 + +### 步骤 4:实施索引建议 + +在实施索引建议之前,您需要先从**索引洞察详情**页面审查和评估建议。 + +要实施索引建议,请按照以下步骤操作: + +1. 评估建议的索引对现有查询和工作负载的影响。 +2. 考虑与索引实施相关的存储需求和潜在权衡。 +3. 使用适当的数据库管理工具在相关表上创建索引建议。 +4. 实施索引后监控性能以评估改进情况。 + +## 最佳实践 + +本节介绍使用索引洞察功能的一些最佳实践。 + +### 定期触发索引洞察 + +为了维护优化的索引,建议定期触发索引洞察功能,例如每天一次,或在查询或数据库架构发生重大变化时触发。 + +### 实施索引前分析影响 + +在实施索引建议之前,分析对查询执行计划、磁盘空间和任何相关权衡的潜在影响。优先实施能提供最显著性能改进的索引。 + +### 监控性能 + +实施索引建议后定期监控查询性能。这有助于您确认改进情况并在必要时进行进一步调整。 + +## 常见问题 + +本节列出了有关索引洞察功能的一些常见问题。 + +### 如何停用索引洞察? + +要停用索引洞察功能,请执行以下步骤: + +1. 在**索引洞察概览**页面的右上角,点击**设置**。将显示**索引洞察设置**页面。 +2. 点击**停用**。将显示确认对话框。 +3. 点击**确定**确认停用。 + + 停用索引洞察功能后,所有索引建议都将从**索引洞察概览**页面中删除。但是,为该功能创建的 SQL 用户不会被删除。您可以手动删除该 SQL 用户。 + +### 停用索引洞察后如何删除 SQL 用户? + +停用索引洞察功能后,您可以执行 `DROP USER` 语句删除为该功能创建的 SQL 用户。以下是一个示例。将 `'username'` 替换为您的值。 + +```sql +DROP USER 'username'; +``` + +### 为什么在激活或检查期间显示 `invalid user or password` 消息? + +`invalid user or password` 消息通常在系统无法验证您提供的凭据时提示。此问题可能由各种原因引起,例如用户名或密码不正确,或用户账户已过期或被锁定。 + +要解决此问题,请执行以下步骤: + +1. 验证您的凭据:确保您提供的用户名和密码正确。注意区分大小写。 +2. 检查账户状态:确保您的用户账户处于活动状态,未过期或被锁定。您可以通过联系系统管理员或相关支持渠道确认这一点。 +3. 创建新的 SQL 用户:如果通过前面的步骤未解决此问题,您可以使用以下语句创建新的 SQL 用户。将 `'index_insight_user'` 和 `'random_password'` 替换为您的值。 + + ```sql + CREATE user 'index_insight_user'@'%' IDENTIFIED by 'random_password'; + GRANT SELECT ON information_schema.* TO 'index_insight_user'@'%'; + GRANT SELECT ON mysql.* TO 'index_insight_user'@'%'; + GRANT PROCESS, REFERENCES ON *.* TO 'index_insight_user'@'%'; + FLUSH PRIVILEGES; + ``` + +如果在执行上述步骤后仍然遇到问题,建议联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +### 为什么在激活或检查期间显示 `no sufficient privileges` 消息? + +`no sufficient privileges` 消息通常在您提供的 SQL 用户缺少从索引洞察请求索引建议所需的权限时提示。 + +要解决此问题,请执行以下步骤: + +1. 检查用户权限:确认您的用户账户是否已被授予所需权限,包括 `information_schema` 和 `mysql` 的读取权限,以及所有数据库的 `PROCESS` 和 `REFERENCES` 权限。 + +2. 创建新的 SQL 用户:如果通过前面的步骤未解决此问题,您可以使用以下语句创建新的 SQL 用户。将 `'index_insight_user'` 和 `'random_password'` 替换为您的值。 + + ```sql + CREATE user 'index_insight_user'@'%' IDENTIFIED by 'random_password'; + GRANT SELECT ON information_schema.* TO 'index_insight_user'@'%'; + GRANT SELECT ON mysql.* TO 'index_insight_user'@'%'; + GRANT PROCESS, REFERENCES ON *.* TO 'index_insight_user'@'%'; + FLUSH PRIVILEGES; + ``` + +如果在执行上述步骤后仍然遇到问题,建议联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +### 为什么在使用索引洞察时显示 `operations may be too frequent` 消息? + +`operations may be too frequent` 消息通常在您超过索引洞察设置的速率或使用限制时提示。 + +要解决此问题,请执行以下步骤: + +1. 降低操作频率:如果您收到此消息,您需要降低对索引洞察的操作频率。 +2. 联系支持:如果问题仍然存在,请联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)并提供错误消息、您的操作以及任何其他相关信息的详细信息。 + +### 为什么在使用索引洞察时显示 `internal error` 消息? + +`internal error` 消息通常在系统遇到意外错误或问题时提示。此错误消息是通用的,不提供有关根本原因的详细信息。 + +要解决此问题,请执行以下步骤: + +1. 重试操作:刷新页面或重试操作。错误可能是临时的,可以通过简单的重试来解决。 +2. 联系支持:如果问题仍然存在,请联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)并提供错误消息、您的操作以及任何其他相关信息的详细信息。 diff --git a/tidb-cloud/integrate-tidbcloud-with-airbyte.md b/tidb-cloud/integrate-tidbcloud-with-airbyte.md new file mode 100644 index 000000000000..784639ceebbf --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-airbyte.md @@ -0,0 +1,111 @@ +--- +title: 将 TiDB Cloud 与 Airbyte 集成 +summary: 了解如何使用 Airbyte TiDB 连接器。 +--- + +# 将 TiDB Cloud 与 Airbyte 集成 + +[Airbyte](https://airbyte.com/) 是一个开源的数据集成引擎,用于构建提取、加载、转换(ELT)管道,并将您的数据整合到数据仓库、数据湖和数据库中。本文介绍如何将 Airbyte 作为源或目标连接到 TiDB Cloud。 + +## 部署 Airbyte + +您只需几个步骤就可以在本地部署 Airbyte。 + +1. 在您的工作空间上安装 [Docker](https://www.docker.com/products/docker-desktop)。 + +2. 克隆 Airbyte 源代码。 + + ```shell + git clone https://github.com/airbytehq/airbyte.git && \ + cd airbyte + ``` + +3. 使用 docker-compose 运行 Docker 镜像。 + + ```shell + docker-compose up + ``` + +当您看到 Airbyte 横幅时,您可以使用用户名(`airbyte`)和密码(`password`)访问 [http://localhost:8000](http://localhost:8000) 来访问用户界面。 + +``` +airbyte-server | ___ _ __ __ +airbyte-server | / | (_)____/ /_ __ __/ /____ +airbyte-server | / /| | / / ___/ __ \/ / / / __/ _ \ +airbyte-server | / ___ |/ / / / /_/ / /_/ / /_/ __/ +airbyte-server | /_/ |_/_/_/ /_.___/\__, /\__/\___/ +airbyte-server | /____/ +airbyte-server | -------------------------------------- +airbyte-server | Now ready at http://localhost:8000/ +airbyte-server | -------------------------------------- +``` + +## 设置 TiDB 连接器 + +无论将 TiDB 设置为源还是目标,步骤都是相同的。 + +1. 在侧边栏中点击**源**或**目标**,然后选择 TiDB 类型以创建新的 TiDB 连接器。 + +2. 填写以下参数。 + + - 主机:TiDB Cloud 集群的端点 + - 端口:数据库的端口 + - 数据库:您想要同步数据的数据库 + - 用户名:访问数据库的用户名 + - 密码:用户名的密码 + + 您可以从集群的连接对话框中获取参数值。要打开对话框,请转到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称以进入其概览页面,然后点击右上角的**连接**。 + +3. 启用 **SSL 连接**,并在 **JDBC URL 参数**中将 TLS 协议设置为 **TLSv1.2** 或 **TLSv1.3**。 + + > 注意: + > + > - TiDB Cloud 支持 TLS 连接。您可以在 **TLSv1.2** 和 **TLSv1.3** 中选择 TLS 协议,例如,`enabledTLSProtocols=TLSv1.2`。 + > - 如果您想通过 JDBC 禁用与 TiDB Cloud 的 TLS 连接,您需要在 JDBC URL 参数中特别将 useSSL 设置为 `false` 并关闭 SSL 连接,例如,`useSSL=false`。 + > - TiDB Cloud Serverless 仅支持 TLS 连接。 + +4. 点击**设置源**或**目标**以完成创建连接器。以下截图显示了将 TiDB 设置为源的配置。 + +![TiDB 源配置](/media/tidb-cloud/integration-airbyte-parameters.jpg) + +您可以使用任何源和目标的组合,例如从 TiDB 到 Snowflake,或从 CSV 文件到 TiDB。 + +有关 TiDB 连接器的更多详细信息,请参见 [TiDB 源](https://docs.airbyte.com/integrations/sources/tidb)和 [TiDB 目标](https://docs.airbyte.com/integrations/destinations/tidb)。 + +## 设置连接 + +设置好源和目标后,您可以构建和配置连接。 + +以下步骤使用 TiDB 作为源和目标。其他连接器可能有不同的参数。 + +1. 在侧边栏中点击**连接**,然后点击**新建连接**。 +2. 选择之前建立的源和目标。 +3. 转到**设置**连接面板,为连接创建一个名称,例如 `${source_name} - ${destination-name}`。 +4. 将**复制频率**设置为**每 24 小时**,这意味着连接每天复制一次数据。 +5. 将**目标命名空间**设置为**自定义格式**,并将**命名空间自定义格式**设置为 **test**,以将所有数据存储在 `test` 数据库中。 +6. 选择**同步模式**为**完全刷新 | 覆盖**。 + + > **提示:** + > + > TiDB 连接器支持[增量和完全刷新同步](https://airbyte.com/blog/understanding-data-replication-modes)。 + > + > - 在增量模式下,Airbyte 只读取自上次同步任务以来添加到源的记录。使用增量模式的第一次同步相当于完全刷新模式。 + > - 在完全刷新模式下,Airbyte 在每次同步任务中读取源中的所有记录并复制到目标。您可以在 Airbyte 中为每个名为**命名空间**的表单独设置同步模式。 + + ![设置连接](/media/tidb-cloud/integration-airbyte-connection.jpg) + +7. 将**规范化和转换**设置为**规范化表格数据**以使用默认规范化模式,或者您可以为您的任务设置 dbt 文件。有关规范化的更多信息,请参见[转换和规范化](https://docs.airbyte.com/operator-guides/transformation-and-normalization/transformations-with-dbt)。 +8. 点击**设置连接**。 +9. 建立连接后,点击**启用**以激活同步任务。您也可以点击**立即同步**立即同步。 + +![同步数据](/media/tidb-cloud/integration-airbyte-sync.jpg) + +## 限制 + +- TiDB 连接器无法使用 TiCDC 提供的变更数据捕获(CDC)功能。增量同步基于游标机制执行。 +- TiDB 目标在默认规范化模式下将 `timestamp` 类型转换为 `varchar` 类型。这是因为 Airbyte 在传输过程中将时间戳类型转换为字符串,而 TiDB 不支持 `cast ('2020-07-28 14:50:15+1:00' as timestamp)`。 +- 对于一些大型 ELT 任务,您需要增加 TiDB 中[事务限制](/develop/dev-guide-transaction-restraints.md#large-transaction-restrictions)的参数。 + +## 另请参阅 + +[使用 Airbyte 将数据从 TiDB Cloud 迁移到 Snowflake](https://www.pingcap.com/blog/using-airbyte-to-migrate-data-from-tidb-cloud-to-snowflake/)。 diff --git a/tidb-cloud/integrate-tidbcloud-with-aws-lambda.md b/tidb-cloud/integrate-tidbcloud-with-aws-lambda.md new file mode 100644 index 000000000000..d3ec3b42badd --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-aws-lambda.md @@ -0,0 +1,202 @@ +--- +title: 使用 AWS CloudFormation 将 TiDB Cloud Serverless 与 Amazon Lambda 集成 +summary: 逐步介绍如何将 TiDB Cloud Serverless 与 Amazon Lambda 和 CloudFormation 集成。 +--- + +# 使用 AWS CloudFormation 将 TiDB Cloud Serverless 与 Amazon Lambda 集成 + +本文档提供了一个分步指南,介绍如何使用 [AWS CloudFormation](https://aws.amazon.com/cloudformation/) 将云原生分布式 SQL 数据库 [TiDB Cloud Serverless](https://www.pingcap.com/tidb-cloud/) 与无服务器和事件驱动的计算服务 [AWS Lambda](https://aws.amazon.com/lambda/) 集成。通过将 TiDB Cloud Serverless 与 Amazon Lambda 集成,你可以通过 TiDB Cloud Serverless 和 AWS Lambda 利用微服务的可扩展性和成本效益。AWS CloudFormation 自动化了 AWS 资源的创建和管理,包括 Lambda 函数、API Gateway 和 Secrets Manager。 + +## 解决方案概述 + +在本指南中,你将创建一个包含以下组件的功能完整的在线书店: + +- AWS Lambda 函数:使用 Sequelize ORM 和 Fastify API 框架处理请求并从 TiDB Cloud Serverless 集群查询数据。 +- AWS Secrets Manager SDK:检索和管理 TiDB Cloud Serverless 集群的连接配置。 +- AWS API Gateway:处理 HTTP 请求路由。 +- TiDB Cloud Serverless:云原生分布式 SQL 数据库。 + +AWS CloudFormation 用于创建项目所需的资源,包括 Secrets Manager、API Gateway 和 Lambda 函数。 + +书店项目的结构如下: + +![AWS Lambda 结构概览](/media/develop/aws-lambda-structure-overview.png) + +## 前提条件 + +在开始之前,请确保你具备以下条件: + +- 一个可以访问以下 AWS 服务的 AWS 账户: + - [AWS CloudFormation](https://aws.amazon.com/cloudformation/) + - [Secrets Manager](https://aws.amazon.com/secrets-manager/) + - [API Gateway](https://aws.amazon.com/api-gateway/) + - [Lambda services](https://aws.amazon.com/lambda/) + - [S3](https://aws.amazon.com/s3/) + - [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) +- 一个 [TiDB Cloud](https://tidbcloud.com) 账户和一个 TiDB Cloud Serverless 集群。获取 TiDB Cloud Serverless 集群的连接信息: + + ![TiDB Cloud 连接信息](/media/develop/aws-lambda-tidbcloud-connection-info.png) + +- API 测试工具,如 [Postman](https://www.postman.com/) 和 [cURL](https://curl.se/)。本文档中的大多数示例使用 cURL。对于 Windows 用户,建议使用 Postman。 +- 将项目的[最新发布资产](https://github.com/pingcap/TiDB-Lambda-integration/releases/latest)下载到本地计算机,其中包括 `cloudformation_template.yml` 和 `cloudformation_template.json` 文件。 + +> **注意:** +> +> - 创建 AWS 资源时,建议使用 `us-east-1` 作为集群区域。这是因为此演示中的 Lambda 函数代码将区域硬编码为 `us-east-1`,并且代码包存储在 `us-east-1` 区域。 +> - 如果你使用不同的区域,需要按照以下说明修改 Lambda 函数代码,重新构建它,并将代码包上传到你自己的 S3 存储桶。 + +
+如果使用 us-east-1 以外的区域,请修改并重新构建 Lambda 函数代码 + +如果你使用 `us-east-1` 作为集群区域,请跳过本节并转到[步骤 1:使用 AWS CloudFormation 设置项目](#步骤-1-使用-aws-cloudformation-设置书店项目)。 + +如果你使用 `us-east-1` 以外的其他 AWS 区域来创建 AWS 资源,则需要修改 Lambda 函数代码,重新构建它,并将代码包上传到你自己的 S3 存储桶。 + +为避免本地开发环境问题,建议使用云原生开发环境,如 [Gitpod](https://www.gitpod.io/)。 + +要重新构建代码包并将其上传到你自己的 S3 存储桶,请执行以下操作: + +1. 初始化开发环境。 + + - 打开 [Gitpod](https://gitpod.io/#/https://github.com/pingcap/TiDB-Lambda-integration) 工作区并使用你的 GitHub 账户登录。 + +2. 修改 Lambda 函数代码。 + + 1. 在左侧边栏中打开 `aws-lambda-cloudformation/src/secretManager.ts` 文件。 + 2. 找到第 22 行,然后修改 `region` 变量以匹配你自己的区域。 + +3. 重新构建代码包。 + + 1. 安装依赖项。 + + 1. 在 Gitpod 中打开终端。 + 2. 进入工作目录: + + ```shell + cd aws-lambda-cloudformation + ``` + + 3. 安装依赖项: + + ```shell + yarn + ``` + + 2. 重新构建代码包。 + + 1. 构建代码包。 + + ```shell + yarn build + ``` + + 2. 检查 `aws-lambda-cloudformation/dist/index.zip` 文件。 + 3. 右键点击 `index.zip` 文件并选择**下载**。 + +4. 将重新构建的代码包上传到你自己的 S3 存储桶。 + + 1. 访问 AWS 管理控制台中的 [S3 服务](https://console.aws.amazon.com/s3)。 + 2. 在你选择的区域中创建一个新的存储桶。 + 3. 将 `index.zip` 文件上传到存储桶。 + 4. 记下 S3 存储桶名称和区域,以供后续使用。 + +
+ +## 步骤 1. 使用 AWS CloudFormation 设置书店项目 + +要使用 AWS CloudFormation 设置书店项目,请执行以下操作: + +1. 导航到 AWS 管理控制台并访问 [AWS CloudFormation 服务](https://console.aws.amazon.com/cloudformation)。 +2. 点击**创建堆栈** > **使用新资源(标准)**。 +3. 在**创建堆栈**页面,完成堆栈创建过程。 + + 1. 在**前提条件**区域,选择**选择现有模板**。 + 2. 在**指定模板**区域,选择**上传模板文件**,点击**选择文件**上传模板文件(YAML 或 JSON),然后点击**下一步**。 + + 如果你还没有该文件,请从 [GitHub](https://github.com/pingcap/TiDB-Lambda-integration/releases/latest) 下载。该文件包含用于创建项目所需资源的 AWS CloudFormation 模板。 + + ![创建堆栈](/media/develop/aws-lambda-cf-create-stack.png) + + 3. 指定堆栈详细信息。 + + - 如果你使用 `us-east-1` 作为集群区域,请按照以下截图填写字段: + + ![指定 AWS Lambda 堆栈详细信息](/media/develop/aws-lambda-cf-stack-config.png) + + - **Stack name**:输入堆栈名称。 + - **S3Bucket**:输入存储 zip 文件的 S3 存储桶。 + - **S3Key**:输入 S3 密钥。 + - **TiDBDatabase**:输入 TiDB Cloud 集群名称。 + - **TiDBHost**:输入用于访问 TiDB Cloud 数据库的主机 URL。输入 `localhost`。 + - **TiDBPassword**:输入用于访问 TiDB Cloud 数据库的密码。 + - **TiDBPort**:输入用于访问 TiDB Cloud 数据库的端口。 + - **TiDBUser**:输入用于访问 TiDB Cloud 数据库的用户名。 + + - 如果你使用 `us-east-1` 以外的其他 AWS 区域,请按照以下步骤操作: + + 1. 参考[如果使用 `us-east-1` 以外的区域,请修改并重新构建 Lambda 函数代码](#前提条件)修改 Lambda 函数代码,重新构建它,并将代码包上传到你自己的 S3 存储桶。 + 2. 在堆栈详细信息字段中,根据你自己的配置在 `S3Bucket` 和 `S3Key` 参数中指定 S3 存储桶名称和区域。 + 3. 按照上述截图填写其他字段。 + + 4. 配置堆栈选项。你可以使用默认配置。 + + ![配置堆栈选项](/media/develop/aws-lambda-cf-stack-config-option.png) + + 5. 检查并创建堆栈。 + + ![检查并创建堆栈](/media/develop/aws-lambda-cf-stack-config-review.png) + +## 步骤 2. 使用书店项目 + +堆栈创建完成后,你可以按照以下方式使用项目: + +1. 在 AWS 管理控制台中访问 [API Gateway 服务](https://console.aws.amazon.com/apigateway),点击 `TiDBCloudApiGatewayV2` API,然后在左侧窗格中点击 **API: TiDBCloudApiGatewayV2**。 + +2. 从**概览**页面复制 `调用 URL`。此 URL 作为 API 端点。 + + ![API Gateway 调用 URL](/media/develop/aws-lambda-get-apigateway-invoke-url.png) + +3. 使用 API 测试工具(如 Postman 和 cURL)测试 API: + + - 初始化模拟图书: + + ```shell + curl -X POST -H "Content-Type: application/json" -d '{"count":100}' https:///book/init + ``` + + - 获取所有图书: + + ```shell + curl https:///book + ``` + + - 通过图书 ID 获取图书: + + ```shell + curl https:///book/ + ``` + + - 创建图书: + + ```shell + curl -X POST -H "Content-Type: application/json" -d '{ "title": "Book Title", "type": "Test", "publishAt": "2022-12-15T21:01:49.000Z", "stock": 123, "price": 12.34, "authors": "Test Test" }' https:///book + ``` + + - 更新图书: + + ```shell + curl -X PUT -H "Content-Type: application/json" -d '{ "title": "Book Title(updated)" }' https:///book/ + ``` + + - 删除图书: + + ```shell + curl -X DELETE https:///book/ + ``` + +## 步骤 3. 清理资源 + +为避免不必要的费用,请清理所有已创建的资源。 + +1. 访问 [AWS 管理控制台](https://console.aws.amazon.com/cloudformation)。 +2. 删除你创建的 AWS CloudFormation 堆栈。 diff --git a/tidb-cloud/integrate-tidbcloud-with-cloudflare.md b/tidb-cloud/integrate-tidbcloud-with-cloudflare.md new file mode 100644 index 000000000000..00f7dea578dc --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-cloudflare.md @@ -0,0 +1,117 @@ +--- +title: 将 TiDB Cloud 与 Cloudflare 集成 +summary: 了解如何将 Cloudflare Workers 与 TiDB Cloud 一起部署。 +--- + +# 将 TiDB Cloud 与 Cloudflare Workers 集成 + +[Cloudflare Workers](https://workers.cloudflare.com/) 是一个允许您响应特定事件(如 HTTP 请求或数据库更改)运行代码的平台。Cloudflare Workers 易于使用,可用于构建各种应用程序,包括自定义 API、无服务器函数和微服务。它特别适用于需要低延迟性能或需要快速扩展的应用程序。 + +由于 Cloudflare Workers 运行在 V8 引擎上,无法直接建立 TCP 连接,您可能会发现从 Cloudflare Workers 连接到 TiDB Cloud 比较困难。您可以使用 [TiDB Cloud 无服务器驱动](/tidb-cloud/serverless-driver.md)通过 HTTP 连接帮助您连接到 Cloudflare Workers。 + +本文档将逐步说明如何使用 TiDB Cloud 无服务器驱动连接到 Cloudflare Workers。 + +> **注意:** +> +> TiDB Cloud 无服务器驱动只能在 TiDB Cloud Serverless 中使用。 + +## 开始之前 + +在尝试本文中的步骤之前,您需要准备以下内容: + +- TiDB Cloud 账号和 TiDB Cloud 上的 TiDB Cloud Serverless 集群。更多详情,请参阅 [TiDB Cloud 快速入门](/tidb-cloud/tidb-cloud-quickstart.md#step-1-create-a-tidb-cluster)。 +- [Cloudflare Workers 账号](https://dash.cloudflare.com/login)。 +- 已安装 [npm](https://docs.npmjs.com/about-npm)。 + +## 步骤 1:设置 Wrangler + +[Wrangler](https://developers.cloudflare.com/workers/wrangler/) 是官方的 Cloudflare Worker CLI。您可以使用它来生成、构建、预览和发布您的 Workers。 + +1. 安装 Wrangler: + + ``` + npm install wrangler + ``` + +2. 要验证 Wrangler,请运行 wrangler login: + + ``` + wrangler login + ``` + +3. 使用 Wrangler 创建一个 worker 项目: + + ``` + wrangler init tidb-cloud-cloudflare + ``` + +4. 在终端中,您将被问到一系列与项目相关的问题。对所有问题选择默认值。 + +## 步骤 2:安装无服务器驱动 + +1. 进入您的项目目录: + + ``` + cd tidb-cloud-cloudflare + ``` + +2. 使用 npm 安装无服务器驱动: + + ``` + npm install @tidbcloud/serverless + ``` + + 这会在 `package.json` 中添加无服务器驱动依赖。 + +## 步骤 3:开发 Cloudflare Worker 函数 + +您需要根据需要修改 `src/index.ts`。 + +例如,如果您想显示所有数据库,可以使用以下代码: + +```ts +import { connect } from '@tidbcloud/serverless' + + +export interface Env { + DATABASE_URL: string; +} + +export default { + async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { + const conn = connect({url:env.DATABASE_URL}) + const resp = await conn.execute("show databases") + return new Response(JSON.stringify(resp)); + }, +}; +``` + +## 步骤 4:在环境中设置 DATABASE_URL + +`DATABASE_URL` 遵循 `mysql://username:password@host/database` 格式。您可以使用 wrangler cli 设置环境变量: + +``` +wrangler secret put +``` + +您也可以通过 Cloudflare Workers 仪表板编辑 `DATABASE_URL` 密钥。 + +## 步骤 5:发布到 Cloudflare Workers + +现在您已准备好部署到 Cloudflare Workers。 + +在您的项目目录中,运行以下命令: + +``` +npx wrangler publish +``` + +## 步骤 6:尝试您的 Cloudflare Workers + +1. 转到 [Cloudflare 仪表板](https://dash.cloudflare.com)找到您的 worker。您可以在概览页面上找到您的 worker 的 URL。 + +2. 访问该 URL,您将获得结果。 + +## 示例 + +请参阅 [Cloudflare Workers 示例](https://github.com/tidbcloud/car-sales-insight/tree/main/examples/cloudflare-workers)。 diff --git a/tidb-cloud/integrate-tidbcloud-with-dbt.md b/tidb-cloud/integrate-tidbcloud-with-dbt.md new file mode 100644 index 000000000000..541d3d422943 --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-dbt.md @@ -0,0 +1,355 @@ +--- +title: 将 TiDB Cloud 与 dbt 集成 +summary: 了解 dbt 在 TiDB Cloud 中的使用场景。 +--- + +# 将 TiDB Cloud 与 dbt 集成 + +[数据构建工具 (dbt)](https://www.getdbt.com/) 是一个流行的开源数据转换工具,可帮助分析工程师通过 SQL 语句转换其数据仓库中的数据。通过 [dbt-tidb](https://github.com/pingcap/dbt-tidb) 插件,使用 TiDB Cloud 的分析工程师可以直接通过 SQL 创建表单和匹配数据,而无需考虑创建表或视图的过程。 + +本文档介绍如何将 dbt 与 TiDB Cloud 一起使用,以一个 dbt 项目为例。 + +## 步骤 1:安装 dbt 和 dbt-tidb + +您可以使用一个命令安装 dbt 和 dbt-tidb。在以下命令中,当您安装 dbt-tidb 时,dbt 会作为依赖项安装。 + +```shell +pip install dbt-tidb +``` + +您也可以单独安装 dbt。请参阅 dbt 文档中的[如何安装 dbt](https://docs.getdbt.com/docs/get-started/installation)。 + +## 步骤 2:创建演示项目 + +要试用 dbt 功能,您可以使用 dbt-lab 提供的演示项目 [jaffle_shop](https://github.com/dbt-labs/jaffle_shop)。您可以直接从 GitHub 克隆该项目: + +```shell +git clone https://github.com/dbt-labs/jaffle_shop && \ +cd jaffle_shop +``` + +`jaffle_shop` 目录中的所有文件结构如下: + +```shell +. +├── LICENSE +├── README.md +├── dbt_project.yml +├── etc +│ ├── dbdiagram_definition.txt +│ └── jaffle_shop_erd.png +├── models +│ ├── customers.sql +│ ├── docs.md +│ ├── orders.sql +│ ├── overview.md +│ ├── schema.yml +│ └── staging +│ ├── schema.yml +│ ├── stg_customers.sql +│ ├── stg_orders.sql +│ └── stg_payments.sql +└── seeds + ├── raw_customers.csv + ├── raw_orders.csv + └── raw_payments.csv +``` + +在此目录中: + +- `dbt_project.yml` 是 dbt 项目配置文件,其中包含项目名称和数据库配置文件信息。 + +- `models` 目录包含项目的 SQL 模型和表结构。请注意,这部分由数据分析师编写。有关模型的更多信息,请参阅 [SQL 模型](https://docs.getdbt.com/docs/build/sql-models)。 + +- `seeds` 目录存储由数据库导出工具导出的 CSV 文件。例如,您可以通过 Dumpling [导出 TiDB Cloud 数据](https://docs.pingcap.com/tidbcloud/export-data-from-tidb-cloud)到 CSV 文件。在 `jaffle_shop` 项目中,这些 CSV 文件用作要处理的原始数据。 + +## 步骤 3:配置项目 + +要配置项目,请执行以下步骤: + +1. 完成全局配置。 + + 您可以参考[配置字段说明](#配置字段说明)并编辑默认的全局配置文件 `~/.dbt/profiles.yml` 来配置与 TiDB Cloud 的连接: + + ```shell + sudo vi ~/.dbt/profiles.yml + ``` + + 在编辑器中,添加以下配置: + + ```yaml + jaffle_shop_tidb: # 项目名称 + target: dev # 目标 + outputs: + dev: + type: tidb # 要使用的特定适配器 + server: gateway01.ap-southeast-1.prod.aws.tidbcloud.com # 要连接的 TiDB Cloud 集群的端点 + port: 4000 # 要使用的端口 + schema: analytics # 指定要将数据规范化到的架构(数据库) + username: xxxxxxxxxxx.root # 用于连接 TiDB Cloud 集群的用户名 + password: "your_password" # 用于向 TiDB Cloud 集群进行身份验证的密码 + ``` + + 您可以从集群的连接对话框中获取 `server`、`port` 和 `username` 的值。要打开此对话框,请转到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称以进入其概览页面,然后点击右上角的**连接**。 + +2. 完成项目配置。 + + 在 jaffle_shop 项目目录中,编辑项目配置文件 `dbt_project.yml` 并将 `profile` 字段更改为 `jaffle_shop_tidb`。此配置允许项目从 `~/.dbt/profiles.yml` 文件中指定的数据库进行查询。 + + ```shell + vi dbt_project.yml + ``` + + 在编辑器中,更新配置如下: + + ```yaml + name: 'jaffle_shop' + + config-version: 2 + version: '0.1' + + profile: 'jaffle_shop_tidb' # 注意此处的修改 + + model-paths: ["models"] # 模型路径 + seed-paths: ["seeds"] # seed 路径 + test-paths: ["tests"] + analysis-paths: ["analysis"] + macro-paths: ["macros"] + + target-path: "target" + clean-targets: + - "target" + - "dbt_modules" + - "logs" + + require-dbt-version: [">=1.0.0", "<2.0.0"] + + models: + jaffle_shop: + materialized: table # models/ 中的 *.sql 将实体化为表 + staging: + materialized: view # models/staging/ 中的 *.sql 将实体化为视图 + ``` + +3. 验证配置。 + + 运行以下命令以检查数据库和项目配置是否正确。 + + ```shell + dbt debug + ``` + +## 步骤 4:(可选)加载 CSV 文件 + +> **注意:** +> +> 此步骤是可选的。如果要处理的数据已经在目标数据库中,您可以跳过此步骤。 + +现在您已成功创建并配置了项目,是时候加载 CSV 数据并将 CSV 实体化为目标数据库中的表了。 + +1. 加载 CSV 数据并将 CSV 实体化为目标数据库中的表。 + + ```shell + dbt seed + ``` + + 以下是示例输出: + + ```shell + Running with dbt=1.0.1 + Partial parse save file not found. Starting full parse. + Found 5 models, 20 tests, 0 snapshots, 0 analyses, 172 macros, 0 operations, 3 seed files, 0 sources, 0 exposures, 0 metrics + + Concurrency: 1 threads (target='dev') + + 1 of 3 START seed file analytics.raw_customers.................................. [RUN] + 1 of 3 OK loaded seed file analytics.raw_customers.............................. [INSERT 100 in 0.19s] + 2 of 3 START seed file analytics.raw_orders..................................... [RUN] + 2 of 3 OK loaded seed file analytics.raw_orders................................. [INSERT 99 in 0.14s] + 3 of 3 START seed file analytics.raw_payments................................... [RUN] + 3 of 3 OK loaded seed file analytics.raw_payments............................... [INSERT 113 in 0.24s] + ``` + + 从结果中可以看到,seed 文件已启动并加载到三个表中:`analytics.raw_customers`、`analytics.raw_orders` 和 `analytics.raw_payments`。 + +2. 在 TiDB Cloud 中验证结果。 + + `show databases` 命令列出了 dbt 创建的新 `analytics` 数据库。`show tables` 命令表明 `analytics` 数据库中有三个表,对应于您创建的表。 + + ```sql + mysql> SHOW DATABASES; + +--------------------+ + | Database | + +--------------------+ + | INFORMATION_SCHEMA | + | METRICS_SCHEMA | + | PERFORMANCE_SCHEMA | + | analytics | + | io_replicate | + | mysql | + | test | + +--------------------+ + 7 rows in set (0.00 sec) + + mysql> USE ANALYTICS; + mysql> SHOW TABLES; + +---------------------+ + | Tables_in_analytics | + +---------------------+ + | raw_customers | + | raw_orders | + | raw_payments | + +---------------------+ + 3 rows in set (0.00 sec) + + mysql> SELECT * FROM raw_customers LIMIT 10; + +------+------------+-----------+ + | id | first_name | last_name | + +------+------------+-----------+ + | 1 | Michael | P. | + | 2 | Shawn | M. | + | 3 | Kathleen | P. | + | 4 | Jimmy | C. | + | 5 | Katherine | R. | + | 6 | Sarah | R. | + | 7 | Martin | M. | + | 8 | Frank | R. | + | 9 | Jennifer | F. | + | 10 | Henry | W. | + +------+------------+-----------+ + 10 rows in set (0.10 sec) + ``` + +## 步骤 5:转换数据 + +现在您已准备好运行配置的项目并完成数据转换。 + +1. 运行 dbt 项目以完成数据转换: + + ```shell + dbt run + ``` + + 以下是示例输出: + + ```shell + Running with dbt=1.0.1 + Found 5 models, 20 tests, 0 snapshots, 0 analyses, 170 macros, 0 operations, 3 seed files, 0 sources, 0 exposures, 0 metrics + + Concurrency: 1 threads (target='dev') + + 1 of 5 START view model analytics.stg_customers................................. [RUN] + 1 of 5 OK created view model analytics.stg_customers............................ [SUCCESS 0 in 0.31s] + 2 of 5 START view model analytics.stg_orders.................................... [RUN] + 2 of 5 OK created view model analytics.stg_orders............................... [SUCCESS 0 in 0.23s] + 3 of 5 START view model analytics.stg_payments.................................. [RUN] + 3 of 5 OK created view model analytics.stg_payments............................. [SUCCESS 0 in 0.29s] + 4 of 5 START table model analytics.customers.................................... [RUN] + 4 of 5 OK created table model analytics.customers............................... [SUCCESS 0 in 0.76s] + 5 of 5 START table model analytics.orders....................................... [RUN] + 5 of 5 OK created table model analytics.orders.................................. [SUCCESS 0 in 0.63s] + + Finished running 3 view models, 2 table models in 2.27s. + + Completed successfully + + Done. PASS=5 WARN=0 ERROR=0 SKIP=0 TOTAL=5 + ``` + + 结果显示已成功创建两个表(`analytics.customers` 和 `analytics.orders`)和三个视图(`analytics.stg_customers`、`analytics.stg_orders` 和 `analytics.stg_payments`)。 + +2. 转到 TiDB Cloud 验证转换是否成功。 + + ```sql + mysql> USE ANALYTICS; + mysql> SHOW TABLES; + +---------------------+ + | Tables_in_analytics | + +---------------------+ + | customers | + | orders | + | raw_customers | + | raw_orders | + | raw_payments | + | stg_customers | + | stg_orders | + | stg_payments | + +---------------------+ + 8 rows in set (0.00 sec) + + mysql> SELECT * FROM customers LIMIT 10; + +-------------+------------+-----------+-------------+-------------------+------------------+-------------------------+ + | customer_id | first_name | last_name | first_order | most_recent_order | number_of_orders | customer_lifetime_value | + +-------------+------------+-----------+-------------+-------------------+------------------+-------------------------+ + | 1 | Michael | P. | 2018-01-01 | 2018-02-10 | 2 | 33.0000 | + | 2 | Shawn | M. | 2018-01-11 | 2018-01-11 | 1 | 23.0000 | + | 3 | Kathleen | P. | 2018-01-02 | 2018-03-11 | 3 | 65.0000 | + | 4 | Jimmy | C. | NULL | NULL | NULL | NULL | + | 5 | Katherine | R. | NULL | NULL | NULL | NULL | + | 6 | Sarah | R. | 2018-02-19 | 2018-02-19 | 1 | 8.0000 | + | 7 | Martin | M. | 2018-01-14 | 2018-01-14 | 1 | 26.0000 | + | 8 | Frank | R. | 2018-01-29 | 2018-03-12 | 2 | 45.0000 | + | 9 | Jennifer | F. | 2018-03-17 | 2018-03-17 | 1 | 30.0000 | + | 10 | Henry | W. | NULL | NULL | NULL | NULL | + +-------------+------------+-----------+-------------+-------------------+------------------+-------------------------+ + 10 rows in set (0.00 sec) + ``` + + 输出显示已添加了五个表或视图,并且表或视图中的数据已转换。本示例中仅显示了客户表中的部分数据。 + +## 步骤 6:生成文档 + +dbt 允许您生成显示项目整体结构并描述所有表和视图的可视化文档。 + +要生成可视化文档,请执行以下步骤: + +1. 生成文档: + + ```shell + dbt docs generate + ``` + +2. 启动服务器: + + ```shell + dbt docs serve + ``` + +3. 要从浏览器访问文档,请转到 [http://localhost:8080](http://localhost:8080)。 + +## 配置字段说明 + +| 选项 | 说明 | 是否必需? | 示例 | +|------------------|-------------------------------------------------------------------------|-----------|---------------------------------------------------| +| `type` | 要使用的特定适配器 | 必需 | `tidb` | +| `server` | 要连接的 TiDB Cloud 集群的端点 | 必需 | `gateway01.ap-southeast-1.prod.aws.tidbcloud.com` | +| `port` | 要使用的端口 | 必需 | `4000` | +| `schema` | 要将数据规范化到的架构(数据库) | 必需 | `analytics` | +| `username` | 用于连接 TiDB Cloud 集群的用户名 | 必需 | `xxxxxxxxxxx.root` | +| `password` | 用于向 TiDB Cloud 集群进行身份验证的密码 | 必需 | `"your_password"` | +| `retries` | 连接 TiDB Cloud 集群的重试次数(默认为 1) | 可选 | `2` | + +## 支持的函数 + +您可以在 dbt-tidb 中直接使用以下函数。有关如何使用它们的信息,请参阅 [dbt-util](https://github.com/dbt-labs/dbt-utils)。 + +支持以下函数: + +- `bool_or` +- `cast_bool_to_text` +- `dateadd` +- `datediff`。注意,`datediff` 与 dbt-util 略有不同。它向下取整而不是向上取整。 +- `date_trunc` +- `hash` +- `safe_cast` +- `split_part` +- `last_day` +- `cast_bool_to_text` +- `concat` +- `escape_single_quotes` +- `except` +- `intersect` +- `length` +- `position` +- `replace` +- `right` diff --git a/tidb-cloud/integrate-tidbcloud-with-n8n.md b/tidb-cloud/integrate-tidbcloud-with-n8n.md new file mode 100644 index 000000000000..0fd99896cfef --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-n8n.md @@ -0,0 +1,295 @@ +--- +title: 将 TiDB Cloud 与 n8n 集成 +summary: 了解如何在 n8n 中使用 TiDB Cloud 节点。 +--- + +# 将 TiDB Cloud 与 n8n 集成 + +[n8n](https://n8n.io/) 是一个可扩展的工作流自动化工具。通过 [fair-code](https://faircode.io/) 分发模式,n8n 将始终保持源代码可见,支持自托管,并允许你添加自定义函数、逻辑和应用程序。 + +本文介绍如何构建一个自动工作流:创建 TiDB Cloud Serverless 集群,收集 Hacker News RSS,将其存储到 TiDB 并发送简报邮件。 + +## 前提条件:获取 TiDB Cloud API 密钥 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**组织设置** > **API 密钥**。 +3. 在 **API 密钥**页面,点击**创建 API 密钥**。 +4. 输入 API 密钥的描述,然后点击**下一步**。 +5. 复制创建的 API 密钥以供后续在 n8n 中使用,然后点击**完成**。 + +更多信息,请参阅 [TiDB Cloud API 概览](/tidb-cloud/api-overview.md)。 + +## 步骤 1:安装 n8n + +有两种方式可以安装自托管的 n8n。选择适合你的方式即可。 + + +
+ +1. 在你的工作空间安装 [node.js](https://nodejs.org/en/download/)。 +2. 通过 `npx` 下载并启动 n8n。 + + ```shell + npx n8n + ``` + +
+
+ +1. 在你的工作空间安装 [Docker](https://www.docker.com/products/docker-desktop)。 +2. 通过 `docker` 下载并启动 n8n。 + + ```shell + docker run -it --rm --name n8n -p 5678:5678 -v ~/.n8n:/home/node/.n8n n8nio/n8n + ``` + +
+
+ +启动 n8n 后,你可以访问 [localhost:5678](http://localhost:5678) 来试用 n8n。 + +## 步骤 2:在 n8n 中安装 TiDB Cloud 节点 + +TiDB Cloud 节点在 npm 仓库中的名称为 `n8n-nodes-tidb-cloud`。你需要手动安装此节点才能使用 n8n 控制 TiDB Cloud。 + +1. 在 [localhost:5678](http://localhost:5678) 页面,为自托管的 n8n 创建一个所有者账户。 +2. 转到**设置** > **社区节点**。 +3. 点击**安装社区节点**。 +4. 在 **npm 包名称**字段中,输入 `n8n-nodes-tidb-cloud`。 +5. 点击**安装**。 + +然后,你可以在**工作流** > 搜索栏中搜索 **TiDB Cloud** 节点,并通过将其拖动到工作区来使用 TiDB Cloud 节点。 + +## 步骤 3:构建工作流 + +在此步骤中,你将创建一个新的工作流,当你点击**执行**按钮时,它会向 TiDB 插入一些数据。 + +此示例工作流将使用以下节点: + +- [Schedule Trigger](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/) +- [RSS Read](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.rssfeedread/) +- [Code](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/) +- [Gmail](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.gmail/) +- [TiDB Cloud node](https://www.npmjs.com/package/n8n-nodes-tidb-cloud) + +最终的工作流应如下图所示。 + +![img](/media/tidb-cloud/integration-n8n-workflow-rss.jpg) + +### (可选)创建 TiDB Cloud Serverless 集群 + +如果你还没有 TiDB Cloud Serverless 集群,可以使用此节点创建一个。否则,可以跳过此操作。 + +1. 导航到**工作流**面板,点击**添加工作流**。 +2. 在新的工作流工作区中,点击右上角的 **+** 并选择**全部**字段。 +3. 搜索 `TiDB Cloud` 并将其拖动到工作区。 +4. 为 TiDB Cloud 节点输入凭据,即 TiDB Cloud API 密钥。 +5. 在**项目**列表中,选择你的项目。 +6. 在**操作**列表中,选择 `Create Serverless Cluster`。 +7. 在**集群名称**框中,输入集群名称。 +8. 在**区域**列表中,选择一个区域。 +9. 在**密码**框中,输入用于登录 TiDB 集群的密码。 +10. 点击**执行节点**以运行节点。 + +> **注意:** +> +> 创建新的 TiDB Cloud Serverless 集群需要几秒钟时间。 + +### 创建工作流 + +#### 使用手动触发器作为工作流的起点 + +1. 如果你还没有工作流,请导航到**工作流**面板,然后点击**从头开始**。否则,请跳过此步骤。 +2. 点击右上角的 **+** 并搜索 `schedule trigger`。 +3. 将手动触发器节点拖动到工作区,然后双击该节点。此时会显示**参数**对话框。 +4. 按如下方式配置规则: + + - **触发间隔**:`天` + - **触发间隔天数**:`1` + - **触发小时**:`8am` + - **触发分钟**:`0` + +此触发器将在每天早上 8 点执行你的工作流。 + +#### 创建用于插入数据的表 + +1. 点击手动触发器节点右侧的 **+**。 +2. 搜索 `TiDB Cloud` 并将其添加到工作区。 +3. 在**参数**对话框中,输入 TiDB Cloud 节点的凭据。凭据是你的 TiDB Cloud API 密钥。 +4. 在**项目**列表中,选择你的项目。 +5. 在**操作**列表中,选择 `Execute SQL`。 +6. 选择集群。如果你在列表中看不到新集群,需要等待几分钟,直到集群创建完成。 +7. 在**用户**列表中,选择一个用户。TiDB Cloud 始终创建一个默认用户,因此你不必手动创建。 +8. 在**数据库**框中,输入 `test`。 +9. 输入你的数据库密码。 +10. 在 **SQL** 框中,输入以下 SQL: + + ```sql + CREATE TABLE IF NOT EXISTS hacker_news_briefing (creator VARCHAR (200), title TEXT, link VARCHAR(200), pubdate VARCHAR(200), comments VARCHAR(200), content TEXT, guid VARCHAR (200), isodate VARCHAR(200)); + ``` + +11. 点击**执行节点**以创建表。 + +#### 获取 Hacker News RSS + +1. 点击 TiDB Cloud 节点右侧的 **+**。 +2. 搜索 `RSS Read` 并将其添加到工作区。 +3. 在 **URL** 框中,输入 `https://hnrss.org/frontpage`。 + +#### 将数据插入 TiDB + +1. 点击 RSS Read 节点右侧的 **+**。 +2. 搜索 `TiDB Cloud` 并将其添加到工作区。 +3. 选择你在前面的 TiDB Cloud 节点中输入的凭据。 +4. 在**项目**列表中,选择你的项目。 +5. 在**操作**列表中,选择 `Insert`。 +6. 在**集群**、**用户**、**数据库**和**密码**框中,输入相应的值。 +7. 在**表**框中,输入 `hacker_news_briefing` 表。 +8. 在**列**框中,输入 `creator, title, link, pubdate, comments, content, guid, isodate`。 + +#### 构建消息 + +1. 点击 RSS Feed Read 节点右侧的 **+**。 +2. 搜索 `code` 并将其添加到工作区。 +3. 选择 `Run Once for All Items` 模式。 +4. 在 **JavaScript** 框中,复制并粘贴以下代码。 + + ```javascript + let message = ""; + + // Loop the input items + for (item of items) { + message += ` +

${item.json.title}

+
+ ${item.json.content} +
+ ` + } + + let response = + ` + + + + Hacker News Briefing + + + ${message} + + + ` + // Return our message + return [{json: {response}}]; + ``` + +#### 通过 Gmail 发送消息 + +1. 点击代码节点右侧的 **+**。 +2. 搜索 `gmail` 并将其添加到工作区。 +3. 为 Gmail 节点输入凭据。有关详细说明,请参阅 [n8n 文档](https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/)。 +4. 在**资源**列表中,选择 `Message`。 +5. 在**操作**列表中,选择 `Send`。 +6. 在**收件人**框中,输入你的电子邮件。 +7. 在**主题**框中,输入 `Hacker News Briefing`。 +8. 在**邮件类型**框中,选择 `HTML`。 +9. 在**消息**框中,点击 `Expression` 并输入 `{{ $json["response"] }}`。 + + > **注意:** + > + > 你必须将鼠标悬停在**消息**框上并选择 **Expression** 模式。 + +## 步骤 4:运行工作流 + +构建完工作流后,你可以点击**执行工作流**进行测试运行。 + +如果工作流按预期运行,你将收到 Hacker News 简报邮件。这些新闻内容将记录到你的 TiDB Cloud Serverless 集群中,因此你不必担心丢失它们。 + +现在你可以在**工作流**面板中激活此工作流。这个工作流将帮助你每天获取 Hacker News 的头版文章。 + +## TiDB Cloud 节点核心 + +### 支持的操作 + +TiDB Cloud 节点作为[常规节点](https://docs.n8n.io/workflows/nodes/#regular-nodes)运行,仅支持以下五种操作: + +- **Create Serverless Cluster**:创建 TiDB Cloud Serverless 集群。 +- **Execute SQL**:在 TiDB 中执行 SQL 语句。 +- **Delete**:在 TiDB 中删除行。 +- **Insert**:在 TiDB 中插入行。 +- **Update**:在 TiDB 中更新行。 + +### 字段 + +要使用不同的操作,你需要填写不同的必填字段。以下显示了相应操作的字段说明。 + + +
+ +- **Credential for TiDB Cloud API**:仅支持 TiDB Cloud API 密钥。有关如何创建 API 密钥,请参阅[获取 TiDB Cloud API 密钥](#前提条件获取-tidb-cloud-api-密钥)。 +- **Project**:TiDB Cloud 项目名称。 +- **Operation**:此节点的操作。有关所有支持的操作,请参阅[支持的操作](#支持的操作)。 +- **Cluster**:TiDB Cloud 集群名称。为你的新集群输入名称。 +- **Region**:区域名称。选择将部署集群的区域。通常选择离应用程序部署最近的区域。 +- **Password**:root 密码。为你的新集群设置密码。 + +
+
+ +- **Credential for TiDB Cloud API**:仅支持 TiDB Cloud API 密钥。有关如何创建 API 密钥,请参阅[获取 TiDB Cloud API 密钥](#前提条件获取-tidb-cloud-api-密钥)。 +- **Project**:TiDB Cloud 项目名称。 +- **Operation**:此节点的操作。有关所有支持的操作,请参阅[支持的操作](#支持的操作)。 +- **Cluster**:TiDB Cloud 集群名称。你应该选择一个现有集群。 +- **Password**:TiDB Cloud 集群的密码。 +- **User**:TiDB Cloud 集群的用户名。 +- **Database**:数据库名称。 +- **SQL**:要执行的 SQL 语句。 + +
+
+ +- **Credential for TiDB Cloud API**:仅支持 TiDB Cloud API 密钥。有关如何创建 API 密钥,请参阅[获取 TiDB Cloud API 密钥](#前提条件获取-tidb-cloud-api-密钥)。 +- **Project**:TiDB Cloud 项目名称。 +- **Operation**:此节点的操作。有关所有支持的操作,请参阅[支持的操作](#支持的操作)。 +- **Cluster**:TiDB Cloud 集群名称。你应该选择一个现有集群。 +- **Password**:TiDB Cloud 集群的密码。 +- **User**:TiDB Cloud 集群的用户名。 +- **Database**:数据库名称。 +- **Table**:表名。你可以使用 `From list` 模式选择一个,或使用 `Name` 模式手动输入表名。 +- **Delete Key**:决定数据库中哪些行被删除的项目属性名称。项目是从一个节点发送到另一个节点的数据。节点对传入数据的每个项目执行其操作。有关 n8n 中项目的更多信息,请参阅 [n8n 文档](https://docs.n8n.io/workflows/items/)。 + +
+
+ +- **Credential for TiDB Cloud API**:仅支持 TiDB Cloud API 密钥。有关如何创建 API 密钥,请参阅[获取 TiDB Cloud API 密钥](#前提条件获取-tidb-cloud-api-密钥)。 +- **Project**:TiDB Cloud 项目名称。 +- **Operation**:此节点的操作。有关所有支持的操作,请参阅[支持的操作](#支持的操作)。 +- **Cluster**:TiDB Cloud 集群名称。你应该选择一个现有集群。 +- **Password**:TiDB Cloud 集群的密码。 +- **User**:TiDB Cloud 集群的用户名。 +- **Database**:数据库名称。 +- **Table**:表名。你可以使用 `From list` 模式选择一个,或使用 `Name` 模式手动输入表名。 +- **Columns**:用作新行列的输入项目属性的逗号分隔列表。项目是从一个节点发送到另一个节点的数据。节点对传入数据的每个项目执行其操作。有关 n8n 中项目的更多信息,请参阅 [n8n 文档](https://docs.n8n.io/workflows/items/)。 + +
+
+ +- **Credential for TiDB Cloud API**:仅支持 TiDB Cloud API 密钥。有关如何创建 API 密钥,请参阅[获取 TiDB Cloud API 密钥](#前提条件获取-tidb-cloud-api-密钥)。 +- **Project**:TiDB Cloud 项目名称。 +- **Operation**:此节点的操作。有关所有支持的操作,请参阅[支持的操作](#支持的操作)。 +- **Cluster**:TiDB Cloud 集群名称。你应该选择一个现有集群。 +- **Password**:TiDB Cloud 集群的密码。 +- **User**:TiDB Cloud 集群的用户名。 +- **Database**:数据库名称。 +- **Table**:表名。你可以使用 `From list` 模式选择一个,或使用 `Name` 模式手动输入表名。 +- **Update Key**:决定数据库中哪些行被更新的项目属性名称。项目是从一个节点发送到另一个节点的数据。节点对传入数据的每个项目执行其操作。有关 n8n 中项目的更多信息,请参阅 [n8n 文档](https://docs.n8n.io/workflows/items/)。 +- **Columns**:用作要更新行的列的输入项目属性的逗号分隔列表。 + +
+
+ +### 限制 + +- 通常在 **Execute SQL** 操作中只允许执行一条 SQL 语句。如果你想在单个操作中执行多条语句,需要手动启用 [`tidb_multi_statement_mode`](https://docs.pingcap.com/tidbcloud/system-variables#tidb_multi_statement_mode-new-in-v4011)。 +- 对于 **Delete** 和 **Update** 操作,你需要指定一个字段作为键。例如,`Delete Key` 设置为 `id`,相当于执行 `DELETE FROM table WHERE id = ${item.id}`。目前,**Delete** 和 **Update** 操作仅支持指定一个键。 +- 对于 **Insert** 和 **Update** 操作,你需要在 **Columns** 字段中指定逗号分隔的列表,并且字段名称必须与输入项目的属性相同。 diff --git a/tidb-cloud/integrate-tidbcloud-with-netlify.md b/tidb-cloud/integrate-tidbcloud-with-netlify.md new file mode 100644 index 000000000000..75a28e7f8734 --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-netlify.md @@ -0,0 +1,261 @@ +--- +title: 将 TiDB Cloud 与 Netlify 集成 +summary: 了解如何将 TiDB Cloud 集群连接到 Netlify 项目。 +--- + +# 将 TiDB Cloud 与 Netlify 集成 + +[Netlify](https://netlify.com/) 是一个用于自动化现代 Web 项目的一体化平台。它用单一工作流替代了你的托管基础设施、持续集成和部署流程,并随着项目的增长集成了无服务器函数、用户认证和表单处理等动态功能。 + +本文档描述如何在 Netlify 上部署一个以 TiDB Cloud 作为数据库后端的全栈应用。你还可以了解如何将 Netlify 边缘函数与我们的 TiDB Cloud 无服务器驱动程序一起使用。 + +## 前提条件 + +在部署之前,请确保满足以下前提条件。 + +### Netlify 账号和 CLI + +你需要有一个 Netlify 账号和 CLI。如果你没有,请参考以下链接创建: + +* [注册 Netlify 账号](https://app.netlify.com/signup)。 +* [获取 Netlify CLI](https://docs.netlify.com/cli/get-started/)。 + +### TiDB Cloud 账号和 TiDB 集群 + +你需要在 TiDB Cloud 中拥有一个账号和一个集群。如果你没有,请参考以下内容创建: + +- [创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md) +- [创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md) + +一个 TiDB Cloud 集群可以连接到多个 Netlify 站点。 + +### TiDB Cloud 中允许所有 IP 地址的流量过滤器 + +对于 TiDB Cloud Dedicated 集群,确保集群的流量过滤器允许所有 IP 地址(设置为 `0.0.0.0/0`)进行连接。这是因为 Netlify 部署使用动态 IP 地址。 + +TiDB Cloud Serverless 集群默认允许所有 IP 地址连接,因此你不需要配置任何流量过滤器。 + +## 步骤 1. 获取示例项目和连接字符串 + +为了帮助你快速入门,TiDB Cloud 提供了一个使用 React 和 Prisma Client 的 Next.js TypeScript 全栈示例应用。这是一个简单的博客站点,你可以发布和删除自己的博客。所有内容都通过 Prisma 存储在 TiDB Cloud 中。 + +### Fork 示例项目并将其克隆到你自己的空间 + +1. 将 [Fullstack Example with Next.js and Prisma](https://github.com/tidbcloud/nextjs-prisma-example) 仓库 fork 到你自己的 GitHub 仓库。 + +2. 将 fork 的仓库克隆到你自己的空间: + + ```shell + git clone https://github.com/${your_username}/nextjs-prisma-example.git + cd nextjs-prisma-example/ + ``` + +### 获取 TiDB Cloud 连接字符串 + +对于 TiDB Cloud Serverless 集群,你可以从 [TiDB Cloud CLI](/tidb-cloud/cli-reference.md) 或 [TiDB Cloud 控制台](https://tidbcloud.com/) 获取连接字符串。 + +对于 TiDB Cloud Dedicated 集群,你只能从 TiDB Cloud 控制台获取连接字符串。 + + +
+ +> **提示:** +> +> 如果你尚未安装 Cloud CLI,请在执行以下步骤之前参考 [TiDB Cloud CLI 快速入门](/tidb-cloud/get-started-with-cli.md) 进行快速安装。 + +1. 在交互模式下获取集群的连接字符串: + + ```shell + ticloud cluster connect-info + ``` + +2. 按照提示选择你的集群、客户端和操作系统。注意,本文档使用的客户端是 `Prisma`。 + + ``` + Choose the cluster + > [x] Cluster0(13796194496) + Choose the client + > [x] Prisma + Choose the operating system + > [x] macOS/Alpine (Detected) + ``` + + 输出如下,你可以在 `url` 值中找到 Prisma 的连接字符串。 + + ```shell + datasource db { + provider = "mysql" + url = "mysql://:@:/?sslaccept=strict" + } + ``` + + > **注意:** + > + > 在稍后使用连接字符串时,请注意以下事项: + > + > - 将连接字符串中的参数替换为实际值。 + > - 本文档中的示例应用需要一个新数据库,因此你需要将 `` 替换为一个唯一的新名称。 + +
+
+ +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,转到项目的 [**Clusters**](https://tidbcloud.com/project/clusters) 页面,点击目标集群的名称进入其概览页面,然后点击右上角的 **Connect**。在显示的对话框中,你可以从连接字符串中获取以下连接参数。 + + - `${host}` + - `${port}` + - `${user}` + - `${password}` + +2. 在以下连接字符串中填入连接参数: + + ```shell + mysql://:@:/?sslaccept=strict + ``` + + > **注意:** + > + > 在稍后使用连接字符串时,请注意以下事项: + > + > - 将连接字符串中的参数替换为实际值。 + > - 本文档中的示例应用需要一个新数据库,因此你需要将 `` 替换为一个唯一的新名称。 + +
+
+ +## 步骤 2. 将示例应用部署到 Netlify + +1. 在 Netlify CLI 中,验证你的 Netlify 账号并获取访问令牌。 + + ```shell + netlify login + ``` + +2. 启动自动设置。此步骤将你的仓库连接到持续部署,因此 Netlify CLI 需要访问权限来在仓库中创建部署密钥和 webhook。 + + ```shell + netlify init + ``` + + 当出现提示时,选择 **Create & configure a new site**,并授予 GitHub 访问权限。对于所有其他选项,使用默认值。 + + ```shell + Adding local .netlify folder to .gitignore file... + ? What would you like to do? + Create & configure a new site + ? Team: your_username's team + ? Site name (leave blank for a random name; you can change it later): + + Site Created + + Admin URL: https://app.netlify.com/sites/mellow-crepe-e2ca2b + URL: https://mellow-crepe-e2ca2b.netlify.app + Site ID: b23d1359-1059-49ed-9d08-ed5dba8e83a2 + + Linked to mellow-crepe-e2ca2b + + + ? Netlify CLI needs access to your GitHub account to configure Webhooks and Deploy Keys. What would you like to do? Authorize with GitHub through app.netlify.com + Configuring Next.js runtime... + + ? Your build command (hugo build/yarn run build/etc): npm run netlify-build + ? Directory to deploy (blank for current dir): .next + + Adding deploy key to repository... + (node:36812) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time + (Use `node --trace-warnings ...` to show where the warning was created) + Deploy key added! + + Creating Netlify GitHub Notification Hooks... + Netlify Notification Hooks configured! + + Success! Netlify CI/CD Configured! + + This site is now configured to automatically deploy from github branches & pull requests + + Next steps: + + git push Push to your git repository to trigger new site builds + netlify open Open the Netlify admin URL of your site + ``` + +3. 设置环境变量。要从你自己的空间和 Netlify 空间连接到你的 TiDB Cloud 集群,你需要将 `DATABASE_URL` 设置为从[步骤 1](#步骤-1-获取示例项目和连接字符串)获取的连接字符串。 + + ```shell + # 为你自己的空间设置环境变量 + export DATABASE_URL='mysql://:@:/?sslaccept=strict' + + # 为 Netlify 空间设置环境变量 + netlify env:set DATABASE_URL 'mysql://:@:/?sslaccept=strict' + ``` + + 检查你的环境变量。 + + ```shell + # 检查你自己空间的环境变量 + env | grep DATABASE_URL + + # 检查 Netlify 空间的环境变量 + netlify env:list + ``` + +4. 在本地构建应用并将架构迁移到你的 TiDB Cloud 集群。 + + > **提示:** + > + > 如果你想跳过本地部署直接将应用部署到 Netlify,只需转到步骤 6。 + + ```shell + npm install . + npm run netlify-build + ``` + +5. 在本地运行应用。你可以启动本地开发服务器来预览你的站点。 + + ```shell + netlify dev + ``` + + 然后,在浏览器中访问 `http://localhost:3000/` 来探索其用户界面。 + +6. 将应用部署到 Netlify。一旦你对本地预览满意,就可以使用以下命令将你的站点部署到 Netlify。`--trigger` 表示不上传本地文件进行部署。如果你进行了任何本地更改,请确保已将它们提交到你的 GitHub 仓库。 + + ```shell + netlify deploy --prod --trigger + ``` + + 转到你的 Netlify 控制台检查部署状态。部署完成后,应用的站点将有一个由 Netlify 提供的公共 IP 地址,以便所有人都可以访问它。 + +## 使用边缘函数 + +上述部分提到的示例应用在 Netlify 无服务器函数上运行。本节向你展示如何将边缘函数与 [TiDB Cloud 无服务器驱动程序](/tidb-cloud/serverless-driver.md)一起使用。边缘函数是 Netlify 提供的一个功能,它允许你在 Netlify CDN 的边缘运行无服务器函数。 + +要使用边缘函数,请执行以下步骤: + +1. 在项目的根目录下创建一个名为 `netlify/edge-functions` 的目录。 + +2. 在该目录中创建一个名为 `hello.ts` 的文件,并添加以下代码: + + ```typescript + import { connect } from 'https://esm.sh/@tidbcloud/serverless' + + export default async () => { + const conn = connect({url: Netlify.env.get('DATABASE_URL')}) + const result = await conn.execute('show databases') + return new Response(JSON.stringify(result)); + } + + export const config = { path: "/api/hello" }; + ``` + +3. 设置 `DATABASE_URL` 环境变量。你可以从 [TiDB Cloud 控制台](https://tidbcloud.com/)获取连接信息。 + + ```shell + netlify env:set DATABASE_URL 'mysql://:@/' + ``` + +4. 将边缘函数部署到 Netlify。 + + ```shell + netlify deploy --prod --trigger + ``` + +然后你可以转到你的 Netlify 控制台检查部署状态。部署完成后,你可以通过 `https:///api/hello` URL 访问边缘函数。 diff --git a/tidb-cloud/integrate-tidbcloud-with-vercel.md b/tidb-cloud/integrate-tidbcloud-with-vercel.md new file mode 100644 index 000000000000..34150a8d0efa --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-vercel.md @@ -0,0 +1,266 @@ +--- +title: 将 TiDB Cloud 与 Vercel 集成 +summary: 了解如何将 TiDB Cloud 集群连接到 Vercel 项目。 +--- + + + +# 将 TiDB Cloud 与 Vercel 集成 + +[Vercel](https://vercel.com/) 是一个面向前端开发者的平台,为创新者提供灵感迸发时所需的速度和可靠性。 + +将 TiDB Cloud 与 Vercel 结合使用,可以让您使用 MySQL 兼容的关系模型更快地构建新的前端应用程序,并借助为弹性、可扩展性以及最高级别的数据隐私和安全性而构建的平台,让您的应用程序充满信心地成长。 + +本指南描述了如何使用以下方法之一将 TiDB Cloud 集群连接到 Vercel 项目: + +* [通过 TiDB Cloud Vercel 集成连接](#通过-tidb-cloud-vercel-集成连接) +* [通过手动配置环境变量连接](#通过手动设置环境变量连接) + +对于上述两种方法,TiDB Cloud 提供以下选项用于以编程方式连接到您的数据库: + +- 集群:通过直接连接或[无服务器驱动](/tidb-cloud/serverless-driver.md)将您的 TiDB Cloud 集群连接到您的 Vercel 项目。 +- [数据应用](/tidb-cloud/data-service-manage-data-app.md):通过一组 HTTP 端点访问您的 TiDB Cloud 集群的数据。 + +## 前提条件 + +在连接之前,请确保满足以下前提条件。 + +### Vercel 账号和 Vercel 项目 + +您需要在 Vercel 中拥有一个账号和一个项目。如果您没有,请参考以下 Vercel 文档创建: + +* [创建新的个人账号](https://vercel.com/docs/teams-and-accounts#creating-a-personal-account)或[创建新的团队](https://vercel.com/docs/teams-and-accounts/create-or-join-a-team#creating-a-team)。 +* 在 Vercel 中[创建项目](https://vercel.com/docs/concepts/projects/overview#creating-a-project),或者如果您没有要部署的应用程序,可以使用 [TiDB Cloud 入门模板](https://vercel.com/templates/next.js/tidb-cloud-starter)进行尝试。 + +一个 Vercel 项目只能连接到一个 TiDB Cloud 集群。要更改集成,您需要先断开当前集群的连接,然后再连接到新集群。 + +### TiDB Cloud 账号和 TiDB 集群 + +您需要在 TiDB Cloud 中拥有一个账号和一个集群。如果您没有,请参考以下内容创建: + +- [创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md) + + > **注意:** + > + > TiDB Cloud Vercel 集成支持创建 TiDB Cloud Serverless 集群。您也可以在集成过程中稍后创建。 + +- [创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md) + + > **注意:** + > + > 对于 TiDB Cloud Dedicated 集群,请确保集群的流量过滤器允许所有 IP 地址(设置为 `0.0.0.0/0`)进行连接,因为 Vercel 部署使用[动态 IP 地址](https://vercel.com/guides/how-to-allowlist-deployment-ip-address)。 + +要[通过 TiDB Cloud Vercel 集成进行集成](#通过-tidb-cloud-vercel-集成连接),您需要在 TiDB Cloud 中拥有组织的`组织所有者`角色或目标项目的`项目所有者`角色。更多信息,请参阅[用户角色](/tidb-cloud/manage-user-access.md#user-roles)。 + +一个 TiDB Cloud 集群可以连接到多个 Vercel 项目。 + +### 数据应用和端点 + +如果您想通过[数据应用](/tidb-cloud/data-service-manage-data-app.md)连接到您的 TiDB Cloud 集群,您需要预先在 TiDB Cloud 中拥有目标数据应用和端点。如果您没有,请参考以下步骤创建: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,转到项目的[**数据服务**](https://tidbcloud.com/project/data-service)页面。 +2. 为您的项目[创建数据应用](/tidb-cloud/data-service-manage-data-app.md#create-a-data-app)。 +3. [将数据应用链接](/tidb-cloud/data-service-manage-data-app.md#manage-linked-data-sources)到目标 TiDB Cloud 集群。 +4. [管理端点](/tidb-cloud/data-service-manage-endpoint.md),以便您可以自定义它们来执行 SQL 语句。 + +一个 Vercel 项目只能连接到一个 TiDB Cloud 数据应用。要更改 Vercel 项目的数据应用,您需要先断开当前应用的连接,然后再连接到新应用。 + +## 通过 TiDB Cloud Vercel 集成连接 + +要通过 TiDB Cloud Vercel 集成进行连接,请从 [Vercel 的集成市场](https://vercel.com/integrations)转到 [TiDB Cloud 集成](https://vercel.com/integrations/tidb-cloud)页面。使用此方法,您可以选择要连接的集群,TiDB Cloud 将自动为您的 Vercel 项目生成所有必要的环境变量。 + +> **注意:** +> +> 此方法仅适用于 TiDB Cloud Serverless 集群。如果您想连接到 TiDB Cloud Dedicated 集群,请使用[手动方法](#通过手动设置环境变量连接)。 + +### 集成工作流程 + +详细步骤如下: + + +
+ +1. 在 [TiDB Cloud Vercel 集成](https://vercel.com/integrations/tidb-cloud)页面的右上角点击**添加集成**。将显示**添加 TiDB Cloud**对话框。 +2. 在下拉列表中选择集成范围,然后点击**继续**。 +3. 选择要添加集成的 Vercel 项目,然后点击**继续**。 +4. 确认集成所需的权限,然后点击**添加集成**。然后您将被引导到 TiDB Cloud 控制台的集成页面。 +5. 在集成页面上,执行以下操作: + + 1. 选择您的目标 Vercel 项目,然后点击**下一步**。 + 2. 选择您的目标 TiDB Cloud 组织和项目。 + 3. 选择**集群**作为您的连接类型。 + 4. 选择您的目标 TiDB Cloud 集群。如果**集群**下拉列表为空或您想选择新的 TiDB Cloud Serverless 集群,请在列表中点击**+ 创建集群**来创建一个。 + 5. 选择您要连接的数据库。如果**数据库**下拉列表为空或您想选择新的数据库,请在列表中点击**+ 创建数据库**来创建一个。 + 6. 选择您的 Vercel 项目使用的框架。如果目标框架未列出,请选择**通用**。不同的框架决定了不同的环境变量。 + 7. 选择是否启用**分支**以为预览环境创建新分支。 + 8. 点击**添加集成并返回 Vercel**。 + +![Vercel 集成页面](/media/tidb-cloud/vercel/integration-link-cluster-page.png) + +6. 返回到您的 Vercel 仪表板,转到您的 Vercel 项目,点击**设置** > **环境变量**,检查是否已自动添加目标 TiDB 集群的环境变量。 + + 如果已添加以下变量,则集成完成。 + + **通用** + + ```shell + TIDB_HOST + TIDB_PORT + TIDB_USER + TIDB_PASSWORD + TIDB_DATABASE + ``` + + **Prisma** + + ``` + DATABASE_URL + ``` + + **TiDB Cloud 无服务器驱动** + + ``` + DATABASE_URL + ``` + +
+ +
+ +1. 在 [TiDB Cloud Vercel 集成](https://vercel.com/integrations/tidb-cloud)页面的右上角点击**添加集成**。将显示**添加 TiDB Cloud**对话框。 +2. 在下拉列表中选择集成范围,然后点击**继续**。 +3. 选择要添加集成的 Vercel 项目,然后点击**继续**。 +4. 确认集成所需的权限,然后点击**添加集成**。然后您将被引导到 TiDB Cloud 控制台的集成页面。 +5. 在集成页面上,执行以下操作: + + 1. 选择您的目标 Vercel 项目,然后点击**下一步**。 + 2. 选择您的目标 TiDB Cloud 组织和项目。 + 3. 选择**数据应用**作为您的连接类型。 + 4. 选择您的目标 TiDB 数据应用。 + 6. 点击**添加集成并返回 Vercel**。 + +![Vercel 集成页面](/media/tidb-cloud/vercel/integration-link-data-app-page.png) + +6. 返回到您的 Vercel 仪表板,转到您的 Vercel 项目,点击**设置** > **环境变量**,检查是否已自动添加目标数据应用的环境变量。 + + 如果已添加以下变量,则集成完成。 + + ```shell + DATA_APP_BASE_URL + DATA_APP_PUBLIC_KEY + DATA_APP_PRIVATE_KEY + ``` + +
+
+ +### 配置连接 + +如果您已安装 [TiDB Cloud Vercel 集成](https://vercel.com/integrations/tidb-cloud),您可以在集成内添加或删除连接。 + +1. 在您的 Vercel 仪表板中,点击**集成**。 +2. 在 TiDB Cloud 条目中点击**管理**。 +3. 点击**配置**。 +4. 点击**添加链接**或**删除**以添加或删除连接。 + + ![Vercel 集成配置页面](/media/tidb-cloud/vercel/integration-vercel-configuration-page.png) + + 当您删除连接时,集成工作流程设置的环境变量也会从 Vercel 项目中删除。但是,此操作不会影响 TiDB Cloud Serverless 集群的数据。 + +### 使用 TiDB Cloud Serverless 分支连接 + +Vercel 的[预览部署](https://vercel.com/docs/deployments/preview-deployments)功能允许您在不将更改合并到 Git 项目的生产分支的情况下,在实时部署中预览应用程序的更改。使用 [TiDB Cloud Serverless 分支](/tidb-cloud/branch-overview.md),您可以为 Vercel 项目的每个分支创建一个新实例。这允许您在实时部署中预览应用程序更改,而不会影响您的生产数据。 + +> **注意:** +> +> 目前,TiDB Cloud Serverless 分支仅支持[与 GitHub 仓库关联的 Vercel 项目](https://vercel.com/docs/deployments/git/vercel-for-github)。 + +要启用 TiDB Cloud Serverless 分支,您需要在 [TiDB Cloud Vercel 集成工作流程](#集成工作流程)中确保以下内容: + +1. 选择**集群**作为您的连接类型。 +2. 启用**分支**以为预览环境创建新分支。 + +在您将更改推送到 Git 仓库后,Vercel 将触发预览部署。TiDB Cloud 集成将自动为 Git 分支创建一个 TiDB Cloud Serverless 分支并设置环境变量。详细步骤如下: + +1. 在您的 Git 仓库中创建一个新分支。 + + ```shell + cd tidb-prisma-vercel-demo1 + git checkout -b new-branch + ``` + +2. 添加一些更改并将更改推送到远程仓库。 +3. Vercel 将为新分支触发预览部署。 + + ![Vercel 预览部署](/media/tidb-cloud/vercel/vercel-preview-deployment.png) + + 1. 在部署过程中,TiDB Cloud 集成将自动创建一个与 Git 分支同名的 TiDB Cloud Serverless 分支。如果 TiDB Cloud Serverless 分支已存在,TiDB Cloud 集成将跳过此步骤。 + + ![TiDB Cloud 分支检查](/media/tidb-cloud/vercel/tidbcloud-branch-check.png) + + 2. TiDB Cloud Serverless 分支就绪后,TiDB Cloud 集成将在 Vercel 项目的预览部署中设置环境变量。 + + ![预览环境变量](/media/tidb-cloud/vercel/preview-envs.png) + + 3. TiDB Cloud 集成还将注册一个阻塞检查,以等待 TiDB Cloud Serverless 分支就绪。您可以手动重新运行检查。 +4. 检查通过后,您可以访问预览部署以查看更改。 + +> **注意:** +> +> 由于 Vercel 部署工作流程的限制,无法确保在部署中设置环境变量。在这种情况下,您需要重新部署。 + +> **注意:** +> +> 对于 TiDB Cloud 中的每个组织,默认情况下最多可以创建五个 TiDB Cloud Serverless 分支。为避免超过限制,您可以删除不再需要的 TiDB Cloud Serverless 分支。更多信息,请参阅[管理 TiDB Cloud Serverless 分支](/tidb-cloud/branch-manage.md)。 + +## 通过手动设置环境变量连接 + + +
+ +1. 获取您的 TiDB 集群的连接信息。 + + 您可以从集群的连接对话框中获取连接信息。要打开对话框,请转到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称以进入其概览页面,然后点击右上角的**连接**。 + +2. 转到您的 Vercel 仪表板 > Vercel 项目 > **设置** > **环境变量**,然后根据您的 TiDB 集群的连接信息[声明每个环境变量值](https://vercel.com/docs/concepts/projects/environment-variables#declare-an-environment-variable)。 + + ![Vercel 环境变量](/media/tidb-cloud/vercel/integration-vercel-environment-variables.png) + +这里我们以 Prisma 应用程序为例。以下是 Prisma schema 文件中针对 TiDB Cloud Serverless 集群的数据源设置: + +``` +datasource db { + provider = "mysql" + url = env("DATABASE_URL") +} +``` + +在 Vercel 中,您可以按如下方式声明环境变量: + +- **Key** = `DATABASE_URL` +- **Value** = `mysql://:@:/?sslaccept=strict` + +您可以在 TiDB Cloud 控制台中获取 ``、``、``、`` 和 `` 的信息。 + +
+
+ +1. 如果您尚未创建数据应用及其端点,请按照[管理数据应用](/tidb-cloud/data-service-manage-data-app.md)和[管理端点](/tidb-cloud/data-service-manage-endpoint.md)中的步骤进行操作。 + +2. 转到您的 Vercel 仪表板 > Vercel 项目 > **设置** > **环境变量**,然后根据您的数据应用的连接信息[声明每个环境变量值](https://vercel.com/docs/concepts/projects/environment-variables#declare-an-environment-variable)。 + + ![Vercel 环境变量](/media/tidb-cloud/vercel/integration-vercel-environment-variables.png) + + 在 Vercel 中,您可以按如下方式声明环境变量: + + - **Key** = `DATA_APP_BASE_URL` + - **Value** = `` + - **Key** = `DATA_APP_PUBLIC_KEY` + - **Value** = `` + - **Key** = `DATA_APP_PRIVATE_KEY` + - **Value** = `` + + 您可以从 TiDB Cloud 控制台的[数据服务](https://tidbcloud.com/project/data-service)页面获取 ``、`` 和 `` 的信息。 + +
+
diff --git a/tidb-cloud/integrate-tidbcloud-with-zapier.md b/tidb-cloud/integrate-tidbcloud-with-zapier.md new file mode 100644 index 000000000000..8fe33f2d785a --- /dev/null +++ b/tidb-cloud/integrate-tidbcloud-with-zapier.md @@ -0,0 +1,236 @@ +--- +title: 将 TiDB Cloud 与 Zapier 集成 +summary: 了解如何通过 Zapier 将 TiDB Cloud 连接到 5000+ 个应用。 +--- + +# 将 TiDB Cloud 与 Zapier 集成 + +[Zapier](https://zapier.com) 是一个无代码自动化工具,可让你轻松创建涉及数千个应用和服务的工作流。 + +使用 Zapier 上的 [TiDB Cloud 应用](https://zapier.com/apps/tidb-cloud/integrations)可以让你: + +- 使用 TiDB,一个兼容 MySQL 的 HTAP 数据库。无需本地构建。 +- 更轻松地管理你的 TiDB Cloud。 +- 将 TiDB Cloud 连接到 5000+ 个应用并自动化你的工作流。 + +本指南对 Zapier 上的 TiDB Cloud 应用进行高级介绍,并提供一个使用示例。 + +## 使用模板快速开始 + +[Zap 模板](https://platform.zapier.com/partners/zap-templates)是预制的集成或 Zap,已预先选择了应用和核心字段,适用于公开可用的 Zapier 集成。 + +在本节中,我们将使用**将新的 Github 全局事件添加到 TiDB 行**模板作为示例来创建工作流。在此工作流中,每当你的 GitHub 账户创建新的全局事件(在任何仓库中发生的任何 [GitHub 事件](https://docs.github.com/en/developers/webhooks-and-events/events/github-event-types))时,Zapier 都会在你的 TiDB Cloud 集群中添加一个新行。 + +### 前提条件 + +在开始之前,你需要: + +- 一个 [Zapier 账户](https://zapier.com/app/login)。 +- 一个 [GitHub 账户](https://github.com/login)。 +- 一个 [TiDB Cloud 账户](https://tidbcloud.com/signup)和 TiDB Cloud 上的 TiDB Cloud Serverless 集群。更多详情,请参阅 [TiDB Cloud 快速入门](https://docs.pingcap.com/tidbcloud/tidb-cloud-quickstart#step-1-create-a-tidb-cluster)。 + +### 步骤 1:获取模板 + +转到 [Zapier 上的 TiDB Cloud 应用](https://zapier.com/apps/tidb-cloud/integrations)。选择**将新的 Github 全局事件添加到 TiDB 行**模板,然后点击**试用**。之后你将进入编辑器页面。 + +### 步骤 2:设置触发器 + +在编辑器页面,你可以看到触发器和操作。点击触发器进行设置。 + +1. 选择应用和事件 + + 模板已默认设置了应用和事件,因此你无需在此处进行任何操作。点击**继续**。 + +2. 选择账户 + + 选择你想要与 TiDB Cloud 连接的 GitHub 账户。你可以连接新账户或选择现有账户。设置完成后,点击**继续**。 + +3. 设置触发器 + + 模板已默认设置了触发器。点击**继续**。 + +4. 测试触发器 + + 点击**测试触发器**。如果触发器设置成功,你可以看到来自 GitHub 账户的新全局事件数据。点击**继续**。 + +### 步骤 3:设置 `在 TiDB Cloud 中查找表` 操作 + +1. 选择应用和事件 + + 保持模板设置的默认值 `查找表`。点击**继续**。 + +2. 选择账户 + + 1. 点击**登录**按钮,你将被重定向到新的登录页面。 + 2. 在登录页面,填写你的公钥和私钥。要获取 TiDB Cloud API 密钥,请按照 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication/API-Key-Management)中的说明操作。 + 3. 点击**继续**。 + + ![账户](/media/tidb-cloud/zapier/zapier-tidbcloud-account.png) + +3. 设置操作 + + 在此步骤中,你需要指定 TiDB Cloud 集群中的一个表来存储事件数据。如果你还没有表,可以通过此步骤创建一个。 + + 1. 从下拉列表中选择项目名称和集群名称。你的集群的连接信息将自动显示。 + + ![设置项目名称和集群名称](/media/tidb-cloud/zapier/zapier-set-up-tidbcloud-project-and-cluster.png) + + 2. 输入你的密码。 + + 3. 从下拉列表中选择数据库。 + + ![设置数据库名称](/media/tidb-cloud/zapier/zapier-set-up-tidbcloud-databse.png) + + Zapier 使用你输入的密码从 TiDB Cloud 查询数据库。如果在你的集群中找不到数据库,请重新输入密码并刷新页面。 + + 4. 在**你想要搜索的表**框中,填入 `github_global_event`。如果表不存在,模板将使用以下 DDL 创建表。点击**继续**。 + + ![创建表 DDL](/media/tidb-cloud/zapier/zapier-tidbcloud-create-table-ddl.png) + +4. 测试操作 + + 点击**测试操作**,Zapier 将创建表。你也可以跳过测试,表将在此工作流首次运行时创建。 + +### 步骤 4:设置 `在 TiDB Cloud 中创建行` 操作 + +1. 选择应用和事件 + + 保持模板设置的默认值。点击**继续**。 + +2. 选择账户 + + 选择你在设置 `在 TiDB Cloud 中查找表` 操作时选择的账户。点击**继续**。 + + ![选择账户](/media/tidb-cloud/zapier/zapier-tidbcloud-choose-account.png) + +3. 设置操作 + + 1. 按照前面的步骤填写**项目名称**、**集群名称**、**TiDB 密码**和**数据库名称**。 + + 2. 在**表名**中,从下拉列表中选择 **github_global_event** 表。表的列将显示出来。 + + ![表列](/media/tidb-cloud/zapier/zapier-set-up-tidbcloud-columns.png) + + 3. 在**列**框中,从触发器中选择相应的数据。填写所有列,然后点击**继续**。 + + ![填写列](/media/tidb-cloud/zapier/zapier-fill-in-tidbcloud-triggers-data.png) + +4. 测试操作 + + 点击**测试操作**在表中创建新行。如果你检查你的 TiDB Cloud 集群,你可以发现数据已成功写入。 + + ```sql + mysql> SELECT * FROM test.github_global_event; + +-------------+-------------+------------+-----------------+----------------------------------------------+--------+---------------------+ + | id | type | actor | repo_name | repo_url | public | created_at | + +-------------+-------------+------------+-----------------+----------------------------------------------+--------+---------------------+ + | 25324462424 | CreateEvent | shiyuhang0 | shiyuhang0/docs | https://api.github.com/repos/shiyuhang0/docs | True | 2022-11-18 08:03:14 | + +-------------+-------------+------------+-----------------+----------------------------------------------+--------+---------------------+ + 1 row in set (0.17 sec) + ``` + +### 步骤 5:发布你的 zap + +点击**发布**来发布你的 zap。你可以在[主页](https://zapier.com/app/zaps)上看到 zap 正在运行。 + +![发布 zap](/media/tidb-cloud/zapier/zapier-tidbcloud-publish.png) + +现在,这个 zap 将自动将你的 GitHub 账户的所有全局事件记录到 TiDB Cloud 中。 + +## 触发器和操作 + +[触发器和操作](https://zapier.com/how-it-works)是 Zapier 中的关键概念。通过组合不同的触发器和操作,你可以创建各种自动化工作流。 + +本节介绍 Zapier 上的 TiDB Cloud 应用提供的触发器和操作。 + +### 触发器 + +下表列出了 TiDB Cloud 应用支持的触发器。 + +| 触发器 | 描述 | +| ---------------------- |-----------------------------------------------------------------------------| +| 新集群 | 在创建新集群时触发。 | +| 新表 | 在创建新表时触发。 | +| 新行 | 在创建新行时触发。仅获取最近的 10000 个新行。 | +| 新行(自定义查询) | 在你提供的自定义查询返回新行时触发。 | + +### 操作 + +下表列出了 TiDB Cloud 应用支持的操作。注意,某些操作需要额外的资源,你需要在使用操作之前准备相应的资源。 + +| 操作 | 描述 | 资源 | +|---|---|---| +| 查找集群 | 查找现有的 TiDB Cloud Serverless 或 TiDB Cloud Dedicated 集群。 | 无 | +| 创建集群 | 创建新集群。仅支持创建 TiDB Cloud Serverless 集群。 | 无 | +| 查找数据库 | 查找现有数据库。 | TiDB Cloud Serverless 集群 | +| 创建数据库 | 创建新数据库。 | TiDB Cloud Serverless 集群 | +| 查找表 | 查找现有表。 | TiDB Cloud Serverless 集群和数据库 | +| 创建表 | 创建新表。 | TiDB Cloud Serverless 集群和数据库 | +| 创建行 | 创建新行。 | TiDB Cloud Serverless 集群、数据库和表 | +| 更新行 | 更新现有行。 | TiDB Cloud Serverless 集群、数据库和表 | +| 查找行 | 通过查找列在表中查找行。 | TiDB Cloud Serverless 集群、数据库和表 | +| 查找行(自定义查询) | 通过你提供的自定义查询在表中查找行。 | TiDB Cloud Serverless 集群、数据库和表 | + +## TiDB Cloud 应用模板 + +TiDB Cloud 在 Zapier 上提供了一些可直接使用的模板。你可以在 [TiDB Cloud 应用](https://zapier.com/apps/tidb-cloud/integrations)页面找到所有模板。 + +以下是一些示例: + +- [在 Google Sheets 中复制新的 TiDB Cloud 行](https://zapier.com/apps/google-sheets/integrations/tidb-cloud/1134881/duplicate-new-tidb-cloud-rows-in-google-sheets) +- [从新的自定义 TiDB 查询通过 Gmail 发送邮件](https://zapier.com/apps/gmail/integrations/tidb-cloud/1134903/send-emails-via-gmail-from-new-custom-tidb-queries) +- [从新捕获的 webhook 向 TiDB Cloud 添加行](https://zapier.com/apps/tidb-cloud/integrations/webhook/1134955/add-rows-to-tidb-cloud-from-newly-caught-webhooks) +- [将新的 Salesforce 联系人存储在 TiDB 行中](https://zapier.com/apps/salesforce/integrations/tidb-cloud/1134923/store-new-salesforce-contacts-on-tidb-rows) +- [为带有简历的新 Gmail 邮件创建 TiDB 行并发送直接 Slack 通知](https://zapier.com/apps/gmail/integrations/slack/1135456/create-tidb-rows-for-new-gmail-emails-with-resumes-and-send-direct-slack-notifications) + +## 常见问题 + +### 如何在 Zapier 中设置 TiDB Cloud 账户? + +Zapier 需要你的 **TiDB Cloud API 密钥**来连接你的 TiDB Cloud 账户。Zapier 不需要你的 TiDB Cloud 登录账户。 + +要获取你的 TiDB Cloud API 密钥,请按照 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication/API-Key-Management)操作。 + +### TiDB Cloud 触发器如何执行去重? + +Zapier 触发器可以通过轮询 API 调用定期检查新数据(间隔取决于你的 Zapier 计划)。 + +TiDB Cloud 触发器提供了一个返回大量结果的轮询 API 调用。然而,大多数结果都已被 Zapier 见过,也就是说,大多数结果都是重复的。 + +由于我们不希望在 API 中的项目在多个不同的轮询中存在时多次触发操作,TiDB Cloud 触发器使用 `id` 字段对数据进行去重。 + +`新集群`和`新表`触发器只是简单地使用 `cluster_id` 或 `table_id` 作为 `id` 字段来进行去重。你无需为这两个触发器做任何事情。 + +**新行触发器** + +`新行`触发器在每次获取时限制 10,000 个结果。因此,如果某些新行不包含在这 10,000 个结果中,它们就无法触发 Zapier。 + +避免这种情况的一种方法是在触发器中指定 `Order By` 配置。例如,一旦你按创建时间对行进行排序,新行将始终包含在 10,000 个结果中。 + +`新行`触发器还使用灵活的策略生成 `id` 字段来进行去重。触发器按以下顺序生成 `id` 字段: + +1. 如果结果包含 `id` 列,使用 `id` 列。 +2. 如果你在触发器配置中指定了 `去重键`,使用 `去重键`。 +3. 如果表有主键,使用主键。如果有多个主键,使用第一列。 +4. 如果表有唯一键,使用唯一键。 +5. 使用表的第一列。 + +**新行(自定义查询)触发器** + +`新行(自定义查询)`触发器在每次获取时限制 1,000,000 个结果。1,000,000 是一个很大的数字,设置它只是为了保护整个系统。建议你的查询包含 `ORDER BY` 和 `LIMIT`。 + +要执行去重,你的查询结果必须有一个唯一的 id 字段。否则,你将收到 `你必须返回带有 id 字段的结果` 错误。 + +确保你的自定义查询在 30 秒内执行完成。否则,你将收到超时错误。 + +### 如何使用 `查找或创建` 操作? + +`查找或创建`操作使你能够在资源不存在时创建它。以下是一个示例: + +1. 选择 `查找表` 操作 + +2. 在`设置操作`步骤中,勾选 `如果表不存在则创建 TiDB Cloud 表?` 框以启用 `查找并创建`。 + + ![查找并创建](/media/tidb-cloud/zapier/zapier-tidbcloud-find-and-create.png) + +此工作流将在表不存在时创建表。注意,如果你测试你的操作,表将直接创建。 diff --git a/tidb-cloud/key-concepts.md b/tidb-cloud/key-concepts.md new file mode 100644 index 000000000000..d1224a5ae347 --- /dev/null +++ b/tidb-cloud/key-concepts.md @@ -0,0 +1,59 @@ +--- +title: 关键概念概述 +summary: 了解 TiDB Cloud 中的关键概念。 +--- + +# 关键概念概述 + +本文档提供了 [TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 中关键概念的概述。理解这些概念有助于您更好地使用 TiDB Cloud 的功能和特性。 + +## 架构 + +TiDB Cloud 基于云原生分布式架构构建,实现了计算与存储分离,从而支持弹性扩展和高可用性。[了解更多 TiDB Cloud 架构信息](/tidb-cloud/architecture-concepts.md)。 + +## 数据库模式 + +TiDB Cloud 使您能够使用数据库、表、列、索引和约束等对象来组织和构建数据。它还支持临时表、向量索引和缓存表等高级功能。[了解更多数据库模式信息](/tidb-cloud/database-schema-concepts.md)。 + +## 事务 + +TiDB 提供完整的分布式事务支持,其模型在 [Google Percolator](https://research.google.com/pubs/pub36726.html) 的基础上进行了一些优化。[了解更多事务信息](/tidb-cloud/transaction-concepts.md)。 + +## SQL + +TiDB 高度兼容 MySQL 协议以及 MySQL 5.7 和 MySQL 8.0 的常用功能和语法。[了解更多 TiDB Cloud 中的 SQL 信息](/tidb-cloud/sql-concepts.md)。 + +## AI 功能 + +TiDB Cloud 中的 AI 功能使您能够充分利用先进技术进行数据探索、搜索和集成。[了解更多 AI 功能信息](/tidb-cloud/ai-feature-concepts.md)。 + +## 数据服务(Beta) + +数据服务使您能够通过自定义 API 端点使用 HTTPS 请求访问 TiDB Cloud 数据。[了解更多数据服务信息](/tidb-cloud/data-service-concepts.md)。 + +## 可扩展性 + +TiDB Cloud Dedicated 让您可以根据数据量或工作负载的变化分别调整其计算和存储资源。[了解更多可扩展性信息](/tidb-cloud/scalability-concepts.md)。 + +## 高可用性 + +TiDB Cloud 在 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 集群中都确保高可用性: + +- [TiDB Cloud Serverless 中的高可用性](/tidb-cloud/serverless-high-availability.md) +- [TiDB Cloud Dedicated 中的高可用性](/tidb-cloud/high-availability-with-multi-az.md) + +## 监控 + +TiDB Cloud 为集群性能和健康状况提供全面的监控功能。[了解更多监控信息](/tidb-cloud/monitoring-concepts.md)。 + +## 数据流 + +TiDB Cloud 允许您将数据变更从 TiDB 集群流式传输到 Kafka、MySQL 和对象存储等其他系统。[了解更多数据流信息](/tidb-cloud/data-streaming-concepts.md)。 + +## 备份和恢复 + +TiDB Cloud 提供自动备份解决方案和时间点恢复(PITR)功能。[了解更多备份和恢复信息](/tidb-cloud/backup-and-restore-concepts.md)。 + +## 安全性 + +TiDB Cloud 提供了一个强大而灵活的安全框架,旨在保护数据、执行访问控制并满足现代合规标准。[了解更多安全性信息](/tidb-cloud/security-concepts.md)。 diff --git a/tidb-cloud/limitations-and-quotas.md b/tidb-cloud/limitations-and-quotas.md new file mode 100644 index 000000000000..8f73d279d54d --- /dev/null +++ b/tidb-cloud/limitations-and-quotas.md @@ -0,0 +1,35 @@ +--- +title: TiDB Cloud Dedicated 限制和配额 +summary: 了解 TiDB Cloud 中的限制和配额。 +--- + +# TiDB Cloud Dedicated 限制和配额 + +TiDB Cloud 限制了你在 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中可以创建的每种组件的数量,以及 TiDB 的常见使用限制。此外,还有一些组织级别的配额来限制用户创建的资源数量,以防创建超出实际需要的资源。这些表格概述了限制和配额。 + +> **注意:** +> +> 如果这些限制或配额中的任何一个对你的组织造成问题,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +## 集群限制 + +| 组件 | 限制 | +|:-|:-| +| 每个[数据 region](/tidb-cloud/tidb-cloud-glossary.md#region) 的副本数量 | 3 | +| 跨可用区部署的可用区数量 | 3 | + +> **注意:** +> +> 如果你想了解更多关于 TiDB 的常见使用限制,请参考 [TiDB 限制](https://docs.pingcap.com/tidb/stable/tidb-limitations)。 + +## 集群配额 + +| 组件 | 配额(默认) | +|:-|:-| +| 组织中所有集群的 TiDB 节点总数上限 | 10 | +| 组织中所有集群的 TiKV 节点总数上限 | 15 | +| 组织中所有集群的 TiFlash 节点总数上限 | 5 | + +> **注意:** +> +> 如果这些限制或配额中的任何一个对你的组织造成问题,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 diff --git a/tidb-cloud/limited-sql-features.md b/tidb-cloud/limited-sql-features.md new file mode 100644 index 000000000000..3c89ea4c5cc2 --- /dev/null +++ b/tidb-cloud/limited-sql-features.md @@ -0,0 +1,242 @@ +--- +title: TiDB Cloud 上的受限 SQL 功能 +summary: 了解 TiDB Cloud 上的受限 SQL 功能。 +--- + +# TiDB Cloud 上的受限 SQL 功能 + +TiDB Cloud 可以支持几乎所有 TiDB 支持的工作负载,但在 TiDB 自托管版本和 TiDB Cloud Dedicated/Serverless 版本之间存在一些功能差异。本文描述了 TiDB Cloud 上的 SQL 功能限制。我们正在不断填补 TiDB 自托管版本和 TiDB Cloud Dedicated/Serverless 版本之间的功能差距。如果你需要这些差距中的功能或能力,请[联系我们](/tidb-cloud/tidb-cloud-support.md)提出功能请求。 + +## 语句 + +### 放置和范围管理 + +| 语句 | TiDB Cloud Dedicated | TiDB Cloud Serverless | +|:-|:-|:-| +| `ALTER PLACEMENT POLICY` | 支持 | 不支持 [^1] | +| `CREATE PLACEMENT POLICY` | 支持 | 不支持 [^1] | +| `DROP PLACEMENT POLICY` | 支持 | 不支持 [^1] | +| `SHOW CREATE PLACEMENT POLICY` | 支持 | 不支持 [^1] | +| `SHOW PLACEMENT` | 支持 | 不支持 [^1] | +| `SHOW PLACEMENT FOR` | 支持 | 不支持 [^1] | +| `SHOW PLACEMENT LABELS` | 支持 | 不支持 [^1] | +| `SHOW TABLE REGIONS` | 支持 | 不支持 [^1] | +| `SPLIT REGION` | 支持 | 不支持 [^1] | + +### 资源组 + +| 语句 | TiDB Cloud Dedicated | TiDB Cloud Serverless | +|:-|:-|:-| +| `ALTER RESOURCE GROUP` | 支持 | 不支持 [^2] | +| `CALIBRATE RESOURCE` | 不支持 | 不支持 [^2] | +| `CREATE RESOURCE GROUP` | 支持 | 不支持 [^2] | +| `DROP RESOURCE GROUP` | 支持 | 不支持 [^2] | +| `SET RESOURCE GROUP` | 支持 | 不支持 [^2] | +| `SHOW CREATE RESOURCE GROUP` | 支持 | 不支持 [^2] | + +### 其他 + +| 语句 | TiDB Cloud Dedicated | TiDB Cloud Serverless | +|:-|:-|:-| +| `BACKUP` | 支持 | 不支持 [^3] | +| `SHOW BACKUPS` | 支持 | 不支持 [^3] | +| `RESTORE` | 支持 | 不支持 [^3] | +| `SHOW RESTORES` | 支持 | 不支持 [^3] | +| `ADMIN RESET TELEMETRY_ID` | 支持 | TiDB Cloud Serverless 不支持遥测。 | +| `ADMIN SHOW TELEMETRY` | 不支持 [^4] | 不支持 [^4] | +| `ADMIN SHOW SLOW` | 支持 | 不支持 [^5] | +| `ADMIN PLUGINS ENABLE` | 支持 | 不支持 [^8] | +| `ADMIN PLUGINS DISABLE` | 支持 | 不支持 [^8] | +| `ALTER INSTANCE RELOAD TLS` | 支持 | TiDB Cloud Serverless 自动刷新 TLS 证书。 | +| `LOAD DATA INFILE` | 支持 `LOAD DATA LOCAL INFILE` 和从 Amazon S3 或 Google Cloud Storage 导入的 `LOAD DATA INFILE` | 仅支持 `LOAD DATA LOCAL INFILE` | +| `CHANGE DRAINER` | 不支持 [^7] | 不支持 [^7] | +| `CHANGE PUMP` | 不支持 [^7] | 不支持 [^7] | +| `FLASHBACK CLUSTER` | 支持 | 不支持 [^3] | +| `LOAD STATS` | 支持 | 不支持 | +| `SELECT ... INTO OUTFILE` | 不支持 [^4] | 不支持 [^4] | +| `SET CONFIG` | 不支持 [^4] | 不支持 [^4] | +| `SHOW CONFIG` | 不支持 [^4] | 不支持 [^4] | +| `SHOW DRAINER STATUS` | 不支持 [^7] | 不支持 [^7] | +| `SHOW PLUGINS` | 支持 | 不支持 [^8] | +| `SHOW PUMP STATUS` | 不支持 [^7] | 不支持 [^7] | +| `SHUTDOWN` | 不支持 [^4] | 不支持 [^4] | +| `PLAN REPLAYER` | 支持 | 以不同方式支持[^11] | + +## 函数和运算符 + +| 函数和运算符 | TiDB Cloud Dedicated | TiDB Cloud Serverless | +|:-|:-|:-| +| `SLEEP` | 无限制 | [`SLEEP()` 函数](https://docs.pingcap.com/tidbcloud/miscellaneous-functions)有限制,最大睡眠时间为 300 秒。| + +## 系统表 + +| 数据库 | 表 | TiDB Cloud Dedicated | TiDB Cloud Serverless | +|:-|:-|:-|:-| +| `information_schema` | `ATTRIBUTES` | 支持 | 不支持 [^1] | +| `information_schema` | `CLUSTER_CONFIG` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `CLUSTER_HARDWARE` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `CLUSTER_INFO` | 支持 | 不支持 [^1] | +| `information_schema` | `CLUSTER_LOAD` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `CLUSTER_LOG` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `CLUSTER_SLOW_QUERY` | 支持 | 不支持 [^5] | +| `information_schema` | `CLUSTER_STATEMENTS_SUMMARY` | 支持 | 不支持 [^6] | +| `information_schema` | `CLUSTER_STATEMENTS_SUMMARY_EVICTED` | 支持 | 不支持 [^6] | +| `information_schema` | `CLUSTER_STATEMENTS_SUMMARY_HISTORY` | 支持 | 不支持 [^6] | +| `information_schema` | `CLUSTER_SYSTEMINFO` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `INSPECTION_RESULT` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `INSPECTION_RULES` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `INSPECTION_SUMMARY` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `METRICS_SUMMARY` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `METRICS_SUMMARY_BY_LABEL` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `METRICS_TABLES` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `PLACEMENT_POLICIES` | 支持 | 不支持 [^1] | +| `information_schema` | `RESOURCE_GROUPS` | 支持 | 不支持 [^2] | +| `information_schema` | `SLOW_QUERY` | 支持 | 不支持 [^5] | +| `information_schema` | `STATEMENTS_SUMMARY` | 支持 | 不支持 [^6] | +| `information_schema` | `STATEMENTS_SUMMARY_EVICTED` | 支持 | 不支持 [^6] | +| `information_schema` | `STATEMENTS_SUMMARY_HISTORY` | 支持 | 不支持 [^6] | +| `information_schema` | `TIDB_HOT_REGIONS` | 不支持 [^4] | 不支持 [^4] | +| `information_schema` | `TIDB_HOT_REGIONS_HISTORY` | 支持 | 不支持 [^1] | +| `information_schema` | `TIDB_SERVERS_INFO` | 支持 | 不支持 [^1] | +| `information_schema` | `TIKV_REGION_PEERS` | 支持 | 不支持 [^1] | +| `information_schema` | `TIKV_REGION_STATUS` | 支持 | 不支持 [^1] | +| `information_schema` | `TIKV_STORE_STATUS` | 支持 | 不支持 [^1] | +| `performance_schema` | `pd_profile_allocs` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `pd_profile_block` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `pd_profile_cpu` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `pd_profile_goroutines` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `pd_profile_memory` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `pd_profile_mutex` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `tidb_profile_allocs` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `tidb_profile_block` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `tidb_profile_cpu` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `tidb_profile_goroutines` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `tidb_profile_memory` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `tidb_profile_mutex` | 不支持 [^4] | 不支持 [^4] | +| `performance_schema` | `tikv_profile_cpu` | 不支持 [^4] | 不支持 [^4] | +| `mysql` | `expr_pushdown_blacklist` | 不支持 [^4] | 不支持 [^4] | +| `mysql` | `gc_delete_range` | 不支持 [^4] | 不支持 [^4] | +| `mysql` | `gc_delete_range_done` | 不支持 [^4] | 不支持 [^4] | +| `mysql` | `opt_rule_blacklist` | 不支持 [^4] | 不支持 [^4] | +| `mysql` | `tidb` | 不支持 [^4] | 不支持 [^4] | + +## 系统变量 + +| 变量 | TiDB Cloud Dedicated | TiDB Cloud Serverless | +|:-|:-|:-| +| `datadir` | 无限制 | 不支持 [^1] | +| `interactive_timeout` | 无限制 | 只读 [^10] | +| `max_allowed_packet` | 无限制 | 只读 [^10] | +| `plugin_dir` | 无限制 | 不支持 [^8] | +| `plugin_load` | 无限制 | 不支持 [^8] | +| `require_secure_transport` | 不支持 [^12] | 只读 [^10] | +| `skip_name_resolve` | 无限制 | 只读 [^10] | +| `sql_log_bin` | 无限制 | 只读 [^10] | +| `tidb_cdc_write_source` | 无限制 | 只读 [^10] | +| `tidb_check_mb4_value_in_utf8` | 不支持 [^4] | 不支持 [^4] | +| `tidb_config` | 不支持 [^4] | 不支持 [^4] | +| `tidb_ddl_disk_quota` | 无限制 | 只读 [^10] | +| `tidb_ddl_enable_fast_reorg` | 无限制 | 只读 [^10] | +| `tidb_ddl_error_count_limit` | 无限制 | 只读 [^10] | +| `tidb_ddl_flashback_concurrency` | 无限制 | 只读 [^10] | +| `tidb_ddl_reorg_batch_size` | 无限制 | 只读 [^10] | +| `tidb_ddl_reorg_priority` | 无限制 | 只读 [^10] | +| `tidb_ddl_reorg_worker_cnt` | 无限制 | 只读 [^10] | +| `tidb_enable_1pc` | 无限制 | 只读 [^10] | +| `tidb_enable_async_commit` | 无限制 | 只读 [^10] | +| `tidb_enable_auto_analyze` | 无限制 | 只读 [^10] | +| `tidb_enable_collect_execution_info` | 不支持 [^4] | 不支持 [^4] | +| `tidb_enable_ddl` | 无限制 | 只读 [^10] | +| `tidb_enable_gc_aware_memory_track` | 无限制 | 只读 [^10] | +| `tidb_enable_gogc_tuner` | 无限制 | 只读 [^10] | +| `tidb_enable_local_txn` | 无限制 | 只读 [^10] | +| `tidb_enable_resource_control` | 无限制 | 只读 [^10] | +| `tidb_enable_slow_log` | 不支持 [^4] | 不支持 [^4] | +| `tidb_enable_stmt_summary` | 无限制 | 只读 [^10] | +| `tidb_enable_telemetry` | 不支持 [^4] | 不支持 [^4] | +| `tidb_enable_top_sql` | 无限制 | 只读 [^10] | +| `tidb_enable_tso_follower_proxy` | 无限制 | 只读 [^10] | +| `tidb_expensive_query_time_threshold` | 不支持 [^4] | 不支持 [^4] | +| `tidb_force_priority` | 不支持 [^4] | 不支持 [^4] | +| `tidb_gc_concurrency` | 无限制 | 只读 [^10] | +| `tidb_gc_enable` | 无限制 | 只读 [^10] | +| `tidb_gc_max_wait_time` | 无限制 | 只读 [^10] | +| `tidb_gc_run_interval` | 无限制 | 只读 [^10] | +| `tidb_gc_scan_lock_mode` | 无限制 | 只读 [^10] | +| `tidb_general_log` | 不支持 [^4] | 不支持 [^4] | +| `tidb_generate_binary_plan` | 无限制 | 只读 [^10] | +| `tidb_gogc_tuner_threshold` | 无限制 | 只读 [^10] | +| `tidb_guarantee_linearizability` | 无限制 | 只读 [^10] | +| `tidb_isolation_read_engines` | 无限制 | 只读 [^10] | +| `tidb_log_file_max_days` | 无限制 | 只读 [^10] | +| `tidb_memory_usage_alarm_ratio` | 不支持 [^4] | 不支持 [^4] | +| `tidb_metric_query_range_duration` | 不支持 [^4] | 不支持 [^4] | +| `tidb_metric_query_step` | 不支持 [^4] | 不支持 [^4] | +| `tidb_opt_write_row_id` | 不支持 [^4] | 不支持 [^4] | +| `tidb_placement_mode` | 无限制 | 只读 [^10] | +| `tidb_pprof_sql_cpu` | 不支持 [^4] | 不支持 [^4] | +| `tidb_record_plan_in_slow_log` | 不支持 [^4] | 不支持 [^4] | +| `tidb_redact_log` | 不支持 [^4] | 不支持 [^4] | +| `tidb_restricted_read_only` | 不支持 [^4] | 不支持 [^4] | +| `tidb_row_format_version` | 不支持 [^4] | 不支持 [^4] | +| `tidb_scatter_region` | 无限制 | 只读 [^10] | +| `tidb_server_memory_limit` | 无限制 | 只读 [^10] | +| `tidb_server_memory_limit_gc_trigger` | 无限制 | 只读 [^10] | +| `tidb_server_memory_limit_sess_min_size` | 无限制 | 只读 [^10] | +| `tidb_simplified_metrics` | 无限制 | 只读 [^10] | +| `tidb_slow_query_file` | 不支持 [^4] | 不支持 [^4] | +| `tidb_slow_log_threshold` | 不支持 [^4] | 不支持 [^4] | +| `tidb_slow_txn_log_threshold` | 不支持 [^4] | 不支持 [^4] | +| `tidb_stats_load_sync_wait` | 无限制 | 只读 [^10] | +| `tidb_stmt_summary_history_size` | 无限制 | 只读 [^10] | +| `tidb_stmt_summary_internal_query` | 无限制 | 只读 [^10] | +| `tidb_stmt_summary_max_sql_length` | 无限制 | 只读 [^10] | +| `tidb_stmt_summary_max_stmt_count` | 无限制 | 只读 [^10] | +| `tidb_stmt_summary_refresh_interval` | 无限制 | 只读 [^10] | +| `tidb_sysproc_scan_concurrency` | 无限制 | 只读 [^10] | +| `tidb_top_sql_max_meta_count` | 不支持 [^4] | 不支持 [^4] | +| `tidb_top_sql_max_time_series_count` | 不支持 [^4] | 不支持 [^4] | +| `tidb_tso_client_batch_max_wait_time` | 无限制 | 只读 [^10] | +| `tidb_ttl_delete_batch_size` | 无限制 | 只读 [^10] | +| `tidb_ttl_delete_rate_limit` | 无限制 | 只读 [^10] | +| `tidb_ttl_delete_worker_count` | 无限制 | 只读 [^10] | +| `tidb_ttl_job_schedule_window_end_time` | 无限制 | 只读 [^10] | +| `tidb_ttl_job_schedule_window_start_time` | 无限制 | 只读 [^10] | +| `tidb_ttl_running_tasks` | 无限制 | 只读 [^10] | +| `tidb_ttl_scan_batch_size` | 无限制 | 只读 [^10] | +| `tidb_ttl_scan_worker_count` | 无限制 | 只读 [^10] | +| `tidb_txn_mode` | 无限制 | 只读 [^10] | +| `tidb_wait_split_region_finish` | 无限制 | 只读 [^10] | +| `tidb_wait_split_region_timeout` | 无限制 | 只读 [^10] | +| `txn_scope` | 无限制 | 只读 [^10] | +| `validate_password.enable` | 无限制 | 始终启用 [^9] | +| `validate_password.length` | 无限制 | 至少 `8` [^9] | +| `validate_password.mixed_case_count` | 无限制 | 至少 `1` [^9] | +| `validate_password.number_count` | 无限制 | 至少 `1` [^9] | +| `validate_password.policy` | 无限制 | 只能是 `MEDIUM` 或 `STRONG` [^9] | +| `validate_password.special_char_count` | 无限制 | 至少 `1` [^9] | +| `wait_timeout` | 无限制 | 只读 [^10] | + +[^1]: TiDB Cloud Serverless 不支持配置数据放置。 + +[^2]: TiDB Cloud Serverless 不支持配置资源组。 + +[^3]: 要在 TiDB Cloud Serverless 上执行[备份和恢复](/tidb-cloud/backup-and-restore-serverless.md)操作,你可以使用 TiDB Cloud 控制台。 + +[^4]: 该功能在[安全增强模式(SEM)](/system-variables.md#tidb_enable_enhanced_security)下不可用。 + +[^5]: 要在 TiDB Cloud Serverless 上跟踪[慢查询](/tidb-cloud/tune-performance.md#slow-query),你可以使用 TiDB Cloud 控制台。 + +[^6]: 要在 TiDB Cloud Serverless 上执行[语句分析](/tidb-cloud/tune-performance.md#statement-analysis),你可以使用 TiDB Cloud 控制台。 + +[^7]: TiDB Cloud 不支持 Drainer 和 Pump。 + +[^8]: TiDB Cloud Serverless 不支持插件。 + +[^9]: TiDB Cloud Serverless 强制执行强密码策略。 + +[^10]: 该变量在 TiDB Cloud Serverless 上为只读。 + +[^11]: TiDB Cloud Serverless 不支持像[示例](https://docs.pingcap.com/tidb/stable/sql-plan-replayer#examples-of-exporting-cluster-information)中那样通过 `${tidb-server-status-port}` 下载由 `PLAN REPLAYER` 导出的文件。相反,TiDB Cloud Serverless 会生成一个[预签名 URL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html)供你下载文件。请注意,此 URL 在生成后 10 小时内有效。 + +[^12]: 不支持。为 TiDB Cloud Dedicated 集群启用 `require_secure_transport` 将导致 SQL 客户端连接失败。 diff --git a/tidb-cloud/manage-serverless-spend-limit.md b/tidb-cloud/manage-serverless-spend-limit.md new file mode 100644 index 000000000000..d15ac1758377 --- /dev/null +++ b/tidb-cloud/manage-serverless-spend-limit.md @@ -0,0 +1,47 @@ +--- +title: 管理 TiDB Cloud Serverless 可扩展集群的支出限额 +summary: 了解如何管理 TiDB Cloud Serverless 可扩展集群的支出限额。 +--- + +# 管理 TiDB Cloud Serverless 可扩展集群的支出限额 + +> **注意:** +> +> 支出限额仅适用于 TiDB Cloud Serverless [可扩展集群](/tidb-cloud/select-cluster-tier.md#可扩展集群计划)。 + +支出限额是指您愿意在一个月内为特定工作负载支付的最大金额。它是一种成本控制机制,允许您为 TiDB Cloud Serverless 可扩展集群设置预算。 + +对于 TiDB Cloud 中的每个组织,默认情况下您最多可以创建五个[免费集群](/tidb-cloud/select-cluster-tier.md#免费集群计划)。要创建更多的 TiDB Cloud Serverless 集群,您需要添加信用卡并创建可扩展集群以供使用。但是,如果您在创建更多集群之前删除了一些之前的集群,则无需信用卡也可以创建新集群。 + +## 使用配额 + +对于您组织中的前五个 TiDB Cloud Serverless 集群,无论是免费还是可扩展集群,TiDB Cloud 都为每个集群提供以下免费使用配额: + +- 行存储:5 GiB +- 列存储:5 GiB +- [请求单元 (RUs)](/tidb-cloud/tidb-cloud-glossary.md#请求单元):每月 5000 万 RUs + +一旦集群达到其使用配额,它会立即拒绝任何新的连接尝试,直到您[增加配额](#更新支出限额)或在新月开始时重置使用量。在达到配额之前建立的现有连接将保持活动状态,但会经历限制。例如,当免费集群的行存储超过 5 GiB 时,集群会自动限制任何新的连接尝试。 + +要了解不同资源(包括读取、写入、SQL CPU 和网络出口)的 RU 消耗、定价详情和限制信息,请参见 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-cloud-serverless-pricing-details)。 + +如果您想创建具有额外配额的 TiDB Cloud Serverless 集群,可以在集群创建页面上编辑支出限额。更多信息,请参见[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)。 + +## 更新支出限额 + +对于 TiDB Cloud Serverless 免费集群,您可以通过将其升级为可扩展集群来增加使用配额。对于现有的可扩展集群,您可以直接调整每月支出限额。 + +要更新 TiDB Cloud Serverless 集群的支出限额,请执行以下步骤: + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面上,点击目标集群的名称进入其概览页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 在**本月使用量**区域,点击**升级到可扩展集群**。 + + 要调整现有可扩展集群的支出限额,点击 **编辑**。 + +3. 根据需要编辑每月支出限额。如果您尚未添加付款方式,则在编辑限额后需要添加信用卡。 +4. 点击**更新集群计划**。 diff --git a/tidb-cloud/manage-user-access.md b/tidb-cloud/manage-user-access.md new file mode 100644 index 000000000000..fc0fdf3e4ee4 --- /dev/null +++ b/tidb-cloud/manage-user-access.md @@ -0,0 +1,336 @@ +--- +title: 身份访问管理 +summary: 了解如何在 TiDB Cloud 中管理身份访问。 +--- + +# 身份访问管理 + +本文档介绍如何在 TiDB Cloud 中管理组织、项目、角色和用户配置文件的访问权限。 + +在访问 TiDB Cloud 之前,请[创建 TiDB Cloud 账号](https://tidbcloud.com/free-trial)。你可以使用电子邮件和密码注册,这样就可以[使用 TiDB Cloud 管理密码](/tidb-cloud/tidb-cloud-password-authentication.md),或者选择使用 Google、GitHub 或 Microsoft 账号进行单点登录(SSO)到 TiDB Cloud。 + +## 组织和项目 + +TiDB Cloud 基于组织和项目提供层级结构,以便于管理 TiDB Cloud 用户和集群。如果你是组织所有者,你可以在组织中创建多个项目。 + +例如: + +``` +- 你的组织 + - 项目 1 + - 集群 1 + - 集群 2 + - 项目 2 + - 集群 3 + - 集群 4 + - 项目 3 + - 集群 5 + - 集群 6 +``` + +在此结构下: + +- 要访问组织,用户必须是该组织的成员。 +- 要访问组织中的项目,用户必须至少具有该组织中项目的读取权限。 +- 要管理项目中的集群,用户必须具有 `Project Owner` 角色。 + +有关用户角色和权限的更多信息,请参见[用户角色](#用户角色)。 + +### 组织 + +一个组织可以包含多个项目。 + +TiDB Cloud 在组织级别计算账单,并提供每个项目的账单详情。 + +如果你是组织所有者,你拥有组织中的最高权限。 + +例如,你可以执行以下操作: + +- 为不同目的创建不同的项目(如开发、暂存和生产)。 +- 为不同用户分配不同的组织角色和项目角色。 +- 配置组织设置。例如,为组织配置时区。 + +### 项目 + +一个项目可以包含多个集群。 + +如果你是项目所有者,你可以管理项目的集群和项目设置。 + +例如,你可以执行以下操作: + +- 根据业务需求创建多个集群。 +- 为不同用户分配不同的项目角色。 +- 配置项目设置。例如,为不同项目配置不同的告警设置。 + +## 用户角色 + +TiDB Cloud 定义了不同的用户角色来管理组织、项目或两者中 TiDB Cloud 用户的不同权限。 + +你可以在组织级别或项目级别为用户授予角色。出于安全考虑,请仔细规划组织和项目的层级结构。 + +### 组织角色 + +在组织级别,TiDB Cloud 定义了四个角色,其中 `Organization Owner` 可以邀请成员并为成员授予组织角色。 + +| 权限 | `Organization Owner` | `Organization Billing Manager` | `Organization Billing Viewer` | `Organization Console Audit Manager` | `Organization Viewer` | +|---|---|---|---|---|---| +| 管理组织设置,如项目、API 密钥和时区。 | ✅ | ❌ | ❌ | ❌ | ❌ | +| 邀请用户加入组织或从组织中移除用户,并编辑用户的组织角色。 | ✅ | ❌ | ❌ | ❌ | ❌ | +| 组织中所有项目的所有 `Project Owner` 权限。 | ✅ | ❌ | ❌ | ❌ | ❌ | +| 创建启用客户管理加密密钥(CMEK)的项目。 | ✅ | ❌ | ❌ | ❌ | ❌ | +| 编辑组织的支付信息。 | ✅ | ✅ | ❌ | ❌ | ❌ | +| 查看账单并使用[成本分析器](/tidb-cloud/tidb-cloud-billing.md#cost-explorer)。 | ✅ | ✅ | ✅ | ❌ | ❌ | +| 管理组织的 TiDB Cloud [控制台审计日志](/tidb-cloud/tidb-cloud-console-auditing.md)。 | ✅ | ❌ | ❌ | ✅ | ❌ | +| 查看组织中的用户和成员所属的项目。 | ✅ | ✅ | ✅ | ✅ | ✅ | + +> **注意:** +> +> - `Organization Console Audit Manager` 角色(从 `Organization Console Audit Admin` 重命名)用于管理 TiDB Cloud 控制台的审计日志,而不是数据库审计日志。要管理数据库审计,请使用项目级别的 `Project Owner` 角色。 +> - `Organization Billing Manager` 角色从 `Organization Billing Admin` 重命名,`Organization Viewer` 角色从 `Organization Member` 重命名。 + +### 项目角色 + +在项目级别,TiDB Cloud 定义了三个角色,其中 `Project Owner` 可以邀请成员并为成员授予项目角色。 + +> **注意:** +> +> - `Organization Owner` 拥有所有项目的所有 Project Owner 权限,因此 `Organization Owner` 也可以邀请项目成员并为成员授予项目角色。 +> - 每个项目角色默认拥有所有 Organization Viewer 权限。 +> - 如果组织中的用户不属于任何项目,该用户没有任何项目权限。 + +| 权限 | `Project Owner` | `Project Data Access Read-Write` | `Project Data Access Read-Only` | `Project Viewer` | +|---|---|---|---|---| +| 管理项目设置 | ✅ | ❌ | ❌ | ❌ | +| 邀请用户加入项目或从项目中移除用户,并编辑用户的项目角色。 | ✅ | ❌ | ❌ | ❌ | +| 管理项目的[数据库审计日志](/tidb-cloud/tidb-cloud-auditing.md)。 | ✅ | ❌ | ❌ | ❌ | +| 管理项目中所有 TiDB Cloud Serverless 集群的[支出限制](/tidb-cloud/manage-serverless-spend-limit.md)。 | ✅ | ❌ | ❌ | ❌ | +| 管理项目中的集群操作,如集群创建、修改和删除。 | ✅ | ❌ | ❌ | ❌ | +| 管理项目中 TiDB Cloud Serverless 集群的分支,如分支创建、连接和删除。 | ✅ | ❌ | ❌ | ❌ | +| 管理项目中 TiDB Cloud Dedicated 集群的[恢复组](/tidb-cloud/recovery-group-overview.md),如恢复组创建和删除。 | ✅ | ❌ | ❌ | ❌ | +| 管理集群数据,如数据导入、数据备份和恢复以及数据迁移。 | ✅ | ✅ | ❌ | ❌ | +| 管理[数据服务](/tidb-cloud/data-service-overview.md)的数据只读操作,如使用或创建端点读取数据。 | ✅ | ✅ | ✅ | ❌ | +| 管理[数据服务](/tidb-cloud/data-service-overview.md)的数据读写操作。 | ✅ | ✅ | ❌ | ❌ | +| 使用 [SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)查看集群数据。 | ✅ | ✅ | ✅ | ❌ | +| 使用 [SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)修改和删除集群数据。 | ✅ | ✅ | ❌ | ❌ | +| 管理[变更数据捕获](/tidb-cloud/changefeed-overview.md)。 | ✅ | ✅ | ✅ | ❌ | +| 查看和重置集群密码。 | ✅ | ❌ | ❌ | ❌ | +| 查看项目中的集群概览、备份记录、指标、事件和[变更数据捕获](/tidb-cloud/changefeed-overview.md)。 | ✅ | ✅ | ✅ | ✅ | + +## 管理组织访问 + +### 查看和切换组织 + +要查看和切换组织,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,点击左上角的组合框。显示你所属的组织和项目列表。 + + > **提示:** + > + > - 如果你当前在特定集群的页面上,点击左上角的组合框后,还需要点击组合框中的 ← 返回组织和项目列表。 + > - 如果你是多个组织的成员,可以在组合框中点击目标组织名称,在组织之间切换账号。 + +2. 要查看组织的详细信息(如组织 ID 和时区),请点击组织名称,然后在左侧导航栏中点击 **Organization Settings** > **General**。 + +### 设置组织时区 + +如果你具有 `Organization Owner` 角色,你可以根据时区修改系统显示时间。 + +要更改本地时区设置,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Organization Settings** > **General**。 + +3. 在 **Time Zone** 部分,从下拉列表中选择你的时区。 + +4. 点击 **Update**。 + +### 邀请组织成员 + +如果你具有 `Organization Owner` 角色,你可以邀请用户加入组织。 + +> **注意:** +> +> 你也可以根据需要直接[邀请用户加入项目](#邀请项目成员),这样用户也会成为组织成员。 + +要邀请成员加入组织,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Organization Settings** > **Users**。 + +3. 在 **Users** 页面,点击 **By Organization** 标签页。 + +4. 点击 **Invite**。 + +5. 输入要邀请的用户的电子邮件地址,然后为该用户选择组织角色。 + + > **提示:** + > + > - 如果你想一次邀请多个成员,可以输入多个电子邮件地址。 + > - 被邀请的用户默认不属于任何项目。要邀请用户加入项目,请参见[邀请项目成员](#邀请项目成员)。 + +6. 点击 **Confirm**。然后新用户成功添加到用户列表中。同时,系统会向被邀请的电子邮件地址发送一封包含验证链接的邮件。 + +7. 收到此邮件后,用户需要点击邮件中的链接验证身份,然后会显示一个新页面。 + +8. 如果被邀请的电子邮件地址尚未注册 TiDB Cloud 账号,用户将被引导到注册页面创建账号。如果该电子邮件地址已注册 TiDB Cloud 账号,用户将被引导到登录页面,登录后账号会自动加入组织。 + +> **注意:** +> +> 邮件中的验证链接将在 24 小时后过期。如果你要邀请的用户没有收到邮件,请点击 **Resend**。 + +### 修改组织角色 + +如果你具有 `Organization Owner` 角色,你可以修改组织中所有成员的组织角色。 + +要修改成员的组织角色,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Organization Settings** > **Users**。 + +3. 在 **Users** 页面,点击 **By Organization** 标签页。 + +4. 点击目标成员的角色,然后修改角色。 + +### 移除组织成员 + +如果你具有 `Organization Owner` 角色,你可以从组织中移除组织成员。 + +要从组织中移除成员,请执行以下步骤: + +> **注意:** +> +> 如果成员从组织中移除,该成员也会从所属的项目中移除。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Organization Settings** > **Users**。 + +3. 在 **Users** 页面,点击 **By Organization** 标签页。 + +4. 在目标成员所在行,点击 **...** > **Delete**。 + +## 管理项目访问 + +### 查看和切换项目 + +要查看和切换项目,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,点击左上角的组合框。显示你所属的组织和项目列表。 + + > **提示:** + > + > - 如果你当前在特定集群的页面上,点击左上角的组合框后,还需要点击组合框中的 ← 返回组织和项目列表。 + > - 如果你是多个项目的成员,可以在组合框中点击目标项目名称,在项目之间切换。 + +2. 要查看项目的详细信息,请点击项目名称,然后在左侧导航栏中点击 **Project Settings**。 + +### 创建项目 + +> **注意:** +> +> 对于免费试用用户,你不能创建新项目。 + +如果你具有 `Organization Owner` 角色,你可以在组织中创建项目。 + +要创建新项目,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Projects**。 + +3. 在 **Projects** 页面,点击 **Create New Project**。 + +4. 输入项目名称。 + +5. 点击 **Confirm**。 + +### 重命名项目 + +如果你具有 `Organization Owner` 角色,你可以重命名组织中的任何项目。如果你具有 `Project Owner` 角色,你可以重命名你的项目。 + +要重命名项目,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Projects**。 + +3. 在要重命名的项目所在行,点击 **...** > **Rename**。 + +4. 输入新的项目名称。 + +5. 点击 **Confirm**。 + +### 邀请项目成员 + +如果你具有 `Organization Owner` 或 `Project Owner` 角色,你可以邀请成员加入项目。 + +> **注意:** +> +> 当不在组织中的用户加入项目时,该用户也会自动加入组织。 + +要邀请成员加入项目,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Organization Settings** > **Users**。 + +3. 在 **Users** 页面,点击 **By Project** 标签页,然后在下拉列表中选择你的项目。 + +4. 点击 **Invite**。 + +5. 输入要邀请的用户的电子邮件地址,然后为该用户选择项目角色。 + + > **提示:** + > + > 如果你想一次邀请多个成员,可以输入多个电子邮件地址。 + +6. 点击 **Confirm**。然后新用户成功添加到用户列表中。同时,系统会向被邀请的电子邮件地址发送一封包含验证链接的邮件。 + +7. 收到此邮件后,用户需要点击邮件中的链接验证身份,然后会显示一个新页面。 + +8. 如果被邀请的电子邮件地址尚未注册 TiDB Cloud 账号,用户将被引导到注册页面创建账号。如果该电子邮件地址已注册 TiDB Cloud 账号,用户将被引导到登录页面。登录后,账号会自动加入项目。 + +> **注意:** +> +> 邮件中的验证链接将在 24 小时后过期。如果你的用户没有收到邮件,请点击 **Resend**。 + +### 修改项目角色 + +如果你具有 `Organization Owner` 角色,你可以修改组织中所有项目成员的项目角色。如果你具有 `Project Owner` 角色,你可以修改项目中所有成员的项目角色。 + +要修改成员的项目角色,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Organization Settings** > **Users**。 + +3. 在 **Users** 页面,点击 **By Project** 标签页,然后在下拉列表中选择你的项目。 + +4. 在目标成员所在行,点击 **Role** 列中的角色,然后从下拉列表中选择新角色。 + +### 移除项目成员 + +如果你具有 `Organization Owner` 或 `Project Owner` 角色,你可以移除项目成员。 + +要从项目中移除成员,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + +2. 在左侧导航栏中,点击 **Organization Settings** > **Users**。 + +3. 在 **Users** 页面,点击 **By Project** 标签页,然后在下拉列表中选择你的项目。 + +4. 在目标成员所在行,点击 **...** > **Delete**。 + +## 管理用户配置文件 + +在 TiDB Cloud 中,你可以轻松管理你的配置文件,包括名字、姓氏和电话号码。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,点击左下角的 。 + +2. 点击 **Account Settings**。 + +3. 在显示的对话框中,更新配置文件信息,然后点击 **Update**。 diff --git a/tidb-cloud/managed-service-provider-customer.md b/tidb-cloud/managed-service-provider-customer.md new file mode 100644 index 000000000000..6b77b8b6aa26 --- /dev/null +++ b/tidb-cloud/managed-service-provider-customer.md @@ -0,0 +1,43 @@ +--- +title: 托管服务提供商客户 +summary: 了解如何成为托管服务提供商 (MSP) 客户。 +--- + +# 托管服务提供商客户 + +托管服务提供商(Managed Service Provider,MSP)客户是使用托管服务提供商提供的 TiDB Cloud 服务的客户。 + +与直接的 TiDB Cloud 客户相比,MSP 客户在注册和发票支付方面有几点不同: + +- MSP 客户需要通过 MSP 提供的专用注册页面注册 TiDB Cloud 账户。 +- MSP 客户通过 MSP 渠道支付发票,而不是直接向 PingCAP 支付。 + +在 TiDB Cloud 控制台上的其他日常操作对直接 TiDB Cloud 客户和 MSP 客户来说都是相同的。 + +本文档描述了如何成为 MSP 客户以及 MSP 客户如何查看历史和未来账单。 + +## 创建新的 MSP 客户账户 + +要创建新的 MSP 客户账户,请访问 MSP 专用注册页面。每个 MSP 都有一个唯一的专用注册页面。请联系你的 MSP 获取注册页面的 URL。 + +## 从直接 TiDB Cloud 账户迁移到 MSP 客户账户 + +> **提示:** +> +> 直接客户是直接从 PingCAP 购买 TiDB Cloud 并支付发票的最终客户。 + +如果你目前是拥有 TiDB Cloud 账户的直接客户,你可以请求你的 MSP 将你的账户迁移到 MSP 客户账户。 + +迁移将在未来某个月的第一天生效。请与你的 MSP 讨论确定具体的生效日期。 + +在迁移生效当天,你将收到一封电子邮件通知。 + +## 查看未来账单 + +一旦你成功成为 MSP 客户,你将通过 MSP 支付发票。请询问你的 MSP 在哪里可以查看你的账单和发票。 + +PingCAP 不会向 MSP 客户发送任何账单和发票。 + +## 查看历史账单 + +如果你已经从直接 TiDB Cloud 账户迁移到 MSP 客户账户,你可以通过访问 TiDB Cloud 控制台中的 **Billing** > **Bills** > **History** 查看迁移之前的历史账单。 diff --git a/tidb-cloud/migrate-from-mysql-using-aws-dms.md b/tidb-cloud/migrate-from-mysql-using-aws-dms.md new file mode 100644 index 000000000000..40b5feab13b3 --- /dev/null +++ b/tidb-cloud/migrate-from-mysql-using-aws-dms.md @@ -0,0 +1,187 @@ +--- +title: 使用 AWS DMS 将 MySQL 兼容数据库迁移至 TiDB Cloud +summary: 了解如何使用 AWS Database Migration Service (AWS DMS) 将数据从 MySQL 兼容数据库迁移至 TiDB Cloud。 +--- + +# 使用 AWS DMS 将 MySQL 兼容数据库迁移至 TiDB Cloud + +如果你想迁移异构数据库(如 PostgreSQL、Oracle 和 SQL Server)到 TiDB Cloud,建议使用 AWS Database Migration Service (AWS DMS)。 + +AWS DMS 是一项云服务,可以轻松迁移关系数据库、数据仓库、NoSQL 数据库和其他类型的数据存储。你可以使用 AWS DMS 将数据迁移到 TiDB Cloud。 + +本文以 Amazon RDS 为例,展示如何使用 AWS DMS 将数据迁移到 TiDB Cloud。此过程也适用于将数据从自托管 MySQL 数据库或 Amazon Aurora 迁移到 TiDB Cloud。 + +在本例中,数据源是 Amazon RDS,数据目标是 TiDB Cloud 中的 TiDB Cloud Dedicated 集群。上游和下游数据库都在同一区域。 + +## 前提条件 + +在开始迁移之前,请确保你已阅读以下内容: + +- 如果源数据库是 Amazon RDS 或 Amazon Aurora,你需要将 `binlog_format` 参数设置为 `ROW`。如果数据库使用默认参数组,`binlog_format` 参数默认为 `MIXED` 且无法修改。在这种情况下,你需要[创建一个新的参数组](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_GettingStarted.Prerequisites.html#CHAP_GettingStarted.Prerequisites.params),例如 `newset`,并将其 `binlog_format` 设置为 `ROW`。然后,[修改默认参数组](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithDBInstanceParamGroups.html#USER_WorkingWithParamGroups.Modifying)为 `newset`。请注意,修改参数组将重启数据库。 +- 检查并确保源数据库使用与 TiDB 兼容的排序规则。TiDB 中 utf8mb4 字符集的默认排序规则是 `utf8mb4_bin`。但在 MySQL 8.0 中,默认排序规则是 `utf8mb4_0900_ai_ci`。如果上游 MySQL 使用默认排序规则,由于 TiDB 不兼容 `utf8mb4_0900_ai_ci`,AWS DMS 无法在 TiDB 中创建目标表并且无法迁移数据。要解决此问题,你需要在迁移前将源数据库的排序规则修改为 `utf8mb4_bin`。有关 TiDB 支持的字符集和排序规则的完整列表,请参见[字符集和排序规则](https://docs.pingcap.com/tidb/stable/character-set-and-collation)。 +- TiDB 默认包含以下系统数据库:`INFORMATION_SCHEMA`、`PERFORMANCE_SCHEMA`、`mysql`、`sys` 和 `test`。当你创建 AWS DMS 迁移任务时,你需要过滤掉这些系统数据库,而不是使用默认的 `%` 来选择迁移对象。否则,AWS DMS 将尝试将这些系统数据库从源数据库迁移到目标 TiDB,这将导致任务失败。为避免此问题,建议填写具体的数据库和表名。 +- 将 AWS DMS 的公网和私网 IP 地址添加到源数据库和目标数据库的 IP 访问列表中。否则,在某些情况下网络连接可能会失败。 +- 使用 [VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md#在-aws-上设置-vpc-对等连接)或[私有端点连接](/tidb-cloud/set-up-private-endpoint-connections.md)来连接 AWS DMS 和 TiDB 集群。 +- 建议将 AWS DMS 和 TiDB 集群使用相同的区域,以获得更好的数据写入性能。 +- 建议使用 AWS DMS `dms.t3.large`(2 个 vCPU 和 8 GiB 内存)或更高实例类型。较小的实例类型可能会导致内存不足(OOM)错误。 +- AWS DMS 将在目标数据库中自动创建 `awsdms_control` 数据库。 + +## 限制 + +- AWS DMS 不支持复制 `DROP TABLE`。 +- AWS DMS 支持基本的架构迁移,包括创建表和主键。但是,AWS DMS 不会自动在 TiDB Cloud 中创建二级索引、外键或用户账户。如果需要,你必须手动在 TiDB 中创建这些对象,包括带有二级索引的表。更多信息,请参见 [Migration planning for AWS Database Migration Service](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_BestPractices.html#CHAP_SettingUp.MigrationPlanning)。 + +## 步骤 1. 创建 AWS DMS 复制实例 + +1. 在 AWS DMS 控制台中转到[复制实例](https://console.aws.amazon.com/dms/v2/home#replicationInstances)页面,并切换到相应的区域。建议 AWS DMS 使用与 TiDB Cloud 相同的区域。在本文档中,上游和下游数据库以及 DMS 实例都在 **us-west-2** 区域。 + +2. 点击**创建复制实例**。 + + ![创建复制实例](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-create-instance.png) + +3. 填写实例名称、ARN 和描述。 + +4. 填写实例配置: + - **实例类型**:选择适当的实例类型。建议使用 `dms.t3.large` 或更高实例类型以获得更好的性能。 + - **引擎版本**:使用默认配置。 + - **多可用区**:根据业务需求选择**单可用区**或**多可用区**。 + +5. 在**分配存储(GiB)**字段中配置存储。使用默认配置。 + +6. 配置连接和安全性。 + - **网络类型 - 新**:选择 **IPv4**。 + - **IPv4 的虚拟私有云(VPC)**:选择你需要的 VPC。建议使用与上游数据库相同的 VPC 以简化网络配置。 + - **复制子网组**:为你的复制实例选择一个子网组。 + - **公共可访问**:使用默认配置。 + +7. 根据需要配置**高级设置**、**维护**和**标签**。点击**创建复制实例**完成实例创建。 + +## 步骤 2. 创建源数据库端点 + +1. 在 [AWS DMS 控制台](https://console.aws.amazon.com/dms/v2/home)中,点击你刚刚创建的复制实例。复制公网和私网 IP 地址,如下图所示。 + + ![复制公网和私网 IP 地址](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-copy-ip.png) + +2. 配置 Amazon RDS 的安全组规则。在本例中,将 AWS DMS 实例的公网和私网 IP 地址添加到安全组中。 + + ![配置安全组规则](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-rules.png) + +3. 点击**创建端点**以创建源数据库端点。 + + ![点击创建端点](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-endpoint.png) + +4. 在本例中,点击**选择 RDS DB 实例**,然后选择源 RDS 实例。如果源数据库是自托管 MySQL,你可以跳过此步骤,直接在后续步骤中填写信息。 + + ![选择 RDS DB 实例](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-select-rds.png) + +5. 配置以下信息: + - **端点标识符**:为源端点创建一个标签,以帮助你在后续任务配置中识别它。 + - **描述性 Amazon Resource Name (ARN) - 可选**:为默认 DMS ARN 创建一个友好名称。 + - **源引擎**:选择 **MySQL**。 + - **访问端点数据库**:选择**手动提供访问信息**。 + - **服务器名称**:填写数据提供者的数据服务器名称。你可以从数据库控制台复制它。如果上游是 Amazon RDS 或 Amazon Aurora,名称将自动填充。如果是没有域名的自托管 MySQL,你可以填写 IP 地址。 + - 填写源数据库的**端口**、**用户名**和**密码**。 + - **安全套接字层 (SSL) 模式**:你可以根据需要启用 SSL 模式。 + + ![填写端点配置](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-endpoint-config.png) + +6. 对于**端点设置**、**KMS 密钥**和**标签**,使用默认值。在**测试端点连接(可选)**部分,建议选择与源数据库相同的 VPC 以简化网络配置。选择相应的复制实例,然后点击**运行测试**。状态需要为**成功**。 + +7. 点击**创建端点**。 + + ![点击创建端点](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-connection.png) +## 步骤 3. 创建目标数据库端点 + +1. 在 [AWS DMS 控制台](https://console.aws.amazon.com/dms/v2/home)中,点击你刚刚创建的复制实例。复制公网和私网 IP 地址,如下图所示。 + + ![复制公网和私网 IP 地址](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-copy-ip.png) + +2. 在 TiDB Cloud 控制台中,转到[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称,然后点击右上角的**连接**以获取 TiDB Cloud 数据库连接信息。 + +3. 在对话框中的**步骤 1:创建流量过滤器**下,点击**编辑**,输入你从 AWS DMS 控制台复制的公网和私网 IP 地址,然后点击**更新过滤器**。建议同时将 AWS DMS 复制实例的公网 IP 地址和私网 IP 地址添加到 TiDB 集群的流量过滤器中。否则,在某些情况下 AWS DMS 可能无法连接到 TiDB 集群。 + +4. 点击**下载 CA 证书**以下载 CA 证书。在对话框中的**步骤 3:使用 SQL 客户端连接**下,记下连接字符串中的 `-u`、`-h` 和 `-P` 信息,以供后续使用。 + +5. 在对话框中点击 **VPC 对等连接**选项卡,然后在**步骤 1:设置 VPC**下点击**添加**,为 TiDB 集群和 AWS DMS 创建 VPC 对等连接。 + +6. 配置相应的信息。请参见[设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)。 + +7. 为 TiDB 集群配置目标端点。 + - **端点类型**:选择**目标端点**。 + - **端点标识符**:为端点填写一个名称。 + - **描述性 Amazon Resource Name (ARN) - 可选**:为默认 DMS ARN 创建一个友好名称。 + - **目标引擎**:选择 **MySQL**。 + + ![配置目标端点](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-target-endpoint.png) + +8. 在 [AWS DMS 控制台](https://console.aws.amazon.com/dms/v2/home)中,点击**创建端点**以创建目标数据库端点,然后配置以下信息: + - **服务器名称**:填写你的 TiDB 集群的主机名,即你记录的 `-h` 信息。 + - **端口**:输入你的 TiDB 集群的端口,即你记录的 `-P` 信息。TiDB 集群的默认端口是 4000。 + - **用户名**:输入你的 TiDB 集群的用户名,即你记录的 `-u` 信息。 + - **密码**:输入你的 TiDB 集群的密码。 + - **安全套接字层 (SSL) 模式**:选择 **Verify-ca**。 + - 点击**添加新的 CA 证书**以导入之前从 TiDB Cloud 控制台下载的 CA 文件。 + + ![填写目标端点信息](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-target-endpoint2.png) + +9. 导入 CA 文件。 + + ![上传 CA](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-upload-ca.png) + +10. 对于**端点设置**、**KMS 密钥**和**标签**,使用默认值。在**测试端点连接(可选)**部分,选择与源数据库相同的 VPC。选择相应的复制实例,然后点击**运行测试**。状态需要为**成功**。 + +11. 点击**创建端点**。 + + ![点击创建端点](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-target-endpoint3.png) + +## 步骤 4. 创建数据库迁移任务 + +1. 在 AWS DMS 控制台中,转到[数据迁移任务](https://console.aws.amazon.com/dms/v2/home#tasks)页面。切换到你的区域。然后点击窗口右上角的**创建任务**。 + + ![创建任务](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-create-task.png) + +2. 配置以下信息: + - **任务标识符**:为任务填写一个名称。建议使用容易记住的名称。 + - **描述性 Amazon Resource Name (ARN) - 可选**:为默认 DMS ARN 创建一个友好名称。 + - **复制实例**:选择你刚刚创建的 AWS DMS 实例。 + - **源数据库端点**:选择你刚刚创建的源数据库端点。 + - **目标数据库端点**:选择你刚刚创建的目标数据库端点。 + - **迁移类型**:根据需要选择迁移类型。在本例中,选择**迁移现有数据并复制持续变更**。 + + ![任务配置](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-task-config.png) + +3. 配置以下信息: + - **编辑模式**:选择**向导**。 + - **源事务的自定义 CDC 停止模式**:使用默认设置。 + - **目标表准备模式**:根据需要选择**不执行任何操作**或其他选项。在本例中,选择**不执行任何操作**。 + - **完成全量加载后停止任务**:使用默认设置。 + - **在复制中包含 LOB 列**:选择**有限 LOB 模式**。 + - **最大 LOB 大小(KB)**:使用默认值 **32**。 + - **开启验证**:根据需要选择。 + - **任务日志**:选择**开启 CloudWatch 日志**以便将来进行故障排除。对相关配置使用默认设置。 + + ![任务设置](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-task-settings.png) + +4. 在**表映射**部分,指定要迁移的数据库。 + + 架构名称是 Amazon RDS 实例中的数据库名称。**源名称**的默认值是"%",这意味着 Amazon RDS 中的所有数据库都将迁移到 TiDB。这将导致 Amazon RDS 中的系统数据库(如 `mysql` 和 `sys`)被迁移到 TiDB 集群,并导致任务失败。因此,建议填写具体的数据库名称,或过滤掉所有系统数据库。例如,根据以下截图中的设置,只有名为 `franktest` 的数据库及其所有表会被迁移。 + + ![表映射](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-table-mappings.png) + +5. 点击右下角的**创建任务**。 + +6. 返回[数据迁移任务](https://console.aws.amazon.com/dms/v2/home#tasks)页面。切换到你的区域。你可以看到任务的状态和进度。 + + ![任务状态](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-task-status.png) + +如果在迁移过程中遇到任何问题或失败,你可以在 [CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 中查看日志信息以排除问题。 + +![故障排除](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-to-tidb-cloud-troubleshooting.png) + +## 另请参阅 + +- 如果你想了解更多关于如何将 AWS DMS 连接到 TiDB Cloud Serverless 或 TiDB Cloud Dedicated 的信息,请参见[将 AWS DMS 连接到 TiDB Cloud 集群](/tidb-cloud/tidb-cloud-connect-aws-dms.md)。 + +- 如果你想从 MySQL 兼容数据库(如 Aurora MySQL 和 Amazon Relational Database Service (RDS))迁移到 TiDB Cloud,建议使用 [TiDB Cloud 上的数据迁移](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +- 如果你想使用 AWS DMS 将 Amazon RDS for Oracle 迁移到 TiDB Cloud Serverless,请参见[使用 AWS DMS 将 Amazon RDS for Oracle 迁移到 TiDB Cloud Serverless](/tidb-cloud/migrate-from-oracle-using-aws-dms.md)。 diff --git a/tidb-cloud/migrate-from-mysql-using-data-migration.md b/tidb-cloud/migrate-from-mysql-using-data-migration.md new file mode 100644 index 000000000000..ee148092d67b --- /dev/null +++ b/tidb-cloud/migrate-from-mysql-using-data-migration.md @@ -0,0 +1,515 @@ +--- +title: 使用数据迁移功能将 MySQL 兼容数据库迁移至 TiDB Cloud +summary: 了解如何使用数据迁移功能将 Amazon Aurora MySQL、Amazon RDS、Azure Database for MySQL - Flexible Server、Google Cloud SQL for MySQL 或自管理 MySQL 实例无缝迁移至 TiDB Cloud,并将停机时间降至最低。 +aliases: ['/tidbcloud/migrate-data-into-tidb','/tidbcloud/migrate-incremental-data-from-mysql'] +--- + +# 使用数据迁移功能将 MySQL 兼容数据库迁移至 TiDB Cloud + +本文档指导你如何使用 [TiDB Cloud 控制台](https://tidbcloud.com/) 中的数据迁移功能,将 MySQL 数据库从 Amazon Aurora MySQL、Amazon RDS、Azure Database for MySQL - Flexible Server、Google Cloud SQL for MySQL 或自管理 MySQL 实例迁移至 TiDB Cloud。 + +此功能使你能够直接将现有的 MySQL 数据和持续变更(binlog)从 MySQL 兼容的源数据库复制到 TiDB Cloud,无论是在同一区域还是跨不同区域,都能保持数据一致性。这种简化的流程消除了单独的导出和导入操作的需求,减少了停机时间,简化了从 MySQL 到更具可扩展性平台的迁移过程。 + +如果你只想将 MySQL 兼容数据库的持续 binlog 变更复制到 TiDB Cloud,请参阅[使用数据迁移功能将增量数据从 MySQL 兼容数据库迁移至 TiDB Cloud](/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md)。 + +## 限制 + +### 可用性 + +- 数据迁移功能仅适用于 **TiDB Cloud Dedicated** 集群。 + +- 如果你在 [TiDB Cloud 控制台](https://tidbcloud.com/) 中看不到 TiDB Cloud Dedicated 集群的[数据迁移](/tidb-cloud/migrate-from-mysql-using-data-migration.md#步骤-1-进入数据迁移页面)入口,该功能可能在你所在的区域不可用。要请求支持你所在的区域,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +- Amazon Aurora MySQL 写入实例支持现有数据和增量数据迁移。Amazon Aurora MySQL 只读实例仅支持现有数据迁移,不支持增量数据迁移。 + +### 迁移任务的最大数量 + +每个组织最多可以创建 200 个迁移任务。如需创建更多迁移任务,你需要[提交支持工单](/tidb-cloud/tidb-cloud-support.md)。 + +### 被过滤和删除的数据库 + +- 即使你选择迁移所有数据库,系统数据库也会被过滤掉,不会迁移到 TiDB Cloud。也就是说,`mysql`、`information_schema`、`performance_schema` 和 `sys` 不会使用此功能进行迁移。 + +- 当你删除 TiDB Cloud 中的集群时,该集群中的所有迁移任务都会自动删除,且无法恢复。 + +### 现有数据迁移的限制 + +- 在现有数据迁移期间,如果目标数据库中已经存在要迁移的表,并且存在重复的键,具有重复键的行将被替换。 + +- 如果你的数据集大小小于 1 TiB,建议使用逻辑模式(默认模式)。如果你的数据集大小大于 1 TiB,或者你想更快地迁移现有数据,可以使用物理模式。更多信息,请参阅[迁移现有数据和增量数据](#迁移现有数据和增量数据)。 + +### 增量数据迁移的限制 + +- 在增量数据迁移期间,如果要迁移的表在目标数据库中已存在且有重复的键,将报告错误并中断迁移。在这种情况下,你需要确认 MySQL 源数据是否准确。如果准确,点击迁移任务的"重启"按钮,迁移任务将用 MySQL 源记录替换目标 TiDB Cloud 集群中的冲突记录。 + +- 在增量复制(将持续变更迁移到集群)期间,如果迁移任务从突发错误中恢复,它可能会开启 60 秒的安全模式。在安全模式期间,`INSERT` 语句将作为 `REPLACE` 迁移,`UPDATE` 语句将作为 `DELETE` 和 `REPLACE` 迁移,然后这些事务将迁移到目标 TiDB Cloud 集群,以确保突发错误期间的所有数据都已顺利迁移到目标 TiDB Cloud 集群。在这种情况下,对于没有主键或非空唯一索引的 MySQL 源表,一些数据可能在目标 TiDB Cloud 集群中重复,因为数据可能会重复插入到目标 TiDB Cloud 集群中。 + +- 在以下场景中,如果迁移任务耗时超过 24 小时,请不要清除源数据库中的二进制日志,以确保数据迁移可以获取连续的二进制日志进行增量复制: + + - 在现有数据迁移期间。 + - 在现有数据迁移完成后,当首次启动增量数据迁移时,延迟不为 0ms。 +## 前提条件 + +在开始迁移之前,请检查你的数据源是否受支持,在 MySQL 兼容数据库中启用二进制日志记录,确保网络连接,并为源数据库和目标 TiDB Cloud 集群数据库授予所需权限。 + +### 确保你的数据源和版本受支持 + +数据迁移支持以下数据源和版本: + +| 数据源 | 支持的版本 | +|:------------|:-------------------| +| 自管理 MySQL(本地或公有云) | 8.0、5.7、5.6 | +| Amazon Aurora MySQL | 8.0、5.7、5.6 | +| Amazon RDS MySQL | 8.0、5.7 | +| Azure Database for MySQL - Flexible Server | 8.0、5.7 | +| Google Cloud SQL for MySQL | 8.0、5.7、5.6 | + +### 在源 MySQL 兼容数据库中启用二进制日志以进行复制 + +要使用 DM 将源 MySQL 兼容数据库的增量变更持续复制到 TiDB Cloud 目标集群,你需要在源数据库中进行以下配置以启用二进制日志: + +| 配置 | 必需值 | 原因 | +|:--------------|:---------------|:----| +| `log_bin` | `ON` | 启用二进制日志记录,DM 使用它来复制变更到 TiDB | +| `binlog_format` | `ROW` | 准确捕获所有数据变更(其他格式会遗漏边缘情况) | +| `binlog_row_image` | `FULL` | 在事件中包含所有列值以进行安全的冲突解决 | +| `binlog_expire_logs_seconds` | ≥ `86400`(1 天),`604800`(7 天,推荐) | 确保 DM 在迁移期间可以访问连续的日志 | + +#### 检查当前值并配置源 MySQL 实例 + +要检查当前配置,连接到源 MySQL 实例并执行以下语句: + +```sql +SHOW VARIABLES WHERE Variable_name IN +('log_bin','server_id','binlog_format','binlog_row_image', +'binlog_expire_logs_seconds','expire_logs_days'); +``` + +如有必要,更改源 MySQL 实例配置以匹配所需值。 + +
+ 配置自管理 MySQL 实例 + +1. 打开 `/etc/my.cnf` 并添加以下内容: + + ``` + [mysqld] + log_bin = mysql-bin + binlog_format = ROW + binlog_row_image = FULL + binlog_expire_logs_seconds = 604800 # 7 天保留期 + ``` + +2. 重启 MySQL 服务以应用更改: + + ``` + sudo systemctl restart mysqld + ``` + +3. 再次运行 `SHOW VARIABLES` 语句以验证设置是否生效。 + +有关详细说明,请参阅 MySQL 文档中的 [MySQL Server System Variables](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html) 和 [The Binary Log](https://dev.mysql.com/doc/refman/8.0/en/binary-log.html)。 + +
+ +
+ 配置 AWS RDS 或 Aurora MySQL + +1. 在 AWS 管理控制台中,打开 [Amazon RDS 控制台](https://console.aws.amazon.com/rds/),在左侧导航栏中点击 **Parameter groups**,然后创建或编辑自定义参数组。 +2. 将上述四个参数设置为所需值。 +3. 将参数组附加到你的实例或集群,然后重启以应用更改。 +4. 重启后,连接到实例并运行 `SHOW VARIABLES` 语句以验证配置。 + +有关详细说明,请参阅 AWS 文档中的 [Working with DB Parameter Groups](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html) 和 [Configuring MySQL Binary Logging](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.BinaryFormat.html)。 + +
+ +
+ 配置 Azure Database for MySQL - Flexible Server + +1. 在 [Azure 门户](https://portal.azure.com/) 中,搜索并选择 **Azure Database for MySQL servers**,点击你的实例名称,然后在左侧导航栏中点击 **Setting** > **Server parameters**。 + +2. 搜索每个参数并更新其值。 + + 大多数更改无需重启即可生效。如果需要重启,门户会提示你。 + +3. 运行 `SHOW VARIABLES` 语句以验证配置。 + +有关详细说明,请参阅 Microsoft Azure 文档中的 [Configure server parameters in Azure Database for MySQL - Flexible Server using the Azure portal](https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-configure-server-parameters-portal)。 + +
+ +
+ 配置 Google Cloud SQL for MySQL + +1. 在 [Google Cloud 控制台](https://console.cloud.google.com/project/_/sql/instances) 中,选择包含你实例的项目,点击你的实例名称,然后点击 **Edit**。 +2. 添加或修改所需的标志(`log_bin`、`binlog_format`、`binlog_row_image`、`binlog_expire_logs_seconds`)。 +3. 点击 **Save**。如果需要重启,控制台会提示你。 +4. 重启后,运行 `SHOW VARIABLES` 语句以确认更改。 + +有关详细说明,请参阅 Google Cloud 文档中的 [Configure database flags](https://cloud.google.com/sql/docs/mysql/flags) 和 [Use point-in-time recovery](https://cloud.google.com/sql/docs/mysql/backup-recovery/pitr)。 + +
+ +### 确保网络连接 + +在创建迁移任务之前,你需要规划并设置源 MySQL 实例、TiDB Cloud 数据迁移(DM)服务和目标 TiDB Cloud 集群之间的适当网络连接。 + +可用的连接方法如下: + +| 连接方法 | 可用性 | 推荐用于 | +|:---------------------|:-------------|:----------------| +| 公共端点或 IP 地址 | TiDB Cloud 支持的所有云提供商 | 快速概念验证迁移、测试或无法使用私有连接时 | +| 私有链接或私有端点 | 仅 AWS 和 Azure | 不向公共互联网暴露数据的生产工作负载 | +| VPC 对等连接 | 仅 AWS 和 Google Cloud | 需要低延迟、区域内连接且 VPC/VNet CIDR 不重叠的生产工作负载 | + +选择最适合你的云提供商、网络拓扑和安全要求的连接方法,然后按照该方法的设置说明进行操作。 + +#### 通过 TLS/SSL 的端到端加密 + +无论选择哪种连接方法,都强烈建议使用 TLS/SSL 进行端到端加密。虽然私有端点和 VPC 对等连接可以保护网络路径,但 TLS/SSL 可以保护数据本身并帮助满足合规要求。 + +
+ 下载并存储云提供商的证书以进行 TLS/SSL 加密连接 + +- Amazon Aurora MySQL 或 Amazon RDS MySQL:[Using SSL/TLS to encrypt a connection to a DB instance or cluster](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.SSL.html) +- Azure Database for MySQL - Flexible Server:[Connect with encrypted connections](https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-connect-tls-ssl) +- Google Cloud SQL for MySQL:[Manage SSL/TLS certificates](https://cloud.google.com/sql/docs/mysql/manage-ssl-instance) + +
+ +#### 公共端点或 IP 地址 + +使用公共端点时,你可以在 DM 任务创建过程中验证网络连接和访问。TiDB Cloud 将提供特定的出口 IP 地址并在当时提示相关说明。 + +1. 确定并记录源 MySQL 实例的端点主机名(FQDN)或公共 IP 地址。 +2. 确保你有修改数据库防火墙或安全组规则的必要权限。参考以下云提供商的文档获取指导: + + - Amazon Aurora MySQL 或 Amazon RDS MySQL:[Controlling access with security groups](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Overview.RDSSecurityGroups.html)。 + - Azure Database for MySQL - Flexible Server:[Public Network Access](https://learn.microsoft.com/en-us/azure/mysql/flexible-server/concepts-networking-public) + - Google Cloud SQL for MySQL:[Authorized Networks](https://cloud.google.com/sql/docs/mysql/configure-ip#authorized-networks)。 + +3. 可选:使用具有公共互联网访问权限的机器和适当的证书验证与源数据库的连接,以进行传输中加密: + + ```shell + mysql -h -P -u -p --ssl-ca= -e "SELECT version();" + ``` + +4. 在数据迁移任务设置期间,TiDB Cloud 将提供一个出口 IP 范围。此时,你需要按照上述相同的程序将此 IP 范围添加到数据库的防火墙或安全组规则中。 +#### 私有链接或私有端点 + +如果你使用提供商原生的私有链接或私有端点,请为你的源 MySQL 实例(RDS、Aurora 或 Azure Database for MySQL)创建私有端点。 + +
+ 为 MySQL 源数据库设置 AWS PrivateLink 和私有端点 + +AWS 不支持直接通过 PrivateLink 访问 RDS 或 Aurora。因此,你需要创建一个网络负载均衡器(NLB)并将其作为与源 MySQL 实例关联的端点服务发布。 + +1. 在 [Amazon EC2 控制台](https://console.aws.amazon.com/ec2/) 中,在与 RDS 或 Aurora 写入器相同的子网中创建一个 NLB。配置 NLB 时,设置一个在端口 `3306` 上将流量转发到数据库端点的 TCP 监听器。 + + 有关详细说明,请参阅 AWS 文档中的 [Create a Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/create-network-load-balancer.html)。 + +2. 在 [Amazon VPC 控制台](https://console.aws.amazon.com/vpc/) 中,在左侧导航栏中点击 **Endpoint Services**,然后创建一个端点服务。在设置过程中,选择上一步创建的 NLB 作为后端负载均衡器,并启用 **Require acceptance for endpoint** 选项。端点服务创建后,复制服务名称(格式为 `com.amazonaws.vpce-svc-xxxxxxxxxxxxxxxxx`)以供后续使用。 + + 有关详细说明,请参阅 AWS 文档中的 [Create an endpoint service](https://docs.aws.amazon.com/vpc/latest/privatelink/create-endpoint-service.html)。 + +3. 可选:在开始迁移之前,从同一 VPC 或 VNet 内的堡垒机或客户端测试连接: + + ```shell + mysql -h -P 3306 -u -p --ssl-ca= -e "SELECT version();" + ``` + +4. 稍后,当配置 TiDB Cloud DM 通过 PrivateLink 连接时,你需要返回 AWS 控制台并批准来自 TiDB Cloud 到此私有端点的待处理连接请求。 + +
+ +
+ 为 MySQL 源数据库设置 Azure PrivateLink 和私有端点 + +Azure Database for MySQL - Flexible Server 支持原生私有端点。你可以在创建 MySQL 实例时启用私有访问(VNet 集成),或者稍后添加私有端点。 + +要添加新的私有端点,请执行以下步骤: + +1. 在 [Azure 门户](https://portal.azure.com/) 中,搜索并选择 **Azure Database for MySQL servers**,点击你的实例名称,然后在左侧导航栏中点击 **Setting** > **Networking**。 +2. 在 **Networking** 页面上,滚动到 **Private endpoints** 部分,点击 **+ Create private endpoint**,然后按照屏幕上的说明设置私有端点。 + + 在设置过程中,在 **Virtual Network** 选项卡中选择 TiDB Cloud 可以访问的虚拟网络和子网,并在 **DNS** 选项卡中保持启用 **Private DNS integration**。私有端点创建和部署后,点击 **Go to resource**,在左侧导航栏中点击 **Settings** > **DNS configuration**,在 **Customer Visible FQDNs** 部分找到用于连接实例的主机名。通常,主机名的格式为 `.mysql.database.azure.com`。 + + 有关详细说明,请参阅 Azure 文档中的 [Create a private endpoint via Private Link Center](https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-networking-private-link-portal#create-a-private-endpoint-via-private-link-center)。 + +3. 可选:在开始迁移之前,从同一 VPC 或 VNet 内的堡垒机或客户端测试连接: + + ```shell + mysql -h -P 3306 -u -p --ssl-ca= -e "SELECT version();" + ``` + +4. 在 [Azure 门户](https://portal.azure.com/) 中,返回到 MySQL Flexible Server 实例(不是私有端点对象)的概览页面,点击 **Essentials** 部分的 **JSON View**,然后复制资源 ID 以供后续使用。资源 ID 的格式为 `/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/flexibleServers/`。你将使用此资源 ID(而不是私有端点 ID)来配置 TiDB Cloud DM。 + +5. 稍后,当配置 TiDB Cloud DM 通过 PrivateLink 连接时,你需要返回 Azure 门户并批准来自 TiDB Cloud 到此私有端点的待处理连接请求。 + +
+ +#### VPC 对等连接 + +如果你使用 AWS VPC 对等连接或 Google Cloud VPC 网络对等连接,请参阅以下说明配置网络。 + +
+ 设置 AWS VPC 对等连接 + +如果你的 MySQL 服务在 AWS VPC 中,请执行以下步骤: + +1. [设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md),连接 MySQL 服务的 VPC 和你的 TiDB 集群。 + +2. 修改与 MySQL 服务关联的安全组的入站规则。 + + 你必须将[你的 TiDB Cloud 集群所在区域的 CIDR](/tidb-cloud/set-up-vpc-peering-connections.md#prerequisite-set-a-cidr-for-a-region) 添加到入站规则中。这样做可以允许流量从你的 TiDB 集群流向 MySQL 实例。 + +3. 如果 MySQL URL 包含 DNS 主机名,你需要允许 TiDB Cloud 能够解析 MySQL 服务的主机名。 + + 1. 按照 [Enable DNS resolution for a VPC peering connection](https://docs.aws.amazon.com/vpc/latest/peering/modify-peering-connections.html#vpc-peering-dns) 中的步骤操作。 + 2. 启用 **Accepter DNS resolution** 选项。 + +
+ +
+ 设置 Google Cloud VPC 网络对等连接 + +如果你的 MySQL 服务在 Google Cloud VPC 中,请执行以下步骤: + +1. 如果是自托管 MySQL,你可以跳过此步骤并继续下一步。如果你的 MySQL 服务是 Google Cloud SQL,你必须在 Google Cloud SQL 实例关联的 VPC 中暴露一个 MySQL 端点。你可能需要使用 Google 开发的 [Cloud SQL Auth proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy)。 + +2. [设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md),连接你的 MySQL 服务的 VPC 和你的 TiDB 集群。 + +3. 修改 MySQL 所在 VPC 的入站防火墙规则。 + + 你必须将[你的 TiDB Cloud 集群所在区域的 CIDR](/tidb-cloud/set-up-vpc-peering-connections.md#prerequisite-set-a-cidr-for-a-region) 添加到入站防火墙规则中。这样可以允许流量从你的 TiDB 集群流向 MySQL 端点。 + +
+ +### 授予迁移所需的权限 + +在开始迁移之前,你需要在源数据库和目标数据库上设置具有所需权限的适当数据库用户。这些权限使 TiDB Cloud DM 能够安全地从 MySQL 读取数据、复制变更并写入你的 TiDB Cloud 集群。由于迁移涉及现有数据的完整导出和增量变更的 binlog 复制,你的迁移用户需要基本读取访问权限之外的特定权限。 + +#### 在源 MySQL 数据库中为迁移用户授予所需权限 + +对于测试目的,你可以在源 MySQL 数据库中使用管理员用户(如 `root`)。 + +对于生产工作负载,建议在源 MySQL 数据库中有一个专门用于数据导出和复制的用户,并只授予必要的权限: + +| 权限 | 范围 | 用途 | +|:----------|:------|:--------| +| `SELECT` | 表 | 允许从所有表读取数据 | +| `RELOAD` | 全局 | 确保完整导出期间的一致性快照 | +| `REPLICATION SLAVE` | 全局 | 启用 binlog 流式传输以进行增量复制 | +| `REPLICATION CLIENT` | 全局 | 提供对 binlog 位置和服务器状态的访问 | + +例如,你可以在源 MySQL 实例中使用以下 `GRANT` 语句授予相应权限: + +```sql +GRANT SELECT, RELOAD, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'dm_source_user'@'%'; +``` + +#### 在目标 TiDB Cloud 集群中授予所需权限 + +对于测试目的,你可以使用 TiDB Cloud 集群的 `root` 账户。 + +对于生产工作负载,建议在目标 TiDB Cloud 集群中有一个专门用于复制的用户,并只授予必要的权限: + +| 权限 | 范围 | 用途 | +|:----------|:------|:--------| +| `CREATE` | 数据库、表 | 在目标中创建架构对象 | +| `SELECT` | 表 | 在迁移期间验证数据 | +| `INSERT` | 表 | 写入迁移的数据 | +| `UPDATE` | 表 | 在增量复制期间修改现有行 | +| `DELETE` | 表 | 在复制或更新期间删除行 | +| `ALTER` | 表 | 在架构变更时修改表定义 | +| `DROP` | 数据库、表 | 在架构同步期间删除对象 | +| `INDEX` | 表 | 创建和修改索引 | +| `CREATE VIEW` | 视图 | 创建迁移使用的视图 | + +例如,你可以在目标 TiDB Cloud 集群中执行以下 `GRANT` 语句授予相应权限: + +```sql +GRANT CREATE, SELECT, INSERT, UPDATE, DELETE, ALTER, DROP, INDEX ON *.* TO 'dm_target_user'@'%'; +``` +## 步骤 1:进入数据迁移页面 + +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/) 并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的下拉框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称以进入其概览页面,然后在左侧导航栏中点击 **Data** > **Migration**。 + +3. 在**数据迁移**页面,点击右上角的**创建迁移任务**。此时会显示**创建迁移任务**页面。 + +## 步骤 2:配置源和目标连接 + +在**创建迁移任务**页面,配置源和目标连接。 + +1. 输入任务名称,必须以字母开头且少于 60 个字符。可以使用字母(A-Z、a-z)、数字(0-9)、下划线(_)和连字符(-)。 + +2. 填写源连接配置。 + + - **数据源**:数据源类型。 + - **连接方式**:根据你的安全要求和云提供商选择数据源的连接方式: + - **公共 IP**:适用于所有云提供商(推荐用于测试和概念验证迁移)。 + - **Private Link**:仅适用于 AWS 和 Azure(推荐用于需要私有连接的生产工作负载)。 + - **VPC 对等连接**:仅适用于 AWS 和 Google Cloud(推荐用于需要低延迟、区域内连接且 VPC/VNet CIDR 不重叠的生产工作负载)。 + - 根据选择的**连接方式**,执行以下操作: + - 如果选择了**公共 IP**或 **VPC 对等连接**,在**主机名或 IP 地址**字段中填写数据源的主机名或 IP 地址。 + - 如果选择了 **Private Link**,填写以下信息: + - **端点服务名称**(如果**数据源**来自 AWS):输入你为 RDS 或 Aurora 实例创建的 VPC 端点服务名称(格式:`com.amazonaws.vpce-svc-xxxxxxxxxxxxxxxxx`)。 + - **私有端点资源 ID**(如果**数据源**来自 Azure):输入你的 MySQL Flexible Server 实例的资源 ID(格式:`/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/flexibleServers/`)。 + - **端口**:数据源的端口。 + - **用户名**:数据源的用户名。 + - **密码**:用户名的密码。 + - **SSL/TLS**:启用 SSL/TLS 进行端到端数据加密(强烈建议用于所有迁移任务)。根据你的 MySQL 服务器的 SSL 配置上传适当的证书。 + + SSL/TLS 配置选项: + + - 选项 1:仅服务器认证 + + - 如果你的 MySQL 服务器仅配置了服务器认证,只需上传 **CA 证书**。 + - 在此选项中,MySQL 服务器提供其证书以证明其身份,TiDB Cloud 根据 CA 验证服务器证书。 + - 如果 MySQL 服务器以 `require_secure_transport = ON` 启动,则需要 CA 证书来防止中间人攻击。 + + - 选项 2:客户端证书认证 + + - 如果你的 MySQL 服务器配置了客户端证书认证,上传**客户端证书**和**客户端私钥**。 + - 在此选项中,TiDB Cloud 向 MySQL 服务器提供其证书进行认证,但 TiDB Cloud 不验证 MySQL 服务器的证书。 + - 当 MySQL 服务器配置了 `REQUIRE SUBJECT '...'` 或 `REQUIRE ISSUER '...'` 等选项而没有 `REQUIRE X509` 时,通常使用此选项,允许它检查客户端证书的特定属性而不进行完整的 CA 验证。 + - 当 MySQL 服务器在自签名或自定义 PKI 环境中接受客户端证书时,通常使用此选项。请注意,此配置容易受到中间人攻击,除非其他网络级别的控制可以保证服务器的真实性,否则不建议在生产环境中使用。 + + - 选项 3:相互 TLS (mTLS) - 最高安全性 + + - 如果你的 MySQL 服务器配置了相互 TLS (mTLS) 认证,上传 **CA 证书**、**客户端证书**和**客户端私钥**。 + - 在此选项中,MySQL 服务器使用客户端证书验证 TiDB Cloud 的身份,TiDB Cloud 使用 CA 证书验证 MySQL 服务器的身份。 + - 当 MySQL 服务器为迁移用户配置了 `REQUIRE X509` 或 `REQUIRE SSL` 时,需要此选项。 + - 当 MySQL 服务器需要客户端证书进行认证时,使用此选项。 + - 你可以从以下来源获取证书: + - 从你的云提供商下载(参见 [TLS 证书链接](#通过-tlsssl-的端到端加密))。 + - 使用你组织的内部 CA 证书。 + - 自签名证书(仅用于开发/测试)。 + +3. 填写目标连接配置。 + + - **用户名**:输入 TiDB Cloud 中目标集群的用户名。 + - **密码**:输入 TiDB Cloud 用户名的密码。 + +4. 点击**验证连接并继续**以验证你输入的信息。 + +5. 根据你看到的消息采取行动: + + - 如果你使用**公共 IP**或 **VPC 对等连接**作为连接方式,你需要将数据迁移服务的 IP 地址添加到源数据库的 IP 访问列表和防火墙(如果有)中。 + - 如果你使用 **Private Link** 作为连接方式,系统会提示你接受端点请求: + - 对于 AWS:转到 [AWS VPC 控制台](https://us-west-2.console.aws.amazon.com/vpc/home),点击 **Endpoint services**,接受来自 TiDB Cloud 的端点请求。 + - 对于 Azure:转到 [Azure 门户](https://portal.azure.com),按名称搜索你的 MySQL Flexible Server,在左侧导航栏中点击 **Setting** > **Networking**,在右侧找到 **Private endpoint** 部分,然后批准来自 TiDB Cloud 的待处理连接请求。 +## 步骤 3:选择迁移任务类型 + +在**选择要迁移的对象**步骤中,你可以选择现有数据迁移、增量数据迁移或两者都选。 + +### 迁移现有数据和增量数据 + +要一次性将数据迁移到 TiDB Cloud,请同时选择**现有数据迁移**和**增量数据迁移**,这可以确保源数据库和目标数据库之间的数据一致性。 + +你可以使用**物理模式**或**逻辑模式**来迁移**现有数据**和**增量数据**。 + +- 默认模式是**逻辑模式**。此模式将数据从 MySQL 源数据库导出为 SQL 语句,然后在 TiDB 上执行这些语句。在此模式下,迁移前的目标表可以是空的或非空的。但性能比物理模式慢。 + +- 对于大型数据集,建议使用**物理模式**。此模式从 MySQL 源数据库导出数据并将其编码为 KV 对,直接写入 TiKV 以实现更快的性能。此模式要求迁移前目标表必须为空。对于 16 RCU(复制容量单位)的规格,性能约为逻辑模式的 2.5 倍。其他规格的性能可以比逻辑模式提高 20% 到 50%。请注意,性能数据仅供参考,在不同场景中可能有所不同。 + +> **注意:** +> +> - 当你使用物理模式时,在现有数据迁移完成之前,不能为 TiDB 集群创建第二个迁移任务或导入任务。 +> - 当你使用物理模式且迁移任务已经开始时,请**不要**启用 PITR(时间点恢复)或在集群上有任何 changefeed。否则,迁移任务将会卡住。如果你需要启用 PITR 或有任何 changefeed,请改用逻辑模式迁移数据。 + +物理模式尽可能快地导出 MySQL 源数据,因此[不同规格](/tidb-cloud/tidb-cloud-billing-dm.md#数据迁移的规格)对 MySQL 源数据库在数据导出期间的 QPS 和 TPS 有不同的性能影响。下表显示了每个规格的性能回退。 + +| 迁移规格 | 最大导出速度 | MySQL 源数据库的性能回退 | +|---------|-------------|--------| +| 2 RCU | 80.84 MiB/s | 15.6% | +| 4 RCU | 214.2 MiB/s | 20.0% | +| 8 RCU | 365.5 MiB/s | 28.9% | +| 16 RCU | 424.6 MiB/s | 46.7% | + +### 仅迁移现有数据 + +要仅将源数据库的现有数据迁移到 TiDB Cloud,请选择**现有数据迁移**。 + +你只能使用逻辑模式迁移现有数据。更多信息,请参见[迁移现有数据和增量数据](#迁移现有数据和增量数据)。 + +### 仅迁移增量数据 + +要仅将源数据库的增量数据迁移到 TiDB Cloud,请选择**增量数据迁移**。在这种情况下,迁移任务不会将源数据库的现有数据迁移到 TiDB Cloud,而只会迁移迁移任务明确指定的源数据库的持续变更。 + +有关增量数据迁移的详细说明,请参见[使用数据迁移功能仅迁移增量数据从 MySQL 兼容数据库到 TiDB Cloud](/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md)。 + +## 步骤 4:选择要迁移的对象 + +1. 在**选择要迁移的对象**页面,选择要迁移的对象。你可以点击**全部**选择所有对象,或点击**自定义**然后点击对象名称旁边的复选框来选择对象。 + + - 如果你点击**全部**,迁移任务将从整个源数据库实例迁移现有数据到 TiDB Cloud,并在完整迁移后迁移持续变更。请注意,这仅在你在上一步中选择了**现有数据迁移**和**增量数据迁移**复选框时才会发生。 + - 如果你点击**自定义**并选择一些数据库,迁移任务将迁移所选数据库的现有数据并迁移持续变更到 TiDB Cloud。请注意,这仅在你在上一步中选择了**现有数据迁移**和**增量数据迁移**复选框时才会发生。 + - 如果你点击**自定义**并选择数据集名称下的一些表,迁移任务将只迁移所选表的现有数据并迁移持续变更。之后在同一数据库中创建的表不会被迁移。 + +2. 点击**下一步**。 + +## 步骤 5:预检查 + +在**预检查**页面,你可以查看预检查结果。如果预检查失败,你需要根据**失败**或**警告**详情进行操作,然后点击**重新检查**以重新检查。 + +如果某些检查项只有警告,你可以评估风险并考虑是否忽略警告。如果所有警告都被忽略,迁移任务将自动进入下一步。 + +有关错误和解决方案的更多信息,请参见[预检查错误和解决方案](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#预检查错误和解决方案)。 + +有关预检查项的更多信息,请参见[迁移任务预检查](https://docs.pingcap.com/tidb/stable/dm-precheck)。 + +如果所有检查项显示**通过**,点击**下一步**。 + +## 步骤 6:选择规格并开始迁移 + +在**选择规格并开始迁移**页面,根据你的性能要求选择适当的迁移规格。有关规格的更多信息,请参见[数据迁移的规格](/tidb-cloud/tidb-cloud-billing-dm.md#数据迁移的规格)。 + +选择规格后,点击**创建任务并开始**以开始迁移。 + +## 步骤 7:查看迁移进度 + +创建迁移任务后,你可以在**迁移任务详情**页面查看迁移进度。迁移进度显示在**阶段和状态**区域。 + +你可以在迁移任务运行时暂停或删除它。 + +如果迁移任务失败,你可以在解决问题后恢复它。 + +你可以在任何状态下删除迁移任务。 + +如果在迁移过程中遇到任何问题,请参见[迁移错误和解决方案](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#迁移错误和解决方案)。 + +## 扩缩容迁移任务规格 + +TiDB Cloud 支持扩大或缩小迁移任务规格,以满足不同场景下的性能和成本要求。 + +不同的迁移规格有不同的性能。你在不同阶段的性能要求也可能不同。例如,在现有数据迁移期间,你希望性能尽可能快,所以选择了一个大规格的迁移任务,如 8 RCU。一旦现有数据迁移完成,增量迁移不需要如此高的性能,所以你可以缩小任务规格,例如从 8 RCU 缩小到 2 RCU,以节省成本。 + +在扩缩容迁移任务规格时,请注意以下事项: + +- 扩缩容迁移任务规格需要大约 5 到 10 分钟。 +- 如果扩缩容失败,任务规格将保持与扩缩容前相同。 + +### 限制 + +- 只有当任务处于**运行中**或**已暂停**状态时,才能扩缩容迁移任务规格。 +- TiDB Cloud 不支持在现有数据导出阶段扩缩容迁移任务规格。 +- 扩缩容迁移任务规格将重启任务。如果任务的源表没有主键,可能会插入重复数据。 +- 在扩缩容期间,不要清除源数据库的二进制日志或临时增加 MySQL 源数据库的 `expire_logs_days`。否则,由于无法获取连续的二进制日志位置,任务可能会失败。 + +### 扩缩容程序 + +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/) 并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + +2. 点击目标集群的名称以进入其概览页面,然后在左侧导航栏中点击 **Data** > **Migration**。 + +3. 在**数据迁移**页面,找到要扩缩容的迁移任务。在**操作**列中,点击 **...** > **扩缩容**。 + +4. 在**扩缩容**窗口中,选择要使用的新规格,然后点击**提交**。你可以在窗口底部查看新规格的价格。 diff --git a/tidb-cloud/migrate-from-op-tidb.md b/tidb-cloud/migrate-from-op-tidb.md new file mode 100644 index 000000000000..21703b513a0c --- /dev/null +++ b/tidb-cloud/migrate-from-op-tidb.md @@ -0,0 +1,410 @@ +--- +title: 从 TiDB 自建集群迁移到 TiDB Cloud +summary: 了解如何将数据从 TiDB 自建集群迁移到 TiDB Cloud。 +--- + +# 从 TiDB 自建集群迁移到 TiDB Cloud + +本文档描述了如何通过 Dumpling 和 TiCDC 将数据从 TiDB 自建集群迁移到 TiDB Cloud (AWS)。 + +整体流程如下: + +1. 搭建环境并准备工具。 +2. 迁移全量数据。过程如下: + 1. 使用 Dumpling 将数据从 TiDB 自建集群导出到 Amazon S3。 + 2. 将数据从 Amazon S3 导入到 TiDB Cloud。 +3. 使用 TiCDC 复制增量数据。 +4. 验证迁移的数据。 + +## 前提条件 + +建议将 S3 存储桶和 TiDB Cloud 集群放在同一区域。跨区域迁移可能会产生额外的数据转换成本。 + +迁移前,你需要准备以下内容: + +- 具有管理员访问权限的 [AWS 账户](https://docs.aws.amazon.com/AmazonS3/latest/userguide/setting-up-s3.html#sign-up-for-aws-gsg) +- [AWS S3 存储桶](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html) +- [TiDB Cloud 账户](/tidb-cloud/tidb-cloud-quickstart.md),至少具有目标 AWS 上 TiDB Cloud 集群的 [`Project Data Access Read-Write`](/tidb-cloud/manage-user-access.md#user-roles) 访问权限 + +## 准备工具 + +你需要准备以下工具: + +- Dumpling:数据导出工具 +- TiCDC:数据复制工具 + +### Dumpling + +[Dumpling](https://docs.pingcap.com/tidb/dev/dumpling-overview) 是一个将数据从 TiDB 或 MySQL 导出到 SQL 或 CSV 文件的工具。你可以使用 Dumpling 从 TiDB 自建集群导出全量数据。 + +在部署 Dumpling 之前,请注意以下事项: + +- 建议将 Dumpling 部署在与 TiDB Cloud 中的 TiDB 集群位于同一 VPC 的新 EC2 实例上。 +- 推荐的 EC2 实例类型是 **c6g.4xlarge**(16 个 vCPU 和 32 GiB 内存)。你可以根据需要选择其他 EC2 实例类型。Amazon Machine Image (AMI) 可以是 Amazon Linux、Ubuntu 或 Red Hat。 + +你可以通过使用 TiUP 或使用安装包来部署 Dumpling。 + +#### 使用 TiUP 部署 Dumpling + +使用 [TiUP](https://docs.pingcap.com/tidb/stable/tiup-overview) 部署 Dumpling: + +```bash +## 部署 TiUP +curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh +source /root/.bash_profile +## 部署 Dumpling 并更新到最新版本 +tiup install dumpling +tiup update --self && tiup update dumpling +``` + +#### 使用安装包部署 Dumpling + +要使用安装包部署 Dumpling: + +1. 下载[工具包](https://docs.pingcap.com/tidb/stable/download-ecosystem-tools)。 + +2. 将其解压到目标机器。你可以通过运行 `tiup install dumpling` 使用 TiUP 获取 Dumpling。之后,你可以使用 `tiup dumpling ...` 运行 Dumpling。更多信息,请参见 [Dumpling 简介](https://docs.pingcap.com/tidb/stable/dumpling-overview#dumpling-introduction)。 + +#### 配置 Dumpling 的权限 + +你需要以下权限才能从上游数据库导出数据: + +- SELECT +- RELOAD +- LOCK TABLES +- REPLICATION CLIENT +- PROCESS + +### 部署 TiCDC + +你需要[部署 TiCDC](https://docs.pingcap.com/tidb/dev/deploy-ticdc) 来将增量数据从上游 TiDB 集群复制到 TiDB Cloud。 + +1. 确认当前 TiDB 版本是否支持 TiCDC。TiDB v4.0.8.rc.1 及更高版本支持 TiCDC。你可以通过在 TiDB 集群中执行 `select tidb_version();` 来检查 TiDB 版本。如果需要升级,请参见[使用 TiUP 升级 TiDB](https://docs.pingcap.com/tidb/dev/deploy-ticdc#upgrade-ticdc-using-tiup)。 + +2. 向 TiDB 集群添加 TiCDC 组件。请参见[使用 TiUP 向现有 TiDB 集群添加或扩容 TiCDC](https://docs.pingcap.com/tidb/dev/deploy-ticdc#add-or-scale-out-ticdc-to-an-existing-tidb-cluster-using-tiup)。编辑 `scale-out.yml` 文件以添加 TiCDC: + + ```yaml + cdc_servers: + - host: 10.0.1.3 + gc-ttl: 86400 + data_dir: /tidb-data/cdc-8300 + - host: 10.0.1.4 + gc-ttl: 86400 + data_dir: /tidb-data/cdc-8300 + ``` + +3. 添加 TiCDC 组件并检查状态。 + + ```shell + tiup cluster scale-out scale-out.yml + tiup cluster display + ``` + +## 迁移全量数据 + +要将数据从 TiDB 自建集群迁移到 TiDB Cloud,请执行以下全量数据迁移: + +1. 将数据从 TiDB 自建集群迁移到 Amazon S3。 +2. 将数据从 Amazon S3 迁移到 TiDB Cloud。 + +### 将数据从 TiDB 自建集群迁移到 Amazon S3 + +你需要使用 Dumpling 将数据从 TiDB 自建集群迁移到 Amazon S3。 + +如果你的 TiDB 集群在本地 IDC 中,或者 Dumpling 服务器与 Amazon S3 之间的网络未连接,你可以先将文件导出到本地存储,然后再上传到 Amazon S3。 + +#### 步骤 1. 暂时禁用上游 TiDB 自建集群的 GC 机制 + +为确保增量迁移期间不会丢失新写入的数据,你需要在开始迁移之前禁用上游集群的垃圾回收(GC)机制,以防止系统清理历史数据。 + +运行以下命令验证设置是否成功。 + +```sql +SET GLOBAL tidb_gc_enable = FALSE; +``` + +以下是示例输出,其中 `0` 表示已禁用。 + +```sql +SELECT @@global.tidb_gc_enable; ++-------------------------+ +| @@global.tidb_gc_enable | ++-------------------------+ +| 0 | ++-------------------------+ +1 row in set (0.01 sec) +``` + +#### 步骤 2. 为 Dumpling 配置 Amazon S3 存储桶的访问权限 + +在 AWS 控制台中创建访问密钥。详细信息请参见[创建访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey)。 + +1. 使用你的 AWS 账户 ID 或账户别名、IAM 用户名和密码登录 [IAM 控制台](https://console.aws.amazon.com/iam/home#/security_credentials)。 + +2. 在导航栏右上角,选择你的用户名,然后点击**我的安全凭证**。 + +3. 要创建访问密钥,点击**创建访问密钥**。然后选择**下载 .csv 文件**将访问密钥 ID 和秘密访问密钥保存到计算机上的 CSV 文件中。将文件存储在安全位置。此对话框关闭后,你将无法再次访问秘密访问密钥。下载 CSV 文件后,选择**关闭**。创建访问密钥时,密钥对默认处于活动状态,你可以立即使用该密钥对。 + + ![创建访问密钥](/media/tidb-cloud/op-to-cloud-create-access-key01.png) + + ![下载 CSV 文件](/media/tidb-cloud/op-to-cloud-create-access-key02.png) + +#### 步骤 3. 使用 Dumpling 将数据从上游 TiDB 集群导出到 Amazon S3 + +执行以下操作,使用 Dumpling 将数据从上游 TiDB 集群导出到 Amazon S3: + +1. 为 Dumpling 配置环境变量。 + + ```shell + export AWS_ACCESS_KEY_ID=${AccessKey} + export AWS_SECRET_ACCESS_KEY=${SecretKey} + ``` + +2. 从 AWS 控制台获取 S3 存储桶 URI 和区域信息。详细信息请参见[创建存储桶](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)。 + + 以下截图显示如何获取 S3 存储桶 URI 信息: + + ![获取 S3 URI](/media/tidb-cloud/op-to-cloud-copy-s3-uri.png) + + 以下截图显示如何获取区域信息: + + ![获取区域信息](/media/tidb-cloud/op-to-cloud-copy-region-info.png) + +3. 运行 Dumpling 将数据导出到 Amazon S3 存储桶。 + + ```shell + dumpling \ + -u root \ + -P 4000 \ + -h 127.0.0.1 \ + -r 20000 \ + --filetype {sql|csv} \ + -F 256MiB \ + -t 8 \ + -o "${S3 URI}" \ + --s3.region "${s3.region}" + ``` + + `-t` 选项指定导出的线程数。增加线程数可以提高 Dumpling 的并发性和导出速度,但也会增加数据库的内存消耗。因此,不要将此参数设置得太大。 + + 更多信息,请参见 [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview#export-to-sql-files)。 + +4. 检查导出的数据。通常导出的数据包括以下内容: + + - `metadata`:此文件包含导出的开始时间和主二进制日志的位置。 + - `{schema}-schema-create.sql`:创建 schema 的 SQL 文件 + - `{schema}.{table}-schema.sql`:创建表的 SQL 文件 + - `{schema}.{table}.{0001}.{sql|csv}`:数据文件 + - `*-schema-view.sql`、`*-schema-trigger.sql`、`*-schema-post.sql`:其他导出的 SQL 文件 + +### 将数据从 Amazon S3 迁移到 TiDB Cloud + +将数据从 TiDB 自建集群导出到 Amazon S3 后,你需要将数据迁移到 TiDB Cloud。 + +1. 在 TiDB Cloud 控制台中获取集群的账户 ID 和外部 ID。更多信息,请参见[步骤 2. 配置 Amazon S3 访问](/tidb-cloud/tidb-cloud-auditing.md#step-2-configure-amazon-s3-access)。 + + 以下截图显示如何获取账户 ID 和外部 ID: + + ![获取账户 ID 和外部 ID](/media/tidb-cloud/op-to-cloud-get-role-arn.png) + +2. 配置 Amazon S3 的访问权限。通常你需要以下只读权限: + + - s3:GetObject + - s3:GetObjectVersion + - s3:ListBucket + - s3:GetBucketLocation + + 如果 S3 存储桶使用服务器端加密 SSE-KMS,你还需要添加 KMS 权限。 + + - kms:Decrypt + +3. 配置访问策略。转到 [AWS 控制台 > IAM > 访问管理 > 策略](https://console.aws.amazon.com/iamv2/home#/policies),切换到你的区域,检查是否已存在 TiDB Cloud 的访问策略。如果不存在,请按照[在 JSON 选项卡上创建策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html)文档创建策略。 + + 以下是 json 策略的示例模板。 + + ```json + ## 创建 json 策略模板 + ##:填写 S3 存储桶中要导入的数据文件所在文件夹的路径。 + ##:填写 S3 存储桶的 ARN。你可以在 S3 存储桶概览页面上点击复制 ARN 按钮获取。 + ##:填写 S3 存储桶 KMS 密钥的 ARN。你可以从 S3 存储桶 > 属性 > 默认加密 > AWS KMS 密钥 ARN 获取。更多信息,请参见 https://docs.aws.amazon.com/AmazonS3/latest/userguide/viewing-bucket-key-settings.html + + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion" + ], + "Resource": "arn:aws:s3:::" + }, + { + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetBucketLocation" + ], + "Resource": "" + } + // 如果你为 S3 存储桶启用了 SSE-KMS,则需要添加以下权限。 + { + "Effect": "Allow", + "Action": [ + "kms:Decrypt" + ], + "Resource": "" + } + , + { + "Effect": "Allow", + "Action": "kms:Decrypt", + "Resource": "" + } + ] + } + ``` + +4. 配置角色。请参见[创建 IAM 角色(控制台)](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user.html)。在账户 ID 字段中,输入你在步骤 1 中记下的 TiDB Cloud 账户 ID 和 TiDB Cloud 外部 ID。 + +5. 获取 Role-ARN。转到 [AWS 控制台 > IAM > 访问管理 > 角色](https://console.aws.amazon.com/iamv2/home#/roles)。切换到你的区域。点击你创建的角色,并记下 ARN。在将数据导入 TiDB Cloud 时,你将使用它。 + +6. 将数据导入 TiDB Cloud。请参见[从云存储将 CSV 文件导入到 TiDB Cloud Dedicated](/tidb-cloud/import-csv-files.md)。 + +## 复制增量数据 + +要复制增量数据,请执行以下操作: + +1. 获取增量数据迁移的开始时间。例如,你可以从全量数据迁移的元数据文件中获取。 + + ![元数据中的开始时间](/media/tidb-cloud/start_ts_in_metadata.png) + +2. 授予 TiCDC 连接 TiDB Cloud 的权限。 + + 1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/project/clusters)中,导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + 2. 在左侧导航栏中,点击**设置** > **网络**。 + 3. 在**网络**页面上,点击**添加 IP 地址**。 + 4. 在显示的对话框中,选择**使用 IP 地址**,点击 **+**,在 **IP 地址**字段中填入 TiCDC 组件的公网 IP 地址,然后点击**确认**。现在 TiCDC 可以访问 TiDB Cloud。更多信息,请参见[配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md)。 + +3. 获取下游 TiDB Cloud 集群的连接信息。 + + 1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/project/clusters)中,导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + 2. 点击右上角的**连接**。 + 3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**,从**连接方式**下拉列表中选择**通用**。 + 4. 从连接信息中,你可以获取集群的主机 IP 地址和端口。更多信息,请参见[通过公共连接连接](/tidb-cloud/connect-via-standard-connection.md)。 + +4. 创建并运行增量复制任务。在上游集群中运行以下命令: + + ```shell + tiup cdc cli changefeed create \ + --pd=http://172.16.6.122:2379 \ + --sink-uri="tidb://root:123456@172.16.6.125:4000" \ + --changefeed-id="upstream-to-downstream" \ + --start-ts="431434047157698561" + ``` + + - `--pd`:上游集群的 PD 地址。格式为:`[upstream_pd_ip]:[pd_port]` + - `--sink-uri`:复制任务的下游地址。根据以下格式配置 `--sink-uri`。目前,scheme 支持 `mysql`、`tidb`、`kafka`、`s3` 和 `local`。 + + ```shell + [scheme]://[userinfo@][host]:[port][/path]?[query_parameters] + ``` + + - `--changefeed-id`:复制任务的 ID。格式必须匹配 ^[a-zA-Z0-9]+(\-[a-zA-Z0-9]+)*$ 正则表达式。如果未指定此 ID,TiCDC 会自动生成一个 UUID(版本 4 格式)作为 ID。 + - `--start-ts`:指定 changefeed 的起始 TSO。从此 TSO 开始,TiCDC 集群开始拉取数据。默认值为当前时间。 + + 更多信息,请参见 [TiCDC Changefeeds 的 CLI 和配置参数](https://docs.pingcap.com/tidb/dev/ticdc-changefeed-config)。 + +5. 在上游集群中重新启用 GC 机制。如果增量复制中没有发现错误或延迟,请启用 GC 机制以恢复集群的垃圾回收。 + + 运行以下命令验证设置是否生效。 + + ```sql + SET GLOBAL tidb_gc_enable = TRUE; + ``` + + 以下是示例输出,其中 `1` 表示 GC 已禁用。 + + ```sql + SELECT @@global.tidb_gc_enable; + +-------------------------+ + | @@global.tidb_gc_enable | + +-------------------------+ + | 1 | + +-------------------------+ + 1 row in set (0.01 sec) + ``` + +6. 验证增量复制任务。 + + - 如果输出中显示 "Create changefeed successfully!",则复制任务创建成功。 + - 如果状态为 `normal`,则复制任务正常。 + + ```shell + tiup cdc cli changefeed list --pd=http://172.16.6.122:2379 + ``` + + ![更新过滤器](/media/tidb-cloud/normal_status_in_replication_task.png) + + - 验证复制。向上游集群写入新记录,然后检查记录是否复制到下游 TiDB Cloud 集群。 + +7. 为上游和下游集群设置相同的时区。默认情况下,TiDB Cloud 将时区设置为 UTC。如果上游和下游集群之间的时区不同,你需要为两个集群设置相同的时区。 + + 1. 在上游集群中,运行以下命令检查时区: + + ```sql + SELECT @@global.time_zone; + ``` + + 2. 在下游集群中,运行以下命令设置时区: + + ```sql + SET GLOBAL time_zone = '+08:00'; + ``` + + 3. 再次检查时区以验证设置: + + ```sql + SELECT @@global.time_zone; + ``` + +8. 备份上游集群中的[查询绑定](/sql-plan-management.md)并在下游集群中恢复它们。你可以使用以下查询备份查询绑定: + + ```sql + SELECT DISTINCT(CONCAT('CREATE GLOBAL BINDING FOR ', original_sql,' USING ', bind_sql,';')) FROM mysql.bind_info WHERE status='enabled'; + ``` + + 如果没有得到任何输出,上游集群中可能没有使用查询绑定。在这种情况下,你可以跳过此步骤。 + + 获取查询绑定后,在下游集群中运行它们以恢复查询绑定。 + +9. 备份上游集群中的用户和权限信息,并在下游集群中恢复它们。你可以使用以下脚本备份用户和权限信息。注意需要将占位符替换为实际值。 + + ```shell + #!/bin/bash + + export MYSQL_HOST={tidb_op_host} + export MYSQL_TCP_PORT={tidb_op_port} + export MYSQL_USER=root + export MYSQL_PWD={root_password} + export MYSQL="mysql -u${MYSQL_USER} --default-character-set=utf8mb4" + + function backup_user_priv(){ + ret=0 + sql="SELECT CONCAT(user,':',host,':',authentication_string) FROM mysql.user WHERE user NOT IN ('root')" + for usr in `$MYSQL -se "$sql"`;do + u=`echo $usr | awk -F ":" '{print $1}'` + h=`echo $usr | awk -F ":" '{print $2}'` + p=`echo $usr | awk -F ":" '{print $3}'` + echo "-- Grants for '${u}'@'${h}';" + [[ ! -z "${p}" ]] && echo "CREATE USER IF NOT EXISTS '${u}'@'${h}' IDENTIFIED WITH 'mysql_native_password' AS '${p}' ;" + $MYSQL -se "SHOW GRANTS FOR '${u}'@'${h}';" | sed 's/$/;/g' + [ $? -ne 0 ] && ret=1 && break + done + return $ret + } + + backup_user_priv + ``` + + 获取用户和权限信息后,在下游集群中运行生成的 SQL 语句以恢复用户和权限信息。 diff --git a/tidb-cloud/migrate-from-oracle-using-aws-dms.md b/tidb-cloud/migrate-from-oracle-using-aws-dms.md new file mode 100644 index 000000000000..62469e6a174c --- /dev/null +++ b/tidb-cloud/migrate-from-oracle-using-aws-dms.md @@ -0,0 +1,157 @@ +--- +title: 使用 AWS DMS 从 Amazon RDS for Oracle 迁移到 TiDB Cloud +summary: 了解如何使用 AWS Database Migration Service (AWS DMS) 将数据从 Amazon RDS for Oracle 迁移到 TiDB Cloud Serverless。 +--- + +# 使用 AWS DMS 从 Amazon RDS for Oracle 迁移到 TiDB Cloud + +本文档提供了一个分步示例,说明如何使用 AWS Database Migration Service (AWS DMS) 将数据从 Amazon RDS for Oracle 迁移到 [TiDB Cloud Serverless](https://tidbcloud.com/clusters/create-cluster)。 + +如果你想了解更多关于 TiDB Cloud 和 AWS DMS 的信息,请参阅以下内容: + +- [TiDB Cloud](https://docs.pingcap.com/tidbcloud/) +- [TiDB 开发者指南](https://docs.pingcap.com/tidbcloud/dev-guide-overview) +- [AWS DMS 文档](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_GettingStarted.html) + +## 为什么使用 AWS DMS? + +AWS DMS 是一项云服务,可用于迁移关系型数据库、数据仓库、NoSQL 数据库和其他类型的数据存储。 + +如果你想从异构数据库(如 PostgreSQL、Oracle 和 SQL Server)迁移数据到 TiDB Cloud,建议使用 AWS DMS。 + +## 部署架构 + +总体上,需要执行以下步骤: + +1. 设置源 Amazon RDS for Oracle。 +2. 设置目标 [TiDB Cloud Serverless](https://tidbcloud.com/project/clusters/create-cluster)。 +3. 使用 AWS DMS 设置数据迁移(全量加载)。 + +下图展示了高级架构。 + +![架构](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-0.png) + +## 前提条件 + +开始之前,请阅读以下前提条件: + +- [AWS DMS 前提条件](/tidb-cloud/migrate-from-mysql-using-aws-dms.md#prerequisites) +- [AWS Cloud 账户](https://aws.amazon.com) +- [TiDB Cloud 账户](https://tidbcloud.com) +- [DBeaver](https://dbeaver.io/) + +接下来,你将学习如何使用 AWS DMS 将数据从 Amazon RDS for Oracle 迁移到 TiDB Cloud。 + +## 步骤 1. 创建 VPC + +登录 [AWS 控制台](https://console.aws.amazon.com/vpc/home#vpcs:) 并创建一个 AWS VPC。你稍后需要在此 VPC 中创建 Oracle RDS 和 DMS 实例。 + +有关如何创建 VPC 的说明,请参阅[创建 VPC](https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html#Create-VPC)。 + +![创建 VPC](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-1.png) + +## 步骤 2. 创建 Oracle 数据库实例 + +在刚刚创建的 VPC 中创建一个 Oracle 数据库实例,记住密码并授予公共访问权限。你必须启用公共访问才能使用 AWS Schema Conversion Tool。请注意,不建议在生产环境中授予公共访问权限。 + +有关如何创建 Oracle 数据库实例的说明,请参阅[创建 Oracle 数据库实例并连接到 Oracle 数据库实例上的数据库](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.Oracle.html)。 + +![创建 Oracle RDS](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-2.png) + +## 步骤 3. 在 Oracle 中准备表数据 + +使用以下脚本在 github_events 表中创建并填充 10000 行数据。你可以使用 github 事件数据集,并从 [GH Archive](https://gharchive.org/) 下载。它包含 10000 行数据。在 Oracle 中执行以下 SQL 脚本。 + +- [table_schema_oracle.sql](https://github.com/pingcap-inc/tidb-integration-script/blob/main/aws-dms/oracle_table_schema.sql) +- [oracle_data.sql](https://github.com/pingcap-inc/tidb-integration-script/blob/main/aws-dms/oracle_data.sql) + +执行完 SQL 脚本后,检查 Oracle 中的数据。以下示例使用 [DBeaver](https://dbeaver.io/) 查询数据: + +![Oracle RDS 数据](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-3.png) + +## 步骤 4. 创建 TiDB Cloud Serverless 集群 + +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/project/clusters)。 + +2. [创建 TiDB Cloud Serverless 集群](/tidb-cloud/tidb-cloud-quickstart.md)。 + +3. 在[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群名称进入其概览页面。 + +4. 在右上角,点击**连接**。 + +5. 点击**生成密码**生成密码并复制生成的密码。 + +## 步骤 5. 创建 AWS DMS 复制实例 + +1. 在 AWS DMS 控制台中转到[复制实例](https://console.aws.amazon.com/dms/v2/home#replicationInstances)页面,并切换到相应的区域。 + +2. 在 VPC 中创建一个 `dms.t3.large` 的 AWS DMS 复制实例。 + + ![创建 AWS DMS 实例](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-8.png) + +> **注意:** +> +> 有关创建与 TiDB Cloud Serverless 配合使用的 AWS DMS 复制实例的详细步骤,请参阅[将 AWS DMS 连接到 TiDB Cloud 集群](/tidb-cloud/tidb-cloud-connect-aws-dms.md)。 + +## 步骤 6. 创建 DMS 端点 + +1. 在 [AWS DMS 控制台](https://console.aws.amazon.com/dms/v2/home)中,点击左侧窗格中的 `Endpoints` 菜单项。 + +2. 创建 Oracle 源端点和 TiDB 目标端点。 + + 以下截图显示了源端点的配置。 + + ![创建 AWS DMS 源端点](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-9.png) + + 以下截图显示了目标端点的配置。 + + ![创建 AWS DMS 目标端点](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-10.png) + +> **注意:** +> +> 有关创建 TiDB Cloud Serverless DMS 端点的详细步骤,请参阅[将 AWS DMS 连接到 TiDB Cloud 集群](/tidb-cloud/tidb-cloud-connect-aws-dms.md)。 + +## 步骤 7. 迁移架构 + +在本示例中,由于架构定义简单,AWS DMS 会自动处理架构。 + +如果你决定使用 AWS Schema Conversion Tool 迁移架构,请参阅[安装 AWS SCT](https://docs.aws.amazon.com/SchemaConversionTool/latest/userguide/CHAP_Installing.html#CHAP_Installing.Procedure)。 + +更多信息,请参阅[使用 AWS SCT 将源架构迁移到目标数据库](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_GettingStarted.SCT.html)。 + +## 步骤 8. 创建数据库迁移任务 + +1. 在 AWS DMS 控制台中,转到[数据迁移任务](https://console.aws.amazon.com/dms/v2/home#tasks)页面。切换到你的区域。然后点击窗口右上角的**创建任务**。 + + ![创建任务](/media/tidb-cloud/aws-dms-to-tidb-cloud-create-task.png) + +2. 创建数据库迁移任务并指定**选择规则**: + + ![创建 AWS DMS 迁移任务](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-11.png) + + ![AWS DMS 迁移任务选择规则](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-12.png) + +3. 创建任务,启动它,然后等待任务完成。 + +4. 点击**表统计信息**检查表。架构名称是 `ADMIN`。 + + ![检查 AWS DMS 迁移任务](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-13.png) + +## 步骤 9. 检查下游 TiDB 集群中的数据 + +连接到 [TiDB Cloud Serverless 集群](https://tidbcloud.com/clusters/create-cluster)并检查 `admin.github_event` 表数据。如下截图所示,DMS 成功迁移了表 `github_events` 和 10000 行数据。 + +![检查 TiDB 中的数据](/media/tidb-cloud/aws-dms-from-oracle-to-tidb-14.png) + +## 总结 + +使用 AWS DMS,你可以按照本文档中的示例成功地从任何上游 AWS RDS 数据库迁移数据。 + +如果在迁移过程中遇到任何问题或失败,你可以在 [CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 中检查日志信息来排查问题。 + +![故障排除](/media/tidb-cloud/aws-dms-to-tidb-cloud-troubleshooting.png) + +## 另请参阅 + +- [使用 AWS DMS 从 MySQL 兼容数据库迁移](/tidb-cloud/migrate-from-mysql-using-aws-dms.md) +- [将 AWS DMS 连接到 TiDB Cloud 集群](/tidb-cloud/tidb-cloud-connect-aws-dms.md) diff --git a/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md b/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md new file mode 100644 index 000000000000..b930ab3635ae --- /dev/null +++ b/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md @@ -0,0 +1,242 @@ +--- +title: 使用数据迁移功能从 MySQL 兼容数据库仅迁移增量数据到 TiDB Cloud +summary: 了解如何使用数据迁移功能将 Amazon Aurora MySQL、Amazon Relational Database Service (RDS)、Google Cloud SQL for MySQL、Azure Database for MySQL 或本地 MySQL 实例中的增量数据迁移到 TiDB Cloud。 +--- + +# 使用数据迁移功能从 MySQL 兼容数据库仅迁移增量数据到 TiDB Cloud + +本文档介绍如何使用 TiDB Cloud 控制台的数据迁移功能,将云服务商(Amazon Aurora MySQL、Amazon Relational Database Service (RDS)、Google Cloud SQL for MySQL 或 Azure Database for MySQL)或自托管源数据库中的增量数据迁移到 TiDB Cloud。 + +关于如何迁移现有数据或同时迁移现有数据和增量数据的说明,请参见[使用数据迁移功能将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +## 限制 + +> **注意:** +> +> 本节仅包含增量数据迁移的限制。建议你同时阅读通用限制。参见[限制](/tidb-cloud/migrate-from-mysql-using-data-migration.md#limitations)。 + +- 如果目标数据库中尚未创建目标表,迁移任务将报告以下错误并失败。在这种情况下,你需要手动创建目标表,然后重试迁移任务。 + + ```sql + startLocation: [position: (mysql_bin.000016, 5122), gtid-set: + 00000000-0000-0000-0000-00000000000000000], endLocation: + [position: (mysql_bin.000016, 5162), gtid-set: 0000000-0000-0000 + 0000-0000000000000:0]: cannot fetch downstream table schema of + zm`.'table1' to initialize upstream schema 'zm'.'table1' in sschema + tracker Raw Cause: Error 1146: Table 'zm.table1' doesn't exist + ``` + +- 如果上游删除或更新了某些行,而下游没有相应的行,迁移任务在从上游复制 `DELETE` 和 `UPDATE` DML 操作时会检测到没有可供删除或更新的行。 + +如果你指定 GTID 作为迁移增量数据的起始位置,请注意以下限制: + +- 确保源数据库已启用 GTID 模式。 +- 如果源数据库是 MySQL,MySQL 版本必须是 5.6 或更高版本,存储引擎必须是 InnoDB。 +- 如果迁移任务连接到上游的从库,则无法迁移 `REPLICATE CREATE TABLE ... SELECT` 事件。这是因为该语句会被拆分为两个事务(`CREATE TABLE` 和 `INSERT`),它们被分配了相同的 GTID。因此,从库会忽略 `INSERT` 语句。 + +## 前提条件 + +> **注意:** +> +> 本节仅包含增量数据迁移的前提条件。建议你同时阅读[通用前提条件](/tidb-cloud/migrate-from-mysql-using-data-migration.md#prerequisites)。 + +如果你想使用 GTID 指定起始位置,请确保源数据库已启用 GTID。操作因数据库类型而异。 + +### 对于 Amazon RDS 和 Amazon Aurora MySQL + +对于 Amazon RDS 和 Amazon Aurora MySQL,你需要创建一个新的可修改参数组(即非默认参数组),然后修改参数组中的以下参数并重启实例应用。 + +- `gtid_mode` +- `enforce_gtid_consistency` + +你可以通过执行以下 SQL 语句来检查 GTID 模式是否已成功启用: + +```sql +SHOW VARIABLES LIKE 'gtid_mode'; +``` + +如果结果是 `ON` 或 `ON_PERMISSIVE`,则 GTID 模式已成功启用。 + +更多信息,请参见 [Parameters for GTID-based replication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/mysql-replication-gtid.html#mysql-replication-gtid.parameters)。 + +### 对于 Google Cloud SQL for MySQL + +Google Cloud SQL for MySQL 默认启用 GTID 模式。你可以通过执行以下 SQL 语句来检查 GTID 模式是否已成功启用: + +```sql +SHOW VARIABLES LIKE 'gtid_mode'; +``` + +如果结果是 `ON` 或 `ON_PERMISSIVE`,则 GTID 模式已成功启用。 + +### 对于 Azure Database for MySQL + +Azure Database for MySQL(5.7 及更高版本)默认启用 GTID 模式。你可以通过执行以下 SQL 语句来检查 GTID 模式是否已成功启用: + +```sql +SHOW VARIABLES LIKE 'gtid_mode'; +``` + +如果结果是 `ON` 或 `ON_PERMISSIVE`,则 GTID 模式已成功启用。 + +此外,确保 `binlog_row_image` 服务器参数设置为 `FULL`。你可以通过执行以下 SQL 语句来检查: + +```sql +SHOW VARIABLES LIKE 'binlog_row_image'; +``` + +如果结果不是 `FULL`,你需要使用 [Azure 门户](https://portal.azure.com/)或 [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/) 为你的 Azure Database for MySQL 实例配置此参数。 + +### 对于自托管 MySQL 实例 + +> **注意:** +> +> 具体步骤和命令可能因 MySQL 版本和配置而异。确保你了解启用 GTID 的影响,并在执行此操作之前在非生产环境中进行适当的测试和验证。 + +要为自托管 MySQL 实例启用 GTID 模式,请按照以下步骤操作: + +1. 使用具有适当权限的 MySQL 客户端连接到 MySQL 服务器。 + +2. 执行以下 SQL 语句以启用 GTID 模式: + + ```sql + -- 启用 GTID 模式 + SET GLOBAL gtid_mode = ON; + + -- 启用 `enforce_gtid_consistency` + SET GLOBAL enforce_gtid_consistency = ON; + + -- 重新加载 GTID 配置 + RESET MASTER; + ``` + +3. 重启 MySQL 服务器以确保配置更改生效。 + +4. 通过执行以下 SQL 语句检查 GTID 模式是否已成功启用: + + ```sql + SHOW VARIABLES LIKE 'gtid_mode'; + ``` + + 如果结果是 `ON` 或 `ON_PERMISSIVE`,则 GTID 模式已成功启用。 + +## 步骤 1:进入数据迁移页面 + +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **迁移**。 + +3. 在**数据迁移**页面,点击右上角的**创建迁移任务**。此时会显示**创建迁移任务**页面。 + +## 步骤 2:配置源和目标连接 + +在**创建迁移任务**页面,配置源和目标连接。 + +1. 输入任务名称,必须以字母开头,且长度不超过 60 个字符。可以使用字母(A-Z、a-z)、数字(0-9)、下划线(_)和连字符(-)。 + +2. 填写源连接配置。 + + - **数据源**:数据源类型。 + - **区域**:数据源的区域,仅云数据库需要。 + - **连接方式**:数据源的连接方式。目前,你可以根据你的连接方式选择公共 IP、VPC 对等连接或 Private Link。 + - **主机名或 IP 地址**(适用于公共 IP 和 VPC 对等连接):数据源的主机名或 IP 地址。 + - **服务名称**(适用于 Private Link):端点服务名称。 + - **端口**:数据源的端口。 + - **用户名**:数据源的用户名。 + - **密码**:用户名的密码。 + - **SSL/TLS**:如果启用 SSL/TLS,你需要上传数据源的证书,包括以下任意一项: + - 仅 CA 证书 + - 客户端证书和客户端密钥 + - CA 证书、客户端证书和客户端密钥 + +3. 填写目标连接配置。 + + - **用户名**:输入 TiDB Cloud 中目标集群的用户名。 + - **密码**:输入 TiDB Cloud 用户名的密码。 + +4. 点击**验证连接并继续**以验证你输入的信息。 + +5. 根据你看到的消息采取行动: + + - 如果使用公共 IP 或 VPC 对等连接,你需要将数据迁移服务的 IP 地址添加到源数据库的 IP 访问列表和防火墙(如果有)中。 + - 如果使用 AWS Private Link,系统会提示你接受端点请求。转到 [AWS VPC 控制台](https://us-west-2.console.aws.amazon.com/vpc/home),点击**端点服务**以接受端点请求。 + +## 步骤 3:选择迁移任务类型 + +要仅将源数据库的增量数据迁移到 TiDB Cloud,请选择**增量数据迁移**,不要选择**现有数据迁移**。这样,迁移任务只会将源数据库的持续变更迁移到 TiDB Cloud。 + +在**起始位置**区域,你可以为增量数据迁移指定以下类型的起始位置之一: + +- 增量迁移任务开始的时间 +- GTID +- Binlog 文件名和位置 + +迁移任务开始后,你无法更改起始位置。 + +### 增量迁移任务开始的时间 + +如果选择此选项,迁移任务将只迁移迁移任务开始后在源数据库中生成的增量数据。 + +### 指定 GTID + +选择此选项以指定源数据库的 GTID,例如 `3E11FA47-71CA-11E1-9E33-C80AA9429562:1-23`。迁移任务将复制不包含指定 GTID 集的事务,以将源数据库的持续变更迁移到 TiDB Cloud。 + +你可以运行以下命令来检查源数据库的 GTID: + +```sql +SHOW MASTER STATUS; +``` + +有关如何启用 GTID 的信息,请参见[前提条件](#前提条件)。 + +### 指定 binlog 文件名和位置 + +选择此选项以指定源数据库的 binlog 文件名(例如 `binlog.000001`)和 binlog 位置(例如 `1307`)。迁移任务将从指定的 binlog 文件名和位置开始,将源数据库的持续变更迁移到 TiDB Cloud。 + +你可以运行以下命令来检查源数据库的 binlog 文件名和位置: + +```sql +SHOW MASTER STATUS; +``` + +如果目标数据库中有数据,请确保 binlog 位置正确。否则,现有数据和增量数据之间可能会发生冲突。如果发生冲突,迁移任务将失败。如果你想用源数据库中的数据替换冲突的记录,可以恢复迁移任务。 + +## 步骤 4:选择要迁移的对象 + +1. 在**选择要迁移的对象**页面,选择要迁移的对象。你可以点击**全部**选择所有对象,或点击**自定义**,然后点击对象名称旁边的复选框选择对象。 + +2. 点击**下一步**。 + +## 步骤 5:预检查 + +在**预检查**页面,你可以查看预检查结果。如果预检查失败,你需要根据**失败**或**警告**详情进行操作,然后点击**重新检查**以重新检查。 + +如果某些检查项只有警告,你可以评估风险并考虑是否忽略警告。如果所有警告都被忽略,迁移任务将自动进入下一步。 + +有关错误和解决方案的更多信息,请参见[预检查错误和解决方案](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#precheck-errors-and-solutions)。 + +有关预检查项的更多信息,请参见[迁移任务预检查](https://docs.pingcap.com/tidb/stable/dm-precheck)。 + +如果所有检查项都显示**通过**,点击**下一步**。 + +## 步骤 6:选择规格并开始迁移 + +在**选择规格并开始迁移**页面,根据你的性能要求选择适当的迁移规格。有关规格的更多信息,请参见[数据迁移的规格](/tidb-cloud/tidb-cloud-billing-dm.md#specifications-for-data-migration)。 + +选择规格后,点击**创建任务并开始**以开始迁移。 + +## 步骤 7:查看迁移进度 + +创建迁移任务后,你可以在**迁移任务详情**页面查看迁移进度。迁移进度显示在**阶段和状态**区域。 + +你可以在迁移任务运行时暂停或删除它。 + +如果迁移任务失败,你可以在解决问题后恢复它。 + +你可以在任何状态下删除迁移任务。 + +如果在迁移过程中遇到任何问题,请参见[迁移错误和解决方案](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#migration-errors-and-solutions)。 diff --git a/tidb-cloud/migrate-sql-shards.md b/tidb-cloud/migrate-sql-shards.md new file mode 100644 index 000000000000..3315564b5470 --- /dev/null +++ b/tidb-cloud/migrate-sql-shards.md @@ -0,0 +1,599 @@ +--- +title: 将大规模 MySQL 分片数据迁移和合并到 TiDB Cloud +summary: 了解如何将大规模 MySQL 分片数据迁移和合并到 TiDB Cloud。 +--- + +# 将大规模 MySQL 分片数据迁移和合并到 TiDB Cloud + +本文档介绍如何将大规模 MySQL 数据集(例如,超过 1 TiB)从不同分区迁移到 TiDB Cloud。完成全量数据迁移后,你可以根据业务需求使用 [TiDB Data Migration (DM)](https://docs.pingcap.com/tidb/stable/dm-overview) 执行增量迁移。 + +本文档中的示例使用了跨多个 MySQL 实例的复杂分片迁移任务,并涉及处理自增主键的冲突。本示例中的场景也适用于合并单个 MySQL 实例中不同分片表的数据。 + +## 示例环境信息 + +本节描述示例中使用的上游集群、DM 和下游集群的基本信息。 + +### 上游集群 + +上游集群的环境信息如下: + +- MySQL 版本:MySQL v5.7.18 +- MySQL 实例 1: + - schema `store_01` 和表 `[sale_01, sale_02]` + - schema `store_02` 和表 `[sale_01, sale_02]` +- MySQL 实例 2: + - schema `store_01` 和表 `[sale_01, sale_02]` + - schema `store_02` 和表 `[sale_01, sale_02]` +- 表结构: + + ```sql + CREATE TABLE sale_01 ( + id bigint(20) NOT NULL auto_increment, + uid varchar(40) NOT NULL, + sale_num bigint DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY ind_uid (uid) + ); + ``` + +### DM + +DM 的版本是 v5.3.0。你需要手动部署 TiDB DM。详细步骤,请参见[使用 TiUP 部署 DM 集群](https://docs.pingcap.com/tidb/stable/deploy-a-dm-cluster-using-tiup)。 + +### 外部存储 + +本文档以 Amazon S3 为例。 + +### 下游集群 + +分片的 schema 和表被合并到表 `store.sales` 中。 +## 从 MySQL 到 TiDB Cloud 执行全量数据迁移 + +以下是将 MySQL 分片的全量数据迁移和合并到 TiDB Cloud 的步骤。 + +在以下示例中,你只需要将表中的数据导出为 **CSV** 格式。 + +### 步骤 1. 在 Amazon S3 存储桶中创建目录 + +在 Amazon S3 存储桶中创建一个一级目录 `store`(对应数据库级别)和一个二级目录 `sales`(对应表级别)。在 `sales` 中,为每个 MySQL 实例创建一个三级目录(对应 MySQL 实例级别)。例如: + +- 将 MySQL 实例 1 中的数据迁移到 `s3://dumpling-s3/store/sales/instance01/` +- 将 MySQL 实例 2 中的数据迁移到 `s3://dumpling-s3/store/sales/instance02/` + +如果有跨多个实例的分片,你可以为每个数据库创建一个一级目录,为每个分片表创建一个二级目录。然后为每个 MySQL 实例创建一个三级目录,以便于管理。例如,如果你想将 MySQL 实例 1 和 MySQL 实例 2 中的表 `stock_N.product_N` 迁移和合并到 TiDB Cloud 中的表 `stock.products`,你可以创建以下目录: + +- `s3://dumpling-s3/stock/products/instance01/` +- `s3://dumpling-s3/stock/products/instance02/` + +### 步骤 2. 使用 Dumpling 将数据导出到 Amazon S3 + +有关如何安装 Dumpling 的信息,请参见 [Dumpling 简介](https://docs.pingcap.com/tidb/stable/dumpling-overview)。 + +使用 Dumpling 将数据导出到 Amazon S3 时,请注意以下事项: + +- 为上游集群启用 binlog。 +- 选择正确的 Amazon S3 目录和区域。 +- 通过配置 `-t` 选项选择适当的并发度,以最小化对上游集群的影响,或直接从备份数据库导出。有关如何使用此参数的更多信息,请参见 [Dumpling 参数列表](https://docs.pingcap.com/tidb/stable/dumpling-overview#option-list-of-dumpling)。 +- 为 `--filetype csv` 和 `--no-schemas` 设置适当的值。有关如何使用这些参数的更多信息,请参见 [Dumpling 参数列表](https://docs.pingcap.com/tidb/stable/dumpling-overview#option-list-of-dumpling)。 + +CSV 文件的命名规则如下: + +- 如果一个表的数据被分成多个 CSV 文件,在这些 CSV 文件后面添加数字后缀。例如,`${db_name}.${table_name}.000001.csv` 和 `${db_name}.${table_name}.000002.csv`。数字后缀可以不连续但必须按升序排列。你还需要在数字前添加额外的零,以确保所有后缀的长度相同。 + +> **注意:** +> +> 如果在某些情况下无法按照上述规则更新 CSV 文件名(例如,CSV 文件链接也被其他程序使用),你可以保持文件名不变,并在[步骤 5](#步骤-5-执行数据导入任务) 中使用**映射设置**将源数据导入到单个目标表。 + +要将数据导出到 Amazon S3,请执行以下操作: + +1. 获取 Amazon S3 存储桶的 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY`。 + + ```shell + [root@localhost ~]# export AWS_ACCESS_KEY_ID={your_aws_access_key_id} + [root@localhost ~]# export AWS_SECRET_ACCESS_KEY= {your_aws_secret_access_key} + ``` + +2. 将数据从 MySQL 实例 1 导出到 Amazon S3 存储桶中的 `s3://dumpling-s3/store/sales/instance01/` 目录。 + + ```shell + [root@localhost ~]# tiup dumpling -u {username} -p {password} -P {port} -h {mysql01-ip} -B store_01,store_02 -r 20000 --filetype csv --no-schemas -o "s3://dumpling-s3/store/sales/instance01/" --s3.region "ap-northeast-1" + ``` + + 有关参数的更多信息,请参见 [Dumpling 参数列表](https://docs.pingcap.com/tidb/stable/dumpling-overview#option-list-of-dumpling)。 + +3. 将数据从 MySQL 实例 2 导出到 Amazon S3 存储桶中的 `s3://dumpling-s3/store/sales/instance02/` 目录。 + + ```shell + [root@localhost ~]# tiup dumpling -u {username} -p {password} -P {port} -h {mysql02-ip} -B store_01,store_02 -r 20000 --filetype csv --no-schemas -o "s3://dumpling-s3/store/sales/instance02/" --s3.region "ap-northeast-1" + ``` + +详细步骤,请参见[导出数据到 Amazon S3 云存储](https://docs.pingcap.com/tidb/stable/dumpling-overview#export-data-to-amazon-s3-cloud-storage)。 + +### 步骤 3. 在 TiDB Cloud 集群中创建 schema + +按照以下步骤在 TiDB Cloud 集群中创建 schema: + +```sql +mysql> CREATE DATABASE store; +Query OK, 0 rows affected (0.16 sec) +mysql> use store; +Database changed +``` + +在本示例中,上游表 `sale_01` 和 `sale_02` 的列 ID 是自增主键。在下游数据库中合并分片表时可能会发生冲突。执行以下 SQL 语句将 ID 列设置为普通索引而不是主键: + +```sql +mysql> CREATE TABLE `sales` ( + `id` bigint(20) NOT NULL , + `uid` varchar(40) NOT NULL, + `sale_num` bigint DEFAULT NULL, + INDEX (`id`), + UNIQUE KEY `ind_uid` (`uid`) + ); +Query OK, 0 rows affected (0.17 sec) +``` + +有关解决此类冲突的解决方案,请参见[移除列的 PRIMARY KEY 属性](https://docs.pingcap.com/tidb/stable/shard-merge-best-practices#remove-the-primary-key-attribute-from-the-column)。 +### 步骤 4. 配置 Amazon S3 访问 + +按照[配置 Amazon S3 访问](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)中的说明获取访问源数据的角色 ARN。 + +以下示例仅列出关键策略配置。请将 Amazon S3 路径替换为你自己的值。 + +```yaml +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion" + ], + "Resource": [ + "arn:aws:s3:::dumpling-s3/*" + ] + }, + { + "Sid": "VisualEditor1", + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetBucketLocation" + ], + + "Resource": "arn:aws:s3:::dumpling-s3" + } + ] +} +``` + +### 步骤 5. 执行数据导入任务 + +配置 Amazon S3 访问后,你可以在 TiDB Cloud 控制台中执行数据导入任务,步骤如下: + +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的下拉框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 选择**从云存储导入数据**,然后点击 **Amazon S3**。 + +3. 在**从 Amazon S3 导入数据**页面,填写以下信息: + + - **导入文件数量**:对于 TiDB Cloud Serverless,选择**多个文件**。TiDB Cloud Dedicated 中不提供此字段。 + - **包含 Schema 文件**:选择**否**。 + - **数据格式**:选择 **CSV**。 + - **文件夹 URI**:填写源数据的存储桶 URI。你可以使用对应表的二级目录,本例中为 `s3://dumpling-s3/store/sales/`,这样 TiDB Cloud 可以一次性将所有 MySQL 实例中的数据导入并合并到 `store.sales` 中。 + - **存储桶访问** > **AWS Role ARN**:输入你获取的 Role-ARN。 + + 如果存储桶的位置与你的集群不同,请确认跨区域合规性。 + + TiDB Cloud 开始验证是否可以访问指定存储桶 URI 中的数据。验证后,TiDB Cloud 会使用默认的文件命名模式尝试扫描数据源中的所有文件,并在下一页的左侧返回扫描摘要结果。如果遇到 `AccessDenied` 错误,请参见[排查从 S3 导入数据时的访问被拒绝错误](/tidb-cloud/troubleshoot-import-access-denied-error.md)。 + +4. 点击**连接**。 + +5. 在**目标**部分,选择目标数据库和表。 + + 导入多个文件时,你可以使用**高级设置** > **映射设置**为每个目标表及其对应的 CSV 文件定义自定义映射规则。之后,数据源文件将使用提供的自定义映射规则重新扫描。 + + 在**源文件 URI 和名称**中输入源文件 URI 和名称时,确保其格式为 `s3://[bucket_name]/[data_source_folder]/[file_name].csv`。例如,`s3://sampledata/ingest/TableName.01.csv`。 + + 你也可以使用通配符来匹配源文件。例如: + + - `s3://[bucket_name]/[data_source_folder]/my-data?.csv`:该文件夹中以 `my-data` 开头后跟一个字符的所有 CSV 文件(如 `my-data1.csv` 和 `my-data2.csv`)将被导入到同一个目标表中。 + + - `s3://[bucket_name]/[data_source_folder]/my-data*.csv`:该文件夹中以 `my-data` 开头的所有 CSV 文件将被导入到同一个目标表中。 + + 注意,仅支持 `?` 和 `*` 通配符。 + + > **注意:** + > + > URI 必须包含数据源文件夹。 + +6. 如果需要,编辑 CSV 配置。 + + 你也可以点击**编辑 CSV 配置**来配置反斜杠转义、分隔符和定界符,以实现更精细的控制。 + + > **注意:** + > + > 对于分隔符、定界符和空值的配置,你可以使用字母数字字符和某些特殊字符。支持的特殊字符包括 `\t`、`\b`、`\n`、`\r`、`\f` 和 `\u0001`。 + +7. 点击**开始导入**。 + +8. 当导入进度显示**已完成**时,检查导入的表。 + +数据导入后,如果你想移除 TiDB Cloud 的 Amazon S3 访问权限,只需删除你添加的策略即可。 +## 从 MySQL 到 TiDB Cloud 执行增量数据复制 + +要基于 binlog 从上游集群的指定位置复制数据变更到 TiDB Cloud,你可以使用 TiDB Data Migration (DM) 执行增量复制。 + +### 开始之前 + +如果你想迁移增量数据并合并 MySQL 分片到 TiDB Cloud,你需要手动部署 TiDB DM,因为 TiDB Cloud 目前不支持迁移和合并 MySQL 分片。详细步骤,请参见[使用 TiUP 部署 DM 集群](https://docs.pingcap.com/tidb/stable/deploy-a-dm-cluster-using-tiup)。 + +### 步骤 1. 添加数据源 + +1. 创建一个新的数据源文件 `dm-source1.yaml` 以将上游数据源配置到 DM 中。添加以下内容: + + ```yaml + # MySQL 配置。 + source-id: "mysql-replica-01" + # 指定 DM-worker 是否使用 GTID(全局事务标识符)拉取 binlog。 + # 前提是你已经在上游 MySQL 中启用了 GTID。 + # 如果你已经配置上游数据库服务在不同节点之间自动切换主节点,则必须启用 GTID。 + enable-gtid: true + from: + host: "${host}" # 例如:192.168.10.101 + user: "user01" + password: "${password}" # 支持明文密码,但不推荐。建议使用 dmctl encrypt 加密明文密码。 + port: ${port} # 例如:3307 + ``` + +2. 创建另一个新的数据源文件 `dm-source2.yaml`,并添加以下内容: + + ```yaml + # MySQL 配置。 + source-id: "mysql-replica-02" + # 指定 DM-worker 是否使用 GTID(全局事务标识符)拉取 binlog。 + # 前提是你已经在上游 MySQL 中启用了 GTID。 + # 如果你已经配置上游数据库服务在不同节点之间自动切换主节点,则必须启用 GTID。 + enable-gtid: true + from: + host: "192.168.10.102" + user: "user02" + password: "${password}" + port: 3308 + ``` + +3. 在终端中运行以下命令。使用 `tiup dmctl` 将第一个数据源配置加载到 DM 集群中: + + ```shell + [root@localhost ~]# tiup dmctl --master-addr ${advertise-addr} operate-source create dm-source1.yaml + ``` + + 上述命令中使用的参数说明如下: + + |参数 |说明 | + |- |- | + |`--master-addr` |要连接的 DM 集群中任一 DM-master 节点的 `{advertise-addr}`。例如:192.168.11.110:9261| + |`operate-source create`|将数据源加载到 DM 集群。| + + 以下是示例输出: + + ```shell + tiup is checking updates for component dmctl ... + + Starting component `dmctl`: /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl --master-addr 192.168.11.110:9261 operate-source create dm-source1.yaml + + { + "result": true, + "msg": "", + "sources": [ + { + "result": true, + "msg": "", + "source": "mysql-replica-01", + "worker": "dm-192.168.11.111-9262" + } + ] + } + + ``` + +4. 在终端中运行以下命令。使用 `tiup dmctl` 将第二个数据源配置加载到 DM 集群中: + + ```shell + [root@localhost ~]# tiup dmctl --master-addr 192.168.11.110:9261 operate-source create dm-source2.yaml + ``` + + 以下是示例输出: + + ```shell + tiup is checking updates for component dmctl ... + + Starting component `dmctl`: /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl --master-addr 192.168.11.110:9261 operate-source create dm-source2.yaml + + { + "result": true, + "msg": "", + "sources": [ + { + "result": true, + "msg": "", + "source": "mysql-replica-02", + "worker": "dm-192.168.11.112-9262" + } + ] + } + ``` +### 步骤 2. 创建复制任务 + +1. 为复制任务创建一个 `test-task1.yaml` 文件。 + +2. 在 Dumpling 导出的 MySQL 实例 1 的元数据文件中找到起始点。例如: + + ```toml + Started dump at: 2022-05-25 10:16:26 + SHOW MASTER STATUS: + Log: mysql-bin.000002 + Pos: 246546174 + GTID:b631bcad-bb10-11ec-9eee-fec83cf2b903:1-194801 + Finished dump at: 2022-05-25 10:16:27 + ``` + +3. 在 Dumpling 导出的 MySQL 实例 2 的元数据文件中找到起始点。例如: + + ```toml + Started dump at: 2022-05-25 10:20:32 + SHOW MASTER STATUS: + Log: mysql-bin.000001 + Pos: 1312659 + GTID:cd21245e-bb10-11ec-ae16-fec83cf2b903:1-4036 + Finished dump at: 2022-05-25 10:20:32 + ``` + +4. 编辑任务配置文件 `test-task1`,为每个数据源配置增量复制模式和复制起始点。 + + ```yaml + ## ********* 任务配置 ********* + name: test-task1 + shard-mode: "pessimistic" + # 任务模式。"incremental" 模式仅执行增量数据迁移。 + task-mode: incremental + # timezone: "UTC" + + ## ******** 数据源配置 ********** + ## (可选)如果你需要增量复制已经在全量数据迁移中迁移的数据,则需要启用安全模式以避免增量数据迁移错误。 + ## 这种情况在以下场景中很常见:全量迁移数据不属于数据源的一致性快照,之后 DM 从早于全量迁移的位置开始复制增量数据。 + syncers: # 同步处理单元的运行配置。 + global: # 配置名称。 + safe-mode: false # # 如果此字段设置为 true,DM 会将数据源的 INSERT 更改为目标数据库的 REPLACE, + # # 并将数据源的 UPDATE 更改为目标数据库的 DELETE 和 REPLACE。 + # # 这是为了确保当表结构包含主键或唯一索引时,DML 语句可以重复导入。 + # # 在启动或恢复增量迁移任务的第一分钟,DM 会自动启用安全模式。 + mysql-instances: + - source-id: "mysql-replica-01" + block-allow-list: "bw-rule-1" + route-rules: ["store-route-rule", "sale-route-rule"] + filter-rules: ["store-filter-rule", "sale-filter-rule"] + syncer-config-name: "global" + meta: + binlog-name: "mysql-bin.000002" + binlog-pos: 246546174 + binlog-gtid: "b631bcad-bb10-11ec-9eee-fec83cf2b903:1-194801" + - source-id: "mysql-replica-02" + block-allow-list: "bw-rule-1" + route-rules: ["store-route-rule", "sale-route-rule"] + filter-rules: ["store-filter-rule", "sale-filter-rule"] + syncer-config-name: "global" + meta: + binlog-name: "mysql-bin.000001" + binlog-pos: 1312659 + binlog-gtid: "cd21245e-bb10-11ec-ae16-fec83cf2b903:1-4036" + + ## ******** TiDB Cloud 上目标 TiDB 集群的配置 ********** + target-database: # TiDB Cloud 上的目标 TiDB 集群 + host: "tidb.xxxxxxx.xxxxxxxxx.ap-northeast-1.prod.aws.tidbcloud.com" + port: 4000 + user: "root" + password: "${password}" # 如果密码不为空,建议使用 dmctl 加密的密文。 + + ## ******** 功能配置 ********** + routes: + store-route-rule: + schema-pattern: "store_*" + target-schema: "store" + sale-route-rule: + schema-pattern: "store_*" + table-pattern: "sale_*" + target-schema: "store" + target-table: "sales" + filters: + sale-filter-rule: + schema-pattern: "store_*" + table-pattern: "sale_*" + events: ["truncate table", "drop table", "delete"] + action: Ignore + store-filter-rule: + schema-pattern: "store_*" + events: ["drop database"] + action: Ignore + block-allow-list: + bw-rule-1: + do-dbs: ["store_*"] + + ## ******** 忽略检查项 ********** + ignore-checking-items: ["table_schema","auto_increment_ID"] + ``` + +有关详细的任务配置,请参见 [DM 任务配置](https://docs.pingcap.com/tidb/stable/task-configuration-file-full)。 + +为了使数据复制任务顺利运行,DM 会在任务开始时自动触发预检查并返回检查结果。DM 仅在预检查通过后才开始复制。要手动触发预检查,请运行 check-task 命令: + +```shell +[root@localhost ~]# tiup dmctl --master-addr 192.168.11.110:9261 check-task dm-task.yaml +``` + +以下是示例输出: + +```shell +tiup is checking updates for component dmctl ... + +Starting component `dmctl`: /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl --master-addr 192.168.11.110:9261 check-task dm-task.yaml + +{ + "result": true, + "msg": "check pass!!!" +} +``` + +### 步骤 3. 启动复制任务 + +使用 `tiup dmctl` 运行以下命令来启动数据复制任务: + +```shell +[root@localhost ~]# tiup dmctl --master-addr ${advertise-addr} start-task dm-task.yaml +``` + +上述命令中使用的参数说明如下: + +|参数 |说明 | +|- |- | +|`--master-addr` |要连接的 DM 集群中任一 DM-master 节点的 `{advertise-addr}`。例如:192.168.11.110:9261| +|`start-task` |启动迁移任务。| + +以下是示例输出: + +```shell +tiup is checking updates for component dmctl ... + +Starting component `dmctl`: /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl /root/.tiup/components/dmctl/${tidb_version}/dmctl/dmctl --master-addr 192.168.11.110:9261 start-task dm-task.yaml + +{ + "result": true, + "msg": "", + "sources": [ + { + "result": true, + "msg": "", + "source": "mysql-replica-01", + "worker": "dm-192.168.11.111-9262" + }, + + { + "result": true, + "msg": "", + "source": "mysql-replica-02", + "worker": "dm-192.168.11.112-9262" + } + ], + "checkResult": "" +} +``` + +如果任务启动失败,请检查提示消息并修复配置。之后,你可以重新运行上述命令来启动任务。 + +如果遇到任何问题,请参考 [DM 错误处理](https://docs.pingcap.com/tidb/stable/dm-error-handling) 和 [DM 常见问题](https://docs.pingcap.com/tidb/stable/dm-faq)。 + +### 步骤 4. 检查复制任务状态 + +要了解 DM 集群是否有正在进行的复制任务并查看任务状态,请使用 `tiup dmctl` 运行 `query-status` 命令: + +```shell +[root@localhost ~]# tiup dmctl --master-addr 192.168.11.110:9261 query-status test-task1 +``` + +以下是示例输出: + +```shell +{ + "result": true, + "msg": "", + "sources": [ + { + "result": true, + "msg": "", + "sourceStatus": { + "source": "mysql-replica-01", + "worker": "dm-192.168.11.111-9262", + "result": null, + "relayStatus": null + }, + + "subTaskStatus": [ + { + "name": "test-task1", + "stage": "Running", + "unit": "Sync", + "result": null, + "unresolvedDDLLockID": "", + "sync": { + "totalEvents": "4048", + "totalTps": "3", + "recentTps": "3", + "masterBinlog": "(mysql-bin.000002, 246550002)", + "masterBinlogGtid": "b631bcad-bb10-11ec-9eee-fec83cf2b903:1-194813", + "syncerBinlog": "(mysql-bin.000002, 246550002)", + "syncerBinlogGtid": "b631bcad-bb10-11ec-9eee-fec83cf2b903:1-194813", + "blockingDDLs": [ + ], + "unresolvedGroups": [ + ], + "synced": true, + "binlogType": "remote", + "secondsBehindMaster": "0", + "blockDDLOwner": "", + "conflictMsg": "" + } + } + ] + }, + { + "result": true, + "msg": "", + "sourceStatus": { + "source": "mysql-replica-02", + "worker": "dm-192.168.11.112-9262", + "result": null, + "relayStatus": null + }, + "subTaskStatus": [ + { + "name": "test-task1", + "stage": "Running", + "unit": "Sync", + "result": null, + "unresolvedDDLLockID": "", + "sync": { + "totalEvents": "33", + "totalTps": "0", + "recentTps": "0", + "masterBinlog": "(mysql-bin.000001, 1316487)", + "masterBinlogGtid": "cd21245e-bb10-11ec-ae16-fec83cf2b903:1-4048", + "syncerBinlog": "(mysql-bin.000001, 1316487)", + "syncerBinlogGtid": "cd21245e-bb10-11ec-ae16-fec83cf2b903:1-4048", + "blockingDDLs": [ + ], + "unresolvedGroups": [ + ], + "synced": true, + "binlogType": "remote", + "secondsBehindMaster": "0", + "blockDDLOwner": "", + "conflictMsg": "" + } + } + ] + } + ] +} +``` + +有关结果的详细解释,请参见[查询状态](https://docs.pingcap.com/tidb/stable/dm-query-status)。 diff --git a/tidb-cloud/monitor-alert-email.md b/tidb-cloud/monitor-alert-email.md new file mode 100644 index 000000000000..952295eb52c1 --- /dev/null +++ b/tidb-cloud/monitor-alert-email.md @@ -0,0 +1,49 @@ +--- +title: 通过电子邮件订阅 +summary: 了解如何通过电子邮件接收告警通知来监控您的 TiDB 集群。 +--- + +# 通过电子邮件订阅 + +TiDB Cloud 为您提供了一种简单的方式来通过电子邮件、[Slack](/tidb-cloud/monitor-alert-slack.md) 和 [Zoom](/tidb-cloud/monitor-alert-zoom.md) 订阅告警通知。本文档介绍如何通过电子邮件订阅告警通知。 + +> **注意:** +> +> 目前,告警订阅功能仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +## 前提条件 + +- 要订阅 TiDB Cloud 的告警通知,您必须拥有组织的 `Organization Owner` 访问权限或目标项目的 `Project Owner` 访问权限。 + +## 订阅告警通知 + +> **提示:** +> +> 告警订阅适用于当前项目中的所有告警。如果您在项目中有多个集群,您只需订阅一次。 + +要获取项目中集群的告警通知,请按照以下步骤操作: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的下拉框切换到目标项目。 +2. 在左侧导航栏中,点击 **Project Settings** > **Alert Subscription**。 +3. 在 **Alert Subscription** 页面,点击右上角的 **Add Subscriber**。 +4. 从 **Subscriber Type** 下拉列表中选择 **Email**。 +5. 输入您的电子邮件地址。 +6. 点击 **Test Connection**。 + + - 如果测试成功,将显示 **Save** 按钮。 + - 如果测试失败,将显示错误消息。请按照消息提示排除问题,然后重试连接。 + +7. 点击 **Save** 完成订阅。 + +另外,您也可以在集群的 [**Alert**](/tidb-cloud/monitor-built-in-alerting.md#view-alerts) 页面右上角点击 **Subscribe**。您将被引导至 **Alert Subscriber** 页面。 + +如果告警条件保持不变,告警将每三小时发送一次电子邮件通知。 + +## 取消告警通知订阅 + +如果您不再希望接收项目中集群的告警通知,请按照以下步骤操作: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的下拉框切换到目标项目。 +2. 在左侧导航栏中,点击 **Project Settings** > **Alert Subscription**。 +3. 在 **Alert Subscription** 页面,找到要删除的目标订阅者所在行,然后点击 **...** > **Unsubscribe**。 +4. 点击 **Unsubscribe** 确认取消订阅。 diff --git a/tidb-cloud/monitor-alert-slack.md b/tidb-cloud/monitor-alert-slack.md new file mode 100644 index 000000000000..3bb3247861e4 --- /dev/null +++ b/tidb-cloud/monitor-alert-slack.md @@ -0,0 +1,65 @@ +--- +title: 通过 Slack 订阅 +summary: 了解如何通过 Slack 获取告警通知来监控 TiDB 集群。 +--- + +# 通过 Slack 订阅 + +TiDB Cloud 为您提供了一种通过 [Slack](https://slack.com/)、[电子邮件](/tidb-cloud/monitor-alert-email.md)和 [Zoom](/tidb-cloud/monitor-alert-zoom.md) 订阅告警通知的简便方法。本文档介绍如何通过 Slack 订阅告警通知。 + +以下截图显示了两个示例告警。 + +![TiDB Cloud 在 Slack 中的告警](/media/tidb-cloud/tidb-cloud-alert-subscription.png) + +> **注意:** +> +> 目前,告警订阅仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +## 前提条件 + +- 通过 Slack 订阅的功能仅适用于订阅了**企业版**或**高级版**支持计划的组织。 + +- 要订阅 TiDB Cloud 的告警通知,您必须拥有 TiDB Cloud 中组织的 `Organization Owner` 访问权限或目标项目的 `Project Owner` 访问权限。 + +## 订阅告警通知 + +### 步骤 1. 生成 Slack webhook URL + +1. 如果您还没有 Slack 应用,请[创建一个 Slack 应用](https://api.slack.com/apps/new)。点击**创建新应用**,然后选择**从头开始**。输入名称,选择要与应用关联的工作区,然后点击**创建应用**。 +2. 转到应用的设置页面。您可以通过[应用管理仪表板](https://api.slack.com/apps)加载其设置。 +3. 点击 **Incoming Webhooks** 标签,然后将 **Activate Incoming Webhooks** 切换为 **ON**。 +4. 点击 **Add New Webhook to Workspace**。 +5. 选择您想要接收告警通知的频道,然后选择**授权**。如果您需要将传入的 webhook 添加到私有频道,您必须先加入该频道。 + +您可以在 **Webhook URLs for Your Workspace** 部分看到一个新条目,格式如下:`https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX`。 + +### 步骤 2. 从 TiDB Cloud 订阅 + +> **提示:** +> +> 告警订阅适用于当前项目中的所有告警。如果您在项目中有多个集群,只需订阅一次即可。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **告警订阅**。 +3. 在**告警订阅**页面,点击右上角的**添加订阅者**。 +4. 从**订阅者类型**下拉列表中选择 **Slack**。 +5. 在**名称**字段中输入名称,在 **URL** 字段中输入您的 Slack webhook URL。 +6. 点击**测试连接**。 + + - 如果测试成功,将显示**保存**按钮。 + - 如果测试失败,将显示错误消息。按照消息提示排除问题并重试连接。 + +7. 点击**保存**完成订阅。 + +或者,您也可以点击集群**告警**页面右上角的**订阅**。您将被引导至**告警订阅者**页面。 + +如果告警条件保持不变,告警会每三小时发送一次通知。 + +## 取消订阅告警通知 + +如果您不再想接收项目中集群的告警通知,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **告警订阅**。 +3. 在**告警订阅**页面,找到要删除的目标订阅者所在行,然后点击 **...** > **取消订阅**。 +4. 点击**取消订阅**确认取消订阅。 diff --git a/tidb-cloud/monitor-alert-zoom.md b/tidb-cloud/monitor-alert-zoom.md new file mode 100644 index 000000000000..ee889206fe73 --- /dev/null +++ b/tidb-cloud/monitor-alert-zoom.md @@ -0,0 +1,75 @@ +--- +title: 通过 Zoom 订阅 +summary: 了解如何通过 Zoom 获取告警通知来监控您的 TiDB 集群。 +--- + +# 通过 Zoom 订阅 + +TiDB Cloud 为您提供了一种通过 [Zoom](https://www.zoom.com/)、[Slack](/tidb-cloud/monitor-alert-slack.md) 和[电子邮件](/tidb-cloud/monitor-alert-email.md)订阅告警通知的简便方法。本文介绍如何通过 Zoom 订阅告警通知。 + +> **注意:** +> +> 目前,告警订阅仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +## 前提条件 + +- 通过 Zoom 订阅功能仅适用于订阅了**企业版**或**高级版**支持计划的组织。 + +- 要订阅 TiDB Cloud 的告警通知,您必须在 TiDB Cloud 中拥有组织的 `Organization Owner` 访问权限或目标项目的 `Project Owner` 访问权限。 + +- 要在 Zoom 中添加和配置传入 Webhook 聊天机器人,您需要在 Zoom 账户上拥有管理员权限。 + +## 订阅告警通知 + +### 步骤 1. 添加 Zoom 传入 Webhook 应用 + +1. 以账户管理员身份登录 [Zoom App Marketplace](https://marketplace.zoom.us/)。 +2. 在 Zoom App Marketplace 中转到 [Incoming Webhook App](https://marketplace.zoom.us/apps/eH_dLuquRd-VYcOsNGy-hQ) 页面,然后点击**添加**以添加此应用。如果应用未预先批准,请联系您的 Zoom 管理员为您的账户批准此应用。更多信息,请参见[批准应用和管理应用请求](https://support.zoom.us/hc/en-us/articles/360027829671)。 +3. 确认应用所需的权限,然后点击**授权**以添加传入 Webhook 应用。 + +### 步骤 2. 生成 Zoom webhook URL + +1. 登录 Zoom 桌面客户端。 +2. 点击**团队聊天**标签。 +3. 在**应用**下,找到并选择**传入 Webhook**,或从上方选择您想要接收消息的聊天频道。 +4. 输入以下命令以创建新连接。您需要将 `${connectionName}` 替换为您想要的连接名称,例如 `tidbcloud-alerts`: + + ```shell + /inc connect ${connectionName} + ``` + +5. 命令将返回以下详细信息: + + - **端点**。它将提供格式为 `https://integrations.zoom.us/chat/webhooks/incomingwebhook/XXXXXXXXXXXXXXXXXXXXXXXX` 的 webhook URL。 + - **验证令牌** + +### 步骤 3. 从 TiDB Cloud 订阅 + +> **提示:** +> +> 告警订阅适用于当前项目中的所有告警。如果您在项目中有多个集群,您只需订阅一次。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到您的目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **告警订阅**。 +3. 在**告警订阅**页面上,点击右上角的**添加订阅者**。 +4. 从**订阅者类型**下拉列表中选择 **Zoom**。 +5. 在**名称**字段中输入名称,在 **URL** 字段中输入您的 Zoom webhook URL,在**令牌**字段中输入验证令牌。 +6. 点击**测试连接**。 + + - 如果测试成功,将显示**保存**按钮。 + - 如果测试失败,将显示错误消息。按照消息进行故障排除并重试连接。 + +7. 点击**保存**完成订阅。 + +或者,您也可以点击集群**告警**页面右上角的**订阅**。您将被引导至**告警订阅者**页面。 + +如果告警条件保持不变,告警每三小时发送一次通知。 + +## 取消订阅告警通知 + +如果您不再想接收项目中集群的告警通知,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到您的目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **告警订阅**。 +3. 在**告警订阅**页面上,找到要删除的目标订阅者所在的行,然后点击 **...** > **取消订阅**。 +4. 点击**取消订阅**确认取消订阅。 diff --git a/tidb-cloud/monitor-built-in-alerting.md b/tidb-cloud/monitor-built-in-alerting.md new file mode 100644 index 000000000000..e6c54d9af95a --- /dev/null +++ b/tidb-cloud/monitor-built-in-alerting.md @@ -0,0 +1,94 @@ +--- +title: TiDB Cloud 内置告警 +summary: 了解如何通过获取 TiDB Cloud 的告警通知来监控你的 TiDB 集群。 +--- + +# TiDB Cloud 内置告警 + +TiDB Cloud 为你提供了一种简单的方式来查看告警、编辑告警规则和订阅告警通知。 + +本文介绍如何执行这些操作,并提供 TiDB Cloud 内置告警条件供你参考。 + +> **注意:** +> +> 目前,告警功能仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +## 查看告警 + +在 TiDB Cloud 中,你可以在**告警**页面查看活动和已关闭的告警。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称。此时会显示集群概览页面。 +3. 在左侧导航栏中点击**告警**。 +4. **告警**页面默认显示活动告警。你可以查看每个活动告警的信息,如告警名称、触发时间和持续时间。 +5. 如果你也想查看已关闭的告警,只需点击**状态**下拉列表并选择**已关闭**或**全部**。 + +## 编辑告警规则 + +在 TiDB Cloud 中,你可以通过禁用或启用告警或更新告警阈值来编辑告警规则。 + +1. 在**告警**页面,点击**编辑规则**。 +2. 根据需要禁用或启用告警规则。 +3. 点击**编辑**来更新告警规则的阈值。 + + > **提示:** + > + > 目前,TiDB Cloud 提供有限的告警规则编辑功能。某些告警规则不支持编辑。如果你想配置不同的触发条件或频率,或让告警自动触发下游服务(如 [PagerDuty](https://www.pagerduty.com/docs/guides/datadog-integration-guide/))中的操作,请考虑使用[第三方监控和告警集成](/tidb-cloud/third-party-monitoring-integrations.md)。 + +## 订阅告警通知 + +在 TiDB Cloud 中,你可以通过以下方法之一订阅告警通知: + +- [电子邮件](/tidb-cloud/monitor-alert-email.md) +- [Slack](/tidb-cloud/monitor-alert-slack.md) +- [Zoom](/tidb-cloud/monitor-alert-zoom.md) + +## TiDB Cloud 内置告警条件 + +下表提供了 TiDB Cloud 内置告警条件和相应的建议操作。 + +> **注意:** +> +> - 虽然这些告警条件不一定意味着存在问题,但它们通常是新出现问题的早期预警指标。因此,建议采取建议的操作。 +> - 你可以在 TiDB Cloud 控制台上编辑告警的阈值。 +> - 某些告警规则默认是禁用的。你可以根据需要启用它们。 + +### 资源使用告警 + +| 条件 | 建议操作 | +|:--- |:--- | +| 集群中 TiDB 节点的总内存使用率超过 70% 持续 10 分钟 | 考虑增加 TiDB 的节点数量或节点大小,以减少当前工作负载的内存使用百分比。| +| 集群中 TiKV 节点的总内存使用率超过 70% 持续 10 分钟 | 考虑增加 TiKV 的节点数量或节点大小,以减少当前工作负载的内存使用百分比。 | +| 集群中 TiFlash 节点的总内存使用率超过 70% 持续 10 分钟 | 考虑增加 TiFlash 的节点数量或节点大小,以减少当前工作负载的内存使用百分比。 | +| TiDB 节点的总 CPU 使用率超过 80% 持续 10 分钟 | 考虑增加 TiDB 的节点数量或节点大小,以减少当前工作负载的 CPU 使用百分比。| +| TiKV 节点的总 CPU 使用率超过 80% 持续 10 分钟 | 考虑增加 TiKV 的节点数量或节点大小,以减少当前工作负载的 CPU 使用百分比。 | +| TiFlash 节点的总 CPU 使用率超过 80% 持续 10 分钟 | 考虑增加 TiFlash 的节点数量或节点大小,以减少当前工作负载的 CPU 使用百分比。 | +| TiKV 存储使用率超过 80% | 考虑增加 TiKV 的节点数量或节点存储大小以增加存储容量。 | +| TiFlash 存储使用率超过 80% | 考虑增加 TiFlash 的节点数量或节点存储大小以增加存储容量。 | +| TiDB 节点中的最大内存使用率超过 70% 持续 10 分钟 | 考虑检查集群中是否存在任何[热点问题](/tidb-cloud/tidb-cloud-sql-tuning-overview.md#hotspot-issues),或增加 TiDB 的节点数量或节点大小,以减少当前工作负载的内存使用百分比。 | +| TiKV 节点中的最大内存使用率超过 70% 持续 10 分钟 | 考虑检查集群中是否存在任何[热点问题](/tidb-cloud/tidb-cloud-sql-tuning-overview.md#hotspot-issues),或增加 TiKV 的节点数量或节点大小,以减少当前工作负载的内存使用百分比。 | +| TiDB 节点中的最大 CPU 使用率超过 80% 持续 10 分钟 | 考虑检查集群中是否存在任何[热点问题](/tidb-cloud/tidb-cloud-sql-tuning-overview.md#hotspot-issues),或增加 TiDB 的节点数量或节点大小,以减少当前工作负载的 CPU 使用百分比。 | +| TiKV 节点中的最大 CPU 使用率超过 80% 持续 10 分钟 | 考虑检查集群中是否存在任何[热点问题](/tidb-cloud/tidb-cloud-sql-tuning-overview.md#hotspot-issues),或增加 TiKV 的节点数量或节点大小,以减少当前工作负载的 CPU 使用百分比。 | + +### 数据迁移告警 + +| 条件 | 建议操作 | +|:--- |:--- | +| 数据导出期间数据迁移任务遇到错误 | 检查错误并参阅[故障排除数据迁移](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#migration-errors-and-solutions)获取帮助。 | +| 数据导入期间数据迁移任务遇到错误 | 检查错误并参阅[故障排除数据迁移](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#migration-errors-and-solutions)获取帮助。 | +| 增量迁移期间数据迁移任务遇到错误 | 检查错误并参阅[故障排除数据迁移](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#migration-errors-and-solutions)获取帮助。 | +| 增量迁移期间数据迁移任务已暂停超过 6 小时 | 数据增量迁移期间数据迁移任务已暂停超过 6 小时。上游数据库中的 binlog 可能已被清除(取决于你的数据库 binlog 清除策略)并可能导致增量迁移失败。参阅[故障排除数据迁移](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#migration-errors-and-solutions)获取帮助。 | +| 复制延迟大于 10 分钟且持续增加超过 20 分钟 | 参阅[故障排除数据迁移](/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md#migration-errors-and-solutions)获取帮助。 | + +### Changefeed 告警 + +| 条件 | 建议操作 | +|:--------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Changefeed 延迟超过 600 秒。 | 在 TiDB Cloud 控制台的 **Changefeed** 页面和 **Changefeed 详情**页面上检查 changefeed 状态,你可以在那里找到一些错误消息来帮助诊断此问题。
可能触发此告警的原因包括:
  • 上游的整体流量增加,导致现有的 changefeed 规格不足以处理。如果流量增加是暂时的,changefeed 延迟会在流量恢复正常后自动恢复。如果流量增加是持续的,你需要扩容 changefeed。
  • 下游或网络异常。在这种情况下,首先解决这种异常。
  • 如果下游是 RDS,表缺少索引可能会导致写入性能低和延迟高。在这种情况下,你需要在上游或下游添加必要的索引。
如果问题无法从你这边解决,你可以联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求进一步帮助。 | +| Changefeed 状态为 `FAILED`。 | 在 TiDB Cloud 控制台的 **Changefeed** 页面和 **Changefeed 详情**页面上检查 changefeed 状态,你可以在那里找到一些错误消息来帮助诊断此问题。
如果问题无法从你这边解决,你可以联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求进一步帮助。 | +| Changefeed 状态为 `WARNING`。 | 在 TiDB Cloud 控制台的 **Changefeed** 页面和 **Changefeed 详情**页面上检查 changefeed 状态,你可以在那里找到一些错误消息来帮助诊断此问题。
如果问题无法从你这边解决,你可以联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求进一步帮助。 | diff --git a/tidb-cloud/monitor-datadog-integration.md b/tidb-cloud/monitor-datadog-integration.md new file mode 100644 index 000000000000..f9c7e85aa3b6 --- /dev/null +++ b/tidb-cloud/monitor-datadog-integration.md @@ -0,0 +1,70 @@ +--- +title: 将 TiDB Cloud 与 Datadog 集成(Beta) +summary: 了解如何通过 Datadog 集成监控 TiDB 集群。 +--- + +# 将 TiDB Cloud 与 Datadog 集成(Beta) + +TiDB Cloud 支持 Datadog 集成(beta)。您可以配置 TiDB Cloud 将 TiDB 集群的指标数据发送到 [Datadog](https://www.datadoghq.com/)。之后,您可以直接在 Datadog 仪表板中查看这些指标。 + +## 前提条件 + +- 要将 TiDB Cloud 与 Datadog 集成,您必须拥有 Datadog 账户和 [Datadog API 密钥](https://app.datadoghq.com/organization-settings/api-keys)。首次创建 Datadog 账户时,Datadog 会授予您一个 API 密钥。 + + 如果您没有 Datadog 账户,请在 [https://app.datadoghq.com/signup](https://app.datadoghq.com/signup) 注册。 + +- 要编辑 TiDB Cloud 的第三方集成设置,您必须在 TiDB Cloud 中拥有组织的 `Organization Owner` 访问权限或目标项目的 `Project Member` 访问权限。 + +## 限制 + +- 您不能在 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群中使用 Datadog 集成。 + +- 当集群状态为 **CREATING**、**RESTORING**、**PAUSED** 或 **RESUMING** 时,Datadog 集成不可用。 + +## 步骤 + +### 步骤 1. 与您的 Datadog API 密钥集成 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **集成**。 +3. 在**集成**页面上,点击 **Datadog 集成(BETA)**。 +4. 输入您的 Datadog API 密钥并选择 Datadog 的站点。 +5. 点击**测试集成**。 + + - 如果测试成功,将显示**确认**按钮。 + - 如果测试失败,将显示错误消息。按照消息进行故障排除并重试集成。 + +6. 点击**确认**以完成集成。 + +### 步骤 2. 在 Datadog 中安装 TiDB Cloud 集成 + +1. 登录 [Datadog](https://app.datadoghq.com)。 +2. 在 Datadog 中转到 **TiDB Cloud 集成**页面([https://app.datadoghq.com/account/settings#integrations/tidb-cloud](https://app.datadoghq.com/account/settings#integrations/tidb-cloud))。 +3. 在**配置**标签中,点击**安装集成**。[**TiDBCloud 集群概览**](https://app.datadoghq.com/dash/integration/30586/tidbcloud-cluster-overview)仪表板将显示在您的[**仪表板列表**](https://app.datadoghq.com/dashboard/lists)中。 + +## 预构建仪表板 + +点击集成中 **Datadog** 卡片的**仪表板**链接。您可以看到 TiDB 集群的预构建仪表板。 + +## Datadog 可用的指标 + +Datadog 跟踪 TiDB 集群的以下指标数据。 + +| 指标名称 | 指标类型 | 标签 | 描述 | +| :------------| :---------- | :------| :----------------------------------------------------- | +| tidb_cloud.db_database_time| gauge | sql_type: Select\|Insert\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | TiDB 中运行的所有 SQL 语句每秒消耗的总时间,包括所有进程的 CPU 时间和非空闲等待时间。 | +| tidb_cloud.db_query_per_second| gauge | type: Select\|Insert\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | 所有 TiDB 实例每秒执行的 SQL 语句数量,按 SELECT、INSERT、UPDATE 和其他类型的语句计数。 | +| tidb_cloud.db_average_query_duration| gauge | sql_type: Select\|Insert\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | 从客户端的网络请求发送到 TiDB 到 TiDB 执行后将请求返回给客户端的时间间隔。 | +| tidb_cloud.db_failed_queries| gauge | type: executor:xxxx\|parser:xxxx\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | 根据每个 TiDB 实例每秒发生的 SQL 执行错误(如语法错误和主键冲突)统计的错误类型。 | +| tidb_cloud.db_total_connection| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | TiDB 服务器中的当前连接数。 | +| tidb_cloud.db_active_connections| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | 活动连接数。 | +| tidb_cloud.db_disconnections| gauge | result: ok\|error\|undetermined
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | 断开连接的客户端数量。 | +| tidb_cloud.db_command_per_second| gauge | type: Query\|StmtPrepare\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | TiDB 每秒处理的命令数,根据命令执行结果的成功或失败进行分类。 | +| tidb_cloud.db_queries_using_plan_cache_ops| gauge | cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | 每秒使用[执行计划缓存](/sql-prepared-plan-cache.md)的查询统计。执行计划缓存仅支持预处理语句命令。 | +| tidb_cloud.db_transaction_per_second| gauge | txn_mode: pessimistic\|optimistic
type: abort\|commit\|...
cluster_name: ``
instance: tidb-0\|tidb-1…
component: `tidb` | 每秒执行的事务数。 | +| tidb_cloud.node_storage_used_bytes | gauge | cluster_name: ``
instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…
component: tikv\|tiflash | TiKV/TiFlash 节点的磁盘使用量,以字节为单位。 | +| tidb_cloud.node_storage_capacity_bytes | gauge | cluster_name: ``
instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…
component: tikv\|tiflash | TiKV/TiFlash 节点的磁盘容量,以字节为单位。 | +| tidb_cloud.node_cpu_seconds_total | count | cluster_name: ``
instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…
component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的 CPU 使用率。 | +| tidb_cloud.node_cpu_capacity_cores | gauge | cluster_name: ``
instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…
component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的 CPU 核心限制。 | +| tidb_cloud.node_memory_used_bytes | gauge | cluster_name: ``
instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…
component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的已用内存,以字节为单位。 | +| tidb_cloud.node_memory_capacity_bytes | gauge | cluster_name: ``
instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…
component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的内存容量,以字节为单位。 | diff --git a/tidb-cloud/monitor-new-relic-integration.md b/tidb-cloud/monitor-new-relic-integration.md new file mode 100644 index 000000000000..d48be418d933 --- /dev/null +++ b/tidb-cloud/monitor-new-relic-integration.md @@ -0,0 +1,68 @@ +--- +title: 将 TiDB Cloud 与 New Relic 集成(Beta) +summary: 了解如何使用 New Relic 集成监控您的 TiDB 集群。 +--- + +# 将 TiDB Cloud 与 New Relic 集成(Beta) + +TiDB Cloud 支持 New Relic 集成(beta)。您可以配置 TiDB Cloud 将 TiDB 集群的指标数据发送到 [New Relic](https://newrelic.com/)。之后,您可以直接在 New Relic 仪表板中查看这些指标。 + +## 前提条件 + +- 要将 TiDB Cloud 与 New Relic 集成,您必须拥有 New Relic 账号和 [New Relic API 密钥](https://one.newrelic.com/admin-portal/api-keys/home?)。首次创建 New Relic 账号时,New Relic 会授予您一个 API 密钥。 + + 如果您没有 New Relic 账号,请在[此处](https://newrelic.com/signup)注册。 + +- 要编辑 TiDB Cloud 的第三方集成设置,您必须拥有组织的**组织所有者**访问权限或目标项目的**项目成员**访问权限。 + +## 限制 + +您不能在 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)中使用 New Relic 集成。 + +## 步骤 + +### 步骤 1. 与您的 New Relic API 密钥集成 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **集成**。 +3. 在**集成**页面上,点击 **New Relic 集成(BETA)**。 +4. 输入您的 New Relic API 密钥并选择 New Relic 的站点。 +5. 点击**测试集成**。 + + - 如果测试成功,将显示**确认**按钮。 + - 如果测试失败,将显示错误消息。按照消息进行故障排除并重试集成。 + +6. 点击**确认**完成集成。 + +### 步骤 2. 在 New Relic 中添加 TiDB Cloud 仪表板 + +1. 登录 [New Relic](https://one.newrelic.com/)。 +2. 点击**添加数据**,搜索 `TiDB Cloud`,然后转到 **TiDB Cloud 监控**页面。或者,您可以点击[链接](https://one.newrelic.com/marketplace?state=79bf274b-0c01-7960-c85c-3046ca96568e)直接访问该页面。 +3. 选择您的账号 ID 并在 New Relic 中创建仪表板。 + +## 预构建仪表板 + +点击集成中 **New Relic** 卡片中的**仪表板**链接。您可以看到 TiDB 集群的预构建仪表板。 + +## New Relic 可用的指标 + +New Relic 跟踪您的 TiDB 集群的以下指标数据。 + +| 指标名称 | 指标类型 | 标签 | 描述 | +| :------------| :---------- | :------| :----------------------------------------------------- | +| tidb_cloud.db_database_time| gauge | sql_type: Select\|Insert\|...

cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | TiDB 中运行的所有 SQL 语句每秒消耗的总时间,包括所有进程的 CPU 时间和非空闲等待时间。 | +| tidb_cloud.db_query_per_second| gauge | type: Select\|Insert\|...

cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | 所有 TiDB 实例每秒执行的 SQL 语句数量,按 `SELECT`、`INSERT`、`UPDATE` 等类型的语句计数。 | +| tidb_cloud.db_average_query_duration| gauge | sql_type: Select\|Insert\|...

cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | 从客户端的网络请求发送到 TiDB 到 TiDB 执行后将请求返回给客户端的时间间隔。 | +| tidb_cloud.db_failed_queries| gauge | type: executor:xxxx\|parser:xxxx\|...

cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | 根据每个 TiDB 实例每秒发生的 SQL 执行错误(如语法错误和主键冲突)统计的错误类型。 | +| tidb_cloud.db_total_connection| gauge | cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | TiDB 服务器中的当前连接数。 | +| tidb_cloud.db_active_connections| gauge | cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | 活动连接数。 | +| tidb_cloud.db_disconnections| gauge | result: ok\|error\|undetermined

cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | 断开连接的客户端数量。 | +| tidb_cloud.db_command_per_second| gauge | type: Query\|StmtPrepare\|...

cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | TiDB 每秒处理的命令数量,根据命令执行结果的成功或失败进行分类。 | +| tidb_cloud.db_queries_using_plan_cache_ops| gauge | cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | 每秒使用[执行计划缓存](/sql-prepared-plan-cache.md)的查询统计。执行计划缓存仅支持预处理语句命令。 | +| tidb_cloud.db_transaction_per_second| gauge | txn_mode: pessimistic\|optimistic

type: abort\|commit\|...

cluster_name: ``

instance: tidb-0\|tidb-1…

component: `tidb` | 每秒执行的事务数。 | +| tidb_cloud.node_storage_used_bytes | gauge | cluster_name: ``

instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…

component: tikv\|tiflash | TiKV/TiFlash 节点的磁盘使用量,以字节为单位。 | +| tidb_cloud.node_storage_capacity_bytes | gauge | cluster_name: ``

instance: tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…

component: tikv\|tiflash | TiKV/TiFlash 节点的磁盘容量,以字节为单位。 | +| tidb_cloud.node_cpu_seconds_total | count | cluster_name: ``

instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…

component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的 CPU 使用率。 | +| tidb_cloud.node_cpu_capacity_cores | gauge | cluster_name: ``

instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…

component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的 CPU 核心限制。 | +| tidb_cloud.node_memory_used_bytes | gauge | cluster_name: ``

instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…

component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的已用内存,以字节为单位。 | +| tidb_cloud.node_memory_capacity_bytes | gauge | cluster_name: ``

instance: tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…

component: tidb\|tikv\|tiflash | TiDB/TiKV/TiFlash 节点的内存容量,以字节为单位。 | diff --git a/tidb-cloud/monitor-prometheus-and-grafana-integration.md b/tidb-cloud/monitor-prometheus-and-grafana-integration.md new file mode 100644 index 000000000000..9622c4f78ab7 --- /dev/null +++ b/tidb-cloud/monitor-prometheus-and-grafana-integration.md @@ -0,0 +1,111 @@ +--- +title: 将 TiDB Cloud 与 Prometheus 和 Grafana 集成(Beta) +summary: 了解如何通过 Prometheus 和 Grafana 集成监控你的 TiDB 集群。 +--- + +# 将 TiDB Cloud 与 Prometheus 和 Grafana 集成(Beta) + +TiDB Cloud 提供了一个 [Prometheus](https://prometheus.io/) API 端点(beta)。如果你有 Prometheus 服务,可以轻松地从该端点监控 TiDB Cloud 的关键指标。 + +本文档描述如何配置你的 Prometheus 服务以从 TiDB Cloud 端点读取关键指标,以及如何使用 [Grafana](https://grafana.com/) 查看这些指标。 + +## 前提条件 + +- 要将 TiDB Cloud 与 Prometheus 集成,你必须有一个自托管或托管的 Prometheus 服务。 + +- 要编辑 TiDB Cloud 的第三方集成设置,你必须在 TiDB Cloud 中拥有组织的 `Organization Owner` 访问权限或目标项目的 `Project Member` 访问权限。 + +## 限制 + +- 你不能在 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群中使用 Prometheus 和 Grafana 集成。 + +- 当集群状态为 **CREATING**、**RESTORING**、**PAUSED** 或 **RESUMING** 时,Prometheus 和 Grafana 集成不可用。 + +## 步骤 + +### 步骤 1. 获取 Prometheus 的 scrape_config 文件 + +在配置 Prometheus 服务以读取 TiDB Cloud 的指标之前,你需要先在 TiDB Cloud 中生成一个 `scrape_config` YAML 文件。`scrape_config` 文件包含一个唯一的持有者令牌,允许 Prometheus 服务监控当前项目中的任何数据库集群。 + +要获取 Prometheus 的 `scrape_config` 文件,请执行以下操作: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击 **Project Settings** > **Integrations**。 +3. 在 **Integrations** 页面,点击 **Integration to Prometheus (BETA)**。 +4. 点击 **Add File** 为当前项目生成并显示 scrape_config 文件。 + +5. 复制 `scrape_config` 文件内容以供后续使用。 + + > **注意:** + > + > 出于安全考虑,TiDB Cloud 只会显示一次新生成的 `scrape_config` 文件。确保在关闭文件窗口之前复制内容。如果忘记复制,你需要在 TiDB Cloud 中删除 `scrape_config` 文件并生成一个新文件。要删除 `scrape_config` 文件,选择该文件,点击 **...**,然后点击 **Delete**。 + +### 步骤 2. 与 Prometheus 集成 + +1. 在 Prometheus 服务指定的监控目录中,找到 Prometheus 配置文件。 + + 例如,`/etc/prometheus/prometheus.yml`。 + +2. 在 Prometheus 配置文件中,找到 `scrape_configs` 部分,然后将从 TiDB Cloud 获取的 `scrape_config` 文件内容复制到该部分。 + +3. 在你的 Prometheus 服务中,检查 **Status** > **Targets** 以确认新的 `scrape_config` 文件已被读取。如果没有,你可能需要重启 Prometheus 服务。 + +### 步骤 3. 使用 Grafana GUI 仪表板可视化指标 + +在你的 Prometheus 服务从 TiDB Cloud 读取指标后,你可以按照以下步骤使用 Grafana GUI 仪表板来可视化指标: + +1. 在[这里](https://github.com/pingcap/docs/blob/master/tidb-cloud/monitor-prometheus-and-grafana-integration-grafana-dashboard-UI.json)下载 TiDB Cloud 的 Grafana 仪表板 JSON。 + +2. [将此 JSON 导入到你自己的 Grafana GUI](https://grafana.com/docs/grafana/v8.5/dashboards/export-import/#import-dashboard) 以可视化指标。 + + > **注意:** + > + > 如果你已经在使用 Prometheus 和 Grafana 监控 TiDB Cloud,并想要整合新可用的指标,建议你创建一个新的仪表板,而不是直接更新现有仪表板的 JSON。 + +3. (可选)根据需要自定义仪表板,例如添加或删除面板、更改数据源和修改显示选项。 + +有关如何使用 Grafana 的更多信息,请参见 [Grafana 文档](https://grafana.com/docs/grafana/latest/getting-started/getting-started-prometheus/)。 + +## 轮换 scrape_config 的最佳实践 + +为了提高数据安全性,定期轮换 `scrape_config` 文件持有者令牌是一般的最佳实践。 + +1. 按照[步骤 1](#步骤-1-获取-prometheus-的-scrape_config-文件)为 Prometheus 创建一个新的 `scrape_config` 文件。 +2. 将新文件的内容添加到你的 Prometheus 配置文件中。 +3. 一旦确认你的 Prometheus 服务仍然能够从 TiDB Cloud 读取数据,从你的 Prometheus 配置文件中删除旧的 `scrape_config` 文件内容。 +4. 在你项目的 **Integrations** 页面上,删除相应的旧 `scrape_config` 文件,以阻止其他人使用它从 TiDB Cloud Prometheus 端点读取数据。 + +## Prometheus 可用的指标 + +Prometheus 跟踪你的 TiDB 集群的以下指标数据。 + +| 指标名称 | 指标类型 | 标签 | 描述 | +|:--- |:--- |:--- |:--- | +| tidbcloud_db_queries_total| count | sql_type: `Select\|Insert\|...`
cluster_name: ``
instance: `tidb-0\|tidb-1…`
component: `tidb` | 执行的语句总数 | +| tidbcloud_db_failed_queries_total | count | type: `planner:xxx\|executor:2345\|...`
cluster_name: ``
instance: `tidb-0\|tidb-1…`
component: `tidb` | 执行错误的总数 | +| tidbcloud_db_connections | gauge | cluster_name: ``
instance: `tidb-0\|tidb-1…`
component: `tidb` | TiDB 服务器中的当前连接数 | +| tidbcloud_db_query_duration_seconds | histogram | sql_type: `Select\|Insert\|...`
cluster_name: ``
instance: `tidb-0\|tidb-1…`
component: `tidb` | 语句的持续时间直方图 | +| tidbcloud_changefeed_latency | gauge | changefeed_id | 变更数据捕获上游和下游之间的数据复制延迟 | +| tidbcloud_changefeed_checkpoint_ts | gauge | changefeed_id | 变更数据捕获的检查点时间戳,表示成功写入下游的最大 TSO(时间戳预言机) | +| tidbcloud_changefeed_replica_rows | gauge | changefeed_id | 变更数据捕获每秒写入下游的复制行数 | +| tidbcloud_node_storage_used_bytes | gauge | cluster_name: ``
instance: `tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…`
component: `tikv\|tiflash` | TiKV/TiFlash 节点的磁盘使用字节数 | +| tidbcloud_node_storage_capacity_bytes | gauge | cluster_name: ``
instance: `tikv-0\|tikv-1…\|tiflash-0\|tiflash-1…`
component: `tikv\|tiflash` | TiKV/TiFlash 节点的磁盘容量字节数 | +| tidbcloud_node_cpu_seconds_total | count | cluster_name: ``
instance: `tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…`
component: `tidb\|tikv\|tiflash` | TiDB/TiKV/TiFlash 节点的 CPU 使用率 | +| tidbcloud_node_cpu_capacity_cores | gauge | cluster_name: ``
instance: `tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…`
component: `tidb\|tikv\|tiflash` | TiDB/TiKV/TiFlash 节点的 CPU 限制核心数 | +| tidbcloud_node_memory_used_bytes | gauge | cluster_name: ``
instance: `tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…`
component: `tidb\|tikv\|tiflash` | TiDB/TiKV/TiFlash 节点的已用内存字节数 | +| tidbcloud_node_memory_capacity_bytes | gauge | cluster_name: ``
instance: `tidb-0\|tidb-1…\|tikv-0…\|tiflash-0…`
component: `tidb\|tikv\|tiflash` | TiDB/TiKV/TiFlash 节点的内存容量字节数 | +| tidbcloud_node_storage_available_bytes | gauge | instance: `tidb-0\|tidb-1\|...`
component: `tikv\|tiflash`
cluster_name: `` | TiKV/TiFlash 节点的可用磁盘空间字节数 | +| tidbcloud_disk_read_latency | histogram | instance: `tidb-0\|tidb-1\|...`
component: `tikv\|tiflash`
cluster_name: ``
`device`: `nvme.*\|dm.*` | 每个存储设备的读取延迟(秒) | +| tidbcloud_disk_write_latency | histogram | instance: `tidb-0\|tidb-1\|...`
component: `tikv\|tiflash`
cluster_name: ``
`device`: `nvme.*\|dm.*` | 每个存储设备的写入延迟(秒) | +| tidbcloud_kv_request_duration | histogram | instance: `tidb-0\|tidb-1\|...`
component: `tikv`
cluster_name: ``
`type`: `BatchGet\|Commit\|Prewrite\|...` | 按类型划分的 TiKV 请求持续时间(秒) | +| tidbcloud_component_uptime | histogram | instance: `tidb-0\|tidb-1\|...`
component: `tidb\|tikv\|pd\|...`
cluster_name: `` | TiDB 组件的运行时间(秒) | +| tidbcloud_ticdc_owner_resolved_ts_lag | gauge | changefeed_id: ``
cluster_name: `` | 变更数据捕获所有者的已解析时间戳延迟(秒) | +| tidbcloud_changefeed_status | gauge | changefeed_id: ``
cluster_name: `` | 变更数据捕获状态:
`-1`: 未知
`0`: 正常
`1`: 警告
`2`: 失败
`3`: 已停止
`4`: 已完成
`6`: 警告
`7`: 其他 | +| tidbcloud_resource_manager_resource_unit_read_request_unit | gauge | cluster_name: ``
resource_group: `` | 资源管理器消耗的读请求单位 | +| tidbcloud_resource_manager_resource_unit_write_request_unit | gauge | cluster_name: ``
resource_group: `` | 资源管理器消耗的写请求单位 | + +## 常见问题 + +- 为什么同一指标在同一时间在 Grafana 和 TiDB Cloud 控制台上显示的值不同? + + Grafana 和 TiDB Cloud 之间的聚合计算逻辑不同,因此显示的聚合值可能会有所不同。你可以调整 Grafana 中的 `mini step` 配置以获取更细粒度的指标值。 diff --git a/tidb-cloud/monitor-tidb-cluster.md b/tidb-cloud/monitor-tidb-cluster.md new file mode 100644 index 000000000000..f4c1822236c4 --- /dev/null +++ b/tidb-cloud/monitor-tidb-cluster.md @@ -0,0 +1,90 @@ +--- +title: 监控 TiDB 集群 +summary: 了解如何监控 TiDB 集群。 +--- + +# 监控 TiDB 集群 + +本文档介绍如何在 TiDB Cloud 上监控 TiDB 集群。 + +## 集群状态和节点状态 + +您可以在集群页面上查看每个运行中集群的当前状态。 + +### 集群状态 + +| 集群状态 | 描述 | +|:--|:--| +| **Available** | 集群运行正常且可用。 | +| **Creating** | 集群正在创建中。在创建过程中集群不可访问。 | +| **Importing** | 正在向集群导入数据。 | +| **Maintaining** | 集群正在维护中。 | +| **Modifying** | 集群正在修改中。 | +| **Unavailable** | 集群发生故障且 TiDB 无法恢复。 | +| **Pausing** | 集群正在暂停中。 | +| **Paused** | 集群已暂停。 | +| **Resuming** | 集群正在从暂停状态恢复。 | +| **Restoring** | 集群当前正在从备份中恢复。 | + +### TiDB 节点状态 + +> **注意:** +> +> TiDB 节点状态仅适用于 TiDB Cloud Dedicated 集群。 + +| TiDB 节点状态 | 描述 | +|:--|:--| +| **Available** | TiDB 节点运行正常且可用。 | +| **Creating** | TiDB 节点正在创建中。 | +| **Unavailable** | TiDB 节点不可用。 | +| **Deleting** | TiDB 节点正在删除中。 | + +### TiKV 节点状态 + +> **注意:** +> +> TiKV 节点状态仅适用于 TiDB Cloud Dedicated 集群。 + +| TiKV 节点状态 | 描述 | +|:--|:--| +| **Available** | TiKV 节点运行正常且可用。 | +| **Creating** | TiKV 节点正在创建中。 | +| **Unavailable** | TiKV 节点不可用。 | +| **Deleting** | TiKV 节点正在删除中。 | + +## 监控指标 + +在 TiDB Cloud 中,您可以从以下页面查看集群的常用指标: + +- **概览**页面 +- **指标**页面 + +### 概览页面 + +**概览**页面提供集群的常规指标。 + +要在集群概览页面查看指标,请执行以下步骤: + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称以进入其概览页面。 + + > **提示:** + > + > 您可以使用左上角的下拉框在组织、项目和集群之间切换。 + +2. 查看**核心指标**部分。 + +### 指标页面 + +**指标**页面提供集群的完整指标集。通过查看这些指标,您可以轻松识别性能问题并确定当前的数据库部署是否满足您的需求。 + +要在**指标**页面查看指标,请执行以下步骤: + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称以进入其概览页面。 + + > **提示:** + > + > 您可以使用左上角的下拉框在组织、项目和集群之间切换。 + +2. 在左侧导航栏中,点击**监控** > **指标**。 + +更多信息,请参见 [TiDB Cloud 内置指标](/tidb-cloud/built-in-monitoring.md)。 diff --git a/tidb-cloud/monitoring-concepts.md b/tidb-cloud/monitoring-concepts.md new file mode 100644 index 000000000000..427012c78484 --- /dev/null +++ b/tidb-cloud/monitoring-concepts.md @@ -0,0 +1,48 @@ +--- +title: 监控 +summary: 了解 TiDB Cloud 的监控概念。 +--- + +# 监控 + +TiDB Cloud 的监控功能提供了工具和集成,使你能够监督集群性能、跟踪活动并及时响应问题。 + +## 内置指标 + +内置指标是指 TiDB Cloud 在**指标**页面上收集和展示的一整套集群标准指标。通过这些指标,你可以轻松识别性能问题,并确定当前的数据库部署是否满足你的需求。 + +更多信息,请参阅 [TiDB Cloud 内置指标](/tidb-cloud/built-in-monitoring.md)。 + +## 内置告警 + +内置告警是指 TiDB Cloud 提供的集群告警机制,用于帮助你监控集群。目前,TiDB Cloud 提供以下三种类型的告警: + +- 资源使用告警 + +- 数据迁移告警 + +- Changefeed 告警 + +在 TiDB Cloud 控制台的告警页面,你可以查看集群的告警、编辑告警规则,以及订阅告警通知邮件。 + +更多信息,请参阅 [TiDB Cloud 内置告警](/tidb-cloud/monitor-built-in-alerting.md)。 + +## 集群事件 + +在 TiDB Cloud 中,事件表示 TiDB Cloud 集群的变更。TiDB Cloud 在集群级别记录历史事件,以帮助你跟踪集群活动。你可以在**事件**页面查看记录的事件,包括事件类型、状态、消息、触发时间和触发用户。 + +更多信息,请参阅 [TiDB Cloud 集群事件](/tidb-cloud/tidb-cloud-events.md)。 + +## 第三方指标集成(Beta) + +TiDB Cloud 允许你集成以下任何第三方指标服务,以接收 TiDB Cloud 告警并查看 TiDB 集群的性能指标。 + +- Datadog 集成 + +- Prometheus 和 Grafana 集成 + +- New Relic 集成 + +目前,这些第三方指标集成处于 beta 阶段。 + +更多信息,请参阅[第三方指标集成(Beta)](/tidb-cloud/third-party-monitoring-integrations.md)。 diff --git a/tidb-cloud/naming-conventions-for-data-import.md b/tidb-cloud/naming-conventions-for-data-import.md new file mode 100644 index 000000000000..47e018b90540 --- /dev/null +++ b/tidb-cloud/naming-conventions-for-data-import.md @@ -0,0 +1,125 @@ +--- +title: 数据导入的命名规范 +summary: 了解 CSV、Parquet、Aurora Snapshot 和 SQL 文件在数据导入过程中的命名规范。 +--- + +# 数据导入的命名规范 + +你可以将以下格式的文件导入到 TiDB Cloud:CSV、Parquet、Aurora Snapshot 和 SQL。为确保数据成功导入,你需要准备以下两类文件: + +- **模式文件**。准备数据库模式文件(可选)和表模式文件,两者都是 SQL 格式(`.sql`)。如果未提供表模式文件,你需要提前在目标数据库中手动创建相应的表。 +- **数据文件**。准备符合导入数据命名规范的数据文件。如果数据文件名称无法满足要求,建议使用[**文件模式**](#文件模式)执行导入任务。否则,导入任务将无法扫描到你想要导入的数据文件。 + +## 模式文件的命名规范 + +本节描述数据库和表模式文件的命名规范。对于以下所有类型的源文件(CSV、Parquet、Aurora Snapshot 和 SQL),模式文件的命名规范都是相同的。 + +模式文件的命名规范如下: + +- 数据库模式文件(可选):`${db_name}-schema-create.sql` +- 表模式文件:`${db_name}.${table_name}-schema.sql` + +以下是数据库模式文件的示例: + +- 名称:`import_db-schema-create.sql` +- 文件内容: + + ```sql + CREATE DATABASE import_db; + ``` + +以下是表模式文件的示例: + +- 名称:`import_db.test_table-schema.sql` +- 文件内容: + + ```sql + CREATE TABLE test_table ( + id INTEGER PRIMARY KEY, + val VARCHAR(255) + ); + ``` + +## 数据文件的命名规范 + +本节描述数据文件的命名规范。根据源文件的类型,数据文件的命名规范有所不同。 + +### CSV + +导入 CSV 文件时,数据文件的命名规范如下: + +`${db_name}.${table_name}${suffix}.csv.${compress}` + +`${suffix}` 是可选的,可以是以下格式之一,其中 *`xxx`* 可以是任何数字: + +- *`.xxx`*,例如 `.01` +- *`._xxx_xxx_xxx`*,例如 `._0_0_01` +- *`_xxx_xxx_xxx`*,例如 `_0_0_01` + +`${compress}` 是压缩格式,是可选的。TiDB Cloud 支持以下格式:`.gzip`、`.gz`、`.zstd`、`.zst` 和 `.snappy`。 + +例如,以下所有文件的目标数据库和表都是 `import_db` 和 `test_table`: + +- `import_db.test_table.csv` +- `import_db.test_table.01.csv` +- `import_db.test_table._0_0_01.csv` +- `import_db.test_table_0_0_01.csv` +- `import_db.test_table_0_0_01.csv.gz` + +> **注意:** +> +> Snappy 压缩文件必须是[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他变体的 Snappy 压缩。 + +### Parquet + +导入 Parquet 文件时,数据文件的命名规范如下: + +`${db_name}.${table_name}${suffix}.parquet`(`${suffix}` 是可选的) + +例如: + +- `import_db.test_table.parquet` +- `import_db.test_table.01.parquet` + +### Aurora Snapshot + +对于 Aurora Snapshot 文件,`${db_name}.${table_name}/` 文件夹中所有带有 `.parquet` 后缀的文件都符合命名规范。数据文件名可以包含由"a-z、0-9、-、_、."组成的任何前缀和后缀 ".parquet"。 + +例如: + +- `import_db.test_table/mydata.parquet` +- `import_db.test_table/part001/mydata.parquet` +- `import_db.test_table/part002/mydata-part002.parquet` + +### SQL + +导入 SQL 文件时,数据文件的命名规范如下: + +`${db_name}.${table_name}${suffix}.sql.${compress}` + +`${suffix}` 是可选的,可以是以下格式之一,其中 *`xxx`* 可以是任何数字: + +- *`.xxx`*,例如 `.01` +- *`._xxx_xxx_xxx`*,例如 `._0_0_01` +- *`_xxx_xxx_xxx`*,例如 `_0_0_01` + +`${compress}` 是压缩格式,是可选的。TiDB Cloud 支持以下格式:`.gzip`、`.gz`、`.zstd`、`.zst` 和 `.snappy`。 + +例如: + +- `import_db.test_table.sql` +- `import_db.test_table.01.sql` +- `import_db.test_table.01.sql.gz` + +如果 SQL 文件是通过默认配置的 TiDB Dumpling 导出的,则默认符合命名规范。 + +> **注意:** +> +> Snappy 压缩文件必须是[官方 Snappy 格式](https://github.com/google/snappy)。不支持其他变体的 Snappy 压缩。 + +## 文件模式 + +如果 CSV 或 Parquet 的源数据文件不符合命名规范,你可以使用文件模式功能建立源数据文件与目标表之间的名称映射关系。此功能不支持 Aurora Snapshot 和 SQL 数据文件。 + +- 对于 CSV 文件,请参阅[步骤 4. 将 CSV 文件导入到 TiDB Cloud](/tidb-cloud/import-csv-files.md#步骤-4-将-csv-文件导入到-tidb-cloud) 中的**高级设置** > **映射设置** +- 对于 Parquet 文件,请参阅[步骤 4. 将 Parquet 文件导入到 TiDB Cloud](/tidb-cloud/import-parquet-files.md#步骤-4-将-parquet-文件导入到-tidb-cloud) 中的**高级设置** > **映射设置** diff --git a/tidb-cloud/notification-2023-08-31-console-maintenance.md b/tidb-cloud/notification-2023-08-31-console-maintenance.md new file mode 100644 index 000000000000..7c3c05d1fbc2 --- /dev/null +++ b/tidb-cloud/notification-2023-08-31-console-maintenance.md @@ -0,0 +1,91 @@ +--- +title: 2023-08-31 TiDB Cloud 控制台维护通知 +summary: 了解 2023 年 8 月 31 日 TiDB Cloud 控制台维护的详细信息,如维护时间窗口、原因和影响。 +--- + +# [2023-08-31] TiDB Cloud 控制台维护通知 + +本通知描述了您需要了解的 2023 年 8 月 31 日 [TiDB Cloud 控制台](https://tidbcloud.com/)维护的详细信息。 + +## 维护时间窗口 + +- 日期:2023-08-31 +- 开始时间:8:00 (UTC+0) +- 结束时间:10:00 (UTC+0) +- 持续时间:约 2 小时 + +> **注意:** +> +> 目前,用户无法修改 TiDB Cloud 控制台的维护时间,因此您需要提前做好相应计划。 + +## 维护原因 + +我们正在升级 TiDB Cloud 控制台的元数据库服务,以提升性能和效率。这项改进旨在为所有用户提供更好的体验,这是我们持续提供高质量服务承诺的一部分。 + +## 影响 + +在维护时间窗口期间,您可能会遇到 TiDB Cloud 控制台 UI 和 API 中与创建和更新相关功能的间歇性中断。但是,您的 TiDB 集群将保持正常的数据读写操作,确保不会对您的在线业务产生不利影响。 + +### 受影响的 TiDB Cloud 控制台 UI 功能 + +- 集群级别 + - 集群管理 + - 创建集群 + - 删除集群 + - 扩展集群 + - 暂停或恢复集群 + - 更改集群密码 + - 更改集群流量过滤器 + - 导入 + - 创建导入任务 + - 数据迁移 + - 创建迁移任务 + - 变更数据捕获 + - 创建变更数据捕获任务 + - 备份 + - 创建手动备份任务 + - 自动备份任务 + - 恢复 + - 创建恢复任务 + - 数据库审计日志 + - 测试连接性 + - 添加或删除访问记录 + - 启用或禁用数据库审计日志 + - 重启数据库审计日志 +- 项目级别 + - 网络访问 + - 创建私有端点 + - 删除私有端点 + - 添加 VPC 对等连接 + - 删除 VPC 对等连接 + - 维护 + - 更改维护时间窗口 + - 延迟任务 + - 回收站 + - 删除集群 + - 删除备份 + - 恢复集群 + +### 受影响的 TiDB Cloud API 功能 + +- 集群管理 + - [CreateCluster](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/CreateCluster) + - [DeleteCluster](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/DeleteCluster) + - [UpdateCluster](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) + - [CreateAwsCmek](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/CreateAwsCmek) +- 备份 + - [CreateBackup](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Backup/operation/CreateBackup) + - [DeleteBackup](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Backup/operation/DeleteBackup) +- 恢复 + - [CreateRestoreTask](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Restore/operation/CreateRestoreTask) +- 导入 + - [CreateImportTask](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Import/operation/CreateImportTask) + - [UpdateImportTask](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Import/operation/UpdateImportTask) + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将恢复,为您提供更好的体验。 + +## 获取支持 + +如果您有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为您解答疑虑并提供必要的指导。 diff --git a/tidb-cloud/notification-2023-09-26-console-maintenance.md b/tidb-cloud/notification-2023-09-26-console-maintenance.md new file mode 100644 index 000000000000..8341b5f1e550 --- /dev/null +++ b/tidb-cloud/notification-2023-09-26-console-maintenance.md @@ -0,0 +1,81 @@ +--- +title: 2023-09-26 TiDB Cloud 控制台维护通知 +summary: 了解 2023 年 9 月 26 日 TiDB Cloud 控制台维护的详细信息,如维护时间窗口、原因和影响。 +--- + +# [2023-09-26] TiDB Cloud 控制台维护通知 + +本通知描述了您需要了解的 2023 年 9 月 26 日 [TiDB Cloud 控制台](https://tidbcloud.com/)维护的详细信息。 + +## 维护时间窗口 + +- 日期:2023-09-26 +- 开始时间:8:00 (UTC+0) +- 结束时间:8:30 (UTC+0) +- 持续时间:约 30 分钟 + +> **注意:** +> +> 目前,TiDB Cloud 控制台的整体维护计划不支持用户修改维护时间。 + +## 维护原因 + +我们正在升级 TiDB Cloud Serverless 的管理基础设施,以提升性能和效率,为所有用户提供更好的体验。这是我们持续提供高质量服务承诺的一部分。 + +## 影响 + +在维护时间窗口期间,您可能会遇到 TiDB Cloud 控制台 UI 和 API 中与创建和更新相关功能的间歇性中断。但是,您的 TiDB 集群将保持正常的数据读写操作,确保不会对您的在线业务产生不利影响。 + +### 受影响的 TiDB Cloud 控制台 UI 功能 + +- 集群级别 + - 集群管理 + - 创建集群 + - 删除集群 + - 扩展集群 + - 查看集群 + - 暂停或恢复集群 + - 更改集群密码 + - 更改集群流量过滤器 + - 导入 + - 创建导入任务 + - 数据迁移 + - 创建迁移任务 + - 变更数据捕获 + - 创建变更数据捕获任务 + - 备份 + - 创建手动备份任务 + - 自动备份任务 + - 恢复 + - 创建恢复任务 + - 数据库审计日志 + - 测试连接性 + - 添加或删除访问记录 + - 启用或禁用数据库审计日志 + - 重启数据库审计日志 +- 项目级别 + - 网络访问 + - 创建私有端点 + - 删除私有端点 + - 添加 VPC 对等连接 + - 删除 VPC 对等连接 + - 维护 + - 更改维护时间窗口 + - 延迟任务 + - 回收站 + - 删除集群 + - 删除备份 + - 恢复集群 + +### 受影响的 TiDB Cloud API 功能 + +- 所有 [API 请求](https://docs.pingcap.com/tidbcloud/api/v1beta)将返回 500 响应。 +- [数据服务 API](https://docs.pingcap.com/tidbcloud/data-service-overview) 不会受到影响。 + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将恢复,为您提供更好的体验。 + +## 获取支持 + +如果您有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为您解答疑虑并提供必要的指导。 diff --git a/tidb-cloud/notification-2023-11-14-scale-feature-maintenance.md b/tidb-cloud/notification-2023-11-14-scale-feature-maintenance.md new file mode 100644 index 000000000000..966bb10bf043 --- /dev/null +++ b/tidb-cloud/notification-2023-11-14-scale-feature-maintenance.md @@ -0,0 +1,42 @@ +--- +title: 2023-11-14 TiDB Cloud Dedicated 扩展功能维护通知 +summary: 了解 2023 年 11 月 14 日 TiDB Cloud Dedicated 扩展功能维护的详细信息,如维护时间窗口和影响。 +--- + +# [2023-11-14] TiDB Cloud Dedicated 扩展功能维护通知 + +本通知描述了你需要了解的 2023 年 11 月 14 日 TiDB Cloud Dedicated [扩展功能](https://docs.pingcap.com/tidbcloud/scale-tidb-cluster#scale-your-tidb-cluster)维护的详细信息。 + +## 维护时间窗口 + +- 开始时间:2023-11-14 16:00 (UTC+0) +- 结束时间:2023-11-21 16:00 (UTC+0) +- 持续时间:7 天 + +> **注意:** +> +> 2023-11-16 更新:维护时间窗口的结束时间已从 2023-11-16 延长至 2023-11-21。 + +## 影响 + +在维护时间窗口期间,[更改 vCPU 和内存](https://docs.pingcap.com/tidbcloud/scale-tidb-cluster#change-vcpu-and-ram)功能将被禁用,你无法更改 Dedicated 集群的 vCPU 和内存。但是,你仍然可以在修改集群页面中更改节点数量或存储。你的 TiDB 集群将保持正常的数据读写操作,确保不会对你的在线业务产生不利影响。 + +### 受影响的 TiDB Cloud 控制台 UI 功能 + +- 集群级别 + - 集群管理 + - 修改集群 + - 更改 TiDB、TiKV 或 TiFlash 节点的 vCPU 和内存。 + +### 受影响的 TiDB Cloud API 功能 + +- 集群管理 + - [UpdateCluster](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将恢复正常,为你提供更好的体验。 + +## 获取支持 + +如果你有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为你解答疑虑并提供必要的指导。 diff --git a/tidb-cloud/notification-2024-04-09-monitoring-features-maintenance.md b/tidb-cloud/notification-2024-04-09-monitoring-features-maintenance.md new file mode 100644 index 000000000000..5ebdd0321db8 --- /dev/null +++ b/tidb-cloud/notification-2024-04-09-monitoring-features-maintenance.md @@ -0,0 +1,53 @@ +--- +title: 2024-04-09 TiDB Cloud 监控功能维护通知 +summary: 了解 2024 年 4 月 9 日 TiDB Cloud 监控功能维护的详细信息,如维护时间窗口、原因和影响。 +--- + +# [2024-04-09] TiDB Cloud 监控功能维护通知 + +本通知描述了你需要了解的关于 2024 年 4 月 9 日 TiDB Cloud [监控功能](/tidb-cloud/monitor-tidb-cluster.md)维护的详细信息。 + +## 维护时间窗口 + +- 开始时间:2024-04-09 08:00 (UTC+0) +- 结束时间:2024-04-09 12:00 (UTC+0) +- 持续时间:4 小时 + +## 影响 + +### 受影响的区域 + +在维护时间窗口期间,以下区域的监控功能将受到影响: + +- TiDB Cloud Dedicated 集群: + - 云服务提供商:AWS,区域:俄勒冈(us-west-2) + - 云服务提供商:AWS,区域:首尔(ap-northeast-2) + - 云服务提供商:AWS,区域:法兰克福(eu-central-1) + - 云服务提供商:AWS,区域:俄勒冈(us-west-2) + - 云服务提供商:Google Cloud,区域:俄勒冈(us-west1) + - 云服务提供商:Google Cloud,区域:东京(asia-northeast1) + - 云服务提供商:Google Cloud,区域:新加坡(asia-southeast1) + - 云服务提供商:Google Cloud,区域:爱荷华(us-central1) + - 云服务提供商:Google Cloud,区域:台湾(asia-east1) + +- TiDB Cloud Serverless 集群: + - 云服务提供商:AWS,区域:法兰克福(eu-central-1) + - 云服务提供商:AWS,区域:俄勒冈(us-west-2) + +### 受影响的监控功能 + +> **注意:** +> +> 维护仅影响 TiDB 集群中的监控功能。所有其他功能保持不受影响。你可以继续管理 TiDB 集群并照常执行读/写操作或其他操作。 + +- **指标**页面将在几个短时间段内暂时不可用(每次不超过 20 分钟)。 +- **慢查询**页面将在几个短时间段内暂时不可用(每次不超过 5 分钟)。 +- 与 Prometheus、DataDog 和 NewRelic 的指标集成可能会出现断点。 + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将被恢复,为你提供更好的体验。 + +## 获取支持 + +如果你有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为你解答疑虑并提供必要的指导。 diff --git a/tidb-cloud/notification-2024-04-11-dm-feature-maintenance.md b/tidb-cloud/notification-2024-04-11-dm-feature-maintenance.md new file mode 100644 index 000000000000..8d9845d36af8 --- /dev/null +++ b/tidb-cloud/notification-2024-04-11-dm-feature-maintenance.md @@ -0,0 +1,49 @@ +--- +title: 2024-04-11 TiDB Cloud 数据迁移(DM)功能维护通知 +summary: 了解 2024 年 4 月 11 日 TiDB Cloud 数据迁移(DM)功能维护的详细信息,如维护时间窗口和影响。 +--- + +# [2024-04-11] TiDB Cloud 数据迁移(DM)功能维护通知 + +本通知描述了你需要了解的关于 2024 年 4 月 11 日 TiDB Cloud Dedicated [数据迁移(DM)功能](/tidb-cloud/migrate-from-mysql-using-data-migration.md)维护的详细信息。 + +## 维护时间窗口 + +- 开始时间:2024-04-11 08:00 (UTC+0) +- 结束时间:2024-04-11 09:00 (UTC+0) +- 持续时间:1 小时 + +## 影响 + +在维护时间窗口期间,以下区域的 TiDB Cloud Dedicated 集群的 DM 功能将受到影响: + +- 云服务提供商:AWS,区域:俄勒冈(us-west-2) +- 云服务提供商:AWS,区域:弗吉尼亚北部(us-east-1) +- 云服务提供商:AWS,区域:新加坡(ap-southeast-1) +- 云服务提供商:AWS,区域:首尔(ap-northeast-2) +- 云服务提供商:AWS,区域:法兰克福(eu-central-1) +- 云服务提供商:AWS,区域:圣保罗(sa-east-1) +- 云服务提供商:AWS,区域:俄勒冈(us-west-2) +- 云服务提供商:Google Cloud,区域:俄勒冈(us-west1) +- 云服务提供商:Google Cloud,区域:东京(asia-northeast1) +- 云服务提供商:Google Cloud,区域:新加坡(asia-southeast1) + +维护仅影响 TiDB 集群中的 DM 功能。所有其他功能保持不受影响。你可以继续管理 TiDB 集群并照常执行读/写操作或其他操作。 + +对于部署在 AWS 上的集群: + +- 在升级期间,DM 任务可以继续运行而不会中断。DM 控制台可以正常使用。 + +对于部署在 Google Cloud 上的集群: + +- DM 控制台将不可用长达 30 分钟。在此期间,你无法创建或管理 DM 任务。 +- 如果 DM 任务处于增量迁移阶段,它将中断长达 30 分钟。在此期间,请勿清除 MySQL 数据库的二进制日志。升级完成后,DM 任务将自动恢复。 +- 如果 DM 任务处于导出和导入全量数据的阶段,它将在升级期间失败,并且在升级后无法恢复。建议在执行升级的当天不要创建任何 DM 任务,以确保在升级开始时没有 DM 任务处于导出和导入全量数据的阶段。 + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将被恢复,为你提供更好的体验。 + +## 获取支持 + +如果你有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为你解答疑虑并提供必要的指导。 diff --git a/tidb-cloud/notification-2024-04-16-monitoring-features-maintenance.md b/tidb-cloud/notification-2024-04-16-monitoring-features-maintenance.md new file mode 100644 index 000000000000..2ec52feec52b --- /dev/null +++ b/tidb-cloud/notification-2024-04-16-monitoring-features-maintenance.md @@ -0,0 +1,46 @@ +--- +title: 2024-04-16 TiDB Cloud 监控功能维护通知 +summary: 了解 2024 年 4 月 16 日 TiDB Cloud 监控功能维护的详细信息,如维护时间窗口、原因和影响。 +--- + +# [2024-04-16] TiDB Cloud 监控功能维护通知 + +本通知描述了您需要了解的 2024 年 4 月 16 日 TiDB Cloud [监控功能](/tidb-cloud/monitor-tidb-cluster.md)维护的详细信息。 + +## 维护时间窗口 + +- 开始时间:2024-04-16 08:00 (UTC+0) +- 结束时间:2024-04-16 12:00 (UTC+0) +- 持续时间:4 小时 + +## 影响 + +### 受影响的区域 + +在维护时间窗口期间,以下区域的监控功能将受到影响: + +- TiDB Cloud Dedicated 集群: + - 云服务提供商:AWS,区域:东京 (ap-northeast-1) + - 云服务提供商:AWS,区域:弗吉尼亚北部 (us-east-1) + +- TiDB Cloud Serverless 集群: + - 云服务提供商:AWS,区域:东京 (ap-northeast-1) + - 云服务提供商:AWS,区域:弗吉尼亚北部 (us-east-1) + +### 受影响的监控功能 + +> **注意:** +> +> 维护仅影响 TiDB 集群中的监控功能。所有其他功能保持不变。您可以继续管理 TiDB 集群并照常执行读写操作或其他操作。 + +- **指标**页面将在几个短时间段内暂时不可用(每次不超过 20 分钟)。 +- **慢查询**页面将在几个短时间段内暂时不可用(每次不超过 5 分钟)。 +- 与 Prometheus、DataDog 和 NewRelic 的指标集成可能会出现断点。 + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将恢复,为您提供更好的体验。 + +## 获取支持 + +如果您有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为您解答疑虑并提供必要的指导。 diff --git a/tidb-cloud/notification-2024-04-18-dm-feature-maintenance.md b/tidb-cloud/notification-2024-04-18-dm-feature-maintenance.md new file mode 100644 index 000000000000..f66cf85b04da --- /dev/null +++ b/tidb-cloud/notification-2024-04-18-dm-feature-maintenance.md @@ -0,0 +1,30 @@ +--- +title: 2024-04-18 TiDB Cloud 数据迁移(DM)功能维护通知 +summary: 了解 2024 年 4 月 18 日 TiDB Cloud 数据迁移(DM)功能维护的详细信息,如维护时间窗口和影响。 +--- + +# [2024-04-18] TiDB Cloud 数据迁移(DM)功能维护通知 + +本通知描述了你需要了解的 2024 年 4 月 18 日 TiDB Cloud Dedicated 的[数据迁移(DM)功能](/tidb-cloud/migrate-from-mysql-using-data-migration.md)维护详情。 + +## 维护时间窗口 + +- 开始时间:2024-04-18 08:00 (UTC+0) +- 结束时间:2024-04-18 09:00 (UTC+0) +- 持续时间:1 小时 + +## 影响 + +在维护时间窗口期间,以下区域的 TiDB Cloud Dedicated 集群的 DM 功能将进行升级: + +- 云服务提供商:AWS,区域:东京 (ap-northeast-1) + +在升级期间,你可以正常使用 TiDB 集群和 DM 控制台的功能。DM 任务可以继续运行而不会中断。 + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将恢复正常,为你提供更好的体验。 + +## 获取支持 + +如果你有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为你解答疑问并提供必要的指导。 diff --git a/tidb-cloud/notification-2024-09-15-console-maintenance.md b/tidb-cloud/notification-2024-09-15-console-maintenance.md new file mode 100644 index 000000000000..89a865425fe2 --- /dev/null +++ b/tidb-cloud/notification-2024-09-15-console-maintenance.md @@ -0,0 +1,92 @@ +--- +title: 2024-09-15 TiDB Cloud 控制台维护通知 +summary: 了解 2024 年 9 月 15 日 TiDB Cloud 控制台维护的详细信息,如维护时间窗口、原因和影响。 +--- + +# [2024-09-15] TiDB Cloud 控制台维护通知 + +本通知描述了你需要了解的 2024 年 9 月 15 日 [TiDB Cloud 控制台](https://tidbcloud.com/)维护的详细信息。 + +## 维护时间窗口 + +- 日期:2024-09-15 +- 开始时间:8:00 (UTC+0) +- 结束时间:8:10 (UTC+0) +- 持续时间:约 10 分钟 + +> **注意:** +> +> - 目前,用户无法修改 TiDB Cloud 控制台的维护时间,因此你需要提前做好相应计划。 +> - 在接下来的 3 个月内,部分用户可能会遇到额外的 20 分钟维护时间窗口。受影响的用户将提前收到电子邮件通知。 + +## 维护原因 + +我们正在升级 TiDB Cloud 控制台的元数据库服务,以提升性能和效率。这项改进旨在为所有用户提供更好的体验,这是我们持续提供高质量服务承诺的一部分。 + +## 影响 + +在维护时间窗口期间,你可能会遇到 TiDB Cloud 控制台 UI 和 API 中与创建和更新相关的功能的间歇性中断。但是,你的 TiDB 集群将保持正常的数据读写操作,确保不会对你的在线业务产生不利影响。 + +### 受影响的 TiDB Cloud 控制台 UI 功能 + +- 集群级别 + - 集群管理 + - 创建集群 + - 删除集群 + - 扩展集群 + - 暂停或恢复集群 + - 更改集群密码 + - 更改集群流量过滤器 + - 导入 + - 创建导入任务 + - 数据迁移 + - 创建迁移任务 + - Changefeed + - 创建 changefeed 任务 + - 备份 + - 创建手动备份任务 + - 自动备份任务 + - 恢复 + - 创建恢复任务 + - 数据库审计日志 + - 测试连接性 + - 添加或删除访问记录 + - 启用或禁用数据库审计日志 + - 重启数据库审计日志 +- 项目级别 + - 网络访问 + - 创建私有端点 + - 删除私有端点 + - 添加 VPC 对等连接 + - 删除 VPC 对等连接 + - 维护 + - 更改维护时间窗口 + - 延迟任务 + - 回收站 + - 删除集群 + - 删除备份 + - 恢复集群 + +### 受影响的 TiDB Cloud API 功能 + +- 集群管理 + - [CreateCluster](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/CreateCluster) + - [DeleteCluster](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/DeleteCluster) + - [UpdateCluster](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) + - [CreateAwsCmek](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/CreateAwsCmek) +- 备份 + - [CreateBackup](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Backup/operation/CreateBackup) + - [DeleteBackup](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Backup/operation/DeleteBackup) +- 恢复 + - [CreateRestoreTask](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Restore/operation/CreateRestoreTask) +- 导入 + - [CreateImportTask](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Import/operation/CreateImportTask) + - [UpdateImportTask](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Import/operation/UpdateImportTask) + +## 完成和恢复 + +一旦维护成功完成,受影响的功能将恢复正常,为你提供更好的体验。 + +## 获取支持 + +如果你有任何问题或需要帮助,请联系我们的[支持团队](/tidb-cloud/tidb-cloud-support.md)。我们随时为你解答疑虑并提供必要的指导。 \ No newline at end of file diff --git a/tidb-cloud/notifications.md b/tidb-cloud/notifications.md new file mode 100644 index 000000000000..3340a53b153d --- /dev/null +++ b/tidb-cloud/notifications.md @@ -0,0 +1,56 @@ +--- +title: TiDB Cloud 控制台中的通知 +summary: 了解 TiDB Cloud 控制台中的通知,包括通知类型、用途以及如何查看它们。 +--- + +# TiDB Cloud 控制台中的通知 + +[TiDB Cloud 控制台](https://tidbcloud.com/)提供通知功能,让你了解重要更新、系统消息、产品变更、账单提醒和其他相关信息。这些通知帮助你在不离开控制台的情况下及时了解最新情况并采取必要的操作。 + +## 通知类型 + +你可能会在 TiDB Cloud 控制台中收到不同类型的通知,例如: + +- **信息通知** + + 提供有用的更新信息,如功能使用提示、应用变更或即将发生的事件提醒。 + +- **操作通知** + + 提示你执行特定操作,如添加信用卡。 + +- **警报通知** + + 通知你需要立即关注的重要问题或紧急事件,如系统错误、安全警告或重要更新。 + +- **账单通知** + + 提供有关账单相关活动的更新,如信用额度和折扣更新。 + +- **反馈通知** + + 请求你对某个功能的使用体验提供反馈,如对最近的交互进行评分或完成调查。 + +## 通知列表 + +下表列出了 TiDB Cloud 中可用的通知,以及它们的触发事件和接收者: + +| 通知 | 触发事件 | 通知接收者 | +| --- | --- | --- | +| TiDB Cloud Serverless 集群创建 | 创建了一个 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 | 所有项目成员 | +| TiDB Cloud Serverless 集群删除 | 删除了一个 TiDB Cloud Serverless 集群。 | 所有项目成员 | +| TiDB Cloud Dedicated 集群创建 | 创建了一个 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 | 所有项目成员 | +| TiDB Cloud Dedicated 集群删除 | 删除了一个 TiDB Cloud Dedicated 集群。 | 所有项目成员 | +| 组织预算阈值警报 | 达到组织[预算阈值](/tidb-cloud/tidb-cloud-budget.md)。 | `组织所有者`、`组织账单管理员`和`组织账单查看者` | +| 项目预算阈值警报 | 达到项目[预算阈值](/tidb-cloud/tidb-cloud-budget.md)。 | `组织所有者`、`组织账单管理员`、`组织账单查看者`和`项目所有者` | +| Serverless 集群支出限额阈值警报 | 达到组织中 TiDB Cloud Serverless 集群的[支出限额阈值](/tidb-cloud/manage-serverless-spend-limit.md)。 | `组织所有者`、`组织账单管理员`、`组织账单查看者`和`项目所有者` | +| 信用额度更新 | 组织的[信用额度](/tidb-cloud/tidb-cloud-billing.md#credits)被应用、完全使用、收回或过期。 | `组织所有者`、`组织账单管理员`和`组织账单查看者` | +| 折扣更新 | 组织的[折扣](/tidb-cloud/tidb-cloud-billing.md#discounts)被应用、收回或过期。 | `组织所有者`、`组织账单管理员`和`组织账单查看者` | +| 云市场更新 | 组织通过云服务提供商市场进行订阅或取消订阅。 | 所有组织成员 | +| 支持计划更新 | 组织的支持计划订阅发生变更。 | 所有组织成员 | + +## 查看通知 + +要查看通知,请点击 [TiDB Cloud 控制台](https://tidbcloud.com/)左下角的**通知**。 + +当有新通知时,**通知**旁边会显示一个数字,表示有多少条未读通知。 diff --git a/tidb-cloud/oauth2.md b/tidb-cloud/oauth2.md new file mode 100644 index 000000000000..4dc4159992b0 --- /dev/null +++ b/tidb-cloud/oauth2.md @@ -0,0 +1,47 @@ +--- +title: OAuth 2.0 +summary: 了解如何在 TiDB Cloud 中使用 OAuth 2.0。 +--- + +# OAuth 2.0 + +本文档介绍如何使用 OAuth 2.0 访问 TiDB Cloud。 + +OAuth(Open Authorization 的缩写)是一个开放标准的认证协议,允许代表用户安全地访问资源。它为第三方应用程序提供了一种访问用户资源的方式,而无需暴露用户的凭据。 + +[OAuth 2.0](https://oauth.net/2/) 是 OAuth 的最新版本,已成为授权的行业标准协议。OAuth 2.0 的主要优势包括: + +- 安全性:通过使用基于令牌的认证,OAuth 2.0 最大限度地降低了密码被盗和未经授权访问的风险。 +- 便利性:你可以授予和撤销对数据的访问权限,而无需管理多个凭据。 +- 访问控制:你可以指定授予第三方应用程序的确切访问级别,确保仅授予必要的权限。 + +## OAuth 授权类型 + +OAuth 框架为不同的使用场景指定了几种授权类型。TiDB Cloud 支持两种最常见的 OAuth 授权类型:设备码和授权码。 + +### 设备码授权类型 + +通常用于无浏览器或输入受限的设备在设备流程中使用先前获得的设备码交换访问令牌。 + +### 授权码授权类型 + +这是最常见的 OAuth 2.0 授权类型,它使网络应用程序和原生应用程序都可以在用户授权应用程序后获取访问令牌。 + +## 使用 OAuth 访问 TiDB Cloud + +你可以使用 OAuth 2.0 设备码授权类型访问 TiDB Cloud CLI: + +- [ticloud auth login](/tidb-cloud/ticloud-auth-login.md):向 TiDB Cloud 进行认证 +- [ticloud auth logout](/tidb-cloud/ticloud-auth-logout.md):从 TiDB Cloud 登出 + +如果你的应用程序需要使用 OAuth 访问 TiDB Cloud,请提交申请[成为云和技术合作伙伴](https://www.pingcap.com/partners/become-a-partner/)(在**合作伙伴计划**中选择**云和技术合作伙伴**)。我们会与你联系。 + +## 查看和撤销已授权的 OAuth 应用程序 + +你可以在 TiDB Cloud 控制台中查看已授权的 OAuth 应用程序记录,步骤如下: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,点击左下角的 。 +2. 点击**账号设置**。 +3. 点击**已授权的 OAuth 应用程序**选项卡。你可以查看已授权的 OAuth 应用程序。 + +你可以随时点击**撤销**来撤销你的授权。 diff --git a/tidb-cloud/optimize-resource-allocation.md b/tidb-cloud/optimize-resource-allocation.md new file mode 100644 index 000000000000..9b186eb1562e --- /dev/null +++ b/tidb-cloud/optimize-resource-allocation.md @@ -0,0 +1,38 @@ +--- +title: 优化 TiDB Cloud Dedicated 的资源分配 +summary: 了解如何优化 TiDB Cloud Dedicated 集群的资源分配。 +--- + +# 优化 TiDB Cloud Dedicated 的资源分配 + +作为一个混合事务和分析处理(HTAP)数据库,[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群可以支持多个业务应用,每个应用都有不同的服务质量(QoS)要求。在某些情况下,你可能需要为高优先级应用分配更多资源以维持可接受的延迟水平。 + +TiDB Cloud Dedicated 提供资源优化功能,包括[资源控制](/tidb-resource-control.md)和 [TiDB 节点组](/tidb-cloud/tidb-node-group-overview.md)功能。这些功能帮助你在多业务场景中高效分配资源。 + +## 使用资源控制 + +[资源控制](/tidb-resource-control.md)允许你将 TiDB Cloud Dedicated 集群的存储节点(TiKV 或 TiFlash)划分为多个逻辑组。在混合工作负载的系统中,你可以将工作负载分配到不同的资源组,以确保资源隔离并满足 QoS 要求。 + +如果集群出现意外的 SQL 性能问题,你可以使用 [SQL 绑定](/sql-statements/sql-statement-create-binding.md)或[管理失控查询](/tidb-resource-control.md#manage-queries-that-consume-more-resources-than-expected-runaway-queries),配合资源组来临时限制特定 SQL 语句的资源消耗。 + +通过有效使用资源控制,你可以减少集群数量,简化运维,并降低管理成本。 + +## 使用 TiDB 节点组 + +[TiDB 节点组](/tidb-cloud/tidb-node-group-overview.md)功能将 TiDB Cloud Dedicated 集群的计算节点(TiDB 层)物理分组。每个组配置特定数量的 TiDB 节点,确保组之间计算资源的物理隔离。 + +你可以根据业务需求将计算节点划分为多个 TiDB 节点组,并为每个组分配唯一的连接端点。你的应用程序通过各自的端点连接到集群,请求路由到相应的节点组进行处理。这确保了一个组中的资源过度使用不会影响其他组。 + +## 在资源控制和 TiDB 节点组之间选择 + +你可以根据应用需求和预算使用资源控制、TiDB 节点组功能或两者的组合来实现资源隔离。 + +下表比较了资源控制和 TiDB 节点组的功能特点: + +| 比较项 | 资源控制 | TiDB 节点组 | +|--------------------------|---------------------------|------------------------| +| 隔离级别 | TiKV 或 TiFlash 逻辑层 | TiDB 节点物理层 | +| 流量控制 | 根据资源组设置的配额控制用户读写请求的流量。 | 不支持。 | +| 配置方式 | 使用 SQL 语句配置 | 通过 TiDB Cloud 控制台配置 | +| 区分工作负载 | 支持在以下级别绑定资源:
  • 用户级别。
  • 会话级别(每个会话设置资源组)。
  • 语句级别(每个语句设置资源组)。
| 为不同工作负载提供不同的连接端点。 | +| 成本 | 无额外成本 | 添加 TiDB 节点会产生相关成本,但创建 TiDB 节点组本身不产生额外成本。 | diff --git a/tidb-cloud/pause-or-resume-tidb-cluster.md b/tidb-cloud/pause-or-resume-tidb-cluster.md new file mode 100644 index 000000000000..80c9f6a1db31 --- /dev/null +++ b/tidb-cloud/pause-or-resume-tidb-cluster.md @@ -0,0 +1,112 @@ +--- +title: 暂停或恢复 TiDB Cloud Dedicated 集群 +summary: 了解如何暂停或恢复 TiDB Cloud Dedicated 集群。 +--- + +# 暂停或恢复 TiDB Cloud Dedicated 集群 + +在 TiDB Cloud 中,您可以轻松地暂停和恢复不需要持续运行的 TiDB Cloud Dedicated 集群。 + +暂停操作不会影响集群中存储的数据,仅会停止收集监控信息和计算资源的消耗。暂停后,您可以随时恢复集群。 + +与备份和恢复相比,暂停和恢复集群所需时间更短,并且可以保留集群信息(包括集群版本、集群配置和 TiDB 用户账户)。 + +> **注意:** +> +> 您不能暂停 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。 + +## 限制条件 + +- 只有当集群处于 **Available**(可用)状态时,您才能暂停集群。如果集群处于其他状态(如 **Modifying**),您必须等待当前操作完成后才能暂停集群。 +- 当数据导入任务正在进行时,您不能暂停集群。您可以等待导入任务完成或取消导入任务。 +- 当备份任务正在进行时,您不能暂停集群。您可以等待当前备份任务完成或[删除正在运行的备份任务](/tidb-cloud/backup-and-restore.md#delete-a-running-backup-job)。 +- 如果集群有任何 [changefeeds](/tidb-cloud/changefeed-overview.md),您不能暂停集群。您需要在暂停集群之前[删除现有的 changefeeds](/tidb-cloud/changefeed-overview.md#delete-a-changefeed)。 + +## 暂停 TiDB 集群 + +暂停时长和行为取决于您的组织创建日期: + +- 2024 年 11 月 12 日之后创建的组织遵循标准暂停行为,最长暂停时间为 7 天。 +- 2024 年 11 月 12 日或之前创建的组织遵循兼容暂停行为,允许更长的暂停时间。这些组织将逐步过渡到标准的 7 天限制。 + + +
+ +当集群被暂停时,请注意以下几点: + +- TiDB Cloud 停止收集集群的监控信息。 +- 您无法从集群读取或写入数据。 +- 您无法导入或备份数据。 +- 仅收取以下费用: + + - 节点存储费用 + - 数据备份费用 + +- TiDB Cloud 停止集群的[自动备份](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup)。 +- 最长暂停时间为 7 天。如果您在 7 天内没有手动恢复集群,TiDB Cloud 将自动恢复它。 +- 您可以在集群概览页面查看自动恢复计划。TiDB Cloud 将在集群自动恢复前 24 小时向组织所有者和项目所有者发送通知邮件。 + +
+
+ +> **注意:** +> +> 如果您的组织是在 2024 年 11 月 12 日之前创建的,您的集群仍然遵循兼容暂停行为。TiDB Cloud 将在过渡到新的标准暂停行为之前通知您。 + +当集群被暂停时,请注意以下几点: + +- TiDB Cloud 停止收集集群的监控信息。 +- 您无法从集群读取或写入数据。 +- 您无法导入或备份数据。 +- TiDB Cloud 不会自动恢复已暂停的集群。 +- 仅收取以下费用: + + - 节点存储费用 + - 数据备份费用 + +- TiDB Cloud 停止集群的[自动备份](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup)。 + +
+
+ +要暂停集群,请按照以下步骤操作: + +1. 在 TiDB Cloud 控制台中,导航到项目的 [**Clusters**](https://tidbcloud.com/project/clusters) 页面。 +2. 在要暂停的集群所在行,点击 **...**。 + + > **提示:** + > + > 或者,您可以在 **Clusters** 页面上点击要暂停的集群名称,然后点击右上角的 **...**。 + +3. 在下拉菜单中点击 **Pause**。 + + 此时会显示 **Pause your cluster** 对话框。 + +4. 在对话框中,点击 **Pause** 确认您的选择。 + + 点击 **Pause** 后,集群将首先进入 **Pausing** 状态。一旦暂停操作完成,集群将转换为 **Paused** 状态。 + +您也可以使用 TiDB Cloud API 暂停集群。目前,TiDB Cloud API 仍处于测试阶段。更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 + +## 恢复 TiDB 集群 + +暂停的集群恢复后,请注意以下几点: + +- TiDB Cloud 恢复收集集群的监控信息,您可以从集群读取或写入数据。 +- TiDB Cloud 恢复收取计算和存储费用。 +- TiDB Cloud 恢复集群的[自动备份](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup)。 + +要恢复已暂停的集群,请按照以下步骤操作: + +1. 在 TiDB Cloud 控制台中,导航到项目的 [**Clusters**](https://tidbcloud.com/project/clusters) 页面。 +2. 对于要恢复的集群,点击 **Resume**。此时会显示 **Resume your cluster** 对话框。 + + > **注意:** + > + > 您不能恢复处于 **Pausing** 状态的集群。 + +3. 在对话框中,点击 **Resume** 确认您的选择。集群状态将变为 **Resuming**。 + +根据集群大小,恢复集群可能需要几分钟时间。集群恢复后,集群状态将从 **Resuming** 变为 **Available**。 + +您也可以使用 TiDB Cloud API 恢复集群。目前,TiDB Cloud API 仍处于测试阶段。更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 diff --git a/tidb-cloud/recovery-group-delete.md b/tidb-cloud/recovery-group-delete.md new file mode 100644 index 000000000000..fce184efc76a --- /dev/null +++ b/tidb-cloud/recovery-group-delete.md @@ -0,0 +1,24 @@ +--- +title: 删除恢复组 +summary: 了解如何在不再需要恢复组时删除它。 +--- + +# 删除恢复组 + +当不再需要恢复组时,您可以删除它。 + +## 删除恢复组 + +当不再需要恢复组来管理一组数据库的复制时,您可以从系统中删除它。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**恢复组**。 +3. 在**恢复组**页面上,找到您想要删除的恢复组的名称。 +4. 点击恢复组的**操作**菜单,然后点击**删除**。此时会显示删除对话框。 + + > **警告** + > + > - 删除恢复组也会删除与该恢复组关联的所有复制关系。 + > - 与恢复组关联的数据库将不再受到灾难保护。 + +5. 通过输入恢复组的名称并点击**我理解,删除它**来确认您了解删除的影响。 diff --git a/tidb-cloud/recovery-group-failover.md b/tidb-cloud/recovery-group-failover.md new file mode 100644 index 000000000000..95220ee0a547 --- /dev/null +++ b/tidb-cloud/recovery-group-failover.md @@ -0,0 +1,69 @@ +--- +title: 数据库故障转移和重新保护 +summary: 了解如何使用恢复组在 TiDB Cloud 集群之间进行数据库故障转移和重新保护。 +--- + +# 数据库故障转移和重新保护 + +恢复组中的数据库会从一个集群复制到另一个集群,通常是在云服务提供商的不同区域。 + +**故障转移**操作会将次要区域中的复制数据库提升为新的主副本,确保在区域性中断期间持续可用。 + +当区域性中断解决后,可以使用**重新保护**操作将复制从恢复区域反向恢复到原始区域。这确保数据库能够防范影响其新区域的未来灾难,并为其需要时迁回原始区域做好准备。 + +## 前提条件 + +在执行故障转移之前,应该已经创建了恢复组并成功地将数据复制到次要集群。更多信息,请参阅[恢复组入门](/tidb-cloud/recovery-group-get-started.md)。 + +![受保护的恢复组](/media/tidb-cloud/recovery-group/recovery-group-protected.png) + +## 使用恢复组进行数据库故障转移 + +在发生灾难时,你可以使用恢复组将数据库故障转移到次要集群。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,使用左上角的组合框切换到目标项目。 + +2. 在左侧导航栏中,点击**恢复组**。 + +3. 在**恢复组**页面上,找到你想要进行故障转移的恢复组名称。 + +4. 点击恢复组的**操作**菜单,然后点击**故障转移**。此时会显示故障转移对话框。 + + > **警告** + > + > 执行故障转移将切断现有的复制关系。 + +5. 选择要提升为主副本的次要 TiDB Cloud 集群。确保所选集群处于健康状态。 + +6. 通过在确认输入框中输入 **Failover** 并点击**我理解,执行故障转移**来确认你理解故障转移可能造成的中断性影响,以开始故障转移。 + + ![故障转移恢复组](/media/tidb-cloud/recovery-group/recovery-group-failover.png) + +## 使用恢复组重新保护数据库 + +故障转移完成后,次要集群上的副本数据库现在成为主副本。但是,由于故障转移过程停止了复制关系,这些数据库无法防范未来的灾难。 + +如果受灾难影响的原始主集群可以重新上线,你可以使用**重新保护**操作将复制从恢复区域重新建立回原始区域。 + +![未受保护的恢复组](/media/tidb-cloud/recovery-group/recovery-group-unprotected.png) + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,使用左上角的组合框切换到目标项目。 + +2. 在左侧导航栏中,点击**恢复组**。 + +3. 在**恢复组**页面上,找到你想要重新保护的恢复组名称。 + + > **注意** + > + > **恢复组详情**页面提供了有关恢复组的信息,包括当前状态和复制拓扑。 + > 在重新保护同步期间,由于传输的数据量较大,可能会影响主集群或次要集群的在线查询性能。建议你在较不繁忙的时段安排数据库的重新保护操作。 + + > **警告** + > + > 作为执行重新保护操作所需的数据复制的一部分,目标集群中所选数据库的内容将被(新)主集群中数据库的内容替换。如果你希望保留目标集群上的唯一内容,请在执行重新保护操作之前完成备份。 + +4. 点击恢复组的**操作**菜单,然后点击**重新保护**。此时会显示重新保护对话框。 + +5. 点击**重新保护**确认重新保护操作,以开始重新保护操作。 + + ![重新保护恢复组](/media/tidb-cloud/recovery-group/recovery-group-reprotected.png) diff --git a/tidb-cloud/recovery-group-get-started.md b/tidb-cloud/recovery-group-get-started.md new file mode 100644 index 000000000000..91282f99b416 --- /dev/null +++ b/tidb-cloud/recovery-group-get-started.md @@ -0,0 +1,89 @@ +--- +title: 恢复组入门 +summary: 了解如何在 TiDB Cloud 中创建恢复组并查看其详细信息。 +--- + +# 恢复组入门 + +本文档介绍如何使用 [TiDB Cloud 控制台](https://tidbcloud.com/) 创建恢复组来保护运行在 TiDB Cloud Dedicated 集群上的数据库。同时还介绍如何查看恢复组的详细信息。 + +## 前提条件 + +- 恢复组将你的数据库复制到另一个集群,以保护你的数据库免受区域性灾难的影响。在创建恢复组之前,你需要有两个 TiDB Cloud Dedicated 集群。一个集群托管主数据库,第二个集群托管主数据库的副本。如果你尚未创建这些集群,请按照[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)中的步骤创建所需的集群。 +- 要创建恢复组,你必须具有组织的 `Organization Owner` 角色或目标项目的 `Project Owner` 角色。 + +> **注意** +> +> 目前,只有在 AWS 上托管的 TiDB Cloud Dedicated 集群支持恢复组。 + +## 创建新的恢复组 + +要创建恢复组,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,使用左上角的组合框切换到目标项目。 + +2. 在左侧导航栏中,点击 **Recovery Group**。 + +3. 在 **Recovery Group** 页面,点击 **Create Recovery Group**。 + +4. 在 **Create Recovery Group** 页面,为恢复组输入名称。 + + > **注意** + > + > 目前仅支持一种弹性级别。有关更多信息,请参见[关于弹性级别](#关于弹性级别)。 + +5. 选择将作为该组主集群的 TiDB Cloud Dedicated 集群。 + +6. 选择将作为该组数据库复制目标的备用 TiDB Cloud Dedicated 集群。 + +7. 选择你希望作为此恢复组一部分进行复制的数据库。 + + > **注意** + > + > 在将数据库分配给组时,你可以选择特定数据库,或选择主集群上的所有(非系统)数据库(当前和未来)。 + > + > - 如果你**分配所有数据库(当前和未来)**,将来添加到集群的任何数据库都将自动包含在此恢复组中,并复制到备用集群。 + > - 如果你**分配特定数据库**,选择你想要复制到备用集群的主集群上的特定数据库。如果将来向主集群添加任何数据库,这些新数据库不会自动作为此恢复组的一部分进行复制。 + > + > 在初始复制期间,由于传输的数据量较大,可能会影响主集群或备用集群的在线查询性能。请在较不繁忙的时期安排数据库的初始保护。 + + > **警告** + > + > 在初始复制期间,主集群上所选数据库的内容将替换备用集群上的数据库内容。如果你希望保留备用集群上的唯一内容,请在设置恢复组之前完成备份。 + +8. 查看摘要信息,然后点击 **Create** 开始将数据库作为新恢复组的一部分进行保护。 + +## 查看恢复组详细信息 + +创建恢复组后,你可以在 **Recovery Group Detail** 页面上查看其状态信息: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,使用左上角的组合框切换到目标项目。 + +2. 在左侧导航栏中,点击 **Recovery Group**。 + +3. 在 **Recovery Group** 页面,点击你想要查看的恢复组的名称。 + + **Recovery Group Detail** 页面提供了有关恢复组的信息,包括其配置详细信息、状态以及复制吞吐量和延迟的指标。 + +4. 当复制关系完全建立并正常运行时,状态显示为 **Available**。 + + > **警告** + > + > 在设置恢复组期间,将在备用集群上创建一个遵循 `cloud-rg-*` 模式命名的账户,用于复制过程。删除或修改此账户将中断复制。 + +## 关于弹性级别 + +弹性级别定义了恢复组在不同场景下数据读取的一致性特征。目前,TiDB Cloud 仅提供以下弹性级别: + +- 不保证一致性。在恢复组的复制过程中,下游集群不保证事务一致性读取。当上游集群不可用时,你无法将下游集群中的数据恢复到事务一致性状态。 + +TiDB Cloud 将在不久的将来提供两个额外的弹性级别: + +- 最终一致性。在恢复组的复制过程中,下游集群不保证事务一致性读取。但是,当上游集群不可用时,你可以将下游集群中的数据恢复到事务一致性状态。 +- 近实时一致性。在恢复组的复制过程中,下游集群提供近实时的事务一致性读取。当上游集群不可用时,你可以将下游集群中的数据恢复到事务一致性状态。 + +## 下一步 + +创建恢复组后,你可能想要熟悉故障转移和重新保护操作。这些操作用于将复制数据库的主集群从一个集群**故障转移**到另一个集群,然后在相反方向重新建立复制以**重新保护**已故障转移的数据库。 + +- [数据库故障转移和重新保护](/tidb-cloud/recovery-group-failover.md) diff --git a/tidb-cloud/recovery-group-overview.md b/tidb-cloud/recovery-group-overview.md new file mode 100644 index 000000000000..c76d952af075 --- /dev/null +++ b/tidb-cloud/recovery-group-overview.md @@ -0,0 +1,37 @@ +--- +title: 恢复组概述(Beta) +summary: 了解如何使用 TiDB Cloud 恢复组保护数据库免受灾难影响。 +--- + +# 恢复组概述(Beta) + +TiDB Cloud 恢复组允许你在 TiDB Cloud Dedicated 集群之间复制数据库,以防止区域性灾难。你可以编排数据库从一个集群到另一个集群的故障转移。在故障转移到备用集群后,如果原主集群恢复可用,你可以重新建立反向复制以重新保护你的数据库。 + +## 架构 + +恢复组由一组可以在两个 TiDB Cloud Dedicated 集群之间进行故障转移的复制数据库组成。每个恢复组都分配有一个主集群,该主集群上的数据库与该组关联,然后复制到备用集群。 + +![恢复组](/media/tidb-cloud/recovery-group/recovery-group-overview.png) + +- 恢复组:在两个集群之间复制的一组数据库 +- 主集群:应用程序主动写入数据库的集群 +- 备用集群:存放数据库副本的集群 + +> **注意** +> +> 恢复组功能不会显式强制将客户端连接到副本数据库设置为只读。确保连接到副本数据库的应用程序只执行只读查询是应用程序的责任。 + +## 主要特性和限制 + +- 目前,只有在 AWS 上托管的 TiDB Cloud Dedicated 集群支持恢复组。 +- 恢复组在两个集群之间建立。 +- 恢复组不支持数据库的双向复制。 + +> **警告** +> +> 此功能处于 beta 阶段,不建议在生产环境中使用。 + +## 下一步 + +- 要开始使用恢复组,请参见[创建数据库恢复组](/tidb-cloud/recovery-group-get-started.md)。 +- 要了解如何使用恢复组,请参见[数据库故障转移和重新保护](/tidb-cloud/recovery-group-failover.md)。 diff --git a/tidb-cloud/release-notes-2020.md b/tidb-cloud/release-notes-2020.md new file mode 100644 index 000000000000..0df77ad3bd2a --- /dev/null +++ b/tidb-cloud/release-notes-2020.md @@ -0,0 +1,81 @@ +--- +title: TiDB Cloud 2020 年发布说明 +summary: 了解 TiDB Cloud 在 2020 年的发布说明。 +--- + +# TiDB Cloud 2020 年发布说明 + +本页列出了 [TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 在 2020 年的发布说明。 + +## 2020 年 12 月 30 日 + +* 将默认 TiDB 版本升级到 v4.0.9 +* 支持优雅地升级和扩展 TiDB,实现零客户端故障 +* 从备份恢复新集群后恢复集群配置 + +## 2020 年 12 月 16 日 + +* 调整所有集群层级的 TiDB 节点最小数量为一个 +* 禁止在 SQL Web Shell 上执行系统命令 +* 默认为 TiDB 集群启用 redact-log + +## 2020 年 11 月 24 日 + +* 允许 TiDB 集群公共端点的流量过滤 IP 列表为空以禁用公共访问 +* 提高发送给使用 Outlook 或 Hotmail 的客户的邀请邮件的送达率 +* 优化注册的错误通知消息 +* 新集群将在 CentOS VM 而不是 Ubuntu 上运行 +* 修复当相应的备份仍然存在时集群不显示在回收站中的问题 + +## 2020 年 11 月 4 日 + +* 实现更改组织名称的功能 +* 在数据恢复期间防止用户访问 TiDB +* 更新注册页面中的服务条款和隐私政策位置 +* 添加反馈表单入口小部件 +* 防止成员在偏好设置标签中删除所有者 +* 更改 TiFlash 和 TiKV 存储图表指标 +* 将默认 TiDB 集群版本升级到 4.0.8 + +## 2020 年 10 月 12 日 + +* 将 SQL Web Shell 客户端从 Oracle MySQL 客户端更改为 `usql` 客户端 +* 将默认 TiDB 版本升级到 4.0.7 +* 将手动备份保留期从 7 天延长到 30 天 + +## 2020 年 10 月 2 日 + +* 修复 TiFlash 磁盘存储配置 + +## 2020 年 9 月 14 日 + +* 通过添加 `region` 标签修复监控指标 +* 修复非 HTAP 集群无法扩展的问题 + +## 2020 年 9 月 11 日 + +* 客户现在可以使用带有流量过滤器的公共端点访问 TiDB +* 在自动备份设置对话框中添加时区指示器 +* 修复注册未完成时邀请链接失效的问题 + +## 2020 年 9 月 4 日 + +* 修复邀请邮件中的错误 URL + +## 2020 年 8 月 6 日 + +* 将电子邮件支持更改为访问 TiDB Cloud 客户支持 +* 为自定义电子邮件登录添加简单的双因素认证功能 +* 添加设置 VPC 对等连接的功能 +* 为注册/登录添加自定义电子邮件支持 + +## 2020 年 7 月 17 日 + +* 将自动每日备份的默认保留期调整为 7 天 +* 在工具提示中添加集群不健康状态的原因 +* 修复初始信用额度为 0 时用户仍然可以创建集群的问题 +* 优化 Dashboard 的集成 +* 为客户添加信用额度时发送邮件 +* 在租户偏好设置页面中添加租户 ID +* 优化用户配额限制的合理通知消息 +* 修复备份/恢复指标 diff --git a/tidb-cloud/release-notes-2021.md b/tidb-cloud/release-notes-2021.md new file mode 100644 index 000000000000..b0eb7be8f774 --- /dev/null +++ b/tidb-cloud/release-notes-2021.md @@ -0,0 +1,128 @@ +--- +title: 2021 年 TiDB Cloud 发布说明 +summary: 了解 2021 年 TiDB Cloud 的发布说明。 +--- + +# 2021 年 TiDB Cloud 发布说明 + +本页列出了 2021 年 [TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 的发布说明。 + +## 2021 年 12 月 28 日 + +新功能: + +* 支持[将 Apache Parquet 文件从 Amazon S3 或 GCS 导入到 TiDB Cloud](/tidb-cloud/import-parquet-files.md) + +Bug 修复: + +* 修复了向 TiDB Cloud 导入超过 1000 个文件时发生的导入错误 +* 修复了 TiDB Cloud 允许将数据导入到已有数据的现有表的问题 + +## 2021 年 11 月 30 日 + +通用变更: + +* 将 TiDB Cloud 的开发者层级升级到 [TiDB v5.3.0](https://docs.pingcap.com/tidb/stable/release-5.3.0) + +新功能: + +* 支持[为您的 TiDB Cloud 项目添加 VPC CIDR](/tidb-cloud/set-up-vpc-peering-connections.md) + +改进: + +* 提升开发者层级的监控能力 +* 支持将自动备份时间设置为与开发者层级集群的创建时间相同 + +Bug 修复: + +* 修复开发者层级中由于磁盘满导致的 TiKV 崩溃问题 +* 修复 HTML 注入漏洞 + +## 2021 年 11 月 8 日 + +* 发布 [开发者层级](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless),为您提供 TiDB Cloud 一年的免费试用 + + 每个开发者层级集群都是一个功能齐全的 TiDB 集群,并包含以下内容: + + * 一个 TiDB 共享节点 + * 一个 TiKV 共享节点(具有 500 MiB 的 OLTP 存储) + * 一个 TiFlash 共享节点(具有 500 MiB 的 OLAP 存储) + + 从[这里](/tidb-cloud/tidb-cloud-quickstart.md)开始。 + +## 2021 年 10 月 21 日 + +* 开放个人邮箱账户的用户注册 +* 支持[从 Amazon S3 或 GCS 导入或迁移到 TiDB Cloud](/tidb-cloud/import-csv-files.md) + +## 2021 年 10 月 11 日 + +* 支持[查看和导出 TiDB Cloud 的账单明细](/tidb-cloud/tidb-cloud-billing.md#billing-details),包括每个服务和每个项目的成本 +* 修复了 TiDB Cloud 内部功能的几个问题 + +## 2021 年 9 月 16 日 + +* 将新部署集群的默认 TiDB 版本从 5.2.0 升级到 5.2.1。 有关 5.2.1 的详细更改,请参阅 [5.2.1](https://docs.pingcap.com/tidb/stable/release-5.2.1) 发行说明。 + +## 2021 年 9 月 2 日 + +* 将新部署集群的默认 TiDB 版本从 5.0.2 升级到 5.2.0。 有关 TiDB 5.1.0 和 5.2.0 功能的详细信息,请参阅 [5.2.0](https://docs.pingcap.com/tidb/stable/release-5.2.0) 和 [5.1.0](https://docs.pingcap.com/tidb/stable/release-5.1.0) 发行说明。 +* 修复了 TiDB Cloud 内部功能的几个问题。 + +## 2021 年 8 月 19 日 + +* 修复了 TiDB Cloud 内部功能的几个问题。此版本不带来任何用户行为的更改。 + +## 2021 年 8 月 5 日 + +* 支持组织角色管理。组织所有者可以根据需要配置组织成员的权限。 +* 支持组织内多个项目的隔离。组织所有者可以根据需要创建和管理项目,并且项目之间的成员和实例支持网络和权限隔离。 +* 优化账单,以显示当月和上个月的每个项目的账单明细。 + +## 2021 年 7 月 22 日 + +* 优化添加信用卡的用户体验 +* 加强信用卡的安全管理 +* 修复集群从备份恢复后无法正常计费的问题 + +## 2021 年 7 月 6 日 + +* 将新部署集群的默认 TiDB 版本从 4.0.11 升级到 5.0.2。此次升级带来了显著的性能和功能改进。详情请参见[此处](https://docs.pingcap.com/tidb/stable/release-5.0.0)。 + +## 2021 年 6 月 25 日 + +* 修复了 [TiDB Cloud 定价](https://www.pingcap.com/pricing/) 页面上 **选择区域** 功能无法使用的问题 + +## 2021 年 6 月 24 日 + +* 修复将 Aurora 快照导入 TiDB 实例时 Parquet 文件的解析错误 +* 修复 PoC 用户创建集群并更改集群配置时,预计工时未更新的问题 + +## 2021 年 6 月 16 日 + +* 在注册账户时,**中国**已添加到**国家/地区**下拉列表中 + +## 2021 年 6 月 14 日 + +* 修复将 Aurora 快照导入 TiDB 实例时挂载 EBS 错误的bug + +## 2021 年 5 月 10 日 + +通用 + +* TiDB Cloud 现在处于公开预览阶段。您可以[注册](https://tidbcloud.com/signup)并选择以下试用选项之一: + + * 48小时免费试用 + * 2周 PoC 免费试用 + * 预览按需 + +管理控制台 + +* 注册流程中增加了邮箱验证和反机器人 reCAPTCHA +* [TiDB Cloud 服务协议](https://pingcap.com/legal/tidb-cloud-services-agreement) 和 [PingCAP 隐私政策](https://pingcap.com/legal/privacy-policy/) 已更新 +* 您可以通过在控制台中填写申请表来申请 [PoC](/tidb-cloud/tidb-cloud-poc.md) +* 您可以通过 UI 将示例数据导入到 TiDB Cloud 集群中 +* 不允许使用相同名称的集群,以避免混淆 +* 您可以通过点击 **支持** 菜单中的 **提供反馈** 来提供反馈 +* 数据备份和恢复功能适用于 PoC 和按需试用选项 +* 为免费试用和 PoC 添加了积分计算器和积分使用情况仪表板。所有试用选项均免除数据存储和传输成本 \ No newline at end of file diff --git a/tidb-cloud/release-notes-2022.md b/tidb-cloud/release-notes-2022.md new file mode 100644 index 000000000000..56c9108ea282 --- /dev/null +++ b/tidb-cloud/release-notes-2022.md @@ -0,0 +1,618 @@ +--- +title: 2022 年 TiDB Cloud 发布说明 +summary: 了解 2022 年 TiDB Cloud 的发布说明。 +--- + +# 2022 年 TiDB Cloud 发布说明 + +此页面列出了 2022 年 [TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 的发布说明。 + +## 2022 年 12月 28 日 + +**常规变更** + +- 目前,在将所有 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的默认 TiDB 版本从 [v6.3.0](https://docs-archive.pingcap.com/tidb/v6.3/release-6.3.0) 升级到 [v6.4.0](https://docs-archive.pingcap.com/tidb/v6.4/release-6.4.0) 之后,在某些情况下冷启动速度变慢。 因此,我们将所有 Serverless Tier 集群的默认 TiDB 版本从 v6.4.0 回滚到 v6.3.0,然后尽快解决该问题,并在稍后再次升级。 + +## 2022 年 12月 27 日 + +**常规变更** + +- 将所有[Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群的默认 TiDB 版本从 [v6.3.0](https://docs-archive.pingcap.com/tidb/v6.3/release-6.3.0) 升级到 [v6.4.0](https://docs-archive.pingcap.com/tidb/v6.4/release-6.4.0)。 + +- Dedicated Tier 集群的时间点恢复 (PITR) 现在已正式发布 (GA)。 + + PITR 支持将任何时间点的数据恢复到新集群。要使用 PITR 功能,请确保您的 TiDB 集群版本至少为 v6.4.0,并且 TiKV 节点大小至少为 8 vCPU 和 16 GiB。 + + 您可以在 [TiDB Cloud 控制台](https://tidbcloud.com)的**备份设置**中启用或禁用 PITR 功能。 + + 有关更多信息,请参阅[备份和恢复 TiDB 集群数据](/tidb-cloud/backup-and-restore.md)。 + +- 支持管理多个 Changefeed 并编辑现有 Changefeed。 + + - 您现在可以根据需要创建任意数量的 Changefeed 来管理不同的数据复制任务。目前,每个集群最多可以有 10 个 Changefeed。有关更多详细信息,请参阅[Changefeed 概述](/tidb-cloud/changefeed-overview.md)。 + - 您可以编辑处于暂停状态的现有 Changefeed 的配置。有关更多信息,请参阅[编辑 Changefeed](/tidb-cloud/changefeed-overview.md#edit-a-changefeed)。 + +- 支持直接将数据从 Amazon Aurora MySQL、Amazon Relational Database Service (RDS) MySQL 或自托管的 MySQL 兼容数据库在线迁移到 TiDB Cloud。此功能现已正式发布。 + + - 在以下 6 个区域提供服务: + - AWS 俄勒冈 (us-west-2) + - AWS 北弗吉尼亚 (us-east-1) + - AWS 孟买 (ap-south-1) + - AWS 新加坡 (ap-southeast-1) + - AWS 东京 (ap-northeast-1) + - AWS 法兰克福 (eu-central-1) + - 支持多种规格。您可以根据所需的性能选择合适的规格,以获得最佳的数据迁移体验。 + + 有关如何将数据迁移到 TiDB Cloud,请参阅[用户文档](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。有关计费详情,请参阅[数据迁移计费](/tidb-cloud/tidb-cloud-billing-dm.md)。 + +- 支持将本地 CSV 文件导入到 TiDB Cloud。 + + 只需点击几下即可完成任务配置,然后您的本地 CSV 数据就可以快速导入到您的 TiDB 集群中。使用此方法时,您无需提供云存储桶路径和 Role ARN。整个导入过程快速而流畅。 + + 有关更多信息,请参阅[将本地文件导入到 TiDB Cloud](/tidb-cloud/tidb-cloud-import-local-files.md)。 + +## 2022 年 12月 20 日 + +**常规变更** + +- 将标签 `project name` 添加到 [Datadog](/tidb-cloud/monitor-datadog-integration.md) 仪表盘,作为过滤器以提供项目信息。 + + 您可以使用过滤器 `project name` 快速找到您想要的集群。 + +## 2022 年 12月 13 日 + +**常规变更** + +- 推出 TiDB Cloud SQL 编辑器(Beta)用于 Serverless Tier。 + + 这是一个基于 Web 的 SQL 编辑器,允许您直接编辑和运行针对 Serverless Tier 数据库的 SQL 查询。 您可以在 Serverless Tier 集群的左侧导航栏中轻松找到它。 + + 对于 Serverless Tier,Web SQL Shell 已被 SQL 编辑器取代。 + +- 支持使用 [Changefeeds](/tidb-cloud/changefeed-overview.md) 为 Dedicated Tier 流式传输数据。 + + - 支持 [将数据变更日志流式传输到 MySQL](/tidb-cloud/changefeed-sink-to-mysql.md)。 + + 当数据从 MySQL/Aurora 迁移到 TiDB 时,通常需要使用 MySQL 作为备用数据库,以防止出现意外的数据迁移问题。 在这种情况下,您可以使用 MySQL sink 将数据从 TiDB 流式传输到 MySQL。 + + - 支持 [将数据变更日志流式传输到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md) (Beta)。 + + 将 TiDB 数据流式传输到消息队列是数据集成场景中非常常见的需求。 您可以使用 Kafka sink 来实现与其他数据处理系统(例如 Snowflake)的集成,或者支持业务消费。 + + 有关更多信息,请参阅 [Changefeed 概述](/tidb-cloud/changefeed-overview.md)。 + +- 组织所有者可以在**组织设置**中编辑组织的名称。 + +**控制台变更** + +- 优化 [TiDB Cloud 控制台](https://tidbcloud.com) 的导航布局,为用户提供全新的导航体验。 + + 新布局包括以下更改: + + - 引入左侧导航栏,最大限度地提高屏幕使用效率。 + - 采用更扁平的导航层次结构。 + +- 改善 Serverless Tier 用户的 [**连接**](/tidb-cloud/connect-to-tidb-cluster-serverless.md) 体验。 + + 现在,开发人员只需点击几下,即可连接到 SQL 编辑器或使用他们喜欢的工具,而无需切换上下文。 + +## 2022 年 12月 6 日 + +**常规变更** + +- 将新 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v6.1.2](https://docs.pingcap.com/tidb/stable/release-6.1.2) 升级到 [v6.1.3](https://docs.pingcap.com/tidb/stable/release-6.1.3)。 + +## 2022 年 11月 29 日 + +**常规变更** + +- 改善来自 AWS Marketplace 和 Google Cloud Marketplace 的用户体验。 + + 无论您是 TiDB Cloud 的新用户还是已经拥有 TiDB Cloud 帐户,现在您都可以与您的 AWS 或 GCP 结算帐户关联,从而更轻松地完成 AWS 或 GCP Marketplace 订阅。 + + 有关如何建立关联,请参阅[从 AWS Marketplace 或 Google Cloud Marketplace 结算](/tidb-cloud/tidb-cloud-billing.md#billing-from-aws-marketplace-azure-marketplace-or-google-cloud-marketplace)。 + +## 2022 年 11月 22 日 + +**常规变更** + +* 支持直接将数据从 Amazon Aurora MySQL、Amazon Relational Database Service (RDS) MySQL 或自托管的 MySQL 兼容数据库在线迁移到 TiDB Cloud(beta 版)。 + + 以前,您需要暂停业务并离线导入数据,或者使用第三方工具将数据迁移到 TiDB Cloud,这很复杂。现在,借助 **数据迁移** 功能,您只需在 TiDB Cloud 控制台上执行操作,即可安全地将数据迁移到 TiDB Cloud,且停机时间最短。 + + 此外,数据迁移还提供完整和增量数据迁移功能,可将现有数据和正在进行的更改从数据源迁移到 TiDB Cloud。 + + 目前,数据迁移功能仍处于 **beta 版**。它仅适用于 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群,且仅在 AWS 俄勒冈 (us-west-2) 和 AWS 新加坡 (ap-southeast-1) 区域提供。每个组织可以免费创建一个迁移作业。要为一个组织创建多个迁移作业,您需要[提交工单](/tidb-cloud/tidb-cloud-support.md)。 + + 有关详细信息,请参阅[使用数据迁移将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +## 2022 年 11月 15 日 + +**常规变更** + +* 支持[专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)集群的时间点恢复 (PITR)(测试版)。 + + PITR 支持将任何时间点的数据恢复到新集群。您可以使用它来: + + * 降低灾难恢复中的 RPO。 + * 通过恢复到错误事件发生前的时间点来解决数据写入错误。 + * 审计业务的历史数据。 + + 要使用 PITR 功能,请确保您的 TiDB 集群版本至少为 v6.3.0,并且 TiKV 节点大小至少为 8 个 vCPU 和 16 GiB。 + + 默认情况下,备份数据存储在创建集群的同一区域中。在日本,对于在 GCP 上托管且启用了 PITR 的 TiDB 集群,您可以选择在一个或两个区域(东京和/或大阪)中存储备份数据。从备用区域恢复数据可提供更高的数据安全性,并且可以容忍区域故障。 + + 有关更多信息,请参见[备份和恢复 TiDB 集群数据](/tidb-cloud/backup-and-restore.md)。 + + 此功能仍处于测试阶段,仅应要求提供: + + * 点击 TiDB Cloud 控制台右下角的**帮助**。 + * 在对话框中,在**描述**字段中填写“申请 PITR”,然后点击**发送**。 + +* 数据库审计日志记录功能现已正式发布 (GA)。 + + 您可以使用数据库审计日志记录来记录用户访问详细信息(例如执行的任何 SQL 语句)的历史记录,并定期分析数据库审计日志,这有助于确保数据库的安全。 + + 有关更多信息,请参见[数据库审计日志记录](/tidb-cloud/tidb-cloud-auditing.md)。 + +## 2022 年 11月 8 日 + +**常规变更** + +* 改进用户反馈渠道。 + + 现在您可以在 TiDB Cloud 控制台的**支持** > **提供反馈**中请求演示或信用额度。如果您想了解更多关于 TiDB Cloud 的信息,这将很有帮助。 + + 收到您的请求后,我们将尽快与您联系以提供帮助。 + +## 2022 年 10月 28 日 + +**常规变更** + +* 开发者层级已升级到[无服务器层级](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。无服务器层级是 TiDB 的完全托管、自动伸缩部署,现已可用。它仍处于 Beta 阶段,可免费使用。 + + * 无服务器层级集群仍然包含与专用层级集群完全相同功能的 HTAP 能力。 + * 无服务器层级为您提供更快的集群创建时间和即时冷启动时间。与开发者层级相比,创建时间从几分钟缩短到几秒钟。 + * 您无需担心部署拓扑。无服务器层级将根据您的请求自动调整。 + * 无服务器层级[为了安全起见,强制执行与集群的 TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md)。 + * 现有的开发者层级集群将在未来几个月 内自动迁移到无服务器层级。您使用集群的能力不应受到影响,并且您不会因在 Beta 版中使用无服务器层级集群而被收费。 + + 从[这里](/tidb-cloud/tidb-cloud-quickstart.md)开始。 + +## 2022 年 10月 25 日 + +**常规变更** + +- 支持动态更改和持久化 TiDB 系统变量的子集(beta)。 + + 您可以使用标准 SQL 语句为支持的系统变量设置新值。 + + ```sql + SET [GLOBAL|SESSION] + ``` + + 例如: + + ```sql + SET GLOBAL tidb_committer_concurrency = 127; + ``` + + 如果在 `GLOBAL` 级别设置变量,则该变量将应用于集群并持久化(即使在您重新启动或重新加载服务器后仍保持有效)。`SESSION` 级别的变量不是持久的,仅在当前会话中有效。 + + **此功能仍处于 beta 阶段**,仅支持有限数量的变量。不建议修改其他 [系统变量](/system-variables.md),因为存在不确定性的副作用。请参阅以下列表,了解基于 TiDB v6.1 的所有支持的变量: + + - [`require_secure_transport`](/system-variables.md#require_secure_transport-new-in-v610) + - [`tidb_committer_concurrency`](/system-variables.md#tidb_committer_concurrency-new-in-v610) + - [`tidb_enable_batch_dml`](/system-variables.md#tidb_enable_batch_dml) + - [`tidb_enable_prepared_plan_cache`](/system-variables.md#tidb_enable_prepared_plan_cache-new-in-v610) + - [`tidb_max_tiflash_threads`](/system-variables.md#tidb_max_tiflash_threads-new-in-v610) + - [`tidb_mem_oom_action`](/system-variables.md#tidb_mem_oom_action-new-in-v610) + - [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) + - [`tidb_prepared_plan_cache_size`](/system-variables.md#tidb_prepared_plan_cache_size-new-in-v610) + - [`tidb_query_log_max_len`](/system-variables.md#tidb_query_log_max_len) + +- 将新的 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v6.1.1](https://docs.pingcap.com/tidb/stable/release-6.1.1) 升级到 [v6.1.2](https://docs.pingcap.com/tidb/stable/release-6.1.2)。 + +## 2022 年 10月 19 日 + +**集成变更** + +* 在 [Vercel Integration Marketplace](https://vercel.com/integrations#databases) 中发布 [TiDB Cloud Vercel 集成](https://vercel.com/integrations/tidb-cloud)。 + + [Vercel](https://vercel.com) 是前端开发者的平台,提供创新者所需的快速性和可靠性,以便在灵感迸发时进行创作。 使用 TiDB Cloud Vercel 集成,您可以轻松地将您的 Vercel 项目连接到 TiDB Cloud 集群。 有关详细信息,请参阅文档 [将 TiDB Cloud 与 Vercel 集成](/tidb-cloud/integrate-tidbcloud-with-vercel.md)。 + +* 在 [Vercel 模板列表](https://vercel.com/templates) 中发布 [TiDB Cloud Starter Template](https://vercel.com/templates/next.js/tidb-cloud-starter)。 + + 您可以使用此模板作为尝试 Vercel 和 TiDB Cloud 的起点。 在使用此模板之前,您需要先[将数据导入到您的 TiDB Cloud 集群中](https://github.com/pingcap/tidb-prisma-vercel-demo#2-import-table-structures-and-data)。 + +## 2022 年 10月 18 日 + +**常规变更** + +* 对于专用层集群,TiKV 或 TiFlash 节点的最小存储大小从 500 GiB 更改为 200 GiB。 这对于工作负载数据量较小的用户来说更具成本效益。 + + 有关更多详细信息,请参见 [TiKV 节点存储](/tidb-cloud/size-your-cluster.md#tikv-node-storage-size) 和 [TiFlash 节点存储](/tidb-cloud/size-your-cluster.md#tiflash-node-storage)。 + +* 引入在线合同以自定义 TiDB Cloud 订阅并满足合规性要求。 + + [**合同** 选项卡](/tidb-cloud/tidb-cloud-billing.md#contract) 已添加到 TiDB Cloud 控制台的 **账单** 页面。 如果您已与我们的销售人员就合同达成一致,并收到一封电子邮件以在线处理合同,则可以转到 **合同** 选项卡以查看和接受合同。 要了解有关合同的更多信息,请随时[联系我们的销售](https://www.pingcap.com/contact-us/)。 + +**文档变更** + +* 添加 [文档](/tidb-cloud/terraform-tidbcloud-provider-overview.md) 以用于 [TiDB Cloud Terraform Provider](https://registry.terraform.io/providers/tidbcloud/tidbcloud)。 + + TiDB Cloud Terraform Provider 是一个插件,允许您使用 [Terraform](https://www.terraform.io/) 来管理 TiDB Cloud 资源,例如集群、备份和恢复。 如果您正在寻找一种简单的方法来自动化资源配置和基础架构工作流程,您可以根据 [文档](/tidb-cloud/terraform-tidbcloud-provider-overview.md) 试用 TiDB Cloud Terraform Provider。 + +## 2022 年 10月 11 日 + +**常规变更** + +* 将新的[开发者层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群的默认 TiDB 版本从 [v6.2.0](https://docs-archive.pingcap.com/tidb/v6.2/release-6.2.0) 升级到 [v6.3.0](https://docs-archive.pingcap.com/tidb/v6.3/release-6.3.0)。 + +**控制台变更** + +* 优化[账单详情页](/tidb-cloud/tidb-cloud-billing.md#billing-details)上的账单信息: + + * 在**按服务汇总**部分提供更细粒度的节点级别账单信息。 + * 添加**使用详情**部分。您还可以将使用详情下载为 CSV 文件。 + +## 2022 年 9月 27 日 + +**常规变更** + +* 支持通过邀请加入多个组织。 + + 在 TiDB Cloud 控制台中,您可以查看您已加入的所有组织并在它们之间切换。有关详细信息,请参阅[在组织之间切换](/tidb-cloud/manage-user-access.md#view-and-switch-between-organizations)。 + +* 添加用于 SQL 诊断的[慢查询](/tidb-cloud/tune-performance.md#slow-query)页面。 + + 在“慢查询”页面上,您可以搜索和查看 TiDB 集群中的所有慢查询,并通过查看其[执行计划](https://docs.pingcap.com/tidbcloud/explain-overview)、SQL 执行信息和其他详细信息来探索每个慢查询的瓶颈。 + +* 当您重置帐户密码时,TiDB Cloud 会根据您最近的四个密码检查您的新密码输入,并提醒您避免使用它们中的任何一个。不允许使用任何四个已使用的密码。 + + 有关详细信息,请参阅[密码验证](/tidb-cloud/tidb-cloud-password-authentication.md)。 + +## 2022 年 9月 20 日 + +**常规变更** + +* 为自助服务用户引入[基于成本配额的发票](/tidb-cloud/tidb-cloud-billing.md#invoices)。 + + 当您的成本达到配额时,TiDB Cloud 将生成发票。要提高配额或每月 接收发票,请联系[我们的销售](https://www.pingcap.com/contact-us/)。 + +* 免除数据备份成本中的存储操作费用。 有关最新定价信息,请参阅[TiDB Cloud 定价详情](https://www.pingcap.com/tidb-cloud-pricing-details/)。 + +**控制台变更** + +* 提供用于数据导入的全新 Web UI。 新的 UI 提供更好的用户体验,并使数据导入更加高效。 + + 使用新的 UI,您可以预览要导入的数据,查看导入过程,并轻松管理所有导入任务。 + +**API 变更** + +* TiDB Cloud API(beta)现已向所有用户开放。 + + 您可以通过在 TiDB Cloud 控制台中创建 API 密钥来开始使用 API。 有关更多信息,请参阅[API 文档](/tidb-cloud/api-overview.md)。 + +## 2022 年 9月 15 日 + +**常规变更** + +* 支持通过 TLS 连接到 TiDB Cloud [专用层级](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + + 对于专用层级集群,[连接](/tidb-cloud/connect-via-standard-connection.md)对话框中的**标准连接**选项卡现在提供了一个链接,用于下载 TiDB 集群 CA,并提供 TLS 连接的连接字符串和示例代码。 您可以使用第三方 MySQL 客户端、MyCLI 以及应用程序的多种连接方法(例如 JDBC、Python、Go 和 Node.js)[通过 TLS 连接到您的专用层级集群](/tidb-cloud/connect-via-standard-connection.md)。 此功能可确保从您的应用程序到 TiDB 集群的数据传输安全。 + +## 2022 年 9月 14 日 + +**控制台变更** + +* 优化[集群](https://tidbcloud.com/project/clusters)页面和集群概览页面的UI,以获得更好的用户体验。 + + 在新的设计中,升级到专用层、集群连接和数据导入的入口被突出显示。 + +* 为[开发者层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群引入 Playground。 + + Playground 包含一个预加载的 GitHub 事件数据集,允许您通过立即运行查询来开始使用 TiDB Cloud,而无需导入数据或连接到客户端。 + +## 2022 年 9月 13 日 + +**通用变更** + +* 支持新的 Google Cloud 区域,用于 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群:`N. Virginia (us-east4)`。 + +## 2022 年 9月 9 日 + +**常规变更** + +* 在 Datadog 中提供 Dedicated Tier 集群的[更多指标](/tidb-cloud/monitor-datadog-integration.md#metrics-available-to-datadog),以帮助您更好地了解集群性能状态。 + + 如果您已将 TiDB Cloud 与 [Datadog 集成](/tidb-cloud/monitor-datadog-integration.md),则可以直接在 Datadog 仪表板中查看这些指标。 + +## 2022 年 9月 6 日 + +**通用变更** + +* 将新[专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)集群的默认 TiDB 版本从 [v6.1.0](https://docs.pingcap.com/tidb/stable/release-6.1.0) 升级到 [v6.1.1](https://docs.pingcap.com/tidb/stable/release-6.1.1)。 + +**控制台变更** + +* 现在,您可以从 TiDB Cloud 控制台右上角的入口[申请 PoC](/tidb-cloud/tidb-cloud-poc.md)。 + +**API 变更** + +* 支持通过 [TiDB Cloud API](/tidb-cloud/api-overview.md) 增加 TiKV 或 TiFlash 节点的存储。 您可以使用 API 端点的 `storage_size_gib` 字段进行扩容。 + + 目前,TiDB Cloud API 仍处于 Beta 阶段,仅应要求提供。 + + 有关详细信息,请参阅[修改专用层集群](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster)。 + +## 2022 年 8月 30 日 + +**常规变更** + +* 支持 AWS PrivateLink 驱动的终端节点连接,作为 TiDB Cloud [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的一种新的网络访问管理选项。 + + 终端节点连接是安全且私密的,不会将您的数据暴露给公共互联网。此外,终端节点连接支持 CIDR 重叠,并且更易于网络管理。 + + 有关更多信息,请参阅 [设置私有终端节点连接](/tidb-cloud/set-up-private-endpoint-connections.md)。 + +**控制台变更** + +* 在 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 [连接](/tidb-cloud/connect-to-tidb-cluster.md) 对话框的 **VPC 对等连接** 选项卡和 **私有终端节点** 选项卡中,提供 MySQL、MyCLI、JDBC、Python、Go 和 Node.js 的示例连接字符串。 + + 您只需将连接代码复制并粘贴到您的应用程序中,即可轻松连接到您的专用层集群。 + +## 2022 年 8月 24 日 + +**常规变更** + +* 支持暂停或恢复专用层集群。 + + 您可以在 TiDB Cloud 中[暂停或恢复您的专用层集群](/tidb-cloud/pause-or-resume-tidb-cluster.md)。集群暂停后,节点计算费用将不会被收取。 + +## 2022 年 8月 23 日 + +**常规变更** + +* 将新的[开发者层级](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群的默认 TiDB 版本从 [v6.1.0](https://docs.pingcap.com/tidb/stable/release-6.1.0) 升级到 [v6.2.0](https://docs-archive.pingcap.com/tidb/v6.2/release-6.2.0)。 + +**API 变更** + +* 引入 TiDB Cloud API 作为 beta 版本。 + + 通过此 API,您可以自动高效地管理 TiDB Cloud 资源(例如集群)。 有关更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 + + 目前,TiDB Cloud API 仍处于 beta 阶段,仅应要求提供。 您可以通过提交请求来申请 API 访问权限: + + * 点击 [TiDB Cloud 控制台](https://tidbcloud.com/project/clusters) 右下角的 **帮助**。 + * 在对话框中,在 **描述** 字段中填写“申请 TiDB Cloud API”,然后点击 **发送**。 + +## 2022 年 8月 16 日 + +* 添加 `2 vCPU, 8 GiB (Beta)` 节点大小的 TiDB 和 TiKV 作为 Beta 版本。 + + * 对于每个 `2 vCPU, 8 GiB (Beta)` TiKV 节点,存储大小在 200 GiB 到 500 GiB 之间。 + + * 建议的使用场景: + + * 中小企业的低负载生产环境 + * PoC 和预发布环境 + * 开发环境 + +* 为 PoC 用户引入 [Credits](/tidb-cloud/tidb-cloud-billing.md#credits)(之前称为试用积分)。 + + 现在您可以在**账单**页面的 **Credits** 选项卡上查看有关您组织积分的信息,这些积分可用于支付 TiDB Cloud 费用。 您可以联系我们以获取积分。 + +## 2022 年 8月 9 日 + +* 添加对GCP区域`Osaka`的支持,用于创建[专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)集群。 + +## 2022 年 8月 2 日 + +* TiDB 和 TiKV 的 `4 vCPU, 16 GiB` 节点大小现已正式发布 (GA)。 + + * 对于每个 `4 vCPU, 16 GiB` TiKV 节点,存储大小在 200 GiB 到 2 TiB 之间。 + * 建议的使用场景: + + * 适用于中小企业的低工作负载生产环境 + * PoC 和暂存环境 + * 开发环境 + +* 在 [专用层集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 的 **诊断** 选项卡中添加 [监控页面](/tidb-cloud/built-in-monitoring.md)。 + + 监控页面提供了一个系统级的入口,用于整体性能诊断。根据自上而下的性能分析方法,监控页面根据数据库时间分解组织 TiDB 性能指标,并以不同的颜色显示这些指标。通过检查这些颜色,您可以一目了然地识别整个系统的性能瓶颈,从而大大缩短性能诊断时间,简化性能分析和诊断。 + +* 在 CSV 和 Parquet 源文件的 **数据导入** 页面上添加一个开关,用于启用或禁用 **自定义模式**。 + + **自定义模式** 功能默认禁用。当您要将文件名与特定模式匹配的 CSV 或 Parquet 文件导入到单个目标表时,可以启用它。 + + 有关更多信息,请参阅 [导入 CSV 文件](/tidb-cloud/import-csv-files.md) 和 [导入 Apache Parquet 文件](/tidb-cloud/import-parquet-files.md)。 + +* 添加 TiDB Cloud 支持计划(基本、标准、企业和高级),以满足客户组织的不同支持需求。有关更多信息,请参阅 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +* 优化 [集群](https://tidbcloud.com/project/clusters) 页面和集群详细信息页面的 UI: + + * 在 **集群** 页面上添加 **连接** 和 **导入数据** 按钮。 + * 将 **连接** 和 **导入数据** 按钮移动到集群详细信息页面的右上角。 + +## 2022 年 7月 28 日 + +* 在**安全快速入门**对话框中添加**允许从任何位置访问**按钮,允许任何 IP 地址访问您的集群。 更多信息,请参阅 [配置集群安全设置](/tidb-cloud/configure-security-settings.md)。 + +## 2022 年 7月 26 日 + +* 支持新的[开发者层集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)的自动休眠和恢复。 + + 开发者层集群在不活动 7 天后不会被删除,因此您可以在一年免费试用期结束前的任何时间使用它。 不活动 24 小时后,开发者层集群将自动休眠。 要恢复集群,请向集群发送新连接,或单击 TiDB Cloud 控制台中的**恢复**按钮。 集群将在 50 秒内恢复并自动恢复服务。 + +* 为新的[开发者层集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)添加用户名前缀限制。 + + 无论何时使用或设置数据库用户名,都必须在用户名中包含集群的前缀。 有关更多信息,请参见[用户名前缀](/tidb-cloud/select-cluster-tier.md#user-name-prefix)。 + +* 禁用[开发者层集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)的备份和恢复功能。 + + 开发者层集群禁用备份和恢复功能(包括自动备份和手动备份)。 您仍然可以使用 [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview) 导出数据作为备份。 + +* 将[开发者层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群的存储大小从 500 MiB 增加到 1 GiB。 +* 向 TiDB Cloud 控制台添加面包屑导航,以改善导航体验。 +* 支持在将数据导入 TiDB Cloud 时配置多个过滤规则。 +* 从**项目设置**中删除**流量过滤器**页面,并从**连接到 TiDB** 对话框中删除**从默认集添加规则**按钮。 + +## 2022 年 7月 19 日 + +* 为 [TiKV 节点大小](/tidb-cloud/size-your-cluster.md#tikv-vcpu-and-ram) 提供一个新的选项:`8 vCPU, 32 GiB`。对于一个 8 vCPU 的 TiKV 节点,您可以选择 `8 vCPU, 32 GiB` 或 `8 vCPU, 64 GiB`。 +* 在 [**连接到 TiDB**](/tidb-cloud/connect-via-standard-connection.md) 对话框中提供的示例代码中支持语法高亮,以提高代码的可读性。您可以轻松识别需要在示例代码中替换的参数。 +* 支持在您确认 [**数据导入任务**](/tidb-cloud/import-sample-data.md) 页面上的导入任务后,自动验证 TiDB Cloud 是否可以访问您的源数据。 +* 更改 TiDB Cloud 控制台的主题颜色,使其与 [PingCAP 网站](https://www.pingcap.com/) 的主题颜色保持一致。 + +## 2022 年 7月 12 日 + +* 在 Amazon S3 的 [**数据导入任务**](/tidb-cloud/import-sample-data.md) 页面添加 **Validate** 按钮,帮助您在数据导入开始前检测数据访问问题。 +* 在 [**付款方式**](/tidb-cloud/tidb-cloud-billing.md#payment-method) 选项卡下添加 **账单资料**。 通过在 **账单资料** 中提供您的税务登记号码,某些税款可能会从您的发票中免除。 有关更多信息,请参阅 [编辑账单资料信息](/tidb-cloud/tidb-cloud-billing.md#billing-profile)。 + +## 2022 年 7月 5 日 + +* 列式存储 [TiFlash](/tiflash/tiflash-overview.md) 现已正式发布 (GA)。 + + - TiFlash 使 TiDB 本质上成为混合事务/分析处理 (HTAP) 数据库。您的应用程序数据首先存储在 TiKV 中,然后通过 Raft 共识算法复制到 TiFlash。因此,它是从行存储到列存储的实时复制。 + - 对于具有 TiFlash 副本的表,TiDB 优化器会自动根据成本估算确定是使用 TiKV 还是 TiFlash 副本。 + + 要体验 TiFlash 带来的好处,请参阅 [TiDB Cloud HTAP 快速入门指南](/tidb-cloud/tidb-cloud-htap-quickstart.md)。 + +* 支持[增加 TiKV 和 TiFlash 的存储大小](/tidb-cloud/scale-tidb-cluster.md#change-storage),适用于专用层集群。 +* 支持在节点大小字段中显示内存信息。 + +## 2022 年 6月 28 日 + +* 将 TiDB Cloud Dedicated Tier 从 [TiDB v5.4.1](https://docs.pingcap.com/tidb/stable/release-5.4.1) 升级到 [TiDB v6.1.0](https://docs.pingcap.com/tidb/stable/release-6.1.0)。 + +## 2022 年 6月 23 日 + +* 增加 TiDB Cloud 上 TiKV 的最大[存储容量](/tidb-cloud/size-your-cluster.md#tikv-node-storage-size)。 + + * 8 vCPU 或 16 vCPU TiKV:支持高达 4 TiB 的存储容量。 + * 4 vCPU TiKV:支持高达 2 TiB 的存储容量。 + +## 2022 年 6月 21 日 + +* 为[专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)集群创建添加对GCP区域`台湾`的支持。 +* 支持在TiDB Cloud控制台中[更新用户个人资料](/tidb-cloud/manage-user-access.md#manage-user-profiles),包括名字、姓氏、公司名称、国家和电话号码。 +* 在[**连接到TiDB**](/tidb-cloud/connect-via-standard-connection.md)对话框中提供MySQL、MyCLI、JDBC、Python、Go和Node.js的连接字符串,以便您可以轻松连接到您的TiDB集群。 +* 支持在数据导入期间自动从存储桶URI获取存储桶区域,从而节省您填写此类信息的工作量。 + +## 2022 年 6月 16 日 + +* 简化[集群创建流程](/tidb-cloud/create-tidb-cluster.md)。 + + - 创建集群时,TiDB Cloud 提供默认集群名称。 您可以使用默认名称或更新它。 + - 创建集群时,您无需在**创建集群**页面上设置密码。 + - 在集群创建期间或之后,您可以设置 root 密码以访问集群,并在**安全快速入门**对话框中设置连接到集群的 IP 地址。 + +## 2022 年 6月 14 日 + +* 将 TiDB Cloud 升级到 [TiDB v6.1.0](https://docs.pingcap.com/tidb/stable/release-6.1.0) 以用于开发者层级。 +* 优化 **项目设置** 的入口。 从 TiDB Cloud 控制台,您可以选择一个目标项目,然后点击 **项目设置** 选项卡轻松进入其设置。 +* 通过在 TiDB Cloud 控制台中提供过期消息,优化密码过期的体验。 + +## 2022 年 6月 7 日 + +* 添加 [免费试用](https://tidbcloud.com/free-trial) 注册页面,以便快速注册 TiDB Cloud。 +* 从套餐选择页面移除 **概念验证计划** 选项。 如果您想免费申请 14 天的 PoC 试用,请联系我们。 更多信息,请参见 [使用 TiDB Cloud 执行概念验证 (PoC)](/tidb-cloud/tidb-cloud-poc.md)。 +* 通过提示使用电子邮件和密码注册 TiDB Cloud 的用户每 90 天重置密码来提高系统安全性。 更多信息,请参见 [密码验证](/tidb-cloud/tidb-cloud-password-authentication.md)。 + +## 2022 年 5月 24 日 + +* 支持在[创建](/tidb-cloud/create-tidb-cluster.md)或[恢复](/tidb-cloud/backup-and-restore.md#restore) Dedicated Tier 集群时自定义 TiDB 端口号。 + +## 2022 年 5月 19 日 + +* 为[开发者层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群创建添加对AWS区域`Frankfurt`的支持。 + +## 2022 年 5月 18 日 + +* 支持使用 GitHub 帐户[注册](https://tidbcloud.com/signup) TiDB Cloud。 + +## 2022 年 5月 13 日 + +* 支持使用 Google 账号[注册](https://tidbcloud.com/signup) TiDB Cloud。 + +## 2022 年 5月 1 日 + +* 支持在[创建](/tidb-cloud/create-tidb-cluster.md)或[恢复](/tidb-cloud/backup-and-restore.md#restore)[专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)集群时配置 TiDB、TiKV 和 TiFlash 的 vCPU 大小。 +* 增加对 AWS 区域 `Mumbai` 创建集群的支持。 +* 更新 [TiDB Cloud 账单](/tidb-cloud/tidb-cloud-billing.md)的计算、存储和数据传输成本。 + +## 2022 年 4月 7 日 + +* 将 TiDB Cloud 升级到 [TiDB v6.0.0](https://docs-archive.pingcap.com/tidb/v6.0/release-6.0.0-dmr),用于开发者层。 + +## 2022 年 3月 31 日 + +TiDB Cloud 现在已正式发布 (GA)。 您可以[注册](https://tidbcloud.com/signup)并选择以下选项之一: + +* 免费开始使用 [开发者层级](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。 +* 联系我们 申请 14 天的免费 PoC 试用。 +* 通过 [专用层级](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 获得完全访问权限。 + +## 2022 年 3月 25 日 + +新功能: + +* 支持 [TiDB Cloud 内置告警](/tidb-cloud/monitor-built-in-alerting.md)。 + + 使用 TiDB Cloud 内置告警功能,当您的项目中 TiDB Cloud 集群触发 TiDB Cloud 内置告警条件时,您可以通过电子邮件收到通知。 + +## 2022 年 3月 15 日 + +常规变更: + +* 不再有固定集群大小的集群层级。您可以轻松自定义 TiDB、TiKV 和 TiFlash 的[集群大小](/tidb-cloud/size-your-cluster.md)。 +* 支持为没有 TiFlash 的现有集群添加 [TiFlash](/tiflash/tiflash-overview.md) 节点。 +* 支持在[创建新集群](/tidb-cloud/create-tidb-cluster.md)时指定存储大小(500 到 2048 GiB)。集群创建后,存储大小无法更改。 +* 引入一个新的公共区域:`eu-central-1`。 +* 弃用 8 vCPU TiFlash,并提供 16 vCPU TiFlash。 +* 分离 CPU 和存储的价格(两者都有 30% 的公开预览折扣)。 +* 更新[计费信息](/tidb-cloud/tidb-cloud-billing.md)和[价格表](https://www.pingcap.com/pricing/)。 + +新功能: + +* 支持 [Prometheus 和 Grafana 集成](/tidb-cloud/monitor-prometheus-and-grafana-integration.md)。 + + 通过 Prometheus 和 Grafana 集成,您可以配置一个 [Prometheus](https://prometheus.io/) 服务来从 TiDB Cloud 端点读取关键指标,并使用 [Grafana](https://grafana.com/) 查看这些指标。 + +* 支持根据新集群的所选区域分配默认备份时间。 + + 有关更多信息,请参阅[备份和恢复 TiDB 集群数据](/tidb-cloud/backup-and-restore.md)。 + +## 2022 年 3月 4 日 + +新功能: + +* 支持 [Datadog 集成](/tidb-cloud/monitor-datadog-integration.md)。 + + 通过 Datadog 集成,您可以配置 TiDB Cloud 以将有关 TiDB 集群的指标数据发送到 [Datadog](https://www.datadoghq.com/)。 之后,您可以直接在 Datadog 仪表板中查看这些指标。 + +## 2022 年 2月 15 日 + +常规变更: + +* 将 TiDB Cloud 升级到 [TiDB v5.4.0](https://docs.pingcap.com/tidb/stable/release-5.4.0),适用于开发者层级。 + +改进: + +* 支持在将 [CSV 文件](/tidb-cloud/import-csv-files.md) 或 [Apache Parquet 文件](/tidb-cloud/import-parquet-files.md) 导入到 TiDB Cloud 时使用自定义文件名。 + +## 2022 年 1月 11 日 + +常规变更: + +* 将 TiDB Operator 升级到 [v1.2.6](https://docs.pingcap.com/tidb-in-kubernetes/stable/release-1.2.6)。 + +改进: + +* 在 [**连接**](/tidb-cloud/connect-via-standard-connection.md) 页面上的 MySQL 客户端添加建议选项 `--connect-timeout 15`。 + +Bug 修复: + +* 修复了密码包含单引号时用户无法创建集群的问题。 +* 修复了即使一个组织只有一个所有者,所有者也可以被删除或更改为其他角色的问题。 \ No newline at end of file diff --git a/tidb-cloud/release-notes-2023.md b/tidb-cloud/release-notes-2023.md new file mode 100644 index 000000000000..725240816da1 --- /dev/null +++ b/tidb-cloud/release-notes-2023.md @@ -0,0 +1,1003 @@ +--- +title: 2023 年 TiDB Cloud 发布说明 +summary: 了解 2023 年 TiDB Cloud 的发布说明。 +--- + +# 2023 年 TiDB Cloud 发布说明 + +本页列出了 2023 年 [TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 的发布说明。 + +## 2023 年 12 月 5 日 + +**常规变更** + +- [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 允许您恢复失败的 Changefeed,从而节省您重新创建 Changefeed 的精力。 + + 更多信息,请参见 [Changefeed 状态](/tidb-cloud/changefeed-overview.md#changefeed-states)。 + +**控制台变更** + +- 增强 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 的连接体验。 + + 优化 **连接** 对话框界面,为 TiDB Cloud Serverless 用户提供更流畅、更高效的连接体验。 此外,TiDB Cloud Serverless 引入了更多客户端类型,并允许您选择所需的连接分支。 + + 更多信息,请参见 [连接到 TiDB Cloud Serverless](/tidb-cloud/connect-via-standard-connection-serverless.md)。 + +## 2023 年 11 月 28 日 + +**常规变更** + +- [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 支持从备份恢复 SQL 绑定。 + + TiDB Cloud Dedicated 现在默认在从备份恢复时恢复用户帐户和 SQL 绑定。此增强功能适用于 v6.2.0 或更高版本的集群,从而简化了数据恢复过程。SQL 绑定的恢复确保了与查询相关的配置和优化的顺利重新集成,为您提供更全面、更高效的恢复体验。 + + 有关更多信息,请参阅[备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md)。 + +**控制台变更** + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 支持监控 SQL 语句 RU 成本。 + + TiDB Cloud Serverless 现在提供有关每个 SQL 语句的[请求单元 (RU)](/tidb-cloud/tidb-cloud-glossary.md#request-unit)的详细信息。您可以查看每个 SQL 语句的**总 RU** 和**平均 RU** 成本。此功能可帮助您识别和分析 RU 成本,从而为您的运营提供潜在的成本节省机会。 + + 要查看您的 SQL 语句 RU 详细信息,请导航到[您的 TiDB Cloud Serverless 集群](https://tidbcloud.com/project/clusters)的**诊断**页面,然后单击 **SQL 语句**选项卡。 + +## 2023 年 11 月 21 日 + +**常规变更** + +- [数据迁移](/tidb-cloud/migrate-from-mysql-using-data-migration.md) 支持在 Google Cloud 上部署的 TiDB 集群的高速物理模式。 + + 现在,您可以对部署在 AWS 和 Google Cloud 上的 TiDB 集群使用物理模式。物理模式的迁移速度最高可达 110 MiB/s,比逻辑模式快 2.4 倍。改进后的性能适用于将大型数据集快速迁移到 TiDB Cloud。 + + 有关更多信息,请参阅[迁移现有数据和增量数据](/tidb-cloud/migrate-from-mysql-using-data-migration.md#migrate-existing-data-and-incremental-data)。 + +## 2023 年 11 月 14 日 + +**常规变更** + +- 当您从 TiDB Cloud Dedicated 集群恢复数据时,默认行为现在从不恢复用户帐户修改为恢复所有用户帐户。 + + 更多信息,请参阅 [备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md)。 + +- 引入 changefeed 的事件过滤器。 + + 此增强功能使您能够通过 [TiDB Cloud 控制台](https://tidbcloud.com/) 轻松管理 changefeed 的事件过滤器,从而简化了从 changefeed 中排除特定事件的过程,并更好地控制下游数据复制。 + + 更多信息,请参阅 [Changefeed](/tidb-cloud/changefeed-overview.md#edit-a-changefeed)。 + +## 2023 年 11 月 7 日 + +**常规变更** + +- 添加以下资源使用率警报。 默认情况下,新警报处于禁用状态。 您可以根据需要启用它们。 + + - TiDB 节点的最大内存利用率在 10 分钟内超过 70% + - TiKV 节点的最大内存利用率在 10 分钟内超过 70% + - TiDB 节点的最大 CPU 利用率在 10 分钟内超过 80% + - TiKV 节点的最大 CPU 利用率在 10 分钟内超过 80% + + 有关更多信息,请参阅 [TiDB Cloud 内置警报](/tidb-cloud/monitor-built-in-alerting.md#resource-usage-alerts)。 + +## 2023 年 10 月 31 日 + +**常规变更** + +- 支持在 TiDB Cloud 控制台中直接升级到企业支持计划,无需联系销售。 + + 更多信息,请参见 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +## 2023 年 10 月 25 日 + +**常规变更** + +- [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 支持 Google Cloud 上的双区域备份(beta)。 + + 托管在 Google Cloud 上的 TiDB Cloud Dedicated 集群可以与 Google Cloud Storage 无缝协作。 与 Google Cloud Storage 的 [双区域](https://cloud.google.com/storage/docs/locations#location-dr) 功能类似,您在 TiDB Cloud Dedicated 中用于双区域的区域对必须位于同一多区域内。 例如,东京和大阪位于同一多区域 `ASIA` 中,因此它们可以一起用于双区域存储。 + + 有关更多信息,请参阅 [备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md#turn-on-dual-region-backup)。 + +- [将数据变更日志流式传输到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md) 的功能现已正式发布 (GA)。 + + 经过 10 个月的成功 Beta 试用后,将数据变更日志从 TiDB Cloud 流式传输到 Apache Kafka 的功能已正式发布。 将数据从 TiDB 流式传输到消息队列是数据集成场景中的常见需求。 您可以使用 Kafka sink 与其他数据处理系统(例如 Snowflake)集成或支持业务消费。 + + 有关更多信息,请参阅 [Changefeed 概述](/tidb-cloud/changefeed-overview.md)。 + +## 2023 年 10 月 11 日 + +**常规变更** + +- 支持 [双区域备份 (beta)](/tidb-cloud/backup-and-restore.md#turn-on-dual-region-backup),适用于部署在 AWS 上的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + + 您现在可以在云提供商内的地理区域之间复制备份。此功能提供了一个额外的数据保护层和灾难恢复能力。 + + 更多信息,请参阅 [备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md)。 + +- 数据迁移现在支持物理模式和逻辑模式来迁移现有数据。 + + 在物理模式下,迁移速度可以达到 110 MiB/s。与逻辑模式下的 45 MiB/s 相比,迁移性能得到了显着提高。 + + 更多信息,请参阅 [迁移现有数据和增量数据](/tidb-cloud/migrate-from-mysql-using-data-migration.md#migrate-existing-data-and-incremental-data)。 + +## 2023 年 10 月 10 日 + +**常规变更** + +- 支持在 [Vercel 预览部署](https://vercel.com/docs/deployments/preview-deployments) 中使用 TiDB Cloud Serverless 分支,通过 TiDB Cloud Vercel 集成。 + + 更多信息,请参考 [连接 TiDB Cloud Serverless 分支](/tidb-cloud/integrate-tidbcloud-with-vercel.md#connect-with-tidb-cloud-serverless-branching)。 + +## 2023 年 9 月 28 日 + +**API 变更** + +- 引入 TiDB Cloud 账单 API 端点,用于检索特定组织在给定月份的账单。 + + 此账单 API 端点在 TiDB Cloud API v1beta1 中发布,这是 TiDB Cloud 的最新 API 版本。 有关更多信息,请参阅 [API 文档 (v1beta1)](https://docs.pingcap.com/tidbcloud/api/v1beta1#tag/Billing)。 + +## 2023 年 9 月 19 日 + +**常规变更** + +- 从 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中移除 2 vCPU 的 TiDB 和 TiKV 节点。 + + **创建集群**页面或**修改集群**页面不再提供 2 vCPU 选项。 + +- 发布适用于 JavaScript 的 [TiDB Cloud serverless driver (beta)](/tidb-cloud/serverless-driver.md)。 + + 适用于 JavaScript 的 TiDB Cloud serverless driver 允许您通过 HTTPS 连接到您的 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 它在 TCP 连接受限的边缘环境中特别有用,例如 [Vercel Edge Function](https://vercel.com/docs/functions/edge-functions) 和 [Cloudflare Workers](https://workers.cloudflare.com/)。 + + 有关更多信息,请参阅 [TiDB Cloud serverless driver (beta)](/tidb-cloud/serverless-driver.md)。 + +**控制台变更** + +- 对于 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,您可以在**本月用量**面板中或设置消费限额时获得成本估算。 + +## 2023 年 9 月 5 日 + +**常规变更** + +- [数据服务 (beta)](https://tidbcloud.com/project/data-service) 支持为每个 API 密钥自定义速率限制,以满足不同情况下的特定速率限制要求。 + + 您可以在[创建](/tidb-cloud/data-service-api-key.md#create-an-api-key)或[编辑](/tidb-cloud/data-service-api-key.md#edit-an-api-key)密钥时调整 API 密钥的速率限制。 + + 有关更多信息,请参见[速率限制](/tidb-cloud/data-service-api-key.md#rate-limiting)。 + +- 支持 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的新 AWS 区域:圣保罗 (sa-east-1)。 + +- 支持为每个 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 IP 访问列表添加最多 100 个 IP 地址。 + + 有关更多信息,请参见[配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md)。 + +**控制台变更** + +- 为 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群引入 **Events** 页面,该页面提供集群主要变更的记录。 + + 在此页面上,您可以查看过去 7 天的事件历史记录,并跟踪重要详细信息,例如触发时间和发起操作的用户。 + + 有关更多信息,请参见 [TiDB Cloud 集群事件](/tidb-cloud/tidb-cloud-events.md)。 + +**API 变更** + +- 发布多个 TiDB Cloud API 端点,用于管理 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 [AWS PrivateLink](https://aws.amazon.com/privatelink/?privatelink-blogs.sort-by=item.additionalFields.createdDate&privatelink-blogs.sort-order=desc) 或 [Google Cloud Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect): + + - 为集群创建私有端点服务 + - 检索集群的私有端点服务信息 + - 为集群创建私有端点 + - 列出集群的所有私有端点 + - 列出项目中的所有私有端点 + - 删除集群的私有端点 + + 有关更多信息,请参阅 [API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster)。 + +## 2023 年 8 月 23 日 + +**常规变更** + +- 支持 Google Cloud [Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect),用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + + 现在,您可以创建一个私有端点,并与托管在 Google Cloud 上的 TiDB Cloud Dedicated 集群建立安全连接。 + + 主要优势: + + - 直观的操作:只需几个步骤即可帮助您创建私有端点。 + - 增强的安全性:建立安全连接以保护您的数据。 + - 改进的性能:提供低延迟和高带宽的连接。 + + 有关更多信息,请参见 [通过 Google Cloud 上的私有端点连接](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 + +- 支持使用 Changefeed 将数据从 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群流式传输到 [Google Cloud Storage (GCS)](https://cloud.google.com/storage)。 + + 现在,您可以使用自己的帐户的存储桶并提供精确定制的权限,将数据从 TiDB Cloud 流式传输到 GCS。 将数据复制到 GCS 后,您可以根据需要分析数据中的更改。 + + 有关更多信息,请参见 [Sink to Cloud Storage](/tidb-cloud/changefeed-sink-to-cloud-storage.md)。 + +## 2023 年 8 月 15 日 + +**常规变更** + +- [数据服务(beta)](https://tidbcloud.com/project/data-service) 支持对 `GET` 请求进行分页,以改善开发体验。 + + 对于 `GET` 请求,您可以通过在**高级属性**中启用**分页**,并在调用端点时将 `page` 和 `page_size` 指定为查询参数来对结果进行分页。 例如,要获取每页 10 个项目的第二页,您可以使用以下命令: + + ```bash + curl --digest --user ':' \ + --request GET 'https://.data.tidbcloud.com/api/v1beta/app//endpoint/?page=2&page_size=10' + ``` + + 请注意,此功能仅适用于最后一个查询是 `SELECT` 语句的 `GET` 请求。 + + 有关更多信息,请参见 [调用端点](/tidb-cloud/data-service-manage-endpoint.md#call-an-endpoint)。 + +- [数据服务(beta)](https://tidbcloud.com/project/data-service) 支持缓存 `GET` 请求的端点响应,并指定生存时间 (TTL)。 + + 此功能可降低数据库负载并优化端点延迟。 + + 对于使用 `GET` 请求方法的端点,您可以启用**缓存响应**并在**高级属性**中配置缓存的 TTL 期限。 + + 有关更多信息,请参见 [高级属性](/tidb-cloud/data-service-manage-endpoint.md#advanced-properties)。 + +- 禁用为在 AWS 上托管并在 2023 年 8 月 15 日之后创建的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群进行的负载均衡改进,包括: + + - 当您横向扩展在 AWS 上托管的 TiDB 节点时,禁用自动将现有连接迁移到新的 TiDB 节点。 + - 当您横向缩减在 AWS 上托管的 TiDB 节点时,禁用自动将现有连接迁移到可用的 TiDB 节点。 + + 此更改避免了混合部署的资源争用,并且不会影响已启用此改进的现有集群。 如果您想为新集群启用负载均衡改进,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +## 2023 年 8 月 8 日 + +**常规变更** + +- [数据服务 (beta)](https://tidbcloud.com/project/data-service) 现在支持基本身份验证。 + + 您可以在请求中使用 ['Basic' HTTP 身份验证](https://datatracker.ietf.org/doc/html/rfc7617),并将您的公钥作为用户名,私钥作为密码提供。 与摘要身份验证相比,基本身份验证更简单,可以在调用数据服务端点时实现更直接的用法。 + + 有关更多信息,请参阅 [调用端点](/tidb-cloud/data-service-manage-endpoint.md#call-an-endpoint)。 + +## 2023 年 8 月 1 日 + +**常规变更** + +- 支持 TiDB Cloud 中数据应用的 OpenAPI 规范 [数据服务](https://tidbcloud.com/project/data-service)。 + + TiDB Cloud 数据服务为每个数据应用提供自动生成的 OpenAPI 文档。 在文档中,您可以查看端点、参数和响应,并试用这些端点。 + + 您还可以下载 YAML 或 JSON 格式的数据应用及其已部署端点的 OpenAPI 规范 (OAS)。 OAS 提供标准化的 API 文档、简化的集成和简单的代码生成,从而实现更快的开发和改进的协作。 + + 有关更多信息,请参阅 [使用 OpenAPI 规范](/tidb-cloud/data-service-manage-data-app.md#use-the-openapi-specification) 和 [将 OpenAPI 规范与 Next.js 结合使用](/tidb-cloud/data-service-oas-with-nextjs.md)。 + +- 支持在 [Postman](https://www.postman.com/) 中运行数据应用。 + + Postman 集成使您能够将数据应用的端点作为集合导入到您首选的工作区中。 然后,您可以受益于增强的协作和无缝的 API 测试,并支持 Postman Web 和桌面应用程序。 + + 有关更多信息,请参阅 [在 Postman 中运行数据应用](/tidb-cloud/data-service-postman-integration.md)。 + +- 为 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群引入新的 **暂停中** 状态,允许以经济高效的方式暂停,在此期间不收取任何费用。 + + 当您单击 TiDB Cloud Dedicated 集群的**暂停**时,该集群将首先进入**暂停中**状态。 暂停操作完成后,集群状态将转换为**已暂停**。 + + 只有在集群状态转换为**已暂停**后才能恢复集群,这解决了因快速单击**暂停**和**恢复**而导致的异常恢复问题。 + + 有关更多信息,请参阅 [暂停或恢复 TiDB Cloud Dedicated 集群](/tidb-cloud/pause-or-resume-tidb-cluster.md)。 + +## 2023 年 7 月 26 日 + +**常规变更** + +- 在 TiDB Cloud [数据服务](https://tidbcloud.com/project/data-service) 中引入一项强大的功能:自动端点生成。 + + 开发者现在可以轻松地通过最少的点击和配置来创建 HTTP 端点。 消除重复的样板代码,简化并加速端点创建,并减少潜在的错误。 + + 有关如何使用此功能的更多信息,请参见 [自动生成端点](/tidb-cloud/data-service-manage-endpoint.md#generate-an-endpoint-automatically)。 + +- 支持 TiDB Cloud [数据服务](https://tidbcloud.com/project/data-service) 中端点的 `PUT` 和 `DELETE` 请求方法。 + + - 使用 `PUT` 方法更新或修改数据,类似于 `UPDATE` 语句。 + - 使用 `DELETE` 方法删除数据,类似于 `DELETE` 语句。 + + 有关更多信息,请参见 [配置属性](/tidb-cloud/data-service-manage-endpoint.md#configure-properties)。 + +- 支持 TiDB Cloud [数据服务](https://tidbcloud.com/project/data-service) 中 `POST`、`PUT` 和 `DELETE` 请求方法的**批量操作**。 + + 当为端点启用**批量操作**时,你将能够在单个请求中对多行执行操作。 例如,你可以使用单个 `POST` 请求插入多行数据。 + + 有关更多信息,请参见 [高级属性](/tidb-cloud/data-service-manage-endpoint.md#advanced-properties)。 + +## 2023 年 7 月 25 日 + +**常规变更** + +- 将新的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v6.5.3](https://docs.pingcap.com/tidb/v6.5/release-6.5.3) 升级到 [v7.1.1](https://docs.pingcap.com/tidb/v7.1/release-7.1.1)。 + +**控制台变更** + +- 通过优化支持条目,简化 TiDB Cloud 用户对 PingCAP 支持的访问。改进包括: + + - 在左下角的 中添加 **支持** 入口。 + - 改进 [TiDB Cloud 控制台](https://tidbcloud.com/) 右下角的 **?** 图标的菜单,使其更直观。 + + 更多信息,请参阅 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +## 2023 年 7 月 18 日 + +**常规变更** + +- 优化了组织级别和项目级别的基于角色的访问控制,使您可以向用户授予具有最低权限的角色,从而提高安全性、合规性和生产力。 + + - 组织角色包括 `Organization Owner`、`Organization Billing Admin`、`Organization Console Audit Admin` 和 `Organization Member`。 + - 项目角色包括 `Project Owner`、`Project Data Access Read-Write` 和 `Project Data Access Read-Only`。 + - 要管理项目中的集群(例如集群创建、修改和删除),您需要担任 `Organization Owner` 或 `Project Owner` 角色。 + + 有关不同角色的权限的更多信息,请参阅 [用户角色](/tidb-cloud/manage-user-access.md#user-roles)。 + +- 支持用于在 AWS 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的客户管理的加密密钥 (CMEK) 功能(beta)。 + + 您可以创建基于 AWS KMS 的 CMEK,以直接从 TiDB Cloud 控制台加密存储在 EBS 和 S3 中的数据。这确保了客户数据使用客户管理的密钥进行加密,从而增强了安全性。 + + 请注意,此功能仍有局限性,仅应要求提供。要申请此功能,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +- 优化 TiDB Cloud 中的导入功能,旨在增强数据导入体验。已进行以下改进: + + - 统一 TiDB Cloud Serverless 的导入入口:整合了导入数据的入口,使您可以无缝地在导入本地文件和从 Amazon S3 导入文件之间切换。 + - 简化配置:从 Amazon S3 导入数据现在只需要一个步骤,从而节省了时间和精力。 + - 增强的 CSV 配置:CSV 配置设置现在位于文件类型选项下,使您可以更轻松地快速配置必要的参数。 + - 增强的目标表选择:支持通过单击复选框来选择所需的数据导入目标表。此改进消除了对复杂表达式的需求,并简化了目标表选择。 + - 改进的显示信息:解决了与导入过程中显示的不准确信息相关的问题。此外,已删除“预览”功能,以防止不完整的数据显示并避免误导性信息。 + - 改进的源文件映射:支持定义源文件和目标表之间的映射关系。它解决了修改源文件名以满足特定命名要求的挑战。 + +## 2023 年 7 月 11 日 + +**常规变更** + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 现已正式发布 (Generally Available)。 + +- 推出 TiDB Bot (beta),这是一个由 OpenAI 提供支持的聊天机器人,提供多语言支持、24/7 实时响应和集成的文档访问。 + + TiDB Bot 为您提供以下好处: + + - 持续支持:始终可用以协助和回答您的问题,从而增强支持体验。 + - 提高效率:自动响应减少延迟,从而提高整体运营效率。 + - 无缝文档访问:直接访问 TiDB Cloud 文档,以便轻松检索信息和快速解决问题。 + + 要使用 TiDB Bot,请单击 [TiDB Cloud 控制台](https://tidbcloud.com) 右下角的 **?**,然后选择 **Ask TiDB Bot** 开始聊天。 + +- 支持 [分支功能 (beta)](/tidb-cloud/branch-overview.md),适用于 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 + + TiDB Cloud 允许您为 TiDB Cloud Serverless 集群创建分支。集群的分支是一个独立的实例,其中包含来自原始集群的数据的分叉副本。它提供了一个隔离的环境,允许您连接到它并自由地进行实验,而不必担心影响原始集群。 + + 您可以使用 [TiDB Cloud 控制台](/tidb-cloud/branch-manage.md) 或 [TiDB Cloud CLI](/tidb-cloud/ticloud-branch-create.md) 为 2023 年 7 月 5 日之后创建的 TiDB Cloud Serverless 集群创建分支。 + + 如果您使用 GitHub 进行应用程序开发,则可以将 TiDB Cloud Serverless 分支集成到您的 GitHub CI/CD 管道中,这使您可以自动使用分支测试您的拉取请求,而不会影响生产数据库。有关更多信息,请参见 [将 TiDB Cloud Serverless 分支(Beta)与 GitHub 集成](/tidb-cloud/branch-github-integration.md)。 + +- 支持 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的每周备份。有关更多信息,请参见 [备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup)。 + +## 2023 年 7 月 4 日 + +**常规变更** + +- 支持 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的时间点恢复 (PITR)(测试版)。 + + 现在,您可以将 TiDB Cloud Serverless 集群恢复到过去 90 天内的任何时间点。此功能增强了 TiDB Cloud Serverless 集群的数据恢复能力。例如,当发生数据写入错误并且您想要将数据恢复到较早的状态时,可以使用 PITR。 + + 有关更多信息,请参阅[备份和恢复 TiDB Cloud Serverless 数据](/tidb-cloud/backup-and-restore-serverless.md#restore)。 + +**控制台变更** + +- 增强了 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的集群概览页面上的**本月用量**面板,以提供更清晰的当前资源使用情况视图。 + +- 通过进行以下更改来增强整体导航体验: + + - 将右上角的 **组织** 和 **帐户** 合并到左侧导航栏中。 + - 将左侧导航栏中的 **管理** 合并到左侧导航栏中的 **项目** 中,并删除左上角的 ☰ 悬停菜单。现在,您可以单击 以在项目之间切换并修改项目设置。 + - 将 TiDB Cloud 的所有帮助和支持信息整合到右下角 **?** 图标的菜单中,例如文档、交互式教程、自定进度的培训和支持条目。 + +- TiDB Cloud 控制台现在支持暗黑模式,提供更舒适、更护眼的体验。您可以从左侧导航栏底部在浅色模式和深色模式之间切换。 + +## 2023 年 6 月 27 日 + +**常规变更** + +- 移除为新创建的 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群预置的示例数据集。 + +## 2023 年 6 月 20 日 + +**常规变更** + +- 将新 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v6.5.2](https://docs.pingcap.com/tidb/v6.5/release-6.5.2) 升级到 [v6.5.3](https://docs.pingcap.com/tidb/v6.5/release-6.5.3)。 + +## 2023 年 6 月 13 日 + +**常规变更** + +- 支持使用变更流将数据流式传输到 Amazon S3。 + + 这实现了 TiDB Cloud 和 Amazon S3 之间的无缝集成。它允许从 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群进行实时数据捕获和复制到 Amazon S3,确保下游应用程序和分析可以访问最新的数据。 + + 更多信息,请参见 [Sink to cloud storage](/tidb-cloud/changefeed-sink-to-cloud-storage.md)。 + +- 将 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 16 vCPU TiKV 的最大节点存储从 4 TiB 增加到 6 TiB。 + + 此增强功能增加了 TiDB Cloud Dedicated 集群的数据存储容量,提高了工作负载扩展效率,并满足了不断增长的数据需求。 + + 更多信息,请参见 [Size your cluster](/tidb-cloud/size-your-cluster.md)。 + +- 将 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的[监控指标保留期](/tidb-cloud/built-in-monitoring.md#metrics-retention-policy) 从 3 天延长至 7 天。 + + 通过延长指标保留期,您现在可以访问更多历史数据。 这有助于您识别集群的趋势和模式,从而做出更好的决策并更快地进行故障排除。 + +**控制台变更** + +- 为 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 [**Key Visualizer**](/tidb-cloud/tune-performance.md#key-visualizer) 页面发布新的原生 Web 基础设施。 + + 借助新的基础设施,您可以轻松浏览 **Key Visualizer** 页面,并以更直观和高效的方式访问必要的信息。 新的基础设施还解决了 UX 上的许多问题,使 SQL 诊断过程更加用户友好。 + +## 2023 年 6 月 6 日 + +**常规变更** + +- 为 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群引入 [Index Insight (beta)](/tidb-cloud/index-insight.md),它通过为慢查询提供索引建议来优化查询性能。 + + 借助 Index Insight,您可以通过以下方式提高整体应用程序性能和数据库操作效率: + + - 增强的查询性能:Index Insight 识别慢查询并为其建议适当的索引,从而加快查询执行速度,缩短响应时间并改善用户体验。 + - 成本效益:通过使用 Index Insight 优化查询性能,可以减少对额外计算资源的需求,从而使您能够更有效地利用现有基础设施。 这可能会带来运营成本的节省。 + - 简化的优化过程:Index Insight 简化了索引改进的识别和实施,无需手动分析和猜测。 因此,您可以节省时间和精力,并获得准确的索引建议。 + - 提高应用程序效率:通过使用 Index Insight 优化数据库性能,在 TiDB Cloud 上运行的应用程序可以处理更大的工作负载并同时为更多用户提供服务,从而使应用程序的扩展操作更加高效。 + + 要使用 Index Insight,请导航到 TiDB Cloud Dedicated 集群的**诊断**页面,然后单击 **Index Insight BETA** 选项卡。 + + 有关更多信息,请参见 [使用 Index Insight (beta)](/tidb-cloud/index-insight.md)。 + +- 引入 [TiDB Playground](https://play.tidbcloud.com/?utm_source=docs&utm_medium=tidb_cloud_release_notes),这是一个交互式平台,无需注册或安装即可体验 TiDB 的全部功能。 + + TiDB Playground 是一个交互式平台,旨在为探索 TiDB 的功能(例如可伸缩性、MySQL 兼容性和实时分析)提供一站式体验。 + + 借助 TiDB Playground,您可以在受控环境中实时试用 TiDB 功能,而无需复杂的配置,这使其成为了解 TiDB 功能的理想选择。 + + 要开始使用 TiDB Playground,请转到 [**TiDB Playground**](https://play.tidbcloud.com/?utm_source=docs&utm_medium=tidb_cloud_release_notes) 页面,选择要探索的功能,然后开始您的探索。 + +## 2023 年 6 月 5 日 + +**通用变更** + +- 支持将您的 [数据应用](/tidb-cloud/tidb-cloud-glossary.md#data-app) 连接到 GitHub。 + + 通过 [将您的数据应用连接到 GitHub](/tidb-cloud/data-service-manage-github-connection.md),您可以将数据应用的所有配置作为 GitHub 上的 [代码文件](/tidb-cloud/data-service-app-config-files.md) 进行管理,从而将 TiDB Cloud 数据服务与您的系统架构和 DevOps 流程无缝集成。 + + 借助此功能,您可以轻松完成以下任务,从而改善开发数据应用的 CI/CD 体验: + + - 使用 GitHub 自动部署数据应用更改。 + - 在 GitHub 上使用版本控制配置数据应用更改的 CI/CD 管道。 + - 断开与已连接的 GitHub 存储库的连接。 + - 在部署之前查看端点更改。 + - 查看部署历史记录,并在发生故障时采取必要的措施。 + - 重新部署提交以回滚到较早的部署。 + + 有关更多信息,请参见 [使用 GitHub 自动部署数据应用](/tidb-cloud/data-service-manage-github-connection.md)。 + +## 2023 年 6 月 2 日 + +**常规变更** + +- 为了简化和明确,我们更新了产品的名称: + + - "TiDB Cloud Serverless Tier" 现在称为 "TiDB Cloud Serverless"。 + - "TiDB Cloud Dedicated Tier" 现在称为 "TiDB Cloud Dedicated"。 + - "TiDB On-Premises" 现在称为 "TiDB Self-Managed"。 + + 在这些更新后的名称下享受同样的卓越性能。您的体验是我们的首要任务。 + +## 2023 年 5 月 30 日 + +**常规变更** + +- 增强了 TiDB Cloud 中数据迁移功能对增量数据迁移的支持。 + + 现在,您可以指定一个 binlog 位置或全局事务标识符 (GTID),仅复制指定位置之后生成的增量数据到 TiDB Cloud。此增强功能使您能够更灵活地选择和复制所需的数据,以满足您的特定需求。 + + 有关详细信息,请参阅[使用数据迁移将 MySQL 兼容数据库中的增量数据迁移到 TiDB Cloud](/tidb-cloud/migrate-incremental-data-from-mysql-using-data-migration.md)。 + +- 在 [**事件**](/tidb-cloud/tidb-cloud-events.md) 页面添加了一个新的事件类型 (`ImportData`)。 + +- 从 TiDB Cloud 控制台中移除 **Playground**。 + + 敬请期待具有优化体验的全新独立 Playground。 + +## 2023 年 5 月 23 日 + +**常规变更** + +- 当上传 CSV 文件到 TiDB 时,您不仅可以使用英文字母和数字,还可以使用中文和日文等字符来定义列名。但是,对于特殊字符,仅支持下划线 (`_`)。 + + 有关详细信息,请参阅 [将本地文件导入到 TiDB Cloud](/tidb-cloud/tidb-cloud-import-local-files.md)。 + +## 2023 年 5 月 16 日 + +**控制台变更** + +- 引入按功能类别组织的左侧导航条目,适用于专用层和无服务器层。 + + 新的导航使您更容易、更直观地发现功能条目。要查看新的导航,请访问集群的概览页面。 + +- 为专用层集群的**诊断**页面上的以下两个选项卡发布新的原生 Web 基础设施。 + + - [慢查询](/tidb-cloud/tune-performance.md#slow-query) + - [SQL 语句](/tidb-cloud/tune-performance.md#statement-analysis) + + 借助新的基础设施,您可以轻松浏览这两个选项卡,并以更直观、更高效的方式访问必要的信息。新的基础设施还改善了用户体验,使 SQL 诊断过程更加用户友好。 + +## 2023 年 5 月 9 日 + +**常规变更** + +- 支持更改 2023 年 4 月 26 日之后创建的 GCP 托管集群的节点大小。 + + 借助此功能,您可以升级到更高性能的节点以满足更高的需求,或者降级到更低性能的节点以节省成本。 凭借这种增加的灵活性,您可以调整集群的容量以适应您的工作负载并优化成本。 + + 有关详细步骤,请参阅[更改节点大小](/tidb-cloud/scale-tidb-cluster.md#change-vcpu-and-ram)。 + +- 支持导入压缩文件。 您可以导入以下格式的 CSV 和 SQL 文件:`.gzip`、`.gz`、`.zstd`、`.zst` 和 `.snappy`。 此功能提供了一种更高效且经济高效的数据导入方式,并降低了您的数据传输成本。 + + 有关更多信息,请参阅[将 CSV 文件从云存储导入到 TiDB Cloud Dedicated](/tidb-cloud/import-csv-files.md)和[导入示例数据](/tidb-cloud/import-sample-data.md)。 + +- 支持基于 AWS PrivateLink 的端点连接,作为 TiDB Cloud [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的一种新的网络访问管理选项。 + + 私有端点连接不会将您的数据暴露给公共互联网。 此外,端点连接支持 CIDR 重叠,并且更易于网络管理。 + + 有关更多信息,请参阅[设置私有端点连接](/tidb-cloud/set-up-private-endpoint-connections.md)。 + +**控制台变更** + +- 将新的事件类型添加到[**事件**](/tidb-cloud/tidb-cloud-events.md)页面,以记录 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的备份、恢复和变更数据捕获操作。 + + 要获取可以记录的事件的完整列表,请参阅[已记录的事件](/tidb-cloud/tidb-cloud-events.md#logged-events)。 + +- 在 [**SQL 诊断**](/tidb-cloud/tune-performance.md) 页面上为 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群引入 **SQL 语句** 选项卡。 + + **SQL 语句** 选项卡提供以下内容: + + - 全面概述 TiDB 数据库执行的所有 SQL 语句,使您可以轻松识别和诊断慢查询。 + - 有关每个 SQL 语句的详细信息,例如查询时间、执行计划和数据库服务器响应,帮助您优化数据库性能。 + - 用户友好的界面,可以轻松地对大量数据进行排序、过滤和搜索,使您可以专注于最关键的查询。 + + 有关更多信息,请参阅[语句分析](/tidb-cloud/tune-performance.md#statement-analysis)。 + +## 2023 年 5 月 6 日 + +**常规变更** + +- 支持直接访问 TiDB [Serverless 层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群所在区域的[数据服务终端节点](/tidb-cloud/tidb-cloud-glossary.md#endpoint)。 + + 对于新创建的 Serverless 层集群,终端节点 URL 现在包含集群区域信息。 通过请求区域域名 `.data.tidbcloud.com`,您可以直接访问 TiDB 集群所在区域的终端节点。 + + 或者,您也可以请求全局域名 `data.tidbcloud.com` 而不指定区域。 这样,TiDB Cloud 将在内部将请求重定向到目标区域,但这可能会导致额外的延迟。 如果您选择这种方式,请确保在调用终端节点时将 `--location-trusted` 选项添加到您的 curl 命令中。 + + 有关更多信息,请参阅[调用终端节点](/tidb-cloud/data-service-manage-endpoint.md#call-an-endpoint)。 + +## 2023 年 4 月 25 日 + +**常规变更** + +- 对于您组织中的前五个 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,TiDB Cloud 为每个集群提供如下免费使用配额: + + - 行存储:5 GiB + - [请求单元 (RUs)](/tidb-cloud/tidb-cloud-glossary.md#request-unit):每月 5000 万 RUs + + 在 2023 年 5 月 31 日之前,Serverless Tier 集群仍然免费,享受 100% 折扣。之后,超出免费配额的使用量将被收费。 + + 您可以轻松地在集群**概览**页面的**本月使用量**区域[监控您的集群使用量或增加您的使用配额](/tidb-cloud/manage-serverless-spend-limit.md#manage-spending-limit-for-tidb-cloud-serverless-scalable-clusters)。一旦集群达到免费配额,该集群上的读写操作将被限制,直到您增加配额或在新月份开始时重置使用量。 + + 有关不同资源(包括读取、写入、SQL CPU 和网络出口)的 RU 消耗、定价详情和限制信息的更多信息,请参阅 [TiDB Cloud Serverless Tier 定价详情](https://www.pingcap.com/tidb-cloud-serverless-pricing-details)。 + +- 支持 TiDB Cloud [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的备份和恢复。 + + 有关更多信息,请参阅 [备份和恢复 TiDB 集群数据](/tidb-cloud/backup-and-restore-serverless.md)。 + +- 将新的 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v6.5.1](https://docs.pingcap.com/tidb/v6.5/release-6.5.1) 升级到 [v6.5.2](https://docs.pingcap.com/tidb/v6.5/release-6.5.2)。 + +- 提供维护窗口功能,使您能够轻松地为 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群安排和管理计划的维护活动。 + + 维护窗口是指定的时间段,在此期间会自动执行计划的维护活动,例如操作系统更新、安全补丁和基础设施升级,以确保 TiDB Cloud 服务的可靠性、安全性和性能。 + + 在维护窗口期间,可能会发生临时连接中断或 QPS 波动,但集群仍然可用,并且 SQL 操作、现有数据导入、备份、恢复、迁移和复制任务仍然可以正常运行。请参阅维护期间[允许和禁止的操作列表](/tidb-cloud/configure-maintenance-window.md#allowed-and-disallowed-operations-during-a-maintenance-window)。 + + 我们将努力尽量减少维护频率。如果计划了维护窗口,则默认开始时间为目标周的星期三 03:00(基于您的 TiDB Cloud 组织的时区)。为避免潜在的中断,重要的是要注意维护计划并相应地计划您的操作。 + + - 为了让您了解情况,TiDB Cloud 将为每个维护窗口向您发送三封电子邮件通知:一封在维护任务之前,一封在维护任务开始时,一封在维护任务之后。 + - 为了最大限度地减少维护影响,您可以在**维护**页面上将维护开始时间修改为您首选的时间或推迟维护活动。 + + 有关更多信息,请参阅 [配置维护窗口](/tidb-cloud/configure-maintenance-window.md)。 + +- 改进 TiDB 的负载均衡,并减少在扩展 AWS 上托管并在 2023 年 4 月 25 日之后创建的 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 TiDB 节点时连接断开的情况。 + + - 支持在扩展 TiDB 节点时自动将现有连接迁移到新的 TiDB 节点。 + - 支持在缩减 TiDB 节点时自动将现有连接迁移到可用的 TiDB 节点。 + + 目前,此功能适用于 AWS 上托管的所有 Dedicated Tier 集群。 + +**控制台变更** + +- 为 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 [监控](/tidb-cloud/built-in-monitoring.md#view-the-metrics-page) 页面发布新的原生 Web 基础设施。 + + 借助新的基础设施,您可以轻松浏览[监控](/tidb-cloud/built-in-monitoring.md#view-the-metrics-page)页面,并以更直观和高效的方式访问必要的信息。新的基础设施还解决了 UX 上的许多问题,使监控过程更加用户友好。 + +## 2023 年 4 月 18 日 + +**常规变更** + +- 支持为[专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)集群向上或向下扩展[数据迁移作业规格](/tidb-cloud/tidb-cloud-billing-dm.md#specifications-for-data-migration)。 + + 使用此功能,您可以通过向上扩展规格来提高迁移性能,或者通过向下扩展规格来降低成本。 + + 有关更多信息,请参阅[使用数据迁移将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md#scale-a-migration-job-specification)。 + +**控制台变更** + +- 改进了 UI,使[集群创建](https://tidbcloud.com/clusters/create-cluster)体验更加用户友好,使您只需点击几下即可创建和配置集群。 + + 新设计侧重于简洁性,减少视觉混乱并提供清晰的说明。 在集群创建页面上单击**创建**后,您将被定向到集群概览页面,而无需等待集群创建完成。 + + 有关更多信息,请参阅[创建集群](/tidb-cloud/create-tidb-cluster.md)。 + +- 在**账单**页面上引入**折扣**选项卡,以显示组织所有者和账单管理员的折扣信息。 + + 有关更多信息,请参阅[折扣](/tidb-cloud/tidb-cloud-billing.md#discounts)。 + +## 2023 年 4 月 11 日 + +**常规变更** + +- 提高 TiDB 的负载均衡,并减少在 AWS 上托管的 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群扩展 TiDB 节点时连接断开的情况。 + + - 支持在横向扩展 TiDB 节点时,自动将现有连接迁移到新的 TiDB 节点。 + - 支持在横向缩减 TiDB 节点时,自动将现有连接迁移到可用的 TiDB 节点。 + + 目前,此功能仅适用于托管在 AWS `俄勒冈 (us-west-2)` 区域的专用层集群。 + +- 支持 [New Relic](https://newrelic.com/) 集成,用于 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + + 通过 New Relic 集成,您可以配置 TiDB Cloud 将 TiDB 集群的指标数据发送到 [New Relic](https://newrelic.com/)。 然后,您可以在 [New Relic](https://newrelic.com/) 上监控和分析您的应用程序性能和 TiDB 数据库性能。 此功能可以帮助您快速识别和排除潜在问题,并缩短解决时间。 + + 有关集成步骤和可用指标,请参阅 [将 TiDB Cloud 与 New Relic 集成](/tidb-cloud/monitor-new-relic-integration.md)。 + +- 将以下 [changefeed](/tidb-cloud/changefeed-overview.md) 指标添加到专用层集群的 Prometheus 集成中。 + + - `tidbcloud_changefeed_latency` + - `tidbcloud_changefeed_replica_rows` + + 如果您已 [将 TiDB Cloud 与 Prometheus 集成](/tidb-cloud/monitor-prometheus-and-grafana-integration.md),则可以使用这些指标实时监控 changefeed 的性能和健康状况。 此外,您可以轻松创建警报以使用 Prometheus 监控指标。 + +**控制台变更** + +- 更新 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 [监控](/tidb-cloud/built-in-monitoring.md#view-the-metrics-page) 页面,以使用 [节点级资源指标](/tidb-cloud/built-in-monitoring.md#server)。 + + 通过节点级资源指标,您可以更准确地了解资源消耗情况,从而更好地了解所购买服务的实际使用情况。 + + 要访问这些指标,请导航到集群的 [监控](/tidb-cloud/built-in-monitoring.md#view-the-metrics-page) 页面,然后选中 **指标** 选项卡下的 **服务器** 类别。 + +- 通过重新组织 **按项目汇总** 和 **按服务汇总** 中的计费项目来优化 [计费](/tidb-cloud/tidb-cloud-billing.md#billing-details) 页面,这使得计费信息更加清晰。 + +## 2023 年 4 月 4 日 + +**常规变更** + +- 从 [TiDB Cloud 内置告警](/tidb-cloud/monitor-built-in-alerting.md#tidb-cloud-built-in-alert-conditions) 中删除以下两个告警,以防止误报。 这是因为一个节点上的临时离线或内存不足 (OOM) 问题不会显着影响集群的整体健康状况。 + + - 集群中至少有一个 TiDB 节点内存不足。 + - 一个或多个集群节点处于离线状态。 + +**控制台变更** + +- 为 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群引入 [告警](/tidb-cloud/monitor-built-in-alerting.md) 页面,其中列出了每个专用层集群的活动和已关闭告警。 + + **告警** 页面提供以下内容: + + - 直观且用户友好的用户界面。 即使您没有订阅告警通知电子邮件,也可以在此页面上查看集群的告警。 + - 高级筛选选项,可帮助您根据告警的严重性、状态和其他属性快速查找和排序告警。 它还允许您查看过去 7 天的历史数据,从而简化了告警历史记录的跟踪。 + - **编辑规则** 功能。 您可以自定义告警规则设置以满足集群的特定需求。 + + 有关更多信息,请参阅 [TiDB Cloud 内置告警](/tidb-cloud/monitor-built-in-alerting.md)。 + +- 将 TiDB Cloud 的帮助相关信息和操作整合到一个位置。 + + 现在,您可以通过单击 [TiDB Cloud 控制台](https://tidbcloud.com/) 右下角的 **?** 来获取所有 [TiDB Cloud 帮助信息](/tidb-cloud/tidb-cloud-support.md) 并联系支持。 + +- 引入 [入门](https://tidbcloud.com/getting-started) 页面,以帮助您了解 TiDB Cloud。 + + **入门** 页面为您提供交互式教程、基本指南和有用的链接。 通过遵循交互式教程,您可以轻松地使用预构建的行业特定数据集(Steam 游戏数据集和 S&P 500 数据集)探索 TiDB Cloud 功能和 HTAP 功能。 + + 要访问 **入门** 页面,请单击 [TiDB Cloud 控制台](https://tidbcloud.com/) 左侧导航栏中的 **入门**。 在此页面上,您可以单击 **查询示例数据集** 以打开交互式教程,或单击其他链接以探索 TiDB Cloud。 或者,您可以单击右下角的 **?**,然后单击 **交互式教程**。 + +## 2023 年 3 月 29 日 + +**常规变更** + +- [数据服务 (beta)](/tidb-cloud/data-service-overview.md) 支持对数据应用进行更细粒度的访问控制。 + + 在数据应用详情页面,现在您可以将集群链接到您的数据应用,并为每个 API 密钥指定角色。该角色控制 API 密钥是否可以读取或写入链接集群的数据,并且可以设置为 `ReadOnly` 或 `ReadAndWrite`。此功能为数据应用提供集群级别和权限级别的访问控制,使您可以更灵活地根据业务需求控制访问范围。 + + 有关更多信息,请参阅 [管理链接的集群](/tidb-cloud/data-service-manage-data-app.md#manage-linked-data-sources) 和 [管理 API 密钥](/tidb-cloud/data-service-api-key.md)。 + +## 2023 年 3 月 28 日 + +**常规变更** + +- 为 [changefeeds](/tidb-cloud/changefeed-overview.md) 添加 2 RCUs、4 RCUs 和 8 RCUs 规格,并支持在 [创建 changefeed](/tidb-cloud/changefeed-overview.md#create-a-changefeed) 时选择所需的规格。 + + 与之前需要 16 RCUs 的场景相比,使用这些新规格,数据复制成本最多可降低 87.5%。 + +- 支持扩展或缩小 2023 年 3 月 28 日之后创建的 [changefeeds](/tidb-cloud/changefeed-overview.md) 的规格。 + + 您可以通过选择更高的规格来提高复制性能,或通过选择更低的规格来降低复制成本。 + + 有关更多信息,请参阅 [缩放 changefeed](/tidb-cloud/changefeed-overview.md#scale-a-changefeed)。 + +- 支持将 AWS 中 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中的增量数据实时复制到同一项目和同一区域中的 [无服务器层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 + + 有关更多信息,请参阅 [Sink to TiDB Cloud](/tidb-cloud/changefeed-sink-to-tidb-cloud.md)。 + +- 为 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 [数据迁移](/tidb-cloud/migrate-from-mysql-using-data-migration.md) 功能支持两个新的 GCP 区域:`Singapore (asia-southeast1)` 和 `Oregon (us-west1)`。 + + 有了这些新区域,您可以有更多选择将数据迁移到 TiDB Cloud。如果您的上游数据存储在这些区域中或附近,您现在可以利用从 GCP 到 TiDB Cloud 更快、更可靠的数据迁移。 + + 有关更多信息,请参阅 [使用数据迁移将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +**控制台变更** + +- 为 [无服务器层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的 [慢查询](/tidb-cloud/tune-performance.md#slow-query) 页面发布新的原生 Web 基础设施。 + + 借助这种新的基础设施,您可以轻松地浏览 [慢查询](/tidb-cloud/tune-performance.md#slow-query) 页面,并以更直观、更高效的方式访问必要的信息。 新的基础设施还解决了 UX 上的许多问题,使 SQL 诊断过程更加用户友好。 + +## 2023 年 3 月 21 日 + +**常规变更** + +- 针对 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,引入 [Data Service (beta)](https://tidbcloud.com/project/data-service),使您能够通过使用自定义 API 端点的 HTTPS 请求来访问数据。 + + 借助 Data Service,您可以将 TiDB Cloud 与任何兼容 HTTPS 的应用程序或服务无缝集成。以下是一些常见场景: + + - 直接从移动或 Web 应用程序访问 TiDB 集群的数据库。 + - 使用 Serverless 边缘函数调用端点,避免数据库连接池导致的可扩展性问题。 + - 通过使用 Data Service 作为数据源,将 TiDB Cloud 与数据可视化项目集成。 + - 从 MySQL 接口不支持的环境连接到您的数据库。 + + 此外,TiDB Cloud 还提供 [Chat2Query API](/tidb-cloud/use-chat2query-api.md),这是一个 RESTful 接口,允许您使用 AI 生成和执行 SQL 语句。 + + 要访问 Data Service,请导航到左侧导航窗格中的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面。有关更多信息,请参阅以下文档: + + - [Data Service 概述](/tidb-cloud/data-service-overview.md) + - [Data Service 入门](/tidb-cloud/data-service-get-started.md) + - [Chat2Query API 入门](/tidb-cloud/use-chat2query-api.md) + +- 支持减小 TiDB、TiKV 和 TiFlash 节点的大小,以在 AWS 上托管且在 2022 年 12 月 31 日之后创建的 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中进行缩容。 + + 您可以[通过 TiDB Cloud 控制台](/tidb-cloud/scale-tidb-cluster.md#change-vcpu-and-ram)或[通过 TiDB Cloud API (beta)](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) 减小节点大小。 + +- 为 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 [Data Migration](/tidb-cloud/migrate-from-mysql-using-data-migration.md) 功能支持新的 GCP 区域:`Tokyo (asia-northeast1)`。 + + 该功能可以帮助您轻松高效地将 Google Cloud Platform (GCP) 中与 MySQL 兼容的数据库中的数据迁移到您的 TiDB 集群。 + + 有关更多信息,请参阅 [使用 Data Migration 将与 MySQL 兼容的数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +**控制台变更** + +- 为 [Dedicated Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群引入 **Events** 页面,该页面提供对集群的主要更改的记录。 + + 在此页面上,您可以查看过去 7 天的事件历史记录,并跟踪重要详细信息,例如触发时间和发起操作的用户。例如,您可以查看集群何时暂停或谁修改了集群大小等事件。 + + 有关更多信息,请参阅 [TiDB Cloud 集群事件](/tidb-cloud/tidb-cloud-events.md)。 + +- 将 **Database Status** 选项卡添加到 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的 **Monitoring** 页面,该页面显示以下数据库级别指标: + + - 每个数据库的 QPS + - 每个数据库的平均查询持续时间 + - 每个数据库的失败查询 + + 通过这些指标,您可以监控各个数据库的性能,做出数据驱动的决策,并采取措施来提高应用程序的性能。 + + 有关更多信息,请参阅 [Serverless Tier 集群的监控指标](/tidb-cloud/built-in-monitoring.md)。 + +## 2023 年 3 月 14 日 + +**常规变更** + +- 将新 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v6.5.0](https://docs.pingcap.com/tidb/v6.5/release-6.5.0) 升级到 [v6.5.1](https://docs.pingcap.com/tidb/v6.5/release-6.5.1)。 + +- 支持在上传带有标题行的本地 CSV 文件时,修改 TiDB Cloud 创建的目标表的列名。 + + 当将带有标题行的本地 CSV 文件导入到 [Serverless 层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群时,如果您需要 TiDB Cloud 创建目标表,并且标题行中的列名不符合 TiDB Cloud 列命名约定,您将在相应列名旁边看到一个警告图标。要解决此警告,您可以将光标移到图标上,然后按照消息编辑现有列名或输入新的列名。 + + 有关列命名约定的信息,请参阅 [导入本地文件](/tidb-cloud/tidb-cloud-import-local-files.md#import-local-files)。 + +## 2023 年 3 月 7 日 + +**通用变更** + +- 将所有[Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群的默认 TiDB 版本从 [v6.4.0](https://docs.pingcap.com/tidb/v6.4/release-6.4.0) 升级到 [v6.6.0](https://docs.pingcap.com/tidb/v6.6/release-6.6.0)。 + +## 2023 年 2 月 28 日 + +**常规变更** + +- 为[Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)集群添加[SQL诊断](/tidb-cloud/tune-performance.md)功能。 + + 通过SQL诊断,您可以深入了解与SQL相关的运行时状态,从而更有效地进行SQL性能调优。目前,Serverless Tier的SQL诊断功能仅提供慢查询数据。 + + 要使用SQL诊断,请单击Serverless Tier集群页面左侧导航栏上的**SQL诊断**。 + +**控制台变更** + +- 优化左侧导航。 + + 您可以更高效地浏览页面,例如: + + - 您可以将鼠标悬停在左上角以快速切换集群或项目。 + - 您可以在**集群**页面和**管理**页面之间切换。 + +**API变更** + +- 发布了多个用于数据导入的TiDB Cloud API端点: + + - 列出所有导入任务 + - 获取导入任务 + - 创建导入任务 + - 更新导入任务 + - 上传导入任务的本地文件 + - 在启动导入任务之前预览数据 + - 获取导入任务的角色信息 + + 有关更多信息,请参阅[API文档](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Import)。 + +## 2023 年 2 月 22 日 + +**常规变更** + +- 支持使用 [控制台审计日志](/tidb-cloud/tidb-cloud-console-auditing.md) 功能来跟踪组织成员在 [TiDB Cloud 控制台](https://tidbcloud.com/) 中执行的各种活动。 + + 控制台审计日志功能仅对具有 `Owner` 或 `Audit Admin` 角色的用户可见,并且默认情况下处于禁用状态。要启用它,请单击 **组织** > **控制台审计日志**,位于 [TiDB Cloud 控制台](https://tidbcloud.com/) 的右上角。 + + 通过分析控制台审计日志,您可以识别组织内执行的可疑操作,从而提高组织资源和数据的安全性。 + + 有关更多信息,请参阅 [控制台审计日志](/tidb-cloud/tidb-cloud-console-auditing.md)。 + +**CLI 变更** + +- 为 [TiDB Cloud CLI](/tidb-cloud/cli-reference.md) 添加了一个新命令 `ticloud cluster connect-info`。 + + `ticloud cluster connect-info` 是一个允许您获取集群连接字符串的命令。要使用此命令,请[更新 `ticloud`](/tidb-cloud/ticloud-upgrade.md) 到 v0.3.2 或更高版本。 + +## 2023 年 2 月 21 日 + +**常规变更** + +- 支持使用 IAM 用户的 AWS 访问密钥来访问您的 Amazon S3 存储桶,以便将数据导入到 TiDB Cloud。 + + 此方法比使用角色 ARN 更简单。有关更多信息,请参阅 [配置 Amazon S3 访问](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)。 + +- 将 [监控指标保留期限](/tidb-cloud/built-in-monitoring.md#metrics-retention-policy) 从 2 天延长到更长的时间: + + - 对于专用层集群,您可以查看过去 7 天的指标数据。 + - 对于无服务器层集群,您可以查看过去 3 天的指标数据。 + + 通过延长指标保留期限,您现在可以访问更多历史数据。这有助于您识别集群的趋势和模式,从而更好地进行决策和更快地进行故障排除。 + +**控制台变更** + +- 在 [无服务器层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的监控页面上发布新的原生 Web 基础设施。 + + 借助新的基础设施,您可以轻松浏览监控页面,并以更直观和高效的方式访问必要的信息。新的基础设施还解决了 UX 上的许多问题,使监控过程更加用户友好。 + +## 2023 年 2 月 17 日 + +**CLI 变更** + +- 添加一个新命令 [`ticloud connect`](/tidb-cloud/ticloud-serverless-shell.md) 用于 [TiDB Cloud CLI](/tidb-cloud/cli-reference.md)。 + + `ticloud connect` 是一个允许你从本地机器连接到你的 TiDB Cloud 集群而无需安装任何 SQL 客户端的命令。 连接到你的 TiDB Cloud 集群后,你可以在 TiDB Cloud CLI 中执行 SQL 语句。 + +## 2023 年 2 月 14 日 + +**常规变更** + +- 支持减少 TiKV 和 TiFlash 节点数量,以在 TiDB [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中进行缩容。 + + 您可以通过 [TiDB Cloud 控制台](/tidb-cloud/scale-tidb-cluster.md#change-node-number) 或 [通过 TiDB Cloud API (beta)](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) 减少节点数量。 + +**控制台变更** + +- 为 [Serverless 层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群引入 **监控** 页面。 + + **监控** 页面提供了一系列指标和数据,例如每秒执行的 SQL 语句数量、查询的平均持续时间以及失败的查询数量,这有助于您更好地了解 Serverless 层集群中 SQL 语句的整体性能。 + + 有关更多信息,请参阅 [TiDB Cloud 内置监控](/tidb-cloud/built-in-monitoring.md)。 + +## 2023 年 2 月 2 日 + +**CLI 变更** + +- 引入 TiDB Cloud CLI 客户端 [`ticloud`](/tidb-cloud/cli-reference.md)。 + + 使用 `ticloud`,您可以通过几行命令从终端或其他自动工作流程轻松管理您的 TiDB Cloud 资源。 特别是对于 GitHub Actions,我们提供了 [`setup-tidbcloud-cli`](https://github.com/marketplace/actions/set-up-tidbcloud-cli),以便您轻松设置 `ticloud`。 + + 有关更多信息,请参阅 [TiDB Cloud CLI 快速入门](/tidb-cloud/get-started-with-cli.md) 和 [TiDB Cloud CLI 参考](/tidb-cloud/cli-reference.md)。 + +## 2023 年 1 月 18 日 + +**常规变更** + +* 支持使用 Microsoft 帐户[注册](https://tidbcloud.com/free-trial) TiDB Cloud。 + +## 2023 年 1 月 17 日 + +**常规变更** + +- 将新 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v6.1.3](https://docs.pingcap.com/tidb/stable/release-6.1.3) 升级到 [v6.5.0](https://docs.pingcap.com/tidb/stable/release-6.5.0)。 + +- 对于新注册用户,TiDB Cloud 将自动创建一个免费的 [Serverless 层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,以便您可以快速开始使用 TiDB Cloud 进行数据探索之旅。 + +- 为 [专用层](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群支持一个新的 AWS 区域:`Seoul (ap-northeast-2)`。 + + 此区域启用了以下功能: + + - [使用数据迁移将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md) + - [使用变更数据捕获将数据从 TiDB Cloud 流式传输到其他数据服务](/tidb-cloud/changefeed-overview.md) + - [备份和恢复 TiDB 集群数据](/tidb-cloud/backup-and-restore.md) + +## 2023 年 1 月 10 日 + +**常规变更** + +- 优化了从本地 CSV 文件导入数据到 TiDB 的功能,以改善 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的用户体验。 + + - 要上传 CSV 文件,现在您可以简单地将其拖放到 **导入** 页面上的上传区域。 + - 创建导入任务时,如果目标数据库或表不存在,您可以输入一个名称,让 TiDB Cloud 自动为您创建。 对于要创建的目标表,您可以指定主键或选择多个字段以形成复合主键。 + - 导入完成后,您可以通过单击 **通过 Chat2Query 探索您的数据** 或单击任务列表中的目标表名,使用 [AI 驱动的 Chat2Query](/tidb-cloud/explore-data-with-chat2query.md) 探索您的数据。 + + 有关更多信息,请参见 [将本地文件导入到 TiDB Cloud](/tidb-cloud/tidb-cloud-import-local-files.md)。 + +**控制台变更** + +- 为每个集群添加 **获取支持** 选项,以简化请求特定集群支持的过程。 + + 您可以通过以下任一方式请求集群支持: + + - 在项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面上,单击集群所在行的 **...**,然后选择 **获取支持**。 + - 在集群概览页面上,单击右上角的 **...**,然后选择 **获取支持**。 + +## 2023 年 1 月 5 日 + +**控制台变更** + +- 将 SQL 编辑器(beta)重命名为 Chat2Query(beta),适用于 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,并支持使用 AI 生成 SQL 查询。 + + 在 Chat2Query 中,您可以让 AI 自动生成 SQL 查询,或者手动编写 SQL 查询,并在没有终端的情况下针对数据库运行 SQL 查询。 + + 要访问 Chat2Query,请转到项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面,点击您的集群名称,然后在左侧导航窗格中点击 **Chat2Query**。 + +## 2023 年 1 月 4 日 + +**常规变更** + +- 支持通过增加在 AWS 上托管且在 2022 年 12 月 31 日之后创建的 TiDB Cloud Dedicated 集群的 **节点大小(vCPU + RAM)** 来扩展 TiDB、TiKV 和 TiFlash 节点。 + + 您可以使用 [TiDB Cloud 控制台](/tidb-cloud/scale-tidb-cluster.md#change-vcpu-and-ram) 或 [TiDB Cloud API (beta)](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) 来增加节点大小。 + +- 将 [**监控**](/tidb-cloud/built-in-monitoring.md) 页面上的指标保留期限延长至两天。 + + 现在您可以访问过去两天的指标数据,从而更灵活地了解集群性能和趋势。 + + 此改进无需额外费用,可以在集群的 [**监控**](/tidb-cloud/built-in-monitoring.md) 页面的 **诊断** 选项卡上访问。 这将帮助您识别和排除性能问题,并更有效地监控集群的整体健康状况。 + +- 支持为 Prometheus 集成自定义 Grafana 仪表板 JSON。 + + 如果您已将 [TiDB Cloud 与 Prometheus 集成](/tidb-cloud/monitor-prometheus-and-grafana-integration.md),您现在可以导入预构建的 Grafana 仪表板来监控 TiDB Cloud 集群,并根据您的需要自定义仪表板。 此功能可以轻松快速地监控您的 TiDB Cloud 集群,并帮助您快速识别任何性能问题。 + + 有关更多信息,请参阅 [使用 Grafana GUI 仪表板可视化指标](/tidb-cloud/monitor-prometheus-and-grafana-integration.md#step-3-use-grafana-gui-dashboards-to-visualize-the-metrics)。 + +- 将所有 [Serverless Tier](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的默认 TiDB 版本从 [v6.3.0](https://docs.pingcap.com/tidb/v6.3/release-6.3.0) 升级到 [v6.4.0](https://docs.pingcap.com/tidb/v6.4/release-6.4.0)。 将 Serverless Tier 集群的默认 TiDB 版本升级到 v6.4.0 后,冷启动问题已得到解决。 + +**控制台变更** + +- 简化 [**集群**](https://tidbcloud.com/project/clusters) 页面和集群概览页面的显示。 + + - 您可以单击 [**集群**](https://tidbcloud.com/project/clusters) 页面上的集群名称以进入集群概览页面并开始操作集群。 + - 从集群概览页面中删除 **连接** 和 **导入** 窗格。 您可以单击右上角的 **连接** 以获取连接信息,然后单击左侧导航窗格中的 **导入** 以导入数据。 diff --git a/tidb-cloud/release-notes-2024.md b/tidb-cloud/release-notes-2024.md new file mode 100644 index 000000000000..dfad4ba53c9b --- /dev/null +++ b/tidb-cloud/release-notes-2024.md @@ -0,0 +1,471 @@ +--- +title: 2024 年 TiDB Cloud 发布说明 +summary: 了解 2024 年 TiDB Cloud 的发布说明。 +--- + +# 2024 年 TiDB Cloud 发布说明 + +此页面列出了 2024 年 [TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 的发布说明。 + +## 2024 年 12 月 17 日 + +**常规变更** + +- TiDB Cloud Serverless 备份和恢复变更 + + - 支持将数据恢复到新集群,提供更大的灵活性,并确保您当前集群的运营不受中断。 + + - 优化备份和恢复策略,使其与您的集群计划保持一致。 更多信息,请参见 [备份和恢复 TiDB Cloud Serverless 数据](/tidb-cloud/backup-and-restore-serverless.md#learn-about-the-backup-setting)。 + + - 应用以下兼容性策略,以帮助您顺利过渡: + + - 在 2024-12-17T10:00:00Z 之前创建的备份将在所有集群中遵循之前的保留期限。 + - 可扩展集群的备份时间将保留当前配置,而免费集群的备份时间将重置为默认设置。 + +## 2024 年 12 月 3 日 + +**通用变更** + +- 推出恢复组功能(beta),用于在 AWS 上部署的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的灾难恢复。 + + 此功能使您能够在 TiDB Cloud Dedicated 集群之间复制数据库,从而确保在发生区域性灾难时能够快速恢复。如果您是项目所有者角色,则可以通过创建新的恢复组并将数据库分配给该组来启用此功能。通过使用恢复组复制数据库,您可以提高灾难准备能力,满足更严格的可用性 SLA,并实现更积极的恢复点目标 (RPO) 和恢复时间目标 (RTO)。 + + 有关更多信息,请参阅 [恢复组入门](/tidb-cloud/recovery-group-get-started.md)。 + +## 2024 年 11 月 26 日 + +**通用变更** + +- 将新 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v7.5.4](https://docs.pingcap.com/tidb/v7.5/release-7.5.4) 升级到 [v8.1.1](https://docs.pingcap.com/tidb/stable/release-8.1.1)。 + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 将以下场景下的大数据写入成本降低高达 80%: + + - 当你在 [自动提交模式](/transaction-overview.md#autocommit) 下执行大于 16 MiB 的写入操作时。 + - 当你在 [乐观事务模型](/optimistic-transaction.md) 下执行大于 16 MiB 的写入操作时。 + - 当你 [将数据导入到 TiDB Cloud](/tidb-cloud/tidb-cloud-migration-overview.md#import-data-from-files-to-tidb-cloud) 时。 + + 此改进提高了数据操作的效率和成本效益,随着工作负载的扩展,可提供更大的节省。 + +## 2024 年 11 月19 日 + +**常规变更** + +- [TiDB Cloud Serverless 分支(beta)](/tidb-cloud/branch-overview.md) 引入了以下分支管理方面的改进: + + - **灵活的分支创建**:创建分支时,您可以选择特定的集群或分支作为父级,并指定要从父级使用的精确时间点。这使您可以精确控制分支中的数据。 + + - **分支重置**:您可以重置分支,使其与父级的最新状态同步。 + + - **改进的 GitHub 集成**:[TiDB Cloud Branching](https://github.com/apps/tidb-cloud-branching) GitHub App 引入了 [`branch.mode`](/tidb-cloud/branch-github-integration.md#branchmode) 参数,该参数控制拉取请求同步期间的行为。在默认模式 `reset` 下,该应用程序会重置分支以匹配拉取请求中的最新更改。 + + 有关更多信息,请参阅[管理 TiDB Cloud Serverless 分支](/tidb-cloud/branch-manage.md)和[将 TiDB Cloud Serverless 分支(Beta)与 GitHub 集成](/tidb-cloud/branch-github-integration.md)。 + +## 2024 年 11 月 12 日 + +**常规变更** + +- 为 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群添加暂停时长限制。 + + TiDB Cloud Dedicated 现在限制最大暂停时长为 7 天。如果您未在 7 天内手动恢复集群,TiDB Cloud 将自动恢复它。 + + 此更改仅适用于**2024 年 11 月 12 日之后创建的组织**。在此日期或之前创建的组织将逐步过渡到新的暂停行为,并会事先收到通知。 + + 有关更多信息,请参阅 [暂停或恢复 TiDB Cloud Dedicated 集群](/tidb-cloud/pause-or-resume-tidb-cluster.md)。 + +- [Datadog 集成(beta)](/tidb-cloud/monitor-datadog-integration.md) 增加了对新区域的支持:`AP1`(日本)。 + +- 支持 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的一个新的 AWS 区域:`孟买 (ap-south-1)`。 + +- 移除对 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 AWS `圣保罗 (sa-east-1)` 区域的支持。 + +## 2024 年 10 月 29 日 + +**常规变更** + +- 新增指标:为 Prometheus 集成添加 `tidbcloud_changefeed_checkpoint_ts`。 + + 此指标跟踪 changefeed 的检查点时间戳,表示成功写入下游的最大 TSO(时间戳预言机)。 有关可用指标的更多信息,请参阅 [将 TiDB Cloud 与 Prometheus 和 Grafana 集成(Beta)](/tidb-cloud/monitor-prometheus-and-grafana-integration.md#metrics-available-to-prometheus)。 + +## 2024 年 10 月 22 日 + +**常规变更** + +- 将新 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v7.5.3](https://docs.pingcap.com/tidb/v7.5/release-7.5.3) 升级到 [v7.5.4](https://docs.pingcap.com/tidb/v7.5/release-7.5.4)。 + +## 2024 年 10 月 15 日 + +**API 变更** + +* [MSP](https://docs.pingcap.com/tidbcloud/api/v1beta1/msp) 自 2024 年 10 月 15 日起已弃用,并将在未来移除。如果您目前正在使用 MSP API,请迁移到 [TiDB Cloud Partner](https://partner-console.tidbcloud.com/signin) 中的 Partner Management API。 + +## 2024 年 9 月 24 日 + +**通用变更** + +- 为在 AWS 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群提供新的 [TiFlash vCPU 和 RAM 大小](/tidb-cloud/size-your-cluster.md#tiflash-vcpu-and-ram):`32 vCPU, 128 GiB` + +**CLI 变更** + +- 发布 [TiDB Cloud CLI v1.0.0-beta.2](https://github.com/tidbcloud/tidbcloud-cli/releases/tag/v1.0.0-beta.2)。 + + TiDB Cloud CLI 提供以下新功能: + + - 支持通过 [`ticloud serverless sql-user`](/tidb-cloud/ticloud-serverless-sql-user-create.md) 管理 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的 SQL 用户。 + - 允许在 [`ticloud serverless create`](/tidb-cloud/ticloud-cluster-create.md) 和 [`ticloud serverless update`](/tidb-cloud/ticloud-serverless-update.md) 中禁用 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的公共端点。 + - 添加 [`ticloud auth whoami`](/tidb-cloud/ticloud-auth-whoami.md) 命令,在使用 OAuth 身份验证时获取有关当前用户的信息。 + - 在 [`ticloud serverless export create`](/tidb-cloud/ticloud-serverless-export-create.md) 中支持 `--sql`、`--where` 和 `--filter` 标志,以灵活地选择源表。 + - 支持将数据导出到 CSV 和 Parquet 文件。 + - 支持使用角色 ARN 作为凭据将数据导出到 Amazon S3,并且还支持导出到 Google Cloud Storage 和 Azure Blob Storage。 + - 支持从 Amazon S3、Google Cloud Storage 和 Azure Blob Storage 导入数据。 + - 支持从分支和特定时间戳创建分支。 + + TiDB Cloud CLI 增强了以下功能: + + - 改进调试日志记录。现在它可以记录凭据和 user-agent。 + - 将本地导出文件下载速度从每秒数十 KiB 提高到每秒数十 MiB。 + + TiDB Cloud CLI 替换或删除了以下功能: + + - [`ticloud serverless export create`](/tidb-cloud/ticloud-serverless-export-create.md) 中的 `--s3.bucket-uri` 标志被 `--s3.uri` 替换。 + - [`ticloud serverless export create`](/tidb-cloud/ticloud-serverless-export-create.md) 中删除了 `--database` 和 `--table` 标志。相反,您可以使用 `--sql`、`--where` 和 `--filter` 标志。 + - [`ticloud serverless update`](/tidb-cloud/ticloud-serverless-update.md) 无法再更新 annotations 字段。 + +## 2024 年 9 月 10 日 + +**常规变更** + +- 发布 TiDB Cloud 合作伙伴 Web 控制台和 Open API,以增强 TiDB Cloud 合作伙伴的资源和账单管理。 + + 通过 AWS Marketplace Channel Partner Private Offer (CPPO) 的托管服务提供商 (MSP) 和经销商现在可以利用 [TiDB Cloud 合作伙伴 Web 控制台](https://partner-console.tidbcloud.com/) 和 Open API 来简化他们的日常运营。 + + 有关更多信息,请参阅 [TiDB Cloud 合作伙伴 Web 控制台](/tidb-cloud/tidb-cloud-partners.md)。 + +## 2024 年 9 月 3 日 + +**控制台变更** + +- 支持使用 [TiDB Cloud 控制台](https://tidbcloud.com/) 从 TiDB Cloud Serverless 集群导出数据。 + + 此前,TiDB Cloud 仅支持使用 [TiDB Cloud CLI](/tidb-cloud/cli-reference.md) 导出数据。现在,您可以轻松地将 TiDB Cloud Serverless 集群中的数据导出到本地文件和 Amazon S3,通过 [TiDB Cloud 控制台](https://tidbcloud.com/)。 + + 有关更多信息,请参阅 [从 TiDB Cloud Serverless 导出数据](/tidb-cloud/serverless-export.md) 和 [为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md)。 + +- 增强 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的连接体验。 + + - 修改 **连接** 对话框界面,为 TiDB Cloud Dedicated 用户提供更精简高效的连接体验。 + - 引入新的集群级别 **网络** 页面,以简化集群的网络配置。 + - 将 **安全设置** 页面替换为新的 **密码设置** 页面,并将 IP 访问列表设置移至新的 **网络** 页面。 + + 有关更多信息,请参阅 [连接到 TiDB Cloud Dedicated](/tidb-cloud/connect-to-tidb-cluster.md)。 + +- 增强 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 和 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的数据导入体验: + + - 使用更清晰的布局优化 **导入** 页面的布局。 + - 统一 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 集群的导入步骤。 + - 简化 AWS Role ARN 创建过程,以便更轻松地进行连接设置。 + + 有关更多信息,请参阅 [从文件导入数据到 TiDB Cloud](/tidb-cloud/tidb-cloud-migration-overview.md#import-data-from-files-to-tidb-cloud)。 + +## 2024 年 8 月 20 日 + +**控制台变更** + +- 优化了**创建私有终端节点连接**页面的布局,以改善在 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中创建新的私有终端节点连接的用户体验。 + + 更多信息,请参考 [通过 AWS 私有终端节点连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections.md) 和 [通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 + +## 2024 年 8 月 6 日 + +**通用变更** + +- [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 在 AWS 上负载均衡的计费变更。 + + 从 2024 年 8 月 1 日起,TiDB Cloud Dedicated 的账单将包含新的 AWS 公共 IPv4 地址费用,与 [AWS 自 2024 年 2 月 1 日起生效的定价变更](https://aws.amazon.com/blogs/aws/new-aws-public-ipv4-address-charge-public-ip-insights/)保持一致。 每个公共 IPv4 地址的费用为每小时 0.005 美元,这将导致每个托管在 AWS 上的 TiDB Cloud Dedicated 集群每月大约 10 美元。 + + 此费用将显示在您[账单详情](/tidb-cloud/tidb-cloud-billing.md#billing-details)中现有的 **TiDB Cloud Dedicated - 数据传输 - 负载均衡** 服务下。 + +- 将新的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v7.5.2](https://docs.pingcap.com/tidb/v7.5/release-7.5.2) 升级到 [v7.5.3](https://docs.pingcap.com/tidb/v7.5/release-7.5.3)。 + +**控制台变更** + +- 增强 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 的集群大小配置体验。 + + 优化 [**创建集群**](/tidb-cloud/create-tidb-cluster.md) 和 [**修改集群**](/tidb-cloud/scale-tidb-cluster.md) 页面上 TiDB Cloud Dedicated 集群的 **集群大小** 部分的布局。 此外,**集群大小** 部分现在包含指向节点大小推荐文档的链接,这有助于您选择合适的集群大小。 + +## 2024 年 7 月 23 日 + +**常规变更** + +- [数据服务(beta)](https://tidbcloud.com/project/data-service) 支持自动生成向量搜索端点。 + + 如果您的表包含[向量数据类型](/tidb-cloud/vector-search-data-types.md),您可以自动生成一个向量搜索端点,该端点会根据您选择的距离函数计算向量距离。 + + 此功能实现了与 AI 平台(例如 [Dify](https://docs.dify.ai/guides/tools) 和 [GPTs](https://openai.com/blog/introducing-gpts))的无缝集成,通过先进的自然语言处理和 AI 功能增强您的应用程序,从而实现更复杂的任务和智能解决方案。 + + 有关更多信息,请参阅[自动生成端点](/tidb-cloud/data-service-manage-endpoint.md#generate-an-endpoint-automatically)和[将数据应用与第三方工具集成](/tidb-cloud/data-service-integrations.md)。 + +- 引入预算功能,帮助您跟踪 TiDB Cloud 的实际成本与计划支出,防止意外成本。 + + 要访问此功能,您必须是您组织的 `Organization Owner` 或 `Organization Billing Admin` 角色。 + + 有关更多信息,请参阅[管理 TiDB Cloud 的预算](/tidb-cloud/tidb-cloud-budget.md)。 + +## 2024 年 7 月 9 日 + +**通用变更** + +- 增强了[系统状态](https://status.tidbcloud.com/)页面,以提供对 TiDB Cloud 系统健康和性能的更好洞察。 + + 要访问它,请直接访问 ,或者通过 [TiDB Cloud 控制台](https://tidbcloud.com) 导航,方法是单击右下角的 **?** 并选择 **系统状态**。 + +**控制台变更** + +- 优化了 **VPC 对等连接** 页面布局,以改善在 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中[创建 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)的用户体验。 + +## 2024 年 7 月 2 日 + +**通用变更** + +- [数据服务(beta)](https://tidbcloud.com/project/data-service) 提供了一个端点库,其中包含预定义的系统端点,您可以直接将其添加到您的数据应用中,从而减少端点开发的工作量。 + + 目前,该库仅包含 `/system/query` 端点,您只需在预定义的 `sql` 参数中传递 SQL 语句即可执行任何 SQL 语句。 此端点有助于立即执行 SQL 查询,从而提高灵活性和效率。 + + 有关更多信息,请参阅 [添加预定义的系统端点](/tidb-cloud/data-service-manage-endpoint.md#add-a-predefined-system-endpoint)。 + +- 增强慢查询数据存储。 + + [TiDB Cloud 控制台](https://tidbcloud.com)上的慢查询访问现在更加稳定,并且不会影响数据库性能。 + +## 2024 年 6 月 25 日 + +**通用变更** + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 支持向量搜索(beta)。 + + 向量搜索(beta)功能提供了一种高级搜索解决方案,用于跨各种数据类型(包括文档、图像、音频和视频)执行语义相似性搜索。 此功能使开发人员能够使用熟悉的 MySQL 技能轻松构建具有生成式人工智能 (AI) 功能的可扩展应用程序。 主要功能包括: + + - [向量数据类型](/tidb-cloud/vector-search-data-types.md)、[向量索引](/tidb-cloud/vector-search-index.md) 和 [向量函数和运算符](/tidb-cloud/vector-search-functions-and-operators.md)。 + - 与 [LangChain](/tidb-cloud/vector-search-integrate-with-langchain.md)、[LlamaIndex](/tidb-cloud/vector-search-integrate-with-llamaindex.md) 和 [JinaAI](/tidb-cloud/vector-search-integrate-with-jinaai-embedding.md) 的生态系统集成。 + - Python 的编程语言支持:[SQLAlchemy](/tidb-cloud/vector-search-integrate-with-sqlalchemy.md)、[Peewee](/tidb-cloud/vector-search-integrate-with-peewee.md) 和 [Django ORM](/tidb-cloud/vector-search-integrate-with-django-orm.md)。 + - 示例应用程序和教程:使用 [Python](/tidb-cloud/vector-search-get-started-using-python.md) 或 [SQL](/tidb-cloud/vector-search-get-started-using-sql.md) 对文档执行语义搜索。 + + 有关更多信息,请参阅 [向量搜索(beta)概述](/tidb-cloud/vector-search-overview.md)。 + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 现在为组织所有者提供每周电子邮件报告。 + + 这些报告提供了有关集群性能和活动的见解。 通过接收自动每周更新,您可以随时了解集群的信息,并做出数据驱动的决策来优化集群。 + +- 发布 Chat2Query API v3 端点并弃用 Chat2Query API v1 端点 `/v1/chat2data`。 + + 使用 Chat2Query API v3 端点,您可以使用会话启动多轮 Chat2Query。 + + 有关更多信息,请参阅 [Chat2Query API 入门](/tidb-cloud/use-chat2query-api.md)。 + +**控制台变更** + +- 将 Chat2Query(beta)重命名为 SQL Editor(beta)。 + + 先前称为 Chat2Query 的界面已重命名为 SQL Editor。 此更改阐明了手动 SQL 编辑和 AI 辅助查询生成之间的区别,从而增强了可用性和您的整体体验。 + + - **SQL Editor**:用于在 TiDB Cloud 控制台中手动编写和执行 SQL 查询的默认界面。 + - **Chat2Query**:AI 辅助的文本到查询功能,使您能够使用自然语言与数据库进行交互,以生成、重写和优化 SQL 查询。 + + 有关更多信息,请参阅 [使用 AI 辅助的 SQL Editor 探索您的数据](/tidb-cloud/explore-data-with-chat2query.md)。 + +## 2024 年 6 月 18 日 + +**常规变更** + +- 将 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 16 vCPU TiFlash 和 32 vCPU TiFlash 的最大节点存储从 2048 GiB 增加到 4096 GiB。 + + 此增强功能提高了 TiDB Cloud Dedicated 集群的分析数据存储容量,提高了工作负载的扩展效率,并满足了不断增长的数据需求。 + + 有关更多信息,请参阅 [TiFlash 节点存储](/tidb-cloud/size-your-cluster.md#tiflash-node-storage)。 + +- 将新的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v7.5.1](https://docs.pingcap.com/tidb/v7.5/release-7.5.1) 升级到 [v7.5.2](https://docs.pingcap.com/tidb/v7.5/release-7.5.2)。 + +## 2024 年 6 月 4 日 + +**通用变更** + +- 推出恢复组功能(beta),用于在 AWS 上部署的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的灾难恢复。 + + 此功能使您能够在 TiDB Cloud Dedicated 集群之间复制数据库,从而确保在发生区域性灾难时快速恢复。如果您具有 `Project Owner` 角色,则可以通过创建新的恢复组并将数据库分配给该组来启用此功能。通过使用恢复组复制数据库,您可以提高灾难准备能力,满足更严格的可用性 SLA,并实现更积极的恢复点目标 (RPO) 和恢复时间目标 (RTO)。 + + 有关更多信息,请参阅 [恢复组入门](/tidb-cloud/recovery-group-get-started.md)。 + +- 推出 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 列式存储 [TiFlash](/tiflash/tiflash-overview.md) 的计费和计量(beta)。 + + 在 2024 年 6 月 30 日之前,TiDB Cloud Serverless 集群中的列式存储仍然免费,享受 100% 的折扣。在此日期之后,每个 TiDB Cloud Serverless 集群将包含 5 GiB 的免费列式存储配额。超出免费配额的使用将收费。 + + 有关更多信息,请参阅 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-serverless-pricing-details/#storage)。 + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 支持 [生存时间 (TTL)](/time-to-live.md)。 + +## 2024 年 5 月 28 日 + +**常规变更** + +- Google Cloud `台湾 (asia-east1)` 区域支持 [数据迁移](/tidb-cloud/migrate-from-mysql-using-data-migration.md) 功能。 + + 托管在 Google Cloud `台湾 (asia-east1)` 区域的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群现在支持数据迁移 (DM) 功能。如果您的上游数据存储在该区域或附近,您现在可以利用更快、更可靠的数据迁移,从 Google Cloud 迁移到 TiDB Cloud。 + +- 为托管在 AWS 和 Google Cloud 上的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群提供新的 [TiDB 节点大小](/tidb-cloud/size-your-cluster.md#tidb-vcpu-and-ram):`16 vCPU, 64 GiB` + +**API 变更** + +- 引入 TiDB Cloud Data Service API,用于自动高效地管理以下资源: + + * **Data App (数据应用)**:一组端点,您可以使用这些端点来访问特定应用程序的数据。 + * **Data Source (数据源)**:链接到数据应用以进行数据操作和检索的集群。 + * **Endpoint (端点)**:一个 Web API,您可以自定义它来执行 SQL 语句。 + * **Data API Key (数据 API 密钥)**:用于安全地访问端点。 + * **OpenAPI Specification (OpenAPI 规范)**:Data Service 支持为每个数据应用生成 OpenAPI 规范 3.0,使您能够以标准化格式与您的端点进行交互。 + + 这些 TiDB Cloud Data Service API 端点在 TiDB Cloud API v1beta1 中发布,这是 TiDB Cloud 的最新 API 版本。 + + 有关更多信息,请参阅 [API 文档 (v1beta1)](https://docs.pingcap.com/tidbcloud/api/v1beta1/dataservice)。 + +## 2024 年 5 月 21 日 + +**常规变更** + +- 为在 Google Cloud 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群提供一个新的 [TiDB 节点大小](/tidb-cloud/size-your-cluster.md#tidb-vcpu-and-ram):`8 vCPU, 16 GiB` + +## 2024 年 5 月 14 日 + +**通用变更** + +- 扩展了[**时区**](/tidb-cloud/manage-user-access.md#set-the-time-zone-for-your-organization)部分中的时区选择,以更好地适应来自不同地区的客户。 + +- 支持[创建VPC对等连接](/tidb-cloud/set-up-vpc-peering-connections.md),即使您的VPC与TiDB Cloud的VPC位于不同的区域。 + +- [数据服务 (beta)](https://tidbcloud.com/project/data-service) 除了查询参数外,还支持路径参数。 + + 此功能通过结构化 URL 增强了资源识别,并改善了用户体验、搜索引擎优化 (SEO) 和客户端集成,为开发人员提供了更大的灵活性和与行业标准的更好对齐。 + + 有关更多信息,请参阅[基本属性](/tidb-cloud/data-service-manage-endpoint.md#basic-properties)。 + +## 2024 年 4 月 16 日 + +**CLI 变更** + +- 推出 [TiDB Cloud CLI 1.0.0-beta.1](https://github.com/tidbcloud/tidbcloud-cli),构建于新的 [TiDB Cloud API](/tidb-cloud/api-overview.md) 之上。 新的 CLI 带来了以下新功能: + + - [从 TiDB Cloud Serverless 集群导出数据](/tidb-cloud/serverless-export.md) + - [将本地存储中的数据导入到 TiDB Cloud Serverless 集群](/tidb-cloud/ticloud-import-start.md) + - [通过 OAuth 认证](/tidb-cloud/ticloud-auth-login.md) + - [通过 TiDB Bot 提问](/tidb-cloud/ticloud-ai.md) + + 在升级您的 TiDB Cloud CLI 之前,请注意这个新的 CLI 与之前的版本不兼容。 例如,CLI 命令中的 `ticloud cluster` 现在更新为 `ticloud serverless`。 更多信息,请参阅 [TiDB Cloud CLI 参考](/tidb-cloud/cli-reference.md)。 + +## 2024 年 4 月 9 日 + +**通用变更** + +- 为托管在 AWS 上的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群提供一个新的 [TiDB 节点大小](/tidb-cloud/size-your-cluster.md#tidb-vcpu-and-ram): `8 vCPU, 32 GiB`。 + +## 2024 年 4 月 2 日 + +**通用变更** + +- 为 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群引入两种服务计划:**免费** 和 **可扩展**。 + + 为了满足不同的用户需求,TiDB Cloud Serverless 提供免费和可扩展的服务计划。无论您是刚开始使用还是扩展以满足不断增长的应用程序需求,这些计划都能提供您需要的灵活性和功能。 + + 更多信息,请参阅 [集群计划](/tidb-cloud/select-cluster-tier.md#cluster-plans)。 + +- 修改 TiDB Cloud Serverless 集群达到其使用配额时的限流行为。现在,一旦集群达到其使用配额,它会立即拒绝任何新的连接尝试,从而确保现有操作的不间断服务。 + + 更多信息,请参阅 [使用配额](/tidb-cloud/serverless-limitations.md#usage-quota)。 + +## 2024 年 3 月 5 日 + +**通用变更** + +- 将新 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v7.5.0](https://docs.pingcap.com/tidb/v7.5/release-7.5.0) 升级到 [v7.5.1](https://docs.pingcap.com/tidb/v7.5/release-7.5.1)。 + +**控制台变更** + +- 在 [**账单**](https://tidbcloud.com/org-settings/billing/payments) 页面引入 **成本探索器** 标签,该标签提供了一个直观的界面,用于分析和自定义您组织随时间的成本报告。 + + 要使用此功能,请导航到您组织的 **账单** 页面,然后单击 **成本探索器** 标签。 + + 有关更多信息,请参见 [成本探索器](/tidb-cloud/tidb-cloud-billing.md#cost-explorer)。 + +- [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 为 [节点级资源指标](/tidb-cloud/built-in-monitoring.md#server) 显示 **limit** 标签。 + + **limit** 标签显示集群中每个组件的 CPU、内存和存储等资源的最大使用量。此增强功能简化了监控集群资源使用率的过程。 + + 要访问这些指标限制,请导航到集群的 **监控** 页面,然后查看 **指标** 选项卡下的 **服务器** 类别。 + + 有关更多信息,请参见 [TiDB Cloud Dedicated 集群的指标](/tidb-cloud/built-in-monitoring.md#server)。 + +## 2024 年 2 月 21 日 + +**常规变更** + +- 将 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的 TiDB 版本从 [v6.6.0](https://docs.pingcap.com/tidb/v6.6/release-6.6.0) 升级到 [v7.1.3](https://docs.pingcap.com/tidb/v7.1/release-7.1.3)。 + +## 2024 年 2 月 20 日 + +**通用变更** + +- 支持在 Google Cloud 上创建更多 TiDB Cloud 节点。 + + - 通过为 Google Cloud [配置区域 CIDR 大小](/tidb-cloud/set-up-vpc-peering-connections.md#prerequisite-set-a-cidr-for-a-region) 为 `/19`,您现在可以在项目的任何区域内创建最多 124 个 TiDB Cloud 节点。 + - 如果您想在项目的任何区域中创建超过 124 个节点,您可以联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md),以获得定制 IP 范围大小(范围从 `/16` 到 `/18`)的帮助。 + +## 2024 年 1 月 23 日 + +**常规变更** + +- 为 TiDB、TiKV 和 TiFlash 添加 32 vCPU 作为节点大小选项。 + + 对于每个 `32 vCPU, 128 GiB` 的 TiKV 节点,节点存储范围从 200 GiB 到 6144 GiB。 + + 建议在以下场景中使用此类节点: + + - 高负载生产环境 + - 极高性能 + +## 2024 年 1 月 16 日 + +**常规变更** + +- 增强了项目的 CIDR 配置。 + + - 您可以直接为每个项目设置区域级别的 CIDR。 + - 您可以从更广泛的 CIDR 值范围中选择您的 CIDR 配置。 + + 注意:先前项目的全局级别 CIDR 设置已停用,但所有处于活动状态的现有区域 CIDR 均不受影响。现有集群的网络不会受到影响。 + + 有关更多信息,请参阅[为区域设置 CIDR](/tidb-cloud/set-up-vpc-peering-connections.md#prerequisite-set-a-cidr-for-a-region)。 + +- TiDB Cloud Serverless 用户现在可以禁用集群的公共端点。 + + 有关更多信息,请参阅[禁用公共端点](/tidb-cloud/connect-via-standard-connection-serverless.md#disable-a-public-endpoint)。 + +- [数据服务 (beta)](https://tidbcloud.com/project/data-service) 支持配置自定义域名以访问数据应用中的端点。 + + 默认情况下,TiDB Cloud 数据服务提供域名 `.data.tidbcloud.com` 以访问每个数据应用的端点。为了增强个性化和灵活性,您现在可以为您的数据应用配置自定义域名,而不是使用默认域名。此功能使您能够为您的数据库服务使用品牌 URL 并增强安全性。 + + 有关更多信息,请参阅[数据服务中的自定义域名](/tidb-cloud/data-service-custom-domain.md)。 + +## 2024 年 1 月 3 日 + +**常规变更** + +- 支持[组织单点登录 (SSO)](https://tidbcloud.com/org-settings/authentication),以简化企业身份验证流程。 + + 借助此功能,您可以使用[安全断言标记语言 (SAML)](https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language) 或 [OpenID Connect (OIDC)](https://openid.net/developers/how-connect-works/) 将 TiDB Cloud 与任何身份提供商 (IdP) 无缝集成。 + + 有关更多信息,请参阅[组织单点登录身份验证](/tidb-cloud/tidb-cloud-org-sso-authentication.md)。 + +- 将新 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v7.1.1](https://docs.pingcap.com/tidb/v7.1/release-7.1.1) 升级到 [v7.5.0](https://docs.pingcap.com/tidb/v7.5/release-7.5.0)。 + +- [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 的双区域备份功能现已正式发布 (GA)。 + + 通过使用此功能,您可以在 AWS 或 Google Cloud 内的地理区域之间复制备份。 此功能提供了额外的数据保护层和灾难恢复能力。 + + 有关更多信息,请参阅[双区域备份](/tidb-cloud/backup-and-restore.md#turn-on-dual-region-backup)。 \ No newline at end of file diff --git a/tidb-cloud/scalability-concepts.md b/tidb-cloud/scalability-concepts.md new file mode 100644 index 000000000000..4b3bad53cee4 --- /dev/null +++ b/tidb-cloud/scalability-concepts.md @@ -0,0 +1,43 @@ +--- +title: 可扩展性 +summary: 了解 TiDB Cloud 的可扩展性概念。 +--- + +# 可扩展性 + +TiDB Cloud Dedicated 允许你分别调整其计算和存储资源,以适应数据量或工作负载的变化。TiDB Cloud Dedicated 可以在不中断服务的情况下进行扩展。这种灵活性使组织能够在保持高性能和高可用性的同时优化其基础设施成本。 + +> **注意:** +> +> [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 会根据应用程序的工作负载变化自动扩展。但是,你不能手动扩展 TiDB Cloud Serverless 集群。 + +> **提示:** +> +> 有关如何确定 TiDB Cloud Dedicated 集群大小的信息,请参见[确定 TiDB 大小](/tidb-cloud/size-your-cluster.md)。 + +## 垂直和水平扩展 + +TiDB Cloud Dedicated 支持垂直(向上扩展)和水平(向外扩展)扩展。 + +- 水平扩展是向专用集群添加节点以分配工作负载的过程。 +- 垂直扩展是为专用集群增加 vCPU 和内存的过程。 + +TiDB Cloud Dedicated 也支持垂直和水平扩展的组合。 + +## TiDB 可扩展性 + +TiDB 仅用于计算,不存储数据。你可以配置 TiDB 的节点数量、vCPU 和内存。 + +通常,TiDB 性能随着 TiDB 节点数量的增加而线性增长。 + +## TiKV 可扩展性 + +TiKV 负责存储行式数据。你可以配置 TiKV 的节点数量、vCPU 和内存以及存储。TiKV 节点数量应至少为 1 组(3 个不同可用区中的 3 个节点),并以 3 个节点为单位增加。 + +TiDB Cloud 将 TiKV 节点均匀部署在你选择的区域中的 3 个可用区,以实现持久性和高可用性。在典型的 3 副本设置中,你的数据在所有可用区的 TiKV 节点之间均匀分布,并持久化到每个 TiKV 节点的磁盘上。虽然 TiKV 主要用于数据存储,但 TiKV 节点的性能也会根据不同的工作负载而变化。 + +## TiFlash 可扩展性 + +TiFlash 负责存储列式数据。TiFlash 实时从 TiKV 同步数据,并开箱即支持实时分析工作负载。你可以配置 TiFlash 的节点数量、vCPU 和内存以及存储。 + +TiDB Cloud 将 TiFlash 节点均匀部署在区域内的不同可用区。建议在每个 TiDB Cloud 集群中至少配置两个 TiFlash 节点,并在生产环境中为数据创建至少两个副本以实现高可用性。 diff --git a/tidb-cloud/scale-tidb-cluster.md b/tidb-cloud/scale-tidb-cluster.md new file mode 100644 index 000000000000..c9efaf14acdb --- /dev/null +++ b/tidb-cloud/scale-tidb-cluster.md @@ -0,0 +1,102 @@ +--- +title: 扩缩容 TiDB 集群 +summary: 了解如何扩缩容 TiDB Cloud 集群。 +--- + +# 扩缩容 TiDB 集群 + +> **注意:** +> +> - [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 会根据应用程序的工作负载变化自动扩缩容。但是,您无法手动扩缩容 TiDB Cloud Serverless 集群。 +> - 当集群处于**修改中**状态时,您无法对其执行任何新的扩缩容操作。 + +您可以在以下维度扩缩容 TiDB 集群: + +- TiDB、TiKV 和 TiFlash 的节点数量 +- TiDB、TiKV 和 TiFlash 的 vCPU 和内存 +- TiKV 和 TiFlash 的存储空间 + +有关如何确定 TiDB 集群大小的信息,请参见[确定 TiDB 集群大小](/tidb-cloud/size-your-cluster.md)。 + +> **注意:** +> +> 如果 TiDB 或 TiKV 的 vCPU 和内存大小设置为 **4 vCPU,16 GiB**,请注意以下限制。要绕过这些限制,您可以先[增加 vCPU 和内存](#更改-vcpu-和内存)。 +> +> - TiDB 的节点数量只能设置为 1 或 2,TiKV 的节点数量固定为 3。 +> - 4 vCPU 的 TiDB 只能与 4 vCPU 的 TiKV 搭配使用,4 vCPU 的 TiKV 只能与 4 vCPU 的 TiDB 搭配使用。 +> - TiFlash 不可用。 + +## 更改节点数量 + +您可以增加或减少 TiDB、TiKV 或 TiFlash 节点的数量。 + +> **警告:** +> +> 减少 TiKV 或 TiFlash 节点数量可能存在风险,这可能导致剩余节点的存储空间不足、CPU 使用率过高或内存使用率过高。 + +要更改 TiDB、TiKV 或 TiFlash 节点的数量,请执行以下步骤: + +1. 在 TiDB Cloud 控制台中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 +2. 在要扩缩容的集群所在行,点击 **...**。 + + > **提示:** + > + > 或者,您也可以在**集群**页面上点击要扩缩容的集群名称,然后点击右上角的 **...**。 + +3. 在下拉菜单中点击**修改**。此时会显示**修改集群**页面。 +4. 在**修改集群**页面上,更改 TiDB、TiKV 或 TiFlash 节点的数量。 +5. 在右侧窗格中查看集群大小,然后点击**确认**。 + +您也可以通过 [修改 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) 端点使用 TiDB Cloud API 更改 TiDB、TiKV 或 TiFlash 节点的数量。目前,TiDB Cloud API 仍处于测试阶段。有关更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 + +## 更改 vCPU 和内存 + +您可以增加或减少 TiDB、TiKV 或 TiFlash 节点的 vCPU 和内存。 + +> **注意:** +> +> - 更改 vCPU 和内存仅适用于以下集群: +> - 在 2022/12/31 之后创建的 AWS 托管集群。 +> - 在 2023/04/26 之后创建的 Google Cloud 托管集群。 +> - Azure 托管集群。 +> - AWS 对 vCPU 和内存更改有冷却期限制。如果您的 TiDB 集群托管在 AWS 上,在更改 TiKV 或 TiFlash 的 vCPU 和内存后,必须等待至少六小时才能再次更改。 +> - 在减少 vCPU 之前,请确保当前 TiKV 或 TiFlash 的节点存储空间不超过目标 vCPU 的最大节点存储空间。有关详细信息,请参见 [TiKV 节点存储空间](/tidb-cloud/size-your-cluster.md#tikv-node-storage-size)和 [TiFlash 节点存储空间](/tidb-cloud/size-your-cluster.md#tiflash-node-storage)。如果任何组件的当前存储空间超过其限制,您将无法减少 vCPU。 + +要更改 TiDB、TiKV 或 TiFlash 节点的 vCPU 和内存,请执行以下步骤: + +1. 在 TiDB Cloud 控制台中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 +2. 在要扩缩容的集群所在行,点击 **...**。 + + > **提示:** + > + > 或者,您也可以在**集群**页面上点击要扩缩容的集群名称,然后点击右上角的 **...**。 + +3. 在下拉菜单中点击**修改**。此时会显示**修改集群**页面。 +4. 在**修改集群**页面上,更改 TiDB、TiKV 或 TiFlash 节点的 vCPU 和内存。 +5. 在右侧窗格中查看集群大小,然后点击**确认**。 + +您也可以通过 [修改 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) 端点使用 TiDB Cloud API 更改 TiDB、TiKV 或 TiFlash 节点的 vCPU 和内存。目前,TiDB Cloud API 仍处于测试阶段。有关更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 + +## 更改存储空间 + +您可以增加 TiKV 或 TiFlash 的存储空间。 + +> **警告:** +> +> - 对于正在运行的集群,AWS、Azure 和 Google Cloud 不允许原地降级存储容量。 +> - AWS 和 Azure 对存储空间更改有冷却期限制。如果您的 TiDB 集群托管在 AWS 或 Azure 上,在更改 TiKV 或 TiFlash 的存储空间或 vCPU 和内存后,必须等待至少六小时才能再次更改。 + +要更改 TiKV 或 TiFlash 的存储空间,请执行以下步骤: + +1. 在 TiDB Cloud 控制台中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 +2. 在要扩缩容的集群所在行,点击 **...**。 + + > **提示:** + > + > 或者,您也可以在**集群**页面上点击要扩缩容的集群名称,然后点击右上角的 **...**。 + +3. 在下拉菜单中点击**修改**。此时会显示**修改集群**页面。 +4. 在**修改集群**页面上,更改每个 TiKV 或 TiFlash 节点的存储空间。 +5. 在右侧窗格中查看集群大小,然后点击**确认**。 + +您也可以通过 [修改 TiDB Cloud Dedicated 集群](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/UpdateCluster) 端点使用 TiDB Cloud API 更改 TiKV 或 TiFlash 节点的存储空间。目前,TiDB Cloud API 仍处于测试阶段。有关更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 diff --git a/tidb-cloud/secure-connections-to-serverless-clusters.md b/tidb-cloud/secure-connections-to-serverless-clusters.md new file mode 100644 index 000000000000..a5815d94e8e4 --- /dev/null +++ b/tidb-cloud/secure-connections-to-serverless-clusters.md @@ -0,0 +1,107 @@ +--- +title: TiDB Cloud Serverless 的 TLS 连接 +summary: 介绍 TiDB Cloud Serverless 中的 TLS 连接。 +aliases: ['/tidbcloud/secure-connections-to-serverless-tier-clusters'] +--- + +# TiDB Cloud Serverless 的 TLS 连接 + +在客户端和 TiDB Cloud Serverless 集群之间建立安全的 TLS 连接是连接数据库的基本安全实践之一。TiDB Cloud Serverless 的服务器证书由独立的第三方证书提供商颁发。您可以轻松连接到 TiDB Cloud Serverless 集群,而无需下载服务器端数字证书。 + +## 前提条件 + +- 通过[密码认证](/tidb-cloud/tidb-cloud-password-authentication.md)或 [SSO 认证](/tidb-cloud/tidb-cloud-sso-authentication.md)登录 TiDB Cloud。 +- [创建 TiDB Cloud Serverless 集群](/tidb-cloud/tidb-cloud-quickstart.md)。 + +## 连接到 TiDB Cloud Serverless 集群的 TLS 连接 + +在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,您可以获取不同连接方法的示例,并按以下方式连接到 TiDB Cloud Serverless 集群: + +1. 导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击集群名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个对话框。 + +3. 在对话框中,保持连接类型的默认设置为 `Public`,然后选择您首选的连接方法和操作系统。 + +4. 如果您尚未设置密码,请点击**生成密码**为 TiDB Cloud Serverless 集群生成随机密码。该密码将自动嵌入到示例连接字符串中,以便轻松连接到您的集群。 + + > **注意:** + > + > - 随机密码由 16 个字符组成,包括大小写字母、数字和特殊字符。 + > - 关闭此对话框后,生成的密码将不再显示,因此您需要将密码保存在安全的位置。如果您忘记了密码,可以在此对话框中点击**重置密码**进行重置。 + > - TiDB Cloud Serverless 集群可以通过互联网访问。如果您需要在其他地方使用密码,建议重置密码以确保数据库安全。 + +5. 使用连接字符串连接到您的集群。 + + > **注意:** + > + > 连接到 TiDB Cloud Serverless 集群时,您必须在用户名中包含集群的前缀,并用引号将名称括起来。有关更多信息,请参见[用户名前缀](/tidb-cloud/select-cluster-tier.md#user-name-prefix)。 + +## 根证书管理 + +### 根证书颁发和有效期 + +TiDB Cloud Serverless 使用 [Let's Encrypt](https://letsencrypt.org/) 的证书作为证书颁发机构(CA),用于客户端和 TiDB Cloud Serverless 集群之间的 TLS 连接。一旦 TiDB Cloud Serverless 证书过期,它将自动轮换,而不会影响集群的正常运行和已建立的 TLS 安全连接。 + +如果客户端默认使用系统的根 CA 存储,例如 Java 和 Go,您可以轻松安全地连接到 TiDB Cloud Serverless 集群,而无需指定 CA 根证书的路径。但是,某些驱动程序和 ORM 不使用系统根 CA 存储。在这些情况下,您需要将驱动程序或 ORM 的 CA 根路径配置为系统根 CA 存储。例如,当您在 macOS 上使用 [mysqlclient](https://github.com/PyMySQL/mysqlclient) 连接 TiDB Cloud Serverless 集群时,需要在 `ssl` 参数中设置 `ca: /etc/ssl/cert.pem`。 + +如果您使用的是不接受包含多个证书的证书文件的 GUI 客户端(如 DBeaver),则必须下载 [ISRG Root X1](https://letsencrypt.org/certs/isrgrootx1.pem) 证书。 + +### 根证书默认路径 + +在不同的操作系统中,根证书的默认存储路径如下: + +**MacOS** + +``` +/etc/ssl/cert.pem +``` + +**Debian / Ubuntu / Arch** + +``` +/etc/ssl/certs/ca-certificates.crt +``` + +**RedHat / Fedora / CentOS / Mageia** + +``` +/etc/pki/tls/certs/ca-bundle.crt +``` + +**Alpine** + +``` +/etc/ssl/cert.pem +``` + +**OpenSUSE** + +``` +/etc/ssl/ca-bundle.pem +``` + +**Windows** + +Windows 不提供 CA 根证书的特定路径。相反,它使用[注册表](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/local-machine-and-current-user-certificate-stores)来存储证书。因此,要在 Windows 上指定 CA 根路径,请执行以下步骤: + +1. 下载 [ISRG Root X1 证书](https://letsencrypt.org/certs/isrgrootx1.pem),然后将其保存在您喜欢的路径中,例如 ``。 +2. 连接到 TiDB Cloud Serverless 集群时,使用该路径(``)作为您的 CA 根路径。 + +## 常见问题 + +### 连接到 TiDB Cloud Serverless 集群支持哪些 TLS 版本? + +出于安全考虑,TiDB Cloud Serverless 仅支持 TLS 1.2 和 TLS 1.3,不支持 TLS 1.0 和 TLS 1.1 版本。详情请参见 IETF [弃用 TLS 1.0 和 TLS 1.1](https://datatracker.ietf.org/doc/rfc8996/)。 + +### 是否支持连接客户端和 TiDB Cloud Serverless 之间的双向 TLS 认证? + +不支持。 + +TiDB Cloud Serverless 仅支持单向 TLS 认证,这意味着您的客户端使用公钥验证 TiDB Cloud 集群证书的私钥签名,而集群不验证客户端。 + +### TiDB Cloud Serverless 是否必须配置 TLS 才能建立安全连接? + +对于标准连接,TiDB Cloud Serverless 仅允许 TLS 连接,禁止非 SSL/TLS 连接。原因是当您通过互联网连接到 TiDB Cloud Serverless 集群时,SSL/TLS 是减少数据暴露在互联网上风险的最基本安全措施之一。 + +对于私有端点连接,由于它支持对 TiDB Cloud 服务的高度安全和单向访问,且不会将您的数据暴露在公共互联网上,因此配置 TLS 是可选的。 diff --git a/tidb-cloud/security-concepts.md b/tidb-cloud/security-concepts.md new file mode 100644 index 000000000000..5b8c86d5d128 --- /dev/null +++ b/tidb-cloud/security-concepts.md @@ -0,0 +1,243 @@ +--- +title: 安全性 +summary: 了解 TiDB Cloud 的安全性概念。 +--- + +# 安全性 + +TiDB Cloud 提供了一个强大且灵活的安全框架,旨在保护数据、执行访问控制并满足现代合规标准。该框架将高级安全功能与运营效率相结合,以支持大规模的组织需求。 + +**关键组件** + +- **身份和访问管理(IAM)**:为 TiDB Cloud 控制台和数据库环境提供安全且灵活的身份验证和权限管理。 + +- **网络访问控制**:可配置的连接选项,包括私有端点、VPC 对等连接、TLS 加密和 IP 访问列表。 + +- **数据访问控制**:高级加密功能,如客户管理的加密密钥(CMEK),用于保护静态数据。 + +- **审计日志**:全面跟踪控制台操作和数据库操作,确保问责制和透明度。 + +通过整合这些功能,TiDB Cloud 使组织能够保护敏感数据、简化访问控制并优化安全操作。 + +## 身份和访问管理(IAM) + +TiDB Cloud 采用身份和访问管理(IAM)来安全高效地管理控制台和数据库环境中的用户身份和权限。IAM 功能通过身份验证选项、基于角色的访问控制和分层资源结构的组合,旨在满足组织的安全性和合规性需求。 + +### TiDB Cloud 用户账户 + +TiDB Cloud 用户账户是管理平台中资源身份和访问的基础。每个账户代表平台中的个人或实体,并支持多种身份验证方法以满足组织需求: + +- **默认用户名和密码** + + - 用户使用电子邮件地址和密码创建账户。 + + - 适用于没有外部身份提供商的小型团队或个人。 + +- **标准 SSO 身份验证** + + - 用户通过 GitHub、Google 或 Microsoft 账户登录。 + + - 默认为所有组织启用。 + + - **最佳实践**:适用于较小的团队或没有严格合规需求的团队。 + + - 更多信息,请参见[标准 SSO 身份验证](/tidb-cloud/tidb-cloud-sso-authentication.md)。 + +- **组织 SSO 身份验证** + + - 使用 OIDC 或 SAML 协议与企业身份提供商(IdP)集成。 + + - 启用多因素认证强制执行、密码过期策略和域名限制等功能。 + + - **最佳实践**:适用于具有高级安全性和合规性要求的大型组织。 + + - 更多信息,请参见[组织 SSO 身份验证](/tidb-cloud/tidb-cloud-org-sso-authentication.md)。 + +### 数据库访问控制 + +TiDB Cloud 通过基于用户和基于角色的权限提供细粒度的数据库访问控制。这些机制使管理员能够安全地管理数据对象和模式的访问,同时确保符合组织的安全策略。 + +- **最佳实践:** + + - 通过仅授予用户其角色所需的权限来实施最小权限原则。 + + - 定期审核和更新用户访问权限,以适应不断变化的组织需求。 + +### 数据库用户账户 + +数据库用户账户存储在 `mysql.user` 系统表中,并通过用户名和客户端主机唯一标识。 + +在数据库初始化期间,TiDB 自动创建一个默认账户:`'root'@'%'`。 + +更多信息,请参见 [TiDB 用户账户管理](https://docs.pingcap.com/tidb/stable/user-account-management#user-names-and-passwords)。 + +### SQL 代理账户 + +SQL 代理账户是由 TiDB Cloud 自动生成的特殊用途账户。这些账户的主要特征包括: + +- **与 TiDB Cloud 用户账户关联:** 每个 SQL 代理账户对应一个特定的 TiDB Cloud 用户。 + +- **映射到角色:** SQL 代理账户被授予 `role_admin` 角色。 + +- **基于令牌:** SQL 代理账户使用安全的 JWT 令牌而不是密码,确保通过 TiDB Cloud 数据服务或 SQL 编辑器进行无缝、受限访问。 + +### TiDB 权限和角色 + +TiDB 的权限管理系统基于 MySQL 5.7,支持对数据库对象的细粒度访问。同时,TiDB 还引入了 MySQL 8.0 的 RBAC 和动态权限机制。这实现了细粒度和便捷的数据库权限管理。 + +**静态权限** + +- 支持基于数据库对象的细粒度访问控制,包括表、视图、索引、用户和其他对象。 + +- *示例:向用户授予特定表的 SELECT 权限。* + +**动态权限** + +- 支持合理拆分数据库管理权限,实现系统管理权限的细粒度控制。 + +- 示例:将 `BACKUP_ADMIN` 分配给管理数据库备份的账户,而不需要更广泛的管理权限。 + +**SQL 角色(RBAC)** + +- 将权限分组到可分配给用户的角色中,实现简化的权限管理和动态更新。 + +- 示例:为分析师分配读写角色以简化用户访问控制。 + +该系统确保了管理用户访问的灵活性和精确性,同时符合组织政策。 + +### 组织和项目 + +TiDB Cloud 使用分层结构管理用户和资源:组织、项目和集群。 + +**组织** + +- 管理资源、角色和计费的顶级实体。 + +- 组织所有者拥有完整权限,包括项目创建和角色分配。 + +**项目** + +- 组织的子部门,包含集群和特定于项目的配置。 + +- 由负责其范围内集群的项目所有者管理。 + +**集群** + +- 项目内的单个数据库实例。 + +### 示例结构 + +``` +- 您的组织 + - 项目 1 + - 集群 1 + - 集群 2 + - 项目 2 + - 集群 3 + - 集群 4 + - 项目 3 + - 集群 5 + - 集群 6 +``` + +### 主要功能 + +- **细粒度权限**: + - 在组织和项目级别分配特定角色,实现精确的访问控制。 + + - 通过仔细规划角色分配确保灵活性和安全性。 + +- **计费管理**: + - 在组织级别整合计费,并提供每个项目的详细分类。 + +### 身份和访问管理(IAM)角色 + +TiDB Cloud 提供基于角色的访问控制来管理组织和项目的权限: + +- **[组织级角色](/tidb-cloud/manage-user-access.md#organization-roles)**:授予管理整个组织的权限,包括计费和项目创建。 + +- **[项目级角色](/tidb-cloud/manage-user-access.md#project-roles)**:分配管理特定项目的权限,包括集群和配置。 + +## 网络访问控制 + +TiDB Cloud 通过强大的网络访问控制确保集群连接和数据传输的安全性。主要功能包括: + +### 私有端点 + +- 使您的虚拟私有云(VPC)中的 SQL 客户端能够安全连接到 TiDB Cloud Dedicated 集群。 + +- 支持 [AWS PrivateLink](/tidb-cloud/set-up-private-endpoint-connections.md)、[Azure Private Link](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md) 和 [Google Cloud Private Service Connect](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 + +**最佳实践:** 在生产环境中使用私有端点以最小化公共暴露,并定期审查配置。 + +### TLS(传输层安全) + +- 加密客户端和服务器之间的通信以保护数据传输。 + +- 提供 [Serverless](/tidb-cloud/secure-connections-to-serverless-clusters.md) 和 [Dedicated](/tidb-cloud/tidb-cloud-tls-connect-to-dedicated.md) 集群的设置指南。 + +**最佳实践:** 确保 TLS 证书是最新的,并定期轮换。 + +### VPC 对等连接 + +- 在虚拟私有云之间建立私有连接,实现安全、无缝的通信。 + +- 更多信息,请参见[通过 VPC 对等连接连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-vpc-peering-connections.md)。 + +**最佳实践:** 用于关键工作负载以避免公共互联网暴露,并监控性能。 + +### IP 访问列表 + +- 作为防火墙限制集群访问仅限于受信任的 IP 地址。 + +- 更多信息,请参见[配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md)。 + +**最佳实践:** 定期审核和更新访问列表以维护安全性。 + +## 数据访问控制 + +TiDB Cloud 通过高级加密功能保护静态数据,确保符合行业法规的安全性和合规性。 + +**客户管理的加密密钥(CMEK)** + +- 为组织提供对 TiDB Cloud Dedicated 集群加密的完全控制。 + +- 启用时使用 CMEK 密钥加密静态数据和备份。 + +- 对于没有 CMEK 的 TiDB Cloud Dedicated 集群,TiDB Cloud 使用托管密钥;TiDB Cloud Serverless 集群仅使用托管密钥。 + +**最佳实践:** + +- 定期轮换 CMEK 密钥以增强安全性并满足合规标准。 + +- 使用 CMEK 密钥一致地加密备份以提供额外保护。 + +- 对于需要严格合规性的行业(如 HIPAA 和 GDPR),利用 CMEK。 + +更多信息,请参见[使用客户管理的加密密钥进行静态加密](/tidb-cloud/tidb-cloud-encrypt-cmek.md)。 + +## 审计日志 + +TiDB Cloud 提供全面的审计日志功能,用于监控用户活动和数据库操作,确保安全性、问责制和合规性。 + +### 控制台审计日志 + +跟踪 TiDB Cloud 控制台上的关键操作,如邀请用户或管理集群。 + +**最佳实践:** + +- 将日志与 SIEM 工具集成以进行实时监控和告警。 + +- 设置保留策略以满足合规要求。 + +### 数据库审计日志 + +记录详细的数据库操作,包括执行的 SQL 语句和用户访问。 + +**最佳实践:** + +- 定期审查日志以发现异常活动或未授权访问。 + +- 使用日志进行合规报告和取证分析。 + +更多信息,请参见[控制台审计日志](/tidb-cloud/tidb-cloud-console-auditing.md)和[数据库审计日志](/tidb-cloud/tidb-cloud-auditing.md)。 diff --git a/tidb-cloud/select-cluster-tier.md b/tidb-cloud/select-cluster-tier.md new file mode 100644 index 000000000000..b9c1586a9a93 --- /dev/null +++ b/tidb-cloud/select-cluster-tier.md @@ -0,0 +1,102 @@ +--- +title: 选择集群套餐 +summary: 了解如何在 TiDB Cloud 上选择集群套餐。 +aliases: ['/tidbcloud/developer-tier-cluster'] +--- + +# 选择集群套餐 + +集群套餐决定了集群的吞吐量和性能。 + +TiDB Cloud 提供以下两种集群套餐选项。在创建集群之前,您需要考虑哪个选项更适合您的需求。 + +- [TiDB Cloud Serverless](#tidb-cloud-serverless) +- [TiDB Cloud Dedicated](#tidb-cloud-dedicated) + +## TiDB Cloud Serverless + + +TiDB Cloud Serverless 是一个完全托管的多租户 TiDB 产品。它提供即时、自动扩展的 MySQL 兼容数据库,并提供慷慨的免费套餐,超出免费限制后按使用量计费。 + +### 集群方案 + +TiDB Cloud Serverless 提供两种服务方案以满足不同用户的需求。无论您是刚刚开始使用,还是需要扩展以满足不断增长的应用程序需求,这些服务方案都能提供您所需的灵活性和能力。 + +#### 免费集群方案 + +免费集群方案非常适合刚开始使用 TiDB Cloud Serverless 的用户。它为开发者和小型团队提供以下基本功能: + +- **免费**:此方案完全免费,无需信用卡即可开始使用。 +- **存储**:提供初始 5 GiB 的行存储和 5 GiB 的列存储。 +- **请求单位**:包含 50 百万[请求单位 (RUs)](/tidb-cloud/tidb-cloud-glossary.md#request-unit) 用于数据库操作。 +- **轻松升级**:随着需求增长,可以平滑过渡到[可扩展集群方案](#可扩展集群方案)。 + +#### 可扩展集群方案 + +对于工作负载不断增长并需要实时扩展的应用程序,可扩展集群方案通过以下功能提供灵活性和性能,以跟上您的业务增长: + +- **增强功能**:包含免费集群方案的所有功能,同时具备处理更大和更复杂工作负载的能力,以及高级安全功能。 +- **自动扩展**:自动调整存储和计算资源,以高效满足不断变化的工作负载需求。 +- **可预测定价**:虽然此方案需要信用卡,但您只需为使用的资源付费,确保成本效益的可扩展性。 + +### 使用配额 + +对于 TiDB Cloud 中的每个组织,默认情况下您最多可以创建五个[免费集群](#免费集群方案)。要创建更多 TiDB Cloud Serverless 集群,您需要添加信用卡并创建[可扩展集群](#可扩展集群方案)。 + +对于您组织中的前五个 TiDB Cloud Serverless 集群,无论是免费还是可扩展集群,TiDB Cloud 都为每个集群提供以下免费使用配额: + +- 行存储:5 GiB +- 列存储:5 GiB +- 请求单位 (RUs):每月 50 百万 RUs + +请求单位 (RU) 是用于表示单个数据库请求消耗的资源量的度量单位。请求消耗的 RU 数量取决于各种因素,如操作类型或正在检索或修改的数据量。 + +一旦集群达到其使用配额,它会立即拒绝任何新的连接尝试,直到您[增加配额](/tidb-cloud/manage-serverless-spend-limit.md#update-spending-limit)或在新月份开始时重置使用量。在达到配额之前建立的现有连接将保持活动状态,但会经历限流。例如,当免费集群的行存储超过 5 GiB 时,集群会自动限制任何新的连接尝试。 + +要了解不同资源(包括读取、写入、SQL CPU 和网络出口)的 RU 消耗、定价详情和限流信息,请参见 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-cloud-serverless-pricing-details)。 + +### 用户名前缀 + + + +对于每个 TiDB Cloud Serverless 集群,TiDB Cloud 生成一个唯一的前缀以区分它与其他集群。 + +每当您使用或设置数据库用户名时,您必须在用户名中包含前缀。例如,假设您的集群前缀是 `3pTAoNNegb47Uc8`。 + +- 要连接到您的集群: + + ```shell + mysql -u '3pTAoNNegb47Uc8.root' -h -P 4000 -D test --ssl-mode=VERIFY_IDENTITY --ssl-ca= -p + ``` + + > **注意:** + > + > TiDB Cloud Serverless 需要 TLS 连接。要在您的系统上找到 CA 根路径,请参见[根证书默认路径](/tidb-cloud/secure-connections-to-serverless-clusters.md#root-certificate-default-path)。 + +- 要创建数据库用户: + + ```sql + CREATE USER '3pTAoNNegb47Uc8.jeffrey'; + ``` + +要获取集群的前缀,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面。 +2. 点击目标集群的名称进入其概览页面,然后点击右上角的**连接**。此时会显示一个连接对话框。 +3. 在对话框中,从连接字符串中获取前缀。 + +### TiDB Cloud Serverless 特殊条款和条件 + +某些 TiDB Cloud 功能在 TiDB Cloud Serverless 上部分支持或不支持。详细信息请参见 [TiDB Cloud Serverless 限制](/tidb-cloud/serverless-limitations.md)。 + +## TiDB Cloud Dedicated + +TiDB Cloud Dedicated 适用于生产环境,具有跨可用区高可用性、水平扩展和 [HTAP](https://en.wikipedia.org/wiki/Hybrid_transactional/analytical_processing) 的优势。 + +对于 TiDB Cloud Dedicated 集群,您可以根据业务需求轻松自定义 TiDB、TiKV 和 TiFlash 的集群大小。对于每个 TiKV 节点和 TiFlash 节点,节点上的数据会在不同的可用区中复制和分布,以实现[高可用性](/tidb-cloud/high-availability-with-multi-az.md)。 + +要创建 TiDB Cloud Dedicated 集群,您需要[添加付款方式](/tidb-cloud/tidb-cloud-billing.md#payment-method)或[申请概念验证 (PoC) 试用](/tidb-cloud/tidb-cloud-poc.md)。 + +> **注意:** +> +> 集群创建后,您无法减少节点存储。 diff --git a/tidb-cloud/serverless-driver-drizzle-example.md b/tidb-cloud/serverless-driver-drizzle-example.md new file mode 100644 index 000000000000..2b450585a109 --- /dev/null +++ b/tidb-cloud/serverless-driver-drizzle-example.md @@ -0,0 +1,272 @@ +--- +title: TiDB Cloud Serverless 驱动程序 Drizzle 教程 +summary: 了解如何将 TiDB Cloud serverless 驱动程序与 Drizzle 配合使用。 +--- + +# TiDB Cloud Serverless 驱动程序 Drizzle 教程 + +[Drizzle ORM](https://orm.drizzle.team/) 是一个轻量级且高性能的 TypeScript ORM,专注于开发者体验。从 `drizzle-orm@0.31.2` 开始,它支持 [drizzle-orm/tidb-serverless](https://orm.drizzle.team/docs/get-started-mysql#tidb-serverless),使您能够通过 HTTPS 使用 [TiDB Cloud serverless 驱动程序](/tidb-cloud/serverless-driver.md)。 + +本教程介绍如何在 Node.js 环境和边缘环境中将 TiDB Cloud serverless 驱动程序与 Drizzle 配合使用。 + +## 在 Node.js 环境中使用 Drizzle 和 TiDB Cloud serverless 驱动程序 + +本节介绍如何在 Node.js 环境中将 TiDB Cloud serverless 驱动程序与 Drizzle 配合使用。 + +### 开始之前 + +要完成本教程,您需要: + +- [Node.js](https://nodejs.org/en) >= 18.0.0。 +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 或您首选的包管理器。 +- 一个 TiDB Cloud Serverless 集群。如果您还没有,可以[创建一个 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 + +### 步骤 1. 创建项目 + +1. 创建一个名为 `drizzle-node-example` 的项目: + + ```shell + mkdir drizzle-node-example + cd drizzle-node-example + ``` + +2. 安装 `drizzle-orm` 和 `@tidbcloud/serverless` 包: + + ```shell + npm install drizzle-orm @tidbcloud/serverless + ``` + +3. 在项目的根目录中找到 `package.json` 文件,然后通过添加 `"type": "module"` 来指定 ES 模块: + + ```json + { + "type": "module", + "dependencies": { + "@tidbcloud/serverless": "^0.1.1", + "drizzle-orm": "^0.31.2" + } + } + ``` + +4. 在项目的根目录中添加一个 `tsconfig.json` 文件来定义 TypeScript 编译器选项。以下是示例文件: + + ```json + { + "compilerOptions": { + "module": "ES2022", + "target": "ES2022", + "moduleResolution": "node", + "strict": false, + "declaration": true, + "outDir": "dist", + "removeComments": true, + "allowJs": true, + "esModuleInterop": true, + "resolveJsonModule": true + } + } + ``` + +### 步骤 2. 设置环境 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称进入其概览页面。 + +2. 在概览页面上,点击右上角的**连接**,在**连接方式**下拉列表中选择 `Serverless Driver`,然后点击**生成密码**创建一个随机密码。 + + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码,也可以点击**重置密码**生成一个新密码。 + + 连接字符串的格式如下: + + ``` + mysql://[username]:[password]@[host]/[database] + ``` + +3. 在本地环境中设置环境变量 `DATABASE_URL`。例如,在 Linux 或 macOS 中,您可以运行以下命令: + + ```shell + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' + ``` + +### 步骤 3. 使用 Drizzle 查询数据 + +1. 在您的 TiDB Cloud Serverless 集群中创建一个表。 + + 您可以使用 [TiDB Cloud 控制台中的 SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)执行 SQL 语句。以下是示例: + + ```sql + CREATE TABLE `test`.`users` ( + `id` BIGINT PRIMARY KEY auto_increment, + `full_name` TEXT, + `phone` VARCHAR(256) + ); + ``` + +2. 在项目的根目录中创建一个名为 `hello-world.ts` 的文件,并添加以下代码: + + ```ts + import { connect } from '@tidbcloud/serverless'; + import { drizzle } from 'drizzle-orm/tidb-serverless'; + import { mysqlTable, serial, text, varchar } from 'drizzle-orm/mysql-core'; + + // 初始化 + const client = connect({ url: process.env.DATABASE_URL }); + const db = drizzle(client); + + // 定义模式 + export const users = mysqlTable('users', { + id: serial("id").primaryKey(), + fullName: text('full_name'), + phone: varchar('phone', { length: 256 }), + }); + export type User = typeof users.$inferSelect; // 查询时的返回类型 + export type NewUser = typeof users.$inferInsert; // 插入类型 + + // 插入和选择数据 + const user: NewUser = { fullName: 'John Doe', phone: '123-456-7890' }; + await db.insert(users).values(user) + const result: User[] = await db.select().from(users); + console.log(result); + ``` + +### 步骤 4. 运行 TypeScript 代码 + +1. 安装 `ts-node` 将 TypeScript 转换为 JavaScript,然后安装 `@types/node` 为 Node.js 提供 TypeScript 类型定义。 + + ```shell + npm install -g ts-node + npm i --save-dev @types/node + ``` + +2. 使用以下命令运行 TypeScript 代码: + + ```shell + ts-node --esm hello-world.ts + ``` + +## 在边缘环境中使用 Drizzle 和 TiDB Cloud serverless 驱动程序 + +本节以 Vercel Edge Function 为例。 + +### 开始之前 + +要完成本教程,您需要: + +- 一个提供边缘环境的 [Vercel](https://vercel.com/docs) 账户。 +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 或您首选的包管理器。 +- 一个 TiDB Cloud Serverless 集群。如果您还没有,可以[创建一个 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 + +### 步骤 1. 创建项目 + +1. 安装 Vercel CLI: + + ```shell + npm i -g vercel@latest + ``` + +2. 使用以下终端命令创建一个名为 `drizzle-example` 的 [Next.js](https://nextjs.org/) 项目: + + ```shell + npx create-next-app@latest drizzle-example --ts --no-eslint --tailwind --no-src-dir --app --import-alias "@/*" + ``` + +3. 导航到 `drizzle-example` 目录: + + ```shell + cd drizzle-example + ``` + +4. 安装 `drizzle-orm` 和 `@tidbcloud/serverless` 包: + + ```shell + npm install drizzle-orm @tidbcloud/serverless --force + ``` + +### 步骤 2. 设置环境 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标 TiDB Cloud Serverless 集群的名称进入其概览页面。 + +2. 在概览页面上,点击右上角的**连接**,在**连接方式**下拉列表中选择 `Serverless Driver`,然后点击**生成密码**创建一个随机密码。 + + > **提示:** + > + > 如果您之前已经创建了密码,您可以使用原始密码,也可以点击**重置密码**生成一个新密码。 + + 连接字符串的格式如下: + + ``` + mysql://[username]:[password]@[host]/[database] + ``` + +### 步骤 3. 创建边缘函数 + +1. 在您的 TiDB Cloud Serverless 集群中创建一个表。 + + 您可以使用 [TiDB Cloud 控制台中的 SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)执行 SQL 语句。以下是示例: + + ```sql + CREATE TABLE `test`.`users` ( + `id` BIGINT PRIMARY KEY auto_increment, + `full_name` TEXT, + `phone` VARCHAR(256) + ); + ``` + +2. 在项目的 `app` 目录中创建一个文件 `/api/edge-function-example/route.ts`,并添加以下代码: + + ```ts + import { NextResponse } from 'next/server'; + import type { NextRequest } from 'next/server'; + import { connect } from '@tidbcloud/serverless'; + import { drizzle } from 'drizzle-orm/tidb-serverless'; + import { mysqlTable, serial, text, varchar } from 'drizzle-orm/mysql-core'; + export const runtime = 'edge'; + + // 初始化 + const client = connect({ url: process.env.DATABASE_URL }); + const db = drizzle(client); + + // 定义模式 + export const users = mysqlTable('users', { + id: serial("id").primaryKey(), + fullName: text('full_name'), + phone: varchar('phone', { length: 256 }), + }); + export type User = typeof users.$inferSelect; // 查询时的返回类型 + export type NewUser = typeof users.$inferInsert; // 插入类型 + + export async function GET(request: NextRequest) { + // 插入和选择数据 + const user: NewUser = { fullName: 'John Doe', phone: '123-456-7890' }; + await db.insert(users).values(user) + const result: User[] = await db.select().from(users); + return NextResponse.json(result); + } + ``` + +3. 在本地测试您的代码: + + ```shell + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' + next dev + ``` + +4. 导航到 `http://localhost:3000/api/edge-function-example` 以获取路由的响应。 + +### 步骤 4. 将代码部署到 Vercel + +1. 使用 `DATABASE_URL` 环境变量将代码部署到 Vercel: + + ```shell + vercel -e DATABASE_URL='mysql://[username]:[password]@[host]/[database]' --prod + ``` + + 部署完成后,您将获得项目的 URL。 + +2. 导航到 `${Your-URL}/api/edge-function-example` 页面以获取路由的响应。 + +## 下一步 + +- 了解更多关于 [Drizzle](https://orm.drizzle.team/docs/overview) 和 [drizzle-orm/tidb-serverless](https://orm.drizzle.team/docs/get-started-mysql#tidb-serverless) 的信息。 +- 了解如何[将 TiDB Cloud 与 Vercel 集成](/tidb-cloud/integrate-tidbcloud-with-vercel.md)。 diff --git a/tidb-cloud/serverless-driver-kysely-example.md b/tidb-cloud/serverless-driver-kysely-example.md new file mode 100644 index 000000000000..3f3ecc6e63b5 --- /dev/null +++ b/tidb-cloud/serverless-driver-kysely-example.md @@ -0,0 +1,299 @@ +--- +title: TiDB Cloud Serverless 驱动程序 Kysely 教程 +summary: 学习如何使用 TiDB Cloud serverless 驱动程序与 Kysely。 +--- + +# TiDB Cloud Serverless 驱动程序 Kysely 教程 + +[Kysely](https://kysely.dev/docs/intro) 是一个类型安全且支持自动补全的 TypeScript SQL 查询构建器。TiDB Cloud 提供了 [@tidbcloud/kysely](https://github.com/tidbcloud/kysely),使你能够通过 HTTPS 使用 [TiDB Cloud serverless 驱动程序](/tidb-cloud/serverless-driver.md) 来使用 Kysely。与传统的 TCP 方式相比,[@tidbcloud/kysely](https://github.com/tidbcloud/kysely) 带来以下优势: + +- 在 serverless 环境中具有更好的性能。 +- 能够在边缘环境中使用 Kysely。 + +本教程介绍如何在 Node.js 环境和边缘环境中使用 TiDB Cloud serverless 驱动程序与 Kysely。 + +## 在 Node.js 环境中使用 TiDB Cloud Kysely dialect + +本节介绍如何在 Node.js 环境中使用 TiDB Cloud serverless 驱动程序与 Kysely。 + +### 开始之前 + +完成本教程需要以下准备: + +- [Node.js](https://nodejs.org/en) >= 18.0.0。 +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 或你偏好的包管理器。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,可以[创建一个 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 + +### 步骤 1. 创建项目 + +1. 创建一个名为 `kysely-node-example` 的项目: + + ``` + mkdir kysely-node-example + cd kysely-node-example + ``` + +2. 安装 `kysely`、`@tidbcloud/kysely` 和 `@tidbcloud/serverless` 包: + + ``` + npm install kysely @tidbcloud/kysely @tidbcloud/serverless + ``` + +3. 在项目根目录中找到 `package.json` 文件,然后通过添加 `"type": "module"` 来指定 ES 模块: + + ```json + { + "type": "module", + "dependencies": { + "@tidbcloud/kysely": "^0.0.4", + "@tidbcloud/serverless": "^0.0.7", + "kysely": "^0.26.3", + } + } + ``` + +4. 在项目根目录中添加 `tsconfig.json` 文件来定义 TypeScript 编译器选项。以下是示例文件: + + ```json + { + "compilerOptions": { + "module": "ES2022", + "target": "ES2022", + "moduleResolution": "node", + "strict": false, + "declaration": true, + "outDir": "dist", + "removeComments": true, + "allowJs": true, + "esModuleInterop": true, + "resolveJsonModule": true + } + } + ``` + +### 步骤 2. 设置环境 + +1. 在 TiDB Cloud Serverless 集群的概览页面,点击右上角的 **Connect**,然后从显示的对话框中获取数据库的连接字符串。连接字符串格式如下: + + ``` + mysql://[username]:[password]@[host]/[database] + ``` + +2. 在本地环境中设置环境变量 `DATABASE_URL`。例如,在 Linux 或 macOS 中,可以运行以下命令: + + ```bash + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' + ``` + +### 步骤 3. 使用 Kysely 查询数据 + +1. 在 TiDB Cloud Serverless 集群中创建一个表并插入一些数据。 + + 你可以使用 [TiDB Cloud 控制台中的 SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)来执行 SQL 语句。以下是示例: + + ```sql + CREATE TABLE `test`.`person` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL DEFAULT NULL, + `gender` enum('male','female') NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE + ); + + insert into test.person values (1,'pingcap','male') + ``` + +2. 在项目根目录中创建一个名为 `hello-world.ts` 的文件,并添加以下代码: + + ```ts + import { Kysely,GeneratedAlways,Selectable } from 'kysely' + import { TiDBServerlessDialect } from '@tidbcloud/kysely' + + // Types + interface Database { + person: PersonTable + } + + interface PersonTable { + id: GeneratedAlways + name: string + gender: "male" | "female" + } + + // Dialect + const db = new Kysely({ + dialect: new TiDBServerlessDialect({ + url: process.env.DATABASE_URL + }), + }) + + // Simple Querying + type Person = Selectable + export async function findPeople(criteria: Partial = {}) { + let query = db.selectFrom('person') + + if (criteria.name){ + query = query.where('name', '=', criteria.name) + } + + return await query.selectAll().execute() + } + + console.log(await findPeople()) + ``` + +### 步骤 4. 运行 TypeScript 代码 + +1. 安装 `ts-node` 来将 TypeScript 转换为 JavaScript,然后安装 `@types/node` 来提供 Node.js 的 TypeScript 类型定义。 + + ``` + npm install -g ts-node + npm i --save-dev @types/node + ``` + +2. 使用以下命令运行 TypeScript 代码: + + ``` + ts-node --esm hello-world.ts + ``` + +## 在边缘环境中使用 TiDB Cloud Kysely dialect + +本节以在 Vercel Edge Function 中使用 TiDB Cloud Kysely dialect 为例。 + +### 开始之前 + +完成本教程需要以下准备: + +- 一个提供边缘环境的 [Vercel](https://vercel.com/docs) 账户。 +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 或你偏好的包管理器。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,可以[创建一个 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 + +### 步骤 1. 创建项目 + +1. 安装 Vercel CLI: + + ``` + npm i -g vercel@latest + ``` + +2. 使用以下终端命令创建一个名为 `kysely-example` 的 [Next.js](https://nextjs.org/) 项目: + + ``` + npx create-next-app@latest kysely-example --ts --no-eslint --tailwind --no-src-dir --app --import-alias "@/*" + cd kysely-example + ``` + +3. 安装 `kysely`、`@tidbcloud/kysely` 和 `@tidbcloud/serverless` 包: + + ``` + npm install kysely @tidbcloud/kysely @tidbcloud/serverless + ``` + +### 步骤 2. 设置环境 + +在 TiDB Cloud Serverless 集群的概览页面,点击右上角的 **Connect**,然后从显示的对话框中获取数据库的连接字符串。连接字符串格式如下: + +``` +mysql://[username]:[password]@[host]/[database] +``` + +### 步骤 3. 创建边缘函数 + +1. 在 TiDB Cloud Serverless 集群中创建一个表并插入一些数据。 + + 你可以使用 [TiDB Cloud 控制台中的 SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)来执行 SQL 语句。以下是示例: + + ```sql + CREATE TABLE `test`.`person` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL DEFAULT NULL, + `gender` enum('male','female') NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE + ); + + insert into test.person values (1,'pingcap','male') + ``` + +2. 在项目的 `app` 目录中创建一个文件 `/api/edge-function-example/route.ts`,并添加以下代码: + + ```ts + import { NextResponse } from 'next/server'; + import type { NextRequest } from 'next/server'; + import { Kysely,GeneratedAlways,Selectable } from 'kysely' + import { TiDBServerlessDialect } from '@tidbcloud/kysely' + + export const runtime = 'edge'; + + // Types + interface Database { + person: PersonTable + } + + interface PersonTable { + id: GeneratedAlways + name: string + gender: "male" | "female" | "other" + } + + // Dialect + const db = new Kysely({ + dialect: new TiDBServerlessDialect({ + url: process.env.DATABASE_URL + }), + }) + + // Query + type Person = Selectable + async function findPeople(criteria: Partial = {}) { + let query = db.selectFrom('person') + + if (criteria.name){ + query = query.where('name', '=', criteria.name) + } + + return await query.selectAll().execute() + } + + export async function GET(request: NextRequest) { + + const searchParams = request.nextUrl.searchParams + const query = searchParams.get('query') + + let response = null; + if (query) { + response = await findPeople({name: query}) + } else { + response = await findPeople() + } + + return NextResponse.json(response); + } + ``` + + 上述代码接受一个查询参数 `query` 并返回查询结果。如果未提供查询参数,则返回 `person` 表中的所有记录。 + +3. 在本地测试你的代码: + + ``` + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' + next dev + ``` + +4. 导航到 `http://localhost:3000/api/edge-function-example` 以获取路由的响应。 + +### 步骤 4. 将代码部署到 Vercel + +1. 使用 `DATABASE_URL` 环境变量将代码部署到 Vercel: + + ``` + vercel -e DATABASE_URL='mysql://[username]:[password]@[host]/[database]' --prod + ``` + + 部署完成后,你将获得项目的 URL。 + +2. 导航到 `${Your-URL}/api/edge-function-example` 页面以获取路由的响应。 + +## 下一步 + +- 了解更多关于 [Kysely](https://kysely.dev/docs/intro) 和 [@tidbcloud/kysely](https://github.com/tidbcloud/kysely) 的信息 +- 了解如何[将 TiDB Cloud 与 Vercel 集成](/tidb-cloud/integrate-tidbcloud-with-vercel.md) diff --git a/tidb-cloud/serverless-driver-node-example.md b/tidb-cloud/serverless-driver-node-example.md new file mode 100644 index 000000000000..1ef22852e73e --- /dev/null +++ b/tidb-cloud/serverless-driver-node-example.md @@ -0,0 +1,95 @@ +--- +title: TiDB Cloud Serverless 驱动程序 Node.js 教程 +summary: 学习如何在本地 Node.js 项目中使用 TiDB Cloud serverless 驱动程序。 +--- + +# TiDB Cloud Serverless 驱动程序 Node.js 教程 + +本教程介绍如何在本地 Node.js 项目中使用 TiDB Cloud serverless 驱动程序。 + +> **注意:** +> +> - 本教程仅适用于 TiDB Cloud Serverless 集群。 +> - 要了解如何在 Cloudflare Workers、Vercel Edge Functions 和 Netlify Edge Functions 中使用 TiDB Cloud serverless 驱动程序,请查看我们的[汽车销售分析](https://car-sales-insight.vercel.app/)和[示例代码库](https://github.com/tidbcloud/car-sales-insight)。 + +## 开始之前 + +要完成本分步教程,你需要: + +- [Node.js](https://nodejs.org/en) >= 18.0.0 +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 或你偏好的包管理器 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,可以[创建一个 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 + +## 步骤 1. 创建本地 Node.js 项目 + +1. 创建一个名为 `node-example` 的项目: + + ```shell + mkdir node-example + cd node-example + ``` + +2. 使用 npm 或你偏好的包管理器安装 TiDB Cloud serverless 驱动程序。 + + 以下命令以 npm 安装为例。执行此命令将在你的项目目录中创建一个 `node_modules` 目录和一个 `package.json` 文件。 + + ``` + npm install @tidbcloud/serverless + ``` + +## 步骤 2. 使用 serverless 驱动程序 + +serverless 驱动程序同时支持 CommonJS 和 ES 模块。以下步骤以使用 ES 模块为例。 + +1. 在 TiDB Cloud Serverless 集群的概览页面上,点击右上角的**连接**,然后从显示的对话框中获取数据库的连接字符串。连接字符串格式如下: + + ``` + mysql://[username]:[password]@[host]/[database] + ``` + +2. 在 `package.json` 文件中,通过添加 `type: "module"` 来指定 ES 模块。 + + 例如: + + ```json + { + "type": "module", + "dependencies": { + "@tidbcloud/serverless": "^0.0.7", + } + } + ``` + +3. 在项目目录中创建一个名为 `index.js` 的文件,并添加以下代码: + + ```js + import { connect } from '@tidbcloud/serverless' + + const conn = connect({url: 'mysql://[username]:[password]@[host]/[database]'}) // 替换为你的 TiDB Cloud Serverless 集群信息 + console.log(await conn.execute("show tables")) + ``` + +4. 使用以下命令运行你的项目: + + ``` + node index.js + ``` + +## 与早期版本 Node.js 的兼容性 + +如果你使用的是 18.0.0 之前的 Node.js 版本(没有全局 `fetch` 函数),可以按照以下步骤获取 `fetch`: + +1. 安装提供 `fetch` 的包,例如 `undici`: + + ``` + npm install undici + ``` + +2. 将 `fetch` 函数传递给 `connect` 函数: + + ```js + import { connect } from '@tidbcloud/serverless' + import { fetch } from 'undici' + + const conn = connect({url: 'mysql://[username]:[password]@[host]/[database]',fetch}) + ``` diff --git a/tidb-cloud/serverless-driver-prisma-example.md b/tidb-cloud/serverless-driver-prisma-example.md new file mode 100644 index 000000000000..a792a6089874 --- /dev/null +++ b/tidb-cloud/serverless-driver-prisma-example.md @@ -0,0 +1,279 @@ +--- +title: TiDB Cloud Serverless 驱动程序 Prisma 教程 +summary: 学习如何将 TiDB Cloud serverless 驱动程序与 Prisma ORM 一起使用。 +--- + +# TiDB Cloud Serverless 驱动程序 Prisma 教程 + +[Prisma](https://www.prisma.io/docs) 是一个开源的下一代 ORM(对象关系映射),帮助开发者以直观、高效和安全的方式与数据库交互。TiDB Cloud 提供了 [@tidbcloud/prisma-adapter](https://github.com/tidbcloud/prisma-adapter),使你能够通过 HTTPS 使用 [TiDB Cloud serverless 驱动程序](/tidb-cloud/serverless-driver.md)来使用 [Prisma Client](https://www.prisma.io/docs/concepts/components/prisma-client)。与传统的 TCP 方式相比,[@tidbcloud/prisma-adapter](https://github.com/tidbcloud/prisma-adapter) 带来以下好处: + +- 在 serverless 环境中提供更好的 Prisma Client 性能 +- 能够在边缘环境中使用 Prisma Client + +本教程介绍如何在 serverless 环境和边缘环境中使用 [@tidbcloud/prisma-adapter](https://github.com/tidbcloud/prisma-adapter)。 + +## 安装 + +你需要同时安装 [@tidbcloud/prisma-adapter](https://github.com/tidbcloud/prisma-adapter) 和 [TiDB Cloud serverless 驱动程序](/tidb-cloud/serverless-driver.md)。你可以使用 [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 或你喜欢的包管理器进行安装。 + +以 npm 为例,你可以运行以下命令进行安装: + +```shell +npm install @tidbcloud/prisma-adapter +npm install @tidbcloud/serverless +``` + +## 启用 `driverAdapters` + +要使用 Prisma 适配器,你需要在 `schema.prisma` 文件中启用 `driverAdapters` 功能。例如: + +```prisma +generator client { + provider = "prisma-client-js" + previewFeatures = ["driverAdapters"] +} + +datasource db { + provider = "mysql" + url = env("DATABASE_URL") +} +``` + +## 初始化 Prisma Client + +在使用 Prisma Client 之前,你需要使用 `@tidbcloud/prisma-adapter` 对其进行初始化。 + +对于早于 v6.6.0 的 `@tidbcloud/prisma-adapter`: + +```js +import { connect } from '@tidbcloud/serverless'; +import { PrismaTiDBCloud } from '@tidbcloud/prisma-adapter'; +import { PrismaClient } from '@prisma/client'; + +// Initialize Prisma Client +const connection = connect({ url: ${DATABASE_URL} }); +const adapter = new PrismaTiDBCloud(connection); +const prisma = new PrismaClient({ adapter }); +``` + +对于 v6.6.0 或更高版本的 `@tidbcloud/prisma-adapter`: + +```js +import { PrismaTiDBCloud } from '@tidbcloud/prisma-adapter'; +import { PrismaClient } from '@prisma/client'; + +// Initialize Prisma Client +const adapter = new PrismaTiDBCloud({ url: ${DATABASE_URL} }); +const prisma = new PrismaClient({ adapter }); +``` + +然后,来自 Prisma Client 的查询将被发送到 TiDB Cloud serverless 驱动程序进行处理。 + +## 在 Node.js 环境中使用 Prisma 适配器 + +本节提供了在 Node.js 环境中使用 `@tidbcloud/prisma-adapter` 的示例。 + +### 开始之前 + +要完成本教程,你需要以下内容: + +- [Node.js](https://nodejs.org/en) >= 18.0.0。 +- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 或你喜欢的包管理器。 +- 一个 TiDB Cloud Serverless 集群。如果你没有,可以[创建一个 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)。 + +### 第 1 步:创建项目 + +1. 创建一个名为 `prisma-example` 的项目: + + ``` + mkdir prisma-example + cd prisma-example + ``` + +2. 安装 `@tidbcloud/prisma-adapter` 驱动适配器、`@tidbcloud/serverless` serverless 驱动程序和 Prisma CLI。 + + 以下命令使用 npm 作为包管理器。执行 `npm install @tidbcloud/serverless` 将在你的项目目录中创建一个 `node_modules` 目录和一个 `package.json` 文件。 + + ``` + npm install @tidbcloud/prisma-adapter + npm install @tidbcloud/serverless + npm install prisma --save-dev + ``` + +3. 在 `package.json` 文件中,通过添加 `type: "module"` 来指定 ES 模块: + + ```json + { + "type": "module", + "dependencies": { + "@prisma/client": "^6.6.0", + "@tidbcloud/prisma-adapter": "^6.6.0", + "@tidbcloud/serverless": "^0.1.0" + }, + "devDependencies": { + "prisma": "^6.6.0" + } + } + ``` + +### 第 2 步:设置环境 + +1. 在你的 TiDB Cloud Serverless 集群的概览页面上,点击右上角的**连接**,然后从显示的对话框中获取数据库的连接字符串。连接字符串看起来像这样: + + ``` + mysql://[username]:[password]@[host]:4000/[database]?sslaccept=strict + ``` + +2. 在项目的根目录中,创建一个名为 `.env` 的文件,定义一个名为 `DATABASE_URL` 的环境变量,如下所示,然后将此变量中的占位符 `[]` 替换为连接字符串中的相应参数。 + + ```dotenv + DATABASE_URL='mysql://[username]:[password]@[host]:4000/[database]?sslaccept=strict' + ``` + + > **注意:** + > + > `@tidbcloud/prisma-adapter` 仅支持通过 HTTPS 使用 Prisma Client。对于 [Prisma Migrate](https://www.prisma.io/docs/concepts/components/prisma-migrate) 和 [Prisma Introspection](https://www.prisma.io/docs/concepts/components/introspection),仍然使用传统的 TCP 连接。如果你只需要使用 Prisma Client,可以将 `DATABASE_URL` 简化为 `mysql://[username]:[password]@[host]/[database]` 格式。 + +3. 安装 `dotenv` 以从 `.env` 文件加载环境变量: + + ``` + npm install dotenv + ``` + +### 第 3 步:定义你的架构 + +1. 创建一个名为 `schema.prisma` 的文件。在此文件中,包含 `driverAdapters` 预览功能并引用 `DATABASE_URL` 环境变量。以下是示例文件: + + ``` + // schema.prisma + generator client { + provider = "prisma-client-js" + previewFeatures = ["driverAdapters"] + } + + datasource db { + provider = "mysql" + url = env("DATABASE_URL") + } + ``` + +2. 在 `schema.prisma` 文件中,为你的数据库表定义一个数据模型。在以下示例中,定义了一个名为 `user` 的数据模型。 + + ``` + // schema.prisma + generator client { + provider = "prisma-client-js" + previewFeatures = ["driverAdapters"] + } + + datasource db { + provider = "mysql" + url = env("DATABASE_URL") + } + + // define a data model according to your database table + model user { + id Int @id @default(autoincrement()) + email String? @unique(map: "uniq_email") @db.VarChar(255) + name String? @db.VarChar(255) + } + ``` + +3. 将你的数据库与 Prisma 架构同步。你可以手动在 TiDB Cloud Serverless 集群中创建数据库表,或使用 Prisma CLI 自动创建它们,如下所示: + + ``` + npx prisma db push + ``` + + 此命令将通过传统的 TCP 连接(而不是通过使用 `@tidbcloud/prisma-adapter` 的 HTTPS 连接)在你的 TiDB Cloud Serverless 集群中创建 `user` 表。这是因为它使用与 Prisma Migrate 相同的引擎。有关此命令的更多信息,请参阅[原型化你的架构](https://www.prisma.io/docs/concepts/components/prisma-migrate/db-push)。 + +4. 生成 Prisma Client: + + ``` + npx prisma generate + ``` + + 此命令将基于 Prisma 架构生成 Prisma Client。 + +### 第 4 步:执行 CRUD 操作 + +1. 创建一个名为 `hello-word.js` 的文件,并添加以下代码来初始化 Prisma Client: + + ```js + import { PrismaTiDBCloud } from '@tidbcloud/prisma-adapter'; + import { PrismaClient } from '@prisma/client'; + import dotenv from 'dotenv'; + + // setup + dotenv.config(); + const connectionString = `${process.env.DATABASE_URL}`; + + // Initialize Prisma Client + const adapter = new PrismaTiDBCloud({ url: connectionString }); + const prisma = new PrismaClient({ adapter }); + ``` + +2. 使用 Prisma Client 执行一些 CRUD 操作。例如: + + ```js + // Insert + const user = await prisma.user.create({ + data: { + email: 'test@pingcap.com', + name: 'test', + }, + }) + console.log(user) + + // Query + console.log(await prisma.user.findMany()) + + // Delete + await prisma.user.delete({ + where: { + id: user.id, + }, + }) + ``` + +3. 使用 Prisma Client 执行一些事务操作。例如: + + ```js + const createUser1 = prisma.user.create({ + data: { + email: 'test1@pingcap.com', + name: 'test1', + }, + }) + const createUser2 = prisma.user.create({ + data: { + email: 'test1@pingcap.com', + name: 'test1', + }, + }) + const createUser3 = prisma.user.create({ + data: { + email: 'test2@pingcap.com', + name: 'test2', + }, + }) + + try { + await prisma.$transaction([createUser1, createUser2]) // Operations fail because the email address is duplicated + } catch (e) { + console.log(e) + } + + try { + await prisma.$transaction([createUser2, createUser3]) // Operations success because the email address is unique + } catch (e) { + console.log(e) + } + ``` + +## 在边缘环境中使用 Prisma 适配器 + +你可以在边缘环境(如 Vercel Edge Functions 和 Cloudflare Workers)中使用 v5.11.0 或更高版本的 `@tidbcloud/prisma-adapter`。 + +- [Vercel Edge Function 示例](https://github.com/tidbcloud/serverless-driver-example/tree/main/prisma/prisma-vercel-example) +- [Cloudflare Workers 示例](https://github.com/tidbcloud/serverless-driver-example/tree/main/prisma/prisma-cloudflare-worker-example) diff --git a/tidb-cloud/serverless-driver.md b/tidb-cloud/serverless-driver.md new file mode 100644 index 000000000000..7f6e411d9730 --- /dev/null +++ b/tidb-cloud/serverless-driver.md @@ -0,0 +1,342 @@ +--- +title: TiDB Cloud Serverless 驱动(Beta) +summary: 了解如何从 serverless 和边缘环境连接到 TiDB Cloud Serverless。 +aliases: ['/tidbcloud/serverless-driver-config'] +--- + +# TiDB Cloud Serverless 驱动(Beta) + +## 为什么使用 TiDB Cloud Serverless 驱动(Beta) + +传统的基于 TCP 的 MySQL 驱动程序不适合 serverless 函数,因为它们需要长期存在的持久 TCP 连接,这与 serverless 函数的短暂特性相矛盾。此外,在边缘环境中,如 [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions) 和 [Cloudflare Workers](https://workers.cloudflare.com/),由于可能缺乏完整的 TCP 支持和完整的 Node.js 兼容性,这些驱动程序可能完全无法工作。 + +JavaScript 版本的 [TiDB Cloud serverless 驱动(Beta)](https://github.com/tidbcloud/serverless-js) 允许你通过 HTTP 连接到 TiDB Cloud Serverless 集群,这通常在 serverless 环境中都支持。有了它,现在可以从边缘环境连接到 TiDB Cloud Serverless 集群,并减少 TCP 的连接开销,同时保持与传统基于 TCP 的 MySQL 驱动程序类似的开发体验。 + +> **注意:** +> +> 如果你更喜欢使用 RESTful API 而不是 SQL 或 ORM 进行编程,可以使用 [Data Service (beta)](/tidb-cloud/data-service-overview.md)。 + +## 安装 serverless 驱动 + +你可以使用 npm 安装驱动: + +```bash +npm install @tidbcloud/serverless +``` + +## 使用 serverless 驱动 + +你可以使用 serverless 驱动查询 TiDB Cloud Serverless 集群的数据或执行交互式事务。 + +### 查询 + +要从 TiDB Cloud Serverless 集群查询数据,你需要先创建一个连接。然后你可以使用该连接执行原始 SQL 查询。例如: + +```ts +import { connect } from '@tidbcloud/serverless' + +const conn = connect({url: 'mysql://[username]:[password]@[host]/[database]'}) +const results = await conn.execute('select * from test where id = ?',[1]) +``` + +### 事务(实验性) + +你也可以使用 serverless 驱动执行交互式事务。例如: + +```ts +import { connect } from '@tidbcloud/serverless' + +const conn = connect({url: 'mysql://[username]:[password]@[host]/[database]'}) +const tx = await conn.begin() + +try { + await tx.execute('insert into test values (1)') + await tx.execute('select * from test') + await tx.commit() +} catch (err) { + await tx.rollback() + throw err +} +``` + +## 边缘环境示例 + +以下是在边缘环境中使用 serverless 驱动的一些示例。完整示例可以尝试这个[在线演示](https://github.com/tidbcloud/car-sales-insight)。 + + + +
+ +```ts +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; +import { connect } from '@tidbcloud/serverless' +export const runtime = 'edge' + +export async function GET(request: NextRequest) { + const conn = connect({url: process.env.DATABASE_URL}) + const result = await conn.execute('show tables') + return NextResponse.json({result}); +} +``` + +了解更多关于[在 Vercel 中使用 TiDB Cloud serverless 驱动](/tidb-cloud/integrate-tidbcloud-with-vercel.md)。 + +
+ +
+ +```ts +import { connect } from '@tidbcloud/serverless' +export interface Env { + DATABASE_URL: string; +} +export default { + async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { + const conn = connect({url: env.DATABASE_URL}) + const result = await conn.execute('show tables') + return new Response(JSON.stringify(result)); + }, +}; +``` + +了解更多关于[在 Cloudflare Workers 中使用 TiDB Cloud serverless 驱动](/tidb-cloud/integrate-tidbcloud-with-cloudflare.md)。 + +
+ +
+ +```ts +import { connect } from 'https://esm.sh/@tidbcloud/serverless' + +export default async () => { + const conn = connect({url: Netlify.env.get('DATABASE_URL')}) + const result = await conn.execute('show tables') + return new Response(JSON.stringify(result)); +} +``` + +了解更多关于[在 Netlify 中使用 TiDB Cloud serverless 驱动](/tidb-cloud/integrate-tidbcloud-with-netlify.md#use-the-edge-function)。 + +
+ +
+ +```ts +import { connect } from "npm:@tidbcloud/serverless" + +const conn = connect({url: Deno.env.get('DATABASE_URL')}) +const result = await conn.execute('show tables') +``` + +
+ +
+ +```ts +import { connect } from "@tidbcloud/serverless" + +const conn = connect({url: Bun.env.DATABASE_URL}) +const result = await conn.execute('show tables') +``` + +
+ +
+ +## 配置 serverless 驱动 + +你可以在连接级别和 SQL 级别配置 TiDB Cloud serverless 驱动。 + +### 连接级别配置 + +在连接级别,你可以进行以下配置: + +| 名称 | 类型 | 默认值 | 描述 | +|--------------|----------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `username` | string | N/A | TiDB Cloud Serverless 的用户名 | +| `password` | string | N/A | TiDB Cloud Serverless 的密码 | +| `host` | string | N/A | TiDB Cloud Serverless 的主机名 | +| `database` | string | `test` | TiDB Cloud Serverless 的数据库 | +| `url` | string | N/A | 数据库的 URL,格式为 `mysql://[username]:[password]@[host]/[database]`,如果你打算连接到默认数据库,可以省略 `database`。 | +| `fetch` | function | global fetch | 自定义 fetch 函数。例如,你可以在 node.js 中使用 `undici` fetch。 | +| `arrayMode` | bool | `false` | 是否将结果以数组而不是对象形式返回。要获得更好的性能,请设置为 `true`。 | +| `fullResult` | bool | `false` | 是否返回完整的结果对象而不是仅返回行。要获得更详细的结果,请设置为 `true`。 | +| `decoders` | object | `{}` | 一组键值对,使你能够自定义不同列类型的解码过程。在每个键值对中,你可以指定一个列类型作为键,并指定一个相应的函数作为值。这个函数接收从 TiDB Cloud serverless 驱动接收到的原始字符串值作为参数,并返回解码后的值。 | + +**数据库 URL** + +> **注意:** +> +> 如果你的用户名、密码或数据库名称包含特殊字符,在通过 URL 传递时必须对这些字符进行[百分比编码](https://en.wikipedia.org/wiki/Percent-encoding)。例如,密码 `password1@//?` 需要在 URL 中编码为 `password1%40%2F%2F%3F`。 + +当配置了 `url` 时,就不需要单独配置 `host`、`username`、`password` 和 `database`。以下代码是等效的: + +```ts +const config = { + host: '', + username: '', + password: '', + database: '', + arrayMode: true, +} + +const conn = connect(config) +``` + +```ts +const config = { + url: process.env['DATABASE_URL'] || 'mysql://[username]:[password]@[host]/[database]', + arrayMode: true +} + +const conn = connect(config) +``` + +### SQL 级别选项 + +> **注意:** +> +> SQL 级别选项的优先级高于连接级别配置。 + +在 SQL 级别,你可以配置以下选项: + +| 选项 | 类型 | 默认值 | 描述 | +|--------------|--------|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `arrayMode` | bool | `false` | 是否将结果以数组而不是对象形式返回。要获得更好的性能,请设置为 `true`。 | +| `fullResult` | bool | `false` | 是否返回完整的结果对象而不是仅返回行。要获得更详细的结果,请设置为 `true`。 | +| `isolation` | string | `REPEATABLE READ`| 事务隔离级别,可以设置为 `READ COMMITTED` 或 `REPEATABLE READ`。 | +| `decoders` | object | `{}` | 一组键值对,使你能够自定义不同列类型的解码过程。在每个键值对中,你可以指定一个列类型作为键,并指定一个相应的函数作为值。这个函数接收从 TiDB Cloud serverless 驱动接收到的原始字符串值作为参数,并返回解码后的值。如果你在连接级别和 SQL 级别都配置了 `decoders`,连接级别配置的具有不同键的键值对将合并到 SQL 级别生效。如果在两个级别都指定了相同的键(即列类型),SQL 级别的值优先。 | + +**arrayMode 和 fullResult** + +要将完整的结果对象以数组形式返回,你可以按如下方式配置 `arrayMode` 和 `fullResult` 选项: + +```ts +const conn = connect({url: process.env['DATABASE_URL'] || 'mysql://[username]:[password]@[host]/[database]'}) +const results = await conn.execute('select * from test',null,{arrayMode:true,fullResult:true}) +``` + +**isolation** + +`isolation` 选项只能在 `begin` 函数中使用。 + +```ts +const conn = connect({url: 'mysql://[username]:[password]@[host]/[database]'}) +const tx = await conn.begin({isolation:"READ COMMITTED"}) +``` + +**decoders** + +要自定义返回的列值格式,你可以在 `connect()` 方法中按如下方式配置 `decoder` 选项: + +```ts +import { connect, ColumnType } from '@tidbcloud/serverless'; + +const conn = connect({ + url: 'mysql://[username]:[password]@[host]/[database]', + decoders: { + // 默认情况下,TiDB Cloud serverless 驱动将 BIGINT 类型作为文本值返回。这个解码器将 BIGINT 转换为 JavaScript 内置的 BigInt 类型。 + [ColumnType.BIGINT]: (rawValue: string) => BigInt(rawValue), + + // 默认情况下,TiDB Cloud serverless 驱动将 DATETIME 类型作为 'yyyy-MM-dd HH:mm:ss' 格式的文本值返回。这个解码器将 DATETIME 文本转换为 JavaScript 原生 Date 对象。 + [ColumnType.DATETIME]: (rawValue: string) => new Date(rawValue), + } +}) + +// 你也可以在 SQL 级别配置 decoder 选项来覆盖连接级别具有相同键的解码器。 +conn.execute(`select ...`, [], { + decoders: { + // ... + } +}) +``` + +> **注意:** +> +> TiDB Cloud serverless 驱动配置变更: +> +> - v0.0.7:添加 SQL 级别选项 `isolation`。 +> - v0.0.10:添加连接级别配置 `decoders` 和 SQL 级别选项 `decoders`。 + +## 功能特性 + +### 支持的 SQL 语句 + +支持 DDL 和以下 SQL 语句:`SELECT`、`SHOW`、`EXPLAIN`、`USE`、`INSERT`、`UPDATE`、`DELETE`、`BEGIN`、`COMMIT`、`ROLLBACK` 和 `SET`。 + +### 数据类型映射 + +TiDB Cloud Serverless 和 Javascript 之间的类型映射如下: + +| TiDB Cloud Serverless 类型 | Javascript 类型 | +|----------------------|-----------------| +| TINYINT | number | +| UNSIGNED TINYINT | number | +| BOOL | number | +| SMALLINT | number | +| UNSIGNED SMALLINT | number | +| MEDIUMINT | number | +| INT | number | +| UNSIGNED INT | number | +| YEAR | number | +| FLOAT | number | +| DOUBLE | number | +| BIGINT | string | +| UNSIGNED BIGINT | string | +| DECIMAL | string | +| CHAR | string | +| VARCHAR | string | +| BINARY | Uint8Array | +| VARBINARY | Uint8Array | +| TINYTEXT | string | +| TEXT | string | +| MEDIUMTEXT | string | +| LONGTEXT | string | +| TINYBLOB | Uint8Array | +| BLOB | Uint8Array | +| MEDIUMBLOB | Uint8Array | +| LONGBLOB | Uint8Array | +| DATE | string | +| TIME | string | +| DATETIME | string | +| TIMESTAMP | string | +| ENUM | string | +| SET | string | +| BIT | Uint8Array | +| JSON | object | +| NULL | null | +| Others | string | + +> **注意:** +> +> 确保在 TiDB Cloud Serverless 中使用默认的 `utf8mb4` 字符集进行 JavaScript 字符串的类型转换,因为 TiDB Cloud serverless 驱动使用 UTF-8 编码将它们解码为字符串。 + +> **注意:** +> +> TiDB Cloud serverless 驱动数据类型映射变更: +> +> - v0.1.0:`BINARY`、`VARBINARY`、`TINYBLOB`、`BLOB`、`MEDIUMBLOB`、`LONGBLOB` 和 `BIT` 类型现在返回 `Uint8Array` 而不是 `string`。 + +### ORM 集成 + +TiDB Cloud serverless 驱动已经与以下 ORM 集成: + +- [TiDB Cloud serverless 驱动 Kysely 方言](https://github.com/tidbcloud/kysely)。 +- [TiDB Cloud serverless 驱动 Prisma 适配器](https://github.com/tidbcloud/prisma-adapter)。 + +## 定价 + +serverless 驱动本身是免费的,但使用驱动访问数据会产生 [Request Units (RUs)](/tidb-cloud/tidb-cloud-glossary.md#request-unit) 和存储使用量。定价遵循 [TiDB Cloud Serverless 定价](https://www.pingcap.com/tidb-serverless-pricing-details/) 模型。 + +## 限制 + +目前,使用 serverless 驱动有以下限制: + +- 单个查询最多可以获取 10,000 行数据。 +- 一次只能执行一条 SQL 语句。目前不支持在一个查询中执行多条 SQL 语句。 +- 尚不支持通过[私有端点](/tidb-cloud/set-up-private-endpoint-connections-serverless.md)连接。 + +## 下一步 + +- 了解如何[在本地 Node.js 项目中使用 TiDB Cloud serverless 驱动](/tidb-cloud/serverless-driver-node-example.md)。 diff --git a/tidb-cloud/serverless-export.md b/tidb-cloud/serverless-export.md new file mode 100644 index 000000000000..3bcbbb362426 --- /dev/null +++ b/tidb-cloud/serverless-export.md @@ -0,0 +1,428 @@ +--- +title: 从 TiDB Cloud Serverless 导出数据 +summary: 了解如何从 TiDB Cloud Serverless 集群导出数据。 +--- + +# 从 TiDB Cloud Serverless 导出数据 + +TiDB Cloud Serverless 导出功能(Beta)是一项服务,可让您将数据从 TiDB Cloud Serverless 集群导出到本地文件或外部存储服务。您可以将导出的数据用于备份、迁移、数据分析或其他用途。 + +虽然您也可以使用 [mysqldump](https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html) 和 TiDB [Dumpling](https://docs.pingcap.com/tidb/dev/dumpling-overview) 等工具导出数据,但 TiDB Cloud Serverless 导出功能提供了一种更便捷、高效的方式来从 TiDB Cloud Serverless 集群导出数据。它具有以下优势: + +- 便捷性:导出服务提供了一种简单易用的方式来从 TiDB Cloud Serverless 集群导出数据,无需额外的工具或资源。 +- 隔离性:导出服务使用独立的计算资源,确保与您的在线服务资源隔离。 +- 一致性:导出服务确保导出数据的一致性,且不会造成锁定,不影响您的在线服务。 + +> **注意:** +> +> 目前最大导出大小为 1 TiB。如需导出更多数据或请求更高的导出速度,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +## 导出位置 + +您可以将数据导出到以下位置: + +- 本地文件 +- 外部存储,包括: + + - [Amazon S3](https://aws.amazon.com/s3/) + - [Google Cloud Storage](https://cloud.google.com/storage) + - [Azure Blob Storage](https://azure.microsoft.com/en-us/services/storage/blobs/) + - [阿里云对象存储服务(OSS)](https://www.alibabacloud.com/product/oss) + +> **注意:** +> +> 如果要导出的数据量较大(超过 100 GiB),建议导出到外部存储。 + +### 本地文件 + +要将数据从 TiDB Cloud Serverless 集群导出到本地文件,您需要[使用 TiDB Cloud 控制台](#导出数据到本地文件)或[使用 TiDB Cloud CLI](/tidb-cloud/ticloud-serverless-export-create.md) 导出数据,然后使用 TiDB Cloud CLI 下载导出的数据。 + +导出数据到本地文件有以下限制: + +- 不支持使用 TiDB Cloud 控制台下载导出的数据。 +- 导出的数据保存在 TiDB Cloud 的暂存区域,两天后过期。您需要及时下载导出的数据。 +- 如果暂存区域的存储空间已满,您将无法导出数据到本地文件。 + +### Amazon S3 + +要导出数据到 Amazon S3,您需要提供以下信息: + +- URI:`s3:////` +- 以下访问凭证之一: + - [访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html):确保访问密钥具有 `s3:PutObject` 和 `s3:ListBucket` 权限。 + - [角色 ARN](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html):确保角色 ARN(Amazon Resource Name)具有 `s3:PutObject` 和 `s3:ListBucket` 权限。注意,只有托管在 AWS 上的集群支持角色 ARN。 + +更多信息,请参见[配置 Amazon S3 访问](/tidb-cloud/serverless-external-storage.md#configure-amazon-s3-access)。 + +### Google Cloud Storage + +要导出数据到 Google Cloud Storage,您需要提供以下信息: + +- URI:`gs:////` +- 访问凭证:存储桶的 **base64 编码**[服务账号密钥](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)。确保服务账号密钥具有 `storage.objects.create` 权限。 + +更多信息,请参见[配置 GCS 访问](/tidb-cloud/serverless-external-storage.md#configure-gcs-access)。 + +### Azure Blob Storage + +要导出数据到 Azure Blob Storage,您需要提供以下信息: + +- URI:`azure://.blob.core.windows.net///` 或 `https://.blob.core.windows.net///` +- 访问凭证:Azure Blob Storage 容器的[共享访问签名(SAS)令牌](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview)。确保 SAS 令牌对 `Container` 和 `Object` 资源具有 `Read` 和 `Write` 权限。 + +更多信息,请参见[配置 Azure Blob Storage 访问](/tidb-cloud/serverless-external-storage.md#configure-azure-blob-storage-access)。 + +### 阿里云 OSS + +要导出数据到阿里云 OSS,您需要提供以下信息: + +- URI:`oss:////` +- 访问凭证:阿里云账号的 [AccessKey 对](https://www.alibabacloud.com/help/en/ram/user-guide/create-an-accesskey-pair)。确保 AccessKey 对具有 `oss:PutObject`、`oss:ListBuckets` 和 `oss:GetBucketInfo` 权限,以允许将数据导出到 OSS 存储桶。 + +更多信息,请参见[配置阿里云对象存储服务(OSS)访问](/tidb-cloud/serverless-external-storage.md#configure-alibaba-cloud-object-storage-service-oss-access)。 + +## 导出选项 + +### 数据过滤 + +- TiDB Cloud 控制台支持导出选定的数据库和表。 +- TiDB Cloud CLI 支持使用 SQL 语句和[表过滤器](/table-filter.md)导出数据。 + +### 数据格式 + +您可以将数据导出为以下格式: + +- `SQL`:以 SQL 格式导出数据。 +- `CSV`:以 CSV 格式导出数据。您可以指定以下选项: + - `delimiter`:指定导出数据中使用的分隔符。默认分隔符为 `"`。 + - `separator`:指定导出数据中用于分隔字段的字符。默认分隔符为 `,`。 + - `header`:指定是否在导出数据中包含标题行。默认值为 `true`。 + - `null-value`:指定导出数据中表示 NULL 值的字符串。默认值为 `\N`。 +- `Parquet`:以 Parquet 格式导出数据。 + +模式和数据的导出遵循以下命名约定: + +| 项目 | 未压缩 | 已压缩 | +|-----------------|-------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------| +| 数据库模式 | {database}-schema-create.sql | {database}-schema-create.sql.{compression-type} | +| 表模式 | {database}.{table}-schema.sql | {database}.{table}-schema.sql.{compression-type} | +| 数据 | {database}.{table}.{0001}.{csv|parquet|sql} | {database}.{table}.{0001}.{csv|sql}.{compression-type}
{database}.{table}.{0001}.{compression-type}.parquet | + +### 数据压缩 + +您可以使用以下算法压缩导出的 CSV 和 SQL 数据: + +- `gzip`(默认):使用 `gzip` 压缩导出的数据。 +- `snappy`:使用 `snappy` 压缩导出的数据。 +- `zstd`:使用 `zstd` 压缩导出的数据。 +- `none`:不压缩导出的数据。 + +您可以使用以下算法压缩导出的 Parquet 数据: + +- `zstd`(默认):使用 `zstd` 压缩 Parquet 文件。 +- `gzip`:使用 `gzip` 压缩 Parquet 文件。 +- `snappy`:使用 `snappy` 压缩 Parquet 文件。 +- `none`:不压缩 Parquet 文件。 + +### 数据转换 + +在导出数据到 Parquet 格式时,TiDB Cloud Serverless 和 Parquet 之间的数据转换如下: + +| TiDB Cloud Serverless 类型 | Parquet 基本类型 | Parquet 逻辑类型 | +|----------------------------|-------------------------|----------------------------------------------| +| VARCHAR | BYTE_ARRAY | String(UTF8) | +| TIME | BYTE_ARRAY | String(UTF8) | +| TINYTEXT | BYTE_ARRAY | String(UTF8) | +| MEDIUMTEXT | BYTE_ARRAY | String(UTF8) | +| TEXT | BYTE_ARRAY | String(UTF8) | +| LONGTEXT | BYTE_ARRAY | String(UTF8) | +| SET | BYTE_ARRAY | String(UTF8) | +| JSON | BYTE_ARRAY | String(UTF8) | +| DATE | BYTE_ARRAY | String(UTF8) | +| CHAR | BYTE_ARRAY | String(UTF8) | +| VECTOR | BYTE_ARRAY | String(UTF8) | +| DECIMAL(1<=p<=9) | INT32 | DECIMAL(p,s) | +| DECIMAL(10<=p<=18) | INT64 | DECIMAL(p,s) | +| DECIMAL(p>=19) | BYTE_ARRAY | String(UTF8) | +| ENUM | BYTE_ARRAY | String(UTF8) | +| TIMESTAMP | INT64 | TIMESTAMP(unit=MICROS,isAdjustedToUTC=false) | +| DATETIME | INT64 | TIMESTAMP(unit=MICROS,isAdjustedToUTC=false) | +| YEAR | INT32 | / | +| TINYINT | INT32 | / | +| UNSIGNED TINYINT | INT32 | / | +| SMALLINT | INT32 | / | +| UNSIGNED SMALLINT | INT32 | / | +| MEDIUMINT | INT32 | / | +| UNSIGNED MEDIUMINT | INT32 | / | +| INT | INT32 | / | +| UNSIGNED INT | FIXED_LEN_BYTE_ARRAY(9) | DECIMAL(20,0) | +| BIGINT | FIXED_LEN_BYTE_ARRAY(9) | DECIMAL(20,0) | +| UNSIGNED BIGINT | BYTE_ARRAY | String(UTF8) | +| FLOAT | FLOAT | / | +| DOUBLE | DOUBLE | / | +| BLOB | BYTE_ARRAY | / | +| TINYBLOB | BYTE_ARRAY | / | +| MEDIUMBLOB | BYTE_ARRAY | / | +| LONGBLOB | BYTE_ARRAY | / | +| BINARY | BYTE_ARRAY | / | +| VARBINARY | BYTE_ARRAY | / | +| BIT | BYTE_ARRAY | / | + +## 示例 + +### 导出数据到本地文件 + + +
+ +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +3. 在**导入**页面,点击右上角的**导出数据到**,然后从下拉列表中选择**本地文件**。填写以下参数: + + - **任务名称**:输入导出任务的名称。默认值为 `SNAPSHOT_{snapshot_time}`。 + - **导出数据**:选择要导出的数据库和表。 + - **数据格式**:选择 **SQL**、**CSV** 或 **Parquet**。 + - **压缩**:选择 **Gzip**、**Snappy**、**Zstd** 或 **None**。 + + > **提示:** + > + > 如果您的集群之前没有导入或导出任何数据,您需要点击页面底部的**点击此处导出数据到...**来导出数据。 + +4. 点击**导出**。 + +5. 导出任务成功后,您可以复制导出任务详情中显示的下载命令,然后在 [TiDB Cloud CLI](/tidb-cloud/cli-reference.md) 中运行该命令下载导出的数据。 + +
+ +
+ +1. 创建导出任务: + + ```shell + ticloud serverless export create -c + ``` + + 您将从输出中获得导出 ID。 + +2. 导出任务成功后,将导出的数据下载到本地文件: + + ```shell + ticloud serverless export download -c -e + ``` + + 有关下载命令的更多信息,请参见 [ticloud serverless export download](/tidb-cloud/ticloud-serverless-export-download.md)。 + +
+
+ +### 导出数据到 Amazon S3 + + +
+ +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +3. 在**导入**页面,点击右上角的**导出数据到**,然后从下拉列表中选择 **Amazon S3**。填写以下参数: + + - **任务名称**:输入导出任务的名称。默认值为 `SNAPSHOT_{snapshot_time}`。 + - **导出数据**:选择要导出的数据库和表。 + - **数据格式**:选择 **SQL**、**CSV** 或 **Parquet**。 + - **压缩**:选择 **Gzip**、**Snappy**、**Zstd** 或 **None**。 + - **文件夹 URI**:输入 Amazon S3 的 URI,格式为 `s3:////`。 + - **存储桶访问**:选择以下访问凭证之一,然后填写凭证信息: + - **AWS 角色 ARN**:输入具有访问存储桶权限的角色 ARN。建议使用 AWS CloudFormation 创建角色 ARN。更多信息,请参见[配置 TiDB Cloud Serverless 的外部存储访问](/tidb-cloud/serverless-external-storage.md#configure-amazon-s3-access)。 + - **AWS 访问密钥**:输入具有访问存储桶权限的访问密钥 ID 和访问密钥密钥。 + +4. 点击**导出**。 + +
+ +
+ +```shell +ticloud serverless export create -c --target-type S3 --s3.uri --s3.access-key-id --s3.secret-access-key --filter "database.table" + +ticloud serverless export create -c --target-type S3 --s3.uri --s3.role-arn --filter "database.table" +``` + +- `s3.uri`:Amazon S3 URI,格式为 `s3:////`。 +- `s3.access-key-id`:具有访问存储桶权限的用户的访问密钥 ID。 +- `s3.secret-access-key`:具有访问存储桶权限的用户的访问密钥密钥。 +- `s3.role-arn`:具有访问存储桶权限的角色 ARN。 + +
+
+ +### 导出数据到 Google Cloud Storage + + +
+ +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +3. 在**导入**页面,点击右上角的**导出数据到**,然后从下拉列表中选择 **Google Cloud Storage**。填写以下参数: + + - **任务名称**:输入导出任务的名称。默认值为 `SNAPSHOT_{snapshot_time}`。 + - **导出数据**:选择要导出的数据库和表。 + - **数据格式**:选择 **SQL**、**CSV** 或 **Parquet**。 + - **压缩**:选择 **Gzip**、**Snappy**、**Zstd** 或 **None**。 + - **文件夹 URI**:输入 Google Cloud Storage 的 URI,格式为 `gs:////`。 + - **存储桶访问**:上传具有访问存储桶权限的 Google Cloud 凭证文件。 + +4. 点击**导出**。 + +
+ +
+ +```shell +ticloud serverless export create -c --target-type GCS --gcs.uri --gcs.service-account-key --filter "database.table" +``` + +- `gcs.uri`:Google Cloud Storage 存储桶的 URI,格式为 `gs:////`。 +- `gcs.service-account-key`:base64 编码的服务账号密钥。 + +
+
+ +### 导出数据到 Azure Blob Storage + + +
+ +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +3. 在**导入**页面,点击右上角的**导出数据到**,然后从下拉列表中选择 **Azure Blob Storage**。填写以下参数: + + - **任务名称**:输入导出任务的名称。默认值为 `SNAPSHOT_{snapshot_time}`。 + - **导出数据**:选择要导出的数据库和表。 + - **数据格式**:选择 **SQL**、**CSV** 或 **Parquet**。 + - **压缩**:选择 **Gzip**、**Snappy**、**Zstd** 或 **None**。 + - **文件夹 URI**:输入 Azure Blob Storage 的 URI,格式为 `azure://.blob.core.windows.net///`。 + - **SAS 令牌**:输入具有访问容器权限的 SAS 令牌。建议使用 [Azure ARM 模板](https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/)创建 SAS 令牌。更多信息,请参见[配置 TiDB Cloud Serverless 的外部存储访问](/tidb-cloud/serverless-external-storage.md#configure-azure-blob-storage-access)。 + +4. 点击**导出**。 + +
+ +
+ +```shell +ticloud serverless export create -c --target-type AZURE_BLOB --azblob.uri --azblob.sas-token --filter "database.table" +``` + +- `azblob.uri`:Azure Blob Storage 的 URI,格式为 `(azure|https)://.blob.core.windows.net///`。 +- `azblob.sas-token`:Azure Blob Storage 的账号 SAS 令牌。 + +
+
+ +### 导出数据到阿里云 OSS + + +
+ +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +3. 在**导入**页面,点击右上角的**导出数据到**,然后从下拉列表中选择**阿里云 OSS**。 + +4. 填写以下参数: + + - **任务名称**:输入导出任务的名称。默认值为 `SNAPSHOT_{snapshot_time}`。 + - **导出数据**:选择要导出的数据库和表。 + - **数据格式**:选择 **SQL**、**CSV** 或 **Parquet**。 + - **压缩**:选择 **Gzip**、**Snappy**、**Zstd** 或 **None**。 + - **文件夹 URI**:输入要导出数据的阿里云 OSS URI,格式为 `oss:////`。 + - **AccessKey ID** 和 **AccessKey Secret**:输入具有访问存储桶权限的 AccessKey ID 和 AccessKey Secret。 + +5. 点击**导出**。 + +
+ +
+ +```shell +ticloud serverless export create -c --target-type OSS --oss.uri --oss.access-key-id --oss.access-key-secret --filter "database.table" +``` + +- `oss.uri`:要导出数据的阿里云 OSS URI,格式为 `oss:////`。 +- `oss.access-key-id`:具有访问存储桶权限的用户的 AccessKey ID。 +- `oss.access-key-secret`:具有访问存储桶权限的用户的 AccessKey Secret。 + +
+
+ +### 取消导出任务 + +要取消正在进行的导出任务,请执行以下步骤: + + +
+ +1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +3. 在**导入**页面,点击**导出**查看导出任务列表。 + +4. 选择要取消的导出任务,然后点击**操作**。 + +5. 从下拉列表中选择**取消**。注意,您只能取消处于**运行中**状态的导出任务。 + +
+ +
+ +```shell +ticloud serverless export cancel -c -e +``` + +
+
+ +## 导出速度 + +导出速度取决于您的[集群套餐](/tidb-cloud/select-cluster-tier.md#cluster-plans)。详情请参见下表: + +| 套餐 | 导出速度 | +|:-------------------|:-------------------| +| 免费集群套餐 | 最高 25 MiB/s | +| 可扩展集群套餐 | 最高 100 MiB/s | + +## 定价 + +导出服务在 beta 期间免费。您只需为成功或已取消的导出任务过程中产生的[请求单元(RU)](/tidb-cloud/tidb-cloud-glossary.md#request-unit)付费。对于失败的导出任务,您将不会被收费。 diff --git a/tidb-cloud/serverless-external-storage.md b/tidb-cloud/serverless-external-storage.md new file mode 100644 index 000000000000..37cd227ad15a --- /dev/null +++ b/tidb-cloud/serverless-external-storage.md @@ -0,0 +1,294 @@ +--- +title: 配置 TiDB Cloud Serverless 外部存储访问 +summary: 了解如何配置 Amazon Simple Storage Service (Amazon S3) 访问。 +--- + +# 配置 TiDB Cloud Serverless 的外部存储访问 + +如果你想在 TiDB Cloud Serverless 集群中从外部存储导入数据或将数据导出到外部存储,你需要配置跨账户访问。本文档描述了如何为 TiDB Cloud Serverless 集群配置外部存储访问。 + +如果你需要为 TiDB Cloud Dedicated 集群配置这些外部存储,请参见[配置 TiDB Cloud Dedicated 的外部存储访问](/tidb-cloud/dedicated-external-storage.md)。 + +## 配置 Amazon S3 访问 + +要允许 TiDB Cloud Serverless 集群访问你的 Amazon S3 存储桶中的源数据,请使用以下任一方法为集群配置存储桶访问: + +- [使用角色 ARN](#使用角色-arn-配置-amazon-s3-访问):使用角色 ARN 访问你的 Amazon S3 存储桶。 +- [使用 AWS 访问密钥](#使用-aws-访问密钥配置-amazon-s3-访问):使用 IAM 用户的访问密钥访问你的 Amazon S3 存储桶。 + +### 使用角色 ARN 配置 Amazon S3 访问 + +建议你使用 [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) 创建角色 ARN。按照以下步骤创建: + +> **注意:** +> +> 角色 ARN 访问 Amazon S3 仅支持云提供商为 AWS 的集群。如果你使用其他云提供商,请改用 AWS 访问密钥。更多信息,请参见[使用 AWS 访问密钥配置 Amazon S3 访问](#使用-aws-访问密钥配置-amazon-s3-访问)。 + +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/) 并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + 2. 点击目标集群的名称以进入其概览页面,然后在左侧导航栏中点击 **Data** > **Import**。 + +2. 打开**添加新 ARN**对话框。 + + - 如果你想从 Amazon S3 导入数据,按以下步骤打开**添加新 ARN**对话框: + + 1. 点击**从 S3 导入**。 + 2. 填写**文件 URI**字段。 + 3. 选择 **AWS Role ARN** 并点击**点击此处使用 AWS CloudFormation 创建新的**。 + + - 如果你想将数据导出到 Amazon S3,按以下步骤打开**添加新 ARN**对话框: + + 1. 点击**导出数据到...** > **Amazon S3**。如果你的集群之前从未导入或导出过任何数据,请点击页面底部的**点击此处导出数据到...** > **Amazon S3**。 + 2. 填写**文件夹 URI**字段。 + 3. 选择 **AWS Role ARN** 并点击**点击此处使用 AWS CloudFormation 创建新的**。 + +3. 使用 AWS CloudFormation 模板创建角色 ARN。 + + 1. 在**添加新 ARN**对话框中,点击 **AWS Console with CloudFormation Template**。 + + 2. 登录 [AWS 管理控制台](https://console.aws.amazon.com),你将被重定向到 AWS CloudFormation **快速创建堆栈**页面。 + + 3. 填写**角色名称**。 + + 4. 确认创建新角色并点击**创建堆栈**以创建角色 ARN。 + + 5. CloudFormation 堆栈执行完成后,你可以点击**输出**选项卡,在**值**列中找到角色 ARN 值。 + + ![img.png](/media/tidb-cloud/serverless-external-storage/serverless-role-arn.png) + +如果你在使用 AWS CloudFormation 创建角色 ARN 时遇到任何问题,可以按照以下步骤手动创建: + +
+点击此处查看详细信息 + +1. 在前面说明中描述的**添加新 ARN**对话框中,点击**遇到问题?手动创建角色 ARN**。你将获得 **TiDB Cloud 账户 ID** 和 **TiDB Cloud 外部 ID**。 + +2. 在 AWS 管理控制台中,为你的 Amazon S3 存储桶创建托管策略。 + + 1. 登录 [AWS 管理控制台](https://console.aws.amazon.com/) 并打开 [Amazon S3 控制台](https://console.aws.amazon.com/s3/)。 + + 2. 在**存储桶**列表中,选择包含源数据的存储桶名称,然后点击**复制 ARN**以获取你的 S3 存储桶 ARN(例如,`arn:aws:s3:::tidb-cloud-source-data`)。记下存储桶 ARN 以供后续使用。 + + ![复制存储桶 ARN](/media/tidb-cloud/copy-bucket-arn.png) + + 3. 打开 [IAM 控制台](https://console.aws.amazon.com/iam/),在左侧导航栏中点击**策略**,然后点击**创建策略**。 + + ![创建策略](/media/tidb-cloud/aws-create-policy.png) + + 4. 在**创建策略**页面,点击 **JSON** 选项卡。 + + 5. 根据你的需求在策略文本字段中配置策略。以下是一个可用于从 TiDB Cloud Serverless 集群导出数据和导入数据的示例。 + + - 从 TiDB Cloud Serverless 集群导出数据需要 **s3:PutObject** 和 **s3:ListBucket** 权限。 + - 将数据导入 TiDB Cloud Serverless 集群需要 **s3:GetObject**、**s3:GetObjectVersion** 和 **s3:ListBucket** 权限。 + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion", + "s3:PutObject" + ], + "Resource": "//*" + }, + { + "Sid": "VisualEditor1", + "Effect": "Allow", + "Action": [ + "s3:ListBucket" + ], + "Resource": "" + } + ] + } + ``` + + 在策略文本字段中,将以下配置替换为你自己的值。 + + - `"Resource": "//*"`。例如: + + - 如果你的源数据存储在 `tidb-cloud-source-data` 存储桶的根目录中,使用 `"Resource": "arn:aws:s3:::tidb-cloud-source-data/*"`。 + - 如果你的源数据存储在存储桶的 `mydata` 目录中,使用 `"Resource": "arn:aws:s3:::tidb-cloud-source-data/mydata/*"`。 + + 确保在目录末尾添加 `/*`,以便 TiDB Cloud 可以访问此目录中的所有文件。 + + - `"Resource": ""`,例如 `"Resource": "arn:aws:s3:::tidb-cloud-source-data"`。 + + - 如果你已启用带有客户管理密钥加密的 AWS Key Management Service 密钥(SSE-KMS),请确保策略中包含以下配置。`"arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f"` 是存储桶的示例 KMS 密钥。 + + ``` + { + "Sid": "AllowKMSkey", + "Effect": "Allow", + "Action": [ + "kms:Decrypt" + ], + "Resource": "arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f" + } + ``` + + - 如果你的存储桶中的对象是从另一个加密存储桶复制的,KMS 密钥值需要包含两个存储桶的密钥。例如,`"Resource": ["arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f","arn:aws:kms:ap-northeast-1:495580073302:key/0d7926a7-6ecc-4bf7-a9c1-a38f0faec0cd"]`。 + + 6. 点击**下一步**。 + + 7. 设置策略名称,添加策略标签(可选),然后点击**创建策略**。 + +3. 在 AWS 管理控制台中,为 TiDB Cloud 创建访问角色并获取角色 ARN。 + + 1. 在 [IAM 控制台](https://console.aws.amazon.com/iam/)中,在左侧导航栏中点击**角色**,然后点击**创建角色**。 + + ![创建角色](/media/tidb-cloud/aws-create-role.png) + + 2. 要创建角色,填写以下信息: + + - 在**可信实体类型**中,选择 **AWS 账户**。 + - 在 **AWS 账户**中,选择**其他 AWS 账户**,然后将 TiDB Cloud 账户 ID 粘贴到**账户 ID**字段中。 + - 在**选项**中,点击**需要外部 ID(当第三方将承担此角色时的最佳实践)**,然后将 TiDB Cloud 外部 ID 粘贴到**外部 ID**字段中。如果创建角色时没有需要外部 ID,一旦为项目中的一个 TiDB 集群完成配置,该项目中的所有 TiDB 集群都可以使用相同的角色 ARN 访问你的 Amazon S3 存储桶。如果使用账户 ID 和外部 ID 创建角色,则只有相应的 TiDB 集群可以访问存储桶。 + + 3. 点击**下一步**打开策略列表,选择你刚刚创建的策略,然后点击**下一步**。 + + 4. 在**角色详细信息**中,为角色设置名称,然后点击右下角的**创建角色**。创建角色后,将显示角色列表。 + + 5. 在角色列表中,点击你刚刚创建的角色名称以进入其摘要页面,然后你可以获取角色 ARN。 + + ![复制 AWS 角色 ARN](/media/tidb-cloud/aws-role-arn.png) + +
+ +### 使用 AWS 访问密钥配置 Amazon S3 访问 + +建议你使用 IAM 用户(而不是 AWS 账户根用户)创建访问密钥。 + +按照以下步骤配置访问密钥: + +1. 创建 IAM 用户。更多信息,请参见[创建 IAM 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console)。 + +2. 使用你的 AWS 账户 ID 或账户别名以及你的 IAM 用户名和密码登录 [IAM 控制台](https://console.aws.amazon.com/iam)。 + +3. 创建访问密钥。更多信息,请参见[为 IAM 用户创建访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey)。 + +> **注意:** +> +> TiDB Cloud 不会存储你的访问密钥。建议你在导入或导出完成后[删除访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey)。 + +## 配置 GCS 访问 + +要允许 TiDB Cloud Serverless 集群访问你的 GCS 存储桶,你需要为存储桶配置 GCS 访问。你可以使用服务账号密钥配置存储桶访问: + +按照以下步骤配置服务账号密钥: + +1. 在 Google Cloud [服务账号页面](https://console.cloud.google.com/iam-admin/serviceaccounts),点击**创建服务账号**以创建服务账号。更多信息,请参见[创建服务账号](https://cloud.google.com/iam/docs/creating-managing-service-accounts)。 + + 1. 输入服务账号名称。 + 2. 可选:输入服务账号的描述。 + 3. 点击**创建并继续**以创建服务账号。 + 4. 在`授予此服务账号对项目的访问权限`中,选择具有所需权限的 [IAM 角色](https://cloud.google.com/iam/docs/understanding-roles)。 + + - 从 TiDB Cloud Serverless 集群导出数据需要具有 `storage.objects.create` 权限的角色。 + - 将数据导入 TiDB Cloud Serverless 集群需要具有 `storage.buckets.get`、`storage.objects.get` 和 `storage.objects.list` 权限的角色。 + + 5. 点击**继续**进入下一步。 + 6. 可选:在`授予用户访问此服务账号的权限`中,选择需要[将服务账号附加到其他资源](https://cloud.google.com/iam/docs/attach-service-accounts)的成员。 + 7. 点击**完成**以完成服务账号创建。 + + ![service-account](/media/tidb-cloud/serverless-external-storage/gcs-service-account.png) + +2. 点击服务账号,然后在`密钥`页面点击**添加密钥**以创建服务账号密钥。 + + ![service-account-key](/media/tidb-cloud/serverless-external-storage/gcs-service-account-key.png) + +3. 选择默认的 `JSON` 密钥类型,然后点击**创建**以下载 Google Cloud 凭证文件。该文件包含配置 TiDB Cloud Serverless 集群的 GCS 访问时需要使用的服务账号密钥。 + +## 配置 Azure Blob Storage 访问 + +要允许 TiDB Cloud Serverless 访问你的 Azure Blob 容器,你需要为容器创建服务 SAS 令牌。 + +你可以使用 [Azure ARM 模板](https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/overview)(推荐)或手动配置创建 SAS 令牌。 + +要使用 Azure ARM 模板创建 SAS 令牌,请按照以下步骤操作: + +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/) 并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + 2. 点击目标集群的名称以进入其概览页面,然后在左侧导航栏中点击 **Data** > **Import**。 + +2. 打开**通过 ARM 模板部署生成新的 SAS 令牌**对话框。 + + 1. 点击**导出数据到...** > **Azure Blob Storage**。如果你的集群之前从未导入或导出过任何数据,请点击页面底部的**点击此处导出数据到...** > **Azure Blob Storage**。 + + 2. 滚动到 **Azure Blob Storage 设置**区域,然后在 SAS 令牌字段下点击**点击此处使用 Azure ARM 模板创建新的**。 + +3. 使用 Azure ARM 模板创建 SAS 令牌。 + + 1. 在**通过 ARM 模板部署生成新的 SAS 令牌**对话框中,点击**点击打开预配置 ARM 模板的 Azure 门户**。 + + 2. 登录 Azure 后,你将被重定向到 Azure **自定义部署**页面。 + + 3. 在**自定义部署**页面中填写**资源组**和**存储账号名称**。你可以从容器所在的存储账号概览页面获取所有信息。 + + ![azure-storage-account-overview](/media/tidb-cloud/serverless-external-storage/azure-storage-account-overview.png) + + 4. 点击**查看 + 创建**或**下一步**以查看部署。点击**创建**开始部署。 + + 5. 完成后,你将被重定向到部署概览页面。导航到**输出**部分以获取 SAS 令牌。 + +如果你在使用 Azure ARM 模板创建 SAS 令牌时遇到任何问题,请按照以下步骤手动创建: + +
+点击此处查看详细信息 + +1. 在 [Azure 存储账号](https://portal.azure.com/#browse/Microsoft.Storage%2FStorageAccounts)页面,点击容器所属的存储账号。 + +2. 在你的**存储账号**页面,点击**安全性 + 网络**,然后点击**共享访问签名**。 + + ![sas-position](/media/tidb-cloud/serverless-external-storage/azure-sas-position.png) + +3. 在**共享访问签名**页面,按如下方式创建具有所需权限的服务 SAS 令牌。更多信息,请参见[创建服务 SAS 令牌](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview)。 + + 1. 在**允许的服务**部分,选择 **Blob** 服务。 + 2. 在**允许的资源类型**部分,选择**容器**和**对象**。 + 3. 在**允许的权限**部分,根据需要选择权限。 + + - 从 TiDB Cloud Serverless 集群导出数据需要**读取**和**写入**权限。 + - 将数据导入 TiDB Cloud Serverless 集群需要**读取**和**列表**权限。 + + 4. 根据需要调整**开始和到期日期/时间**。 + 5. 其他设置可以保持默认值。 + + ![sas-create](/media/tidb-cloud/serverless-external-storage/azure-sas-create.png) + +4. 点击**生成 SAS 和连接字符串**以生成 SAS 令牌。 + +
+ +## 配置阿里云对象存储服务(OSS)访问 + +要允许 TiDB Cloud Serverless 访问你的阿里云 OSS 存储桶,你需要为存储桶创建 AccessKey 对。 + +按照以下步骤配置 AccessKey 对: + +1. 创建 RAM 用户并获取 AccessKey 对。更多信息,请参见[创建 RAM 用户](https://www.alibabacloud.com/help/en/ram/user-guide/create-a-ram-user)。 + + 在**访问方式**部分,选择**使用永久 AccessKey 访问**。 + +2. 创建具有所需权限的自定义策略。更多信息,请参见[创建自定义策略](https://www.alibabacloud.com/help/en/ram/user-guide/create-a-custom-policy)。 + + - 在**效果**部分,选择**允许**。 + - 在**服务**部分,选择**对象存储服务**。 + - 在**操作**部分,根据需要选择权限。 + + 要将数据导入 TiDB Cloud Serverless 集群,授予 **oss:GetObject**、**oss:GetBucketInfo** 和 **oss:ListObjects** 权限。 + + 要从 TiDB Cloud Serverless 集群导出数据,授予 **oss:PutObject**、**oss:GetBucketInfo** 和 **oss:ListBuckets** 权限。 + + - 在**资源**部分,选择存储桶和存储桶中的对象。 + +3. 将自定义策略附加到 RAM 用户。更多信息,请参见[为 RAM 用户授权](https://www.alibabacloud.com/help/en/ram/user-guide/grant-permissions-to-the-ram-user)。 diff --git a/tidb-cloud/serverless-faqs.md b/tidb-cloud/serverless-faqs.md new file mode 100644 index 000000000000..3b2a4b8cb29b --- /dev/null +++ b/tidb-cloud/serverless-faqs.md @@ -0,0 +1,153 @@ +--- +title: TiDB Cloud Serverless 常见问题 +summary: 了解关于 TiDB Cloud Serverless 的常见问题(FAQ)。 +aliases: ['/tidbcloud/serverless-tier-faqs'] +--- + +# TiDB Cloud Serverless 常见问题 + + + +本文列出了关于 TiDB Cloud Serverless 的最常见问题。 + +## 一般问题 + +### 什么是 TiDB Cloud Serverless? + +TiDB Cloud Serverless 为你和你的组织提供具有完整 HTAP 功能的 TiDB 数据库。它是一个完全托管的、自动扩展的 TiDB 部署,让你可以立即开始使用数据库,无需关心底层节点即可开发和运行应用程序,并根据应用程序的工作负载变化自动扩展。 + +### 如何开始使用 TiDB Cloud Serverless? + +参考 5 分钟[快速上手 TiDB Cloud](/tidb-cloud/tidb-cloud-quickstart.md)。 + +### 我可以在 TiDB Cloud 中创建多少个 TiDB Cloud Serverless 集群? + +对于 TiDB Cloud 中的每个组织,默认情况下最多可以创建五个[免费集群](/tidb-cloud/select-cluster-tier.md#free-cluster-plan)。要创建更多 TiDB Cloud Serverless 集群,你需要添加信用卡并创建[可扩展集群](/tidb-cloud/select-cluster-tier.md#scalable-cluster-plan)以供使用。 + +### TiDB Cloud 的所有功能在 TiDB Cloud Serverless 上都完全支持吗? + +某些 TiDB Cloud 功能在 TiDB Cloud Serverless 上部分支持或不支持。更多信息,请参见 [TiDB Cloud Serverless 限制和配额](/tidb-cloud/serverless-limitations.md)。 + +### TiDB Cloud Serverless 何时会在 AWS 以外的云平台(如 Google Cloud 或 Azure)上可用? + +我们正在积极扩展 TiDB Cloud Serverless 到其他云平台,包括 Google Cloud 和 Azure。但是,由于我们目前专注于填补差距并确保所有环境中的功能无缝运行,因此目前还没有确切的时间表。请放心,我们正在努力使 TiDB Cloud Serverless 在更多云平台上可用,我们会随着进展及时更新社区。 + +### 我在 TiDB Cloud Serverless 可用之前创建了一个 Developer Tier 集群。我还能继续使用我的集群吗? + +是的,你的 Developer Tier 集群已自动迁移到 TiDB Cloud Serverless 集群,为你提供改进的用户体验,而不会中断你之前的使用。 + +### TiDB Cloud Serverless 中的列式存储是什么? + +TiDB Cloud Serverless 中的列式存储作为行式存储的额外副本,确保强一致性。与传统的按行存储数据的行式存储不同,列式存储按列组织数据,优化数据分析任务。 + +列式存储是 TiDB 的一个关键特性,通过无缝融合事务和分析工作负载,实现混合事务和分析处理(HTAP)功能。 + +为了高效管理列式存储数据,TiDB Cloud Serverless 使用独立的弹性 TiFlash 引擎。在查询执行期间,优化器指导集群自动决定是从行式存储还是列式存储中检索数据。 + +### 什么时候应该在 TiDB Cloud Serverless 中使用列式存储? + +在以下场景中,考虑在 TiDB Cloud Serverless 中使用列式存储: + +- 你的工作负载涉及需要高效数据扫描和聚合的分析任务。 +- 你优先考虑提高性能,特别是对于分析工作负载。 +- 你想要将分析处理与事务处理隔离,以防止对事务处理(TP)工作负载的性能影响。独立的列式存储有助于优化这些不同的工作负载模式。 + +在这些场景中,列式存储可以显著提高查询性能,并为系统中的混合工作负载提供无缝体验。 + +### 如何在 TiDB Cloud Serverless 中使用列式存储? + +在 TiDB Cloud Serverless 中使用列式存储与在 TiFlash 中使用类似。你可以在表级和数据库级启用列式存储: + +- 表级:为表分配 TiFlash 副本以启用该特定表的列式存储。 +- 数据库级:为数据库中的所有表配置 TiFlash 副本,以在整个数据库中使用列式存储。 + +为表设置 TiFlash 副本后,TiDB 会自动将数据从该表的行式存储复制到列式存储。这确保了数据一致性并优化了分析查询的性能。 + +有关如何设置 TiFlash 副本的更多信息,请参见[创建 TiFlash 副本](/tiflash/create-tiflash-replicas.md)。 + +## 计费和计量问题 + +### 什么是请求单元? + +TiDB Cloud Serverless 采用按需付费模式,这意味着你只需为存储空间和集群使用付费。在此模式下,所有集群活动(如 SQL 查询、批量操作和后台作业)都以[请求单元(RUs)](/tidb-cloud/tidb-cloud-glossary.md#request-unit)来量化。RU 是对集群上发起的请求的大小和复杂性的抽象度量。更多信息,请参见 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-cloud-serverless-pricing-details/)。 + +### TiDB Cloud Serverless 有免费计划吗? + +对于组织中的前五个 TiDB Cloud Serverless 集群,TiDB Cloud 为每个集群提供以下免费使用配额: + +- 行式存储:5 GiB +- 列式存储:5 GiB +- [请求单元(RUs)](/tidb-cloud/tidb-cloud-glossary.md#request-unit):每月 5000 万 RUs + +如果你使用可扩展集群,超出免费配额的使用将被收费。对于免费集群,一旦达到免费配额,该集群的读写操作将被限制,直到你升级到可扩展集群或在新月份开始时重置使用量。 + +更多信息,请参见 [TiDB Cloud Serverless 使用配额](/tidb-cloud/select-cluster-tier.md#usage-quota)。 + +### 免费计划有什么限制? + +在免费计划下,由于资源不可扩展,集群性能受限。这导致每个查询的内存分配限制为 256 MiB,并可能导致每秒请求单元(RUs)的明显瓶颈。要最大化集群性能并避免这些限制,你可以升级到[可扩展集群](/tidb-cloud/select-cluster-tier.md#scalable-cluster-plan)。 + +### 如何估算我的工作负载所需的 RUs 数量并规划每月预算? + +要获取单个 SQL 语句的 RU 消耗,你可以使用 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md#ru-request-unit-consumption) SQL 语句。但是,需要注意的是,`EXPLAIN ANALYZE` 返回的 RUs 使用量不包括出口 RUs,因为出口使用量是在网关中单独测量的,TiDB 服务器并不知道这些信息。 + +要获取集群使用的 RUs 和存储量,请查看集群概览页面上的**本月使用量**面板。通过此面板中的过去资源使用数据和实时资源使用情况,你可以跟踪集群的资源消耗并估算合理的支出限额。如果免费配额无法满足你的需求,你可以升级到[可扩展集群](/tidb-cloud/select-cluster-tier.md#scalable-cluster-plan)并编辑支出限额。更多信息,请参见 [TiDB Cloud Serverless 使用配额](/tidb-cloud/select-cluster-tier.md#usage-quota)。 + +### 如何优化我的工作负载以最小化消耗的 RUs 数量? + +确保你的查询已按照[优化 SQL 性能](/develop/dev-guide-optimize-sql-overview.md)中的指南进行了仔细优化。要识别消耗最多 RUs 的 SQL 语句,请导航到集群的[**诊断**](/tidb-cloud/tune-performance.md#view-the-diagnosis-page)页面,然后查看 **SQL 语句**标签,你可以在其中观察 SQL 执行情况并按**总 RU**或**平均 RU**查看排名靠前的语句。更多信息,请参见[语句分析](/tidb-cloud/tune-performance.md#statement-analysis)。此外,最小化出口流量的数量对于减少 RUs 消耗也很重要。为此,建议在查询中只返回必要的列和行,这反过来有助于减少网络出口流量。这可以通过仔细选择和过滤要返回的列和行来实现,从而优化网络利用率。 + +### TiDB Cloud Serverless 如何计量存储? + +存储根据 TiDB Cloud Serverless 集群中存储的数据量计量,以每月 GiB 为单位。它通过将所有表和索引的总大小(不包括数据压缩或副本)乘以该月数据存储的小时数来计算。 + +### 为什么在立即删除表或数据库后存储使用量大小保持不变? + +这是因为 TiDB 会在一定时间内保留已删除的表和数据库。这个保留期确保依赖这些表的事务可以继续执行而不会中断。此外,保留期使 [`FLASHBACK TABLE`](/sql-statements/sql-statement-flashback-table.md)/[`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.md) 功能成为可能,允许你恢复误删的表和数据库。 + +### 为什么在我没有主动运行任何查询时也会有 RU 消耗? + +RU 消耗可能发生在各种场景中。一个常见场景是在后台查询期间,例如在 TiDB 实例之间同步架构更改。另一个场景是当某些 Web 控制台功能生成查询时,如加载架构。即使没有明确的用户触发,这些进程也会使用 RUs。 + +### 为什么在我的工作负载稳定时会出现 RU 使用量的峰值? + +RU 使用量的峰值可能是由 TiDB 中必要的后台作业导致的。这些作业,如自动分析表和重建统计信息,是生成优化查询计划所必需的。 + +### 当我的集群耗尽免费配额或超出支出限额时会发生什么? + +一旦集群达到其免费配额或支出限额,集群会立即拒绝任何新的连接尝试,直到增加配额或在新月份开始时重置使用量。在达到配额之前建立的现有连接将保持活动状态,但会经历限制。更多信息,请参见 [TiDB Cloud Serverless 限制和配额](/tidb-cloud/serverless-limitations.md#usage-quota)。 + +### 为什么在导入数据时我观察到 RU 使用量的峰值? + +在 TiDB Cloud Serverless 集群的数据导入过程中,只有在数据成功导入时才会发生 RU 消耗,这导致 RU 使用量出现峰值。 + +### 在 TiDB Cloud Serverless 中使用列式存储涉及哪些成本? + +TiDB Cloud Serverless 中列式存储的定价与行式存储类似。当你使用列式存储时,会创建一个额外的副本来存储你的数据(不包括索引)。从行式存储到列式存储的数据复制不会产生额外费用。 + +有关详细定价信息,请参见 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-serverless-pricing-details/)。 + +### 使用列式存储是否更贵? + +TiDB Cloud Serverless 中的列式存储由于额外副本而产生额外成本,需要更多存储和资源用于数据复制。但是,在运行分析查询时,列式存储变得更具成本效益。 + +根据 TPC-H 基准测试,在列式存储上运行分析查询的成本约为使用行式存储时成本的三分之一。 + +因此,虽然由于额外副本可能会有初始成本,但在分析过程中减少的计算成本可以使其对特定用例更具成本效益。特别是对于有分析需求的用户,列式存储可以显著降低成本,提供可观的成本节省机会。 + +## 安全问题 + +### 我的 TiDB Cloud Serverless 是共享的还是专用的? + +serverless 技术设计用于多租户,所有集群使用的资源是共享的。要获得具有隔离基础设施和资源的托管 TiDB 服务,你可以升级到 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +### TiDB Cloud Serverless 如何确保安全? + +- 你的连接通过传输层安全性(TLS)加密。有关使用 TLS 连接到 TiDB Cloud Serverless 的更多信息,请参见[到 TiDB Cloud Serverless 的 TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md)。 +- TiDB Cloud Serverless 上的所有持久化数据都使用集群运行所在的云提供商的工具进行静态加密。 + +## 维护问题 + +### 我可以升级集群运行的 TiDB 版本吗? + +不可以。TiDB Cloud Serverless 集群会在我们在 TiDB Cloud 上推出新的 TiDB 版本时自动升级。你可以在 [TiDB Cloud 控制台](https://tidbcloud.com/project/clusters)或最新的[发布说明](https://docs.pingcap.com/tidbcloud/tidb-cloud-release-notes)中查看集群运行的 TiDB 版本。或者,你也可以连接到集群并使用 `SELECT version()` 或 `SELECT tidb_version()` 来检查 TiDB 版本。 diff --git a/tidb-cloud/serverless-high-availability.md b/tidb-cloud/serverless-high-availability.md new file mode 100644 index 000000000000..9d51489822ba --- /dev/null +++ b/tidb-cloud/serverless-high-availability.md @@ -0,0 +1,114 @@ +--- +title: TiDB Cloud Serverless 的高可用性 +summary: 了解 TiDB Cloud Serverless 的高可用性架构。探索可用区和区域高可用性选项、自动备份、故障转移流程,以及 TiDB 如何确保数据持久性和业务连续性。 +--- + +# TiDB Cloud Serverless 的高可用性 + +TiDB Cloud Serverless 在设计时就内置了强大的机制来默认维持高可用性和数据持久性,防止单点故障并确保在面对中断时能够持续提供服务。作为基于经过实战检验的 TiDB 开源产品的完全托管服务,它继承了 TiDB 的核心高可用性(HA)特性,并通过额外的云原生功能增强了这些特性。 + +## 概述 + +TiDB 使用 Raft 共识算法来确保高可用性和数据持久性。该算法在多个节点之间一致地复制数据变更,使 TiDB 即使在节点故障或网络分区的情况下也能处理读写请求。这种方法提供了高数据持久性和容错能力。 + +TiDB Cloud Serverless 通过两种类型的高可用性来扩展这些功能,以满足不同的运营需求: + +- **可用区高可用性(默认)**:此选项将所有节点放置在单个可用区内,减少网络延迟。它确保高可用性,无需跨区域的应用程序级冗余,适用于优先考虑单个区域内低延迟的应用程序。可用区高可用性在所有支持 TiDB Cloud Serverless 的区域中都可用。更多信息,请参见[可用区高可用性架构](#可用区高可用性架构)。 + +- **区域高可用性(测试版)**:此选项将节点分布在多个可用区中,提供最大程度的基础设施隔离和冗余。它提供最高级别的可用性,但需要跨区域的应用程序级冗余。如果您需要针对区域内基础设施故障的最大可用性保护,建议选择此选项。请注意,这会增加延迟并可能产生跨区域数据传输费用。此功能仅在支持多可用区的特定区域中可用,且只能在集群创建时启用。更多信息,请参见[区域高可用性架构](#区域高可用性架构)。 + +## 可用区高可用性架构 + +> **注意:** +> +> 可用区高可用性是默认选项,在所有支持 TiDB Cloud Serverless 的 AWS 区域中都可用。 + +当您使用默认的可用区高可用性创建集群时,所有组件(包括 Gateway、TiDB、TiKV 和 TiFlash 计算/写入节点)都在同一可用区中运行。数据平面中这些组件的放置通过虚拟机池提供基础设施冗余,由于组件位置相近,最大限度地减少了故障转移时间和网络延迟。 + +![TiDB Cloud Serverless 可用区高可用性](/media/tidb-cloud/serverless-zonal-high-avaliability-aws.png) + +在可用区高可用性架构中: + +- Placement Driver (PD) 部署在多个可用区中,通过跨区域冗余复制数据确保高可用性。 +- 数据在本地可用区内的 TiKV 服务器和 TiFlash 写入节点之间复制。 +- TiDB 服务器和 TiFlash 计算节点从 TiKV 和 TiFlash 写入节点读取和写入数据,这些节点通过存储级复制得到保护。 + +### 故障转移流程 + +TiDB Cloud Serverless 为您的应用程序确保透明的故障转移流程。在故障转移期间: + +- 创建新的副本来替换失败的副本。 + +- 提供存储服务的服务器从 Amazon S3 上的持久化数据中恢复本地缓存,使系统与副本恢复到一致状态。 + +在存储层,持久化数据会定期推送到 Amazon S3 以实现高持久性。此外,即时更新不仅在多个 TiKV 服务器之间复制,还存储在每个服务器的 EBS 上,这进一步复制了数据以提供额外的持久性。TiDB 通过在毫秒级别内回退和重试来自动解决问题,确保故障转移过程对客户端应用程序保持无缝。 + +网关和计算层是无状态的,因此故障转移涉及立即在其他地方重启它们。应用程序应该实现连接重试逻辑。虽然可用区设置提供了高可用性,但它无法处理整个区域故障。如果区域变得不可用,将会出现停机,直到区域及其依赖的服务恢复。 + +## 区域高可用性架构 + +当您使用区域高可用性创建集群时,关键的 OLTP(在线事务处理)工作负载组件(如 PD 和 TiKV)部署在多个可用区中,以确保冗余复制并最大化可用性。在正常运行期间,Gateway、TiDB 和 TiFlash 计算/写入节点等组件托管在主要可用区中。数据平面中这些组件通过虚拟机池提供基础设施冗余,由于组件位置相近,最大限度地减少了故障转移时间和网络延迟。 + +> **注意:** +> +> - 区域高可用性目前处于测试阶段,仅在 AWS 东京(`ap-northeast-1`)区域可用。 +> - 您只能在集群创建时启用区域高可用性。 + +![TiDB Cloud Serverless 区域高可用性](/media/tidb-cloud/serverless-regional-high-avaliability-aws.png) + +在区域高可用性架构中: + +- Placement Driver (PD) 和 TiKV 部署在多个可用区中,数据始终在区域之间冗余复制,以确保最高级别的可用性。 +- 数据在主要可用区内的 TiFlash 写入节点之间复制。 +- TiDB 服务器和 TiFlash 计算节点从这些 TiKV 和 TiFlash 写入节点读取和写入数据,这些节点通过存储级复制得到保护。 + +### 故障转移流程 + +在罕见的主要区域故障场景中(可能由自然灾害、配置更改、软件问题或硬件故障引起),关键的 OLTP 工作负载组件(包括 Gateway 和 TiDB)会自动在备用可用区中启动。流量会自动重定向到备用区域,以确保快速恢复和维持业务连续性。 + +TiDB Cloud Serverless 通过执行以下操作,在主要区域故障期间最大限度地减少服务中断并确保业务连续性: + +- 在备用可用区中自动创建 Gateway 和 TiDB 的新副本。 +- 使用弹性负载均衡器检测备用可用区中的活动网关副本,并将来自失败主要区域的 OLTP 流量重定向。 + +除了通过 TiKV 复制提供高可用性外,TiKV 实例的部署和配置还确保每个数据副本放置在不同的可用区中。只要有两个可用区正常运行,系统就能保持可用。为了实现高持久性,通过定期将数据备份到 S3 来确保数据持久性。即使两个区域发生故障,存储在 S3 中的数据仍然可以访问和恢复。 + +应用程序不受非主要区域故障的影响,并且不会察觉到此类事件。在主要区域故障期间,Gateway 和 TiDB 在备用可用区中启动以处理工作负载。确保您的应用程序实现重试逻辑,以将新请求重定向到备用可用区中的活动服务器。 + +## 自动备份和持久性 + +数据库备份对于业务连续性和灾难恢复至关重要,有助于保护您的数据免受损坏或意外删除。通过备份,您可以将数据库恢复到保留期内的特定时间点,最大限度地减少数据丢失和停机时间。 + +TiDB Cloud Serverless 提供强大的自动备份机制,以确保持续的数据保护: + +- **每日全量备份**:每天创建一次数据库的完整备份,捕获整个数据库状态。 +- **持续事务日志备份**:事务日志持续备份,大约每 5 分钟一次,具体频率取决于数据库活动。 + +这些自动备份使您能够从全量备份恢复数据库,或通过结合全量备份和持续事务日志从特定时间点恢复。这种灵活性确保您可以将数据库恢复到事件发生前的精确时间点。 + +> **注意:** +> +> 自动备份(包括基于快照的备份和用于时间点恢复(PITR)的持续备份)在 Amazon S3 上执行,提供区域级的高持久性。 + +## 故障期间对会话的影响 + +在故障期间,失败服务器上的进行中事务可能会中断。虽然故障转移对应用程序是透明的,但您必须实现逻辑来处理活动事务期间的可恢复故障。不同的故障场景处理如下: + +- **TiDB 故障**:如果 TiDB 实例发生故障,客户端连接不受影响,因为 TiDB Cloud Serverless 自动通过网关重新路由流量。虽然失败的 TiDB 实例上的事务可能会中断,但系统确保已提交的数据得到保留,新事务由另一个可用的 TiDB 实例处理。 +- **Gateway 故障**:如果 Gateway 发生故障,客户端连接会中断。但是,TiDB Cloud Serverless 网关是无状态的,可以立即在新的区域或服务器中重启。流量会自动重定向到新的网关,最大限度地减少停机时间。 + +建议在您的应用程序中实现重试逻辑以处理可恢复的故障。有关实现详细信息,请参考您的驱动程序或 ORM 文档(例如,[JDBC](https://dev.mysql.com/doc/connector-j/en/connector-j-config-failover.html))。 + +## RTO 和 RPO + +在制定业务连续性计划时,请考虑以下两个关键指标: + +- 恢复时间目标(RTO):应用程序在中断事件后完全恢复所需的最大可接受时间。 +- 恢复点目标(RPO):在从计划外中断事件恢复期间,应用程序可以容忍丢失的最近数据更新的最大可接受时间间隔。 + +下表比较了每种高可用性选项的 RTO 和 RPO: + +| 高可用性架构 | RTO(停机时间) | RPO(数据丢失) | +|--------------------------------|-------------------------------|-----------------| +| 可用区高可用性 | 接近 0 秒 | 0 | +| 区域高可用性 | 通常少于 600 秒 | 0 | diff --git a/tidb-cloud/serverless-limitations.md b/tidb-cloud/serverless-limitations.md new file mode 100644 index 000000000000..53bc223072f1 --- /dev/null +++ b/tidb-cloud/serverless-limitations.md @@ -0,0 +1,78 @@ +--- +title: TiDB Cloud Serverless 限制和配额 +summary: 了解 TiDB Cloud Serverless 的限制。 +aliases: ['/tidbcloud/serverless-tier-limitations'] +--- + +# TiDB Cloud Serverless 限制和配额 + + + +TiDB Cloud Serverless 几乎可以支持所有 TiDB 支持的工作负载,但在 TiDB 自管理或 TiDB Cloud Dedicated 集群与 TiDB Cloud Serverless 集群之间存在一些功能差异。本文档描述了 TiDB Cloud Serverless 的限制。 + +我们正在不断填补 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 之间的功能差距。如果你需要这些差距中的功能或能力,请使用 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 或[联系我们](https://www.pingcap.com/contact-us/?from=en)提出功能请求。 + +## 限制 + +### 审计日志 + +- 目前不支持[数据库审计日志](/tidb-cloud/tidb-cloud-auditing.md)。 + +### 连接 + +- 只能使用[公共端点](/tidb-cloud/connect-via-standard-connection-serverless.md)和[私有端点](/tidb-cloud/set-up-private-endpoint-connections-serverless.md)。你不能使用 [VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)连接到 TiDB Cloud Serverless 集群。 +- 不支持 [IP 访问列表](/tidb-cloud/configure-ip-access-list.md)。 + +### 加密 + +- 你的 TiDB Cloud Serverless 集群中持久化的数据使用管理集群的云提供商提供的加密工具进行加密。对于[可扩展集群](/tidb-cloud/select-cluster-tier.md#scalable-cluster-plan),在集群创建过程中可以选择使用第二层加密,在默认的静态加密之外提供额外的安全级别。 +- 目前不支持使用[客户管理的加密密钥 (CMEK)](/tidb-cloud/tidb-cloud-encrypt-cmek.md)。 + +### 维护窗口 + +- 目前不支持[维护窗口](/tidb-cloud/configure-maintenance-window.md)。 + +### 监控和诊断 + +- 目前不支持[第三方监控集成](/tidb-cloud/third-party-monitoring-integrations.md)。 +- 目前不支持[内置告警](/tidb-cloud/monitor-built-in-alerting.md)。 +- 目前不支持 [Key Visualizer](/tidb-cloud/tune-performance.md#key-visualizer)。 +- 目前不支持 [Index Insight](/tidb-cloud/tune-performance.md#index-insight-beta)。 + +### 自助升级 + +- TiDB Cloud Serverless 是 TiDB 的完全托管部署。TiDB Cloud Serverless 的主要和次要版本升级由 TiDB Cloud 处理,因此用户无法主动发起。 + +### 数据流 + +- 目前 TiDB Cloud Serverless 不支持 [Changefeed](/tidb-cloud/changefeed-overview.md)。 +- 目前 TiDB Cloud Serverless 不支持[数据迁移](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +### 生存时间 (TTL) + +- 在 TiDB Cloud Serverless 中,表的 [`TTL_JOB_INTERVAL`](/time-to-live.md#ttl-job) 属性固定为 `15m` 且不能修改。这意味着 TiDB Cloud Serverless 每 15 分钟调度一次后台作业来清理过期数据。 + +### 其他 + +- 事务不能持续超过 30 分钟。 +- 有关 SQL 限制的更多详细信息,请参阅[受限的 SQL 功能](/tidb-cloud/limited-sql-features.md)。 + +## 使用配额 + +对于 TiDB Cloud 中的每个组织,默认最多可以创建五个[免费集群](/tidb-cloud/select-cluster-tier.md#free-cluster-plan)。要创建更多的 TiDB Cloud Serverless 集群,你需要添加信用卡并创建[可扩展集群](/tidb-cloud/select-cluster-tier.md#scalable-cluster-plan)以供使用。 + +对于组织中的前五个 TiDB Cloud Serverless 集群,无论是免费还是可扩展集群,TiDB Cloud 都为每个集群提供以下免费使用配额: + +- 行式存储:5 GiB +- 列式存储:5 GiB +- [请求单位 (RUs)](/tidb-cloud/tidb-cloud-glossary.md#request-unit):每月 5000 万 RU + +请求单位 (RU) 是用于跟踪查询或事务资源消耗的计量单位。它是一个指标,允许你估算处理数据库中特定请求所需的计算资源。请求单位也是 TiDB Cloud Serverless 服务的计费单位。 + +一旦集群达到其使用配额,它会立即拒绝任何新的连接尝试,直到你[增加配额](/tidb-cloud/manage-serverless-spend-limit.md#update-spending-limit)或在新月开始时重置使用量。在达到配额之前建立的现有连接将保持活动状态,但会经历限流。 + +要了解不同资源(包括读取、写入、SQL CPU 和网络出口)的 RU 消耗、定价详情和限流信息,请参阅 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-cloud-serverless-pricing-details)。 + +如果你想创建具有额外配额的 TiDB Cloud Serverless 集群,可以选择可扩展集群计划,并在集群创建页面上编辑支出限制。有关更多信息,请参阅[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)。 + +创建 TiDB Cloud Serverless 集群后,你仍然可以在集群概览页面上查看和编辑支出限制。有关更多信息,请参阅[管理 TiDB Cloud Serverless 集群的支出限制](/tidb-cloud/manage-serverless-spend-limit.md)。 diff --git a/tidb-cloud/set-up-private-endpoint-connections-on-azure.md b/tidb-cloud/set-up-private-endpoint-connections-on-azure.md new file mode 100644 index 000000000000..61600e365f4d --- /dev/null +++ b/tidb-cloud/set-up-private-endpoint-connections-on-azure.md @@ -0,0 +1,123 @@ +--- +title: 通过 Azure Private Link 连接到 TiDB Cloud Dedicated 集群 +summary: 了解如何通过 Azure Private Link 连接到 TiDB Cloud Dedicated 集群。 +--- + +# 通过 Azure Private Link 连接到 TiDB Cloud Dedicated 集群 + +本文档介绍如何通过 [Azure Private Link](https://learn.microsoft.com/en-us/azure/private-link/private-link-overview) 连接到 TiDB Cloud Dedicated 集群。 + +> **提示:** +> +> - 要了解如何通过 AWS 私有端点连接到 TiDB Cloud Dedicated 集群,请参见[通过 AWS PrivateLink 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections.md)。 +> - 要了解如何通过 Google Cloud 私有端点连接到 TiDB Cloud Dedicated 集群,请参见[通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 +> - 要了解如何通过私有端点连接到 TiDB Cloud Serverless 集群,请参见[通过私有端点连接到 TiDB Cloud Serverless](/tidb-cloud/set-up-private-endpoint-connections-serverless.md)。 + +TiDB Cloud 支持通过 [Azure Private Link](https://learn.microsoft.com/en-us/azure/private-link/private-link-overview) 对托管在 Azure 虚拟网络中的 TiDB Cloud 服务进行高度安全和单向访问,就像该服务在您自己的虚拟网络中一样。您可以在您的虚拟网络中创建私有端点,然后通过具有权限的端点连接到 TiDB Cloud 服务。 + +在 Azure Private Link 的支持下,端点连接是安全和私密的,不会将您的数据暴露在公共互联网上。此外,端点连接支持 CIDR 重叠,并且更易于网络管理。 + +Azure Private Link 的架构如下:[^1] + +![Azure Private Link 架构](/media/tidb-cloud/azure-private-endpoint-arch.png) + +有关私有端点和端点服务的更详细定义,请参见以下 Azure 文档: + +- [什么是 Azure Private Link](https://learn.microsoft.com/en-us/azure/private-link/private-link-overview) +- [什么是私有端点](https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-overview) +- [创建私有端点](https://learn.microsoft.com/en-us/azure/private-link/create-private-endpoint-portal?tabs=dynamic-ip) + +## 限制 + +- 只有 `Organization Owner` 和 `Project Owner` 角色可以创建私有端点。 +- 私有端点和要连接的 TiDB 集群必须位于同一区域。 + +## 使用 Azure Private Link 设置私有端点 + +要通过私有端点连接到 TiDB Cloud Dedicated 集群,请完成以下步骤: + +1. [选择 TiDB 集群](#步骤-1-选择-tidb-集群) +2. [创建 Azure 私有端点](#步骤-2-创建-azure-私有端点) +3. [接受端点](#步骤-3-接受端点) +4. [连接到 TiDB 集群](#步骤-4-连接到-tidb-集群) + +如果您有多个集群,则需要对每个要使用 Azure Private Link 连接的集群重复这些步骤。 + +### 步骤 1. 选择 TiDB 集群 + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标 TiDB 集群的名称进入其概览页面。 +2. 点击右上角的**连接**。将显示连接对话框。 +3. 在**连接类型**下拉列表中,选择**私有端点**,然后点击**创建私有端点连接**打开**创建 Azure 私有端点连接**对话框。 + +> **注意:** +> +> 如果您已经创建了私有端点连接,活动端点将显示在连接对话框中。要创建其他私有端点连接,请点击左侧导航栏中的**设置** > **网络**导航到**网络**页面。 + +### 步骤 2. 创建 Azure 私有端点 + +1. 在**创建 Azure 私有端点连接**对话框中,复制私有链接服务的 TiDB Cloud 资源 ID,并保持对话框打开以供后续使用。 + + > **注意:** + > + > 对于每个 TiDB Cloud Dedicated 集群,相应的端点服务会在集群创建后 3 到 4 分钟自动创建。 + +2. 登录 [Azure 门户](https://portal.azure.com/),然后使用复制的 TiDB Cloud 资源 ID 为您的集群创建私有端点,具体步骤如下: + + 1. 在 Azure 门户中,搜索**私有端点**,然后在结果中选择**私有端点**。 + 2. 在**私有端点**页面,点击**+ 创建**。 + 3. 在**基本信息**标签页中,填写项目和实例信息,然后点击**下一步:资源**。 + 4. 在**资源**标签页中,选择**通过资源 ID 或别名连接到 Azure 资源**作为**连接方法**,并将 TiDB Cloud 资源 ID 粘贴到**资源 ID 或别名**字段中。 + 5. 继续点击**下一步**浏览其余配置标签页并完成所需设置。然后,点击**创建**以创建和部署私有端点。Azure 可能需要几秒钟才能完成部署。更多信息,请参见 Azure 文档中的[创建私有端点](https://learn.microsoft.com/en-us/azure/private-link/create-private-endpoint-portal?tabs=dynamic-ip#create-a-private-endpoint)。 + +3. 私有端点创建和部署后,点击**转到资源**,然后执行以下操作: + + - 点击左侧导航栏中的**设置** > **属性**,复制其**资源 ID**以供后续使用。 + + ![Azure 私有端点资源 ID](/media/tidb-cloud/azure-private-endpoint-resource-id.png) + + - 点击左侧导航栏中的**设置** > **DNS 配置**,然后复制其 **IP 地址**以供后续使用。 + + ![Azure 私有端点 DNS IP](/media/tidb-cloud/azure-private-endpoint-dns-ip.png) + +### 步骤 3. 接受端点 + +1. 返回 TiDB Cloud 控制台中的**创建 Azure 私有端点连接**对话框,然后将复制的**资源 ID** 和 **IP 地址**粘贴到相应字段中。 +2. 点击**验证端点**以验证私有端点访问。如果遇到任何错误,请按照错误消息进行故障排除,然后重试。 +3. 验证成功后,点击**接受端点**以批准来自私有端点的连接。 + +### 步骤 4. 连接到 TiDB 集群 + +接受端点连接后,您将被重定向回连接对话框。 + +1. 等待私有端点连接状态变为**活动**(大约 5 分钟)。要检查状态,请点击左侧导航栏中的**设置** > **网络**导航到**网络**页面。 +2. 在**连接方式**下拉列表中,选择您首选的连接方法。对话框底部将显示相应的连接字符串。 +3. 使用连接字符串连接到您的集群。 + +### 私有端点状态参考 + +要查看私有端点或私有端点服务的状态,请点击左侧导航栏中的**设置** > **网络**导航到**网络**页面。 + +私有端点的可能状态说明如下: + +- **已发现**:TiDB Cloud 可以在接受请求之前自动检测与端点服务关联的私有端点,以避免需要创建另一个端点。 +- **等待中**:等待处理。 +- **活动**:您的私有端点已准备就绪可以使用。您无法编辑此状态的私有端点。 +- **删除中**:正在删除私有端点。 +- **失败**:私有端点创建失败。您可以点击该行的**编辑**重试创建。 + +私有端点服务的可能状态说明如下: + +- **创建中**:正在创建端点服务,这需要 3 到 5 分钟。 +- **活动**:端点服务已创建,无论是否已创建私有端点。 + +## 故障排除 + +### TiDB Cloud 无法创建端点服务。我该怎么办? + +端点服务在您打开**创建 Azure 私有端点**页面并选择 TiDB 集群后自动创建。如果显示失败或长时间保持在**创建中**状态,请[提交支持工单](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +### 如果我在设置过程中取消操作,在接受私有端点之前应该怎么做? + +Azure 私有端点连接功能可以自动检测您的私有端点。这意味着在 Azure 门户中[创建 Azure 私有端点](#步骤-2-创建-azure-私有端点)后,如果您在 TiDB Cloud 控制台的**创建 Azure 私有端点连接**对话框中点击**取消**,您仍然可以在**网络**页面上查看已创建的端点。如果取消是无意的,您可以继续配置端点以完成设置。如果取消是有意的,您可以直接在 TiDB Cloud 控制台中删除端点。 + +[^1]: Azure Private Link 架构图来自 Azure 文档中的 [What is Azure Private Link service](https://learn.microsoft.com/en-us/azure/private-link/private-link-service-overview) 文档([GitHub 上的源文件](https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/private-link/private-link-service-overview.md)),根据 Creative Commons Attribution 4.0 International 许可证授权。 diff --git a/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md b/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md new file mode 100644 index 000000000000..c12d26f741c8 --- /dev/null +++ b/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md @@ -0,0 +1,154 @@ +--- +title: 通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群 +summary: 了解如何通过 Google Cloud Private Service Connect 连接到 TiDB Cloud 集群。 +--- + +# 通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群 + +本文介绍如何通过 [Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect) 连接到 TiDB Cloud Dedicated 集群。Google Cloud Private Service Connect 是 Google Cloud 提供的私有端点服务。 + +> **提示:** +> +> - 要了解如何通过 AWS 私有端点连接到 TiDB Cloud Dedicated 集群,请参阅[通过 AWS PrivateLink 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections.md)。 +> - 要了解如何通过 Azure 私有端点连接到 TiDB Cloud Dedicated 集群,请参阅[通过 Azure Private Link 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md)。 +> - 要了解如何通过私有端点连接到 TiDB Cloud Serverless 集群,请参阅[通过私有端点连接到 TiDB Cloud Serverless](/tidb-cloud/set-up-private-endpoint-connections-serverless.md)。 + +TiDB Cloud 支持通过 [Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect) 安全地单向访问托管在 Google Cloud VPC 中的 TiDB Cloud 服务。你可以创建一个端点并使用它连接到 TiDB Cloud 服务。 + +在 Google Cloud Private Service Connect 的支持下,端点连接是安全和私密的,不会将你的数据暴露给公共互联网。此外,端点连接支持 CIDR 重叠,更易于网络管理。 + +Google Cloud Private Service Connect 的架构如下:[^1] + +![Private Service Connect 架构](/media/tidb-cloud/google-cloud-psc-endpoint-overview.png) + +有关私有端点和端点服务的更详细定义,请参阅以下 Google Cloud 文档: + +- [Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect) +- [通过端点访问已发布的服务](https://cloud.google.com/vpc/docs/configure-private-service-connect-services) + +## 限制 + +- 此功能适用于 2023 年 4 月 13 日之后创建的 TiDB Cloud Dedicated 集群。对于较旧的集群,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 +- 只有 `Organization Owner` 和 `Project Owner` 角色可以创建 Google Cloud Private Service Connect 端点。 +- 每个 TiDB 集群最多可以处理来自 10 个端点的连接。 +- 每个 Google Cloud 项目最多可以有 10 个端点连接到一个 TiDB 集群。 +- 在配置了端点服务的项目中,你最多可以创建 8 个托管在 Google Cloud 上的 TiDB Cloud Dedicated 集群。 +- 私有端点和要连接的 TiDB 集群必须位于同一区域。 +- 出站防火墙规则必须允许流量到达端点的内部 IP 地址。[默认允许出站防火墙规则](https://cloud.google.com/firewall/docs/firewalls#default_firewall_rules)允许出站流量到达任何目标 IP 地址。 +- 如果你在 VPC 网络中创建了出站拒绝防火墙规则,或者创建了修改默认允许出站行为的分层防火墙策略,可能会影响对端点的访问。在这种情况下,你需要创建特定的出站允许防火墙规则或策略,以允许流量到达端点的内部目标 IP 地址。 + +在大多数情况下,建议使用私有端点连接而不是 VPC 对等连接。但是,在以下情况下,你应该使用 VPC 对等连接而不是私有端点连接: + +- 你正在使用 [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) 集群跨区域将数据从源 TiDB 集群复制到目标 TiDB 集群,以获得高可用性。目前,私有端点不支持跨区域连接。 +- 你正在使用 TiCDC 集群将数据复制到下游集群(如 Amazon Aurora、MySQL 和 Kafka),但你无法自行维护下游的端点服务。 + +## 使用 Google Cloud Private Service Connect 设置私有端点 + +要通过私有端点连接到 TiDB Cloud Dedicated 集群,请完成[前提条件](#前提条件)并按照以下步骤操作: + +1. [选择 TiDB 集群](#步骤-1-选择-tidb-集群) +2. [创建 Google Cloud 私有端点](#步骤-2-创建-google-cloud-私有端点) +3. [接受端点访问](#步骤-3-接受端点访问) +4. [连接到 TiDB 集群](#步骤-4-连接到-tidb-集群) + +如果你有多个集群,需要对每个要使用 Google Cloud Private Service Connect 连接的集群重复这些步骤。 + +### 前提条件 + +在开始创建端点之前: + +- 在你的 Google Cloud 项目中[启用](https://console.cloud.google.com/apis/library/compute.googleapis.com)以下 API: + - [Compute Engine API](https://cloud.google.com/compute/docs/reference/rest/v1) + - [Service Directory API](https://cloud.google.com/service-directory/docs/reference/rest) + - [Cloud DNS API](https://cloud.google.com/dns/docs/reference/v1) + +- 准备以下具有创建端点所需权限的 [IAM 角色](https://cloud.google.com/iam/docs/understanding-roles)。 + + - 任务: + - 创建端点 + - 自动或手动配置端点的 [DNS 条目](https://cloud.google.com/vpc/docs/configure-private-service-connect-services#dns-endpoint) + - 所需的 IAM 角色: + - [Compute Network Admin](https://cloud.google.com/iam/docs/understanding-roles#compute.networkAdmin) (roles/compute.networkAdmin) + - [Service Directory Editor](https://cloud.google.com/iam/docs/understanding-roles#servicedirectory.editor) (roles/servicedirectory.editor) + +### 步骤 1:选择 TiDB 集群 + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标 TiDB 集群的名称进入其概览页面。你可以选择具有以下任一状态的集群: + + - **可用** + - **恢复中** + - **修改中** + - **导入中** + +2. 点击右上角的**连接**。此时会显示一个连接对话框。 + +3. 在**连接类型**下拉列表中,选择**私有端点**,然后点击**创建私有端点连接**。 + + > **注意:** + > + > 如果你已经创建了私有端点连接,活动端点将显示在连接对话框中。要创建其他私有端点连接,请点击左侧导航栏中的**设置** > **网络**导航到**网络**页面。 + +### 步骤 2:创建 Google Cloud 私有端点 + +1. 提供以下信息以生成私有端点创建命令: + - **Google Cloud 项目 ID**:与你的 Google Cloud 账户关联的项目 ID。你可以在 [Google Cloud **仪表板**页面](https://console.cloud.google.com/home/dashboard)找到该 ID。 + - **Google Cloud VPC 名称**:指定项目中的 VPC 名称。你可以在 [Google Cloud **VPC 网络**页面](https://console.cloud.google.com/networking/networks/list)找到它。 + - **Google Cloud 子网名称**:指定 VPC 中的子网名称。你可以在 **VPC 网络详情**页面找到它。 + - **Private Service Connect 端点名称**:为要创建的私有端点输入一个唯一名称。 +2. 输入信息后,点击**生成命令**。 +3. 复制生成的命令。 +4. 打开 [Google Cloud Shell](https://console.cloud.google.com/home/dashboard) 并执行命令以创建私有端点。 + +### 步骤 3:接受端点访问 + +在 Google Cloud Shell 中成功执行命令后,返回 TiDB Cloud 控制台,然后点击**接受端点访问**。 + +如果你看到错误 `not received connection request from endpoint`,请确保你已正确复制命令并在 Google Cloud Shell 中成功执行。 + +### 步骤 4:连接到 TiDB 集群 + +接受私有端点连接后,你将被重定向回连接对话框。 + +1. 等待私有端点连接状态从**系统检查中**变为**活动**(大约 5 分钟)。 +2. 在**连接方式**下拉列表中,选择你偏好的连接方法。对话框底部将显示相应的连接字符串。 +3. 使用连接字符串连接到你的集群。 + +### 私有端点状态参考 + +使用私有端点连接时,私有端点或私有端点服务的状态会显示在[**私有端点**页面](#前提条件)上。 + +私有端点的可能状态说明如下: + +- **等待中**:等待处理。 +- **活动**:你的私有端点已准备就绪可以使用。你无法编辑此状态的私有端点。 +- **删除中**:正在删除私有端点。 +- **失败**:私有端点创建失败。你可以点击该行的**编辑**重试创建。 + +私有端点服务的可能状态说明如下: + +- **创建中**:正在创建端点服务,需要 3 到 5 分钟。 +- **活动**:端点服务已创建,无论私有端点是否创建。 + +## 故障排除 + +### TiDB Cloud 无法创建端点服务。我该怎么办? + +在你打开**创建 Google Cloud 私有端点连接**页面并选择 TiDB 集群后,端点服务会自动创建。如果显示失败或长时间保持在**创建中**状态,请[提交支持工单](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +### 在 Google Cloud 中创建端点失败。我该怎么办? + +要排查问题,你需要查看在 Google Cloud Shell 中执行私有端点创建命令后返回的错误消息。如果是权限相关的错误,你必须在重试之前授予必要的权限。 + +### 我取消了一些操作。在接受端点访问之前,如何处理取消? + +已取消操作的未保存草稿不会被保留或显示。下次在 TiDB Cloud 控制台创建新的私有端点时,你需要重复每个步骤。 + +如果你已经在 Google Cloud Shell 中执行了创建私有端点的命令,你需要在 Google Cloud 控制台中手动[删除相应的端点](https://cloud.google.com/vpc/docs/configure-private-service-connect-services#delete-endpoint)。 + +### 为什么我在 TiDB Cloud 控制台中看不到通过直接复制服务附件生成的端点? + +在 TiDB Cloud 控制台中,你只能查看通过**创建 Google Cloud 私有端点连接**页面生成的命令创建的端点。 + +但是,通过直接复制服务附件生成的端点(即不是通过 TiDB Cloud 控制台生成的命令创建的)不会显示在 TiDB Cloud 控制台中。 + +[^1]: Google Cloud Private Service Connect 架构图来自 Google Cloud 文档中的 [Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect) 文档,根据 Creative Commons Attribution 4.0 International 许可。 diff --git a/tidb-cloud/set-up-private-endpoint-connections-serverless.md b/tidb-cloud/set-up-private-endpoint-connections-serverless.md new file mode 100644 index 000000000000..18a54088ebad --- /dev/null +++ b/tidb-cloud/set-up-private-endpoint-connections-serverless.md @@ -0,0 +1,127 @@ +--- +title: 通过私有端点连接到 TiDB Cloud Serverless +summary: 了解如何通过私有端点连接到您的 TiDB Cloud 集群。 +--- + +# 通过私有端点连接到 TiDB Cloud Serverless + +本文档介绍如何通过私有端点连接到您的 TiDB Cloud Serverless 集群。 + +> **提示:** +> +> - 要了解如何通过 AWS 私有端点连接到 TiDB Cloud Dedicated 集群,请参阅[通过 AWS PrivateLink 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections.md)。 +> - 要了解如何通过 Azure 私有端点连接到 TiDB Cloud Dedicated 集群,请参阅[通过 Azure Private Link 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md)。 +> - 要了解如何通过 Google Cloud 私有端点连接到 TiDB Cloud Dedicated 集群,请参阅[通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 + +TiDB Cloud 支持通过 [AWS PrivateLink](https://aws.amazon.com/privatelink/?privatelink-blogs.sort-by=item.additionalFields.createdDate&privatelink-blogs.sort-order=desc) 对托管在 AWS VPC 中的 TiDB Cloud 服务进行高度安全的单向访问,就像该服务在您自己的 VPC 中一样。私有端点会在您的 VPC 中公开,您可以通过获得授权的端点连接到 TiDB Cloud 服务。 + +在 AWS PrivateLink 的支持下,端点连接是安全且私密的,不会将您的数据暴露在公共互联网上。此外,端点连接支持 CIDR 重叠,更便于网络管理。 + +私有端点的架构如下: + +![私有端点架构](/media/tidb-cloud/aws-private-endpoint-arch.png) + +有关私有端点和端点服务的更详细定义,请参阅以下 AWS 文档: + +- [什么是 AWS PrivateLink?](https://docs.aws.amazon.com/vpc/latest/privatelink/what-is-privatelink.html) +- [AWS PrivateLink 概念](https://docs.aws.amazon.com/vpc/latest/privatelink/concepts.html) + +## 限制 + +- 目前,TiDB Cloud 仅在端点服务托管在 AWS 时支持通过私有端点连接到 TiDB Cloud Serverless。如果服务托管在 Google Cloud 上,则不适用私有端点。 +- 不支持跨区域的私有端点连接。 + +## 前提条件 + +确保在您的 AWS VPC 设置中启用了 DNS 主机名和 DNS 解析。在 [AWS 管理控制台](https://console.aws.amazon.com/) 中创建 VPC 时,这些功能默认是禁用的。 + +## 使用 AWS 设置私有端点 + +要通过私有端点连接到您的 TiDB Cloud Serverless 集群,请按照以下步骤操作: + +1. [选择 TiDB 集群](#步骤-1-选择-tidb-集群) +2. [创建 AWS 接口端点](#步骤-2-创建-aws-接口端点) +3. [连接到您的 TiDB 集群](#步骤-3-连接到您的-tidb-集群) + +### 步骤 1. 选择 TiDB 集群 + +1. 在[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标 TiDB Cloud Serverless 集群的名称以进入其概览页面。 +2. 点击右上角的**连接**。将显示连接对话框。 +3. 在**连接类型**下拉列表中,选择**私有端点**。 +4. 记下**服务名称**、**可用区 ID** 和**区域 ID**。 + + > **注意:** + > + > 每个 AWS 区域只需要创建一个私有端点,该端点可以由位于同一区域的所有 TiDB Cloud Serverless 集群共享。 + +### 步骤 2. 创建 AWS 接口端点 + + +
+ +要使用 AWS 管理控制台创建 VPC 接口端点,请执行以下步骤: + +1. 登录 [AWS 管理控制台](https://aws.amazon.com/console/),并在 [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/) 打开 Amazon VPC 控制台。 +2. 在导航窗格中点击**端点**,然后点击右上角的**创建端点**。 + + 将显示**创建端点**页面。 + + ![验证端点服务](/media/tidb-cloud/private-endpoint/create-endpoint-2.png) + +3. 选择**使用 NLB 和 GWLB 的端点服务**。 +4. 输入您在[步骤 1](#步骤-1-选择-tidb-集群)中找到的服务名称。 +5. 点击**验证服务**。 +6. 在下拉列表中选择您的 VPC。展开**其他设置**并选中**启用 DNS 名称**复选框。 +7. 在**子网**区域,选择您的 TiDB 集群所在的可用区,并选择子网 ID。 +8. 在**安全组**区域中正确选择您的安全组。 + + > **注意:** + > + > 确保所选安全组允许来自您的 EC2 实例在端口 4000 上的入站访问。 + +9. 点击**创建端点**。 + +
+
+ +要使用 AWS CLI 创建 VPC 接口端点,请执行以下步骤: + +1. 要获取 **VPC ID** 和**子网 ID**,导航到您的 AWS 管理控制台,并在相关部分找到它们。确保填写您在[步骤 1](#步骤-1-选择-tidb-集群)中找到的**可用区 ID**。 +2. 复制下面提供的命令,用您获得的信息替换相关参数,然后在终端中执行它。 + +```bash +aws ec2 create-vpc-endpoint --vpc-id ${your_vpc_id} --region ${region_id} --service-name ${service_name} --vpc-endpoint-type Interface --subnet-ids ${your_subnet_id} +``` + +> **提示:** +> +> 在运行命令之前,您需要安装并配置 AWS CLI。有关详细信息,请参阅 [AWS CLI 配置基础知识](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html)。 + +
+
+ +然后,您可以使用私有 DNS 名称连接到端点服务。 + +### 步骤 3:连接到您的 TiDB 集群 + +创建接口端点后,返回 TiDB Cloud 控制台并执行以下步骤: + +1. 在[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称以进入其概览页面。 +2. 点击右上角的**连接**。将显示连接对话框。 +3. 在**连接类型**下拉列表中,选择**私有端点**。 +4. 在**连接方式**下拉列表中,选择您首选的连接方法。对话框底部将显示相应的连接字符串。 +5. 使用连接字符串连接到您的集群。 + +> **提示:** +> +> 如果您无法连接到集群,原因可能是您在 AWS 中的 VPC 端点的安全组设置不正确。请参阅[此常见问题](#故障排除)获取解决方案。 +> +> 创建 VPC 端点时,如果遇到错误 `private-dns-enabled cannot be set because there is already a conflicting DNS domain for gatewayXX-privatelink.XX.prod.aws.tidbcloud.com in the VPC vpc-XXXXX`,这是因为已经创建了私有端点,无需创建新的端点。 + +## 故障排除 + +### 启用私有 DNS 后无法通过私有端点连接到 TiDB 集群。为什么? + +您可能需要在 AWS 管理控制台中为 VPC 端点正确设置安全组。转到 **VPC** > **端点**。右键单击您的 VPC 端点并选择合适的**管理安全组**。合适的安全组应该是您 VPC 内允许来自 EC2 实例在端口 4000 或客户定义端口上的入站访问的安全组。 + +![管理安全组](/media/tidb-cloud/private-endpoint/manage-security-groups.png) diff --git a/tidb-cloud/set-up-private-endpoint-connections.md b/tidb-cloud/set-up-private-endpoint-connections.md new file mode 100644 index 000000000000..eaa9ee705713 --- /dev/null +++ b/tidb-cloud/set-up-private-endpoint-connections.md @@ -0,0 +1,212 @@ +--- +title: 通过 AWS PrivateLink 连接到 TiDB Cloud Dedicated 集群 +summary: 了解如何通过 AWS 私有端点连接到 TiDB Cloud 集群。 +--- + +# 通过 AWS PrivateLink 连接到 TiDB Cloud Dedicated 集群 + +本文介绍如何通过 [AWS PrivateLink](https://aws.amazon.com/privatelink) 连接到 TiDB Cloud Dedicated 集群。 + +> **提示:** +> +> - 要了解如何通过私有端点连接到 TiDB Cloud Serverless 集群,请参见[通过私有端点连接到 TiDB Cloud Serverless](/tidb-cloud/set-up-private-endpoint-connections-serverless.md)。 +> - 要了解如何通过 Azure 私有端点连接到 TiDB Cloud Dedicated 集群,请参见[通过 Azure Private Link 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md)。 +> - 要了解如何通过 Google Cloud 私有端点连接到 TiDB Cloud Dedicated 集群,请参见[通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 + +TiDB Cloud 支持通过 [AWS PrivateLink](https://aws.amazon.com/privatelink) 安全地单向访问托管在 AWS VPC 中的 TiDB Cloud 服务,就像该服务在您自己的 VPC 中一样。私有端点会在您的 VPC 中公开,您可以通过具有权限的端点连接到 TiDB Cloud 服务。 + +由 AWS PrivateLink 提供支持的端点连接是安全和私密的,不会将您的数据暴露在公共互联网上。此外,端点连接支持 CIDR 重叠,更易于网络管理。 + +私有端点的架构如下: + +![私有端点架构](/media/tidb-cloud/aws-private-endpoint-arch.png) + +有关私有端点和端点服务的更详细定义,请参见以下 AWS 文档: + +- [什么是 AWS PrivateLink?](https://docs.aws.amazon.com/vpc/latest/privatelink/what-is-privatelink.html) +- [AWS PrivateLink 概念](https://docs.aws.amazon.com/vpc/latest/privatelink/concepts.html) + +## 限制 + +- 只有 `Organization Owner` 和 `Project Owner` 角色可以创建私有端点。 +- 私有端点和要连接的 TiDB 集群必须位于同一区域。 + +在大多数情况下,建议使用私有端点连接而不是 VPC 对等连接。但是,在以下情况下,您应该使用 VPC 对等连接而不是私有端点连接: + +- 您正在使用 [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) 集群将数据从源 TiDB 集群复制到跨区域的目标 TiDB 集群,以获得高可用性。目前,私有端点不支持跨区域连接。 +- 您正在使用 TiCDC 集群将数据复制到下游集群(如 Amazon Aurora、MySQL 和 Kafka),但您无法自行维护端点服务。 +- 您正在直接连接到 PD 或 TiKV 节点。 + +## 前提条件 + +确保在 AWS VPC 设置中启用了 DNS 主机名和 DNS 解析。在 [AWS 管理控制台](https://console.aws.amazon.com/) 中创建 VPC 时,这些功能默认是禁用的。 + +## 设置私有端点连接并连接到集群 + +要通过私有端点连接到 TiDB Cloud Dedicated 集群,请完成以下步骤: + +1. [选择 TiDB 集群](#步骤-1-选择-tidb-集群) +2. [创建 AWS 接口端点](#步骤-2-创建-aws-接口端点) +3. [创建私有端点连接](#步骤-3-创建私有端点连接) +4. [启用私有 DNS](#步骤-4-启用私有-dns) +5. [连接到 TiDB 集群](#步骤-5-连接到-tidb-集群) + +如果您有多个集群,则需要对要使用 AWS PrivateLink 连接的每个集群重复这些步骤。 + +### 步骤 1. 选择 TiDB 集群 + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面上,点击目标 TiDB 集群的名称以进入其概览页面。 +2. 点击右上角的**连接**。此时会显示连接对话框。 +3. 在**连接类型**下拉列表中,选择**私有端点**,然后点击**创建私有端点连接**。 + +> **注意:** +> +> 如果您已经创建了私有端点连接,活动端点将显示在连接对话框中。要创建其他私有端点连接,请点击左侧导航栏中的**设置** > **网络**,导航到**网络**页面。 + +### 步骤 2. 创建 AWS 接口端点 + +> **注意:** +> +> 对于 2023 年 3 月 28 日之后创建的每个 TiDB Cloud Dedicated 集群,相应的端点服务会在集群创建后 3 到 4 分钟内自动创建。 + +如果您看到 `TiDB Private Link Service is ready` 消息,则相应的端点服务已准备就绪。您可以提供以下信息来创建端点。 + +1. 填写**您的 VPC ID** 和**您的子网 ID** 字段。您可以从 [AWS 管理控制台](https://console.aws.amazon.com/) 找到这些 ID。对于多个子网,请输入以空格分隔的 ID。 +2. 点击**生成命令**以获取以下端点创建命令。 + + ```bash + aws ec2 create-vpc-endpoint --vpc-id ${your_vpc_id} --region ${your_region} --service-name ${your_endpoint_service_name} --vpc-endpoint-type Interface --subnet-ids ${your_application_subnet_ids} + ``` + +然后,您可以使用 AWS CLI 或 [AWS 管理控制台](https://aws.amazon.com/console/) 创建 AWS 接口端点。 + + +
+ +要使用 AWS CLI 创建 VPC 接口端点,请执行以下步骤: + +1. 复制生成的命令并在终端中运行。 +2. 记录您刚刚创建的 VPC 端点 ID。 + +> **提示:** +> +> - 运行命令之前,您需要安装并配置 AWS CLI。有关详细信息,请参见 [AWS CLI 配置基础知识](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html)。 +> +> - 如果您的服务跨越超过三个可用区(AZ),您将收到一条错误消息,指示 VPC 端点服务不支持子网的可用区。当您选择的区域中除了 TiDB 集群所在的可用区外还有额外的可用区时,就会出现此问题。在这种情况下,您可以联系 [PingCAP 技术支持](https://docs.pingcap.com/tidbcloud/tidb-cloud-support)。 + +
+
+ +要使用 AWS 管理控制台创建 VPC 接口端点,请执行以下步骤: + +1. 登录 [AWS 管理控制台](https://aws.amazon.com/console/),并在 [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/) 打开 Amazon VPC 控制台。 +2. 在导航窗格中点击**端点**,然后点击右上角的**创建端点**。 + + 此时会显示**创建端点**页面。 + + ![验证端点服务](/media/tidb-cloud/private-endpoint/create-endpoint-2.png) + +3. 在**端点设置**区域,如果需要,填写名称标签,然后选择**使用 NLB 和 GWLB 的端点服务**选项。 +4. 在**服务设置**区域,输入生成的命令中的服务名称 `${your_endpoint_service_name}`(`--service-name ${your_endpoint_service_name}`)。 +5. 点击**验证服务**。 +6. 在**网络设置**区域,从下拉列表中选择您的 VPC。 +7. 在**子网**区域,选择 TiDB 集群所在的可用区。 + + > **提示:** + > + > 如果您的服务跨越超过三个可用区(AZ),您可能无法在**子网**区域中选择可用区。当您选择的区域中除了 TiDB 集群所在的可用区外还有额外的可用区时,就会出现此问题。在这种情况下,请联系 [PingCAP 技术支持](https://docs.pingcap.com/tidbcloud/tidb-cloud-support)。 + +8. 在**安全组**区域,正确选择您的安全组。 + + > **注意:** + > + > 确保所选安全组允许来自 EC2 实例的端口 4000 或客户定义端口的入站访问。 + +9. 点击**创建端点**。 + +
+
+ +### 步骤 3. 创建私有端点连接 + +1. 返回 TiDB Cloud 控制台。 +2. 在**创建 AWS 私有端点连接**页面,输入您的 VPC 端点 ID。 +3. 点击**创建私有端点连接**。 + +> **提示:** +> +> 您可以在以下两个页面查看和管理私有端点连接: +> +> - 集群级别的**网络**页面:使用左上角的组合框切换到目标集群,然后点击左侧导航栏中的**设置** > **网络**。 +> - 项目级别的**网络访问**页面:使用左上角的组合框切换到目标项目,然后点击左侧导航栏中的**项目设置** > **网络访问**。 + +### 步骤 4. 启用私有 DNS + +在 AWS 中启用私有 DNS。您可以使用 AWS CLI 或 AWS 管理控制台。 + + +
+ +要使用 AWS CLI 启用私有 DNS,请从**创建私有端点连接**页面复制以下 `aws ec2 modify-vpc-endpoint` 命令并在 AWS CLI 中运行。 + +```bash +aws ec2 modify-vpc-endpoint --vpc-endpoint-id ${your_vpc_endpoint_id} --private-dns-enabled +``` + +或者,您可以在集群的**网络**页面上找到该命令。找到私有端点,然后在**操作**列中点击 **...*** > **启用 DNS**。 + +
+
+ +要在 AWS 管理控制台中启用私有 DNS: + +1. 转到 **VPC** > **端点**。 +2. 右键点击您的端点 ID,然后选择**修改私有 DNS 名称**。 +3. 选中**为此端点启用**复选框。 +4. 点击**保存更改**。 + + ![启用私有 DNS](/media/tidb-cloud/private-endpoint/enable-private-dns.png) + +
+
+ +### 步骤 5. 连接到 TiDB 集群 + +接受私有端点连接后,您将被重定向回连接对话框。 + +1. 等待私有端点连接状态从**系统检查中**变为**活动**(大约 5 分钟)。 +2. 在**连接方式**下拉列表中,选择您首选的连接方法。对话框底部将显示相应的连接字符串。 +3. 使用连接字符串连接到您的集群。 + +> **提示:** +> +> 如果无法连接到集群,原因可能是 AWS 中 VPC 端点的安全组设置不正确。有关解决方案,请参见[此常见问题](#故障排除)。 + +### 私有端点状态参考 + +使用私有端点连接时,私有端点或私有端点服务的状态会显示在以下页面上: + +- 集群级别的**网络**页面:使用左上角的组合框切换到目标集群,然后点击左侧导航栏中的**设置** > **网络**。 +- 项目级别的**网络访问**页面:使用左上角的组合框切换到目标项目,然后点击左侧导航栏中的**项目设置** > **网络访问**。 + +私有端点的可能状态说明如下: + +- **未配置**:已创建端点服务但尚未创建私有端点。 +- **等待中**:等待处理。 +- **活动**:您的私有端点已准备就绪。您无法编辑此状态的私有端点。 +- **删除中**:正在删除私有端点。 +- **失败**:私有端点创建失败。您可以点击该行的**编辑**重试创建。 + +私有端点服务的可能状态说明如下: + +- **创建中**:正在创建端点服务,需要 3 到 5 分钟。 +- **活动**:已创建端点服务,无论是否创建了私有端点。 +- **删除中**:正在删除端点服务或集群,需要 3 到 5 分钟。 + +## 故障排除 + +### 启用私有 DNS 后无法通过私有端点连接到 TiDB 集群。为什么? + +您可能需要在 AWS 管理控制台中为 VPC 端点正确设置安全组。转到 **VPC** > **端点**。右键点击您的 VPC 端点,然后选择适当的**管理安全组**。适当的安全组应该是您 VPC 中允许来自 EC2 实例的端口 4000 或客户定义端口的入站访问的安全组。 + +![管理安全组](/media/tidb-cloud/private-endpoint/manage-security-groups.png) diff --git a/tidb-cloud/set-up-vpc-peering-connections.md b/tidb-cloud/set-up-vpc-peering-connections.md new file mode 100644 index 000000000000..08f659ee2d18 --- /dev/null +++ b/tidb-cloud/set-up-vpc-peering-connections.md @@ -0,0 +1,333 @@ +--- +title: 通过 VPC 对等连接连接到 TiDB Cloud Dedicated +summary: 了解如何通过 VPC 对等连接连接到 TiDB Cloud Dedicated。 +--- + +# 通过 VPC 对等连接连接到 TiDB Cloud Dedicated + +> **注意:** +> +> VPC 对等连接仅适用于在 AWS 和 Google Cloud 上托管的 TiDB Cloud Dedicated 集群。您无法使用 VPC 对等连接连接到在 Azure 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 + +要通过 VPC 对等连接将应用程序连接到 TiDB Cloud,您需要与 TiDB Cloud 建立 [VPC 对等连接](/tidb-cloud/tidb-cloud-glossary.md#vpc-peering)。本文档将指导您在 [AWS](#在-aws-上设置-vpc-对等连接) 和 [Google Cloud](#在-google-cloud-上设置-vpc-对等连接) 上设置 VPC 对等连接,并通过 VPC 对等连接连接到 TiDB Cloud。 + +VPC 对等连接是两个 VPC 之间的网络连接,使您能够使用私有 IP 地址在它们之间路由流量。任一 VPC 中的实例都可以相互通信,就像它们在同一网络中一样。 + +目前,同一项目中同一区域的 TiDB 集群都创建在同一个 VPC 中。因此,一旦在项目的某个区域中设置了 VPC 对等连接,该项目中同一区域创建的所有 TiDB 集群都可以在您的 VPC 中连接。VPC 对等连接的设置因云服务提供商而异。 + +> **提示:** +> +> 要将应用程序连接到 TiDB Cloud,您还可以与 TiDB Cloud 建立[私有端点连接](/tidb-cloud/set-up-private-endpoint-connections.md),这种连接方式安全且私密,不会将您的数据暴露在公共互联网上。建议使用私有端点而不是 VPC 对等连接。 + +## 前提条件:为区域设置 CIDR + +CIDR(无类域间路由)是用于为 TiDB Cloud Dedicated 集群创建 VPC 的 CIDR 块。 + +在向区域添加 VPC 对等连接请求之前,您必须为该区域设置 CIDR 并在该区域创建初始的 TiDB Cloud Dedicated 集群。一旦创建了第一个 Dedicated 集群,TiDB Cloud 将创建该集群的 VPC,允许您建立与应用程序 VPC 的对等连接。 + +您可以在创建第一个 TiDB Cloud Dedicated 集群时设置 CIDR。如果您想在创建集群之前设置 CIDR,请执行以下操作: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **网络访问**。 +3. 在**网络访问**页面,点击**项目 CIDR** 标签页,然后根据您的云服务提供商选择 **AWS** 或 **Google Cloud**。 +4. 在右上角,点击**创建 CIDR**。在**创建 AWS CIDR** 或**创建 Google Cloud CIDR** 对话框中指定区域和 CIDR 值,然后点击**确认**。 + + ![Project-CIDR4](/media/tidb-cloud/Project-CIDR4.png) + + > **注意:** + > + > - 为避免与应用程序所在 VPC 的 CIDR 发生冲突,您需要在此字段中设置不同的项目 CIDR。 + > - 对于 AWS 区域,建议配置 `/16` 到 `/23` 之间的 IP 范围大小。支持的网络地址包括: + > - 10.250.0.0 - 10.251.255.255 + > - 172.16.0.0 - 172.31.255.255 + > - 192.168.0.0 - 192.168.255.255 + > - 对于 Google Cloud 区域,建议配置 `/19` 到 `/20` 之间的 IP 范围大小。如果您想配置 `/16` 到 `/18` 之间的 IP 范围大小,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。支持的网络地址包括: + > - 10.250.0.0 - 10.251.255.255 + > - 172.16.0.0 - 172.17.255.255 + > - 172.30.0.0 - 172.31.255.255 + > - TiDB Cloud 根据区域的 CIDR 块大小限制项目中某个区域的 TiDB Cloud 节点数量。 + +5. 查看云服务提供商和特定区域的 CIDR。 + + CIDR 默认处于非活动状态。要激活 CIDR,您需要在目标区域创建一个集群。当区域 CIDR 处于活动状态时,您可以为该区域创建 VPC 对等连接。 + + ![Project-CIDR2](/media/tidb-cloud/Project-CIDR2.png) + +## 在 AWS 上设置 VPC 对等连接 + +本节介绍如何在 AWS 上设置 VPC 对等连接。对于 Google Cloud,请参见[在 Google Cloud 上设置 VPC 对等连接](#在-google-cloud-上设置-vpc-对等连接)。 + +### 步骤 1. 添加 VPC 对等连接请求 + +您可以在 TiDB Cloud 控制台中的项目级**网络访问**页面或集群级**网络**页面上添加 VPC 对等连接请求。 + + +
+ +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **网络访问**。 +3. 在**网络访问**页面,点击 **VPC 对等连接**标签页,然后点击 **AWS** 子标签页。 + + 默认显示 **VPC 对等连接**配置。 + +4. 在右上角,点击**创建 VPC 对等连接**,选择 **TiDB Cloud VPC 区域**,然后填写您现有 AWS VPC 的必需信息: + + - 您的 VPC 区域 + - AWS 账户 ID + - VPC ID + - VPC CIDR + + 您可以从 [AWS 管理控制台](https://console.aws.amazon.com/) 的 VPC 详情页面获取此类信息。TiDB Cloud 支持在同一区域或不同区域的 VPC 之间创建 VPC 对等连接。 + + ![VPC peering](/media/tidb-cloud/vpc-peering/vpc-peering-creating-infos.png) + +5. 点击**创建**发送 VPC 对等连接请求,然后在 **VPC 对等连接** > **AWS** 标签页上查看 VPC 对等连接信息。新创建的 VPC 对等连接状态为**系统检查中**。 + +6. 要查看新创建的 VPC 对等连接的详细信息,请在**操作**列中点击 **...** > **查看**。此时会显示 **VPC 对等连接详情**页面。 + +
+
+ +1. 打开目标集群的概览页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称以进入其概览页面。 + +2. 在左侧导航栏中,点击**设置** > **网络**。 + +3. 在**网络**页面,点击**创建 VPC 对等连接**,然后填写您现有 AWS VPC 的必需信息: + + - 您的 VPC 区域 + - AWS 账户 ID + - VPC ID + - VPC CIDR + + 您可以从 [AWS 管理控制台](https://console.aws.amazon.com/) 的 VPC 详情页面获取此类信息。TiDB Cloud 支持在同一区域或不同区域的 VPC 之间创建 VPC 对等连接。 + + ![VPC peering](/media/tidb-cloud/vpc-peering/vpc-peering-creating-infos.png) + +4. 点击**创建**发送 VPC 对等连接请求,然后在**网络** > **AWS VPC 对等连接**部分查看 VPC 对等连接信息。新创建的 VPC 对等连接状态为**系统检查中**。 + +5. 要查看新创建的 VPC 对等连接的详细信息,请在**操作**列中点击 **...** > **查看**。此时会显示 **AWS VPC 对等连接详情**页面。 + +
+
+ +### 步骤 2. 批准并配置 VPC 对等连接 + +您可以使用 AWS CLI 或 AWS 控制台批准和配置 VPC 对等连接。 + + +
+ +1. 安装 AWS 命令行界面 (AWS CLI)。 + + {{< copyable "shell-regular" >}} + + ```bash + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + sudo ./aws/install + ``` + +2. 根据您的账户信息配置 AWS CLI。要获取 AWS CLI 所需的信息,请参见 [AWS CLI 配置基础知识](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html)。 + + {{< copyable "shell-regular" >}} + + ```bash + aws configure + ``` + +3. 用您的账户信息替换以下变量值。 + + {{< copyable "shell-regular" >}} + + ```bash + # 设置相关变量。 + pcx_tidb_to_app_id="" + app_region="" + app_vpc_id="" + tidbcloud_project_cidr="" + ``` + + 例如: + + ``` + # 设置相关变量 + pcx_tidb_to_app_id="pcx-069f41efddcff66c8" + app_region="us-west-2" + app_vpc_id="vpc-0039fb90bb5cf8698" + tidbcloud_project_cidr="10.250.0.0/16" + ``` + +4. 运行以下命令。 + + {{< copyable "shell-regular" >}} + + ```bash + # 接受 VPC 对等连接请求。 + aws ec2 accept-vpc-peering-connection --vpc-peering-connection-id "$pcx_tidb_to_app_id" + ``` + + {{< copyable "shell-regular" >}} + + ```bash + # 创建路由表规则。 + aws ec2 describe-route-tables --region "$app_region" --filters Name=vpc-id,Values="$app_vpc_id" --query 'RouteTables[*].RouteTableId' --output text | tr "\t" "\n" | while read row + do + app_route_table_id="$row" + aws ec2 create-route --region "$app_region" --route-table-id "$app_route_table_id" --destination-cidr-block "$tidbcloud_project_cidr" --vpc-peering-connection-id "$pcx_tidb_to_app_id" + done + ``` + + > **注意:** + > + > 有时即使路由表规则创建成功,您可能仍会收到 `An error occurred (MissingParameter) when calling the CreateRoute operation: The request must contain the parameter routeTableId` 错误。在这种情况下,您可以检查已创建的规则并忽略该错误。 + + {{< copyable "shell-regular" >}} + + ```bash + # 修改 VPC 属性以启用 DNS 主机名和 DNS 支持。 + aws ec2 modify-vpc-attribute --vpc-id "$app_vpc_id" --enable-dns-hostnames + aws ec2 modify-vpc-attribute --vpc-id "$app_vpc_id" --enable-dns-support + ``` + +完成配置后,VPC 对等连接已创建。您可以[连接到 TiDB 集群](#连接到-tidb-集群)以验证结果。 + +
+
+ +您也可以使用 AWS 控制台配置 VPC 对等连接。 + +1. 在 [AWS 管理控制台](https://console.aws.amazon.com/)中确认接受对等连接请求。 + + 1. 登录 [AWS 管理控制台](https://console.aws.amazon.com/),点击顶部菜单栏的**服务**。在搜索框中输入 `VPC` 并进入 VPC 服务页面。 + + ![AWS dashboard](/media/tidb-cloud/vpc-peering/aws-vpc-guide-1.jpg) + + 2. 从左侧导航栏打开**对等连接**页面。在**创建对等连接**标签页上,有一个处于**等待接受**状态的对等连接。 + + 3. 确认请求者所有者和请求者 VPC 与 [TiDB Cloud 控制台](https://tidbcloud.com) 的 **VPC 对等连接详情**页面上的 **TiDB Cloud AWS 账户 ID** 和 **TiDB Cloud VPC ID** 匹配。右键点击对等连接并在**接受 VPC 对等连接请求**对话框中选择**接受请求**。 + + ![AWS VPC peering requests](/media/tidb-cloud/vpc-peering/aws-vpc-guide-3.png) + +2. 为每个 VPC 子网路由表添加到 TiDB Cloud VPC 的路由。 + + 1. 从左侧导航栏打开**路由表**页面。 + + 2. 搜索属于您的应用程序 VPC 的所有路由表。 + + ![Search all route tables related to VPC](/media/tidb-cloud/vpc-peering/aws-vpc-guide-4.png) + + 3. 右键点击每个路由表并选择**编辑路由**。在编辑页面上,添加一个目标为 TiDB Cloud CIDR(通过查看 TiDB Cloud 控制台中的 **VPC 对等连接**配置页面)的路由,并在**目标**列中填写您的对等连接 ID。 + + ![Edit all route tables](/media/tidb-cloud/vpc-peering/aws-vpc-guide-5.png) + +3. 确保已为您的 VPC 启用私有 DNS 托管区域支持。 + + 1. 从左侧导航栏打开**您的 VPC** 页面。 + + 2. 选择您的应用程序 VPC。 + + 3. 右键点击所选的 VPC。显示设置下拉列表。 + + 4. 从设置下拉列表中,点击**编辑 DNS 主机名**。启用 DNS 主机名并点击**保存**。 + + 5. 从设置下拉列表中,点击**编辑 DNS 解析**。启用 DNS 解析并点击**保存**。 + +现在您已成功设置 VPC 对等连接。接下来,[通过 VPC 对等连接连接到 TiDB 集群](#连接到-tidb-集群)。 + +
+
+ +## 在 Google Cloud 上设置 VPC 对等连接 + +### 步骤 1. 添加 VPC 对等连接请求 + +您可以在 TiDB Cloud 控制台中的项目级**网络访问**页面或集群级**网络**页面上添加 VPC 对等连接请求。 + + +
+ +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **网络访问**。 +3. 在**网络访问**页面,点击 **VPC 对等连接**标签页,然后点击 **Google Cloud** 子标签页。 + + 默认显示 **VPC 对等连接**配置。 + +4. 在右上角,点击**创建 VPC 对等连接**,选择 **TiDB Cloud VPC 区域**,然后填写您现有 Google Cloud VPC 的必需信息: + + > **提示:** + > + > 您可以按照 **Google Cloud 项目 ID** 和 **VPC 网络名称**字段旁边的说明查找项目 ID 和 VPC 网络名称。 + + - Google Cloud 项目 ID + - VPC 网络名称 + - VPC CIDR + +5. 点击**创建**发送 VPC 对等连接请求,然后在 **VPC 对等连接** > **Google Cloud** 标签页上查看 VPC 对等连接信息。新创建的 VPC 对等连接状态为**系统检查中**。 + +6. 要查看新创建的 VPC 对等连接的详细信息,请在**操作**列中点击 **...** > **查看**。此时会显示 **VPC 对等连接详情**页面。 + +
+
+ +1. 打开目标集群的概览页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/)并导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 您可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称以进入其概览页面。 + +2. 在左侧导航栏中,点击**设置** > **网络**。 + +3. 在**网络**页面,点击**创建 VPC 对等连接**,然后填写您现有 Google Cloud VPC 的必需信息: + + > **提示:** + > + > 您可以按照 **Google Cloud 项目 ID** 和 **VPC 网络名称**字段旁边的说明查找项目 ID 和 VPC 网络名称。 + + - Google Cloud 项目 ID + - VPC 网络名称 + - VPC CIDR + +4. 点击**创建**发送 VPC 对等连接请求,然后在**网络** > **Google Cloud VPC 对等连接**部分查看 VPC 对等连接信息。新创建的 VPC 对等连接状态为**系统检查中**。 + +5. 要查看新创建的 VPC 对等连接的详细信息,请在**操作**列中点击 **...** > **查看**。此时会显示 **Google Cloud VPC 对等连接详情**页面。 + +
+
+ +### 步骤 2. 批准 VPC 对等连接 + +执行以下命令完成 VPC 对等连接的设置: + +```bash +gcloud beta compute networks peerings create --project --network --peer-project --peer-network +``` + +> **注意:** +> +> 您可以根据喜好命名 ``。 + +现在您已成功设置 VPC 对等连接。接下来,[通过 VPC 对等连接连接到 TiDB 集群](#连接到-tidb-集群)。 + +## 连接到 TiDB 集群 + +1. 在项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击目标集群的名称以进入其概览页面。 + +2. 点击右上角的**连接**,从**连接类型**下拉列表中选择 **VPC 对等连接**。 + + 等待 VPC 对等连接状态从**系统检查中**变为**活动**(大约需要 5 分钟)。 + +3. 在**连接方式**下拉列表中,选择您首选的连接方法。对话框底部将显示相应的连接字符串。 + +4. 使用连接字符串连接到您的集群。 diff --git a/tidb-cloud/setup-aws-self-hosted-kafka-private-link-service.md b/tidb-cloud/setup-aws-self-hosted-kafka-private-link-service.md new file mode 100644 index 000000000000..cb542c45bd23 --- /dev/null +++ b/tidb-cloud/setup-aws-self-hosted-kafka-private-link-service.md @@ -0,0 +1,258 @@ +--- +title: 在 AWS 中设置自托管 Kafka Private Link 服务 +summary: 本文档说明如何在 AWS 中为自托管 Kafka 设置 Private Link 服务,以及如何使其与 TiDB Cloud 配合使用。 +aliases: ['/tidbcloud/setup-self-hosted-kafka-private-link-service'] +--- + +# 在 AWS 中设置自托管 Kafka Private Link 服务 + +本文档描述如何在 AWS 中为自托管 Kafka 设置 Private Link 服务,以及如何使其与 TiDB Cloud 配合使用。 + +该机制的工作原理如下: + +1. TiDB Cloud VPC 通过私有端点连接到 Kafka VPC。 +2. Kafka 客户端需要直接与所有 Kafka broker 通信。 +3. 每个 Kafka broker 映射到 TiDB Cloud VPC 内端点的唯一端口。 +4. 利用 Kafka 引导机制和 AWS 资源实现映射。 + +下图显示了该机制。 + +![连接到 AWS 自托管 Kafka Private Link 服务](/media/tidb-cloud/changefeed/connect-to-aws-self-hosted-kafka-privatelink-service.jpeg) + +本文档提供了一个连接到在 AWS 中跨三个可用区(AZ)部署的 Kafka Private Link 服务的示例。虽然可以基于类似的端口映射原理进行其他配置,但本文档涵盖了 Kafka Private Link 服务的基本设置过程。对于生产环境,建议使用具有增强运维可维护性和可观测性的更具弹性的 Kafka Private Link 服务。 + +## 前提条件 + +1. 确保你具有以下授权来在自己的 AWS 账户中设置 Kafka Private Link 服务。 + + - 管理 EC2 节点 + - 管理 VPC + - 管理子网 + - 管理安全组 + - 管理负载均衡器 + - 管理端点服务 + - 连接到 EC2 节点以配置 Kafka 节点 + +2. 如果你还没有 TiDB Cloud Dedicated 集群,请[创建一个](/tidb-cloud/create-tidb-cluster.md)。 + +3. 从你的 TiDB Cloud Dedicated 集群获取 Kafka 部署信息。 + + 1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,导航到 TiDB 集群的概览页面,然后在左侧导航栏中点击**数据** > **Changefeed**。 + 2. 在概览页面上,找到 TiDB 集群的区域。确保你的 Kafka 集群将部署在相同的区域。 + 3. 点击**创建 Changefeed**。 + 1. 在**目标**中,选择 **Kafka**。 + 2. 在**连接方式**中,选择 **Private Link**。 + 4. 记下**继续前的提醒**中的 TiDB Cloud AWS 账户信息。你将使用它来授权 TiDB Cloud 为 Kafka Private Link 服务创建端点。 + 5. 选择**可用区数量**。在本示例中,选择 **3 个可用区**。记下你想要部署 Kafka 集群的可用区的 ID。如果你想知道可用区名称和可用区 ID 之间的关系,请参见 [AWS 资源的可用区 ID](https://docs.aws.amazon.com/ram/latest/userguide/working-with-az-ids.html) 查找。 + 6. 为你的 Kafka Private Link 服务输入唯一的 **Kafka 广播监听器模式**。 + 1. 输入一个唯一的随机字符串。它只能包含数字或小写字母。你稍后将使用它来生成 **Kafka 广播监听器模式**。 + 2. 点击**检查使用情况并生成**以检查随机字符串是否唯一,并生成将用于组装 Kafka broker 的 EXTERNAL 广播监听器的 **Kafka 广播监听器模式**。 + +记下所有部署信息。你稍后需要使用它来配置你的 Kafka Private Link 服务。 + +下表显示了部署信息的示例。 + +| 信息 | 值 | 注意 | +|--------|-----------------|---------------------------| +| 区域 | Oregon (`us-west-2`) | 不适用 | +| TiDB Cloud AWS 账户的主体 | `arn:aws:iam:::root` | 不适用 | +| 可用区 ID |
  • `usw2-az1`
  • `usw2-az2`
  • `usw2-az3`
| 将可用区 ID 与你的 AWS 账户中的可用区名称对齐。
示例:
  • `usw2-az1` => `us-west-2a`
  • `usw2-az2` => `us-west-2c`
  • `usw2-az3` => `us-west-2b`
| +| Kafka 广播监听器模式 | 唯一随机字符串:`abc`
为可用区生成的模式:
  • `usw2-az1` => <broker_id>.usw2-az1.abc.us-west-2.aws.3199015.tidbcloud.com:<port>
  • `usw2-az2` => <broker_id>.usw2-az2.abc.us-west-2.aws.3199015.tidbcloud.com:<port>
  • `usw2-az3` => <broker_id>.usw2-az3.abc.us-west-2.aws.3199015.tidbcloud.com:<port>
| 将可用区名称映射到可用区指定的模式。确保稍后将正确的模式配置到特定可用区中的 broker。
  • `us-west-2a` => <broker_id>.usw2-az1.abc.us-west-2.aws.3199015.tidbcloud.com:<port>
  • `us-west-2c` => <broker_id>.usw2-az2.abc.us-west-2.aws.3199015.tidbcloud.com:<port>
  • `us-west-2b` => <broker_id>.usw2-az3.abc.us-west-2.aws.3199015.tidbcloud.com:<port>
| +## 步骤 1. 设置 Kafka 集群 + +如果你需要部署新集群,请按照[部署新的 Kafka 集群](#部署新的-kafka-集群)中的说明操作。 + +如果你需要暴露现有集群,请按照[重新配置运行中的 Kafka 集群](#重新配置运行中的-kafka-集群)中的说明操作。 + +### 部署新的 Kafka 集群 + +#### 1. 设置 Kafka VPC + +Kafka VPC 需要以下内容: + +- 三个用于 broker 的私有子网,每个可用区一个。 +- 任意可用区中的一个公共子网,其中有一个堡垒节点,可以连接到互联网和三个私有子网,这使得设置 Kafka 集群变得容易。在生产环境中,你可能有自己的堡垒节点可以连接到 Kafka VPC。 + +在创建子网之前,根据可用区 ID 和可用区名称的映射在可用区中创建子网。以下面的映射为例。 + +- `usw2-az1` => `us-west-2a` +- `usw2-az2` => `us-west-2c` +- `usw2-az3` => `us-west-2b` + +在以下可用区中创建私有子网: + +- `us-west-2a` +- `us-west-2c` +- `us-west-2b` + +按照以下步骤创建 Kafka VPC。 + +**1.1. 创建 Kafka VPC** + +1. 转到 [AWS 控制台 > VPC 仪表板](https://console.aws.amazon.com/vpcconsole/home?#vpcs:),并切换到要部署 Kafka 的区域。 + +2. 点击**创建 VPC**。在 **VPC 设置**页面上填写以下信息。 + + 1. 选择**仅 VPC**。 + 2. 在**名称标签**中输入标签,例如 `Kafka VPC`。 + 3. 选择 **IPv4 CIDR 手动输入**,并输入 IPv4 CIDR,例如 `10.0.0.0/16`。 + 4. 其他选项使用默认值。点击**创建 VPC**。 + 5. 在 VPC 详细信息页面上,记下 VPC ID,例如 `vpc-01f50b790fa01dffa`。 + +**1.2. 在 Kafka VPC 中创建私有子网** + +1. 转到[子网列表页面](https://console.aws.amazon.com/vpcconsole/home?#subnets:)。 +2. 点击**创建子网**。 +3. 选择之前记下的 **VPC ID**(在本例中为 `vpc-01f50b790fa01dffa`)。 +4. 使用以下信息添加三个子网。建议在子网名称中加入可用区 ID,以便稍后配置 broker 更容易,因为 TiDB Cloud 要求在 broker 的 `advertised.listener` 配置中编码可用区 ID。 + + - 在 `us-west-2a` 中的子网 1 + - **子网名称**:`broker-usw2-az1` + - **可用区**:`us-west-2a` + - **IPv4 子网 CIDR 块**:`10.0.0.0/18` + + - 在 `us-west-2c` 中的子网 2 + - **子网名称**:`broker-usw2-az2` + - **可用区**:`us-west-2c` + - **IPv4 子网 CIDR 块**:`10.0.64.0/18` + + - 在 `us-west-2b` 中的子网 3 + - **子网名称**:`broker-usw2-az3` + - **可用区**:`us-west-2b` + - **IPv4 子网 CIDR 块**:`10.0.128.0/18` + +5. 点击**创建子网**。显示**子网列表**页面。 + +**1.3. 在 Kafka VPC 中创建公共子网** + +1. 点击**创建子网**。 +2. 选择之前记下的 **VPC ID**(在本例中为 `vpc-01f50b790fa01dffa`)。 +3. 使用以下信息在任意可用区中添加公共子网: + + - **子网名称**:`bastion` + - **IPv4 子网 CIDR 块**:`10.0.192.0/18` + +4. 将堡垒子网配置为公共子网。 + + 1. 转到 [VPC 仪表板 > 互联网网关](https://console.aws.amazon.com/vpcconsole/home#igws:)。创建一个名为 `kafka-vpc-igw` 的互联网网关。 + 2. 在**互联网网关详细信息**页面上,在**操作**中,点击**连接到 VPC** 将互联网网关连接到 Kafka VPC。 + 3. 转到 [VPC 仪表板 > 路由表](https://console.aws.amazon.com/vpcconsole/home#CreateRouteTable:)。在 Kafka VPC 中创建一个到互联网网关的路由表,并添加一个具有以下信息的新路由: + + - **名称**:`kafka-vpc-igw-route-table` + - **VPC**:`Kafka VPC` + - **路由**: + - **目标**:`0.0.0.0/0` + - **目标**:`互联网网关`,`kafka-vpc-igw` + + 4. 将路由表附加到堡垒子网。在路由表的**详细信息**页面上,点击**子网关联** > **编辑子网关联**以添加堡垒子网并保存更改。 + +#### 2. 设置 Kafka broker + +**2.1. 创建堡垒节点** + +转到 [EC2 列表页面](https://console.aws.amazon.com/ec2/home#Instances:)。在堡垒子网中创建堡垒节点。 + +- **名称**:`bastion-node` +- **Amazon 机器映像**:`Amazon linux` +- **实例类型**:`t2.small` +- **密钥对**:`kafka-vpc-key-pair`。创建一个名为 `kafka-vpc-key-pair` 的新密钥对。将 **kafka-vpc-key-pair.pem** 下载到本地以供稍后配置。 +- 网络设置 + + - **VPC**:`Kafka VPC` + - **子网**:`bastion` + - **自动分配公共 IP**:`启用` + - **安全组**:创建一个新的安全组,允许从任何地方进行 SSH 登录。在生产环境中,你可以为了安全起见缩小规则范围。 + +**2.2. 创建 broker 节点** + +转到 [EC2 列表页面](https://console.aws.amazon.com/ec2/home#Instances:)。在 broker 子网中创建三个 broker 节点,每个可用区一个。 + +- 在子网 `broker-usw2-az1` 中的 Broker 1 + + - **名称**:`broker-node1` + - **Amazon 机器映像**:`Amazon linux` + - **实例类型**:`t2.large` + - **密钥对**:重用 `kafka-vpc-key-pair` + - 网络设置 + + - **VPC**:`Kafka VPC` + - **子网**:`broker-usw2-az1` + - **自动分配公共 IP**:`禁用` + - **安全组**:创建一个新的安全组,允许来自 Kafka VPC 的所有 TCP。在生产环境中,你可以为了安全起见缩小规则范围。 + - **协议**:`TCP` + - **端口范围**:`0 - 65535` + - **源**:`10.0.0.0/16` + +- 在子网 `broker-usw2-az2` 中的 Broker 2 + + - **名称**:`broker-node2` + - **Amazon 机器映像**:`Amazon linux` + - **实例类型**:`t2.large` + - **密钥对**:重用 `kafka-vpc-key-pair` + - 网络设置 + + - **VPC**:`Kafka VPC` + - **子网**:`broker-usw2-az2` + - **自动分配公共 IP**:`禁用` + - **安全组**:创建一个新的安全组,允许来自 Kafka VPC 的所有 TCP。在生产环境中,你可以为了安全起见缩小规则范围。 + - **协议**:`TCP` + - **端口范围**:`0 - 65535` + - **源**:`10.0.0.0/16` + +- 在子网 `broker-usw2-az3` 中的 Broker 3 + + - **名称**:`broker-node3` + - **Amazon 机器映像**:`Amazon linux` + - **实例类型**:`t2.large` + - **密钥对**:重用 `kafka-vpc-key-pair` + - 网络设置 + + - **VPC**:`Kafka VPC` + - **子网**:`broker-usw2-az3` + - **自动分配公共 IP**:`禁用` + - **安全组**:创建一个新的安全组,允许来自 Kafka VPC 的所有 TCP。在生产环境中,你可以为了安全起见缩小规则范围。 + - **协议**:`TCP` + - **端口范围**:`0 - 65535` + - **源**:`10.0.0.0/16` + +**2.3. 准备 Kafka 运行时二进制文件** + +1. 转到堡垒节点的详细信息页面。获取**公共 IPv4 地址**。使用之前下载的 `kafka-vpc-key-pair.pem` 通过 SSH 登录到节点。 + + ```shell + chmod 400 kafka-vpc-key-pair.pem + ssh -i "kafka-vpc-key-pair.pem" ec2-user@{bastion_public_ip} # 将 {bastion_public_ip} 替换为你的堡垒节点的 IP 地址,例如 54.186.149.187 + scp -i "kafka-vpc-key-pair.pem" kafka-vpc-key-pair.pem ec2-user@{bastion_public_ip}:~/ + ``` + +2. 下载二进制文件。 + + ```shell + # 下载 Kafka 和 OpenJDK,然后解压文件。你可以根据自己的偏好选择二进制版本。 + wget https://archive.apache.org/dist/kafka/3.7.1/kafka_2.13-3.7.1.tgz + tar -zxf kafka_2.13-3.7.1.tgz + wget https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_linux-x64_bin.tar.gz + tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz + ``` + +3. 将二进制文件复制到每个 broker 节点。 + + ```shell + # 将 {broker-node1-ip} 替换为你的 broker-node1 IP 地址 + scp -i "kafka-vpc-key-pair.pem" kafka_2.13-3.7.1.tgz ec2-user@{broker-node1-ip}:~/ + ssh -i "kafka-vpc-key-pair.pem" ec2-user@{broker-node1-ip} "tar -zxf kafka_2.13-3.7.1.tgz" + scp -i "kafka-vpc-key-pair.pem" openjdk-22.0.2_linux-x64_bin.tar.gz ec2-user@{broker-node1-ip}:~/ + ssh -i "kafka-vpc-key-pair.pem" ec2-user@{broker-node1-ip} "tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz" + + # 将 {broker-node2-ip} 替换为你的 broker-node2 IP 地址 + scp -i "kafka-vpc-key-pair.pem" kafka_2.13-3.7.1.tgz ec2-user@{broker-node2-ip}:~/ + ssh -i "kafka-vpc-key-pair.pem" ec2-user@{broker-node2-ip} "tar -zxf kafka_2.13-3.7.1.tgz" + scp -i "kafka-vpc-key-pair.pem" openjdk-22.0.2_linux-x64_bin.tar.gz ec2-user@{broker-node2-ip}:~/ + ssh -i "kafka-vpc-key-pair.pem" ec2-user@{broker-node2-ip} "tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz" + + # 将 {broker-node3-ip} 替换为你的 broker-node3 IP 地址 + scp -i "kafka-vpc-key-pair.pem" kafka_2.13-3.7.1.tgz ec2-user@{broker-node3-ip}:~/ + ssh -i "kafka-vpc-key-pair.pem" ec2-user@{broker-node3-ip} "tar -zxf kafka_2.13-3.7.1.tgz" + scp -i "kafka-vpc-key-pair.pem" openjdk-22.0.2_linux-x64_bin.tar.gz ec2-user@{broker-node3-ip}:~/ + ssh -i "kafka-vpc-key-pair.pem" ec2-user@{broker-node3-ip} "tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz" + ``` diff --git a/tidb-cloud/setup-azure-self-hosted-kafka-private-link-service.md b/tidb-cloud/setup-azure-self-hosted-kafka-private-link-service.md new file mode 100644 index 000000000000..1a4ec5aa21b2 --- /dev/null +++ b/tidb-cloud/setup-azure-self-hosted-kafka-private-link-service.md @@ -0,0 +1,541 @@ +--- +title: 在 Azure 中设置自托管 Kafka Private Link 服务 +summary: 本文档说明如何在 Azure 中为自托管 Kafka 设置 Private Link 服务,以及如何使其与 TiDB Cloud 配合使用。 +--- + +# 在 Azure 中设置自托管 Kafka Private Link 服务 + +本文档描述如何在 Azure 中为自托管 Kafka 设置 Private Link 服务,以及如何使其与 TiDB Cloud 配合使用。 + +工作机制如下: + +1. TiDB Cloud 虚拟网络通过私有端点连接到 Kafka 虚拟网络。 +2. Kafka 客户端需要直接与所有 Kafka broker 通信。 +3. 每个 Kafka broker 都映射到 TiDB Cloud 虚拟网络中端点的唯一端口。 +4. 利用 Kafka 引导机制和 Azure 资源实现映射。 + +下图显示了该机制。 + +![连接到 Azure 自托管 Kafka Private Link 服务](/media/tidb-cloud/changefeed/connect-to-azure-self-hosted-kafka-privatelink-service.png) + +本文档提供了连接到 Azure 中的 Kafka Private Link 服务的示例。虽然可以基于类似的端口映射原则进行其他配置,但本文档涵盖了 Kafka Private Link 服务的基本设置过程。对于生产环境,建议使用具有增强运维可维护性和可观察性的更具弹性的 Kafka Private Link 服务。 + +## 前提条件 + +1. 确保您有以下授权来在自己的 Azure 账户中设置 Kafka Private Link 服务。 + + - 管理虚拟机 + - 管理虚拟网络 + - 管理负载均衡器 + - 管理私有链接服务 + - 连接到虚拟机以配置 Kafka 节点 + +2. 如果您还没有在 Azure 上的 [TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md),请创建一个。 + +3. 从您的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群获取 Kafka 部署信息。 + + 1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称以进入其概览页面。 + 2. 在左侧导航栏中,点击**数据** > **变更数据捕获**。 + 3. 在**变更数据捕获**页面,点击右上角的**创建变更数据捕获**,然后提供以下信息: + 1. 在**目标**中,选择 **Kafka**。 + 2. 在**连接方式**中,选择 **Private Link**。 + 4. 记下**继续之前的提醒**中的区域信息和 TiDB Cloud Azure 账户的订阅信息。您将使用它来授权 TiDB Cloud 访问 Kafka Private Link 服务。 + 5. 通过提供唯一的随机字符串为您的 Kafka Private Link 服务生成 **Kafka 广播监听器模式**。 + 1. 输入唯一的随机字符串。它只能包含数字或小写字母。您稍后将使用它来生成 **Kafka 广播监听器模式**。 + 2. 点击**检查使用情况并生成**以检查随机字符串是否唯一并生成 **Kafka 广播监听器模式**,该模式将用于组装 Kafka broker 的 EXTERNAL 广播监听器。 + +记下所有部署信息。您稍后需要使用它来配置 Kafka Private Link 服务。 + +下表显示了部署信息的示例。 + +| 信息 | 值 | 注释 | +|--------|-----------------|---------------------------| +| 区域 | 弗吉尼亚 (`eastus`) | 不适用 | +| TiDB Cloud Azure 账户的订阅 | `99549169-6cee-4263-8491-924a3011ee31` | 不适用 | +| Kafka 广播监听器模式 | 唯一随机字符串:`abc` | 生成的模式:`.abc.eastus.azure.3199745.tidbcloud.com:` | + +## 步骤 1. 设置 Kafka 集群 + +如果您需要部署新集群,请按照[部署新的 Kafka 集群](#部署新的-kafka-集群)中的说明进行操作。 + +如果您需要暴露现有集群,请按照[重新配置运行中的 Kafka 集群](#重新配置运行中的-kafka-集群)中的说明进行操作。 + +### 部署新的 Kafka 集群 + +#### 1. 设置 Kafka 虚拟网络 + +1. 登录 [Azure 门户](https://portal.azure.com/),转到[虚拟网络](https://portal.azure.com/#browse/Microsoft.Network%2FvirtualNetworks)页面,然后点击**+ 创建**以创建虚拟网络。 +2. 在**基本信息**选项卡中,选择您的**订阅**、**资源组**和**区域**,在**虚拟网络名称**字段中输入名称(例如 `kafka-pls-vnet`),然后点击**下一步**。 +3. 在**安全性**选项卡中,启用 Azure Bastion,然后点击**下一步**。 +4. 在 **IP 地址**选项卡中,执行以下操作: + + 1. 设置虚拟网络的地址空间,例如 `10.0.0.0/16`。 + 2. 点击**添加子网**为 broker 创建子网,填写以下信息,然后点击**添加**。 + - **名称**:`brokers-subnet` + - **IP 地址范围**:`10.0.0.0/24` + - **大小**:`/24(256 个地址)` + + 默认情况下将创建一个 `AzureBastionSubnet`。 + +5. 点击**查看 + 创建**以验证信息。 +6. 点击**创建**。 + +#### 2. 设置 Kafka broker + +**2.1. 创建 broker 节点** + +1. 登录 [Azure 门户](https://portal.azure.com/),转到[虚拟机](https://portal.azure.com/#view/Microsoft_Azure_ComputeHub/ComputeHubMenuBlade/~/virtualMachinesBrowse)页面,点击**+ 创建**,然后选择 **Azure 虚拟机**。 +2. 在**基本信息**选项卡中,选择您的**订阅**、**资源组**和**区域**,填写以下信息,然后点击**下一步:磁盘**。 + - **虚拟机名称**:`broker-node` + - **可用性选项**:`可用性区域` + - **区域选项**:`自选区域` + - **可用性区域**:`区域 1`、`区域 2`、`区域 3` + - **映像**:`Ubuntu Server 24.04 LTS - x64 Gen2` + - **VM 架构**:`x64` + - **大小**:`Standard_D2s_v3` + - **身份验证类型**:`SSH 公钥` + - **用户名**:`azureuser` + - **SSH 公钥源**:`生成新的密钥对` + - **密钥对名称**:`kafka_broker_key` + - **公共入站端口**:`允许选定的端口` + - **选择入站端口**:`SSH (22)` +3. 点击**下一步:网络**,然后在**网络**选项卡中填写以下信息: + - **虚拟网络**:`kafka-pls-vnet` + - **子网**:`brokers-subnet` + - **公共 IP**:`无` + - **NIC 网络安全组**:`基本` + - **公共入站端口**:`允许选定的端口` + - **选择入站端口**:`SSH (22)` + - **负载均衡选项**:`无` +4. 点击**查看 + 创建**以验证信息。 +5. 点击**创建**。将显示**生成新的密钥对**消息。 +6. 点击**下载私钥并创建资源**将私钥下载到本地计算机。您可以看到虚拟机创建的进度。 + +**2.2. 准备 Kafka 运行时二进制文件** + +虚拟机部署完成后,执行以下步骤: + +1. 在 [Azure 门户](https://portal.azure.com/)中,转到[**资源组**](https://portal.azure.com/#view/HubsExtension/BrowseResourceGroups.ReactView)页面,点击您的资源组名称,然后导航到每个 broker 节点(`broker-node-1`、`broker-node-2` 和 `broker-node-3`)的页面。 + +2. 在每个 broker 节点的页面上,点击左侧导航栏中的**连接 > Bastion**,然后填写以下信息: + + - **身份验证类型**:`来自本地文件的 SSH 私钥` + - **用户名**:`azureuser` + - **本地文件**:选择之前下载的私钥文件 + - 选择**在新的浏览器标签页中打开**选项 + +3. 在每个 broker 节点的页面上,点击**连接**以打开带有 Linux 终端的新浏览器标签页。对于三个 broker 节点,您需要打开三个带有 Linux 终端的浏览器标签页。 + +4. 在每个 Linux 终端中,运行以下命令以在每个 broker 节点中下载二进制文件。 + + ```shell + # 下载 Kafka 和 OpenJDK,然后解压文件。您可以根据偏好选择二进制版本。 + wget https://archive.apache.org/dist/kafka/3.7.1/kafka_2.13-3.7.1.tgz + tar -zxf kafka_2.13-3.7.1.tgz + wget https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_linux-x64_bin.tar.gz + tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz + ``` + +**2.3. 在每个 broker 节点上设置 Kafka 节点** + +1. 使用三个节点设置 KRaft Kafka 集群。每个节点同时作为 broker 和控制器。对于每个 broker 节点: + + 1. 配置 `listeners`。所有三个 broker 都相同,并作为 broker 和控制器角色。 + 1. 为所有**控制器**角色节点配置相同的 CONTROLLER 监听器。如果您只想添加 broker 角色节点,可以在 `server.properties` 中省略 CONTROLLER 监听器。 + 2. 配置两个 broker 监听器:**INTERNAL** 用于内部 Kafka 客户端访问,**EXTERNAL** 用于从 TiDB Cloud 访问。 + + 2. 对于 `advertised.listeners`,执行以下操作: + 1. 为每个 broker 使用 broker 节点的内部 IP 地址配置 INTERNAL 广播监听器,这允许内部 Kafka 客户端通过广播地址连接到 broker。 + 2. 根据从 TiDB Cloud 获取的 **Kafka 广播监听器模式**为每个 broker 节点配置 EXTERNAL 广播监听器,以帮助 TiDB Cloud 区分不同的 broker。不同的 EXTERNAL 广播监听器帮助 TiDB Cloud 端的 Kafka 客户端将请求路由到正确的 broker。 + - 使用不同的 `` 值来区分 Kafka Private Link 服务访问中的 broker。为所有 broker 的 EXTERNAL 广播监听器规划端口范围。这些端口不必是 broker 实际监听的端口。它们是 Private Link 服务中负载均衡器监听的端口,将请求转发到不同的 broker。 + - 建议为不同的 broker 配置不同的 broker ID,以便于故障排除。 + + 3. 规划值: + - CONTROLLER 端口:`29092` + - INTERNAL 端口:`9092` + - EXTERNAL 端口:`39092` + - EXTERNAL 广播监听器端口范围:`9093~9095` + +2. 使用 SSH 登录到每个 broker 节点。为每个 broker 节点分别创建配置文件 `~/config/server.properties`,内容如下: + + ```properties + # broker-node-1 ~/config/server.properties + # 1. 将 {broker-node-1-ip}、{broker-node-2-ip}、{broker-node-3-ip} 替换为实际的 IP 地址。 + # 2. 根据"前提条件"部分中的"Kafka 广播监听器模式"配置"advertised.listeners"中的 EXTERNAL。 + # 2.1 模式是 ".abc.eastus.azure.3199745.tidbcloud.com:"。 + # 2.2 因此 EXTERNAL 可以是 "b1.abc.eastus.azure.3199745.tidbcloud.com:9093"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口(9093)。 + process.roles=broker,controller + node.id=1 + controller.quorum.voters=1@{broker-node-1-ip}:29092,2@{broker-node-2-ip}:29092,3@{broker-node-3-ip}:29092 + listeners=INTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:29092,EXTERNAL://0.0.0.0:39092 + inter.broker.listener.name=INTERNAL + advertised.listeners=INTERNAL://{broker-node-1-ip}:9092,EXTERNAL://b1.abc.eastus.azure.3199745.tidbcloud.com:9093 + controller.listener.names=CONTROLLER + listener.security.protocol.map=INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL + log.dirs=./data + ``` + + ```properties + # broker-node-2 ~/config/server.properties + # 1. 将 {broker-node-1-ip}、{broker-node-2-ip}、{broker-node-3-ip} 替换为实际的 IP 地址。 + # 2. 根据"前提条件"部分中的"Kafka 广播监听器模式"配置"advertised.listeners"中的 EXTERNAL。 + # 2.1 模式是 ".abc.eastus.azure.3199745.tidbcloud.com:"。 + # 2.2 因此 EXTERNAL 可以是 "b2.abc.eastus.azure.3199745.tidbcloud.com:9094"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口(9094)。 + process.roles=broker,controller + node.id=2 + controller.quorum.voters=1@{broker-node-1-ip}:29092,2@{broker-node-2-ip}:29092,3@{broker-node-3-ip}:29092 + listeners=INTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:29092,EXTERNAL://0.0.0.0:39092 + inter.broker.listener.name=INTERNAL + advertised.listeners=INTERNAL://{broker-node-2-ip}:9092,EXTERNAL://b2.abc.eastus.azure.3199745.tidbcloud.com:9094 + controller.listener.names=CONTROLLER + listener.security.protocol.map=INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL + log.dirs=./data + ``` + + ```properties + # broker-node-3 ~/config/server.properties + # 1. 将 {broker-node-1-ip}、{broker-node-2-ip}、{broker-node-3-ip} 替换为实际的 IP 地址。 + # 2. 根据"前提条件"部分中的"Kafka 广播监听器模式"配置"advertised.listeners"中的 EXTERNAL。 + # 2.1 模式是 ".abc.eastus.azure.3199745.tidbcloud.com:"。 + # 2.2 因此 EXTERNAL 可以是 "b3.abc.eastus.azure.3199745.tidbcloud.com:9095"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口(9095)。 + process.roles=broker,controller + node.id=3 + controller.quorum.voters=1@{broker-node-1-ip}:29092,2@{broker-node-2-ip}:29092,3@{broker-node-3-ip}:29092 + listeners=INTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:29092,EXTERNAL://0.0.0.0:39092 + inter.broker.listener.name=INTERNAL + advertised.listeners=INTERNAL://{broker-node-3-ip}:9092,EXTERNAL://b3.abc.eastus.azure.3199745.tidbcloud.com:9095 + controller.listener.names=CONTROLLER + listener.security.protocol.map=INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL + log.dirs=./data + ``` + +3. 创建脚本,然后在每个 broker 节点中执行它以启动 Kafka broker。 + + ```shell + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + export JAVA_HOME="$SCRIPT_DIR/jdk-22.0.2" + KAFKA_DIR="$SCRIPT_DIR/kafka_2.13-3.7.1/bin" + KAFKA_STORAGE_CMD=$KAFKA_DIR/kafka-storage.sh + KAFKA_START_CMD=$KAFKA_DIR/kafka-server-start.sh + KAFKA_DATA_DIR=$SCRIPT_DIR/data + KAFKA_LOG_DIR=$SCRIPT_DIR/log + KAFKA_CONFIG_DIR=$SCRIPT_DIR/config + + KAFKA_PIDS=$(ps aux | grep 'kafka.Kafka' | grep -v grep | awk '{print $2}') + if [ -z "$KAFKA_PIDS" ]; then + echo "没有运行中的 Kafka 进程。" + else + echo "正在终止 PID 为 $KAFKA_PIDS 的 Kafka 进程" + for PID in $KAFKA_PIDS; do + kill -9 $PID + echo "已终止 PID 为 $PID 的 Kafka 进程" + done + echo "所有 Kafka 进程已终止。" + fi + + rm -rf $KAFKA_DATA_DIR + mkdir -p $KAFKA_DATA_DIR + rm -rf $KAFKA_LOG_DIR + mkdir -p $KAFKA_LOG_DIR + + $KAFKA_STORAGE_CMD format -t "BRl69zcmTFmiPaoaANybiw" -c "$KAFKA_CONFIG_DIR/server.properties" > $KAFKA_LOG_DIR/server_format.log + LOG_DIR=$KAFKA_LOG_DIR nohup $KAFKA_START_CMD "$KAFKA_CONFIG_DIR/server.properties" & + ``` +**2.4. 测试集群设置** + +1. 测试 Kafka 引导。 + + ```shell + export JAVA_HOME=/home/azureuser/jdk-22.0.2 + + # 从 INTERNAL 监听器引导 + ./kafka_2.13-3.7.1/bin/kafka-broker-api-versions.sh --bootstrap-server {one_of_broker_ip}:9092 | grep 9092 + # 预期输出(实际顺序可能不同) + {broker-node-1-ip}:9092 (id: 1 rack: null) -> ( + {broker-node-2-ip}:9092 (id: 2 rack: null) -> ( + {broker-node-3-ip}:9092 (id: 3 rack: null) -> ( + + # 从 EXTERNAL 监听器引导 + ./kafka_2.13-3.7.1/bin/kafka-broker-api-versions.sh --bootstrap-server {one_of_broker_ip}:39092 + # 最后 3 行的预期输出(实际顺序可能不同) + # 与"从 INTERNAL 监听器引导"的输出不同之处在于,由于广播监听器无法在 kafka-pls-vnet 中解析,可能会出现异常或错误。 + # 当您创建通过 Private Link Service 连接到此 Kafka 集群的变更数据捕获时,TiDB Cloud 将使这些地址可解析并将请求路由到正确的 broker。 + b1.abc.eastus.azure.3199745.tidbcloud.com:9093 (id: 1 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + b2.abc.eastus.azure.3199745.tidbcloud.com:9094 (id: 2 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + b3.abc.eastus.azure.3199745.tidbcloud.com:9095 (id: 3 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + ``` + +2. 在堡垒节点中创建生产者脚本 `produce.sh`。 + + ```shell + BROKER_LIST=$1 + + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + export JAVA_HOME="$SCRIPT_DIR/jdk-22.0.2" + KAFKA_DIR="$SCRIPT_DIR/kafka_2.13-3.7.1/bin" + TOPIC="test-topic" + + create_topic() { + echo "如果主题不存在则创建..." + $KAFKA_DIR/kafka-topics.sh --create --topic $TOPIC --bootstrap-server $BROKER_LIST --if-not-exists --partitions 3 --replication-factor 3 + } + + produce_messages() { + echo "向主题发送消息..." + for ((chrono=1; chrono <= 10; chrono++)); do + message="测试消息 "$chrono + echo "创建 "$message + echo $message | $KAFKA_DIR/kafka-console-producer.sh --broker-list $BROKER_LIST --topic $TOPIC + done + } + create_topic + produce_messages + ``` + +3. 在堡垒节点中创建消费者脚本 `consume.sh`。 + + ```shell + BROKER_LIST=$1 + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + export JAVA_HOME="$SCRIPT_DIR/jdk-22.0.2" + KAFKA_DIR="$SCRIPT_DIR/kafka_2.13-3.7.1/bin" + TOPIC="test-topic" + CONSUMER_GROUP="test-group" + consume_messages() { + echo "从主题消费消息..." + $KAFKA_DIR/kafka-console-consumer.sh --bootstrap-server $BROKER_LIST --topic $TOPIC --from-beginning --timeout-ms 5000 --consumer-property group.id=$CONSUMER_GROUP + } + consume_messages + ``` + +4. 运行 `produce.sh` 和 `consume.sh` 脚本。这些脚本自动测试连接性和消息流,以验证 Kafka 集群是否正常运行。`produce.sh` 脚本使用 `--partitions 3 --replication-factor 3` 创建主题,发送测试消息,并使用 `--broker-list` 参数连接到所有三个 broker。`consume.sh` 脚本从主题读取消息以确认消息传递成功。 + + ```shell + # 测试写入消息。 + ./produce.sh {one_of_broker_ip}:9092 + ``` + + ```shell + # 预期输出 + 如果主题不存在则创建... + + 向主题发送消息... + 创建 测试消息 1 + >>创建 测试消息 2 + >>创建 测试消息 3 + >>创建 测试消息 4 + >>创建 测试消息 5 + >>创建 测试消息 6 + >>创建 测试消息 7 + >>创建 测试消息 8 + >>创建 测试消息 9 + >>创建 测试消息 10 + ``` + + ```shell + # 测试读取消息 + ./consume.sh {one_of_broker_ip}:9092 + ``` + + ```shell + # 预期示例输出(实际消息顺序可能不同) + 从主题消费消息... + 测试消息 3 + 测试消息 4 + 测试消息 5 + 测试消息 9 + 测试消息 10 + 测试消息 6 + 测试消息 8 + 测试消息 1 + 测试消息 2 + 测试消息 7 + [2024-11-01 08:54:27,547] ERROR Error processing message, terminating consumer process: (kafka.tools.ConsoleConsumer$) + org.apache.kafka.common.errors.TimeoutException + 已处理共计 10 条消息 + ``` +### 重新配置运行中的 Kafka 集群 + +确保您的 Kafka 集群部署在与 TiDB 集群相同的区域。 + +**1. 为 broker 配置 EXTERNAL 监听器** + +以下配置适用于 Kafka KRaft 集群。ZK 模式配置类似。 + +1. 规划配置更改。 + + 1. 为每个 broker 配置一个用于从 TiDB Cloud 外部访问的 EXTERNAL **监听器**。选择一个唯一的端口作为 EXTERNAL 端口,例如 `39092`。 + 2. 根据从 TiDB Cloud 获取的 **Kafka 广播监听器模式**为每个 broker 节点配置 EXTERNAL **广播监听器**,以帮助 TiDB Cloud 区分不同的 broker。不同的 EXTERNAL 广播监听器帮助 TiDB Cloud 端的 Kafka 客户端将请求路由到正确的 broker。 + - `` 区分 Kafka Private Link 服务访问点的 broker。为所有 broker 的 EXTERNAL 广播监听器规划端口范围,例如 `从 9093 开始的范围`。这些端口不必是 broker 实际监听的端口。它们是 Private Link 服务的负载均衡器监听的端口,将请求转发到不同的 broker。 + - 建议为不同的 broker 配置不同的 broker ID,以便于故障排除。 + +2. 使用 SSH 登录到每个 broker 节点。使用以下内容修改每个 broker 的配置文件: + + ```properties + # 添加 EXTERNAL 监听器 + listeners=INTERNAL:...,EXTERNAL://0.0.0.0:39092 + + # 根据"前提条件"部分中的"Kafka 广播监听器模式"添加 EXTERNAL 广播监听器 + # 1. 模式是 ".abc.eastus.azure.3199745.tidbcloud.com:"。 + # 2. 因此 EXTERNAL 可以是 "bx.abc.eastus.azure.3199745.tidbcloud.com:xxxx"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口。 + # 例如 + advertised.listeners=...,EXTERNAL://b1.abc.eastus.azure.3199745.tidbcloud.com:9093 + + # 配置 EXTERNAL 映射 + listener.security.protocol.map=...,EXTERNAL:PLAINTEXT + ``` + +3. 重新配置所有 broker 后,逐个重启您的 Kafka broker。 + +**2. 在内部网络中测试 EXTERNAL 监听器设置** + +您可以在 Kafka 客户端节点中下载 Kafka 和 OpenJDK。 + +```shell +# 下载 Kafka 和 OpenJDK,然后解压文件。您可以根据偏好选择二进制版本。 +wget https://archive.apache.org/dist/kafka/3.7.1/kafka_2.13-3.7.1.tgz +tar -zxf kafka_2.13-3.7.1.tgz +wget https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_linux-x64_bin.tar.gz +tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz +``` + +执行以下脚本以测试引导是否按预期工作。 + +```shell +export JAVA_HOME=~/jdk-22.0.2 + +# 从 EXTERNAL 监听器引导 +./kafka_2.13-3.7.1/bin/kafka-broker-api-versions.sh --bootstrap-server {one_of_broker_ip}:39092 + +# 最后 3 行的预期输出(实际顺序可能不同) +# 由于广播监听器无法在您的 Kafka 网络中解析,将会出现一些异常或错误。 +# 当您创建通过 Private Link Service 连接到此 Kafka 集群的变更数据捕获时,TiDB Cloud 将使这些地址可解析并将请求路由到正确的 broker。 +b1.abc.eastus.azure.3199745.tidbcloud.com:9093 (id: 1 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException +b2.abc.eastus.azure.3199745.tidbcloud.com:9094 (id: 2 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException +b3.abc.eastus.azure.3199745.tidbcloud.com:9095 (id: 3 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException +``` +## 步骤 2. 将 Kafka 集群暴露为 Private Link Service + +### 1. 设置负载均衡器 + +1. 登录 [Azure 门户](https://portal.azure.com/),转到[负载均衡](https://portal.azure.com/#view/Microsoft_Azure_Network/LoadBalancingHubMenuBlade/~/loadBalancers)页面,然后点击**+ 创建**以创建负载均衡器。 +2. 在**基本信息**选项卡中,选择您的**订阅**、**资源组**和**区域**,填写以下实例信息,然后点击**下一步:前端 IP 配置 >**。 + + - **名称**:`kafka-lb` + - **SKU**:`标准` + - **类型**:`内部` + - **层级**:`区域` + +3. 在**前端 IP 配置**选项卡中,点击**+ 添加前端 IP 配置**,填写以下信息,点击**保存**,然后点击**下一步:后端池 >**。 + + - **名称**:`kafka-lb-ip` + - **IP 版本**:`IPv4` + - **虚拟网络**:`kafka-pls-vnet` + - **子网**:`brokers-subnet` + - **分配**:`动态` + - **可用性区域**:`区域冗余` + +4. 在**后端池**选项卡中,添加三个后端池如下,然后点击**下一步:入站规则**。 + + - 名称:`pool1`;后端池配置:`NIC`;IP 配置:`broker-node-1` + - 名称:`pool2`;后端池配置:`NIC`;IP 配置:`broker-node-2` + - 名称:`pool3`;后端池配置:`NIC`;IP 配置:`broker-node-3` + +5. 在**入站规则**选项卡中,添加三个负载均衡规则如下: + + 1. 规则 1 + + - **名称**:`rule1` + - **IP 版本**:`IPv4` + - **前端 IP 地址**:`kafka-lb-ip` + - **后端池**:`pool1` + - **协议**:`TCP` + - **端口**:`9093` + - **后端端口**:`39092` + - **运行状况探测**:点击**创建新的**并填写探测信息。 + - **名称**:`kafka-lb-hp` + - **协议**:`TCP` + - **端口**:`39092` + + 2. 规则 2 + + - **名称**:`rule2` + - **IP 版本**:`IPv4` + - **前端 IP 地址**:`kafka-lb-ip` + - **后端池**:`pool2` + - **协议**:`TCP` + - **端口**:`9094` + - **后端端口**:`39092` + - **运行状况探测**:点击**创建新的**并填写探测信息。 + - **名称**:`kafka-lb-hp` + - **协议**:`TCP` + - **端口**:`39092` + + 3. 规则 3 + + - **名称**:`rule3` + - **IP 版本**:`IPv4` + - **前端 IP 地址**:`kafka-lb-ip` + - **后端池**:`pool3` + - **协议**:`TCP` + - **端口**:`9095` + - **后端端口**:`39092` + - **运行状况探测**:点击**创建新的**并填写探测信息。 + - **名称**:`kafka-lb-hp` + - **协议**:`TCP` + - **端口**:`39092` + +6. 点击**下一步:出站规则**,点击**下一步:标记 >**,然后点击**下一步:查看 + 创建**以验证信息。 + +7. 点击**创建**。 + +### 2. 设置 Private Link Service + +1. 登录 [Azure 门户](https://portal.azure.com/),转到[私有链接服务](https://portal.azure.com/#view/Microsoft_Azure_Network/PrivateLinkCenterBlade/~/privatelinkservices)页面,然后点击**+ 创建**以为 Kafka 负载均衡器创建 Private Link Service。 + +2. 在**基本信息**选项卡中,选择您的**订阅**、**资源组**和**区域**,在**名称**字段中填写 `kafka-pls`,然后点击**下一步:出站设置 >**。 + +3. 在**出站设置**选项卡中,填写参数如下,然后点击**下一步:访问安全性 >**。 + + - **负载均衡器**:`kafka-lb` + - **负载均衡器前端 IP 地址**:`kafka-lb-ip` + - **源 NAT 子网**:`kafka-pls-vnet/brokers-subnet` + +4. 在**访问安全性**选项卡中,执行以下操作: + + - 对于**可见性**,选择**按订阅限制**或**具有您别名的任何人**。 + - 对于**订阅级别访问和自动批准**,点击**添加订阅**以添加您在[前提条件](#前提条件)中获取的 TiDB Cloud Azure 账户的订阅。 + +5. 点击**下一步:标记 >**,然后点击**下一步:查看 + 创建 >**以验证信息。 + +6. 点击**创建**。操作完成后,记下 Private Link Service 的别名,以供后续使用。 +## 步骤 3. 从 TiDB Cloud 连接 + +1. 返回 [TiDB Cloud 控制台](https://tidbcloud.com),通过**私有链接**为集群创建变更数据捕获以连接到 Kafka 集群。更多信息,请参阅[导出到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md)。 + +2. 当您进入**配置变更数据捕获目标 > 连接方式 > Private Link**时,使用相应的值填写以下字段和其他所需字段。 + + - **Kafka 广播监听器模式**:您在[前提条件](#前提条件)中用于生成 **Kafka 广播监听器模式**的唯一随机字符串。 + - **Private Link Service 的别名**:您在[2. 设置 Private Link Service](#2-设置-private-link-service)中获取的 Private Link Service 的别名。 + - **引导端口**:`9093,9094,9095`。 + +3. 按照[导出到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md)中的步骤继续操作。 + +现在您已成功完成任务。 + +## 常见问题 + +### 如何从两个不同的 TiDB Cloud 项目连接到同一个 Kafka Private Link Service? + +如果您已按照本文档成功设置了从第一个项目的连接,您可以按照以下步骤从第二个项目连接到同一个 Kafka Private Link Service: + +1. 按照本文档从头开始操作。 + +2. 当您进入[步骤 1. 设置 Kafka 集群](#步骤-1-设置-kafka-集群)时,按照[重新配置运行中的 Kafka 集群](#重新配置运行中的-kafka-集群)创建另一组 EXTERNAL 监听器和广播监听器。您可以将其命名为 **EXTERNAL2**。注意,**EXTERNAL2** 的端口范围可以与 **EXTERNAL** 重叠。 + +3. 重新配置 broker 后,创建新的负载均衡器和新的 Private Link Service。 + +4. 使用以下信息配置 TiDB Cloud 连接: + + - 新的 Kafka 广播监听器组 + - 新的 Private Link Service diff --git a/tidb-cloud/setup-self-hosted-kafka-private-service-connect.md b/tidb-cloud/setup-self-hosted-kafka-private-service-connect.md new file mode 100644 index 000000000000..ece834066924 --- /dev/null +++ b/tidb-cloud/setup-self-hosted-kafka-private-service-connect.md @@ -0,0 +1,698 @@ +--- +title: 在 Google Cloud 中设置自托管 Kafka Private Service Connect +summary: 本文介绍如何在 Google Cloud 中为自托管 Kafka 设置 Private Service Connect,以及如何使其与 TiDB Cloud 配合使用。 +--- + +# 在 Google Cloud 中设置自托管 Kafka Private Service Connect + +本文介绍如何在 Google Cloud 中为自托管 Kafka 设置 Private Service Connect,以及如何使其与 TiDB Cloud 配合使用。 + +工作机制如下: + +1. TiDB Cloud VPC 通过私有端点连接到 Kafka VPC。 +2. Kafka 客户端需要直接与所有 Kafka broker 通信。 +3. 每个 Kafka broker 在 TiDB Cloud VPC 中映射到一个唯一的端口。 +4. 利用 Kafka 引导机制和 Google Cloud 资源实现映射。 + +在 Google Cloud 中为自托管 Kafka 设置 Private Service Connect 有两种方式: + +- 使用 Private Service Connect (PSC) 端口映射机制。此方法需要静态的端口-broker 映射配置。你需要重新配置现有的 Kafka 集群,添加一组 EXTERNAL 监听器和广播监听器。参见[通过 PSC 端口映射设置自托管 Kafka Private Service Connect 服务](#通过-psc-端口映射设置自托管-kafka-private-service-connect-服务)。 + +- 使用 [Kafka-proxy](https://github.com/grepplabs/kafka-proxy)。此方法在 Kafka 客户端和 Kafka broker 之间引入一个额外的运行进程作为代理。代理动态配置端口-broker 映射并转发请求。你无需重新配置现有的 Kafka 集群。参见[通过 Kafka-proxy 设置自托管 Kafka Private Service Connect](#通过-kafka-proxy-设置自托管-kafka-private-service-connect)。 + +本文提供了一个在 Google Cloud 中跨三个可用区(AZ)部署的 Kafka Private Service Connect 服务的连接示例。虽然可以基于类似的端口映射原理进行其他配置,但本文主要介绍 Kafka Private Service Connect 服务的基本设置过程。对于生产环境,建议使用具有增强运维可维护性和可观测性的更具弹性的 Kafka Private Service Connect 服务。 + +## 前提条件 + +1. 确保你有以下授权来在自己的 Google Cloud 账户中设置 Kafka Private Service Connect。 + + - 管理虚拟机节点 + - 管理 VPC + - 管理子网 + - 管理负载均衡器 + - 管理 Private Service Connect + - 连接到虚拟机节点以配置 Kafka 节点 + +2. 如果你还没有 TiDB Cloud Dedicated 集群,请[创建一个](/tidb-cloud/create-tidb-cluster.md)。 + +3. 从 TiDB Cloud Dedicated 集群获取 Kafka 部署信息。 + + 1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称以进入其概览页面。 + 2. 在概览页面上,找到 TiDB 集群的区域。确保你的 Kafka 集群将部署在相同的区域。 + 3. 在左侧导航栏中点击**数据** > **变更数据捕获**,在右上角点击**创建 Changefeed**,然后提供以下信息: + 1. 在**目标**中,选择 **Kafka**。 + 2. 在**连接方式**中,选择 **Private Service Connect**。 + 4. 记下**继续前的提醒**中的 Google Cloud 项目。你将使用它来授权来自 TiDB Cloud 的自动接受端点创建请求。 + 5. 记下 **TiDB 集群的可用区**。你将在这些可用区中部署 TiDB 集群。建议你在这些可用区中部署 Kafka 以减少跨区流量。 + 6. 为你的 Kafka Private Service Connect 服务选择一个唯一的 **Kafka 广播监听器模式**。 + 1. 输入一个唯一的随机字符串。它只能包含数字或小写字母。你稍后将使用它来生成 **Kafka 广播监听器模式**。 + 2. 点击**检查使用情况并生成**以检查随机字符串是否唯一,并生成 **Kafka 广播监听器模式**,该模式将用于组装 Kafka broker 的 EXTERNAL 广播监听器,或配置 Kafka-proxy。 + +记下所有部署信息。你稍后需要使用它来配置 Kafka Private Service Connect 服务。 + +下表显示了部署信息的示例。 + +| 信息 | 值 | +|------------------------------------|---------------------------------| +| 区域 | Oregon (`us-west1`) | +| TiDB Cloud 的 Google Cloud 项目 | `tidbcloud-prod-000` | +| 可用区 |
  • `us-west1-a`
  • `us-west1-b`
  • `us-west1-c`
| +| Kafka 广播监听器模式 | 唯一随机字符串:`abc`
生成的模式:<broker_id>.abc.us-west1.gcp.3199745.tidbcloud.com:<port> | + +## 通过 PSC 端口映射设置自托管 Kafka Private Service Connect 服务 + +通过使用 PSC 端口映射机制,将每个 Kafka broker 暴露给 TiDB Cloud VPC,并使用唯一的端口。下图展示了其工作原理。 + +![通过端口映射连接到 Google Cloud 自托管 Kafka Private Service Connect](/media/tidb-cloud/changefeed/connect-to-google-cloud-self-hosted-kafka-private-service-connect-by-portmapping.jpeg) + +### 步骤 1. 设置 Kafka 集群 + +如果你需要部署新集群,请按照[部署新的 Kafka 集群](#部署新的-kafka-集群)中的说明进行操作。 + +如果你需要暴露现有集群,请按照[重新配置运行中的 Kafka 集群](#重新配置运行中的-kafka-集群)中的说明进行操作。 +#### 部署新的 Kafka 集群 + +**1. 设置 Kafka VPC** + +你需要为 Kafka VPC 创建两个子网,一个用于 Kafka broker,另一个用于堡垒节点,以便于配置 Kafka 集群。 + +转到 [Google Cloud 控制台](https://cloud.google.com/cloud-console),导航到 [VPC 网络](https://console.cloud.google.com/networking/networks/list)页面,使用以下属性创建 Kafka VPC: + +- **名称**:`kafka-vpc` +- 子网 + - **名称**:`bastion-subnet`;**区域**:`us-west1`;**IPv4 范围**:`10.0.0.0/18` + - **名称**:`brokers-subnet`;**区域**:`us-west1`;**IPv4 范围**:`10.64.0.0/18` +- 防火墙规则 + - `kafka-vpc-allow-custom` + - `kafka-vpc-allow-ssh` + +**2. 配置虚拟机** + +转到[虚拟机实例](https://console.cloud.google.com/compute/instances)页面配置虚拟机: + +1. 堡垒节点 + + - **名称**:`bastion-node` + - **区域**:`us-west1` + - **可用区**:`任意` + - **机器类型**:`e2-medium` + - **镜像**:`Debian GNU/Linux 12` + - **网络**:`kafka-vpc` + - **子网**:`bastion-subnet` + - **外部 IPv4 地址**:`临时` + +2. Broker 节点 1 + + - **名称**:`broker-node1` + - **区域**:`us-west1` + - **可用区**:`us-west1-a` + - **机器类型**:`e2-medium` + - **镜像**:`Debian GNU/Linux 12` + - **网络**:`kafka-vpc` + - **子网**:`brokers-subnet` + - **外部 IPv4 地址**:`无` + +3. Broker 节点 2 + + - **名称**:`broker-node2` + - **区域**:`us-west1` + - **可用区**:`us-west1-b` + - **机器类型**:`e2-medium` + - **镜像**:`Debian GNU/Linux 12` + - **网络**:`kafka-vpc` + - **子网**:`brokers-subnet` + - **外部 IPv4 地址**:`无` + +4. Broker 节点 3 + + - **名称**:`broker-node3` + - **区域**:`us-west1` + - **可用区**:`us-west1-c` + - **机器类型**:`e2-medium` + - **镜像**:`Debian GNU/Linux 12` + - **网络**:`kafka-vpc` + - **子网**:`brokers-subnet` + - **外部 IPv4 地址**:`无` + +**3. 准备 Kafka 运行时二进制文件** + +1. 转到堡垒节点的详情页面。点击 **SSH** 登录到堡垒节点。下载二进制文件。 + + ```shell + # 下载 Kafka 和 OpenJDK,然后解压文件。你可以根据自己的偏好选择二进制版本。 + wget https://archive.apache.org/dist/kafka/3.7.1/kafka_2.13-3.7.1.tgz + tar -zxf kafka_2.13-3.7.1.tgz + wget https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_linux-x64_bin.tar.gz + tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz + ``` + +2. 将二进制文件复制到每个 broker 节点。 + + ```shell + # 运行此命令以使用 Google 用户凭据授权 gcloud 访问 Cloud Platform + # 按照输出中的说明完成登录 + gcloud auth login + + # 将二进制文件复制到 broker 节点 + gcloud compute scp kafka_2.13-3.7.1.tgz openjdk-22.0.2_linux-x64_bin.tar.gz broker-node1:~ --zone=us-west1-a + gcloud compute ssh broker-node1 --zone=us-west1-a --command="tar -zxf kafka_2.13-3.7.1.tgz && tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz" + gcloud compute scp kafka_2.13-3.7.1.tgz openjdk-22.0.2_linux-x64_bin.tar.gz broker-node2:~ --zone=us-west1-b + gcloud compute ssh broker-node2 --zone=us-west1-b --command="tar -zxf kafka_2.13-3.7.1.tgz && tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz" + gcloud compute scp kafka_2.13-3.7.1.tgz openjdk-22.0.2_linux-x64_bin.tar.gz broker-node3:~ --zone=us-west1-c + gcloud compute ssh broker-node3 --zone=us-west1-c --command="tar -zxf kafka_2.13-3.7.1.tgz && tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz" + ``` + +**4. 配置 Kafka broker** + +1. 设置一个包含三个节点的 KRaft Kafka 集群。每个节点同时作为 broker 和 controller 角色。对于每个 broker: + + 1. 对于 `listeners`,所有三个 broker 都相同,并作为 broker 和 controller 角色: + 1. 为所有 **controller** 角色节点配置相同的 CONTROLLER 监听器。如果你只想添加 **broker** 角色节点,则不需要在 `server.properties` 中配置 CONTROLLER 监听器。 + 2. 配置两个 **broker** 监听器。INTERNAL 用于内部访问;EXTERNAL 用于来自 TiDB Cloud 的外部访问。 + + 2. 对于 `advertised.listeners`,执行以下操作: + 1. 为每个 broker 配置一个使用 broker 节点内部 IP 地址的 INTERNAL 广播监听器,这允许内部 Kafka 客户端通过广播地址连接到 broker。 + 2. 基于你从 TiDB Cloud 获取的 **Kafka 广播监听器模式**,为每个 broker 节点配置一个 EXTERNAL 广播监听器,以帮助 TiDB Cloud 区分不同的 broker。不同的 EXTERNAL 广播监听器帮助 TiDB Cloud 端的 Kafka 客户端将请求路由到正确的 broker。 + - `` 用于区分 Kafka Private Service Connect 访问点的 broker。为所有 broker 的 EXTERNAL 广播监听器规划一个端口范围。这些端口不必是 broker 实际监听的端口。它们是 Private Service Connect 的负载均衡器监听的端口,负载均衡器会将请求转发到不同的 broker。 + - 建议为不同的 broker 配置不同的 broker ID,以便于故障排除。 + + 3. 规划的值: + - CONTROLLER 端口:`29092` + - INTERNAL 端口:`9092` + - EXTERNAL:`39092` + - EXTERNAL 广播监听器端口范围:`9093~9095` + +2. 使用 SSH 登录到每个 broker 节点。为每个 broker 节点分别创建配置文件 `~/config/server.properties`,内容如下: + + ```properties + # broker-node1 ~/config/server.properties + # 1. 将 {broker-node1-ip}、{broker-node2-ip}、{broker-node3-ip} 替换为实际的 IP 地址。 + # 2. 根据"前提条件"部分中的"Kafka 广播监听器模式"配置 "advertised.listeners" 中的 EXTERNAL。 + # 2.1 模式为 ".abc.us-west1.gcp.3199745.tidbcloud.com:"。 + # 2.2 因此 EXTERNAL 可以是 "b1.abc.us-west1.gcp.3199745.tidbcloud.com:9093"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口(9093)。 + process.roles=broker,controller + node.id=1 + controller.quorum.voters=1@{broker-node1-ip}:29092,2@{broker-node2-ip}:29092,3@{broker-node3-ip}:29092 + listeners=INTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:29092,EXTERNAL://0.0.0.0:39092 + inter.broker.listener.name=INTERNAL + advertised.listeners=INTERNAL://{broker-node1-ip}:9092,EXTERNAL://b1.abc.us-west1.gcp.3199745.tidbcloud.com:9093 + controller.listener.names=CONTROLLER + listener.security.protocol.map=INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL + log.dirs=./data + ``` + + ```properties + # broker-node2 ~/config/server.properties + # 1. 将 {broker-node1-ip}、{broker-node2-ip}、{broker-node3-ip} 替换为实际的 IP 地址。 + # 2. 根据"前提条件"部分中的"Kafka 广播监听器模式"配置 "advertised.listeners" 中的 EXTERNAL。 + # 2.1 模式为 ".abc.us-west1.gcp.3199745.tidbcloud.com:"。 + # 2.2 因此 EXTERNAL 可以是 "b2.abc.us-west1.gcp.3199745.tidbcloud.com:9094"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口(9094)。 + process.roles=broker,controller + node.id=2 + controller.quorum.voters=1@{broker-node1-ip}:29092,2@{broker-node2-ip}:29092,3@{broker-node3-ip}:29092 + listeners=INTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:29092,EXTERNAL://0.0.0.0:39092 + inter.broker.listener.name=INTERNAL + advertised.listeners=INTERNAL://{broker-node2-ip}:9092,EXTERNAL://b2.abc.us-west1.gcp.3199745.tidbcloud.com:9094 + controller.listener.names=CONTROLLER + listener.security.protocol.map=INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL + log.dirs=./data + ``` + + ```properties + # broker-node3 ~/config/server.properties + # 1. 将 {broker-node1-ip}、{broker-node2-ip}、{broker-node3-ip} 替换为实际的 IP 地址。 + # 2. 根据"前提条件"部分中的"Kafka 广播监听器模式"配置 "advertised.listeners" 中的 EXTERNAL。 + # 2.1 模式为 ".abc.us-west1.gcp.3199745.tidbcloud.com:"。 + # 2.2 因此 EXTERNAL 可以是 "b3.abc.us-west1.gcp.3199745.tidbcloud.com:9095"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口(9095)。 + process.roles=broker,controller + node.id=3 + controller.quorum.voters=1@{broker-node1-ip}:29092,2@{broker-node2-ip}:29092,3@{broker-node3-ip}:29092 + listeners=INTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:29092,EXTERNAL://0.0.0.0:39092 + inter.broker.listener.name=INTERNAL + advertised.listeners=INTERNAL://{broker-node3-ip}:9092,EXTERNAL://b3.abc.us-west1.gcp.3199745.tidbcloud.com:9095 + controller.listener.names=CONTROLLER + listener.security.protocol.map=INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL + log.dirs=./data + ``` +3. 创建脚本,然后在每个 broker 节点中执行该脚本以启动 Kafka broker。 + + ```shell + #!/bin/bash + + # 获取当前脚本的目录 + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # 将 JAVA_HOME 设置为脚本目录中的 Java 安装路径 + export JAVA_HOME="$SCRIPT_DIR/jdk-22.0.2" + # 定义变量 + KAFKA_DIR="$SCRIPT_DIR/kafka_2.13-3.7.1/bin" + KAFKA_STORAGE_CMD=$KAFKA_DIR/kafka-storage.sh + KAFKA_START_CMD=$KAFKA_DIR/kafka-server-start.sh + KAFKA_DATA_DIR=$SCRIPT_DIR/data + KAFKA_LOG_DIR=$SCRIPT_DIR/log + KAFKA_CONFIG_DIR=$SCRIPT_DIR/config + + # 清理步骤,便于多次实验 + # 查找所有 Kafka 进程 ID + KAFKA_PIDS=$(ps aux | grep 'kafka.Kafka' | grep -v grep | awk '{print $2}') + if [ -z "$KAFKA_PIDS" ]; then + echo "没有运行中的 Kafka 进程。" + else + # 终止每个 Kafka 进程 + echo "正在终止 PID 为 $KAFKA_PIDS 的 Kafka 进程" + for PID in $KAFKA_PIDS; do + kill -9 $PID + echo "已终止 PID 为 $PID 的 Kafka 进程" + done + echo "所有 Kafka 进程已终止。" + fi + + rm -rf $KAFKA_DATA_DIR + mkdir -p $KAFKA_DATA_DIR + rm -rf $KAFKA_LOG_DIR + mkdir -p $KAFKA_LOG_DIR + + # Magic id: BRl69zcmTFmiPaoaANybiw。你可以使用自己的 magic ID。 + $KAFKA_STORAGE_CMD format -t "BRl69zcmTFmiPaoaANybiw" -c "$KAFKA_CONFIG_DIR/server.properties" > $KAFKA_LOG_DIR/server_format.log + LOG_DIR=$KAFKA_LOG_DIR nohup $KAFKA_START_CMD "$KAFKA_CONFIG_DIR/server.properties" & + ``` + +**5. 在堡垒节点中测试 Kafka 集群** + +1. 测试 Kafka 引导。 + + ```shell + export JAVA_HOME=~/jdk-22.0.2 + + # 从 INTERNAL 监听器引导 + ./kafka_2.13-3.7.1/bin/kafka-broker-api-versions.sh --bootstrap-server {one_of_broker_ip}:9092 | grep 9092 + # 预期输出(实际顺序可能不同) + {broker-node1-ip}:9092 (id: 1 rack: null) -> ( + {broker-node2-ip}:9092 (id: 2 rack: null) -> ( + {broker-node3-ip}:9092 (id: 3 rack: null) -> ( + + # 从 EXTERNAL 监听器引导 + ./kafka_2.13-3.7.1/bin/kafka-broker-api-versions.sh --bootstrap-server {one_of_broker_ip}:39092 + # 最后 3 行的预期输出(实际顺序可能不同) + # 与"从 INTERNAL 监听器引导"的输出不同之处在于,可能会出现异常或错误,因为广播监听器在 Kafka VPC 中无法解析。 + # 当你通过 Private Service Connect 创建 changefeed 连接到此 Kafka 集群时,我们将在 TiDB Cloud 端使其可解析并将其路由到正确的 broker。 + b1.abc.us-west1.gcp.3199745.tidbcloud.com:9093 (id: 1 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + b2.abc.us-west1.gcp.3199745.tidbcloud.com:9094 (id: 2 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + b3.abc.us-west1.gcp.3199745.tidbcloud.com:9095 (id: 3 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + ``` + +2. 在堡垒节点中创建生产者脚本 `produce.sh`。 + + ```shell + #!/bin/bash + BROKER_LIST=$1 # "{broker_address1},{broker_address2}..." + + # 获取当前脚本的目录 + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # 将 JAVA_HOME 设置为脚本目录中的 Java 安装路径 + export JAVA_HOME="$SCRIPT_DIR/jdk-22.0.2" + # 定义 Kafka 目录 + KAFKA_DIR="$SCRIPT_DIR/kafka_2.13-3.7.1/bin" + TOPIC="test-topic" + + # 如果主题不存在则创建 + create_topic() { + echo "如果主题不存在则创建..." + $KAFKA_DIR/kafka-topics.sh --create --topic $TOPIC --bootstrap-server $BROKER_LIST --if-not-exists --partitions 3 --replication-factor 3 + } + + # 向主题发送消息 + produce_messages() { + echo "正在向主题发送消息..." + for ((chrono=1; chrono <= 10; chrono++)); do + message="Test message "$chrono + echo "创建 "$message + echo $message | $KAFKA_DIR/kafka-console-producer.sh --broker-list $BROKER_LIST --topic $TOPIC + done + } + create_topic + produce_messages + ``` + +3. 在堡垒节点中创建消费者脚本 `consume.sh`。 + + ```shell + #!/bin/bash + + BROKER_LIST=$1 # "{broker_address1},{broker_address2}..." + + # 获取当前脚本的目录 + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # 将 JAVA_HOME 设置为脚本目录中的 Java 安装路径 + export JAVA_HOME="$SCRIPT_DIR/jdk-22.0.2" + # 定义 Kafka 目录 + KAFKA_DIR="$SCRIPT_DIR/kafka_2.13-3.7.1/bin" + TOPIC="test-topic" + CONSUMER_GROUP="test-group" + # 从主题消费消息 + consume_messages() { + echo "正在从主题消费消息..." + $KAFKA_DIR/kafka-console-consumer.sh --bootstrap-server $BROKER_LIST --topic $TOPIC --from-beginning --timeout-ms 5000 --consumer-property group.id=$CONSUMER_GROUP + } + consume_messages + ``` + +4. 执行 `produce.sh` 和 `consume.sh` 以验证 Kafka 集群是否正在运行。这些脚本稍后也将用于网络连接测试。该脚本将创建一个具有 `--partitions 3 --replication-factor 3` 的主题。确保所有三个 broker 都包含数据。确保脚本将连接到所有三个 broker,以保证网络连接将被测试。 + + ```shell + # 测试写入消息 + ./produce.sh {one_of_broker_ip}:9092 + ``` + + ```text + # 预期输出 + 如果主题不存在则创建... + + 正在向主题发送消息... + 创建 Test message 1 + >>创建 Test message 2 + >>创建 Test message 3 + >>创建 Test message 4 + >>创建 Test message 5 + >>创建 Test message 6 + >>创建 Test message 7 + >>创建 Test message 8 + >>创建 Test message 9 + >>创建 Test message 10 + ``` + + ```shell + # 测试读取消息 + ./consume.sh {one_of_broker_ip}:9092 + ``` + + ```text + # 预期示例输出(实际消息顺序可能不同) + 正在从主题消费消息... + Test message 3 + Test message 4 + Test message 5 + Test message 9 + Test message 10 + Test message 6 + Test message 8 + Test message 1 + Test message 2 + Test message 7 + [2024-11-01 08:54:27,547] ERROR Error processing message, terminating consumer process: (kafka.tools.ConsoleConsumer$) + org.apache.kafka.common.errors.TimeoutException + 共处理了 10 条消息 + ``` +#### 重新配置运行中的 Kafka 集群 + +确保你的 Kafka 集群部署在与 TiDB 集群相同的区域。建议可用区也在相同的区域,以减少跨区流量。 + +**1. 为 broker 配置 EXTERNAL 监听器** + +以下配置适用于 Kafka KRaft 集群。ZK 模式配置类似。 + +1. 规划配置更改。 + + 1. 为每个 broker 配置一个用于来自 TiDB Cloud 的外部访问的 EXTERNAL **监听器**。选择一个唯一的端口作为 EXTERNAL 端口,例如 `39092`。 + 2. 基于你从 TiDB Cloud 获取的 **Kafka 广播监听器模式**,为每个 broker 节点配置一个 EXTERNAL **广播监听器**,以帮助 TiDB Cloud 区分不同的 broker。不同的 EXTERNAL 广播监听器帮助 TiDB Cloud 端的 Kafka 客户端将请求路由到正确的 broker。 + - `` 用于区分 Kafka Private Service Connect 访问点的 broker。为所有 broker 的 EXTERNAL 广播监听器规划一个端口范围,例如 `从 9093 开始的范围`。这些端口不必是 broker 实际监听的端口。它们是 Private Service Connect 的负载均衡器监听的端口,负载均衡器会将请求转发到不同的 broker。 + - 建议为不同的 broker 配置不同的 broker ID,以便于故障排除。 + +2. 使用 SSH 登录到每个 broker 节点。使用以下内容修改每个 broker 的配置文件: + + ```properties + # 添加 EXTERNAL 监听器 + listeners=INTERNAL:...,EXTERNAL://0.0.0.0:39092 + + # 根据"前提条件"部分中的"Kafka 广播监听器模式"添加 EXTERNAL 广播监听器 + # 1. 模式为 ".abc.us-west1.gcp.3199745.tidbcloud.com:"。 + # 2. 因此 EXTERNAL 可以是 "bx.abc.us-west1.gcp.3199745.tidbcloud.com:xxxx"。将 替换为 "b" 前缀加上 "node.id" 属性,将 替换为 EXTERNAL 广播监听器端口范围内的唯一端口。 + # 例如 + advertised.listeners=...,EXTERNAL://b1.abc.us-west1.gcp.3199745.tidbcloud.com:9093 + + # 配置 EXTERNAL 映射 + listener.security.protocol.map=...,EXTERNAL:PLAINTEXT + ``` + +3. 重新配置所有 broker 后,逐个重启你的 Kafka broker。 + +**2. 在你的内部网络中测试 EXTERNAL 监听器设置** + +你可以在 Kafka 客户端节点中下载 Kafka 和 OpenJDK。 + +```shell +# 下载 Kafka 和 OpenJDK,然后解压文件。你可以根据自己的偏好选择二进制版本。 +wget https://archive.apache.org/dist/kafka/3.7.1/kafka_2.13-3.7.1.tgz +tar -zxf kafka_2.13-3.7.1.tgz +wget https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_linux-x64_bin.tar.gz +tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz +``` + +执行以下脚本以测试引导是否按预期工作。 + +```shell +export JAVA_HOME=~/jdk-22.0.2 + +# 从 EXTERNAL 监听器引导 +./kafka_2.13-3.7.1/bin/kafka-broker-api-versions.sh --bootstrap-server {one_of_broker_ip}:39092 + +# 最后 3 行的预期输出(实际顺序可能不同) +# 会出现一些异常或错误,因为广播监听器在你的 Kafka 网络中无法解析。 +# 当你通过 Private Service Connect 创建 changefeed 连接到此 Kafka 集群时,我们将在 TiDB Cloud 端使其可解析并将其路由到正确的 broker。 +b1.abc.us-west1.gcp.3199745.tidbcloud.com:9093 (id: 1 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException +b2.abc.us-west1.gcp.3199745.tidbcloud.com:9094 (id: 2 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException +b3.abc.us-west1.gcp.3199745.tidbcloud.com:9095 (id: 3 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException +``` +### 步骤 2. 将 Kafka 集群暴露为 Private Service Connect + +1. 转到[网络端点组](https://console.cloud.google.com/compute/networkendpointgroups/list)页面。创建一个网络端点组,如下所示: + + - **名称**:`kafka-neg` + - **网络端点组类型**:`端口映射 NEG(区域性)` + - **区域**:`us-west1` + - **网络**:`kafka-vpc` + - **子网**:`brokers-subnet` + +2. 转到网络端点组的详情页面,添加网络端点以配置到 broker 节点的端口映射。 + + 1. 网络端点 1 + - **实例**:`broker-node1` + - **VM 端口**:`39092` + - **客户端端口**:`9093` + 2. 网络端点 2 + - **实例**:`broker-node2` + - **VM 端口**:`39092` + - **客户端端口**:`9094` + 3. 网络端点 3 + - **实例**:`broker-node3` + - **VM 端口**:`39092` + - **客户端端口**:`9095` + +3. 转到[负载均衡](https://console.cloud.google.com/net-services/loadbalancing/list/loadBalancers)页面。创建一个负载均衡器,如下所示: + + - **负载均衡器类型**:`网络负载均衡器` + - **代理或直通**:`直通` + - **面向公网或内部**:`内部` + - **负载均衡器名称**:`kafka-lb` + - **区域**:`us-west1` + - **网络**:`kafka-vpc` + - 后端配置 + - **后端类型**:`端口映射网络端点组` + - **协议**:`TCP` + - **端口映射网络端点组**:`kafka-neg` + - 前端配置 + - **子网**:`brokers-subnet` + - **端口**:`全部` + +4. 转到[**Private Service Connect** > **发布服务**](https://console.cloud.google.com/net-services/psc/list/producers)。 + + - **负载均衡器类型**:`内部直通网络负载均衡器` + - **内部负载均衡器**:`kafka-lb` + - **服务名称**:`kafka-psc` + - **子网**:`保留新子网` + - **名称**:`psc-subnet` + - **VPC 网络**:`kafka-vpc` + - **区域**:`us-west1` + - **IPv4 范围**:`10.128.0.0/18` + - **接受的项目**:你在[前提条件](#前提条件)中获得的 TiDB Cloud 的 Google Cloud 项目,例如 `tidbcloud-prod-000`。 + +5. 导航到 `kafka-psc` 的详情页面。记下**服务附件**,例如 `projects/tidbcloud-dp-stg-000/regions/us-west1/serviceAttachments/kafka-psc`。你将在 TiDB Cloud 中使用它来连接到此 PSC。 + +6. 转到 VPC 网络 `kafka-vpc` 的详情页面。添加防火墙规则以允许 PSC 流量到达所有 broker。 + + - **名称**:`allow-psc-traffic` + - **流量方向**:`入站` + - **匹配时的操作**:`允许` + - **目标**:`网络中的所有实例` + - **源过滤器**:`IPv4 范围` + - **源 IPv4 范围**:`10.128.0.0/18`。psc-subnet 的范围。 + - **协议和端口**:允许所有 + +### 步骤 3. 从 TiDB Cloud 连接 + +1. 返回 [TiDB Cloud 控制台](https://tidbcloud.com),为集群创建一个通过 **Private Service Connect** 连接到 Kafka 集群的 changefeed。更多信息,请参阅[同步数据到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md)。 + +2. 当你进入**配置 changefeed 目标** > **连接方式** > **Private Service Connect** 时,使用相应的值填写以下字段和其他所需字段。 + + - **Kafka 广播监听器模式**:`abc`。与你在[前提条件](#前提条件)中用于生成 **Kafka 广播监听器模式** 的唯一随机字符串相同。 + - **服务附件**:PSC 的 Kafka 服务附件,例如 `projects/tidbcloud-dp-stg-000/regions/us-west1/serviceAttachments/kafka-psc`。 + - **引导端口**:`9092,9093,9094` + +3. 按照[同步数据到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md)中的步骤继续操作。 +## 通过 Kafka-proxy 设置自托管 Kafka Private Service Connect + +通过使用 Kafka-proxy 动态端口映射机制,将每个 Kafka broker 暴露给 TiDB Cloud VPC,并使用唯一的端口。下图展示了其工作原理。 + +![通过 Kafka 代理连接到 Google Cloud 自托管 Kafka Private Service Connect](/media/tidb-cloud/changefeed/connect-to-google-cloud-self-hosted-kafka-private-service-connect-by-kafka-proxy.jpeg) + +### 步骤 1. 设置 Kafka-proxy + +假设你已经在与 TiDB 集群相同的区域有一个正在运行的 Kafka 集群。你可以从你的 VPC 网络连接到 Kafka 集群。Kafka 集群可以是自托管的,也可以是由第三方提供商(如 Confluent)提供的。 + +1. 转到[实例组](https://console.cloud.google.com/compute/instanceGroups/list)页面,为 Kafka-proxy 创建一个实例组。 + + - **名称**:`kafka-proxy-ig` + - 实例模板: + - **名称**:`kafka-proxy-tpl` + - **位置**:`区域` + - **区域**:`us-west1` + - **机器类型**:`e2-medium`。你可以根据工作负载选择自己的机器类型。 + - **网络**:你的可以连接到 Kafka 集群的 VPC 网络。 + - **子网**:你的可以连接到 Kafka 集群的子网。 + - **外部 IPv4 地址**:`临时`。启用互联网访问以便于配置 Kafka-proxy。在生产环境中,你可以选择**无**,并以你自己的方式登录节点。 + - **位置**:`单一区域` + - **区域**:`us-west1` + - **可用区**:选择你的 broker 所在的可用区之一。 + - **自动扩缩模式**:`关闭` + - **最小实例数**:`1` + - **最大实例数**:`1`。Kafka-proxy 不支持集群模式,因此只能部署一个实例。每个 Kafka-proxy 随机将本地端口映射到 broker 的端口,导致不同代理之间的映射不同。在负载均衡器后部署多个 Kafka-proxy 可能会导致问题。如果 Kafka 客户端连接到一个代理,然后通过另一个代理访问 broker,请求可能会路由到错误的 broker。 + +2. 转到 kafka-proxy-ig 中节点的详情页面。点击 **SSH** 登录到节点。下载二进制文件: + + ```shell + # 你可以选择其他版本 + wget https://github.com/grepplabs/kafka-proxy/releases/download/v0.3.11/kafka-proxy-v0.3.11-linux-amd64.tar.gz + tar -zxf kafka-proxy-v0.3.11-linux-amd64.tar.gz + ``` + +3. 运行 Kafka-proxy 并连接到 Kafka broker。 + + ```shell + # 需要向 Kafka-proxy 提供三种参数 + # 1. --bootstrap-server-mapping 定义引导映射。建议配置三个映射,每个可用区一个,以提高弹性。 + # a) Kafka broker 地址; + # b) Kafka-proxy 中 broker 的本地地址; + # c) 如果 Kafka 客户端从 Kafka-proxy 引导,则为 broker 的广播监听器 + # 2. --dynamic-sequential-min-port 定义其他 broker 的随机映射的起始端口 + # 3. --dynamic-advertised-listener 根据从"前提条件"部分获得的模式定义其他 broker 的广播监听器地址 + # a) 模式:.abc.us-west1.gcp.3199745.tidbcloud.com: + # b) 确保将 替换为固定的小写字符串,例如 "brokers"。你可以使用自己的字符串。此步骤将帮助 TiDB Cloud 正确路由请求。 + # c) 删除 ":" + # d) 广播监听器地址将是:brokers.abc.us-west1.gcp.3199745.tidbcloud.com + ./kafka-proxy server \ + --bootstrap-server-mapping "{address_of_broker1},0.0.0.0:9092,b1.abc.us-west1.gcp.3199745.tidbcloud.com:9092" \ + --bootstrap-server-mapping "{address_of_broker2},0.0.0.0:9093,b2.abc.us-west1.gcp.3199745.tidbcloud.com:9093" \ + --bootstrap-server-mapping "{address_of_broker3},0.0.0.0:9094,b3.abc.us-west1.gcp.3199745.tidbcloud.com:9094" \ + --dynamic-sequential-min-port=9095 \ + --dynamic-advertised-listener=brokers.abc.us-west1.gcp.3199745.tidbcloud.com > ./kafka_proxy.log 2>&1 & + ``` + +4. 在 Kafka-proxy 节点中测试引导。 + + ```shell + # 下载 Kafka 和 OpenJDK,然后解压文件。你可以根据自己的偏好选择二进制版本。 + wget https://archive.apache.org/dist/kafka/3.7.1/kafka_2.13-3.7.1.tgz + tar -zxf kafka_2.13-3.7.1.tgz + wget https://download.java.net/java/GA/jdk22.0.2/c9ecb94cd31b495da20a27d4581645e8/9/GPL/openjdk-22.0.2_linux-x64_bin.tar.gz + tar -zxf openjdk-22.0.2_linux-x64_bin.tar.gz + + export JAVA_HOME=~/jdk-22.0.2 + + ./kafka_2.13-3.7.1/bin/kafka-broker-api-versions.sh --bootstrap-server 0.0.0.0:9092 + # 最后几行的预期输出(实际顺序可能不同) + # 可能会出现异常或错误,因为广播监听器在你的网络中无法解析。 + # 当你通过 Private Service Connect 创建 changefeed 连接到此 Kafka 集群时,我们将在 TiDB Cloud 端使其可解析并将其路由到正确的 broker。 + b1.abc.us-west1.gcp.3199745.tidbcloud.com:9092 (id: 1 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + b2.abc.us-west1.gcp.3199745.tidbcloud.com:9093 (id: 2 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + b3.abc.us-west1.gcp.3199745.tidbcloud.com:9094 (id: 3 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + brokers.abc.us-west1.gcp.3199745.tidbcloud.com:9095 (id: 4 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + brokers.abc.us-west1.gcp.3199745.tidbcloud.com:9096 (id: 5 rack: null) -> ERROR: org.apache.kafka.common.errors.DisconnectException + ... + ``` +### 步骤 2. 将 Kafka-proxy 暴露为 Private Service Connect 服务 + +1. 转到[负载均衡](https://console.cloud.google.com/net-services/loadbalancing/list/loadBalancers)页面,创建一个负载均衡器。 + + - **负载均衡器类型**:`网络负载均衡器` + - **代理或直通**:`直通` + - **面向公网或内部**:`内部` + - **负载均衡器名称**:`kafka-proxy-lb` + - **区域**:`us-west1` + - **网络**:你的网络 + - 后端配置 + - **后端类型**:`实例组` + - **协议**:`TCP` + - **实例组**:`kafka-proxy-ig` + - 前端配置 + - **子网**:你的子网 + - **端口**:`全部` + - 健康检查: + - **名称**:`kafka-proxy-hc` + - **范围**:`区域` + - **协议**:`TCP` + - **端口**:`9092`。你可以选择 Kafka-proxy 中的一个引导端口。 + +2. 转到[**Private Service Connect** > **发布服务**](https://console.cloud.google.com/net-services/psc/list/producers)。 + + - **负载均衡器类型**:`内部直通网络负载均衡器` + - **内部负载均衡器**:`kafka-proxy-lb` + - **服务名称**:`kafka-proxy-psc` + - **子网**:`保留新子网` + - **名称**:`proxy-psc-subnet` + - **VPC 网络**:你的网络 + - **区域**:`us-west1` + - **IPv4 范围**:根据你的网络规划设置 CIDR + - **接受的项目**:你在[前提条件](#前提条件)中获得的 TiDB Cloud 的 Google Cloud 项目,例如 `tidbcloud-prod-000`。 + +3. 导航到 **kafka-proxy-psc** 的详情页面。记下`服务附件`,例如 `projects/tidbcloud-dp-stg-000/regions/us-west1/serviceAttachments/kafka-proxy-psc`,你将在 TiDB Cloud 中使用它来连接到此 PSC。 + +4. 转到你的 VPC 网络的详情页面。添加防火墙规则以允许所有 broker 的 PSC 流量。 + + - **名称**:`allow-proxy-psc-traffic` + - **流量方向**:`入站` + - **匹配时的操作**:`允许` + - **目标**:网络中的所有实例 + - **源过滤器**:`IPv4 范围` + - **源 IPv4 范围**:proxy-psc-subnet 的 CIDR + - **协议和端口**:允许所有 + +### 步骤 3. 从 TiDB Cloud 连接 + +1. 返回 [TiDB Cloud 控制台](https://tidbcloud.com),为集群创建一个通过 **Private Service Connect** 连接到 Kafka 集群的 changefeed。更多信息,请参阅[同步数据到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md)。 + +2. 当你进入**配置 changefeed 目标** > **连接方式** > **Private Service Connect** 时,使用相应的值填写以下字段和其他所需字段。 + + - **Kafka 广播监听器模式**:`abc`。与你在[前提条件](#前提条件)中用于生成 **Kafka 广播监听器模式** 的唯一随机字符串相同。 + - **服务附件**:kafka-proxy 的 PSC 服务附件,例如 `projects/tidbcloud-dp-stg-000/regions/us-west1/serviceAttachments/kafka-proxy-psc`。 + - **引导端口**:`9092,9093,9094` + +3. 继续按照[同步数据到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md)中的指南操作。 + +## 常见问题 + +### 如何从两个不同的 TiDB Cloud 项目连接到同一个 Kafka Private Service Connect 服务? + +如果你已经按照本文档中的步骤操作并成功从第一个项目建立了连接,现在想要从第二个项目建立第二个连接,你可以通过以下方式从两个不同的 TiDB Cloud 项目连接到同一个 Kafka Private Service Connect 服务: + +- 如果你通过 PSC 端口映射设置 Kafka PSC,请执行以下操作: + + 1. 按照本文档从头开始操作。当你进行到[步骤 1. 设置 Kafka 集群](#步骤-1-设置-kafka-集群)时,按照[重新配置运行中的 Kafka 集群](#重新配置运行中的-kafka-集群)部分创建另一组 EXTERNAL 监听器和广播监听器。你可以将其命名为 `EXTERNAL2`。注意,`EXTERNAL2` 的端口范围不能与 EXTERNAL 重叠。 + + 2. 重新配置 broker 后,向网络端点组添加另一组网络端点,将端口范围映射到 `EXTERNAL2` 监听器。 + + 3. 使用以下输入配置 TiDB Cloud 连接以创建新的 changefeed: + + - 新的引导端口 + - 新的 Kafka 广播监听器模式 + - 相同的服务附件 + +- 如果你[通过 Kafka-proxy 设置自托管 Kafka Private Service Connect](#通过-kafka-proxy-设置自托管-kafka-private-service-connect),请使用新的 Kafka 广播监听器模式从头开始创建新的 Kafka-proxy PSC。 diff --git a/tidb-cloud/size-your-cluster.md b/tidb-cloud/size-your-cluster.md new file mode 100644 index 000000000000..571d950ca1d4 --- /dev/null +++ b/tidb-cloud/size-your-cluster.md @@ -0,0 +1,268 @@ +--- +title: 确定 TiDB 规模 +summary: 了解如何确定 TiDB Cloud 集群的规模。 +--- + +# 确定 TiDB 规模 + +本文介绍如何确定 TiDB Cloud Dedicated 集群的规模。 + +> **注意:** +> +> 你无法更改 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的规模。 + +## TiDB 规模配置 + +TiDB 仅用于计算,不存储数据。它支持水平扩展。 + +你可以配置节点数量、vCPU 和内存。 + +要了解不同集群规模的性能测试结果,请参阅 [TiDB Cloud 性能参考](/tidb-cloud/tidb-cloud-performance-reference.md)。 + +### TiDB vCPU 和内存 + +支持的 vCPU 和内存规格包括: + +| 标准规格 | 高内存规格 | +|:---------:|:----------------:| +| 4 vCPU, 16 GiB | 不适用 | +| 8 vCPU, 16 GiB | 8 vCPU, 32 GiB | +| 16 vCPU, 32 GiB | 16 vCPU, 64 GiB | +| 32 vCPU, 64 GiB | 32 vCPU, 128 GiB | + +> **注意:** +> +> 要使用 **32 vCPU, 128 GiB** 规格的 TiDB,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 +> +> 如果 TiDB 的 vCPU 和内存规格设置为 **4 vCPU, 16 GiB**,请注意以下限制: +> +> - TiDB 节点数量只能设置为 1 或 2,TiKV 节点数量固定为 3。 +> - 4 vCPU TiDB 只能与 4 vCPU TiKV 一起使用。 +> - TiFlash 不可用。 + +### TiDB 节点数量 + +为了实现高可用性,建议为每个 TiDB Cloud 集群配置至少两个 TiDB 节点。 + +通常,TiDB 性能随着 TiDB 节点数量的增加而线性增长。但是,当 TiDB 节点数量超过 8 个时,性能增长略低于线性比例。每增加 8 个节点,性能偏差系数约为 5%。 + +例如: + +- 当有 9 个 TiDB 节点时,性能偏差系数约为 5%,因此 TiDB 性能约为单个 TiDB 节点性能的 `9 * (1 - 5%) = 8.55` 倍。 +- 当有 16 个 TiDB 节点时,性能偏差系数约为 10%,因此 TiDB 性能为单个 TiDB 节点性能的 `16 * (1 - 10%) = 14.4` 倍。 + +对于 TiDB 节点的指定延迟,TiDB 性能会根据不同的读写比例而变化。 + +8 vCPU, 16 GiB TiDB 节点在不同工作负载下的性能如下: + +| 工作负载 | QPS (P95 ≈ 100ms) | QPS (P99 ≈ 300ms) | QPS (P99 ≈ 100ms) | +|----------|-------------------|-------------------|-------------------| +| 读取 | 18,900 | 9,450 | 6,300 | +| 混合 | 15,500 | 7,750 | 5,200 | +| 写入 | 18,000 | 9,000 | 6,000 | + +如果 TiDB 节点数量少于 8 个,性能偏差系数接近 0%,因此 16 vCPU, 32 GiB TiDB 节点的性能大约是 8 vCPU, 16 GiB TiDB 节点的两倍。如果 TiDB 节点数量超过 8 个,建议选择 16 vCPU, 32 GiB TiDB 节点,因为这样需要的节点更少,意味着性能偏差系数更小。 + +在规划集群规模时,你可以根据工作负载类型、整体期望性能(QPS)以及单个 TiDB 节点对应工作负载类型的性能,使用以下公式估算 TiDB 节点数量: + +`节点数量 = ceil(整体期望性能 ÷ 每节点性能 * (1 - 性能偏差系数))` + +在公式中,你需要先计算 `节点数量 = ceil(整体期望性能 ÷ 每节点性能)` 得到一个粗略的节点数量,然后使用相应的性能偏差系数得到最终的节点数量。 + +例如,你在混合工作负载下的整体期望性能是 110,000 QPS,P95 延迟约为 100 ms,并且你想使用 8 vCPU, 16 GiB TiDB 节点。那么,你可以从前面的表格中获取 8 vCPU, 16 GiB TiDB 节点的估计 TiDB 性能(即 `15,500`),并计算粗略的 TiDB 节点数量如下: + +`节点数量 = ceil(110,000 ÷ 15,500) = 8` + +由于 8 个节点的性能偏差系数约为 5%,估计的 TiDB 性能为 `8 * 15,500 * (1 - 5%) = 117,800`,可以满足你期望的 110,000 QPS 性能。 + +因此,建议你使用 8 个 TiDB 节点(8 vCPU, 16 GiB)。 + +## TiKV 规模配置 + +TiKV 负责存储数据。它支持水平扩展。 + +你可以配置节点数量、vCPU 和内存以及存储。 + +要了解不同集群规模的性能测试结果,请参阅 [TiDB Cloud 性能参考](/tidb-cloud/tidb-cloud-performance-reference.md)。 + +### TiKV vCPU 和内存 + +支持的 vCPU 和内存规格包括: + +| 标准规格 | 高内存规格 | +|:---------:|:----------------:| +| 4 vCPU, 16 GiB | 不适用 | +| 8 vCPU, 32 GiB | 8 vCPU, 64 GiB | +| 16 vCPU, 64 GiB | 即将推出 | +| 32 vCPU, 128 GiB | 不适用 | + +> **注意:** +> +> 如果 TiKV 的 vCPU 和内存规格设置为 **4 vCPU, 16 GiB**,请注意以下限制: +> +> - TiDB 节点数量只能设置为 1 或 2,TiKV 节点数量固定为 3。 +> - 4 vCPU TiKV 只能与 4 vCPU TiDB 一起使用。 +> - TiFlash 不可用。 + +### TiKV 节点数量 + +TiKV 节点数量应该**至少为 1 组(3 个节点分布在 3 个不同的可用区)**。 + +TiDB Cloud 将 TiKV 节点均匀部署到你选择的区域中的所有可用区(至少 3 个)以实现持久性和高可用性。在典型的 3 副本设置中,你的数据均匀分布在所有可用区的 TiKV 节点中,并持久化到每个 TiKV 节点的磁盘上。 + +> **注意:** +> +> 当你扩展 TiDB 集群时,3 个可用区中的节点会同时增加或减少。有关如何根据需求扩容或缩容 TiDB 集群,请参阅[扩展 TiDB 集群](/tidb-cloud/scale-tidb-cluster.md)。 + +虽然 TiKV 主要用于数据存储,但 TiKV 节点的性能也会根据不同的工作负载而变化。因此,在规划 TiKV 节点数量时,你需要根据[**数据量**](#根据数据量估算-tikv-节点数量)和[期望性能](#根据期望性能估算-tikv-节点数量)进行估算,然后取两个估算值中的较大者作为推荐的节点数量。 + +#### 根据数据量估算 TiKV 节点数量 + +你可以根据数据量按以下方式计算推荐的 TiKV 节点数量: + +`节点数量 = ceil(数据大小 * TiKV 压缩比 * 副本数量 ÷ TiKV 存储使用率 ÷ 单个 TiKV 容量 ÷ 3) * 3` + +通常,建议将 TiKV 存储使用率保持在 80% 以下。TiDB Cloud 中的副本数量默认为 3。8 vCPU, 64 GiB TiKV 节点的最大存储容量为 4096 GiB。 + +根据历史数据,平均 TiKV 压缩比约为 40%。 + +假设你的 MySQL 转储文件大小为 20 TB,TiKV 压缩比为 40%。那么,你可以根据数据量按以下方式计算推荐的 TiKV 节点数量: + +`节点数量 = ceil(20 TB * 40% * 3 ÷ 0.8 ÷ 4096 GiB ÷ 3) * 3 = 9` + +#### 根据期望性能估算 TiKV 节点数量 + +与 TiDB 性能类似,TiKV 性能随着 TiKV 节点数量的增加而线性增长。但是,当 TiKV 节点数量超过 8 个时,性能增长略低于线性比例。每增加 8 个节点,性能偏差系数约为 5%。 + +例如: + +- 当有 9 个 TiKV 节点时,性能偏差系数约为 5%,因此 TiKV 性能约为单个 TiKV 节点性能的 `9 * (1 - 5%) = 8.55` 倍。 +- 当有 18 个 TiKV 节点时,性能偏差系数约为 10%,因此 TiKV 性能为单个 TiKV 节点性能的 `18 * (1 - 10%) = 16.2` 倍。 + +对于 TiKV 节点的指定延迟,TiKV 性能会根据不同的读写比例而变化。 + +8 vCPU, 32 GiB TiKV 节点在不同工作负载下的性能如下: + +| 工作负载 | QPS (P95 ≈ 100ms) | QPS (P99 ≈ 300ms) | QPS (P99 ≈ 100ms) | +|----------|-------------------|-------------------|-------------------| +| 读取 | 28,000 | 14,000 | 7,000 | +| 混合 | 17,800 | 8,900 | 4,450 | +| 写入 | 14,500 | 7,250 | 3,625 | + +如果 TiKV 节点数量少于 8 个,性能偏差系数接近 0%,因此 16 vCPU, 64 GiB TiKV 节点的性能大约是 8 vCPU, 32 GiB TiKV 节点的两倍。如果 TiKV 节点数量超过 8 个,建议选择 16 vCPU, 64 GiB TiKV 节点,因为这样需要的节点更少,意味着性能偏差系数更小。 + +在规划集群规模时,你可以根据工作负载类型、整体期望性能(QPS)以及单个 TiKV 节点对应工作负载类型的性能,使用以下公式估算 TiKV 节点数量: + +`节点数量 = ceil(整体期望性能 ÷ 每节点性能 * (1 - 性能偏差系数))` + +在公式中,你需要先计算 `节点数量 = ceil(整体期望性能 ÷ 每节点性能)` 得到一个粗略的节点数量,然后使用相应的性能偏差系数得到最终的节点数量。 + +例如,你在混合工作负载下的整体期望性能是 110,000 QPS,P95 延迟约为 100 ms,并且你想使用 8 vCPU, 32 GiB TiKV 节点。那么,你可以从前面的表格中获取 8 vCPU, 32 GiB TiKV 节点的估计 TiKV 性能(即 `17,800`),并计算粗略的 TiKV 节点数量如下: + +`节点数量 = ceil(110,000 / 17,800 ) = 7` + +由于 7 小于 8,7 个节点的性能偏差系数为 0。估计的 TiKV 性能为 `7 * 17,800 * (1 - 0) = 124,600`,可以满足你期望的 110,000 QPS 性能。 + +因此,根据你的期望性能,建议使用 7 个 TiKV 节点(8 vCPU, 32 GiB)。 + +接下来,你可以比较根据数据量计算的 TiKV 节点数量与根据期望性能计算的数量,取较大者作为推荐的 TiKV 节点数量。 + +### TiKV 节点存储大小 + +不同 TiKV vCPU 支持的节点存储大小如下: + +| TiKV vCPU | 最小节点存储 | 最大节点存储 | 默认节点存储 | +|:---------:|:----------------:|:----------------:|:--------------------:| +| 4 vCPU | 200 GiB | 2048 GiB | 500 GiB | +| 8 vCPU | 200 GiB | 4096 GiB | 500 GiB | +| 16 vCPU | 200 GiB | 4096 GiB | 500 GiB | +| 32 vCPU | 200 GiB | 4096 GiB | 500 GiB | + +> **注意:** +> +> 集群创建后,你无法减少 TiKV 节点存储大小。 + +### TiKV 节点存储类型 + +TiDB Cloud 为在 AWS 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群提供以下 TiKV 存储类型: + +- [基础存储](#基础存储) +- [标准存储](#标准存储) +- [性能和增强存储](#性能和增强存储) + +#### 基础存储 + +基础存储是一种通用存储类型,性能低于标准存储。 + +基础存储类型自动应用于以下在 AWS 上托管的集群: + +- 在 2025 年 4 月 1 日之前创建的现有集群。 +- 使用早于 v7.5.5、v8.1.2 或 v8.5.0 版本的 TiDB 创建的新集群。 + +#### 标准存储 + +标准存储适用于大多数工作负载,在性能和成本效益之间取得平衡。与基础存储相比,它通过为 Raft 日志保留充足的磁盘资源提供更好的性能。这减少了 Raft I/O 对数据磁盘 I/O 的影响,提高了 TiKV 的读写性能。 + +标准存储类型自动应用于在 AWS 上托管的、使用 TiDB v7.5.5、v8.1.2、v8.5.0 或更高版本创建的新集群。 + +#### 性能和增强存储 + +性能和增强存储提供更高的性能和稳定性,价格反映了这些增强的功能。目前,这两种存储类型仅在申请后可用于在 AWS 上部署的集群。要申请性能或增强存储,请点击 [TiDB Cloud 控制台](https://tidbcloud.com)右下角的 **?**,然后点击**请求支持**。然后,在**描述**字段中填写"申请 TiKV 存储类型",并点击**提交**。 + +## TiFlash 规模配置 + +TiFlash 实时从 TiKV 同步数据,并支持开箱即用的实时分析工作负载。它支持水平扩展。 + +你可以配置节点数量、vCPU 和内存以及存储。 + +### TiFlash vCPU 和内存 + +支持的 vCPU 和内存规格包括: + +- 8 vCPU, 64 GiB +- 16 vCPU, 128 GiB +- 32 vCPU, 128 GiB +- 32 vCPU, 256 GiB + +注意,当 TiDB 或 TiKV 的 vCPU 和内存规格设置为 **4 vCPU, 16 GiB** 时,TiFlash 不可用。 + +### TiFlash 节点数量 + +TiDB Cloud 将 TiFlash 节点均匀部署到区域中的不同可用区。建议在每个 TiDB Cloud 集群中配置至少两个 TiFlash 节点,并在生产环境中为数据创建至少两个副本以实现高可用性。 + +TiFlash 节点的最小数量取决于特定表的 TiFlash 副本数量: + +TiFlash 节点最小数量:`min((表 A 的压缩大小 * 表 A 的副本数 + 表 B 的压缩大小 * 表 B 的副本数) / 每个 TiFlash 容量大小, max(表 A 的副本数, 表 B 的副本数))` + +例如,如果你在 AWS 上将每个 TiFlash 节点的存储配置为 1024 GiB,并为表 A(压缩大小为 800 GiB)设置 2 个副本,为表 B(压缩大小为 100 GiB)设置 1 个副本,那么所需的 TiFlash 节点数量如下: + +TiFlash 节点最小数量:`min((800 GiB * 2 + 100 GiB * 1) / 1024 GiB, max(2, 1)) ≈ 2` + +### TiFlash 节点存储 + +不同 TiFlash vCPU 支持的节点存储如下: + +| TiFlash vCPU | 最小节点存储 | 最大节点存储 | 默认节点存储 | +|:---------:|:----------------:|:----------------:|:--------------------:| +| 8 vCPU | 200 GiB | 4096 GiB | 500 GiB | +| 16 vCPU | 200 GiB | 4096 GiB | 500 GiB | +| 32 vCPU | 200 GiB | 8192 GiB | 500 GiB | + +> **注意:** +> +> 集群创建后,你无法减少 TiFlash 节点存储。 + +### TiFlash 节点存储类型 + +TiDB Cloud 为在 AWS 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群提供以下 TiFlash 存储类型: + +- [基础存储](#基础存储-1) +- [增强存储](#增强存储) + +#### 基础存储 + +基础存储适用于大多数工作负载,在性能和成本效益之间取得平衡。 + +#### 增强存储 + +增强存储提供更高的性能和稳定性,价格反映了这些增强的功能。目前,此存储类型仅在申请后可用于在 AWS 上部署的集群。要申请它,请点击 [TiDB Cloud 控制台](https://tidbcloud.com)右下角的 **?**,然后点击**请求支持**。然后,在**描述**字段中填写"申请 TiFlash 存储类型",并点击**提交**。 diff --git a/tidb-cloud/sql-concepts.md b/tidb-cloud/sql-concepts.md new file mode 100644 index 000000000000..dab5582e499a --- /dev/null +++ b/tidb-cloud/sql-concepts.md @@ -0,0 +1,94 @@ +--- +title: SQL +summary: 了解 TiDB 的 SQL 概念。 +--- + +# SQL + +TiDB 高度兼容 MySQL 协议以及 MySQL 5.7 和 MySQL 8.0 的常用功能和语法。MySQL 的生态工具(PHPMyAdmin、Navicat、MySQL Workbench、DBeaver 和[更多](https://docs.pingcap.com/tidb/v7.2/dev-guide-third-party-support#gui))和 MySQL 客户端都可以用于 TiDB。 + +然而,TiDB 不支持 MySQL 的某些功能。这可能是因为现在有更好的方法来解决问题(比如使用 JSON 而不是 XML 函数),或者是当前需求相对于所需努力较小(比如存储过程和函数)。此外,某些功能在分布式系统中可能难以实现。更多信息,请参见 [MySQL 兼容性](/mysql-compatibility.md)。 + +## SQL 语句 + +SQL 语句是 SQL(结构化查询语言)中由标识符、参数、变量、数据类型和保留的 SQL 关键字组成的命令或指令。它指示数据库执行特定操作,如检索、修改或管理数据和数据库结构。 + +TiDB 使用的 SQL 语句旨在遵循 ISO/IEC SQL 标准,必要时为 MySQL 和 TiDB 特定语句提供扩展。 + +SQL 根据其功能分为以下 4 种类型: + +- DDL(数据定义语言):用于定义数据库对象,包括数据库、表、视图和索引。有关 TiDB 中的 DDL 语句,请参见[架构管理/数据定义语句 (DDL)](/sql-statements/sql-statement-overview.md#schema-management--data-definition-statements-ddl)。 + +- DML(数据操作语言):用于操作应用程序相关的记录。有关 TiDB 中的 DML 语句,请参见[数据操作语句 (DML)](/sql-statements/sql-statement-overview.md#data-manipulation-statements-dml)。 + +- DQL(数据查询语言):用于在条件过滤后查询记录。 + +- DCL(数据控制语言):用于定义访问权限和安全级别。 + +要了解 TiDB 中 SQL 语句的概览,请参见 [SQL 语句概览](/sql-statements/sql-statement-overview.md)。 + +## SQL 模式 + +TiDB 服务器在不同的 SQL 模式下运行,并针对不同的客户端应用这些模式。SQL 模式定义了 TiDB 支持的 SQL 语法以及要执行的数据验证检查类型。 + +更多信息,请参见 [SQL 模式](/sql-mode.md)。 + +## 行 ID 生成属性 + +TiDB 提供三个 SQL 属性来优化行 ID 生成和数据分布。 + +- AUTO_INCREMENT + +- AUTO_RANDOM + +- SHARD_ROW_ID_BITS + +### AUTO_INCREMENT + +`AUTO_INCREMENT` 是一个列属性,用于自动填充默认列值。当 `INSERT` 语句没有为 `AUTO_INCREMENT` 列指定值时,系统会自动为该列分配值。 + +出于性能考虑,`AUTO_INCREMENT` 数值会批量分配(默认为 3 万个)给每个 TiDB 服务器。这意味着虽然 `AUTO_INCREMENT` 数值保证是唯一的,但分配给 `INSERT` 语句的值只在每个 TiDB 服务器基础上是单调的。 + +如果你希望 `AUTO_INCREMENT` 数值在所有 TiDB 服务器上都是单调的,并且你的 TiDB 版本是 v6.5.0 或更高版本,建议启用 [MySQL 兼容模式](/auto-increment.md#mysql-compatibility-mode)。 + +更多信息,请参见 [AUTO_INCREMENT](/auto-increment.md)。 + +### AUTO_RANDOM + +`AUTO_RANDOM` 是一个列属性,用于自动为 `BIGINT` 列分配值。自动分配的值是随机且唯一的。由于 `AUTO_RANDOM` 的值是随机且唯一的,`AUTO_RANDOM` 经常用来代替 [`AUTO_INCREMENT`](/auto-increment.md),以避免因 TiDB 分配连续 ID 而导致单个存储节点出现写入热点。 + +由于 `AUTO_RANDOM` 的值是随机且唯一的,`AUTO_RANDOM` 经常用来代替 [`AUTO_INCREMENT`](/auto-increment.md),以避免因 TiDB 分配连续 ID 而导致单个存储节点出现写入热点。如果当前的 `AUTO_INCREMENT` 列是主键且类型为 `BIGINT`,你可以执行 `ALTER TABLE t MODIFY COLUMN id BIGINT AUTO_RANDOM(5);` 语句将其从 `AUTO_INCREMENT` 切换为 `AUTO_RANDOM`。 + +更多信息,请参见 [AUTO_RANDOM](/auto-random.md)。 + +### SHARD_ROW_ID_BITS + +对于没有聚簇主键或没有主键的表,TiDB 使用隐式自增行 ID。当执行大量 `INSERT` 操作时,数据会写入单个 Region,导致写入热点。 + +为了缓解热点问题,你可以配置 [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md)。行 ID 会被分散,数据会写入多个不同的 Region。 + +## 关键字 + +关键字是在 SQL 语句中具有特殊含义的词,如 `SELECT`、`UPDATE` 和 `DELETE`。 + +- 其中一些可以直接用作标识符,这些被称为非保留关键字。 + +- 有些在用作标识符之前需要特殊处理,这些被称为保留关键字。 + +然而,一些非保留关键字可能仍需要特殊处理。建议你将它们视为保留关键字。 + +更多信息,请参见[关键字](/keywords.md)。 + +## 用户定义变量 + +TiDB 允许你设置和读取用户定义变量。用户定义变量的格式是 `@var_name`。组成 `var_name` 的字符可以是任何可以组成标识符的字符,包括数字 `0-9`、字母 `a-zA-Z`、下划线 `_`、美元符号 `$` 和 UTF-8 字符。此外,还包括英文句点 `.`。用户定义变量不区分大小写。 + +用户定义变量是会话特定的,这意味着一个客户端连接定义的用户变量不能被其他客户端连接看到或使用。 + +更多信息,请参见[用户定义变量](/user-defined-variables.md)。 + +## 元数据锁 + +在 TiDB 中,元数据锁是一种用于在在线架构变更期间管理表元数据变更的机制。当事务开始时,它会锁定当前元数据的快照。如果在事务期间元数据发生变化,TiDB 会抛出"Information schema is changed"错误,防止事务提交。元数据锁通过优先处理 DML 来协调数据操作语言(DML)和数据定义语言(DDL)操作,确保使用过时元数据的进行中 DML 事务在应用新的 DDL 更改之前提交,从而最小化错误并维护数据一致性。 + +更多信息,请参见[元数据锁](/metadata-lock.md)。 diff --git a/tidb-cloud/sql-proxy-account.md b/tidb-cloud/sql-proxy-account.md new file mode 100644 index 000000000000..d147c49a916b --- /dev/null +++ b/tidb-cloud/sql-proxy-account.md @@ -0,0 +1,90 @@ +--- +title: SQL 代理账号 +summary: 了解 TiDB Cloud 中的 SQL 代理账号。 +--- + +# SQL 代理账号 + +SQL 代理账号是由 TiDB Cloud 自动创建的 SQL 用户账号,用于代表 TiDB Cloud 用户通过 [SQL 编辑器](/tidb-cloud/explore-data-with-chat2query.md)或[数据服务](https://docs.pingcap.com/tidbcloud/api/v1beta1/dataservice)访问数据库。例如,`testuser@pingcap.com` 是一个 TiDB Cloud 用户账号,而 `3jhEcSimm7keKP8.testuser._41mqK6H4` 是其对应的 SQL 代理账号。 + +SQL 代理账号为 TiDB Cloud 中的数据库访问提供了一个安全的、基于令牌的身份验证机制。通过消除传统的用户名和密码凭证的需求,SQL 代理账号增强了安全性并简化了访问管理。 + +SQL 代理账号的主要优势如下: + +- 增强安全性:通过使用 JWT 令牌降低与静态凭证相关的风险。 +- 简化访问:将访问权限特别限制在 SQL 编辑器和数据服务上,确保精确控制。 +- 易于管理:简化了在 TiDB Cloud 中工作的开发人员和管理员的身份验证。 + +## 识别 SQL 代理账号 + +如果你想确定特定的 SQL 账号是否为 SQL 代理账号,请执行以下步骤: + +1. 检查 `mysql.user` 表: + + ```sql + USE mysql; + SELECT user FROM user WHERE plugin = 'tidb_auth_token'; + ``` + +2. 检查该 SQL 账号的授权。如果列出了 `role_admin`、`role_readonly` 或 `role_readwrite` 等角色,则它是一个 SQL 代理账号。 + + ```sql + SHOW GRANTS for 'username'; + ``` + +## SQL 代理账号如何创建 + +当在集群中被授予具有权限的角色的 TiDB Cloud 用户,在 TiDB Cloud 集群初始化期间会自动创建 SQL 代理账号。 + +## SQL 代理账号如何删除 + +当用户从[组织](/tidb-cloud/manage-user-access.md#remove-an-organization-member)或[项目](/tidb-cloud/manage-user-access.md#remove-a-project-member)中被移除,或其角色更改为无法访问集群的角色时,SQL 代理账号会自动删除。 + +请注意,如果手动删除了 SQL 代理账号,当用户下次登录 TiDB Cloud 控制台时,该账号会自动重新创建。 + +## SQL 代理账号用户名 + +在某些情况下,SQL 代理账号用户名与 TiDB Cloud 用户名完全相同,但在其他情况下则不完全相同。SQL 代理账号用户名由 TiDB Cloud 用户的电子邮件地址长度决定。规则如下: + +| 环境 | 邮箱长度 | 用户名格式 | +| ----------- | ------------ | --------------- | +| TiDB Cloud Dedicated | <= 32 字符 | 完整邮箱地址 | +| TiDB Cloud Dedicated | > 32 字符 | `prefix($email, 23)_prefix(base58(sha1($email)), 8)` | +| TiDB Cloud Serverless | <= 15 字符 | `serverless_unique_prefix + "." + email` | +| TiDB Cloud Serverless | > 15 字符 | `serverless_unique_prefix + "." + prefix($email, 6)_prefix(base58(sha1($email)), 8)` | + +示例: + +| 环境 | 邮箱地址 | SQL 代理账号用户名 | +| ----------- | ----- | -------- | +| TiDB Cloud Dedicated | `user@pingcap.com` | `user@pingcap.com` | +| TiDB Cloud Dedicated | `longemailaddressexample@pingcap.com` | `longemailaddressexample_48k1jwL9` | +| TiDB Cloud Serverless | `u1@pingcap.com` | `{user_name_prefix}.u1@pingcap.com` | +| TiDB Cloud Serverless | `longemailaddressexample@pingcap.com` | `{user_name_prefix}.longem_48k1jwL9`| + +> **注意:** +> +> 在上表中,`{user_name_prefix}` 是由 TiDB Cloud 生成的唯一前缀,用于区分 TiDB Cloud Serverless 集群。详情请参见 TiDB Cloud Serverless 集群的[用户名前缀](/tidb-cloud/select-cluster-tier.md#user-name-prefix)。 + +## SQL 代理账号密码 + +由于 SQL 代理账号基于 JWT 令牌,因此无需管理这些账号的密码。安全令牌由系统自动管理。 + +## SQL 代理账号角色 + +SQL 代理账号的角色取决于 TiDB Cloud 用户的 IAM 角色: + +- 组织级别: + - 组织所有者:role_admin + - 组织计费管理员:无代理账号 + - 组织查看者:无代理账号 + - 组织控制台审计管理员:无代理账号 + +- 项目级别: + - 项目所有者:role_admin + - 项目数据访问读写:role_readwrite + - 项目数据访问只读:role_readonly + +## SQL 代理账号访问控制 + +SQL 代理账号基于 JWT 令牌,只能通过数据服务和 SQL 编辑器访问。无法使用用户名和密码通过 SQL 代理账号访问 TiDB Cloud 集群。 diff --git a/tidb-cloud/terraform-get-tidbcloud-provider.md b/tidb-cloud/terraform-get-tidbcloud-provider.md new file mode 100644 index 000000000000..94c8206119a0 --- /dev/null +++ b/tidb-cloud/terraform-get-tidbcloud-provider.md @@ -0,0 +1,130 @@ +--- +title: 获取 TiDB Cloud Terraform Provider +summary: 了解如何获取 TiDB Cloud Terraform Provider。 +--- + +# 获取 TiDB Cloud Terraform Provider + +本文档将介绍如何获取 TiDB Cloud Terraform Provider。 + +## 前提条件 + +确保满足 [TiDB Cloud Terraform Provider 概览](/tidb-cloud/terraform-tidbcloud-provider-overview.md#requirements)中的要求。 + +## 步骤 1. 安装 Terraform + +TiDB Cloud Terraform Provider 已发布到 [Terraform Registry](https://registry.terraform.io/)。您只需要安装 Terraform (>=1.0)。 + +对于 macOS,您可以按照以下步骤使用 Homebrew 安装 Terraform。 + +1. 安装 HashiCorp tap,这是一个包含所有必需 Homebrew 包的仓库。 + + ```shell + brew tap hashicorp/tap + ``` + +2. 使用 `hashicorp/tap/terraform` 安装 Terraform。 + + ```shell + brew install hashicorp/tap/terraform + ``` + +对于其他操作系统,请参阅 [Terraform 文档](https://learn.hashicorp.com/tutorials/terraform/install-cli)获取说明。 + +## 步骤 2. 创建 API 密钥 + +TiDB Cloud API 使用 HTTP 摘要认证。它可以防止您的私钥在网络上传输。 + +目前,TiDB Cloud Terraform Provider 不支持管理 API 密钥。因此,您需要在 [TiDB Cloud 控制台](https://tidbcloud.com/project/clusters)中创建 API 密钥。 + +详细步骤,请参阅 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication/API-Key-Management)。 + +## 步骤 3. 下载 TiDB Cloud Terraform Provider + +1. 创建 `main.tf` 文件: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + version = "~> 0.3.0" + } + } + required_version = ">= 1.0.0" + } + ``` + + - `source` 属性指定要从 [Terraform Registry](https://registry.terraform.io/) 下载的目标 Terraform provider。 + - `version` 属性是可选的,它指定 Terraform provider 的版本。如果未指定,默认使用最新的 provider 版本。 + - `required_version` 是可选的,它指定 Terraform 的版本。如果未指定,默认使用最新的 Terraform 版本。 + +2. 运行 `terraform init` 命令从 Terraform Registry 下载 TiDB Cloud Terraform Provider。 + + ``` + $ terraform init + + Initializing the backend... + + Initializing provider plugins... + - Reusing previous version of tidbcloud/tidbcloud from the dependency lock file + - Using previously-installed tidbcloud/tidbcloud v0.1.0 + + Terraform has been successfully initialized! + + You may now begin working with Terraform. Try running "terraform plan" to see + any changes that are required for your infrastructure. All Terraform commands + should now work. + + If you ever set or change modules or backend configuration for Terraform, + rerun this command to reinitialize your working directory. If you forget, other + commands will detect it and remind you to do so if necessary. + ``` + +## 步骤 4. 使用 API 密钥配置 TiDB Cloud Terraform Provider + +您可以按如下方式配置 `main.tf` 文件: + +``` +terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } +} + +provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" +} +``` + +`public_key` 和 `private_key` 是 API 密钥的公钥和私钥。您也可以通过环境变量传递它们: + +``` +export TIDBCLOUD_PUBLIC_KEY=${public_key} +export TIDBCLOUD_PRIVATE_KEY=${private_key} +``` + +现在,您可以使用 TiDB Cloud Terraform Provider 了。 + +## 步骤 5. 使用同步配置配置 TiDB Cloud Terraform Provider + +Terraform provider (>= 0.3.0) 支持一个可选参数 `sync`。 + +通过将 `sync` 设置为 `true`,您可以同步创建、更新或删除资源。以下是一个示例: + +``` +provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + sync = true +} +``` + +建议将 `sync` 设置为 `true`,但请注意,`sync` 目前仅适用于集群资源。如果您需要对其他资源进行同步操作,请[联系 TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +## 下一步 + +通过[集群资源](/tidb-cloud/terraform-use-cluster-resource.md)开始管理集群。 diff --git a/tidb-cloud/terraform-migrate-cluster-resource.md b/tidb-cloud/terraform-migrate-cluster-resource.md new file mode 100644 index 000000000000..6422b4abbe0d --- /dev/null +++ b/tidb-cloud/terraform-migrate-cluster-resource.md @@ -0,0 +1,87 @@ +--- +title: 将集群资源迁移到 Serverless 或 Dedicated 集群资源 +summary: 了解如何将集群资源迁移到 serverless 或 dedicated 集群资源。 +--- + +# 将集群资源迁移到 Serverless 或 Dedicated 集群资源 + +从 TiDB Cloud Terraform Provider v0.4.0 开始,`tidbcloud_cluster` 资源被两个新资源替代:`tidbcloud_serverless_cluster` 和 `tidbcloud_dedicated_cluster`。如果你正在使用 TiDB Cloud Terraform Provider v0.4.0 或更高版本,可以按照本文档将你的 `tidbcloud_cluster` 资源迁移到 `tidbcloud_serverless_cluster` 或 `tidbcloud_dedicated_cluster` 资源。 + +> **提示:** +> +> 本文档中的步骤使用 Terraform 的配置生成功能来简化迁移过程,通过自动重新创建集群资源的 `.tf` 配置。要了解更多信息,请参阅 Terraform 文档中的[生成配置](https://developer.hashicorp.com/terraform/language/import/generating-configuration)。 + +## 前提条件 + +- 升级到 [TiDB Cloud Terraform Provider v0.4.0 或更高版本](https://registry.terraform.io/providers/tidbcloud/tidbcloud/latest) + +## 步骤 1. 确定要迁移的 `tidbcloud_cluster` 资源 + +1. 列出所有 `tidbcloud_cluster` 资源: + + ```shell + terraform state list | grep "tidbcloud_cluster" + ``` + +2. 选择要迁移的目标集群资源,并获取其集群 `id` 以供后续使用: + + ```shell + terraform state show ${your_target_cluster_resource} | grep ' id ' + ``` + +## 步骤 2. 从 Terraform 状态中移除现有资源 + +从 Terraform 状态中移除目标集群资源: + +```shell +terraform state rm ${your_target_cluster_resource} +``` + +## 步骤 3. 删除目标集群资源的配置 + +在你的 `.tf` 文件中,找到目标集群资源的配置并删除相应的代码。 + +## 步骤 4. 为新的 serverless 或 dedicated 集群资源添加导入块 + +- 如果你的目标集群是 TiDB Cloud Serverless,将以下导入块添加到你的 `.tf` 文件中,将 `example` 替换为所需的资源名称,并将 `${id}` 替换为你在[步骤 1](#步骤-1-确定要迁移的-tidbcloud_cluster-资源)中获取的集群 ID: + + ``` + # TiDB Cloud Serverless + import { + to = tidbcloud_serverless_cluster.example + id = "${id}" + } + ``` + +- 如果你的目标集群是 TiDB Cloud Dedicated,将以下导入块添加到你的 `.tf` 文件中,将 `example` 替换为所需的资源名称,并将 `${id}` 替换为你在[步骤 1](#步骤-1-确定要迁移的-tidbcloud_cluster-资源)中获取的集群 ID: + + ``` + # TiDB Cloud Dedicated + import { + to = tidbcloud_dedicated_cluster.example + id = "${id}" + } + ``` + +## 步骤 5. 生成新的配置文件 + +根据导入块为新的 serverless 或 dedicated 集群资源生成新的配置文件: + +```shell +terraform plan -generate-config-out=generated.tf +``` + +不要在上述命令中指定现有的 `.tf` 文件名。否则,Terraform 将返回错误。 + +## 步骤 6. 审查并应用生成的配置 + +审查生成的配置文件以确保它满足你的需求。你可以选择将此文件的内容移动到你喜欢的位置。 + +然后,运行 `terraform apply` 来导入你的基础设施。应用后,示例输出如下: + +```shell +tidbcloud_serverless_cluster.example: Importing... +tidbcloud_serverless_cluster.example: Import complete + +Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed. +``` diff --git a/tidb-cloud/terraform-tidbcloud-provider-overview.md b/tidb-cloud/terraform-tidbcloud-provider-overview.md new file mode 100644 index 000000000000..e83fab7a8af6 --- /dev/null +++ b/tidb-cloud/terraform-tidbcloud-provider-overview.md @@ -0,0 +1,55 @@ +--- +title: Terraform 集成概览 +summary: 通过 Terraform 创建、管理和更新你的 TiDB Cloud 资源。 +--- + +# Terraform 集成概览 + +[Terraform](https://www.terraform.io/) 是一个基础设施即代码工具,让你可以在可版本控制、可重用和可共享的人类可读配置文件中定义云端和自托管资源。 + +[TiDB Cloud Terraform Provider](https://registry.terraform.io/providers/tidbcloud/tidbcloud) 是一个插件,允许你使用 Terraform 管理 TiDB Cloud 资源,如集群、备份和恢复。 + +如果你正在寻找一种简单的方式来自动化资源配置和基础设施工作流,可以尝试 TiDB Cloud Terraform Provider,它为你提供以下功能: + +- 获取项目信息。 +- 获取集群规格信息,如支持的云服务提供商、区域和节点大小。 +- 管理 TiDB 集群,包括创建、扩缩容、暂停和恢复集群。 +- 为集群创建和删除备份。 +- 为集群创建恢复任务。 + +## 要求 + +- [TiDB Cloud 账户](https://tidbcloud.com/free-trial) +- [Terraform 版本](https://www.terraform.io/downloads.html) >= 1.0 +- [Go 版本](https://golang.org/doc/install) >= 1.18(仅当你想在本地构建 [TiDB Cloud Terraform Provider](https://github.com/tidbcloud/terraform-provider-tidbcloud) 时需要) + +## 支持的资源和数据源 + +[资源](https://www.terraform.io/language/resources)和[数据源](https://www.terraform.io/language/data-sources)是 Terraform 语言中最重要的两个元素。 + +TiDB Cloud 支持以下资源和数据源: + +- 资源 + + - `tidbcloud_cluster` + - `tidbcloud_backup` + - `tidbcloud_restore` + - `tidbcloud_import` + +- 数据源 + + - `tidbcloud_projects` + - `tidbcloud_cluster_specs` + - `tidbcloud_clusters` + - `tidbcloud_restores` + - `tidbcloud_backups` + +要获取资源和数据源的所有可用配置,请参阅此[配置文档](https://registry.terraform.io/providers/tidbcloud/tidbcloud/latest/docs)。 + +## 下一步 + +- [了解更多关于 Terraform 的信息](https://www.terraform.io/docs) +- [获取 TiDB Cloud Terraform Provider](/tidb-cloud/terraform-get-tidbcloud-provider.md) +- [使用集群资源](/tidb-cloud/terraform-use-cluster-resource.md) +- [使用备份资源](/tidb-cloud/terraform-use-backup-resource.md) +- [使用恢复资源](/tidb-cloud/terraform-use-restore-resource.md) diff --git a/tidb-cloud/terraform-use-backup-resource.md b/tidb-cloud/terraform-use-backup-resource.md new file mode 100644 index 000000000000..cfd022f501fa --- /dev/null +++ b/tidb-cloud/terraform-use-backup-resource.md @@ -0,0 +1,176 @@ +--- +title: 使用备份资源 +summary: 了解如何使用备份资源创建 TiDB Cloud 集群的备份。 +--- + +# 使用备份资源 + +你可以在本文档中了解如何使用 `tidbcloud_backup` 资源创建 TiDB Cloud 集群的备份。 + +`tidbcloud_backup` 资源的功能包括以下内容: + +- 为 TiDB Cloud Dedicated 集群创建备份。 +- 删除 TiDB Cloud Dedicated 集群的备份。 + +## 前提条件 + +- [获取 TiDB Cloud Terraform Provider](/tidb-cloud/terraform-get-tidbcloud-provider.md)。 +- 备份和恢复功能不适用于 TiDB Cloud Serverless 集群。要使用备份资源,请确保你已创建了 TiDB Cloud Dedicated 集群。 + +## 使用备份资源创建备份 + +1. 创建一个备份目录并进入该目录。 + +2. 创建一个 `backup.tf` 文件。 + + 例如: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + + provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + } + resource "tidbcloud_backup" "example_backup" { + project_id = "1372813089189561287" + cluster_id = "1379661944630234067" + name = "firstBackup" + description = "create by terraform" + } + ``` + + 你需要将文件中的资源值(如项目 ID 和集群 ID)替换为你自己的值。 + + 如果你已经使用 Terraform 维护了一个集群资源(例如 `example_cluster`),你也可以按如下方式配置备份资源,而无需指定实际的项目 ID 和集群 ID。 + + ``` + resource "tidbcloud_backup" "example_backup" { + project_id = tidbcloud_cluster.example_cluster.project_id + cluster_id = tidbcloud_cluster.example_cluster.id + name = "firstBackup" + description = "create by terraform" + } + ``` + +3. 运行 `terraform apply` 命令: + + ``` + $ terraform apply + + tidbcloud_cluster.example_cluster: Refreshing state... [id=1379661944630234067] + + Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + + create + + Terraform will perform the following actions: + + # tidbcloud_backup.example_backup will be created + + resource "tidbcloud_backup" "example_backup" { + + cluster_id = "1379661944630234067" + + create_timestamp = (known after apply) + + description = "create by terraform" + + id = (known after apply) + + name = "firstBackup" + + project_id = "1372813089189561287" + + size = (known after apply) + + status = (known after apply) + + type = (known after apply) + } + + Plan: 1 to add, 0 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: + ``` + +4. 输入 `yes` 创建备份: + + ``` + Enter a value: yes + + tidbcloud_backup.example_backup: Creating... + tidbcloud_backup.example_backup: Creation complete after 2s [id=1350048] + + Apply complete! Resources: 1 added, 0 changed, 0 destroyed. + + ``` + +5. 使用 `terraform state show tidbcloud_backup.${resource-name}` 检查备份状态: + + ``` + $ terraform state show tidbcloud_backup.example_backup + + # tidbcloud_backup.example_backup: + resource "tidbcloud_backup" "example_backup" { + cluster_id = "1379661944630234067" + create_timestamp = "2022-08-26T07:56:10Z" + description = "create by terraform" + id = "1350048" + name = "firstBackup" + project_id = "1372813089189561287" + size = "0" + status = "PENDING" + type = "MANUAL" + } + ``` + +6. 等待几分钟。然后使用 `terraform refersh` 更新状态: + + ``` + $ terraform refresh + tidbcloud_cluster.example_cluster: Refreshing state... [id=1379661944630234067] + tidbcloud_backup.example_backup: Refreshing state... [id=1350048] + $ terraform state show tidbcloud_backup.example_backup + # tidbcloud_backup.example_backup: + resource "tidbcloud_backup" "example_backup" { + cluster_id = "1379661944630234067" + create_timestamp = "2022-08-26T07:56:10Z" + description = "create by terraform" + id = "1350048" + name = "firstBackup" + project_id = "1372813089189561287" + size = "198775" + status = "SUCCESS" + type = "MANUAL" + } + ``` + +当状态变为 `SUCCESS` 时,表示你已经为集群创建了备份。请注意,备份在创建后无法更新。 + +现在,你已经为集群创建了备份。如果你想使用备份来恢复集群,可以[使用恢复资源](/tidb-cloud/terraform-use-restore-resource.md)。 + +## 更新备份 + +备份无法更新。 + +## 删除备份 + +要删除备份,请转到包含相应 `backup.tf` 文件的备份目录,然后运行 `terraform destroy` 命令来销毁备份资源。 + +``` +$ terraform destroy + +Plan: 0 to add, 0 to change, 1 to destroy. + +Do you really want to destroy all resources? +Terraform will destroy all your managed infrastructure, as shown above. +There is no undo. Only 'yes' will be accepted to confirm. + +Enter a value: yes +``` + +现在,如果你运行 `terraform show` 命令,你将得不到任何内容,因为资源已被清除: + +``` +$ terraform show +``` diff --git a/tidb-cloud/terraform-use-cluster-resource.md b/tidb-cloud/terraform-use-cluster-resource.md new file mode 100644 index 000000000000..15aff5f529ca --- /dev/null +++ b/tidb-cloud/terraform-use-cluster-resource.md @@ -0,0 +1,975 @@ +--- +title: 使用集群资源 +summary: 了解如何使用集群资源创建和修改 TiDB Cloud 集群。 +--- + +# 使用集群资源 + +本文档介绍如何使用 `tidbcloud_cluster` 资源管理 TiDB Cloud 集群。 + +此外,你还将学习如何使用 `tidbcloud_projects` 和 `tidbcloud_cluster_specs` 数据源获取必要信息。 + +`tidbcloud_cluster` 资源的功能包括以下内容: + +- 创建 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 集群。 +- 修改 TiDB Cloud Dedicated 集群。 +- 删除 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 集群。 + +## 前提条件 + +- [获取 TiDB Cloud Terraform Provider](/tidb-cloud/terraform-get-tidbcloud-provider.md)。 + +## 使用 `tidbcloud_projects` 数据源获取项目 ID + +每个 TiDB 集群都在一个项目中。在创建 TiDB 集群之前,你需要获取要在其中创建集群的项目 ID。 + +要查看所有可用项目的信息,你可以按照以下方式使用 `tidbcloud_projects` 数据源: + +1. 在[获取 TiDB Cloud Terraform Provider](/tidb-cloud/terraform-get-tidbcloud-provider.md) 时创建的 `main.tf` 文件中,添加 `data` 和 `output` 块,如下所示: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + + provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + sync = true + } + + data "tidbcloud_projects" "example_project" { + page = 1 + page_size = 10 + } + + output "projects" { + value = data.tidbcloud_projects.example_project.items + } + ``` + + - 使用 `data` 块定义 TiDB Cloud 的数据源,包括数据源类型和数据源名称。 + + - 要使用项目数据源,请将数据源类型设置为 `tidbcloud_projects`。 + - 对于数据源名称,你可以根据需要定义它。例如,"example_project"。 + - 对于 `tidbcloud_projects` 数据源,你可以使用 `page` 和 `page_size` 属性来限制要检查的最大项目数。 + + - 使用 `output` 块定义要在输出中显示的数据源信息,并公开信息供其他 Terraform 配置使用。 + + `output` 块的工作方式类似于编程语言中的返回值。有关更多详细信息,请参阅 [Terraform 文档](https://www.terraform.io/language/values/outputs)。 + + 要获取资源和数据源的所有可用配置,请参阅此[配置文档](https://registry.terraform.io/providers/tidbcloud/tidbcloud/latest/docs)。 + +2. 运行 `terraform apply` 命令以应用配置。你需要在确认提示时输入 `yes` 才能继续。 + + 要跳过提示,请使用 `terraform apply --auto-approve`: + + ``` + $ terraform apply --auto-approve + + Changes to Outputs: + + projects = [ + + { + + cluster_count = 0 + + create_timestamp = "1649154426" + + id = "1372813089191121286" + + name = "test1" + + org_id = "1372813089189921287" + + user_count = 1 + }, + + { + + cluster_count = 1 + + create_timestamp = "1640602740" + + id = "1372813089189561287" + + name = "default project" + + org_id = "1372813089189921287" + + user_count = 1 + }, + ] + + You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure. + + Apply complete! Resources: 0 added, 0 changed, 0 destroyed. + + Outputs: + + projects = tolist([ + { + "cluster_count" = 0 + "create_timestamp" = "1649154426" + "id" = "1372813089191121286" + "name" = "test1" + "org_id" = "1372813089189921287" + "user_count" = 1 + }, + { + "cluster_count" = 1 + "create_timestamp" = "1640602740" + "id" = "1372813089189561287" + "name" = "default project" + "org_id" = "1372813089189921287" + "user_count" = 1 + }, + ]) + ``` + +现在,你可以从输出中获取所有可用的项目。复制你需要的项目 ID。 +## 使用 `tidbcloud_cluster_specs` 数据源获取集群规格信息 + +在创建集群之前,你需要获取集群规格信息,其中包含所有可用的配置值(如支持的云服务提供商、区域和节点大小)。 + +要获取集群规格信息,你可以按照以下方式使用 `tidbcloud_cluster_specs` 数据源: + +1. 编辑 `main.tf` 文件,如下所示: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + sync = true + } + data "tidbcloud_cluster_specs" "example_cluster_spec" { + } + output "cluster_spec" { + value = data.tidbcloud_cluster_specs.example_cluster_spec.items + } + ``` + +2. 运行 `terraform apply --auto-approve` 命令,你将获得集群规格信息。 + + 点击以下行查看部分示例结果供参考。 + +
+ 集群规格 + + ``` + { + "cloud_provider" = "AWS" + "cluster_type" = "DEDICATED" + "region" = "eu-central-1" + "tidb" = tolist([ + { + "node_quantity_range" = { + "min" = 1 + "step" = 1 + } + "node_size" = "4C16G" + }, + { + "node_quantity_range" = { + "min" = 1 + "step" = 1 + } + "node_size" = "8C16G" + }, + { + "node_quantity_range" = { + "min" = 1 + "step" = 1 + } + "node_size" = "16C32G" + }, + ]) + "tiflash" = tolist([ + { + "node_quantity_range" = { + "min" = 0 + "step" = 1 + } + "node_size" = "8C64G" + "storage_size_gib_range" = { + "max" = 2048 + "min" = 500 + } + }, + { + "node_quantity_range" = { + "min" = 0 + "step" = 1 + } + "node_size" = "16C128G" + "storage_size_gib_range" = { + "max" = 2048 + "min" = 500 + } + }, + ]) + "tikv" = tolist([ + { + "node_quantity_range" = { + "min" = 3 + "step" = 3 + } + "node_size" = "4C16G" + "storage_size_gib_range" = { + "max" = 2048 + "min" = 200 + } + }, + { + "node_quantity_range" = { + "min" = 3 + "step" = 3 + } + "node_size" = "8C32G" + "storage_size_gib_range" = { + "max" = 4096 + "min" = 500 + } + }, + { + "node_quantity_range" = { + "min" = 3 + "step" = 3 + } + "node_size" = "8C64G" + "storage_size_gib_range" = { + "max" = 4096 + "min" = 500 + } + }, + { + "node_quantity_range" = { + "min" = 3 + "step" = 3 + } + "node_size" = "16C64G" + "storage_size_gib_range" = { + "max" = 4096 + "min" = 500 + } + }, + ]) + } + ``` + +
+ +在结果中: + +- `cloud_provider` 是可以托管 TiDB 集群的云服务提供商。 +- `region` 是 `cloud_provider` 的区域。 +- `node_quantity_range` 显示最小节点数和扩展节点的步长。 +- `node_size` 是节点的大小。 +- `storage_size_gib_range` 显示可以为节点设置的最小和最大存储大小。 +## 使用集群资源创建集群 + +> **注意:** +> +> 在开始之前,请确保你已在 TiDB Cloud 控制台中设置了 CIDR。有关更多信息,请参阅[设置 CIDR](/tidb-cloud/set-up-vpc-peering-connections.md#prerequisite-set-a-cidr-for-a-region)。 + +你可以使用 `tidbcloud_cluster` 资源创建集群。 + +以下示例展示如何创建 TiDB Cloud Dedicated 集群。 + +1. 为集群创建一个目录并进入该目录。 + +2. 创建一个 `cluster.tf` 文件: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + + provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + sync = true + } + + resource "tidbcloud_cluster" "example_cluster" { + project_id = "1372813089189561287" + name = "firstCluster" + cluster_type = "DEDICATED" + cloud_provider = "AWS" + region = "eu-central-1" + config = { + root_password = "Your_root_password1." + port = 4000 + components = { + tidb = { + node_size : "8C16G" + node_quantity : 1 + } + tikv = { + node_size : "8C32G" + storage_size_gib : 500, + node_quantity : 3 + } + } + } + } + ``` + + 使用 `resource` 块定义 TiDB Cloud 的资源,包括资源类型、资源名称和资源详细信息。 + + - 要使用集群资源,请将资源类型设置为 `tidbcloud_cluster`。 + - 对于资源名称,你可以根据需要定义它。例如,`example_cluster`。 + - 对于资源详细信息,你可以根据项目 ID 和集群规格信息进行配置。 + +3. 运行 `terraform apply` 命令。不建议在应用资源时使用 `terraform apply --auto-approve`。 + + ```shell + $ terraform apply + + Terraform will perform the following actions: + + # tidbcloud_cluster.example_cluster will be created + + resource "tidbcloud_cluster" "example_cluster" { + + cloud_provider = "AWS" + + cluster_type = "DEDICATED" + + config = { + + components = { + + tidb = { + + node_quantity = 1 + + node_size = "8C16G" + } + + tikv = { + + node_quantity = 3 + + node_size = "8C32G" + + storage_size_gib = 500 + } + } + + ip_access_list = [ + + { + + cidr = "0.0.0.0/0" + + description = "all" + }, + ] + + port = 4000 + + root_password = "Your_root_password1." + } + + id = (known after apply) + + name = "firstCluster" + + project_id = "1372813089189561287" + + region = "eu-central-1" + + status = (known after apply) + } + + Plan: 1 to add, 0 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: + ``` + + 如上述结果所示,Terraform 为你生成了一个执行计划,描述了 Terraform 将采取的操作: + + - 你可以检查配置和状态之间的差异。 + - 你还可以看到此 `apply` 的结果。它将添加一个新资源,不会更改或销毁任何资源。 + - `known after apply` 表示你将在 `apply` 后获得该值。 + +4. 如果你的计划看起来没有问题,输入 `yes` 继续: + + ``` + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: yes + + tidbcloud_cluster.example_cluster: Creating... + tidbcloud_cluster.example_cluster: Creation complete after 1s [id=1379661944630234067] + + Apply complete! Resources: 1 added, 0 changed, 0 destroyed. + + ``` + +5. 使用 `terraform show` 或 `terraform state show tidbcloud_cluster.${resource-name}` 命令检查资源的状态。前者将显示所有资源和数据源的状态。 + + ```shell + $ terraform state show tidbcloud_cluster.example_cluster + + # tidbcloud_cluster.example_cluster: + resource "tidbcloud_cluster" "example_cluster" { + cloud_provider = "AWS" + cluster_type = "DEDICATED" + config = { + components = { + tidb = { + node_quantity = 1 + node_size = "8C16G" + } + tikv = { + node_quantity = 3 + node_size = "8C32G" + storage_size_gib = 500 + } + } + ip_access_list = [ + # (1 unchanged element hidden) + ] + port = 4000 + root_password = "Your_root_password1." + } + id = "1379661944630234067" + name = "firstCluster" + project_id = "1372813089189561287" + region = "eu-central-1" + status = "CREATING" + } + ``` + + 集群的状态是 `CREATING`。在这种情况下,你需要等待它变为 `AVAILABLE`,这通常需要至少 10 分钟。 + +6. 如果你想检查最新状态,运行 `terraform refresh` 命令更新状态,然后运行 `terraform state show tidbcloud_cluster.${resource-name}` 命令显示状态。 + + ``` + $ terraform refresh + + tidbcloud_cluster.example_cluster: Refreshing state... [id=1379661944630234067] + + $ terraform state show tidbcloud_cluster.example_cluste + + # tidbcloud_cluster.example_cluster: + resource "tidbcloud_cluster" "example_cluster" { + cloud_provider = "AWS" + cluster_type = "DEDICATED" + config = { + components = { + tidb = { + node_quantity = 1 + node_size = "8C16G" + } + tikv = { + node_quantity = 3 + node_size = "8C32G" + storage_size_gib = 500 + } + } + ip_access_list = [ + # (1 unchanged element hidden) + ] + port = 4000 + root_password = "Your_root_password1." + } + id = "1379661944630234067" + name = "firstCluster" + project_id = "1372813089189561287" + region = "eu-central-1" + status = "AVAILABLE" + } + ``` + +当状态为 `AVAILABLE` 时,表示你的 TiDB 集群已创建完成并可以使用。 +## 修改 TiDB Cloud Dedicated 集群 + +对于 TiDB Cloud Dedicated 集群,你可以使用 Terraform 管理集群资源,如下所示: + +- 向集群添加 TiFlash 组件。 +- 扩缩容集群。 +- 暂停或恢复集群。 + +### 添加 TiFlash 组件 + +1. 在[创建集群](#使用集群资源创建集群)时使用的 `cluster.tf` 文件中,将 `tiflash` 配置添加到 `components` 字段。 + + 例如: + + ``` + components = { + tidb = { + node_size : "8C16G" + node_quantity : 1 + } + tikv = { + node_size : "8C32G" + storage_size_gib : 500 + node_quantity : 3 + } + tiflash = { + node_size : "8C64G" + storage_size_gib : 500 + node_quantity : 1 + } + } + ``` + +2. 运行 `terraform apply` 命令: + + ``` + $ terraform apply + + tidbcloud_cluster.example_cluster: Refreshing state... [id=1379661944630234067] + + Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + ~ update in-place + + Terraform will perform the following actions: + + # tidbcloud_cluster.example_cluster will be updated in-place + ~ resource "tidbcloud_cluster" "example_cluster" { + ~ config = { + ~ components = { + + tiflash = { + + node_quantity = 1 + + node_size = "8C64G" + + storage_size_gib = 500 + } + # (2 unchanged attributes hidden) + } + # (3 unchanged attributes hidden) + } + id = "1379661944630234067" + name = "firstCluster" + ~ status = "AVAILABLE" -> (known after apply) + # (4 unchanged attributes hidden) + } + + Plan: 0 to add, 1 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: + + ``` + + 如上述执行计划所示,将添加 TiFlash,并且将更改一个资源。 + +3. 如果你的计划看起来没有问题,输入 `yes` 继续: + + ``` + Enter a value: yes + + tidbcloud_cluster.example_cluster: Modifying... [id=1379661944630234067] + tidbcloud_cluster.example_cluster: Modifications complete after 2s [id=1379661944630234067] + + Apply complete! Resources: 0 added, 1 changed, 0 destroyed. + ``` + +4. 使用 `terraform state show tidbcloud_cluster.${resource-name}` 查看状态: + + ``` + $ terraform state show tidbcloud_cluster.example_cluster + + # tidbcloud_cluster.example_cluster: + resource "tidbcloud_cluster" "example_cluster" { + cloud_provider = "AWS" + cluster_type = "DEDICATED" + config = { + components = { + tidb = { + node_quantity = 1 + node_size = "8C16G" + } + tiflash = { + node_quantity = 1 + node_size = "8C64G" + storage_size_gib = 500 + } + tikv = { + node_quantity = 3 + node_size = "8C32G" + storage_size_gib = 500 + } + } + ip_access_list = [ + # (1 unchanged element hidden) + ] + port = 4000 + root_password = "Your_root_password1." + } + id = "1379661944630234067" + name = "firstCluster" + project_id = "1372813089189561287" + region = "eu-central-1" + status = "MODIFYING" + } + ``` + +`MODIFYING` 状态表示集群正在更改中。等待一段时间后,状态将变为 `AVAILABLE`。 +### 扩缩容 TiDB 集群 + +当集群状态为 `AVAILABLE` 时,你可以扩缩容集群。 + +1. 在[创建集群](#使用集群资源创建集群)时使用的 `cluster.tf` 文件中,编辑 `components` 配置。 + + 例如,要为 TiDB 增加一个节点,为 TiKV 增加 3 个节点(TiKV 节点数需要是 3 的倍数,因为其步长为 3。你可以[从集群规格中获取此信息](#使用-tidbcloud_cluster_specs-数据源获取集群规格信息)),为 TiFlash 增加一个节点,你可以按如下方式编辑配置: + + ``` + components = { + tidb = { + node_size : "8C16G" + node_quantity : 2 + } + tikv = { + node_size : "8C32G" + storage_size_gib : 500 + node_quantity : 6 + } + tiflash = { + node_size : "8C64G" + storage_size_gib : 500 + node_quantity : 2 + } + } + ``` + +2. 运行 `terraform apply` 命令并输入 `yes` 确认: + + ``` + $ terraform apply + + tidbcloud_cluster.example_cluster: Refreshing state... [id=1379661944630234067] + + Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + ~ update in-place + + Terraform will perform the following actions: + + # tidbcloud_cluster.example_cluster will be updated in-place + ~ resource "tidbcloud_cluster" "example_cluster" { + ~ config = { + ~ components = { + ~ tidb = { + ~ node_quantity = 1 -> 2 + # (1 unchanged attribute hidden) + } + ~ tiflash = { + ~ node_quantity = 1 -> 2 + # (2 unchanged attributes hidden) + } + ~ tikv = { + ~ node_quantity = 3 -> 6 + # (2 unchanged attributes hidden) + } + } + # (3 unchanged attributes hidden) + } + id = "1379661944630234067" + name = "firstCluster" + ~ status = "AVAILABLE" -> (known after apply) + # (4 unchanged attributes hidden) + } + + Plan: 0 to add, 1 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: yes + + tidbcloud_cluster.example_cluster: Modifying... [id=1379661944630234067] + tidbcloud_cluster.example_cluster: Modifications complete after 2s [id=1379661944630234067] + + Apply complete! Resources: 0 added, 1 changed, 0 destroyed. + ``` + +等待状态从 `MODIFYING` 变为 `AVAILABLE`。 +### 暂停或恢复集群 + +当集群状态为 `AVAILABLE` 时,你可以暂停集群,或者当集群状态为 `PAUSED` 时,你可以恢复集群。 + +- 设置 `paused = true` 暂停集群。 +- 设置 `paused = false` 恢复集群。 + +1. 在[创建集群](#使用集群资源创建集群)时使用的 `cluster.tf` 文件中,将 `pause = true` 添加到 `config` 配置中: + + ``` + config = { + paused = true + root_password = "Your_root_password1." + port = 4000 + ... + } + ``` + +2. 运行 `terraform apply` 命令并在检查后输入 `yes`: + + ``` + $ terraform apply + + tidbcloud_cluster.example_cluster: Refreshing state... [id=1379661944630234067] + + Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + ~ update in-place + + Terraform will perform the following actions: + + # tidbcloud_cluster.example_cluster will be updated in-place + ~ resource "tidbcloud_cluster" "example_cluster" { + ~ config = { + + paused = true + # (4 unchanged attributes hidden) + } + id = "1379661944630234067" + name = "firstCluster" + ~ status = "AVAILABLE" -> (known after apply) + # (4 unchanged attributes hidden) + } + + Plan: 0 to add, 1 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: yes + + tidbcloud_cluster.example_cluster: Modifying... [id=1379661944630234067] + tidbcloud_cluster.example_cluster: Modifications complete after 2s [id=1379661944630234067] + + Apply complete! Resources: 0 added, 1 changed, 0 destroyed. + ``` + +3. 使用 `terraform state show tidbcloud_cluster.${resource-name}` 命令检查状态: + + ``` + $ terraform state show tidbcloud_cluster.example_cluster + + # tidbcloud_cluster.example_cluster: + resource "tidbcloud_cluster" "example_cluster" { + cloud_provider = "AWS" + cluster_type = "DEDICATED" + config = { + components = { + tidb = { + node_quantity = 2 + node_size = "8C16G" + } + tiflash = { + node_quantity = 2 + node_size = "8C64G" + storage_size_gib = 500 + } + tikv = { + node_quantity = 6 + node_size = "8C32G" + storage_size_gib = 500 + } + } + ip_access_list = [ + # (1 unchanged element hidden) + ] + paused = true + port = 4000 + root_password = "Your_root_password1." + } + id = "1379661944630234067" + name = "firstCluster" + project_id = "1372813089189561287" + region = "eu-central-1" + status = "PAUSED" + } + ``` + +4. 当你需要恢复集群时,设置 `paused = false`: + + ``` + config = { + paused = false + root_password = "Your_root_password1." + port = 4000 + ... + } + ``` + +5. 运行 `terraform apply` 命令并输入 `yes` 确认。如果你使用 `terraform state show tidbcloud_cluster.${resource-name}` 命令检查状态,你会发现它变为 `RESUMING`: + + ``` + # tidbcloud_cluster.example_cluster: + resource "tidbcloud_cluster" "example_cluster" { + cloud_provider = "AWS" + cluster_type = "DEDICATED" + config = { + components = { + tidb = { + node_quantity = 2 + node_size = "8C16G" + } + tiflash = { + node_quantity = 2 + node_size = "8C64G" + storage_size_gib = 500 + } + tikv = { + node_quantity = 6 + node_size = "8C32G" + storage_size_gib = 500 + } + } + ip_access_list = [ + # (1 unchanged element hidden) + ] + paused = false + port = 4000 + root_password = "Your_root_password1." + } + id = "1379661944630234067" + name = "firstCluster" + project_id = "1372813089189561287" + region = "eu-central-1" + status = "RESUMING" + } + ``` + +6. 等待一段时间,然后使用 `terraform refersh` 命令更新状态。状态最终将变为 `AVAILABLE`。 + +现在,你已经使用 Terraform 创建和管理了一个 TiDB Cloud Dedicated 集群。接下来,你可以尝试使用我们的[备份资源](/tidb-cloud/terraform-use-backup-resource.md)创建集群的备份。 +## 导入集群 + +对于不是由 Terraform 管理的 TiDB 集群,你可以通过导入它来使用 Terraform 管理它。 + +例如,你可以导入不是由 Terraform 创建的集群,或导入[使用恢复资源创建](/tidb-cloud/terraform-use-restore-resource.md#create-a-restore-task)的集群。 + +1. 创建一个 `import_cluster.tf` 文件,如下所示: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + resource "tidbcloud_cluster" "import_cluster" {} + ``` + +2. 通过 `terraform import tidbcloud_cluster.import_cluster projectId,clusterId` 导入集群: + + 例如: + + ``` + $ terraform import tidbcloud_cluster.import_cluster 1372813089189561287,1379661944630264072 + + tidbcloud_cluster.import_cluster: Importing from ID "1372813089189561287,1379661944630264072"... + tidbcloud_cluster.import_cluster: Import prepared! + Prepared tidbcloud_cluster for import + tidbcloud_cluster.import_cluster: Refreshing state... [id=1379661944630264072] + + Import successful! + + The resources that were imported are shown above. These resources are now in + your Terraform state and will henceforth be managed by Terraform. + ``` + +3. 运行 `terraform state show tidbcloud_cluster.import_cluster` 命令检查集群的状态: + + ``` + $ terraform state show tidbcloud_cluster.import_cluster + + # tidbcloud_cluster.import_cluster: + resource "tidbcloud_cluster" "import_cluster" { + cloud_provider = "AWS" + cluster_type = "DEDICATED" + config = { + components = { + tidb = { + node_quantity = 2 + node_size = "8C16G" + } + tiflash = { + node_quantity = 2 + node_size = "8C64G" + storage_size_gib = 500 + } + tikv = { + node_quantity = 6 + node_size = "8C32G" + storage_size_gib = 500 + } + } + port = 4000 + } + id = "1379661944630264072" + name = "restoreCluster" + project_id = "1372813089189561287" + region = "eu-central-1" + status = "AVAILABLE" + } + ``` + +4. 要使用 Terraform 管理集群,你可以将上一步的输出复制到你的配置文件中。注意,你需要删除 `id` 和 `status` 行,因为它们将由 Terraform 控制: + + ``` + resource "tidbcloud_cluster" "import_cluster" { + cloud_provider = "AWS" + cluster_type = "DEDICATED" + config = { + components = { + tidb = { + node_quantity = 2 + node_size = "8C16G" + } + tiflash = { + node_quantity = 2 + node_size = "8C64G" + storage_size_gib = 500 + } + tikv = { + node_quantity = 6 + node_size = "8C32G" + storage_size_gib = 500 + } + } + port = 4000 + } + name = "restoreCluster" + project_id = "1372813089189561287" + region = "eu-central-1" + } + ``` + +5. 你可以使用 `terraform fmt` 格式化你的配置文件: + + ``` + $ terraform fmt + ``` + +6. 为确保配置和状态的一致性,你可以执行 `terraform plan` 或 `terraform apply`。如果你看到 `No changes`,则导入成功。 + + ``` + $ terraform apply + + tidbcloud_cluster.import_cluster: Refreshing state... [id=1379661944630264072] + + No changes. Your infrastructure matches the configuration. + + Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed. + + Apply complete! Resources: 0 added, 0 changed, 0 destroyed. + ``` + +现在你可以使用 Terraform 管理集群了。 + +## 删除集群 + +要删除集群,进入包含相应 `cluster.tf` 文件的集群目录,然后运行 `terraform destroy` 命令销毁集群资源: + +``` +$ terraform destroy + +Plan: 0 to add, 0 to change, 1 to destroy. + +Do you really want to destroy all resources? +Terraform will destroy all your managed infrastructure, as shown above. +There is no undo. Only 'yes' will be accepted to confirm. + +Enter a value: yes +``` + +现在,如果你运行 `terraform show` 命令,你将得到空输出,因为资源已被清除: + +``` +$ terraform show +``` diff --git a/tidb-cloud/terraform-use-import-resource.md b/tidb-cloud/terraform-use-import-resource.md new file mode 100644 index 000000000000..30e787f949a3 --- /dev/null +++ b/tidb-cloud/terraform-use-import-resource.md @@ -0,0 +1,301 @@ +--- +title: 使用导入资源 +summary: 了解如何使用导入资源管理导入任务。 +--- + +# 使用导入资源 + +本文档介绍如何使用 `tidbcloud_import` 资源将数据导入到 TiDB Cloud 集群。 + +`tidbcloud_import` 资源的功能包括以下内容: + +- 为 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 集群创建导入任务。 +- 从本地磁盘或 Amazon S3 存储桶导入数据。 +- 取消正在进行的导入任务。 + +## 前提条件 + +- [获取 TiDB Cloud Terraform Provider](/tidb-cloud/terraform-get-tidbcloud-provider.md)。 +- [创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)或[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +## 创建并运行导入任务 + +您可以使用导入资源管理本地导入任务或 Amazon S3 导入任务。 + +### 创建并运行本地导入任务 + +> **注意:** +> +> 导入本地文件仅支持 TiDB Cloud Serverless 集群,不支持 TiDB Cloud Dedicated 集群。 + +1. 创建用于导入的 CSV 文件。例如: + + ``` + id;name;age + 1;Alice;20 + 2;Bob;30 + ``` + +2. 创建一个 `import` 目录,然后在其中创建一个 `main.tf`。例如: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + + provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + } + + resource "tidbcloud_import" "example_local" { + project_id = "your_project_id" + cluster_id = "your_cluster_id" + type = "LOCAL" + data_format = "CSV" + csv_format = { + separator = ";" + } + target_table = { + database = "test" + table = "import_test" + } + file_name = "your_csv_path" + } + ``` + + 用您自己的值替换文件中的资源值(如项目 ID、集群 ID 和 CSV 路径)。您可以在[配置页面](https://registry.terraform.io/providers/tidbcloud/tidbcloud/latest/docs/resources/import#nested-schema-for-csv_format)上找到 `csv_format` 的详细信息。 + +3. 运行 `terraform apply` 命令创建导入任务,然后输入 `yes` 确认创建并开始导入: + + ``` + $ terraform apply + ... + Plan: 1 to add, 0 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: yes + + tidbcloud_import.example_local: Creating... + tidbcloud_import.example_local: Creation complete after 6s [id=781074] + ``` + +4. 使用 `terraform state show tidbcloud_import.${resource-name}` 检查导入任务的状态: + + ``` + $ terraform state show tidbcloud_import.example_local + # tidbcloud_import.example_local: + resource "tidbcloud_import" "example_local" { + all_completed_tables = [ + { + message = "" + result = "SUCCESS" + table_name = "`test`.`import_test`" + }, + ] + cluster_id = "1379661944641274168" + completed_percent = 100 + completed_tables = 1 + created_at = "2023-02-06T05:39:46.000Z" + csv_format = { + separator = ";" + } + data_format = "CSV" + elapsed_time_seconds = 48 + file_name = "./t.csv" + id = "781074" + new_file_name = "2023-02-06T05:39:42Z-t.csv" + pending_tables = 0 + post_import_completed_percent = 100 + processed_source_data_size = "31" + project_id = "1372813089191151295" + status = "IMPORTING" + target_table = { + database = "test" + table = "import_test" + } + total_files = 0 + total_size = "31" + total_tables_count = 1 + type = "LOCAL" + } + ``` + +5. 几分钟后使用 `terraform refresh` 更新状态: + + ``` + $ terraform refresh && terraform state show tidbcloud_import.example_local + tidbcloud_import.example_local: Refreshing state... [id=781074] + # tidbcloud_import.example_local: + resource "tidbcloud_import" "example_local" { + all_completed_tables = [ + { + message = "" + result = "SUCCESS" + table_name = "`test`.`import_test`" + }, + ] + cluster_id = "1379661944641274168" + completed_percent = 100 + completed_tables = 1 + created_at = "2023-02-06T05:39:46.000Z" + csv_format = { + separator = ";" + } + data_format = "CSV" + elapsed_time_seconds = 49 + file_name = "./t.csv" + id = "781074" + new_file_name = "2023-02-06T05:39:42Z-t.csv" + pending_tables = 0 + post_import_completed_percent = 100 + processed_source_data_size = "31" + project_id = "1372813089191151295" + status = "COMPLETED" + target_table = { + database = "test" + table = "import_test" + } + total_files = 0 + total_size = "31" + total_tables_count = 1 + type = "LOCAL" + } + ``` + + 当状态变为 `COMPLETED` 时,表示导入任务已完成。 + +6. 使用 MySQL CLI 检查导入的数据: + + ``` + mysql> SELECT * FROM test.import_test; + +------+-------+------+ + | id | name | age | + +------+-------+------+ + | 1 | Alice | 20 | + | 2 | Bob | 30 | + +------+-------+------+ + 2 rows in set (0.24 sec) + ``` + +### 创建并运行 Amazon S3 导入任务 + +> **注意:** +> +> 要允许 TiDB Cloud 访问您 Amazon S3 存储桶中的文件,您需要先[配置 Amazon S3 访问权限](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)。 + +1. 创建一个 `import` 目录,然后在其中创建一个 `main.tf`。例如: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + + provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + } + + resource "tidbcloud_import" "example_s3_csv" { + project_id = "your_project_id" + cluster_id = "your_cluster_id" + type = "S3" + data_format = "CSV" + aws_role_arn = "your_arn" + source_url = "your_url" + } + + resource "tidbcloud_import" "example_s3_parquet" { + project_id = "your_project_id" + cluster_id = "your_cluster_id" + type = "S3" + data_format = "Parquet" + aws_role_arn = "your_arn" + source_url = "your_url" + } + ``` + +2. 运行 `terraform apply` 命令创建导入任务,然后输入 `yes` 确认创建并开始导入: + + ``` + $ terraform apply + ... + Plan: 2 to add, 0 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: yes + + tidbcloud_import.example_s3_csv: Creating... + tidbcloud_import.example_s3_csv: Creation complete after 3s [id=781075] + tidbcloud_import.example_s3_parquet: Creating... + tidbcloud_import.example_s3_parquet: Creation complete after 4s [id=781076] + ``` + +3. 使用 `terraform refresh` 和 `terraform state show tidbcloud_import.${resource-name}` 更新和检查导入任务的状态。 + +## 更新导入任务 + +导入任务无法更新。 + +## 删除导入任务 + +对于 Terraform,删除导入任务意味着取消相应的导入资源。 + +您无法取消 `COMPLETED` 状态的导入任务。否则,您将收到如下示例中的 `Delete Error`: + +``` +$ terraform destroy +... +Plan: 0 to add, 0 to change, 1 to destroy. + +Do you really want to destroy all resources? + Terraform will destroy all your managed infrastructure, as shown above. + There is no undo. Only 'yes' will be accepted to confirm. + + Enter a value: yes + +tidbcloud_import.example_local: Destroying... [id=781074] +╷ +│ Error: Delete Error +│ +│ Unable to call CancelImport, got error: [DELETE /api/internal/projects/{project_id}/clusters/{cluster_id}/imports/{id}][500] CancelImport default &{Code:59900104 Details:[] Message:failed to cancel +│ import} +╵ +``` + +您可以取消状态为 `IMPORTING` 的导入任务。例如: + +``` +$ terraform destroy +... +Plan: 0 to add, 0 to change, 1 to destroy. + +Do you really want to destroy all resources? + Terraform will destroy all your managed infrastructure, as shown above. + There is no undo. Only 'yes' will be accepted to confirm. + + Enter a value: yes + +tidbcloud_import.example_local: Destroying... [id=781074] +tidbcloud_import.example_local: Destruction complete after 0s + +Destroy complete! Resources: 1 destroyed. +``` + +## 配置 + +请参阅[配置文档](https://registry.terraform.io/providers/tidbcloud/tidbcloud/latest/docs/resources/import)获取导入资源的所有可用配置。 diff --git a/tidb-cloud/terraform-use-restore-resource.md b/tidb-cloud/terraform-use-restore-resource.md new file mode 100644 index 000000000000..e06bc4a92314 --- /dev/null +++ b/tidb-cloud/terraform-use-restore-resource.md @@ -0,0 +1,192 @@ +--- +title: 使用恢复资源 +summary: 了解如何使用恢复资源。 +--- + +# 使用恢复资源 + +你可以在本文档中了解如何使用 `tidbcloud_restore` 资源管理恢复任务。 + +`tidbcloud_restore` 资源的功能包括以下内容: + +- 根据你的备份为 TiDB Cloud Dedicated 集群创建恢复任务。 + +## 前提条件 + +- [获取 TiDB Cloud Terraform Provider](/tidb-cloud/terraform-get-tidbcloud-provider.md)。 +- 备份和恢复功能不适用于 TiDB Cloud Serverless 集群。要使用恢复资源,请确保你已创建了 TiDB Cloud Dedicated 集群。 + +## 创建恢复任务 + +创建集群备份后,你可以通过使用 `tidbcloud_restore` 资源创建恢复任务来恢复集群。 + +> **注意:** +> +> 你只能从较小的节点规格恢复数据到相同或更大的节点规格。 + +1. 创建一个恢复目录并进入该目录。 + +2. 创建一个 `restore.tf` 文件。 + + 例如: + + ``` + terraform { + required_providers { + tidbcloud = { + source = "tidbcloud/tidbcloud" + } + } + } + + provider "tidbcloud" { + public_key = "your_public_key" + private_key = "your_private_key" + } + resource "tidbcloud_restore" "example_restore" { + project_id = tidbcloud_cluster.example_cluster.project_id + backup_id = tidbcloud_backup.example_backup.id + name = "restoreCluster" + config = { + root_password = "Your_root_password1." + port = 4000 + components = { + tidb = { + node_size : "8C16G" + node_quantity : 2 + } + tikv = { + node_size : "8C32G" + storage_size_gib : 500 + node_quantity : 6 + } + tiflash = { + node_size : "8C64G" + storage_size_gib : 500 + node_quantity : 2 + } + } + } + } + ``` + +3. 运行 `terraform apply` 命令并输入 `yes` 确认: + + ``` + $ terraform apply + tidbcloud_cluster.example_cluster: Refreshing state... [id=1379661944630234067] + tidbcloud_backup.example_backup: Refreshing state... [id=1350048] + + Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + + create + + Terraform will perform the following actions: + + # tidbcloud_restore.example_restore will be created + + resource "tidbcloud_restore" "example_restore" { + + backup_id = "1350048" + + cluster = { + + id = (known after apply) + + name = (known after apply) + + status = (known after apply) + } + + cluster_id = (known after apply) + + config = { + + components = { + + tidb = { + + node_quantity = 2 + + node_size = "8C16G" + } + + tiflash = { + + node_quantity = 2 + + node_size = "8C64G" + + storage_size_gib = 500 + } + + tikv = { + + node_quantity = 6 + + node_size = "8C32G" + + storage_size_gib = 500 + } + } + + port = 4000 + + root_password = "Your_root_password1." + } + + create_timestamp = (known after apply) + + error_message = (known after apply) + + id = (known after apply) + + name = "restoreCluster" + + project_id = "1372813089189561287" + + status = (known after apply) + } + + Plan: 1 to add, 0 to change, 0 to destroy. + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: yes + + tidbcloud_restore.example_restore: Creating... + tidbcloud_restore.example_restore: Creation complete after 1s [id=780114] + + Apply complete! Resources: 1 added, 0 changed, 0 destroyed. + ``` + +4. 使用 `terraform state show tidbcloud_restore.${resource-name}` 命令检查恢复任务的状态: + + ``` + $ terraform state show tidbcloud_restore.example_restore + + # tidbcloud_restore.example_restore: + resource "tidbcloud_restore" "example_restore" { + backup_id = "1350048" + cluster = { + id = "1379661944630264072" + name = "restoreCluster" + status = "INITIALIZING" + } + cluster_id = "1379661944630234067" + config = { + components = { + tidb = { + node_quantity = 2 + node_size = "8C16G" + } + tiflash = { + node_quantity = 2 + node_size = "8C64G" + storage_size_gib = 500 + } + tikv = { + node_quantity = 6 + node_size = "8C32G" + storage_size_gib = 500 + } + } + port = 4000 + root_password = "Your_root_password1." + } + create_timestamp = "2022-08-26T08:16:33Z" + id = "780114" + name = "restoreCluster" + project_id = "1372813089189561287" + status = "PENDING" + } + ``` + + 你可以看到恢复任务的状态是 `PENDING`,集群的状态是 `INITIALIZING`。 + +5. 等待几分钟。然后使用 `terraform refersh` 更新状态。 + +6. 在集群状态变为 `AVAILABLE` 后,恢复任务将变为 `RUNNING`,最后变为 `SUCCESS`。 + +注意,恢复的集群不由 Terraform 管理。你可以通过[导入集群](/tidb-cloud/terraform-use-cluster-resource.md#import-a-cluster)来管理恢复的集群。 + +## 更新恢复任务 + +恢复任务无法更新。 + +## 删除恢复任务 + +恢复任务无法删除。 diff --git a/tidb-cloud/third-party-monitoring-integrations.md b/tidb-cloud/third-party-monitoring-integrations.md new file mode 100644 index 000000000000..65f8c272af16 --- /dev/null +++ b/tidb-cloud/third-party-monitoring-integrations.md @@ -0,0 +1,45 @@ +--- +title: 第三方指标集成(Beta) +summary: 了解如何使用第三方指标集成。 +--- + +# 第三方指标集成(Beta) + +您可以将 TiDB Cloud 与第三方指标服务集成,以接收 TiDB Cloud 警报并使用指标服务查看 TiDB 集群的性能指标。第三方指标集成目前处于 beta 阶段。 + +## 所需权限 + +要编辑第三方集成设置,您必须是组织的 `Organization Owner` 角色或目标项目的 `Project Owner` 角色。 + +## 查看或修改第三方集成 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到您的目标项目。 +2. 在左侧导航栏中,点击**项目设置** > **集成**。 + +此时会显示可用的第三方集成。 + +## 限制 + +- 对于 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,不支持第三方指标集成。 + +- 当集群状态为**创建中**、**恢复中**、**已暂停**或**恢复中**时,第三方指标集成不可用。 + +## 可用集成 + +### Datadog 集成(beta) + +通过 Datadog 集成,您可以配置 TiDB Cloud 将 TiDB 集群的指标数据发送到 [Datadog](https://www.datadoghq.com/),并在 Datadog 仪表板中查看这些指标。 + +有关详细的集成步骤和 Datadog 跟踪的指标列表,请参考[将 TiDB Cloud 与 Datadog 集成](/tidb-cloud/monitor-datadog-integration.md)。 + +### Prometheus 和 Grafana 集成(beta) + +通过 Prometheus 和 Grafana 集成,您可以从 TiDB Cloud 获取 Prometheus 的 `scrape_config` 文件,并使用该文件中的内容配置 Prometheus。您可以在 Grafana 仪表板中查看这些指标。 + +有关详细的集成步骤和 Prometheus 跟踪的指标列表,请参见[将 TiDB Cloud 与 Prometheus 和 Grafana 集成](/tidb-cloud/monitor-prometheus-and-grafana-integration.md)。 + +### New Relic 集成(beta) + +通过 New Relic 集成,您可以配置 TiDB Cloud 将 TiDB 集群的指标数据发送到 [New Relic](https://newrelic.com/),并在 New Relic 仪表板中查看这些指标。 + +有关详细的集成步骤和 New Relic 跟踪的指标列表,请参见[将 TiDB Cloud 与 New Relic 集成](/tidb-cloud/monitor-new-relic-integration.md)。 diff --git a/tidb-cloud/ticloud-ai.md b/tidb-cloud/ticloud-ai.md new file mode 100644 index 000000000000..3a02ff3a3ea4 --- /dev/null +++ b/tidb-cloud/ticloud-ai.md @@ -0,0 +1,47 @@ +--- +title: ticloud ai +summary: `ticloud ai` 命令的参考文档。 +--- + +# ticloud ai + +与 TiDB Bot 对话: + +```shell +ticloud ai [flags] +``` + +## 示例 + +在交互模式下与 TiDB Bot 对话: + +```shell +ticloud ai +``` + +在非交互模式下与 TiDB Bot 对话: + +```shell +ticloud ai -q "How to create a cluster?" +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写这些信息。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|--------------------|--------------------------------|----------|-------------------------------------| +| -q, --query string | 指定要向 TiDB Bot 提出的问题。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均可使用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-auth-login.md b/tidb-cloud/ticloud-auth-login.md new file mode 100644 index 000000000000..2399d45abd32 --- /dev/null +++ b/tidb-cloud/ticloud-auth-login.md @@ -0,0 +1,47 @@ +--- +title: ticloud auth login +summary: `ticloud auth login` 命令的参考。 +--- + +# ticloud auth login + +使用 TiDB Cloud 进行身份验证: + +```shell +ticloud auth login [flags] +``` + +## 示例 + +登录 TiDB Cloud: + +```shell +ticloud auth login +``` + +使用不安全存储方式登录 TiDB Cloud: + +```shell +ticloud auth login --insecure-storage +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|--------------------|---------------------------------------------------------------------------|----------|------------------------------------------------------| +| --insecure-storage | 以明文方式保存身份验证凭据,而不是使用凭据存储。 | 否 | 在非交互和交互模式下都可用。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都可用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|--------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-auth-logout.md b/tidb-cloud/ticloud-auth-logout.md new file mode 100644 index 000000000000..3b646193052e --- /dev/null +++ b/tidb-cloud/ticloud-auth-logout.md @@ -0,0 +1,32 @@ +--- +title: ticloud auth logout +summary: `ticloud auth logout` 命令的参考。 +--- + +# ticloud auth logout + +登出 TiDB Cloud: + +```shell +ticloud auth logout [flags] +``` + +## 示例 + +登出 TiDB Cloud: + +```shell +ticloud auth logout +``` + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-auth-whoami.md b/tidb-cloud/ticloud-auth-whoami.md new file mode 100644 index 000000000000..f5587b90b4ab --- /dev/null +++ b/tidb-cloud/ticloud-auth-whoami.md @@ -0,0 +1,40 @@ +--- +title: ticloud auth whoami +summary: `ticloud auth whoami` 命令的参考文档。 +--- + +# ticloud auth whoami + +显示当前用户的信息: + +```shell +ticloud auth whoami [flags] +``` + +## 示例 + +显示当前用户的信息: + +```shell +ticloud auth whoami +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写这些信息。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------|--------------------------|----------|-------------------------------------| +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均可使用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-branch-create.md b/tidb-cloud/ticloud-branch-create.md new file mode 100644 index 000000000000..708e382749bb --- /dev/null +++ b/tidb-cloud/ticloud-branch-create.md @@ -0,0 +1,56 @@ +--- +title: ticloud serverless branch create +summary: `ticloud serverless branch create` 命令的参考。 +--- + +# ticloud serverless branch create + +为 TiDB Cloud Serverless 集群创建一个[分支](/tidb-cloud/branch-overview.md): + +```shell +ticloud serverless branch create [flags] +``` + +## 示例 + +在交互模式下为 TiDB Cloud Serverless 集群创建分支: + +```shell +ticloud serverless branch create +``` + +在非交互模式下为 TiDB Cloud Serverless 集群创建分支: + +```shell +ticloud serverless branch create --cluster-id --display-name +``` + +在非交互模式下从另一个分支的指定时间点创建分支: + +```shell +ticloud serverless branch create --cluster-id --display-name --parent-id --parent-timestamp +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|---------------------------|-----------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------------| +| -c, --cluster-id string | 指定要在其中创建分支的集群 ID。 | 是 | 仅在非交互模式下有效。 | +| -n, --display-name string | 指定要创建的分支名称。 | 是 | 仅在非交互模式下有效。 | +| --parent-id string | 指定父分支的 ID。默认值为集群 ID。 | 否 | 仅在非交互模式下有效。 | +| --parent-timestamp string | 指定父分支的时间戳,格式为 RFC3339,例如 `2024-01-01T00:00:00Z`。默认值为当前时间。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都可用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-branch-delete.md b/tidb-cloud/ticloud-branch-delete.md new file mode 100644 index 000000000000..6b2da6d23426 --- /dev/null +++ b/tidb-cloud/ticloud-branch-delete.md @@ -0,0 +1,55 @@ +--- +title: ticloud serverless branch delete +summary: `ticloud serverless branch delete` 命令的参考。 +--- + +# ticloud serverless branch delete + +从你的 TiDB Cloud Serverless 集群中删除一个分支: + +```shell +ticloud serverless branch delete [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless branch rm [flags] +``` + +## 示例 + +在交互模式下删除 TiDB Cloud Serverless 分支: + +```shell +ticloud serverless branch delete +``` + +在非交互模式下删除 TiDB Cloud Serverless 分支: + +```shell +ticloud branch delete --branch-id --cluster-id +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-------------------------------------|----------|------------------------------------------| +| -b, --branch-id string | 指定要删除的分支的 ID。 | 是 | 仅在非交互模式下生效。 | +| --force | 删除分支时不需要确认。 | 否 | 在非交互模式和交互模式下都有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下生效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-branch-describe.md b/tidb-cloud/ticloud-branch-describe.md new file mode 100644 index 000000000000..06bf26c379ae --- /dev/null +++ b/tidb-cloud/ticloud-branch-describe.md @@ -0,0 +1,54 @@ +--- +title: ticloud serverless branch describe +summary: `ticloud serverless branch describe` 命令的参考文档。 +--- + +# ticloud serverless branch describe + +获取分支的信息(如端点、[用户名前缀](/tidb-cloud/select-cluster-tier.md#user-name-prefix)和使用情况): + +```shell +ticloud serverless branch describe [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless branch get [flags] +``` + +## 示例 + +在交互模式下获取 TiDB Cloud Serverless 集群的分支信息: + +```shell +ticloud serverless branch describe +``` + +在非交互模式下获取 TiDB Cloud Serverless 集群的分支信息: + +```shell +ticloud serverless branch describe --branch-id --cluster-id +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写这些信息。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|--------------------------------|----------|-------------------------------------| +| -b, --branch-id string | 指定分支的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均可使用。 | +| -c, --cluster-id string| 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-branch-list.md b/tidb-cloud/ticloud-branch-list.md new file mode 100644 index 000000000000..ce6981a5b341 --- /dev/null +++ b/tidb-cloud/ticloud-branch-list.md @@ -0,0 +1,60 @@ +--- +title: ticloud serverless branch list +summary: `ticloud serverless branch list` 命令的参考。 +--- + +# ticloud serverless branch list + +列出 TiDB Cloud Serverless 集群的所有分支: + +```shell +ticloud serverless branch list [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless branch ls [flags] +``` + +## 示例 + +在交互模式下列出 TiDB Cloud Serverless 集群的所有分支: + +```shell +ticloud serverless branch list +``` + +在非交互模式下列出特定 TiDB Cloud Serverless 集群的所有分支: + +```shell +ticloud serverless branch list -c +``` + +以 JSON 格式列出特定 TiDB Cloud Serverless 集群的所有分支: + +```shell +ticloud serverless branch list -o json +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 注意 | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都有效。 | +| -o, --output string | 指定输出格式(默认为 `human`)。有效值为 `human` 或 `json`。要获取完整结果,请使用 `json` 格式。 | 否 | 在非交互和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-branch-shell.md b/tidb-cloud/ticloud-branch-shell.md new file mode 100644 index 000000000000..8aefb61e9968 --- /dev/null +++ b/tidb-cloud/ticloud-branch-shell.md @@ -0,0 +1,63 @@ +--- +title: ticloud serverless branch shell +summary: `ticloud serverless branch shell` 命令的参考。 +aliases: ['/tidbcloud/ticloud-connect'] +--- + +# ticloud serverless branch shell + +连接到 TiDB Cloud Serverless 集群的分支: + +```shell +ticloud serverless branch shell [flags] +``` + +## 示例 + +在交互模式下连接到 TiDB Cloud Serverless 分支: + +```shell +ticloud serverless branch shell +``` + +在非交互模式下使用默认用户连接到 TiDB Cloud Serverless 分支: + +```shell +ticloud serverless branch shell -c -b +``` + +在非交互模式下使用默认用户和密码连接到 TiDB Cloud Serverless 分支: + +```shell +ticloud serverless branch shell -c -b --password +``` + +在非交互模式下使用指定用户和密码连接到 TiDB Cloud Serverless 分支: + +```shell +ticloud serverless branch shell -c -b -u --password +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|-------------------------------------|----------|------------------------------------------------------| +| -b, --branch-id string | 指定分支的 ID。 | 是 | 仅在非交互模式下有效。 | +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | +| --password | 指定用户的密码。 | 否 | 仅在非交互模式下有效。 | +| -u, --user string | 指定登录用户。 | 否 | 仅在非交互模式下有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-cluster-create.md b/tidb-cloud/ticloud-cluster-create.md new file mode 100644 index 000000000000..6c064e717794 --- /dev/null +++ b/tidb-cloud/ticloud-cluster-create.md @@ -0,0 +1,58 @@ +--- +title: ticloud serverless create +summary: `ticloud serverless create` 命令的参考。 +--- + +# ticloud serverless create + +创建 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless create [flags] +``` + +## 示例 + +在交互模式下创建 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless create +``` + +在非交互模式下创建 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless create --display-name --region +``` + +在非交互模式下创建带有支出限制的 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless create --display-name --region --spending-limit-monthly +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------------|--------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------------| +| -n --display-name string | 指定要创建的集群的名称。 | 是 | 仅在非交互模式下有效。 | +| --spending-limit-monthly int | 指定每月最大支出限制(以美分为单位)。 | 否 | 仅在非交互模式下有效。 | +| -p, --project-id string | 指定要在其中创建集群的项目的 ID。默认值为 `default project`。 | 否 | 仅在非交互模式下有效。 | +| -r, --region string | 指定云区域的名称。你可以使用 "ticloud serverless region" 查看所有区域。 | 是 | 仅在非交互模式下有效。 | +| --disable-public-endpoint | 禁用公共端点。 | 否 | 仅在非交互模式下有效。 | +| --encryption | 启用增强的静态加密。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-cluster-delete.md b/tidb-cloud/ticloud-cluster-delete.md new file mode 100644 index 000000000000..584d579630c6 --- /dev/null +++ b/tidb-cloud/ticloud-cluster-delete.md @@ -0,0 +1,54 @@ +--- +title: ticloud serverless cluster delete +summary: `ticloud serverless delete` 命令的参考。 +--- + +# ticloud serverless delete + +从你的项目中删除一个 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless delete [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless rm [flags] +``` + +## 示例 + +在交互模式下删除 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless delete +``` + +在非交互模式下删除 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless delete --cluster-id +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-------------------------------------|----------|------------------------------------------| +| -c, --cluster-id string | 指定要删除的集群的 ID。 | 是 | 仅在非交互模式下生效。 | +| --force | 删除集群时不需要确认。 | 否 | 在非交互模式和交互模式下都有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-cluster-describe.md b/tidb-cloud/ticloud-cluster-describe.md new file mode 100644 index 000000000000..c04dbd38d1c2 --- /dev/null +++ b/tidb-cloud/ticloud-cluster-describe.md @@ -0,0 +1,53 @@ +--- +title: ticloud serverless cluster describe +summary: `ticloud serverless describe` 命令的参考。 +--- + +# ticloud serverless describe + +获取 TiDB Cloud Serverless 集群的信息(例如集群配置和集群状态): + +```shell +ticloud serverless describe [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless get [flags] +``` + +## 示例 + +在交互模式下获取 TiDB Cloud Serverless 集群的信息: + +```shell +ticloud serverless describe +``` + +在非交互模式下获取 TiDB Cloud Serverless 集群的信息: + +```shell +ticloud serverless describe --cluster-id +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-----------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都可用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-cluster-list.md b/tidb-cloud/ticloud-cluster-list.md new file mode 100644 index 000000000000..ea8751807bb0 --- /dev/null +++ b/tidb-cloud/ticloud-cluster-list.md @@ -0,0 +1,60 @@ +--- +title: ticloud serverless cluster list +summary: `ticloud serverless list` 命令的参考。 +--- + +# ticloud serverless list + +列出项目中的所有 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless list [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless ls [flags] +``` + +## 示例 + +在交互模式下列出所有 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless list +``` + +在非交互模式下列出指定项目中的所有 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless list -p +``` + +在非交互模式下以 JSON 格式列出指定项目中的所有 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless list -p -o json +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|------------------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -p, --project-id string | 指定项目的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | +| -o, --output string | 指定输出格式(默认为 `human`)。有效值为 `human` 或 `json`。要获取完整结果,请使用 `json` 格式。 | 否 | 在非交互和交互模式下均有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-completion.md b/tidb-cloud/ticloud-completion.md new file mode 100644 index 000000000000..d190a63825d1 --- /dev/null +++ b/tidb-cloud/ticloud-completion.md @@ -0,0 +1,46 @@ +--- +title: ticloud completion +summary: `ticloud completion` 命令的参考。 +--- + +# ticloud completion + +为指定的 shell 生成 TiDB Cloud CLI 的自动补全脚本: + +```shell +ticloud completion [command] +``` + +## 示例 + +为 bash 生成自动补全脚本: + +```shell +ticloud completion bash +``` + +为 zsh 生成自动补全脚本: + +```shell +ticloud completion zsh +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|-------------------------------------|----------|------------------------------------------------------| +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-config-create.md b/tidb-cloud/ticloud-config-create.md new file mode 100644 index 000000000000..e1651bb6d1b0 --- /dev/null +++ b/tidb-cloud/ticloud-config-create.md @@ -0,0 +1,53 @@ +--- +title: ticloud config create +summary: `ticloud config create` 命令的参考。 +--- + +# ticloud config create + +创建[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)以存储用户配置设置: + +```shell +ticloud config create [flags] +``` + +> **注意:** +> +> 在创建用户配置文件之前,你需要[创建 TiDB Cloud API 密钥](https://docs.pingcap.com/tidbcloud/api/v1beta#section/Authentication/API-Key-Management)。 + +## 示例 + +在交互模式下创建用户配置文件: + +```shell +ticloud config create +``` + +在非交互模式下创建用户配置文件: + +```shell +ticloud config create --profile-name --public-key --private-key +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|-----------------------|----------------------------------------|----------|------------------------------------------| +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | +| --private-key string | 指定 TiDB Cloud API 的私钥。 | 是 | 仅在非交互模式下生效。 | +| --profile-name string | 指定配置文件的名称(不能包含 `.`)。 | 是 | 仅在非交互模式下生效。 | +| --public-key string | 指定 TiDB Cloud API 的公钥。 | 是 | 仅在非交互模式下生效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-config-delete.md b/tidb-cloud/ticloud-config-delete.md new file mode 100644 index 000000000000..30f74ae3e9da --- /dev/null +++ b/tidb-cloud/ticloud-config-delete.md @@ -0,0 +1,45 @@ +--- +title: ticloud config delete +summary: `ticloud config delete` 命令的参考。 +--- + +# ticloud config delete + +删除一个[用户配置文件](/tidb-cloud/cli-reference.md#user-profile): + +```shell +ticloud config delete [flags] +``` + +或使用以下别名命令: + +```shell +ticloud config rm [flags] +``` + +## 示例 + +删除一个用户配置文件: + +```shell +ticloud config delete +``` + +## 参数标志 + +| 参数标志 | 描述 | +|------------|---------------------------------------| +| --force | 无需确认即删除配置文件。 | +| -h, --help | 显示此命令的帮助信息。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-config-describe.md b/tidb-cloud/ticloud-config-describe.md new file mode 100644 index 000000000000..7f17c8e1155f --- /dev/null +++ b/tidb-cloud/ticloud-config-describe.md @@ -0,0 +1,44 @@ +--- +title: ticloud config describe +summary: `ticloud config describe` 命令的参考。 +--- + +# ticloud config describe + +获取特定[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)的属性信息: + +```shell +ticloud config describe [flags] +``` + +或使用以下别名命令: + +```shell +ticloud config get [flags] +``` + +## 示例 + +描述用户配置文件: + +```shell +ticloud config describe +``` + +## 标志 + +| 标志 | 描述 | +|------------|--------------------------| +| -h, --help | 显示此命令的帮助信息。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|-----------------------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-config-edit.md b/tidb-cloud/ticloud-config-edit.md new file mode 100644 index 000000000000..c12f6b5dca2a --- /dev/null +++ b/tidb-cloud/ticloud-config-edit.md @@ -0,0 +1,44 @@ +--- +title: ticloud config edit +summary: `ticloud config edit` 命令的参考。 +--- + +# ticloud config edit + +如果你使用的是 macOS 或 Linux,你可以使用默认的文本编辑器打开配置文件: + +```shell +ticloud config edit [flags] +``` + +如果你使用的是 Windows,执行上述命令后,将会打印配置文件的路径。 + +> **注意:** +> +> 为了避免格式错误和执行失败,不建议手动编辑配置文件。相反,你可以使用 [`ticloud config create`](/tidb-cloud/ticloud-config-create.md)、[`ticloud config delete`](/tidb-cloud/ticloud-config-delete.md) 或 [`ticloud config set`](/tidb-cloud/ticloud-config-set.md) 来修改配置。 + +## 示例 + +编辑配置文件: + +```shell +ticloud config edit +``` + +## 参数标志 + +| 参数标志 | 描述 | +|------------|--------------------------| +| -h, --help | 显示此命令的帮助信息。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-config-list.md b/tidb-cloud/ticloud-config-list.md new file mode 100644 index 000000000000..0b98fd106f43 --- /dev/null +++ b/tidb-cloud/ticloud-config-list.md @@ -0,0 +1,44 @@ +--- +title: ticloud config list +summary: `ticloud config list` 命令的参考。 +--- + +# ticloud config list + +列出所有[用户配置文件](/tidb-cloud/cli-reference.md#user-profile): + +```shell +ticloud config list [flags] +``` + +或使用以下别名命令: + +```shell +ticloud config ls [flags] +``` + +## 示例 + +列出所有可用的用户配置文件: + +```shell +ticloud config list +``` + +## 标志 + +| 标志 | 描述 | +|------------|--------------------------| +| -h, --help | 显示此命令的帮助信息。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-config-set.md b/tidb-cloud/ticloud-config-set.md new file mode 100644 index 000000000000..f0cae22ba608 --- /dev/null +++ b/tidb-cloud/ticloud-config-set.md @@ -0,0 +1,66 @@ +--- +title: ticloud config set +summary: `ticloud config set` 命令的参考。 +--- + +# ticloud config set + +配置活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)的属性: + +```shell +ticloud config set [flags] +``` + +可以配置的属性包括 `public-key`、`private-key` 和 `api-url`。 + +| 属性 | 描述 | 是否必需 | +|-------------|------------------------------------------------------------------|----------| +| public-key | 指定 TiDB Cloud API 的公钥。 | 是 | +| private-key | 指定 TiDB Cloud API 的私钥。 | 是 | +| api-url | 指定 TiDB Cloud 的基础 API URL(默认为 `https://api.tidbcloud.com`)。| 否 | + +> **注意:** +> +> 如果你想为特定用户配置文件配置属性,可以在命令中添加 `-P` 标志并指定目标用户配置文件名称。 + +## 示例 + +为活动配置文件设置 public-key 的值: + +```shell +ticloud config set public-key +``` + +为特定配置文件 `test` 设置 public-key 的值: + +```shell +ticloud config set public-key -P test +``` + +设置 API 主机: + +```shell +ticloud config set api-url https://api.tidbcloud.com +``` + +> **注意:** +> +> TiDB Cloud API URL 默认为 `https://api.tidbcloud.com`。通常情况下,你不需要设置它。 + +## 标志 + +| 标志 | 描述 | +|------------|--------------------------| +| -h, --help | 显示此命令的帮助信息。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-config-use.md b/tidb-cloud/ticloud-config-use.md new file mode 100644 index 000000000000..2d99bb306f0d --- /dev/null +++ b/tidb-cloud/ticloud-config-use.md @@ -0,0 +1,38 @@ +--- +title: ticloud config use +summary: `ticloud config use` 命令的参考文档。 +--- + +# ticloud config use + +将指定的配置文件设置为活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile): + +```shell +ticloud config use [flags] +``` + +## 示例 + +将 `test` 配置文件设置为活动用户配置文件: + +```shell +ticloud config use test +``` + +## 参数标志 + +| 参数标志 | 描述 | +|------------|--------------------------| +| -h, --help | 显示此命令的帮助信息。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-help.md b/tidb-cloud/ticloud-help.md new file mode 100644 index 000000000000..48749126dc55 --- /dev/null +++ b/tidb-cloud/ticloud-help.md @@ -0,0 +1,46 @@ +--- +title: ticloud help +summary: `ticloud help` 命令的参考。 +--- + +# ticloud help + +获取 TiDB Cloud CLI 中任何命令的帮助信息: + +```shell +ticloud help [command] [flags] +``` + +## 示例 + +获取 `auth` 命令的帮助信息: + +```shell +ticloud help auth +``` + +获取 `serverless create` 命令的帮助信息: + +```shell +ticloud help serverless create +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 注意 | +|-------------------------|---------------------------------------------------------------|----------|------------------------------------------------------| +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|-------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-import-cancel.md b/tidb-cloud/ticloud-import-cancel.md new file mode 100644 index 000000000000..27239ef72eba --- /dev/null +++ b/tidb-cloud/ticloud-import-cancel.md @@ -0,0 +1,49 @@ +--- +title: ticloud serverless import cancel +summary: `ticloud serverless import cancel` 命令的参考。 +--- + +# ticloud serverless import cancel + +取消数据导入任务: + +```shell +ticloud serverless import cancel [flags] +``` + +## 示例 + +在交互模式下取消导入任务: + +```shell +ticloud serverless import cancel +``` + +在非交互模式下取消导入任务: + +```shell +ticloud serverless import cancel --cluster-id --import-id +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-------------------------------------|----------|------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下生效。 | +| --force | 取消导入任务时不需要确认。 | 否 | 在非交互模式和交互模式下都有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | +| --import-id string | 指定导入任务的 ID。 | 是 | 仅在非交互模式下生效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-import-describe.md b/tidb-cloud/ticloud-import-describe.md new file mode 100644 index 000000000000..485b9a1d0ed4 --- /dev/null +++ b/tidb-cloud/ticloud-import-describe.md @@ -0,0 +1,54 @@ +--- +title: ticloud serverless import describe +summary: `ticloud serverless import describe` 命令的参考。 +--- + +# ticloud serverless import describe + +描述数据导入任务: + +```shell +ticloud serverless import describe [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless import get [flags] +``` + +## 示例 + +在交互模式下描述导入任务: + +```shell +ticloud serverless import describe +``` + +在非交互模式下描述导入任务: + +```shell +ticloud serverless import describe --cluster-id --import-id +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 注意 | +|-------------------------|-----------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都有效。 | +| --import-id string | 指定导入任务的 ID。 | 是 | 仅在非交互模式下有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-import-list.md b/tidb-cloud/ticloud-import-list.md new file mode 100644 index 000000000000..145228201528 --- /dev/null +++ b/tidb-cloud/ticloud-import-list.md @@ -0,0 +1,60 @@ +--- +title: ticloud serverless import list +summary: `ticloud serverless import list` 命令的参考文档。 +--- + +# ticloud serverless import list + +列出数据导入任务: + +```shell +ticloud serverless import list [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless import ls [flags] +``` + +## 示例 + +在交互模式下列出导入任务: + +```shell +ticloud serverless import list +``` + +在非交互模式下列出导入任务: + +```shell +ticloud serverless import list --cluster-id +``` + +以 JSON 格式列出指定集群的导入任务: + +```shell +ticloud serverless import list --cluster-id --output json +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写这些信息。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|--------------------------------------------------------------------------------------------------------|----------|-------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均可使用。 | +| -o, --output string | 指定输出格式(默认为 `human`)。有效值为 `human` 或 `json`。要获取完整结果,请使用 `json` 格式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-import-start.md b/tidb-cloud/ticloud-import-start.md new file mode 100644 index 000000000000..20d9a6a60f52 --- /dev/null +++ b/tidb-cloud/ticloud-import-start.md @@ -0,0 +1,109 @@ +--- +title: ticloud serverless import start +summary: `ticloud serverless import start` 命令的参考。 +aliases: ['/tidbcloud/ticloud-import-start-local','/tidbcloud/ticloud-import-start-mysql','/tidbcloud/ticloud-import-start-s3'] +--- + +# ticloud serverless import start + +启动数据导入任务: + +```shell +ticloud serverless import start [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless import create [flags] +``` + +> **注意:** +> +> 目前,每个本地导入任务只能导入一个 CSV 文件。 + +## 示例 + +在交互模式下启动导入任务: + +```shell +ticloud serverless import start +``` + +在非交互模式下启动本地导入任务: + +```shell +ticloud serverless import start --local.file-path --cluster-id --file-type --local.target-database --local.target-table +``` + +使用自定义上传并发度启动本地导入任务: + +```shell +ticloud serverless import start --local.file-path --cluster-id --file-type --local.target-database --local.target-table --local.concurrency 10 +``` + +使用自定义 CSV 格式启动本地导入任务: + +```shell +ticloud serverless import start --local.file-path --cluster-id --file-type CSV --local.target-database --local.target-table --csv.separator \" --csv.delimiter \' --csv.backslash-escape=false --csv.trim-last-separator=true +``` + +在非交互模式下启动 S3 导入任务: + +```shell +ticloud serverless import start --source-type S3 --s3.uri --cluster-id --file-type --s3.role-arn +``` + +在非交互模式下启动 GCS 导入任务: + +```shell +ticloud serverless import start --source-type GCS --gcs.uri --cluster-id --file-type --gcs.service-account-key +``` + +在非交互模式下启动 Azure Blob 导入任务: + +```shell +ticloud serverless import start --source-type AZURE_BLOB --azblob.uri --cluster-id --file-type --azblob.sas-token +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------------------|-------------------------------------------------------------------------------------------------------------------|----------|------------------------------------------| +| --azblob.sas-token string | 指定 Azure Blob 的 SAS 令牌。 | 否 | 仅在非交互模式下生效。 | +| --azblob.uri string | 指定 Azure Blob URI,格式为 `azure://.blob.core.windows.net//`。 | 否 | 仅在非交互模式下生效。 | +| --gcs.service-account-key string | 指定 GCS 的 base64 编码服务账号密钥。 | 否 | 仅在非交互模式下生效。 | +| --gcs.uri string | 指定 GCS URI,格式为 `gcs:///`。当源类型为 GCS 时必需。 | 是 | 仅在非交互模式下生效。 | +| --s3.access-key-id string | 指定 Amazon S3 的访问密钥 ID。你只需要设置 `s3.role-arn` 或 [`s3.access-key-id`, `s3.secret-access-key`] 其中之一。 | 否 | 仅在非交互模式下生效。 | +| --s3.role-arn string | 指定 Amazon S3 的角色 ARN。你只需要设置 `s3.role-arn` 或 [`s3.access-key-id`, `s3.secret-access-key`] 其中之一。 | 否 | 仅在非交互模式下生效。 | +| --s3.secret-access-key string | 指定 Amazon S3 的秘密访问密钥。你只需要设置 `s3.role-arn` 或 [`s3.access-key-id`, `s3.secret-access-key`] 其中之一。| 否 | 仅在非交互模式下生效。 | +| --s3.uri string | 指定 S3 URI,格式为 `s3:///`。当源类型为 S3 时必需。 | 是 | 仅在非交互模式下生效。 | +| --source-type string | 指定导入源类型,可选值为 [`"LOCAL"` `"S3"` `"GCS"` `"AZURE_BLOB"`]。默认值为 `"LOCAL"`。 | 否 | 仅在非交互模式下生效。 | +| -c, --cluster-id string | 指定集群 ID。 | 是 | 仅在非交互模式下生效。 | +| --local.concurrency int | 指定上传文件的并发度。默认值为 `5`。 | 否 | 仅在非交互模式下生效。 | +| --local.file-path string | 指定要导入的本地文件路径。 | 否 | 仅在非交互模式下生效。 | +| --local.target-database string | 指定要导入数据的目标数据库。 | 否 | 仅在非交互模式下生效。 | +| --local.target-table string | 指定要导入数据的目标表。 | 否 | 仅在非交互模式下生效。 | +| --file-type string | 指定导入文件类型,可选值为 ["CSV" "SQL" "AURORA_SNAPSHOT" "PARQUET"]。 | 是 | 仅在非交互模式下生效。 | +| --csv.backslash-escape | 指定是否将 CSV 文件中字段内的反斜杠解析为转义字符。默认值为 `true`。 | 否 | 仅在非交互模式下生效。 | +| --csv.delimiter string | 指定 CSV 文件中用于引用的分隔符。默认值为 `\`。 | 否 | 仅在非交互模式下生效。 | +| --csv.separator string | 指定 CSV 文件中的字段分隔符。默认值为 `,`。 | 否 | 仅在非交互模式下生效。 | +| --csv.skip-header | 指定 CSV 文件是否包含标题行。 | 否 | 仅在非交互模式下生效。 | +| --csv.trim-last-separator | 指定是否将分隔符视为行终止符并修剪 CSV 文件中所有尾随分隔符。 | 否 | 仅在非交互模式下生效。 | +| --csv.not-null | 指定 CSV 文件是否可以包含任何 NULL 值。 | 否 | 仅在非交互模式下生效。 | +| --csv.null-value string | 指定 CSV 文件中 NULL 值的表示形式。(默认值为 "\\N") | 否 | 仅在非交互模式下生效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-project-list.md b/tidb-cloud/ticloud-project-list.md new file mode 100644 index 000000000000..185e8ae0d0f6 --- /dev/null +++ b/tidb-cloud/ticloud-project-list.md @@ -0,0 +1,53 @@ +--- +title: ticloud project list +summary: `ticloud project list` 命令的参考。 +--- + +# ticloud project list + +列出所有可访问的项目: + +```shell +ticloud project list [flags] +``` + +或使用以下别名命令: + +```shell +ticloud project ls [flags] +``` + +## 示例 + +列出所有可访问的项目: + +```shell +ticloud project list +``` + +以 JSON 格式列出所有可访问的项目: + +```shell +ticloud project list -o json +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|---------------------|-----------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | +| -o, --output string | 指定输出格式(默认为 `human`)。有效值为 `human` 或 `json`。要获取完整结果,请使用 `json` 格式。 | 否 | 在非交互和交互模式下均有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-authorized-network-create.md b/tidb-cloud/ticloud-serverless-authorized-network-create.md new file mode 100644 index 000000000000..d58e100c3d38 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-authorized-network-create.md @@ -0,0 +1,50 @@ +--- +title: ticloud serverless authorized-network create +summary: `ticloud serverless authorized-network create` 命令的参考。 +--- + +# ticloud serverless authorized-network create + +创建授权网络: + +```shell +ticloud serverless authorized-network create [flags] +``` + +## 示例 + +在交互模式下创建授权网络: + +```shell +ticloud serverless authorized-network create +``` + +在非交互模式下创建授权网络: + +```shell +ticloud serverless authorized-network create -c --display-name --start-ip-address --end-ip-address +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 注意 | +|-------------------------|------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| --display-name string | 指定授权网络的名称。 | 是 | 仅在非交互模式下有效。 | +| --start-ip-address string | 指定授权网络的起始 IP 地址。 | 是 | 仅在非交互模式下有效。 | +| --end-ip-address string | 指定授权网络的结束 IP 地址。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-authorized-network-delete.md b/tidb-cloud/ticloud-serverless-authorized-network-delete.md new file mode 100644 index 000000000000..f10d218faac0 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-authorized-network-delete.md @@ -0,0 +1,50 @@ +--- +title: ticloud serverless authorized-network delete +summary: `ticloud serverless authorized-network delete` 命令的参考。 +--- + +# ticloud serverless authorized-network delete + +删除授权网络: + +```shell +ticloud serverless authorized-network delete [flags] +``` + +## 示例 + +在交互模式下删除授权网络: + +```shell +ticloud serverless authorized-network delete +``` + +在非交互模式下删除授权网络: + +```shell +ticloud serverless authorized-network delete -c --start-ip-address --end-ip-address +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-------------------------------------|----------|------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下生效。 | +| --force string | 删除授权网络时不需要确认。 | 否 | 仅在非交互模式下生效。 | +| --start-ip-address string | 指定授权网络的起始 IP 地址。 | 是 | 仅在非交互模式下生效。 | +| --end-ip-address string | 指定授权网络的结束 IP 地址。 | 是 | 仅在非交互模式下生效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-authorized-network-list.md b/tidb-cloud/ticloud-serverless-authorized-network-list.md new file mode 100644 index 000000000000..eda8a6d2c524 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-authorized-network-list.md @@ -0,0 +1,48 @@ +--- +title: ticloud serverless authorized-network list +summary: `ticloud serverless authorized-network list` 命令的参考文档。 +--- + +# ticloud serverless authorized-network list + +列出所有授权网络: + +```shell +ticloud serverless authorized-network list [flags] +``` + +## 示例 + +在交互模式下列出所有授权网络: + +```shell +ticloud serverless authorized-network list +``` + +在非交互模式下列出所有授权网络: + +```shell +ticloud serverless authorized-network list -c +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写这些信息。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|--------------------------------------------------------------------------------------------------------|----------|-------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| --output string | 指定输出格式(默认为 `human`)。有效值为 `human` 或 `json`。要获取完整结果,请使用 `json` 格式。 | 否 | 在非交互和交互模式下均可使用。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均可使用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-serverless-authorized-network-update.md b/tidb-cloud/ticloud-serverless-authorized-network-update.md new file mode 100644 index 000000000000..3bc936b0a7a8 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-authorized-network-update.md @@ -0,0 +1,52 @@ +--- +title: ticloud serverless authorized-network update +summary: `ticloud serverless authorized-network update` 命令的参考。 +--- + +# ticloud serverless authorized-network update + +更新授权网络: + +```shell +ticloud serverless authorized-network update [flags] +``` + +## 示例 + +在交互模式下更新授权网络: + +```shell +ticloud serverless authorized-network update +``` + +在非交互模式下更新授权网络: + +```shell +ticloud serverless authorized-network update -c --start-ip-address --end-ip-address --new-start-ip-address --new-end-ip-address +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 注意 | +|-------------------------|------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| --start-ip-address string | 指定授权网络的起始 IP 地址。 | 是 | 仅在非交互模式下有效。 | +| --end-ip-address string | 指定授权网络的结束 IP 地址。 | 是 | 仅在非交互模式下有效。 | +| --new-display-name string | 指定授权网络的新名称。 | 否 | 仅在非交互模式下有效。 | +| --new-start-ip-address string | 指定授权网络的新起始 IP 地址。 | 否 | 仅在非交互模式下有效。 | +| --new-end-ip-address string | 指定授权网络的新结束 IP 地址。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-export-cancel.md b/tidb-cloud/ticloud-serverless-export-cancel.md new file mode 100644 index 000000000000..5ed49b25ffd9 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-export-cancel.md @@ -0,0 +1,49 @@ +--- +title: ticloud serverless export cancel +summary: `ticloud serverless export cancel` 命令的参考文档。 +--- + +# ticloud serverless export cancel + +取消数据导出任务: + +```shell +ticloud serverless export cancel [flags] +``` + +## 示例 + +在交互模式下取消导出任务: + +```shell +ticloud serverless export cancel +``` + +在非交互模式下取消导出任务: + +```shell +ticloud serverless export cancel -c -e +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写这些信息。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|--------------------------------|----------|-------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -e, --export-id string | 指定导出任务的 ID。 | 是 | 仅在非交互模式下有效。 | +| --force | 无需确认直接取消导出任务。 | 否 | 在非交互和交互模式下均可使用。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均可使用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-serverless-export-create.md b/tidb-cloud/ticloud-serverless-export-create.md new file mode 100644 index 000000000000..510e407cb82c --- /dev/null +++ b/tidb-cloud/ticloud-serverless-export-create.md @@ -0,0 +1,106 @@ +--- +title: ticloud serverless export create +summary: `ticloud serverless export create` 命令的参考。 +--- + +# ticloud serverless export create + +从 TiDB Cloud Serverless 集群导出数据: + +```shell +ticloud serverless export create [flags] +``` + +## 示例 + +在交互模式下从 TiDB Cloud Serverless 集群导出数据: + +```shell +ticloud serverless export create +``` + +在非交互模式下从 TiDB Cloud Serverless 集群导出数据到本地文件: + +```shell +ticloud serverless export create -c --filter +``` + +在非交互模式下从 TiDB Cloud Serverless 集群导出数据到 Amazon S3: + +```shell +ticloud serverless export create -c --s3.uri --s3.access-key-id --s3.secret-access-key --filter +``` + +在非交互模式下从 TiDB Cloud Serverless 集群导出数据到 Google Cloud Storage: + +```shell +ticloud serverless export create -c --gcs.uri --gcs.service-account-key --filter +``` + +在非交互模式下从 TiDB Cloud Serverless 集群导出数据到 Azure Blob Storage: + +```shell +ticloud serverless export create -c --azblob.uri --azblob.sas-token --filter +``` + +在非交互模式下从 TiDB Cloud Serverless 集群导出数据到阿里云 OSS: + +```shell +ticloud serverless export create -c --oss.uri --oss.access-key-id --oss.access-key-secret --filter +``` + +在非交互模式下导出数据到 Parquet 文件并使用 `SNAPPY` 压缩: + +```shell +ticloud serverless export create -c --file-type parquet --parquet.compression SNAPPY --filter +``` + +在非交互模式下使用 SQL 语句导出数据: + +```shell +ticloud serverless export create -c --sql 'select * from database.table' +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定要从中导出数据的集群 ID。 | 是 | 仅在非交互模式下有效。 | +| --file-type string | 指定导出文件类型。可选值为 ["SQL" "CSV" "PARQUET"]。(默认为 "CSV") | 否 | 仅在非交互模式下有效。 | +| --target-type string | 指定导出目标。可选值为 [`"LOCAL"` `"S3"` `"GCS"` `"AZURE_BLOB"` `"OSS"`]。默认值为 `"LOCAL"`。 | 否 | 仅在非交互模式下有效。 | +| --s3.uri string | 指定 S3 URI,格式为 `s3:///`。当目标类型为 S3 时必需。 | 否 | 仅在非交互模式下有效。 | +| --s3.access-key-id string | 指定 Amazon S3 的访问密钥 ID。你只需要设置 s3.role-arn 或 [s3.access-key-id, s3.secret-access-key] 其中之一。 | 否 | 仅在非交互模式下有效。 | +| --s3.secret-access-key string | 指定 Amazon S3 的秘密访问密钥。你只需要设置 s3.role-arn 或 [s3.access-key-id, s3.secret-access-key] 其中之一。 | 否 | 仅在非交互模式下有效。 | +| --s3.role-arn string | 指定 Amazon S3 的角色 ARN。你只需要设置 s3.role-arn 或 [s3.access-key-id, s3.secret-access-key] 其中之一。 | 否 | 仅在非交互模式下有效。 | +| --gcs.uri string | 指定 GCS URI,格式为 `gcs:///`。当目标类型为 GCS 时必需。 | 否 | 仅在非交互模式下有效。 | +| --gcs.service-account-key string | 指定 GCS 的 base64 编码服务账号密钥。 | 否 | 仅在非交互模式下有效。 | +| --azblob.uri string | 指定 Azure Blob URI,格式为 `azure://.blob.core.windows.net//`。当目标类型为 AZURE_BLOB 时必需。 | 否 | 仅在非交互模式下有效。 | +| --azblob.sas-token string | 指定 Azure Blob 的 SAS 令牌。 | 否 | 仅在非交互模式下有效。 | +| --oss.uri string | 指定阿里云 OSS URI,格式为 `oss:///`。当导出 `target-type` 为 `"OSS"` 时必需。 | 否 | 仅在非交互模式下有效。 | +| --oss.access-key-id string | 指定访问阿里云 OSS 的 AccessKey ID。 | 否 | 仅在非交互模式下有效。 | +| --oss.access-key-secret string | 指定访问阿里云 OSS 的 AccessKey Secret。 | 否 | 仅在非交互模式下有效。 | +| --csv.delimiter string | 指定 CSV 文件中字符串类型变量的分隔符。(默认为 "\"") | 否 | 仅在非交互模式下有效。 | +| --csv.null-value string | 指定 CSV 文件中空值的表示方式。(默认为 "\\N") | 否 | 仅在非交互模式下有效。 | +| --csv.separator string | 指定 CSV 文件中每个值的分隔符。(默认为 ",") | 否 | 仅在非交互模式下有效。 | +| --csv.skip-header | 导出表的 CSV 文件时不包含表头。 | 否 | 仅在非交互模式下有效。 | +| --parquet.compression string | 指定 Parquet 压缩算法。可选值为 [`"GZIP"` `"SNAPPY"` `"ZSTD"` `"NONE"`]。默认值为 `"ZSTD"`。 | 否 | 仅在非交互模式下有效。 | +| --filter strings | 使用表过滤模式指定要导出的表。不要与 --sql 一起使用。更多信息,请参见[表过滤器](/table-filter.md)。 | 否 | 仅在非交互模式下有效。 | +| --sql string | 使用 `SQL SELECT` 语句过滤导出的数据。 | 否 | 仅在非交互模式下有效。 | +| --where string | 使用 `WHERE` 条件过滤导出的表。不要与 --sql 一起使用。 | 否 | 仅在非交互模式下有效。 | +| --compression string | 指定导出文件的压缩算法。支持的算法包括 `GZIP`、`SNAPPY`、`ZSTD` 和 `NONE`。默认值为 `GZIP`。 | 否 | 仅在非交互模式下有效。 | +| --force | 无需确认即创建导出任务。当你想在非交互模式下导出整个集群时需要确认。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都可用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-serverless-export-describe.md b/tidb-cloud/ticloud-serverless-export-describe.md new file mode 100644 index 000000000000..9f1d312df0cd --- /dev/null +++ b/tidb-cloud/ticloud-serverless-export-describe.md @@ -0,0 +1,54 @@ +--- +title: ticloud serverless export describe +summary: `ticloud serverless export describe` 命令的参考。 +--- + +# ticloud serverless export describe + +获取 TiDB Cloud Serverless 集群的导出信息: + +```shell +ticloud serverless export describe [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless export get [flags] +``` + +## 示例 + +在交互模式下获取导出信息: + +```shell +ticloud serverless export describe +``` + +在非交互模式下获取导出信息: + +```shell +ticloud serverless export describe -c -e +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|-------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -e, --export-id string | 指定导出任务的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-export-download.md b/tidb-cloud/ticloud-serverless-export-download.md new file mode 100644 index 000000000000..1722e280b509 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-export-download.md @@ -0,0 +1,51 @@ +--- +title: ticloud serverless export download +summary: `ticloud serverless export download` 命令的参考。 +--- + +# ticloud serverless export download + +将 TiDB Cloud Serverless 集群的导出数据下载到本地存储: + +```shell +ticloud serverless export download [flags] +``` + +## 示例 + +在交互模式下下载导出数据: + +```shell +ticloud serverless export download +``` + +在非交互模式下下载导出数据: + +```shell +ticloud serverless export download -c -e +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|-----------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -e, --export-id string | 指定导出任务的 ID。 | 是 | 仅在非交互模式下有效。 | +| --output-path string | 指定保存下载数据的目标路径。如果未指定,数据将下载到当前目录。 | 否 | 仅在非交互模式下有效。 | +| --concurrency int | 指定下载并发数。默认值为 `3`。 | 否 | 在非交互和交互模式下均有效。 | +| --force | 无需确认直接下载导出数据。 | 否 | 在非交互和交互模式下均有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-export-list.md b/tidb-cloud/ticloud-serverless-export-list.md new file mode 100644 index 000000000000..6dbfb32a9fbb --- /dev/null +++ b/tidb-cloud/ticloud-serverless-export-list.md @@ -0,0 +1,60 @@ +--- +title: ticloud serverless export list +summary: `ticloud serverless export list` 命令的参考。 +--- + +# ticloud serverless export list + +列出 TiDB Cloud Serverless 集群的数据导出任务: + +```shell +ticloud serverless export list [flags] +``` + +或使用以下别名命令: + +```shell +ticloud serverless export ls [flags] +``` + +## 示例 + +在交互模式下列出所有导出任务: + +```shell +ticloud serverless export list +``` + +在非交互模式下列出指定集群的导出任务: + +```shell +ticloud serverless export list -c +``` + +在非交互模式下以 JSON 格式列出指定集群的导出任务: + +```shell +ticloud serverless export list -c -o json +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 注意 | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -o, --output string | 指定输出格式(默认为 `human`)。有效值为 `human` 或 `json`。要获取完整结果,请使用 `json` 格式。 | 否 | 在非交互和交互模式下都有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-region.md b/tidb-cloud/ticloud-serverless-region.md new file mode 100644 index 000000000000..9aada00d1bee --- /dev/null +++ b/tidb-cloud/ticloud-serverless-region.md @@ -0,0 +1,48 @@ +--- +title: ticloud serverless region +summary: `ticloud serverless region` 命令的参考。 +aliases: ['/tidbcloud/ticloud-serverless-regions'] +--- + +# ticloud serverless region + +列出 TiDB Cloud Serverless 的所有可用地域: + +```shell +ticloud serverless region [flags] +``` + +## 示例 + +列出 TiDB Cloud Serverless 的所有可用地域: + +```shell +ticloud serverless region +``` + +以 JSON 格式列出 TiDB Cloud Serverless 集群的所有可用地域: + +```shell +ticloud serverless region -o json +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 注意 | +|---------------------|--------------------------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -o, --output string | 指定输出格式(默认为 `human`)。有效值为 `human` 或 `json`。要获取完整结果,请使用 `json` 格式。 | 否 | 在非交互和交互模式下都有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 注意 | +|----------------------|--------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建[议题](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-shell.md b/tidb-cloud/ticloud-serverless-shell.md new file mode 100644 index 000000000000..db87b1816d4e --- /dev/null +++ b/tidb-cloud/ticloud-serverless-shell.md @@ -0,0 +1,62 @@ +--- +title: ticloud serverless shell +summary: `ticloud serverless shell` 命令的参考。 +aliases: ['/tidbcloud/ticloud-connect'] +--- + +# ticloud serverless shell + +连接到 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless shell [flags] +``` + +## 示例 + +在交互模式下连接到 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless shell +``` + +在非交互模式下使用默认用户连接到 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless shell -c +``` + +在非交互模式下使用默认用户和密码连接到 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless shell -c --password +``` + +在非交互模式下使用指定用户和密码连接到 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless shell -c -u --password +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|-------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | +| --password | 指定用户的密码。 | 否 | 仅在非交互模式下有效。 | +| -u, --user string | 指定登录用户。 | 否 | 仅在非交互模式下有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-spending-limit.md b/tidb-cloud/ticloud-serverless-spending-limit.md new file mode 100644 index 000000000000..e1bb3912d9d2 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-spending-limit.md @@ -0,0 +1,48 @@ +--- +title: ticloud serverless spending-limit +summary: `ticloud serverless spending-limit` 命令的参考。 +--- + +# ticloud serverless spending-limit + +为 TiDB Cloud Serverless 集群设置每月最大[消费限额](/tidb-cloud/manage-serverless-spend-limit.md): + +```shell +ticloud serverless spending-limit [flags] +``` + +## 示例 + +在交互模式下为 TiDB Cloud Serverless 集群设置消费限额: + +```shell +ticloud serverless spending-limit +``` + +在非交互模式下为 TiDB Cloud Serverless 集群设置消费限额: + +```shell +ticloud serverless spending-limit -c --monthly +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-------------------------------------|----------|------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下生效。 | +| --monthly int32 | 指定每月最大消费限额(以美分为单位)。| 是 | 仅在非交互模式下生效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-sql-user-create.md b/tidb-cloud/ticloud-serverless-sql-user-create.md new file mode 100644 index 000000000000..62e766b99db4 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-sql-user-create.md @@ -0,0 +1,50 @@ +--- +title: ticloud serverless sql-user create +summary: `ticloud serverless sql-user create` 命令的参考。 +--- + +# ticloud serverless sql-user create + +创建 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user create [flags] +``` + +## 示例 + +在交互模式下创建 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user create +``` + +在非交互模式下创建 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user create --user --password --role --cluster-id +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|-------------------------|------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| --password string | 指定 SQL 用户的密码。 | 否 | 仅在非交互模式下有效。 | +| --role strings | 指定 SQL 用户的角色。 | 否 | 仅在非交互模式下有效。 | +| -u, --user string | 指定 SQL 用户的名称。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都可用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-serverless-sql-user-delete.md b/tidb-cloud/ticloud-serverless-sql-user-delete.md new file mode 100644 index 000000000000..bbf3ce8eae11 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-sql-user-delete.md @@ -0,0 +1,48 @@ +--- +title: ticloud serverless sql-user delete +summary: `ticloud serverless sql-user delete` 命令的参考。 +--- + +# ticloud serverless sql-user delete + +删除 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user delete [flags] +``` + +## 示例 + +在交互模式下删除 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user delete +``` + +在非交互模式下删除 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user delete -c --user +``` + +## 标志 + +在非交互模式下,你需要手动输入必需的标志。在交互模式下,你只需按照 CLI 提示填写即可。 + +| 标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-------------------------------------|----------|------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下生效。 | +| --force | 删除 SQL 用户时不需要确认。 | 否 | 仅在非交互模式下生效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 继承的标志 + +| 标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下生效。在交互模式下,对某些 UI 组件禁用颜色可能不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互模式和交互模式下都有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互模式和交互模式下都有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-sql-user-list.md b/tidb-cloud/ticloud-serverless-sql-user-list.md new file mode 100644 index 000000000000..d3737a85534b --- /dev/null +++ b/tidb-cloud/ticloud-serverless-sql-user-list.md @@ -0,0 +1,48 @@ +--- +title: ticloud serverless sql-user list +summary: `ticloud serverless sql-user list` 命令的参考。 +--- + +# ticloud serverless sql-user list + +列出 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user list [flags] +``` + +## 示例 + +在交互模式下列出 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user list +``` + +在非交互模式下列出 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user list -c +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|-------------------------|-------------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -o, --output string | 指定输出格式,可选值为 ["human" "json"]。要获取完整结果,请使用 "json" 格式。(默认为 "human")。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下都可用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-serverless-sql-user-update.md b/tidb-cloud/ticloud-serverless-sql-user-update.md new file mode 100644 index 000000000000..69a52636b70e --- /dev/null +++ b/tidb-cloud/ticloud-serverless-sql-user-update.md @@ -0,0 +1,52 @@ +--- +title: ticloud serverless sql-user update +summary: `ticloud serverless sql-user update` 命令的参考。 +--- + +# ticloud serverless sql-user update + +更新 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user update [flags] +``` + +## 示例 + +在交互模式下更新 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user update +``` + +在非交互模式下更新 TiDB Cloud Serverless SQL 用户: + +```shell +ticloud serverless sql-user update -c --user --password --role +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写它们。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|------------------------|-----------------------------------------------------------------------------------------------------|----------|------------------------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| --password string | 指定 SQL 用户的新密码。 | 否 | 仅在非交互模式下有效。 | +| --role strings | 指定 SQL 用户的新角色。使用此标志会替换现有角色。 | 否 | 仅在非交互模式下有效。 | +| --add-role strings | 指定要添加给 SQL 用户的角色。 | 否 | 仅在非交互模式下有效。 | +| --delete-role strings | 指定要从 SQL 用户中删除的角色。 | 否 | 仅在非交互模式下有效。 | +| -u, --user string | 指定要更新的 SQL 用户的名称。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均有效。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|-----------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均有效。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均有效。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何贡献。 diff --git a/tidb-cloud/ticloud-serverless-update.md b/tidb-cloud/ticloud-serverless-update.md new file mode 100644 index 000000000000..e53011ae01b5 --- /dev/null +++ b/tidb-cloud/ticloud-serverless-update.md @@ -0,0 +1,56 @@ +--- +title: ticloud serverless update +summary: `ticloud serverless update` 命令的参考文档。 +--- + +# ticloud serverless update + +更新 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless update [flags] +``` + +## 示例 + +在交互模式下更新 TiDB Cloud Serverless 集群: + +```shell +ticloud serverless update +``` + +在非交互模式下更新 TiDB Cloud Serverless 集群的名称: + +```shell +ticloud serverless update -c --display-name +``` + +在非交互模式下更新 TiDB Cloud Serverless 集群的标签: + +```shell +ticloud serverless update -c --labels "{\"label1\":\"value1\"}" +``` + +## 参数标志 + +在非交互模式下,你需要手动输入必需的参数标志。在交互模式下,你可以按照 CLI 提示填写这些信息。 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|---------------------------|--------------------------------|----------|-------------------------------------| +| -c, --cluster-id string | 指定集群的 ID。 | 是 | 仅在非交互模式下有效。 | +| -n --display-name string | 指定集群的新名称。 | 否 | 仅在非交互模式下有效。 | +| --labels string | 指定集群的新标签。 | 否 | 仅在非交互模式下有效。 | +| --disable-public-endpoint | 禁用集群的公共端点。 | 否 | 仅在非交互模式下有效。 | +| -h, --help | 显示此命令的帮助信息。 | 否 | 在非交互和交互模式下均可使用。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|----------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下均可使用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下均可使用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/ticloud-upgrade.md b/tidb-cloud/ticloud-upgrade.md new file mode 100644 index 000000000000..43df61f9a924 --- /dev/null +++ b/tidb-cloud/ticloud-upgrade.md @@ -0,0 +1,39 @@ +--- +title: ticloud upgrade +summary: `ticloud upgrade` 命令的参考。 +aliases: ['/tidbcloud/ticloud-update'] +--- + +# ticloud upgrade + +将 TiDB Cloud CLI 升级到最新版本: + +```shell +ticloud upgrade [flags] +``` + +## 示例 + +将 TiDB Cloud CLI 升级到最新版本: + +```shell +ticloud upgrade +``` + +## 参数标志 + +| 参数标志 | 描述 | +|------------|-----------------------------------| +| -h, --help | 显示此命令的帮助信息。 | + +## 继承的参数标志 + +| 参数标志 | 描述 | 是否必需 | 说明 | +|----------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------------------------------------------------------| +| --no-color | 禁用输出中的颜色。 | 否 | 仅在非交互模式下有效。在交互模式下,禁用颜色可能对某些 UI 组件不起作用。 | +| -P, --profile string | 指定此命令中使用的活动[用户配置文件](/tidb-cloud/cli-reference.md#user-profile)。 | 否 | 在非交互和交互模式下都可用。 | +| -D, --debug | 启用调试模式。 | 否 | 在非交互和交互模式下都可用。 | + +## 反馈 + +如果你对 TiDB Cloud CLI 有任何问题或建议,欢迎创建一个 [issue](https://github.com/tidbcloud/tidbcloud-cli/issues/new/choose)。同时,我们也欢迎任何形式的贡献。 diff --git a/tidb-cloud/tidb-cloud-auditing.md b/tidb-cloud/tidb-cloud-auditing.md new file mode 100644 index 000000000000..06f65f555e90 --- /dev/null +++ b/tidb-cloud/tidb-cloud-auditing.md @@ -0,0 +1,336 @@ +--- +title: 数据库审计日志 +summary: 了解如何在 TiDB Cloud 中审计集群。 +--- + +# 数据库审计日志 + +TiDB Cloud 提供数据库审计日志功能,可以在日志中记录用户访问详情的历史记录(例如执行的任何 SQL 语句)。 + +> **注意:** +> +> 目前,数据库审计日志功能仅供申请使用。要申请此功能,请点击 [TiDB Cloud 控制台](https://tidbcloud.com)右下角的 **?**,然后点击 **Request Support**。然后,在 **Description** 字段中填写"申请数据库审计日志",并点击 **Submit**。 + +为了评估组织的用户访问策略和其他信息安全措施的有效性,定期分析数据库审计日志是一种安全最佳实践。 + +审计日志功能默认是禁用的。要审计集群,你需要先启用审计日志,然后指定审计过滤规则。 + +> **注意:** +> +> 由于审计日志会消耗集群资源,请谨慎考虑是否对集群进行审计。 + +## 前提条件 + +- 你正在使用 TiDB Cloud Dedicated 集群。TiDB Cloud Serverless 集群不支持审计日志。 +- 你是组织的 `Organization Owner` 或 `Project Owner` 角色。否则,你将无法在 TiDB Cloud 控制台中看到数据库审计相关选项。有关更多信息,请参见[用户角色](/tidb-cloud/manage-user-access.md#用户角色)。 + +## 启用审计日志 + +TiDB Cloud 支持将 TiDB Cloud Dedicated 集群的审计日志记录到你的云存储服务中。在启用数据库审计日志之前,请在集群所在的云服务提供商上配置你的云存储服务。 + +> **注意:** +> +> 对于部署在 AWS 上的 TiDB 集群,你可以在启用数据库审计日志时选择将审计日志文件存储在 TiDB Cloud 中。目前,此功能仅供申请使用。要申请此功能,请点击 [TiDB Cloud 控制台](https://tidbcloud.com)右下角的 **?**,然后点击 **Request Support**。然后,在 **Description** 字段中填写"申请将审计日志文件存储在 TiDB Cloud 中",并点击 **Submit**。 + +### 为 AWS 启用审计日志 + +要为 AWS 启用审计日志,请执行以下步骤: + +#### 步骤 1. 创建 Amazon S3 存储桶 + +在你公司拥有的 AWS 账号中指定一个 Amazon S3 存储桶作为 TiDB Cloud 写入审计日志的目标位置。 + +> 注意: +> +> 不要在 AWS S3 存储桶上启用对象锁定。启用对象锁定将阻止 TiDB Cloud 将审计日志文件推送到 S3。 + +有关更多信息,请参见 AWS 用户指南中的[创建存储桶](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)。 + +#### 步骤 2. 配置 Amazon S3 访问权限 + +1. 获取你要启用审计日志的 TiDB 集群的 TiDB Cloud 账号 ID 和外部 ID。 + + 1. 在 TiDB Cloud 控制台中,导航到项目的 [**Clusters**](https://tidbcloud.com/project/clusters) 页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击 **Settings** > **DB Audit Logging**。 + 3. 在 **DB Audit Logging** 页面,点击右上角的 **Enable**。 + 4. 在 **Enable Database Audit Logging** 对话框中,找到 **AWS IAM Policy Settings** 部分,记录 **TiDB Cloud Account ID** 和 **TiDB Cloud External ID** 以供后续使用。 + +2. 在 AWS 管理控制台中,转到 **IAM** > **Access Management** > **Policies**,然后检查是否存在具有 `s3:PutObject` 只写权限的存储桶策略。 + + - 如果存在,记录匹配的存储桶策略以供后续使用。 + - 如果不存在,转到 **IAM** > **Access Management** > **Policies** > **Create Policy**,并根据以下策略模板定义存储桶策略。 + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:PutObject", + "Resource": "/*" + } + ] + } + ``` + + 在模板中,`` 是要写入审计日志文件的 S3 存储桶的 Amazon 资源名称(ARN)。你可以转到 S3 存储桶的 **Properties** 标签页,在 **Bucket Overview** 区域获取 ARN 值。在 `"Resource"` 字段中,你需要在 ARN 后添加 `/*`。例如,如果 ARN 是 `arn:aws:s3:::tidb-cloud-test`,你需要将 `"Resource"` 字段的值配置为 `"arn:aws:s3:::tidb-cloud-test/*"`。 + +3. 转到 **IAM** > **Access Management** > **Roles**,然后检查是否已存在一个信任实体对应于你之前记录的 TiDB Cloud 账号 ID 和外部 ID 的角色。 + + - 如果存在,记录匹配的角色以供后续使用。 + - 如果不存在,点击 **Create role**,选择 **Another AWS account** 作为信任实体类型,然后在 **Account ID** 字段中输入 TiDB Cloud 账号 ID 值。然后,选择 **Require External ID** 选项,并在 **External ID** 字段中输入 TiDB Cloud 外部 ID 值。 + +4. 在 **IAM** > **Access Management** > **Roles** 中,点击上一步中的角色名称进入 **Summary** 页面,然后执行以下步骤: + + 1. 在 **Permissions** 标签页下,检查是否已将具有 `s3:PutObject` 只写权限的记录策略附加到角色。如果没有,选择 **Attach Policies**,搜索所需策略,然后点击 **Attach Policy**。 + 2. 返回 **Summary** 页面并复制 **Role ARN** 值到剪贴板。 + +#### 步骤 3. 启用审计日志 + +在 TiDB Cloud 控制台中,返回获取 TiDB Cloud 账号 ID 和外部 ID 值的 **Enable Database Audit Logging** 对话框,然后执行以下步骤: + +1. 在 **Bucket URI** 字段中,输入要写入审计日志文件的 S3 存储桶的 URI。 +2. 在 **Bucket Region** 下拉列表中,选择存储桶所在的 AWS 区域。 +3. 在 **Role ARN** 字段中,填入你在[步骤 2. 配置 Amazon S3 访问权限](#步骤-2-配置-amazon-s3-访问权限)中复制的 Role ARN 值。 +4. 点击 **Test Connection** 验证 TiDB Cloud 是否可以访问和写入存储桶。 + + 如果成功,将显示 **The connection is successfully**。否则,请检查你的访问配置。 + +5. 点击 **Enable** 为集群启用审计日志。 + + TiDB Cloud 已准备好将指定集群的审计日志写入你的 Amazon S3 存储桶。 + +> **注意:** +> +> - 启用审计日志后,如果你对存储桶 URI、位置或 ARN 进行任何新的更改,必须再次点击 **Test Connection** 以验证 TiDB Cloud 是否可以连接到存储桶。然后,点击 **Enable** 应用更改。 +> - 要移除 TiDB Cloud 对 Amazon S3 的访问权限,只需在 AWS 管理控制台中删除授予此集群的信任策略即可。 + +### 为 Google Cloud 启用审计日志 + +要为 Google Cloud 启用审计日志,请执行以下步骤: + +#### 步骤 1. 创建 GCS 存储桶 + +在你公司拥有的 Google Cloud 账号中指定一个 Google Cloud Storage (GCS) 存储桶作为 TiDB Cloud 写入审计日志的目标位置。 + +有关更多信息,请参见 Google Cloud Storage 文档中的[创建存储桶](https://cloud.google.com/storage/docs/creating-buckets)。 + +#### 步骤 2. 配置 GCS 访问权限 + +1. 获取你要启用审计日志的 TiDB 集群的 Google Cloud 服务账号 ID。 + + 1. 在 TiDB Cloud 控制台中,导航到项目的 [**Clusters**](https://tidbcloud.com/project/clusters) 页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击 **Settings** > **DB Audit Logging**。 + 3. 在 **DB Audit Logging** 页面,点击右上角的 **Enable**。 + 4. 在 **Enable Database Audit Logging** 对话框中,找到 **Google Cloud Server Account ID** 部分,记录 **Service Account ID** 以供后续使用。 + +2. 在 Google Cloud 控制台中,转到 **IAM & Admin** > **Roles**,然后检查是否存在具有以下存储容器只写权限的角色。 + + - storage.objects.create + - storage.objects.delete + + 如果存在,为 TiDB 集群记录匹配的角色以供后续使用。如果不存在,转到 **IAM & Admin** > **Roles** > **CREATE ROLE** 为 TiDB 集群定义角色。 + +3. 转到 **Cloud Storage** > **Browser**,选择你想要 TiDB Cloud 访问的 GCS 存储桶,然后点击 **SHOW INFO PANEL**。 + + 面板将显示。 + +4. 在面板中,点击 **ADD PRINCIPAL**。 + + 将显示添加主体的对话框。 + +5. 在对话框中,执行以下步骤: + + 1. 在 **New Principals** 字段中,粘贴 TiDB 集群的 Google Cloud 服务账号 ID。 + 2. 在 **Role** 下拉列表中,选择目标 TiDB 集群的角色。 + 3. 点击 **SAVE**。 + +#### 步骤 3. 启用审计日志 + +在 TiDB Cloud 控制台中,返回获取 TiDB Cloud 账号 ID 的 **Enable Database Audit Logging** 对话框,然后执行以下步骤: + +1. 在 **Bucket URI** 字段中,输入你的完整 GCS 存储桶名称。 +2. 在 **Bucket Region** 字段中,选择存储桶所在的 GCS 区域。 +3. 点击 **Test Connection** 验证 TiDB Cloud 是否可以访问和写入存储桶。 + + 如果成功,将显示 **The connection is successfully**。否则,请检查你的访问配置。 + +4. 点击 **Enable** 为集群启用审计日志。 + + TiDB Cloud 已准备好将指定集群的审计日志写入你的 GCS 存储桶。 + +> **注意:** +> +> - 启用审计日志后,如果你对存储桶 URI 或位置进行任何新的更改,必须再次点击 **Test Connection** 以验证 TiDB Cloud 是否可以连接到存储桶。然后,点击 **Enable** 应用更改。 +> - 要移除 TiDB Cloud 对 GCS 存储桶的访问权限,请在 Google Cloud 控制台中删除授予此集群的信任策略。 + +### 为 Azure 启用审计日志 + +要为 Azure 启用审计日志,请执行以下步骤: + +#### 步骤 1. 创建 Azure 存储账号 + +在你组织的 Azure 订阅中创建一个 Azure 存储账号作为 TiDB Cloud 写入数据库审计日志的目标位置。 + +有关更多信息,请参见 Azure 文档中的[创建 Azure 存储账号](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal)。 + +#### 步骤 2. 配置 Azure Blob 存储访问权限 + +1. 在 [Azure 门户](https://portal.azure.com/)中,创建用于存储数据库审计日志的容器。 + + 1. 在 Azure 门户的左侧导航栏中,点击 **Storage Accounts**,然后点击用于存储数据库审计日志的存储账号。 + + > **提示:** + > + > 如果左侧导航栏被隐藏,点击左上角的菜单按钮切换其可见性。 + + 2. 在所选存储账号的导航栏中,点击 **Data storage > Containers**,然后点击 **+ Container** 打开 **New container** 窗格。 + + 3. 在 **New container** 窗格中,输入新容器的名称,设置匿名访问级别(推荐级别是 **Private**,表示无匿名访问),然后点击 **Create**。新容器将在几秒钟内创建并显示在容器列表中。 + +2. 获取目标容器的 URL。 + + 1. 在容器列表中,选择目标容器,点击容器的 **...**,然后选择 **Container properties**。 + 2. 在显示的属性页面上,复制 **URL** 值以供后续使用,然后返回容器列表。 + +3. 为目标容器生成 SAS 令牌。 + + 1. 在容器列表中,选择目标容器,点击容器的 **...**,然后选择 **Generate SAS**。 + 2. 在显示的 **Generate SAS** 窗格中,为 **Signing method** 选择 **Account key**。 + 3. 在 **Permissions** 下拉列表中,选择 **Read**、**Write** 和 **Create** 以允许写入审计日志文件。 + 4. 在 **Start** 和 **Expiry** 字段中,指定 SAS 令牌的有效期。 + + > **注意:** + > + > - 审计功能需要持续将审计日志写入存储账号,因此 SAS 令牌必须具有足够长的有效期。但是,较长的有效期会增加令牌泄露的风险。为了安全起见,建议每六到十二个月更换一次 SAS 令牌。 + > - 生成的 SAS 令牌无法撤销,因此你需要谨慎设置其有效期。 + > - 确保在令牌过期之前重新生成并更新 SAS 令牌,以确保审计日志的持续可用性。 + + 5. 对于 **Allowed protocols**,选择 **HTTPS only** 以确保安全访问。 + 6. 点击 **Generate SAS token and URL**,然后复制显示的 **Blob SAS token** 以供后续使用。 + +#### 步骤 3. 启用审计日志 + +1. 在 TiDB Cloud 控制台中,导航到项目的 [**Clusters**](https://tidbcloud.com/project/clusters) 页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击 **Settings** > **DB Audit Logging**。 +3. 在 **DB Audit Logging** 页面,点击右上角的 **Enable**。 +4. 在 **Enable Database Audit Logging** 对话框中,提供从[步骤 2. 配置 Azure Blob 访问权限](#步骤-2-配置-azure-blob-存储访问权限)获取的 blob URL 和 SAS 令牌: + + - 在 **Blob URL** 字段中,输入存储审计日志的容器的 URL。 + - 在 **SAS Token** 字段中,输入用于访问容器的 SAS 令牌。 + +5. 点击 **Test Connection** 验证 TiDB Cloud 是否可以访问和写入容器。 + + 如果成功,将显示 **The connection is successfully**。否则,请检查你的访问配置。 + +6. 点击 **Enable** 为集群启用审计日志。 + + TiDB Cloud 已准备好将指定集群的审计日志写入你的 Azure blob 容器。 + +> **注意:** +> +> 启用审计日志后,如果你对 **Blob URL** 或 **SAS Token** 字段进行新的更改,必须再次点击 **Test Connection** 以验证 TiDB Cloud 是否可以连接到容器。然后,点击 **Enable** 应用更改。 + +## 指定审计过滤规则 + +启用审计日志后,你必须指定审计过滤规则来控制要捕获并写入审计日志的用户访问事件。如果未指定过滤规则,TiDB Cloud 不会记录任何内容。 + +要为集群指定审计过滤规则,请执行以下步骤: + +1. 在 **DB Audit Logging** 页面的 **Log Filter Rules** 部分,点击 **Add Filter Rule** 添加审计过滤规则。 + + 你一次可以添加一个审计规则。每个规则指定一个用户表达式、数据库表达式、表表达式和访问类型。你可以添加多个审计规则以满足你的审计要求。 + +2. 在 **Log Filter Rules** 部分,点击 **>** 展开并查看你已添加的审计规则列表。 + +> **注意:** +> +> - 过滤规则是正则表达式且区分大小写。如果使用通配符规则 `.*`,将记录集群中所有用户、数据库或表事件。 +> - 由于审计日志会消耗集群资源,请谨慎指定过滤规则。为了最小化消耗,建议你指定过滤规则以尽可能将审计日志的范围限制在特定的数据库对象、用户和操作上。 + +## 查看审计日志 + +默认情况下,TiDB Cloud 将数据库审计日志文件存储在你的存储服务中,因此你需要从你的存储服务中读取审计日志信息。 + +> **注意:** +> +> 如果你已申请并选择将审计日志文件存储在 TiDB Cloud 中,你可以从 **Database Audit Logging** 页面的 **Audit Log Access** 部分下载它们。 + +TiDB Cloud 审计日志是可读的文本文件,文件名中包含集群 ID、Pod ID 和日志创建日期。 + +例如,`13796619446086334065/tidb-0/tidb-audit-2022-04-21T18-16-29.529.log`。在此示例中,`13796619446086334065` 表示集群 ID,`tidb-0` 表示 Pod ID。 + +## 禁用审计日志 + +如果你不再想审计集群,请转到集群页面,点击 **Settings** > **Audit Settings**,然后将右上角的审计设置切换为 **Off**。 + +> **注意:** +> +> 每当日志文件大小达到 10 MiB 时,日志文件将被推送到云存储桶。因此,在禁用审计日志后,大小小于 10 MiB 的日志文件不会自动推送到云存储桶。要在这种情况下获取日志文件,请联系 [PingCAP 支持](/tidb-cloud/tidb-cloud-support.md)。 + +## 审计日志字段 + +对于审计日志中的每个数据库事件记录,TiDB 提供以下字段: + +> **注意:** +> +> 在下表中,字段的最大长度为空表示该字段的数据类型具有明确定义的固定长度(例如,INTEGER 为 4 字节)。 + +| 列号 | 字段名 | TiDB 数据类型 | 最大长度 | 描述 | +|---|---|---|---|---| +| 1 | N/A | N/A | N/A | 保留供内部使用 | +| 2 | N/A | N/A | N/A | 保留供内部使用 | +| 3 | N/A | N/A | N/A | 保留供内部使用 | +| 4 | ID | INTEGER | | 唯一事件 ID | +| 5 | TIMESTAMP | TIMESTAMP | | 事件时间 | +| 6 | EVENT_CLASS | VARCHAR | 15 | 事件类型 | +| 7 | EVENT_SUBCLASS | VARCHAR | 15 | 事件子类型 | +| 8 | STATUS_CODE | INTEGER | | 语句的响应状态 | +| 9 | COST_TIME | FLOAT | | 语句消耗的时间 | +| 10 | HOST | VARCHAR | 16 | 服务器 IP | +| 11 | CLIENT_IP | VARCHAR | 16 | 客户端 IP | +| 12 | USER | VARCHAR | 17 | 登录用户名 | +| 13 | DATABASE | VARCHAR | 64 | 事件相关的数据库 | +| 14 | TABLES | VARCHAR | 64 | 事件相关的表名 | +| 15 | SQL_TEXT | VARCHAR | 64 KB | 掩码 SQL 语句 | +| 16 | ROWS | INTEGER | | 受影响的行数(`0` 表示没有行受影响) | + +根据 TiDB 设置的 EVENT_CLASS 字段值,审计日志中的数据库事件记录还包含以下附加字段: + +- 如果 EVENT_CLASS 值为 `CONNECTION`,数据库事件记录还包含以下字段: + + | 列号 | 字段名 | TiDB 数据类型 | 最大长度 | 描述 | + |---|---|---|---|---| + | 17 | CLIENT_PORT | INTEGER | | 客户端端口号 | + | 18 | CONNECTION_ID | INTEGER | | 连接 ID | + | 19 | CONNECTION_TYPE | VARCHAR | 12 | 通过 `socket` 或 `unix-socket` 连接 | + | 20 | SERVER_ID | INTEGER | | TiDB 服务器 ID | + | 21 | SERVER_PORT | INTEGER | | TiDB 服务器用于监听通过 MySQL 协议通信的客户端的端口 | + | 22 | SERVER_OS_LOGIN_USER | VARCHAR | 17 | TiDB 进程启动系统的用户名 | + | 23 | OS_VERSION | VARCHAR | N/A | TiDB 服务器所在操作系统的版本 | + | 24 | SSL_VERSION | VARCHAR | 6 | TiDB 当前的 SSL 版本 | + | 25 | PID | INTEGER | | TiDB 进程的 PID | + +- 如果 EVENT_CLASS 值为 `TABLE_ACCESS` 或 `GENERAL`,数据库事件记录还包含以下字段: + + | 列号 | 字段名 | TiDB 数据类型 | 最大长度 | 描述 | + |---|---|---|---|---| + | 17 | CONNECTION_ID | INTEGER | | 连接 ID | + | 18 | COMMAND | VARCHAR | 14 | MySQL 协议的命令类型 | + | 19 | SQL_STATEMENT | VARCHAR | 17 | SQL 语句类型 | + | 20 | PID | INTEGER | | TiDB 进程的 PID | diff --git a/tidb-cloud/tidb-cloud-billing-dm.md b/tidb-cloud/tidb-cloud-billing-dm.md new file mode 100644 index 000000000000..6727fba518ed --- /dev/null +++ b/tidb-cloud/tidb-cloud-billing-dm.md @@ -0,0 +1,58 @@ +--- +title: 数据迁移计费 +summary: 了解 TiDB Cloud 中数据迁移的计费情况。 +--- + +# 数据迁移计费 + +本文档描述了 TiDB Cloud 中数据迁移的计费情况。 + +## 数据迁移规格 + +TiDB Cloud 使用复制容量单位(RCU)来衡量数据迁移的容量。创建数据迁移任务时,您可以选择适当的规格。RCU 越高,迁移性能越好。这些数据迁移 RCU 将会产生费用。 + +下表列出了每个数据迁移规格可以迁移的相应性能和最大表数。 + +| 规格 | 全量数据迁移 | 增量数据迁移 | 最大表数 | +|---------------|---------------------|---------------------------|-----------------------| +| 2 RCU | 25 MiB/s | 10,000 行/秒 | 500 | +| 4 RCU | 35 MiB/s | 20,000 行/秒 | 10000 | +| 8 RCU | 40 MiB/s | 40,000 行/秒 | 30000 | +| 16 RCU | 45 MiB/s | 80,000 行/秒 | 60000 | + +有关数据迁移 RCU 的价格信息,请参阅[数据迁移成本](https://www.pingcap.com/tidb-dedicated-pricing-details/#dm-cost)。 + +> **注意:** +> +> - 如果要迁移的表数量超过最大表数,数据迁移任务可能仍会运行,但任务可能变得不稳定甚至失败。 +> - 本表中的所有性能值都是最大和最优值。假设上游和下游数据库没有性能、网络带宽或其他瓶颈。性能值仅供参考,在不同场景下可能会有所不同。 + +数据迁移任务以 MiB/s 衡量全量数据迁移性能。此单位表示数据迁移任务每秒迁移的数据量(以 MiB 为单位)。 + +数据迁移任务以行/秒衡量增量数据迁移性能。此单位表示每秒迁移到目标数据库的行数。例如,如果上游数据库在大约 1 秒内执行 10,000 行的 `INSERT`、`UPDATE` 或 `DELETE` 语句,相应规格的数据迁移任务可以在大约 1 秒内将这 10,000 行复制到下游。 + +## 价格 + +要了解 TiDB Cloud 支持的区域和每个数据迁移 RCU 的价格,请参阅[数据迁移成本](https://www.pingcap.com/tidb-cloud-pricing-details/#dm-cost)。 + +数据迁移任务与目标 TiDB 节点位于同一区域。 + +请注意,如果您使用 AWS PrivateLink 或 VPC 对等连接,且源数据库和 TiDB 节点不在同一区域或不在同一可用区(AZ),将产生两项额外的流量费用:跨区域和跨可用区流量费用。 + +- 如果源数据库和 TiDB 节点不在同一区域,当数据迁移任务从源数据库收集数据时,将产生跨区域流量费用。 + + ![跨区域流量费用](/media/tidb-cloud/dm-billing-cross-region-fees.png) + +- 如果源数据库和 TiDB 节点在同一区域但在不同的可用区,当数据迁移任务从源数据库收集数据时,将产生跨可用区流量费用。 + + ![跨可用区流量费用](/media/tidb-cloud/dm-billing-cross-az-fees.png) + +- 如果数据迁移任务和 TiDB 节点不在同一可用区,当数据迁移任务向目标 TiDB 节点写入数据时,将产生跨可用区流量费用。此外,如果数据迁移任务和 TiDB 节点与源数据库不在同一可用区(或区域),当数据迁移任务从源数据库收集数据时,将产生跨可用区(或跨区域)流量费用。 + + ![跨区域和跨可用区流量费用](/media/tidb-cloud/dm-billing-cross-region-and-az-fees.png) + +跨区域和跨可用区流量的价格与 TiDB Cloud 的价格相同。更多信息,请参阅 [TiDB Cloud 价格详情](https://www.pingcap.com/tidb-dedicated-pricing-details/)。 + +## 另请参阅 + +- [使用数据迁移从 MySQL 兼容数据库迁移](/tidb-cloud/migrate-from-mysql-using-data-migration.md) diff --git a/tidb-cloud/tidb-cloud-billing-recovery-group.md b/tidb-cloud/tidb-cloud-billing-recovery-group.md new file mode 100644 index 000000000000..8bb510ccbef2 --- /dev/null +++ b/tidb-cloud/tidb-cloud-billing-recovery-group.md @@ -0,0 +1,14 @@ +--- +title: 恢复组计费 +summary: 了解 TiDB Cloud 中恢复组的计费方式。 +--- + +# 恢复组计费 + +TiDB Cloud 根据恢复组主集群中 TiKV 节点的部署大小对恢复组进行计费。当你为集群[创建恢复组](/tidb-cloud/recovery-group-get-started.md)时,你可以选择恢复组的主集群。TiKV 配置越大,恢复组保护的成本就越高。 + +TiDB Cloud 还按每 GiB 的数据处理量收费。数据处理价格因数据是复制到另一个区域的次要集群还是同一区域内的次要集群而异。 + +## 定价 + +要了解 TiDB Cloud 恢复组支持的区域和定价,请参阅[恢复组成本](https://www.pingcap.com/tidb-cloud-pricing-details/#recovery-group-cost)。 diff --git a/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md b/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md new file mode 100644 index 000000000000..f7d68ceeb863 --- /dev/null +++ b/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md @@ -0,0 +1,39 @@ +--- +title: 变更数据捕获计费 +summary: 了解 TiDB Cloud 中变更数据捕获的计费方式。 +aliases: ['/tidbcloud/tidb-cloud-billing-tcu'] +--- + +# 变更数据捕获计费 + +## RCU 成本 + +TiDB Cloud 使用 TiCDC 复制容量单位(RCU)来衡量[变更数据捕获](/tidb-cloud/changefeed-overview.md)的容量。当你为集群[创建变更数据捕获](/tidb-cloud/changefeed-overview.md#create-a-changefeed)时,你可以选择适当的规格。RCU 越高,复制性能越好。你将为这些 TiCDC 变更数据捕获 RCU 付费。 + +### TiCDC RCU 数量 + +下表列出了变更数据捕获的规格和相应的复制性能: + +| 规格 | 最大复制性能 | +|---------------|---------------------------------| +| 2 RCU | 5,000 行/秒 | +| 4 RCU | 10,000 行/秒 | +| 8 RCU | 20,000 行/秒 | +| 16 RCU | 40,000 行/秒 | +| 24 RCU | 60,000 行/秒 | +| 32 RCU | 80,000 行/秒 | +| 40 RCU | 100,000 行/秒 | + +> **注意:** +> +> 上述性能数据仅供参考,在不同场景下可能会有所不同。强烈建议你在生产环境中使用变更数据捕获功能之前进行实际工作负载测试。如需进一步帮助,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +### 价格 + +要了解 TiDB Cloud 支持的区域和每个 TiCDC RCU 的价格,请参见[变更数据捕获成本](https://www.pingcap.com/tidb-cloud-pricing-details/#changefeed-cost)。 + +## 私有数据链路成本 + +如果你选择 **Private Link** 或 **Private Service Connect** 网络连接方式,将产生额外的**私有数据链路**成本。这些费用属于[数据传输成本](https://www.pingcap.com/tidb-dedicated-pricing-details/#data-transfer-cost)类别。 + +**私有数据链路**的价格为 **$0.01/GiB**,与 [AWS Interface Endpoint 定价](https://aws.amazon.com/privatelink/pricing/#Interface_Endpoint_pricing)的**数据处理**、[Google Cloud Private Service Connect 定价](https://cloud.google.com/vpc/pricing#psc-forwarding-rules)的**消费者数据处理**以及 [Azure Private Link 定价](https://azure.microsoft.com/en-us/pricing/details/private-link/)的**入站/出站数据处理**相同。 diff --git a/tidb-cloud/tidb-cloud-budget.md b/tidb-cloud/tidb-cloud-budget.md new file mode 100644 index 000000000000..3e1ee7726f9a --- /dev/null +++ b/tidb-cloud/tidb-cloud-budget.md @@ -0,0 +1,92 @@ +--- +title: 管理 TiDB Cloud 预算 +summary: 了解如何使用 TiDB Cloud 的预算功能来监控成本。 +--- + +# 管理 TiDB Cloud 预算 + +在 TiDB Cloud 中,您可以使用预算功能来监控成本并控制支出。 + +当您的月度实际成本超过指定预算的百分比阈值时,系统会向您组织的所有者和计费管理员发送警报邮件。这些通知可以帮助您及时了解情况并采取积极措施来管理支出,使支出与预算保持一致。 + +TiDB Cloud 提供两种类型的预算来帮助您跟踪支出: + +- **Serverless 支出限额**预算:对于每个 TiDB Cloud Serverless 可扩展集群,TiDB Cloud 会自动创建一个 **Serverless 支出限额**预算。此预算帮助您跟踪实际成本是否超过该集群配置的[支出限额](/tidb-cloud/manage-serverless-spend-limit.md)。它包含三个不可编辑的阈值规则:预算的 75%、90% 和 100%。 + +- **自定义**预算:您可以创建自定义预算来跟踪整个组织或特定项目的实际成本。对于每个预算,您可以指定预算范围、设置目标支出金额和配置警报阈值。创建自定义预算后,您可以将月度实际成本与计划成本进行比较,以确保支出不超出预算。 + +## 前提条件 + +要查看、创建、编辑或删除组织或项目的预算,您必须具有组织的`组织所有者`或`组织计费管理员`角色。 + +## 查看预算信息 + +要查看组织的预算页面,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**计费**。 +3. 在**计费**页面上,点击**预算**选项卡。 + +对于每个预算,您可以查看其名称、类型、状态、已使用金额、预算金额、周期和范围。 + +## 创建自定义预算 + +要创建自定义预算以监控组织或特定项目的支出,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**计费**。 +3. 在**计费**页面上,点击**预算**选项卡,然后点击**创建自定义预算**。您最多可以创建五个自定义预算。 +4. 提供预算基本设置。 + + - **名称**:输入预算的名称。 + - **周期**:选择跟踪成本的时间范围。目前,您只能选择**每月**,从每月第一天开始,并在每月初重置。TiDB Cloud 会在此时间范围内跟踪您的实际支出,并与您的预算金额(计划支出)进行比较。 + - **预算范围**:根据需要将范围应用于所有项目(即整个 TiDB Cloud 组织)或特定项目。 + +5. 设置预算金额。 + + - **预算金额**:输入所选周期的计划支出金额。 + - **应用信用额度**:选择是否将信用额度应用于运行总成本。信用额度用于减少您的 TiDB Cloud 使用成本。启用此选项后,预算将跟踪运行总成本减去信用额度。 + - **应用折扣**:选择是否将折扣应用于运行总成本。折扣是 TiDB Cloud 服务常规价格的降价。启用此选项后,预算将跟踪运行总成本减去折扣。 + +6. 为预算配置警报阈值。如果您在所选周期内的实际支出超过指定阈值,TiDB Cloud 会向您组织的所有者和计费管理员发送预算通知邮件。 + + - 默认情况下,TiDB Cloud 提供三个警报阈值:预算金额的 75%、90% 和 100%。您可以根据需要修改这些百分比。 + - 要添加新的警报阈值,请点击**添加警报阈值**。 + - 要删除阈值,请点击阈值旁边的删除图标。 + +7. 点击**创建**。 + +## 编辑自定义预算 + +> **注意:** +> +> **Serverless 支出限额**预算无法编辑,因为它是由 TiDB Cloud 自动创建的,用于帮助您跟踪 TiDB Cloud Serverless 可扩展集群的成本是否超过其[支出限额](/tidb-cloud/manage-serverless-spend-limit.md)。 + +要编辑自定义预算,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**计费**。 +3. 在**计费**页面上,点击**预算**选项卡。 +4. 找到目标预算所在的行,点击该行中的 **...**,然后点击**编辑**。 +5. 根据需要编辑预算名称、预算范围、预算金额和警报阈值。 + + > **注意:** + > + > 不支持编辑预算周期以及是否应用信用额度和折扣。 + +6. 点击**更新**。 + +## 删除自定义预算 + +> **注意:** +> +> - 自定义预算删除后,您将不再收到与之相关的任何警报邮件。 +> - **Serverless 支出限额**预算无法删除,因为它是由 TiDB Cloud 自动创建的,用于帮助您跟踪 TiDB Cloud Serverless 可扩展集群的成本是否超过其[支出限额](/tidb-cloud/manage-serverless-spend-limit.md)。 + +要删除自定义预算,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**计费**。 +3. 在**计费**页面上,点击**预算**选项卡。 +4. 找到目标预算所在的行,点击该行中的 **...**,然后点击**删除**。 +5. 确认删除。 diff --git a/tidb-cloud/tidb-cloud-clinic.md b/tidb-cloud/tidb-cloud-clinic.md new file mode 100644 index 000000000000..fd6f71a4bbb3 --- /dev/null +++ b/tidb-cloud/tidb-cloud-clinic.md @@ -0,0 +1,123 @@ +--- +title: TiDB Cloud 诊所 +summary: 了解如何使用 TiDB Cloud 诊所进行高级监控和诊断。 +--- + +# TiDB Cloud 诊所 + +TiDB Cloud 诊所在 TiDB Cloud 上提供高级监控和诊断功能,旨在帮助您通过详细分析和可操作的见解,快速识别性能问题、优化数据库并提升整体性能。 + +![tidb-cloud-clinic](/media/tidb-cloud/tidb-cloud-clinic.png) + +> **注意:** +> +> 目前,TiDB Cloud 诊所仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +## 前提条件 + +TiDB Cloud 诊所仅适用于订阅了**企业版**或**高级版**支持计划的组织。 + +## 查看集群页面 + +要查看**集群**页面,请按照以下步骤操作: + +1. 登录 [TiDB Cloud 诊所控制台](https://clinic.pingcap.com/),选择**使用 TiDB 账号继续**进入 TiDB Cloud 登录页面。 + +2. 从组织列表中选择目标组织。将显示所选项目中的集群。 + +3. 点击目标集群的名称。将显示集群概览页面,您可以在此查看集群的详细信息,包括: + + - 高级指标 + - 慢查询排行(仅支持 TiDB 版本为 v8.1.1 或更高版本,v7.5.4 或更高版本的集群) + - TopSQL(仅支持 TiDB 版本为 v8.1.1 或更高版本,v7.5.4 或更高版本的集群) + - 基准测试报告 + +## 监控高级指标 + +TiDB Cloud 诊所使用 Grafana 为 TiDB 集群提供全面的指标集。高级指标的保留策略为 90 天。 + +要查看指标仪表板,请按照以下步骤操作: + +1. 在 [TiDB Cloud 诊所控制台](https://clinic.pingcap.com/)中,导航到集群的**集群**页面。 + +2. 点击**指标**。 + +3. 点击您想要查看的仪表板名称。将显示该仪表板。 + +仪表板及其内容可能会发生变化。目前提供以下仪表板: + +- Backup & Import +- DM-Professional +- DM-Standard +- Lightning +- Performance-Overview +- TiCDC-Summary +- TiDB +- TiDB-Resource-Control +- TiFlash-Summary +- TiKV-Details +- User-Node-Info + +## 分析慢查询排行 + +默认情况下,执行时间超过 300 毫秒的 SQL 查询被视为慢查询。 + +在 TiDB Cloud 控制台的默认[**慢查询**](/tidb-cloud/tune-performance.md#slow-query)页面上,特别是在具有大量慢查询的集群中,识别影响性能的查询可能比较困难。TiDB Cloud 诊所中的**慢查询排行**功能基于慢查询日志提供聚合分析。通过此功能,您可以轻松定位存在性能问题的查询,将整体性能调优时间至少减少一半。 + +慢查询排行按 SQL 指纹聚合显示前 10 个查询,并按以下维度排序: + +- 总延迟 +- 最大延迟 +- 平均延迟 +- 总内存 +- 最大内存 +- 平均内存 +- 总次数 + +要查看集群中的慢查询,请按照以下步骤操作: + +1. 在 [TiDB Cloud 诊所控制台](https://clinic.pingcap.com/)中,导航到集群的**集群**页面。 + +2. 点击**慢查询**。 + +3. 慢查询排行将以表格形式显示。您可以按不同列进行排序。 + +4. (可选)点击列表中的任何慢查询以查看其详细执行信息。 + +5. (可选)按时间范围、数据库或语句类型筛选慢查询。 + +慢查询的保留策略为 7 天。 + +更多信息,请参阅 [TiDB Dashboard 中的慢查询](https://docs.pingcap.com/tidb/stable/dashboard-slow-query)。 + +## 监控 TopSQL + +TiDB Cloud 诊所提供 TopSQL 信息,使您能够实时监控和可视化探索数据库中每个 SQL 语句的 CPU 开销。这有助于您优化和解决数据库性能问题。 + +要查看 TopSQL,请按照以下步骤操作: + +1. 在 [TiDB Cloud 诊所控制台](https://clinic.pingcap.com/)中,导航到集群的**集群**页面。 + +2. 点击 **TopSQL**。 + +3. 选择特定的 TiDB 或 TiKV 实例以观察其负载。您可以使用时间选择器或在图表中选择时间范围来细化分析。 + +4. 分析 TopSQL 显示的图表和表格。 + +更多信息,请参阅 [TiDB Dashboard 中的 TopSQL](https://docs.pingcap.com/tidb/stable/top-sql)。 + +## 生成基准测试报告 + +**基准测试报告**功能帮助您在性能测试期间识别 TiDB 集群中的性能问题。完成压力测试后,您可以生成基准测试报告来分析集群的性能。该报告突出显示已识别的瓶颈并提供优化建议。应用这些建议后,您可以运行另一轮压力测试并生成新的基准测试报告以比较性能改进。 + +要生成基准测试报告,请按照以下步骤操作: + +1. 在 [TiDB Cloud 诊所控制台](https://clinic.pingcap.com/)中,导航到集群的**集群**页面。 + +2. 点击**基准测试报告**。 + +3. 选择要在基准测试报告中分析的时间范围。 + +4. 点击**创建报告**以生成基准测试报告。 + +5. 等待报告生成完成。报告准备就绪后,点击**查看**以打开报告。 diff --git a/tidb-cloud/tidb-cloud-connect-aws-dms.md b/tidb-cloud/tidb-cloud-connect-aws-dms.md new file mode 100644 index 000000000000..7c9115297724 --- /dev/null +++ b/tidb-cloud/tidb-cloud-connect-aws-dms.md @@ -0,0 +1,140 @@ +--- +title: 将 AWS DMS 连接到 TiDB Cloud 集群 +summary: 了解如何使用 AWS Database Migration Service (AWS DMS) 从 TiDB Cloud 迁移数据或将数据迁移到 TiDB Cloud。 +--- + +# 将 AWS DMS 连接到 TiDB Cloud 集群 + +[AWS Database Migration Service (AWS DMS)](https://aws.amazon.com/dms/) 是一项云服务,可用于迁移关系数据库、数据仓库、NoSQL 数据库和其他类型的数据存储。你可以使用 AWS DMS 从 TiDB Cloud 集群迁移数据或将数据迁移到 TiDB Cloud 集群。本文档描述如何将 AWS DMS 连接到 TiDB Cloud 集群。 + +## 前提条件 + +### 具有足够访问权限的 AWS 账户 + +你需要拥有具有足够权限来管理 DMS 相关资源的 AWS 账户。如果没有,请参考以下 AWS 文档: + +- [注册 AWS 账户](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_GettingStarted.SettingUp.html#sign-up-for-aws) +- [AWS Database Migration Service 的身份和访问管理](https://docs.aws.amazon.com/dms/latest/userguide/security-iam.html) + +### TiDB Cloud 账户和 TiDB 集群 + +你需要拥有 TiDB Cloud 账户和 TiDB Cloud Serverless 或 TiDB Cloud Dedicated 集群。如果没有,请参考以下文档创建: + +- [创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md) +- [创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md) + +## 配置网络 + +在创建 DMS 资源之前,你需要正确配置网络以确保 DMS 可以与 TiDB Cloud 集群通信。如果你不熟悉 AWS,请联系 AWS 支持。以下提供了几种可能的配置供参考。 + + + +
+ +对于 TiDB Cloud Serverless,客户端可以通过公共端点或私有端点连接到集群。 + +- 要[通过公共端点连接到 TiDB Cloud Serverless 集群](/tidb-cloud/connect-via-standard-connection-serverless.md),请执行以下操作之一以确保 DMS 复制实例可以访问互联网。 + + - 在公共子网中部署复制实例并启用**公共可访问**。更多信息,请参见[互联网访问配置](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html#vpc-igw-internet-access)。 + + - 在私有子网中部署复制实例并将私有子网中的流量路由到公共子网。在这种情况下,你需要至少三个子网,两个私有子网和一个公共子网。这两个私有子网形成一个复制实例所在的子网组。然后,你需要在公共子网中创建一个 NAT 网关,并将两个私有子网的流量路由到 NAT 网关。更多信息,请参见[从私有子网访问互联网](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-scenarios.html#public-nat-internet-access)。 + +- 要通过私有端点连接到 TiDB Cloud Serverless 集群,请先[设置私有端点](/tidb-cloud/set-up-private-endpoint-connections-serverless.md),然后在私有子网中部署复制实例。 + +
+ +
+ +对于 TiDB Cloud Dedicated,客户端可以通过公共端点、私有端点或 VPC 对等连接连接到集群。 + +- 要[通过公共端点连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/connect-via-standard-connection.md),请执行以下操作之一以确保 DMS 复制实例可以访问互联网。此外,你需要将复制实例或 NAT 网关的公共 IP 地址添加到集群的 [IP 访问列表](/tidb-cloud/configure-ip-access-list.md)中。 + + - 在公共子网中部署复制实例并启用**公共可访问**。更多信息,请参见[互联网访问配置](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html#vpc-igw-internet-access)。 + + - 在私有子网中部署复制实例并将私有子网中的流量路由到公共子网。在这种情况下,你需要至少三个子网,两个私有子网和一个公共子网。这两个私有子网形成一个复制实例所在的子网组。然后,你需要在公共子网中创建一个 NAT 网关,并将两个私有子网的流量路由到 NAT 网关。更多信息,请参见[从私有子网访问互联网](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-scenarios.html#public-nat-internet-access)。 + +- 要通过私有端点连接到 TiDB Cloud Dedicated 集群,请先[设置私有端点](/tidb-cloud/set-up-private-endpoint-connections.md),然后在私有子网中部署复制实例。 + +- 要通过 VPC 对等连接连接到 TiDB Cloud Dedicated 集群,请先[设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md),然后在私有子网中部署复制实例。 + +
+
+ +## 创建 AWS DMS 复制实例 + +1. 在 AWS DMS 控制台中,转到[**复制实例**](https://console.aws.amazon.com/dms/v2/home#replicationInstances)页面并切换到相应的区域。建议使用与 TiDB Cloud 相同的区域。 + + ![创建复制实例](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-connect-replication-instances.png) + +2. 点击**创建复制实例**。 + +3. 填写实例名称、ARN 和描述。 + +4. 在**实例配置**部分,配置实例: + - **实例类**:选择适当的实例类。更多信息,请参见[选择复制实例类型](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_ReplicationInstance.Types.html)。 + - **引擎版本**:保持默认配置。 + - **高可用性**:根据业务需求选择**多可用区**或**单可用区**。 + +5. 在**分配存储 (GiB)** 字段中配置存储。 + +6. 配置连接和安全。你可以参考[前一节](#配置网络)进行网络配置。 + + - **网络类型 - 新**:选择 **IPv4**。 + - **虚拟私有云 (VPC) for IPv4**:选择你需要的 VPC。 + - **复制子网组**:为你的复制实例选择一个子网组。 + - **公共可访问**:根据你的网络配置进行设置。 + + ![连接和安全](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-connect-connectivity-security.png) + +7. 根据需要配置**高级设置**、**维护**和**标签**部分,然后点击**创建复制实例**完成实例创建。 + +> **注意:** +> +> AWS DMS 还支持无服务器复制。详细步骤请参见[创建无服务器复制](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Serverless.Components.html#CHAP_Serverless.create)。与复制实例不同,AWS DMS 无服务器复制不提供**公共可访问**选项。 + +## 创建 TiDB Cloud DMS 端点 + +对于连接性,将 TiDB Cloud 集群用作源或目标的步骤类似,但 DMS 对源和目标的数据库设置要求有所不同。更多信息,请参见[使用 MySQL 作为源](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MySQL.html)或[使用 MySQL 作为目标](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Target.MySQL.html)。将 TiDB Cloud 集群用作源时,你只能**迁移现有数据**,因为 TiDB 不支持 MySQL binlog。 + +1. 在 AWS DMS 控制台中,转到[**端点**](https://console.aws.amazon.com/dms/v2/home#endpointList)页面并切换到相应的区域。 + + ![创建端点](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-connect-create-endpoint.png) + +2. 点击**创建端点**以创建目标数据库端点。 + +3. 在**端点类型**部分,选择**源端点**或**目标端点**。 + +4. 在**端点配置**部分,填写**端点标识符**和 ARN 字段。然后,选择 **MySQL** 作为**源引擎**或**目标引擎**。 + +5. 对于**访问端点数据库**字段,选中**手动提供访问信息**复选框,并按如下方式填写集群信息: + + + +
+ + - **服务器名称**:TiDB Cloud Serverless 集群的 `HOST`。 + - **端口**:TiDB Cloud Serverless 集群的 `PORT`。 + - **用户名**:用于迁移的 TiDB Cloud Serverless 集群用户。确保它满足 DMS 要求。 + - **密码**:TiDB Cloud Serverless 集群用户的密码。 + - **安全套接字层 (SSL) 模式**:如果通过公共端点连接,强烈建议将模式设置为 **verify-full** 以确保传输安全。如果通过私有端点连接,可以将模式设置为 **none**。 + - (可选)**CA 证书**:使用 [ISRG Root X1 证书](https://letsencrypt.org/certs/isrgrootx1.pem)。更多信息,请参见[到 TiDB Cloud Serverless 的 TLS 连接](/tidb-cloud/secure-connections-to-serverless-clusters.md)。 + +
+ +
+ + - **服务器名称**:TiDB Cloud Dedicated 集群的 `HOST`。 + - **端口**:TiDB Cloud Dedicated 集群的 `PORT`。 + - **用户名**:用于迁移的 TiDB Cloud Dedicated 集群用户。确保它满足 DMS 要求。 + - **密码**:TiDB Cloud Dedicated 集群用户的密码。 + - **安全套接字层 (SSL) 模式**:如果通过公共端点连接,强烈建议将模式设置为 **verify-full** 以确保传输安全。如果通过私有端点连接,可以将其设置为 **none**。 + - (可选)**CA 证书**:根据[到 TiDB Cloud Dedicated 的 TLS 连接](/tidb-cloud/tidb-cloud-tls-connect-to-dedicated.md)获取 CA 证书。 + +
+
+ + ![手动提供访问信息](/media/tidb-cloud/aws-dms-tidb-cloud/aws-dms-connect-configure-endpoint.png) + +6. 如果要将端点创建为**目标端点**,展开**端点设置**部分,选中**使用端点连接属性**复选框,然后将**额外连接属性**设置为 `Initstmt=SET FOREIGN_KEY_CHECKS=0;`。 + +7. 根据需要配置 **KMS 密钥**和**标签**部分。点击**创建端点**完成实例创建。 diff --git a/tidb-cloud/tidb-cloud-console-auditing.md b/tidb-cloud/tidb-cloud-console-auditing.md new file mode 100644 index 000000000000..39164beb94b8 --- /dev/null +++ b/tidb-cloud/tidb-cloud-console-auditing.md @@ -0,0 +1,184 @@ +--- +title: 控制台审计日志 +summary: 了解 TiDB Cloud 控制台的审计日志功能。 +--- + +# 控制台审计日志 + +TiDB Cloud 提供控制台审计日志功能,帮助您跟踪用户在 [TiDB Cloud 控制台](https://tidbcloud.com)上的各种行为和操作。例如,您可以跟踪邀请用户加入组织和创建集群等操作。 + +## 前提条件 + +- 您必须在 TiDB Cloud 中担任组织的 `Organization Owner` 或 `Organization Console Audit Manager` 角色。否则,您将无法在 TiDB Cloud 控制台中看到控制台审计日志相关选项。 +- 您只能为您的组织启用和禁用控制台审计日志。您只能跟踪组织中用户的操作。 +- 启用控制台审计日志后,将审计 TiDB Cloud 控制台的所有事件类型,您无法指定仅审计其中的某些事件。 + +## 启用控制台审计日志 + +控制台审计日志功能默认是禁用的。要启用它,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**控制台审计日志**。 +3. 点击右上角的**设置**,启用控制台审计日志,然后点击**更新**。 + +## 禁用控制台审计日志 + +要禁用控制台审计日志,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**控制台审计日志**。 +3. 点击右上角的**设置**,禁用控制台审计日志,然后点击**更新**。 + +## 查看控制台审计日志 + +您只能查看组织的控制台审计日志。 + +> **注意:** +> +> - 如果您的组织首次启用控制台审计日志,控制台审计日志将为空。执行任何被审计的事件后,您将看到相应的日志。 +> - 如果控制台审计日志被禁用超过 90 天,您将无法看到任何日志。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**控制台审计日志**。 +3. 要获取特定部分的审计日志,您可以过滤事件类型、操作状态和时间范围。 +4. (可选)要过滤更多字段,点击**高级过滤器**,添加更多过滤条件,然后点击**应用**。 +5. 点击日志行以在右侧窗格中查看其详细信息。 + +## 导出控制台审计日志 + +要导出组织的控制台审计日志,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**控制台审计日志**。 +3. (可选)如果您需要导出特定部分的控制台审计日志,可以通过各种条件进行过滤。否则,跳过此步骤。 +4. 点击**下载日志**,并选择所需的导出格式(JSON 或 CSV)。 + +## 控制台审计日志存储策略 + +控制台审计日志的存储时间为 90 天,之后日志将自动清理。 + +> **注意:** +> +> - 您无法在 TiDB Cloud 中指定控制台审计日志的存储位置。 +> - 您无法手动删除审计日志。 + +## 控制台审计事件类型 + +控制台审计日志通过事件类型记录 TiDB Cloud 控制台上的各种用户活动。 + +> **注意:** +> +> 目前,TiDB Cloud 控制台上的大多数事件类型都可以被审计,您可以在下表中找到它们。对于尚未覆盖的其余事件类型,TiDB Cloud 将持续努力将它们也包含在内。 + +| 控制台审计事件类型 | 描述 | +|--------------------------------|----------------------------------------------------------------------------------| +| CreateOrganization | 创建组织 | +| LoginOrganization | 登录组织 | +| SwitchOrganization | 从当前组织切换到另一个组织 | +| LogoutOrganization | 从组织注销 | +| InviteUserToOrganization | 邀请用户加入组织 | +| DeleteInvitationToOrganization | 删除用户加入组织的邀请 | +| ResendInvitationToOrganization | 重新发送用户加入组织的邀请 | +| ConfirmJoinOrganization | 被邀请的用户确认加入组织 | +| DeleteUserFromOrganization | 从组织中删除已加入的用户 | +| UpdateUserRoleInOrganization | 更新用户在组织中的角色 | +| CreateAPIKey | 创建 API 密钥 | +| EditAPIKey | 编辑 API 密钥 | +| DeleteAPIKey | 删除 API 密钥 | +| UpdateTimezone | 更新组织的时区 | +| ShowBill | 显示组织账单 | +| DownloadBill | 下载组织账单 | +| ShowCredits | 显示组织积分 | +| AddPaymentCard | 添加支付卡 | +| UpdatePaymentCard | 更新支付卡 | +| DeletePaymentCard | 删除支付卡 | +| SetDefaultPaymentCard | 设置默认支付卡 | +| EditBillingProfile | 编辑账单资料信息 | +| ContractAction | 组织合同相关活动 | +| EnableConsoleAuditLog | 启用控制台审计日志 | +| ShowConsoleAuditLog | 显示控制台审计日志 | +| InviteUserToProject | 邀请用户加入项目 | +| DeleteInvitationToProject | 删除用户加入项目的邀请 | +| ResendInvitationToProject | 重新发送用户加入项目的邀请 | +| ConfirmJoinProject | 被邀请的用户确认加入项目 | +| DeleteUserFromProject | 从项目中删除已加入的用户 | +| CreateProject | 创建项目 | +| CreateProjectCIDR | 创建新的项目 CIDR | +| CreateAWSVPCPeering | 创建 AWS VPC 对等连接 | +| DeleteAWSVPCPeering | 删除 AWS VPC 对等连接 | +| CreateGCPVPCPeering | 创建 Google Cloud VPC 对等连接 | +| DeleteGCPVPCPeering | 删除 Google Cloud VPC 对等连接 | +| CreatePrivateEndpointService | 创建私有端点服务 | +| DeletePrivateEndpointService | 删除私有端点服务 | +| CreateAWSPrivateEndPoint | 创建 AWS 私有端点 | +| DeleteAWSPrivateEndPoint | 删除 AWS 私有端点 | +| SubscribeAlerts | 订阅警报 | +| UnsubscribeAlerts | 取消订阅警报 | +| CreateDatadogIntegration | 创建 Datadog 集成 | +| DeleteDatadogIntegration | 删除 Datadog 集成 | +| CreateVercelIntegration | 创建 Vercel 集成 | +| DeleteVercelIntegration | 删除 Vercel 集成 | +| CreatePrometheusIntegration | 创建 Prometheus 集成 | +| DeletePrometheusIntegration | 删除 Prometheus 集成 | +| CreateCluster | 创建集群 | +| DeleteCluster | 删除集群 | +| PauseCluster | 暂停集群 | +| ResumeCluster | 恢复集群 | +| ScaleCluster | 扩展集群 | +| DownloadTiDBClusterCA | 下载 CA 证书 | +| OpenWebSQLConsole | 通过 Web SQL 连接到 TiDB 集群 | +| SetRootPassword | 设置 TiDB 集群的 root 密码 | +| UpdateIPAccessList | 更新 TiDB 集群的 IP 访问列表 | +| SetAutoBackup | 设置 TiDB 集群的自动备份机制 | +| DoManualBackup | 执行 TiDB 集群的手动备份 | +| DeleteBackupTask | 删除备份任务 | +| DeleteBackup | 删除备份文件 | +| RestoreFromBackup | 基于备份文件恢复到 TiDB 集群 | +| RestoreFromTrash | 基于回收站中的备份文件恢复到 TiDB 集群 | +| ImportDataFromAWS | 从 AWS 导入数据 | +| ImportDataFromGCP | 从 Google Cloud 导入数据 | +| ImportDataFromLocal | 从本地磁盘导入数据 | +| CreateMigrationJob | 创建迁移任务 | +| SuspendMigrationJob | 暂停迁移任务 | +| ResumeMigrationJob | 恢复迁移任务 | +| DeleteMigrationJob | 删除迁移任务 | +| ShowDiagnose | 显示诊断信息 | +| DBAuditLogAction | 设置数据库审计日志活动 | +| AddDBAuditFilter | 添加数据库审计日志过滤器 | +| DeleteDBAuditFilter | 删除数据库审计日志过滤器 | +| EditProject | 编辑项目信息 | +| DeleteProject | 删除项目 | +| BindSupportPlan | 绑定支持计划 | +| CancelSupportPlan | 取消支持计划 | +| UpdateOrganizationName | 更新组织名称 | +| SetSpendLimit | 编辑 TiDB Cloud Serverless 可扩展集群的支出限制 | +| UpdateMaintenanceWindow | 修改维护窗口开始时间 | +| DeferMaintenanceTask | 推迟维护任务 | +| CreateBranch | 创建 TiDB Cloud Serverless 分支 | +| DeleteBranch | 删除 TiDB Cloud Serverless 分支 | +| SetBranchRootPassword | 为 TiDB Cloud Serverless 分支设置 root 密码 | +| ConnectBranchGitHub | 将集群与 GitHub 仓库连接以启用分支集成 | +| DisconnectBranchGitHub | 断开集群与 GitHub 仓库的连接以禁用分支集成 | + +## 控制台审计日志字段 + +为帮助您跟踪用户活动,TiDB Cloud 为每个控制台审计日志提供以下字段: + +| 字段名称 | 数据类型 | 描述 | +|---|---|---| +| type | string | 事件类型 | +| ends_at | timestamp | 事件时间 | +| operator_type | enum | 操作者类型:`user` 或 `api_key` | +| operator_id | uint64 | 操作者 ID | +| operator_name | string | 操作者名称 | +| operator_ip | string | 操作者的 IP 地址 | +| operator_login_method | enum | 操作者的登录方法:`google`、`github`、`microsoft`、`email` 或 `api_key` | +| org_id | uint64 | 事件所属的组织 ID | +| org_name | string | 事件所属的组织名称 | +| project_id | uint64 | 事件所属的项目 ID | +| project_name | string | 事件所属的项目名称 | +| cluster_id | uint64 | 事件所属的集群 ID | +| cluster_name | string | 事件所属的集群名称 | +| trace_id | string | 操作者发起请求的跟踪 ID。此字段目前为空,将在未来版本中提供。 | +| result | enum | 事件结果:`success` 或 `failure` | +| details | json | 事件的详细描述 | diff --git a/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md b/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md new file mode 100644 index 000000000000..80909ae42e01 --- /dev/null +++ b/tidb-cloud/tidb-cloud-dm-precheck-and-troubleshooting.md @@ -0,0 +1,129 @@ +--- +title: 数据迁移的预检查错误、迁移错误和告警 +summary: 了解如何解决使用数据迁移时的预检查错误、迁移错误和告警。 +--- + +# 数据迁移的预检查错误、迁移错误和告警 + +本文档介绍如何在[使用数据迁移功能迁移数据](/tidb-cloud/migrate-from-mysql-using-data-migration.md)时解决预检查错误、排查迁移错误和订阅告警。 + +## 预检查错误和解决方案 + +本节介绍数据迁移过程中的预检查错误和相应的解决方案。这些错误会在[使用数据迁移功能迁移数据](/tidb-cloud/migrate-from-mysql-using-data-migration.md)时的**预检查**页面上显示。 + +解决方案因上游数据库而异。 + +### 错误消息:检查 mysql server_id 是否大于 0 + +- Amazon Aurora MySQL 或 Amazon RDS:默认已配置 `server_id`。你不需要配置它。确保使用 Amazon Aurora MySQL 写入实例以支持全量和增量数据迁移。 +- MySQL:要为 MySQL 配置 `server_id`,请参见 [Setting the Replication Source Configuration](https://dev.mysql.com/doc/refman/8.0/en/replication-howto-masterbaseconfig.html)。 + +### 错误消息:检查 mysql binlog 是否已启用 + +- Amazon Aurora MySQL:参见 [How do I turn on binary logging for my Amazon Aurora MySQL-Compatible cluster](https://aws.amazon.com/premiumsupport/knowledge-center/enable-binary-logging-aurora/?nc1=h_ls)。确保使用 Amazon Aurora MySQL 写入实例以支持全量和增量数据迁移。 +- Amazon RDS:参见 [Configuring MySQL binary logging](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.BinaryFormat.html)。 +- Google Cloud SQL for MySQL:Google 通过 MySQL 主数据库的时间点恢复功能启用二进制日志记录。参见 [Enable point-in-time recovery](https://cloud.google.com/sql/docs/mysql/backup-recovery/pitr#enablingpitr)。 +- MySQL:参见 [Setting the Replication Source Configuration](https://dev.mysql.com/doc/refman/8.0/en/replication-howto-masterbaseconfig.html)。 + +### 错误消息:检查 mysql binlog_format 是否为 ROW + +- Amazon Aurora MySQL:参见 [How do I turn on binary logging for my Amazon Aurora MySQL-Compatible cluster](https://aws.amazon.com/premiumsupport/knowledge-center/enable-binary-logging-aurora/?nc1=h_ls)。确保使用 Amazon Aurora MySQL 写入实例以支持全量和增量数据迁移。 +- Amazon RDS:参见 [Configuring MySQL binary logging](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.BinaryFormat.html)。 +- MySQL:执行 `set global binlog_format=ROW;`。参见 [Setting The Binary Log Format](https://dev.mysql.com/doc/refman/8.0/en/binary-log-setting.html)。 + +### 错误消息:检查 mysql binlog_row_image 是否为 FULL + +- Amazon Aurora MySQL:`binlog_row_image` 不可配置。此预检查项不会失败。确保使用 Amazon Aurora MySQL 写入实例以支持全量和增量数据迁移。 +- Amazon RDS:过程与设置 `binlog_format` 参数类似。唯一的区别是你需要更改的参数是 `binlog_row_image` 而不是 `binlog_format`。参见 [Configuring MySQL binary logging](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.BinaryFormat.html)。 +- MySQL:执行 `set global binlog_row_image = FULL;`。参见 [Binary Logging Options and Variables](https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html#sysvar_binlog_row_image)。 + +### 错误消息:检查要迁移的数据库是否在 binlog_do_db/binlog_ignore_db 中 + +确保已在上游数据库中启用 binlog。参见[检查 mysql binlog 是否已启用](#错误消息检查-mysql-binlog-是否已启用)。之后,根据你收到的消息解决问题: + +- 如果消息类似于 `These dbs xxx are not in binlog_do_db xxx`,确保你要迁移的所有数据库都在列表中。参见 [--binlog-do-db=db_name](https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html#option_mysqld_binlog-do-db)。 +- 如果消息类似于 `These dbs xxx are in binlog_ignore_db xxx`,确保你要迁移的所有数据库都不在忽略列表中。参见 [--binlog-ignore-db=db_name](https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html#option_mysqld_binlog-ignore-db)。 + +对于 Amazon Aurora MySQL,此预检查项不会失败。确保使用 Amazon Aurora MySQL 写入实例以支持全量和增量数据迁移。 + +对于 Amazon RDS,你需要更改以下参数:`replicate-do-db`、`replicate-do-table`、`replicate-ignore-db` 和 `replicate-ignore-table`。参见 [Configuring MySQL binary logging](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.BinaryFormat.html)。 + +### 错误消息:检查连接并发是否超过数据库的最大连接限制 + +如果错误发生在上游数据库,按如下方式设置 `max_connections`: + +- Amazon Aurora MySQL:过程与设置 `binlog_format` 类似。唯一的区别是你更改的参数是 `max_connections` 而不是 `binlog_format`。参见 [How do I turn on binary logging for my Amazon Aurora MySQL-Compatible cluster](https://aws.amazon.com/premiumsupport/knowledge-center/enable-binary-logging-aurora/?nc1=h_ls)。 +- Amazon RDS:过程与设置 `binlog_format` 类似。唯一的区别是你更改的参数是 `max_connections` 而不是 `binlog_format`。参见 [Configuring MySQL binary logging](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.BinaryFormat.html)。 +- MySQL:按照文档 [max_connections](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_max_connections) 配置 `max_connections`。 + +如果错误发生在 TiDB Cloud 集群中,按照文档 [max_connections](https://docs.pingcap.com/tidb/stable/system-variables#max_connections) 配置 `max_connections`。 + +## 迁移错误和解决方案 + +本节介绍迁移过程中可能遇到的问题和解决方案。这些错误消息会显示在**迁移任务详情**页面上。 + +### 错误消息:"迁移所需的二进制日志在源数据库上不再存在。请确保二进制日志文件保留足够长的时间以确保迁移成功。" + +此错误表示要迁移的 binlog 已被清理,只能通过创建新任务来恢复。 + +确保增量迁移所需的 binlog 存在。建议配置 `expire_logs_days` 以延长 binlog 的保留时间。如果某些迁移任务需要 binlog,请不要使用 `purge binary log` 清理 binlog。 + +### 错误消息:"使用给定参数连接源数据库失败。请确保源数据库已启动并可以使用给定参数连接。" + +此错误表示连接源数据库失败。检查源数据库是否已启动,并且可以使用指定的参数连接。确认源数据库可用后,你可以尝试点击**重启**来恢复任务。 + +### 迁移任务中断并包含错误 "driver: bad connection" 或 "invalid connection" + +此错误表示连接下游 TiDB 集群失败。检查下游 TiDB 集群是否处于正常状态(包括 `Available` 和 `Modifying`),并且可以使用任务指定的用户名和密码连接。确认下游 TiDB 集群可用后,你可以尝试点击**重启**来恢复任务。 + +### 错误消息:"使用给定的用户和密码连接 TiDB 集群失败。请确保 TiDB 集群已启动并可以使用给定的用户和密码连接。" + +连接 TiDB 集群失败。建议检查 TiDB 集群是否处于正常状态(包括 `Available` 和 `Modifying`)。你可以使用任务指定的用户名和密码连接。确认 TiDB 集群可用后,你可以尝试点击**重启**来恢复任务。 + +### 错误消息:"TiDB 集群存储空间不足。请增加 TiKV 节点存储。" + +TiDB 集群存储空间不足。建议[增加 TiKV 节点存储](/tidb-cloud/scale-tidb-cluster.md#change-storage),然后点击**重启**恢复任务。 + +### 错误消息:"连接源数据库失败。请检查数据库是否可用或是否已达到最大连接数。" + +连接源数据库失败。建议检查源数据库是否已启动,数据库连接数是否未达到上限,以及是否可以使用任务指定的参数连接。确认源数据库可用后,你可以尝试点击**重启**恢复任务。 + +### 错误消息:"Error 1273: Unsupported collation when new collation is enabled: 'utf8mb4_0900_ai_ci'" + +在下游 TiDB 集群中创建架构失败。此错误表示上游 MySQL 使用的排序规则不被 TiDB 集群支持。 + +要解决此问题,你可以根据[支持的排序规则](/character-set-and-collation.md#character-sets-and-collations-supported-by-tidb)在 TiDB 集群中创建架构,然后点击**重启**恢复任务。 + +## 告警 + +你可以订阅 TiDB Cloud 告警邮件,以便在发生告警时及时获得通知。 + +以下是关于数据迁移的告警: + +- "数据迁移任务在数据导出过程中遇到错误" + + 建议操作:检查数据迁移页面上的错误消息,并参见[迁移错误和解决方案](#迁移错误和解决方案)获取帮助。 + +- "数据迁移任务在数据导入过程中遇到错误" + + 建议操作:检查数据迁移页面上的错误消息,并参见[迁移错误和解决方案](#迁移错误和解决方案)获取帮助。 + +- "数据迁移任务在增量数据迁移过程中遇到错误" + + 建议操作:检查数据迁移页面上的错误消息,并参见[迁移错误和解决方案](#迁移错误和解决方案)获取帮助。 + +- "数据迁移任务在增量迁移过程中已暂停超过 6 小时" + + 建议操作:恢复数据迁移任务或忽略此告警。 + +- "复制延迟大于 10 分钟且持续增加超过 20 分钟" + + - 建议操作:联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)获取帮助。 + +如果你需要帮助解决这些告警,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)进行咨询。 + +有关如何订阅告警邮件的更多信息,请参见 [TiDB Cloud 内置告警](/tidb-cloud/monitor-built-in-alerting.md)。 + +## 另请参阅 + +- [使用数据迁移功能将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md) diff --git a/tidb-cloud/tidb-cloud-encrypt-cmek.md b/tidb-cloud/tidb-cloud-encrypt-cmek.md new file mode 100644 index 000000000000..c6de10d6895f --- /dev/null +++ b/tidb-cloud/tidb-cloud-encrypt-cmek.md @@ -0,0 +1,168 @@ +--- +title: 使用客户管理的加密密钥进行静态加密 +summary: 了解如何在 TiDB Cloud 中使用客户管理的加密密钥(CMEK)。 +--- + +# 使用客户管理的加密密钥进行静态加密 + +客户管理的加密密钥(Customer-Managed Encryption Key,CMEK)允许你使用完全由你控制的对称加密密钥来保护 TiDB Cloud Dedicated 集群中的静态数据。这个密钥被称为 CMEK 密钥。 + +当为项目启用 CMEK 后,该项目中创建的所有集群都会使用 CMEK 密钥加密其静态数据。此外,这些集群生成的任何备份数据也会使用相同的密钥进行加密。如果未启用 CMEK,TiDB Cloud 会使用托管密钥来加密集群中的所有静态数据。 + +> **注意:** +> +> 目前,此功能仅供申请使用。如果你需要试用此功能,请联系[技术支持](/tidb-cloud/tidb-cloud-support.md)。 + +## 限制 + +- 目前,TiDB Cloud 仅支持使用 AWS KMS 提供 CMEK。 +- 要使用 CMEK,你需要在创建项目时启用 CMEK,并在创建集群之前完成 CMEK 相关配置。你无法为现有项目启用 CMEK。 +- 目前,在启用 CMEK 的项目中,你只能创建在 AWS 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。不支持在其他云服务提供商上托管的 TiDB Cloud Dedicated 集群和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 +- 目前,对于特定项目,你只能为一个 AWS 区域启用 CMEK。配置完成后,你无法在同一项目中的其他区域创建集群。 + +## 启用 CMEK + +如果你想使用你账号拥有的 KMS 加密数据,请执行以下步骤。 + +### 步骤 1. 创建启用 CMEK 的项目 + +如果你是组织的 `Organization Owner` 角色,你可以使用 TiDB Cloud 控制台或 API 创建启用 CMEK 的项目。 + + +
+ +要创建启用 CMEK 的项目,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击 **Projects**。 +3. 在 **Projects** 页面,点击右上角的 **Create New Project**。 +4. 填写项目名称。 +5. 选择启用项目的 CMEK 功能。 +6. 点击 **Confirm** 完成项目创建。 + +
+
+ +你可以通过 [Create a CMEK-enabled project](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Project/operation/CreateProject) 端点使用 TiDB Cloud API 完成此步骤。确保将 `aws_cmek_enabled` 字段设置为 `true`。 + +目前,TiDB Cloud API 仍处于测试阶段。有关更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 + +
+
+ +### 步骤 2. 完成项目的 CMEK 配置 + +你可以使用 TiDB Cloud 控制台或 API 完成项目的 CMEK 配置。 + +> **注意:** +> +> 确保密钥的策略满足要求,并且没有权限不足或账号问题等错误。这些错误可能导致使用此密钥创建的集群出现问题。 + + +
+ +要完成项目的 CMEK 配置,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标项目。 +2. 在左侧导航栏中,点击 **Project Settings** > **Encryption Access**。 +3. 在 **Encryption Access** 页面,点击 **Create Encryption Key** 进入密钥创建页面。 +4. 密钥提供者仅支持 AWS KMS。你可以选择加密密钥可以使用的区域。 +5. 复制并保存 JSON 文件为 `ROLE-TRUST-POLICY.JSON`。此文件描述了信任关系。 +6. 将此信任关系添加到 AWS KMS 的密钥策略中。有关更多信息,请参见 [AWS KMS 中的密钥策略](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)。 +7. 在 TiDB Cloud 控制台中,滚动到密钥创建页面底部,然后填写从 AWS KMS 获取的 **KMS Key ARN**。 +8. 点击 **Create** 创建密钥。 + +
+
+ +1. 在 AWS KMS 上配置密钥策略,并将以下信息添加到密钥策略中: + + ```json + { + "Version": "2012-10-17", + "Id": "cmek-policy", + "Statement": [ + // EBS 相关策略 + { + "Sid": "Allow access through EBS for all principals in the account that are authorized to use EBS", + "Effect": "Allow", + "Principal": { + "AWS": "*" + }, + "Action": [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:CreateGrant", + "kms:DescribeKey" + ], + "Resource": "*", + "Condition": { + "StringEquals": { + "kms:CallerAccount": "", + "kms:ViaService": "ec2..amazonaws.com" + } + } + }, + // S3 相关策略 + { + "Sid": "Allow TiDB cloud role to use KMS to store encrypted backup to S3", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam:::root" + }, + "Action": [ + "kms:Decrypt", + "kms:GenerateDataKey" + ], + "Resource": "*" + }, + ... // 用户自己的 KMS 管理员访问权限 + ] + } + ``` + + - `` 是运行集群的账号。如果你不知道账号,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + - `` 是你想要创建集群的区域,例如 `us-west-2`。如果你不想指定区域,请将 `` 替换为通配符 `*`,并将其放在 `StringLike` 块中。 + - 有关上述块中的 EBS 相关策略,请参见 [AWS 文档](https://docs.aws.amazon.com/kms/latest/developerguide/conditions-kms.html#conditions-kms-caller-account)。 + - 有关上述块中的 S3 相关策略,请参见 [AWS 博客](https://repost.aws/knowledge-center/s3-bucket-access-default-encryption)。 + +2. 调用 TiDB Cloud API 的 [Configure AWS CMEK](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/CreateAwsCmek) 端点。 + + 目前,TiDB Cloud API 仍处于测试阶段。有关更多信息,请参见 [TiDB Cloud API 文档](https://docs.pingcap.com/tidbcloud/api/v1beta)。 + +
+
+ +> **注意:** +> +> 此功能将在未来进一步增强,即将推出的功能可能需要额外的权限。因此,此策略要求可能会发生变化。 + +### 步骤 3. 创建集群 + +在[步骤 1](#步骤-1-创建启用-cmek-的项目) 中创建的项目下,创建一个在 AWS 上托管的 TiDB Cloud Dedicated 集群。有关详细步骤,请参见[此文档](/tidb-cloud/create-tidb-cluster.md)。确保集群所在的区域与[步骤 2](/tidb-cloud/tidb-cloud-encrypt-cmek.md#步骤-2-完成项目的-cmek-配置)中的区域相同。 + +> **注意:** +> +> 启用 CMEK 后,集群节点使用的 EBS 卷和集群备份使用的 S3 都将使用 CMEK 进行加密。 + +## 轮换 CMEK + +你可以在 AWS KMS 上配置[自动 CMEK 轮换](http://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)。启用此轮换后,你无需在 TiDB Cloud 的项目设置中更新 **Encryption Access**,包括 CMEK ID。 + +## 撤销和恢复 CMEK + +如果你需要临时撤销 TiDB Cloud 对 CMEK 的访问权限,请执行以下步骤: + +1. 在 AWS KMS 控制台上,撤销相应的权限并更新 KMS 密钥策略。 +2. 在 TiDB Cloud 控制台上,暂停项目中的所有集群。 + +> **注意:** +> +> 在 AWS KMS 上撤销 CMEK 后,你正在运行的集群不会受到影响。但是,当你暂停集群然后恢复集群时,由于无法访问 CMEK,集群将无法正常恢复。 + +撤销 TiDB Cloud 对 CMEK 的访问权限后,如果你需要恢复访问权限,请执行以下步骤: + +1. 在 AWS KMS 控制台上,恢复 CMEK 访问策略。 +2. 在 TiDB Cloud 控制台上,恢复项目中的所有集群。 diff --git a/tidb-cloud/tidb-cloud-events.md b/tidb-cloud/tidb-cloud-events.md new file mode 100644 index 000000000000..fbf27481119a --- /dev/null +++ b/tidb-cloud/tidb-cloud-events.md @@ -0,0 +1,58 @@ +--- +title: TiDB Cloud 集群事件 +summary: 了解如何使用事件页面查看 TiDB Cloud 集群的事件。 +--- + +# TiDB Cloud 集群事件 + +TiDB Cloud 会在集群层面记录历史事件。*事件*表示 TiDB Cloud 集群中的一个变更。你可以在**事件**页面查看已记录的事件,包括事件类型、状态、消息、触发时间和触发用户。 + +本文档介绍如何使用**事件**页面查看 TiDB Cloud 集群的事件,并列出支持的事件类型。 + +## 查看事件页面 + +要在**事件**页面查看事件,请按照以下步骤操作: + +1. 在项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面,点击目标集群的名称以进入其概览页面。 + + > **提示:** + > + > 你可以使用左上角的下拉框在组织、项目和集群之间切换。 + +2. 在左侧导航栏中,点击**监控** > **事件**。 + +## 已记录的事件 + +TiDB Cloud 记录以下类型的集群事件: + +| 事件类型 | 描述 | +|:--- |:--- | +| CreateCluster | 创建集群 | +| PauseCluster | 暂停集群 | +| ResumeCluster | 恢复集群 | +| ModifyClusterSize | 修改集群大小 | +| BackupCluster | 备份集群 | +| ExportBackup | 导出备份 | +| RestoreFromCluster | 恢复集群 | +| CreateChangefeed | 创建 changefeed | +| PauseChangefeed | 暂停 changefeed | +| ResumeChangefeed | 恢复 changefeed | +| DeleteChangefeed | 删除 changefeed | +| EditChangefeed | 编辑 changefeed | +| ScaleChangefeed | 调整 changefeed 规格 | +| FailedChangefeed | Changefeed 失败 | +| ImportData | 向集群导入数据 | +| UpdateSpendingLimit | 更新 TiDB Cloud Serverless 可扩展集群的支出限制 | +| ResourceLimitation | 更新 TiDB Cloud Serverless 集群的资源限制 | + +对于每个事件,会记录以下信息: + +- 事件类型 +- 状态 +- 消息 +- 时间 +- 触发者 + +## 事件保留策略 + +事件数据保留 7 天。 diff --git a/tidb-cloud/tidb-cloud-faq.md b/tidb-cloud/tidb-cloud-faq.md new file mode 100644 index 000000000000..69b3d1597db8 --- /dev/null +++ b/tidb-cloud/tidb-cloud-faq.md @@ -0,0 +1,207 @@ +--- +title: TiDB Cloud 常见问题 +summary: 了解关于 TiDB Cloud 的最常见问题(FAQ)。 +--- + +# TiDB Cloud 常见问题 + + + +本文列出了关于 TiDB Cloud 的最常见问题。 + +## 一般问题 + +### 什么是 TiDB Cloud? + +TiDB Cloud 通过完全托管的云实例使部署、管理和维护 TiDB 集群变得更加简单,你可以通过直观的控制台来控制它。你可以轻松地在 Amazon Web Services (AWS)、Google Cloud 或 Microsoft Azure 上部署,快速构建关键任务应用程序。 + +TiDB Cloud 使得几乎不需要培训的开发人员和 DBA 也能轻松处理曾经复杂的任务,如基础设施管理和集群部署,从而专注于你的应用程序,而不是数据库的复杂性。通过简单的点击按钮即可扩展或收缩 TiDB 集群,你不再浪费昂贵的资源,因为你可以根据需要的容量和时间来配置数据库。 + +### TiDB 和 TiDB Cloud 之间是什么关系? + +TiDB 是一个开源数据库,是希望在自己的数据中心、自管理的云环境或两者混合环境中运行 TiDB Self-Managed 的组织的最佳选择。 + +TiDB Cloud 是 TiDB 的完全托管的云数据库即服务。它具有易于使用的基于 Web 的管理控制台,让你可以管理关键任务生产环境的 TiDB 集群。 + +### TiDB Cloud 是否与 MySQL 兼容? + +目前,TiDB Cloud 支持大部分 MySQL 5.7 和 MySQL 8.0 语法,但不支持触发器、存储过程和用户定义函数。更多详细信息,请参见[与 MySQL 的兼容性](/mysql-compatibility.md)。 + +### 我可以使用哪些编程语言来使用 TiDB Cloud? + +你可以使用任何支持 MySQL 客户端或驱动程序的语言。 + +### 我可以在哪里运行 TiDB Cloud? + +TiDB Cloud 目前可在 Amazon Web Services (AWS)、Google Cloud 和 Microsoft Azure 上使用。 + +### TiDB Cloud 是否支持不同云服务提供商之间的 VPC 对等连接? + +不支持。 + +### TiDB Cloud 支持哪些版本的 TiDB? + +- 从 2025 年 1 月 2 日起,新建 TiDB Cloud Dedicated 集群的默认 TiDB 版本是 [v8.1.2](https://docs.pingcap.com/tidb/v8.1/release-8.1.2)。 +- 从 2024 年 2 月 21 日起,TiDB Cloud Serverless 集群的 TiDB 版本是 [v7.1.3](https://docs.pingcap.com/tidb/v7.1/release-7.1.3)。 + +更多信息,请参见 [TiDB Cloud 发布说明](/tidb-cloud/tidb-cloud-release-notes.md)。 + +### 哪些公司在生产环境中使用 TiDB 或 TiDB Cloud? + +TiDB 受到全球超过 1500 家企业的信任,涉及金融服务、游戏和电子商务等各个行业。我们的用户包括 Square(美国)、Shopee(新加坡)和中国银联(中国)。具体详情请参见我们的[案例研究](https://www.pingcap.com/customers/)。 + +### SLA 是什么样的? + +TiDB Cloud 提供 99.99% 的 SLA。详情请参见 [TiDB Cloud 服务的服务级别协议](https://www.pingcap.com/legal/service-level-agreement-for-tidb-cloud-services/)。 + +### TiDB Cloud 中的 BETA 是什么意思? + +BETA 是 TiDB Cloud 功能或产品在正式发布(GA)之前的公开预览阶段。 + +### 如何了解更多关于 TiDB Cloud 的信息? + +了解 TiDB Cloud 的最好方法是按照我们的分步教程进行操作。查看以下主题以开始: + +- [TiDB Cloud 简介](/tidb-cloud/tidb-cloud-intro.md) +- [开始使用](/tidb-cloud/tidb-cloud-quickstart.md) +- [创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md) + +### 删除集群时提到的 `XXX's Org/default project/Cluster0` 是什么意思? + +在 TiDB Cloud 中,集群由组织名称、项目名称和集群名称的组合唯一标识。为确保你删除的是预期的集群,你需要提供该集群的完全限定名称,例如 `XXX's Org/default project/Cluster0`。 + +## 架构问题 + +### 我的 TiDB 集群中有不同的组件。TiDB、TiKV 和 TiFlash 节点是什么? + +TiDB 是 SQL 计算层,用于聚合从 TiKV 或 TiFlash 存储返回的查询数据。TiDB 可以水平扩展;增加 TiDB 节点数量将增加集群可以处理的并发查询数量。 + +TiKV 是用于存储 OLTP 数据的事务存储。TiKV 中的所有数据都自动维护多个副本(默认为三个副本),因此 TiKV 具有原生高可用性并支持自动故障转移。TiKV 可以水平扩展;增加事务存储数量将增加 OLTP 吞吐量。 + +TiFlash 是分析存储,它实时从事务存储(TiKV)复制数据,并支持实时 OLAP 工作负载。与 TiKV 不同,TiFlash 以列式存储数据以加速分析处理。TiFlash 也可以水平扩展;增加 TiFlash 节点将增加 OLAP 存储和计算能力。 + +PD(Placement Driver)是整个 TiDB 集群的"大脑",因为它存储了集群的元数据。它根据 TiKV 节点实时报告的数据分布状态向特定的 TiKV 节点发送数据调度命令。在 TiDB Cloud 中,每个集群的 PD 由 PingCAP 管理,你无法看到或维护它。 + +### TiDB 如何在 TiKV 节点之间复制数据? + +TiKV 将键值空间划分为键范围,每个键范围被视为一个"Region"。在 TiKV 中,数据分布在集群中的所有节点上,并使用 Region 作为基本单位。PD 负责将 Region 尽可能均匀地分布(调度)到集群中的所有节点上。 + +TiDB 使用 Raft 共识算法按 Region 复制数据。存储在不同节点上的 Region 的多个副本形成一个 Raft Group。 + +每个数据更改都记录为一个 Raft 日志。通过 Raft 日志复制,数据被安全可靠地复制到 Raft Group 的多个节点上。 + +## 高可用性问题 + +### TiDB Cloud 如何确保高可用性? + +TiDB 使用 Raft 共识算法确保数据在 Raft Groups 中的存储具有高可用性和安全复制。数据在 TiKV 节点之间冗余复制,并放置在不同的可用区中,以防止机器或数据中心故障。通过自动故障转移,TiDB 确保你的服务始终在线。 + +作为软件即服务(SaaS)提供商,我们非常重视数据安全。我们已经建立了 [Service Organization Control (SOC) 2 Type 1 合规](https://www.pingcap.com/press-release/pingcap-successfully-completes-soc-2-type-1-examination-for-tidb-cloud/) 所要求的严格信息安全政策和程序。这确保了你的数据是安全、可用和保密的。 + +## 迁移问题 + +### 是否有从其他 RDBMS 迁移到 TiDB Cloud 的简单途径? + +TiDB 与 MySQL 高度兼容。你可以从任何 MySQL 兼容的数据库平滑迁移数据到 TiDB,无论数据是来自自托管的 MySQL 实例还是公共云提供的 RDS 服务。更多信息,请参见[使用数据迁移将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +## 备份和恢复问题 + +### TiDB Cloud 是否支持增量备份? + +不支持。如果你需要将数据恢复到集群备份保留期内的任意时间点,你可以使用 PITR(时间点恢复)。更多信息,请参见[在 TiDB Cloud Dedicated 集群中使用 PITR](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup) 或[在 TiDB Cloud Serverless 集群中使用 PITR](/tidb-cloud/backup-and-restore-serverless.md#restore)。 + +## HTAP 问题 + +### 如何利用 TiDB Cloud 的 HTAP 功能? + +传统上,有两种类型的数据库:在线事务处理(OLTP)数据库和在线分析处理(OLAP)数据库。OLTP 和 OLAP 请求通常在不同的独立数据库中处理。使用这种传统架构,将数据从 OLTP 数据库迁移到数据仓库或数据湖进行 OLAP 是一个漫长且容易出错的过程。 + +作为混合事务分析处理(HTAP)数据库,TiDB Cloud 通过在 OLTP(TiKV)存储和 OLAP(TiFlash)存储之间自动可靠地复制数据,帮助你简化系统架构,降低维护复杂性,并支持对事务数据进行实时分析。典型的 HTAP 用例包括用户个性化、AI 推荐、欺诈检测、商业智能和实时报告。 + +有关更多 HTAP 场景,请参考[我们如何构建一个简化数据平台的 HTAP 数据库](https://pingcap.com/blog/how-we-build-an-htap-database-that-simplifies-your-data-platform)。 + +### 我可以直接将数据导入到 TiFlash 吗? + +不可以。当你将数据导入到 TiDB Cloud 时,数据会被导入到 TiKV。导入完成后,你可以使用 SQL 语句指定要复制到 TiFlash 的表。然后,TiDB 会相应地在 TiFlash 中创建指定表的副本。更多信息,请参见[创建 TiFlash 副本](/tiflash/create-tiflash-replicas.md)。 + +### 我可以将 TiFlash 数据以 CSV 格式导出吗? + +不可以。TiFlash 数据无法导出。 + +## 安全问题 + +### TiDB Cloud 是否安全? + +在 TiDB Cloud 中,所有静态数据都经过加密,所有网络流量都使用传输层安全性(TLS)加密。 + +- 静态数据加密使用加密存储卷自动完成。 +- 客户端和集群之间传输中的数据加密使用 TiDB Cloud Web 服务器 TLS 和 TiDB 集群 TLS 自动完成。 + +### TiDB Cloud 如何加密我的业务数据? + +TiDB Cloud 默认使用存储卷加密来保护你的静态业务数据,包括你的数据库数据和备份数据。TiDB Cloud 要求对传输中的数据使用 TLS 加密,并要求对数据库集群中 TiDB、PD、TiKV 和 TiFlash 之间的数据进行组件级 TLS 加密。 + +要获取有关 TiDB Cloud 中业务数据加密的更多具体信息,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +### TiDB Cloud 支持哪些版本的 TLS? + +TiDB Cloud 支持 TLS 1.2 或 TLS 1.3。 + +### 我可以在我的 VPC 中运行 TiDB Cloud 吗? + +不可以。TiDB Cloud 是数据库即服务(DBaaS),只能在 TiDB Cloud VPC 中运行。作为云计算托管服务,TiDB Cloud 提供数据库访问,无需设置物理硬件和安装软件。 + +### 我的 TiDB 集群是否安全? + +在 TiDB Cloud 中,你可以根据需要使用 TiDB Cloud Dedicated 集群或 TiDB Cloud Serverless 集群。 + +对于 TiDB Cloud Dedicated 集群,TiDB Cloud 通过以下措施确保集群安全: + +- 为每个集群创建独立的子账户和 VPC。 +- 设置防火墙规则以隔离外部连接。 +- 为每个集群创建服务器端 TLS 证书和组件级 TLS 证书,以加密传输中的集群数据。 +- 为每个集群提供 IP 访问规则,确保只有允许的源 IP 地址才能访问你的集群。 + +对于 TiDB Cloud Serverless 集群,TiDB Cloud 通过以下措施确保集群安全: + +- 为每个集群创建独立的子账户。 +- 设置防火墙规则以隔离外部连接。 +- 提供集群服务器 TLS 证书以加密传输中的集群数据。 + +### 如何连接到 TiDB 集群中的数据库? + + +
+ +对于 TiDB Cloud Dedicated 集群,连接到集群的步骤简化如下: + +1. 授权你的网络。 +2. 设置数据库用户和登录凭据。 +3. 下载并配置集群服务器的 TLS。 +4. 选择一个 SQL 客户端,获取 TiDB Cloud UI 上显示的自动生成的连接字符串,然后使用该字符串通过 SQL 客户端连接到你的集群。 + +更多信息,请参见[连接到你的 TiDB Cloud Dedicated 集群](/tidb-cloud/connect-to-tidb-cluster.md)。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,连接到集群的步骤简化如下: + +1. 设置数据库用户和登录凭据。 +2. 选择一个 SQL 客户端,获取 TiDB Cloud UI 上显示的自动生成的连接字符串,然后使用该字符串通过 SQL 客户端连接到你的集群。 + +更多信息,请参见[连接到你的 TiDB Cloud Serverless 集群](/tidb-cloud/connect-to-tidb-cluster-serverless.md)。 + +
+
+ +## 支持问题 + +### 为客户提供哪些支持? + +TiDB Cloud 由 TiDB 背后的同一团队提供支持,该团队已经为金融服务、电子商务、企业应用和游戏等行业的 1500 多家全球企业运行关键任务用例。TiDB Cloud 为每个用户提供免费的基本支持计划,你可以升级到付费计划以获得扩展服务。更多信息,请参见 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +### 如何检查 TiDB Cloud 是否宕机? + +你可以在[系统状态](https://status.tidbcloud.com/)页面上检查 TiDB Cloud 的当前运行时间状态。 diff --git a/tidb-cloud/tidb-cloud-glossary.md b/tidb-cloud/tidb-cloud-glossary.md new file mode 100644 index 000000000000..f36c1fd8fd9e --- /dev/null +++ b/tidb-cloud/tidb-cloud-glossary.md @@ -0,0 +1,194 @@ +--- +title: TiDB Cloud 术语表 +summary: 了解 TiDB Cloud 中使用的术语。 +category: glossary +aliases: ['/tidbcloud/glossary'] +--- + +# TiDB Cloud 术语表 + +## A + +### ACID + +ACID 指事务的四个关键属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。每个属性描述如下: + +- **原子性**意味着操作的所有更改要么全部执行,要么全部不执行。TiDB 通过确保存储主键的 [TiDB Region](#region) 的原子性来实现事务的原子性。 + +- **一致性**意味着事务始终将数据库从一个一致的状态转换到另一个一致的状态。在 TiDB 中,在将数据写入内存之前会确保数据一致性。 + +- **隔离性**意味着正在进行的事务在完成之前对其他事务是不可见的。这允许并发事务在不牺牲一致性的情况下读写数据。TiDB 目前支持 `REPEATABLE READ` 隔离级别。 + +- **持久性**意味着一旦事务提交,即使在系统故障的情况下也保持提交状态。TiKV 使用持久存储来确保持久性。 + +## C + +### Chat2Query + +Chat2Query 是集成在 SQL Editor 中的 AI 驱动功能,可以帮助用户使用自然语言指令生成、调试或重写 SQL 查询。更多信息,请参见[使用 AI 辅助的 SQL Editor 探索数据](/tidb-cloud/explore-data-with-chat2query.md)。 + +此外,TiDB Cloud 为 TiDB Cloud Serverless 集群提供 Chat2Query API。启用后,TiDB Cloud 将自动创建一个名为 **Chat2Query** 的系统 Data App 和 Data Service 中的 Chat2Data 端点。你可以调用此端点,通过提供指令让 AI 生成和执行 SQL 语句。更多信息,请参见[开始使用 Chat2Query API](/tidb-cloud/use-chat2query-api.md)。 + +### Credit(积分) + +TiDB Cloud 为概念验证(PoC)用户提供一定数量的积分。一个积分等于一美元。你可以在积分过期前使用积分支付 TiDB 集群费用。 + +## D + +### Data App(数据应用) + +[Data Service (beta)](#data-service) 中的 Data App 是可用于访问特定应用程序数据的端点集合。你可以使用 API 密钥配置授权设置,以限制对 Data App 中端点的访问。 + +更多信息,请参见[管理 Data App](/tidb-cloud/data-service-manage-data-app.md)。 + +### Data Service(数据服务) + +Data Service (beta) 使你能够通过使用自定义 API [端点](#endpoint)通过 HTTPS 请求访问 TiDB Cloud 数据。此功能使用无服务器架构来处理计算资源和弹性扩展,因此你可以专注于端点中的查询逻辑,而无需担心基础设施或维护成本。 + +更多信息,请参见[Data Service 概述](/tidb-cloud/data-service-overview.md)。 + +### Direct Customer(直接客户) + +直接客户是直接从 PingCAP 购买 TiDB Cloud 并支付账单的最终客户。这与 [MSP 客户](#msp-customer)不同。 + +## E + +### Endpoint(端点) + +Data Service 中的端点是可以自定义以执行 SQL 语句的 Web API。你可以为 SQL 语句指定参数,例如在 `WHERE` 子句中使用的值。当客户端调用端点并在请求 URL 中为参数提供值时,端点会使用提供的参数执行相应的 SQL 语句,并将结果作为 HTTP 响应的一部分返回。 + +更多信息,请参见[管理端点](/tidb-cloud/data-service-manage-endpoint.md)。 + +## F + +### Full-text search(全文搜索) + +与专注于语义相似性的[向量搜索](/tidb-cloud/vector-search-overview.md)不同,全文搜索让你可以检索精确关键词的文档。在检索增强生成(RAG)场景中,你可以将全文搜索与向量搜索结合使用,以提高检索质量。 + +更多信息,请参见[使用 SQL 进行全文搜索](/tidb-cloud/vector-search-full-text-search-sql.md)和[使用 Python 进行全文搜索](/tidb-cloud/vector-search-full-text-search-python.md)。 + +## M + +### member(成员) + +已被邀请加入组织的用户,可以访问该组织及其集群。 + +### MPP + +从 v5.0 开始,TiDB 通过 TiFlash 节点引入了大规模并行处理(MPP)架构,在 TiFlash 节点之间共享大型连接查询的执行工作负载。当启用 MPP 模式时,TiDB 会根据成本决定是否使用 MPP 框架执行计算。在 MPP 模式下,连接键通过 Exchange 操作在计算时重新分配,这将计算压力分配到每个 TiFlash 节点并加快计算速度。更多信息,请参见[使用 TiFlash MPP 模式](/tiflash/use-tiflash-mpp-mode.md)。 + +### MSP Customer(MSP 客户) + +托管服务提供商(MSP)客户是通过 MSP 渠道购买 TiDB Cloud 并支付账单的最终客户。这与[直接客户](#direct-customer)不同。 + +### Managed Service Provider(托管服务提供商,MSP) + +托管服务提供商(MSP)是转售 TiDB Cloud 并提供增值服务的合作伙伴,包括但不限于 TiDB Cloud 组织管理、计费服务和技术支持。 + +## N + +### node(节点) + +指数据实例(TiKV)、计算实例(TiDB)或分析实例(TiFlash)。 + +## O + +### organization(组织) + +用于管理 TiDB Cloud 账户的实体,包括一个管理账户和任意数量的多个成员账户。 + +### organization members(组织成员) + +组织成员是由组织所有者或项目所有者邀请加入组织的用户。组织成员可以查看组织的成员,并可以被邀请加入组织内的项目。 + +## P + +### policy(策略) + +定义应用于角色、用户或组织的权限的文档,例如对特定操作或资源的访问权限。 + +### project(项目) + +基于组织创建的项目,可以根据项目分别管理人员、实例和网络等资源,项目之间的资源不会相互干扰。 + +### project members(项目成员) + +项目成员是被邀请加入组织的一个或多个项目的用户。项目成员可以管理集群、网络访问、备份和其他资源。 + +## R + +### Recycle Bin(回收站) + +存储具有有效备份的已删除集群数据的位置。一旦备份的 TiDB Cloud Dedicated 集群被删除,该集群的现有备份文件将被移至回收站。对于自动备份的备份文件,回收站将保留指定时间。你可以在**备份设置**中配置备份保留时间,默认为 7 天。对于手动备份的备份文件,没有过期日期。为避免数据丢失,请及时将数据恢复到新集群。请注意,如果集群**没有备份**,已删除的集群将不会显示在此处。 + +### region(区域) + +- TiDB Cloud region(TiDB Cloud 区域) + + 部署 TiDB Cloud 集群的地理区域。TiDB Cloud 区域包含至少 3 个可用区,集群跨这些区域部署。 + +- TiDB Region + + TiDB 中的基本数据单位。TiKV 将键值空间划分为一系列连续的键段,每个段称为一个 Region。每个 Region 的默认大小限制为 96 MB,可以配置。 + +### replica(副本) + +可以位于相同或不同区域并包含相同数据的单独数据库。副本通常用于灾难恢复或提高性能。 + +### Replication Capacity Unit(复制容量单位) + +changefeed 的复制根据计算资源收费,即 TiCDC 复制容量单位。 + +### Request Unit(请求单位) + +请求单位(RU)是用于表示单个数据库请求消耗的资源量的度量单位。请求消耗的 RU 数量取决于各种因素,例如操作类型或检索或修改的数据量。更多信息,请参见 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-cloud-serverless-pricing-details)。 + +## S + +### Spending limit(消费限额) + +消费限额指你愿意在特定工作负载上每月花费的最大金额。这是一种成本控制机制,使你能够为 TiDB Cloud Serverless 集群设置预算。对于[可扩展集群](/tidb-cloud/select-cluster-tier.md#scalable-cluster-plan),消费限额必须设置为最低 0.01 美元。此外,如果符合条件,可扩展集群可以获得免费配额。具有免费配额的可扩展集群将首先使用免费配额。 + +## T + +### TiDB cluster(TiDB 集群) + +由 [TiDB](https://docs.pingcap.com/tidb/stable/tidb-computing)、[TiKV](https://docs.pingcap.com/tidb/stable/tidb-storage)、[Placement Driver](https://docs.pingcap.com/tidb/stable/tidb-scheduling)(PD)和 [TiFlash](https://docs.pingcap.com/tidb/stable/tiflash-overview) 节点组成的功能性工作数据库集合。 + +### TiDB node(TiDB 节点) + +从事务或分析存储返回的查询数据进行聚合的计算节点。增加 TiDB 节点数量将增加集群可以处理的并发查询数量。 + +### TiFlash node(TiFlash 节点) + +实时从 TiKV 复制数据并支持实时分析工作负载的分析存储节点。 + +### TiKV node(TiKV 节点) + +存储在线事务处理(OLTP)数据的存储节点。为了实现高可用性,它以 3 个节点的倍数(例如 3、6、9)进行扩展,其中两个节点作为副本。增加 TiKV 节点数量将增加总吞吐量。 + +### traffic filter(流量过滤器) + +允许通过 SQL 客户端访问 TiDB Cloud 集群的 IP 地址和无类域间路由(CIDR)地址列表。流量过滤器默认为空。 + +## V + +### Vector search(向量搜索) + +[向量搜索](/tidb-cloud/vector-search-overview.md)是一种优先考虑数据含义以提供相关结果的搜索方法。与依赖精确关键词匹配和词频的传统全文搜索不同,向量搜索将各种数据类型(如文本、图像或音频)转换为高维向量,并基于这些向量之间的相似性进行查询。这种搜索方法捕获数据的语义含义和上下文信息,从而更准确地理解用户意图。即使搜索词与数据库中的内容不完全匹配,向量搜索仍然可以通过分析数据的语义提供符合用户意图的结果。 + +### Virtual Private Cloud(虚拟私有云) + +为你的资源提供托管网络服务的逻辑隔离虚拟网络分区。 + +### VPC + +Virtual Private Cloud(虚拟私有云)的缩写。 + +### VPC peering(VPC 对等连接) + +使你能够连接虚拟私有云([VPC](#vpc))网络,以便不同 VPC 网络中的工作负载可以私密通信。 + +### VPC peering connection(VPC 对等连接) + +两个虚拟私有云(VPC)之间的网络连接,使你能够使用私有 IP 地址在它们之间路由流量,并帮助你促进数据传输。 diff --git a/tidb-cloud/tidb-cloud-htap-quickstart.md b/tidb-cloud/tidb-cloud-htap-quickstart.md new file mode 100644 index 000000000000..409ce6359a6a --- /dev/null +++ b/tidb-cloud/tidb-cloud-htap-quickstart.md @@ -0,0 +1,158 @@ +--- +title: TiDB Cloud HTAP 快速上手指南 +summary: 了解如何在 TiDB Cloud 中开始使用 HTAP。 +aliases: ['/tidbcloud/use-htap-cluster'] +--- + +# TiDB Cloud HTAP 快速上手指南 + +[HTAP](https://en.wikipedia.org/wiki/Hybrid_transactional/analytical_processing)(混合事务和分析处理)是指 Hybrid Transactional and Analytical Processing。TiDB Cloud 中的 HTAP 集群由 [TiKV](https://tikv.org)(为事务处理设计的行存储引擎)和 [TiFlash](https://docs.pingcap.com/tidb/stable/tiflash-overview)(为分析处理设计的列存储)组成。应用程序数据首先存储在 TiKV 中,然后通过 Raft 共识算法复制到 TiFlash。这是从行存储到列存储的实时复制。 + +本教程将指导您体验 TiDB Cloud 的混合事务和分析处理(HTAP)功能。内容包括如何将表复制到 TiFlash、如何使用 TiFlash 运行查询以及如何体验性能提升。 + +## 开始之前 + +在体验 HTAP 功能之前,请按照 [TiDB Cloud 快速上手指南](/tidb-cloud/tidb-cloud-quickstart.md)创建一个 TiDB Cloud Serverless 集群,并将 **Steam Game Stats** 示例数据集导入到集群中。 + +## 步骤 + +### 步骤 1. 将示例数据复制到列存储引擎 + +创建带有 TiFlash 节点的集群后,TiKV 默认不会将数据复制到 TiFlash。您需要在 TiDB 的 MySQL 客户端中执行 DDL 语句来指定要复制的表。之后,TiDB 将在 TiFlash 中相应地创建指定的表副本。 + +例如,要将 `games` 表(在 **Steam Game Stats** 示例数据集中)复制到 TiFlash,请执行以下语句: + +```sql +USE game; +``` + +```sql +ALTER TABLE games SET TIFLASH REPLICA 2; +``` + +要检查复制进度,请执行以下语句: + +```sql +SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_ID, REPLICA_COUNT, LOCATION_LABELS, AVAILABLE, PROGRESS FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = 'game' and TABLE_NAME = 'games'; +``` + +```sql ++--------------+------------+----------+---------------+-----------------+-----------+----------+ +| TABLE_SCHEMA | TABLE_NAME | TABLE_ID | REPLICA_COUNT | LOCATION_LABELS | AVAILABLE | PROGRESS | ++--------------+------------+----------+---------------+-----------------+-----------+----------+ +| game | games | 88 | 2 | | 1 | 1 | ++--------------+------------+----------+---------------+-----------------+-----------+----------+ +1 row in set (0.20 sec) +``` + +在上述语句的结果中: + +- `AVAILABLE` 表示特定表的 TiFlash 副本是否可用。`1` 表示可用,`0` 表示不可用。一旦副本变为可用,此状态将不再改变。 +- `PROGRESS` 表示复制的进度。值在 `0` 和 `1` 之间。`1` 表示至少有一个副本已复制完成。 + +### 步骤 2. 使用 HTAP 查询数据 + +当复制过程完成后,您就可以开始运行一些查询了。 + +例如,您可以查看每年发布的游戏数量,以及平均价格和平均游戏时长: + +```sql +SELECT + YEAR(`release_date`) AS `release_year`, + COUNT(*) AS `games_released`, + AVG(`price`) AS `average_price`, + AVG(`average_playtime_forever`) AS `average_playtime` +FROM + `games` +GROUP BY + `release_year` +ORDER BY + `release_year` DESC; +``` + +### 步骤 3. 比较行存储和列存储的查询性能 + +在这一步中,您可以比较 TiKV(行存储)和 TiFlash(列存储)之间的执行统计信息。 + +- 要获取使用 TiKV 的查询执行统计信息,请执行以下语句: + + ```sql + EXPLAIN ANALYZE SELECT /*+ READ_FROM_STORAGE(TIKV[games]) */ + YEAR(`release_date`) AS `release_year`, + COUNT(*) AS `games_released`, + AVG(`price`) AS `average_price`, + AVG(`average_playtime_forever`) AS `average_playtime` + FROM + `games` + GROUP BY + `release_year` + ORDER BY + `release_year` DESC; + ``` + + 对于具有 TiFlash 副本的表,TiDB 优化器会根据成本估算自动决定使用 TiKV 还是 TiFlash 副本。在上述 `EXPLAIN ANALYZE` 语句中,使用 `/*+ READ_FROM_STORAGE(TIKV[games]) */` 提示来强制优化器选择 TiKV,以便您可以查看 TiKV 的执行统计信息。 + + > **注意:** + > + > 5.7.7 之前版本的 MySQL 命令行客户端默认会去除优化器提示。如果您在这些早期版本中使用 `Hint` 语法,请在启动客户端时添加 `--comments` 选项。例如:`mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 + + 在输出中,您可以从 `execution info` 列获取执行时间。 + + ```sql + id | estRows | actRows | task | access object | execution info | operator info | memory | disk + ---------------------------+----------+---------+-----------+---------------+--------------------------------------------+-----------------------------------------------+---------+--------- + Sort_5 | 4019.00 | 28 | root | | time:672.7ms, loops:2, RU:1159.679690 | Column#36:desc | 18.0 KB | 0 Bytes + └─Projection_7 | 4019.00 | 28 | root | | time:672.7ms, loops:6, Concurrency:5 | year(game.games.release_date)->Column#36, ... | 35.5 KB | N/A + └─HashAgg_15 | 4019.00 | 28 | root | | time:672.6ms, loops:6, partial_worker:... | group by:Column#38, funcs:count(Column#39)... | 56.7 KB | N/A + └─TableReader_16 | 4019.00 | 28 | root | | time:672.4ms, loops:2, cop_task: {num:... | data:HashAgg_9 | 3.60 KB | N/A + └─HashAgg_9 | 4019.00 | 28 | cop[tikv] | | tikv_task:{proc max:300ms, min:0s, avg... | group by:year(game.games.release_date), ... | N/A | N/A + └─TableFullScan_14 | 68223.00 | 68223 | cop[tikv] | table:games | tikv_task:{proc max:290ms, min:0s, avg... | keep order:false | N/A | N/A + (6 rows) + ``` + +- 要获取使用 TiFlash 的查询执行统计信息,请执行以下语句: + + ```sql + EXPLAIN ANALYZE SELECT + YEAR(`release_date`) AS `release_year`, + COUNT(*) AS `games_released`, + AVG(`price`) AS `average_price`, + AVG(`average_playtime_forever`) AS `average_playtime` + FROM + `games` + GROUP BY + `release_year` + ORDER BY + `release_year` DESC; + ``` + + 在输出中,您可以从 `execution info` 列获取执行时间。 + + ```sql + id | estRows | actRows | task | access object | execution info | operator info | memory | disk + -------------------------------------+----------+---------+--------------+---------------+-------------------------------------------------------+--------------------------------------------+---------+--------- + Sort_5 | 4019.00 | 28 | root | | time:222.2ms, loops:2, RU:25.609675 | Column#36:desc | 3.77 KB | 0 Bytes + └─TableReader_39 | 4019.00 | 28 | root | | time:222.1ms, loops:2, cop_task: {num: 2, max: 0s,... | MppVersion: 1, data:ExchangeSender_38 | 4.64 KB | N/A + └─ExchangeSender_38 | 4019.00 | 28 | mpp[tiflash] | | tiflash_task:{time:214.8ms, loops:1, threads:1} | ExchangeType: PassThrough | N/A | N/A + └─Projection_8 | 4019.00 | 28 | mpp[tiflash] | | tiflash_task:{time:214.8ms, loops:1, threads:1} | year(game.games.release_date)->Column#3... | N/A | N/A + └─Projection_34 | 4019.00 | 28 | mpp[tiflash] | | tiflash_task:{time:214.8ms, loops:1, threads:1} | Column#33, div(Column#34, cast(case(eq(... | N/A | N/A + └─HashAgg_35 | 4019.00 | 28 | mpp[tiflash] | | tiflash_task:{time:214.8ms, loops:1, threads:1} | group by:Column#63, funcs:sum(Column#64... | N/A | N/A + └─ExchangeReceiver_37 | 4019.00 | 28 | mpp[tiflash] | | tiflash_task:{time:214.8ms, loops:1, threads:8} | | N/A | N/A + └─ExchangeSender_36 | 4019.00 | 28 | mpp[tiflash] | | tiflash_task:{time:210.6ms, loops:1, threads:1} | ExchangeType: HashPartition, Compressio... | N/A | N/A + └─HashAgg_33 | 4019.00 | 28 | mpp[tiflash] | | tiflash_task:{time:210.6ms, loops:1, threads:1} | group by:Column#75, funcs:count(1)->Col... | N/A | N/A + └─Projection_40 | 68223.00 | 68223 | mpp[tiflash] | | tiflash_task:{time:210.6ms, loops:2, threads:8} | game.games.price, game.games.price, gam... | N/A | N/A + └─TableFullScan_23 | 68223.00 | 68223 | mpp[tiflash] | table:games | tiflash_task:{time:210.6ms, loops:2, threads:8}, ... | keep order:false | N/A | N/A + (11 rows) + ``` + +> **注意:** +> +> 由于示例数据的大小较小,且本文档中的查询非常简单,如果您已经强制优化器为此查询选择了 TiKV 并再次运行相同的查询,TiKV 将重用其缓存,因此查询可能会快得多。如果数据经常更新,缓存将会失效。 + +## 了解更多 + +- [TiFlash 简介](/tiflash/tiflash-overview.md) +- [创建 TiFlash 副本](/tiflash/create-tiflash-replicas.md) +- [使用 TiFlash](/tiflash/use-tidb-to-read-tiflash.md) +- [使用 MPP 模式](/tiflash/use-tiflash-mpp-mode.md) +- [支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md) diff --git a/tidb-cloud/tidb-cloud-import-local-files.md b/tidb-cloud/tidb-cloud-import-local-files.md new file mode 100644 index 000000000000..4c6b12a34865 --- /dev/null +++ b/tidb-cloud/tidb-cloud-import-local-files.md @@ -0,0 +1,140 @@ +--- +title: 将本地文件导入到 TiDB Cloud Serverless +summary: 了解如何将本地文件导入到 TiDB Cloud Serverless。 +--- + +# 将本地文件导入到 TiDB Cloud Serverless + +你可以直接将本地文件导入到 TiDB Cloud Serverless。只需点击几下即可完成任务配置,然后你的本地 CSV 数据将快速导入到你的 TiDB 集群。使用此方法,你无需提供云存储和凭证。整个导入过程快速流畅。 + +目前,此方法支持在一个任务中将一个 CSV 文件导入到一个空的现有表或新表中。 + +## 限制 + +- 目前,TiDB Cloud 仅支持在一个任务中导入大小在 250 MiB 以内的 CSV 格式本地文件。 +- 导入本地文件仅支持 TiDB Cloud Serverless 集群,不支持 TiDB Cloud Dedicated 集群。 +- 你不能同时运行多个导入任务。 + +## 导入本地文件 + +1. 打开目标集群的**导入**页面。 + + 1. 登录 [TiDB Cloud 控制台](https://tidbcloud.com/),导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + + 2. 点击目标集群的名称进入其概览页面,然后在左侧导航栏中点击**数据** > **导入**。 + +2. 在**导入**页面,你可以直接将本地文件拖放到上传区域,或点击**上传本地文件**选择并上传目标本地文件。注意,一个任务只能上传一个小于 250 MiB 的 CSV 文件。如果你的本地文件大于 250 MiB,请参见[如何导入大于 250 MiB 的本地文件?](#如何导入大于-250-mib-的本地文件)。 + +3. 在**目标**部分,选择目标数据库和目标表,或直接输入名称创建新的数据库或新表。名称只能包含 Unicode BMP(基本多语言平面)中的字符,不包括空字符 `\u0000` 和空白字符,长度最多为 64 个字符。点击**定义表**,将显示**表定义**部分。 + +4. 检查表。 + + 你可以看到可配置的表列列表。每行显示 TiDB Cloud 推断的表列名、推断的表列类型以及 CSV 文件中的预览数据。 + + - 如果你将数据导入到 TiDB Cloud 中的现有表,列列表是从表定义中提取的,预览数据通过列名映射到相应的列。 + + - 如果你要创建新表,列列表是从 CSV 文件中提取的,列类型由 TiDB Cloud 推断。例如,如果预览数据都是整数,推断的列类型将是整数。 + +5. 配置列名和数据类型。 + + 如果 CSV 文件中的第一行记录了列名,请确保选中**使用第一行作为列名**,该选项默认是选中的。 + + 如果 CSV 文件没有列名行,请不要选中**使用第一行作为列名**。在这种情况下: + + - 如果目标表已存在,CSV 文件中的列将按顺序导入到目标表中。多余的列将被截断,缺少的列将填充默认值。 + + - 如果你需要 TiDB Cloud 创建目标表,请为每列输入名称。列名必须满足以下要求: + + * 名称必须由 Unicode BMP 中的字符组成,不包括空字符 `\u0000` 和空白字符。 + * 名称长度必须小于 65 个字符。 + + 如果需要,你也可以更改数据类型。 + + > **注意:** + > + > 当你将 CSV 文件导入到 TiDB Cloud 中的现有表,且目标表的列数多于源文件时,多余的列的处理方式取决于具体情况: + > - 如果多余的列不是主键或唯一键,不会报错。相反,这些多余的列将填充其[默认值](/data-type-default-values.md)。 + > - 如果多余的列是主键或唯一键,且没有 `auto_increment` 或 `auto_random` 属性,将会报错。在这种情况下,建议你选择以下策略之一: + > - 提供包含这些主键或唯一键列的源文件。 + > - 修改目标表的主键和唯一键列以匹配源文件中的现有列。 + > - 将主键或唯一键列的属性设置为 `auto_increment` 或 `auto_random`。 + +6. 对于新的目标表,你可以设置主键。你可以选择一列作为主键,或选择多列创建复合主键。复合主键将按照你选择列名的顺序形成。 + + > **注意:** + > + > 表的主键是聚簇索引,创建后不能删除。 + +7. 如果需要,编辑 CSV 配置。 + + 你还可以点击**编辑 CSV 配置**来配置反斜杠转义、分隔符和定界符,以实现更精细的控制。有关 CSV 配置的更多信息,请参见 [CSV 导入数据配置](/tidb-cloud/csv-config-for-import-data.md)。 + +8. 点击**开始导入**。 + + 你可以在**导入任务详情**页面查看导入进度。如果有警告或失败的任务,你可以查看详情并解决它们。 + +9. 导入任务完成后,你可以点击**使用 SQL 编辑器探索数据**来查询导入的数据。有关如何使用 SQL 编辑器的更多信息,请参见[使用 AI 辅助的 SQL 编辑器探索数据](/tidb-cloud/explore-data-with-chat2query.md)。 + +10. 在**导入**页面,你可以在**操作**列中点击 **...** > **查看**来检查导入任务详情。 + +## 常见问题 + +### 我可以只使用 TiDB Cloud 的导入功能导入指定的列吗? + +不可以。目前,使用导入功能时,你只能将 CSV 文件的所有列导入到现有表中。 + +要只导入指定的列,你可以使用 MySQL 客户端连接你的 TiDB 集群,然后使用 [`LOAD DATA`](https://docs.pingcap.com/tidb/stable/sql-statement-load-data) 指定要导入的列。例如: + +```sql +CREATE TABLE `import_test` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(64) NOT NULL, + `address` varchar(64) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB; +LOAD DATA LOCAL INFILE 'load.txt' INTO TABLE import_test FIELDS TERMINATED BY ',' (name, address); +``` + +如果你使用 `mysql` 并遇到 `ERROR 2068 (HY000): LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.`,你可以在连接字符串中添加 `--local-infile=true`。 + +### 为什么导入数据到 TiDB Cloud 后无法查询带有保留关键字的列? + +如果列名是 TiDB 中的保留[关键字](/keywords.md),当你查询该列时,需要添加反引号 `` ` `` 来包围列名。例如,如果列名是 `order`,你需要使用 `` `order` `` 来查询该列。 + +### 如何导入大于 250 MiB 的本地文件? + +如果文件大于 250 MiB,你可以使用 [TiDB Cloud CLI](/tidb-cloud/get-started-with-cli.md) 来导入文件。更多信息,请参见 [`ticloud serverless import start`](/tidb-cloud/ticloud-import-start.md)。 + +或者,你可以使用 `split [-l ${line_count}]` 工具将其分割成多个较小的文件(仅适用于 Linux 或 macOS)。例如,运行 `split -l 100000 tidb-01.csv small_files` 将名为 `tidb-01.csv` 的文件按行长度 `100000` 分割,分割后的文件命名为 `small_files${suffix}`。然后,你可以将这些较小的文件逐个导入到 TiDB Cloud。 + +参考以下脚本: + +```bash +#!/bin/bash +n=$1 +file_path=$2 +file_extension="${file_path##*.}" +file_name="${file_path%.*}" +total_lines=$(wc -l < $file_path) +lines_per_file=$(( (total_lines + n - 1) / n )) +split -d -a 1 -l $lines_per_file $file_path $file_name. +for (( i=0; i<$n; i++ )) +do + mv $file_name.$i $file_name.$i.$file_extension +done +``` + +你可以输入 `n` 和文件名,然后运行脚本。脚本将文件平均分成 `n` 份,同时保持原始文件扩展名。例如: + +```bash +> sh ./split.sh 3 mytest.customer.csv +> ls -h | grep mytest +mytest.customer.0.csv +mytest.customer.1.csv +mytest.customer.2.csv +mytest.customer.csv +``` diff --git a/tidb-cloud/tidb-cloud-intro.md b/tidb-cloud/tidb-cloud-intro.md new file mode 100644 index 000000000000..dd5ebe66c143 --- /dev/null +++ b/tidb-cloud/tidb-cloud-intro.md @@ -0,0 +1,91 @@ +--- +title: 什么是 TiDB Cloud +summary: 了解 TiDB Cloud 及其架构。 +category: intro +--- + +# 什么是 TiDB Cloud + +[TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 是一个全托管的数据库即服务(DBaaS),它将开源的混合事务和分析处理(HTAP)数据库 [TiDB](https://docs.pingcap.com/tidb/stable/overview) 带入云端。TiDB Cloud 提供了一种简单的方式来部署和管理数据库,让您可以专注于应用程序开发,而不是数据库的复杂性。您可以创建 TiDB Cloud 集群,在 Amazon Web Services (AWS)、Google Cloud 和 Microsoft Azure 上快速构建关键任务应用。 + +![TiDB Cloud 概览](/media/tidb-cloud/tidb-cloud-overview.png) + +## 为什么选择 TiDB Cloud + +TiDB Cloud 使您无需或仅需少量培训就能轻松处理复杂的任务,如基础设施管理和集群部署。 + +- 开发人员和数据库管理员(DBA)可以轻松处理大量在线流量,并快速分析跨多个数据集的大量数据。 + +- 各种规模的企业都可以轻松部署和管理 TiDB Cloud,无需预付费用即可适应业务增长。 + +观看以下视频了解更多关于 TiDB Cloud 的信息: + + + +使用 TiDB Cloud,您可以获得以下关键特性: + +- **快速且可定制的扩展** + + 在保持 ACID 事务的同时,可以弹性且透明地扩展到数百个节点以支持关键工作负载。无需考虑分片。您可以根据业务需求分别扩展性能节点和存储节点。 + +- **MySQL 兼容性** + + 借助 TiDB 的 MySQL 兼容性,提高生产力并缩短应用程序的上市时间。无需重写代码即可轻松从现有 MySQL 实例迁移数据。 + +- **高可用性和可靠性** + + 设计上天然具备高可用性。跨多个可用区的数据复制、每日备份和自动故障转移确保业务连续性,无论是硬件故障、网络分区还是数据中心故障。 + +- **实时分析** + + 通过内置分析引擎获得实时分析查询结果。TiDB Cloud 可以在不影响关键任务应用的情况下,对当前数据运行一致的分析查询。 + +- **企业级安全** + + 在专用网络和机器中保护您的数据,支持传输中和静态数据加密。TiDB Cloud 已通过 SOC 2 Type 2、ISO 27001:2013、ISO 27701 认证,并完全符合 GDPR。 + +- **全托管服务** + + 通过易于使用的基于 Web 的管理平台,只需点击几下即可部署、扩展、监控和管理 TiDB 集群。 + +- **多云支持** + + 保持灵活性,避免云厂商锁定。TiDB Cloud 目前可在 AWS、Azure 和 Google Cloud 上使用。 + +- **简单的定价方案** + + 只需为您使用的部分付费,价格透明且无隐藏费用。 + +- **世界级支持** + + 通过我们的支持门户、电子邮件、聊天或视频会议获得世界级支持。 + +## 部署选项 + +TiDB Cloud 提供以下两种部署选项: + +- [TiDB Cloud Serverless](https://www.pingcap.com/tidb-cloud-serverless) + + TiDB Cloud Serverless 是一个全托管的多租户 TiDB 产品。它提供即时、自动扩展的 MySQL 兼容数据库,并提供慷慨的免费额度,超出免费限制后按使用量计费。 + +- [TiDB Cloud Dedicated](https://www.pingcap.com/tidb-cloud-dedicated) + + TiDB Cloud Dedicated 适用于生产环境,具有跨可用区高可用性、水平扩展和 [HTAP](https://en.wikipedia.org/wiki/Hybrid_transactional/analytical_processing) 的优势。 + +有关 TiDB Cloud Serverless 和 TiDB Cloud Dedicated 的功能比较,请参阅 [TiDB:先进的开源分布式 SQL 数据库](https://www.pingcap.com/get-started-tidb)。 + +## 架构 + +![TiDB Cloud 架构](/media/tidb-cloud/tidb-cloud-architecture.png) + +- TiDB VPC(虚拟私有云) + + 对于每个 TiDB Cloud 集群,所有 TiDB 节点和辅助节点(包括 TiDB Operator 节点和日志节点)都部署在同一个 VPC 中。 + +- TiDB Cloud 中央服务 + + 中央服务(包括计费、告警、元数据存储、仪表板 UI)是独立部署的。您可以通过互联网访问仪表板 UI 来操作 TiDB 集群。 + +- 您的 VPC + + 您可以通过私有端点连接或 VPC 对等连接来连接您的 TiDB 集群。详情请参阅[设置私有端点连接](/tidb-cloud/set-up-private-endpoint-connections.md)或[设置 VPC 对等连接](/tidb-cloud/set-up-vpc-peering-connections.md)。 diff --git a/tidb-cloud/tidb-cloud-migration-overview.md b/tidb-cloud/tidb-cloud-migration-overview.md new file mode 100644 index 000000000000..6ec575c6f4c0 --- /dev/null +++ b/tidb-cloud/tidb-cloud-migration-overview.md @@ -0,0 +1,66 @@ +--- +title: 数据迁移和导入概览 +summary: 了解 TiDB Cloud 的数据迁移和导入场景概览。 +aliases: ['/tidbcloud/export-data-from-tidb-cloud'] +--- + +# 数据迁移和导入概览 + +你可以将数据从各种数据源迁移到 TiDB Cloud。本文档概述了数据迁移的场景。 + +## 从 MySQL 兼容的数据库迁移数据 + +当你从 MySQL 兼容的数据库迁移数据时,你可以执行全量数据迁移和增量数据迁移。迁移场景和方法如下: + +- 使用数据迁移工具迁移 MySQL 兼容的数据库 + + TiDB 与 MySQL 高度兼容。你可以使用 TiDB Cloud 控制台中的数据迁移工具从任何 MySQL 兼容的数据库顺利迁移数据到 TiDB Cloud。更多信息,请参见[使用数据迁移工具将 MySQL 兼容的数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md)。 + +- 使用 AWS DMS 迁移 + + 如果你想迁移异构数据库(如 PostgreSQL、Oracle 和 SQL Server)到 TiDB Cloud,建议使用 AWS Database Migration Service (AWS DMS)。 + + - [使用 AWS DMS 将 MySQL 兼容的数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-aws-dms.md) + - [使用 AWS DMS 从 Amazon RDS for Oracle 迁移](/tidb-cloud/migrate-from-oracle-using-aws-dms.md) + +- 迁移和合并 MySQL 分片 + + 如果你的应用程序使用 MySQL 分片存储数据,你可以将这些分片作为一个表迁移到 TiDB Cloud。更多信息,请参见[将大数据集的 MySQL 分片迁移和合并到 TiDB Cloud](/tidb-cloud/migrate-sql-shards.md)。 + +- 从 TiDB 自托管迁移 + + 你可以通过 Dumpling 和 TiCDC 将数据从 TiDB 自托管集群迁移到 TiDB Cloud (AWS)。更多信息,请参见[从 TiDB 自托管迁移到 TiDB Cloud](/tidb-cloud/migrate-from-op-tidb.md)。 + +## 从文件导入数据到 TiDB Cloud + +如果你有 SQL、CSV、Parquet 或 Aurora 快照格式的数据文件,你可以一次性将这些文件导入到 TiDB Cloud。导入场景和方法如下: + +- 将本地 CSV 文件导入到 TiDB Cloud + + 你可以将本地 CSV 文件导入到 TiDB Cloud。更多信息,请参见[将本地文件导入到 TiDB Cloud](/tidb-cloud/tidb-cloud-import-local-files.md)。 + +- 将示例数据(SQL 文件)导入到 TiDB Cloud + + 你可以将示例数据(SQL 文件)导入到 TiDB Cloud,以快速熟悉 TiDB Cloud 界面和导入过程。更多信息,请参见[将示例数据导入到 TiDB Cloud Serverless](/tidb-cloud/import-sample-data-serverless.md) 和[将示例数据导入到 TiDB Cloud Dedicated](/tidb-cloud/import-sample-data.md)。 + +- 从 Amazon S3、Google Cloud Storage (GCS) 或 Azure Blob Storage 将 CSV 文件导入到 TiDB Cloud + + 你可以从 Amazon S3、Google Cloud Storage (GCS) 或 Azure Blob Storage 将 CSV 文件导入到 TiDB Cloud。更多信息,请参见[从云存储将 CSV 文件导入到 TiDB Cloud Serverless](/tidb-cloud/import-csv-files-serverless.md) 和[从云存储将 CSV 文件导入到 TiDB Cloud Dedicated](/tidb-cloud/import-csv-files.md)。 + +- 从 Amazon S3、Google Cloud Storage (GCS) 或 Azure Blob Storage 将 Apache Parquet 文件导入到 TiDB Cloud + + 你可以从 Amazon S3、Google Cloud Storage (GCS) 或 Azure Blob Storage 将 Parquet 文件导入到 TiDB Cloud。更多信息,请参见[从云存储将 Apache Parquet 文件导入到 TiDB Cloud Serverless](/tidb-cloud/import-parquet-files-serverless.md) 和[从云存储将 Apache Parquet 文件导入到 TiDB Cloud Dedicated](/tidb-cloud/import-parquet-files.md)。 + +## 参考 + +### 配置云存储访问 + +如果你的源数据存储在 Amazon S3、Google Cloud Storage (GCS) 存储桶或 Azure Blob Storage 容器中,在将数据导入或迁移到 TiDB Cloud 之前,你需要配置对存储的访问。更多信息,请参见[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md) 和[为 TiDB Cloud Dedicated 配置外部存储访问](/tidb-cloud/dedicated-external-storage.md)。 + +### 数据导入的命名规范 + +为确保你的数据能够成功导入,你需要准备符合命名规范的架构文件和数据文件。更多信息,请参见[数据导入的命名规范](/tidb-cloud/naming-conventions-for-data-import.md)。 + +### 排查从 Amazon S3 导入数据时的访问被拒绝错误 + +你可以排查从 Amazon S3 导入数据到 TiDB Cloud 时可能出现的访问被拒绝错误。更多信息,请参见[排查从 Amazon S3 导入数据时的访问被拒绝错误](/tidb-cloud/troubleshoot-import-access-denied-error.md)。 diff --git a/tidb-cloud/tidb-cloud-org-sso-authentication.md b/tidb-cloud/tidb-cloud-org-sso-authentication.md new file mode 100644 index 000000000000..e1e4dd67db56 --- /dev/null +++ b/tidb-cloud/tidb-cloud-org-sso-authentication.md @@ -0,0 +1,251 @@ +--- +title: 组织 SSO 认证 +summary: 了解如何通过自定义组织认证登录 TiDB Cloud 控制台。 +--- + +# 组织 SSO 认证 + +单点登录(SSO)是一种认证方案,使您的 TiDB Cloud [组织](/tidb-cloud/tidb-cloud-glossary.md#organization)中的成员能够使用身份提供商(IdP)的身份而不是电子邮件地址和密码登录 TiDB Cloud。 + +TiDB Cloud 支持以下两种 SSO 认证: + +- [标准 SSO](/tidb-cloud/tidb-cloud-sso-authentication.md):成员可以使用 GitHub、Google 或 Microsoft 认证方法登录 [TiDB Cloud 控制台](https://tidbcloud.com/)。标准 SSO 默认为 TiDB Cloud 中的所有组织启用。 + +- 云组织 SSO:成员可以使用组织指定的认证方法登录 TiDB Cloud 的自定义登录页面。云组织 SSO 默认是禁用的。 + +与标准 SSO 相比,云组织 SSO 提供了更多的灵活性和自定义选项,以便您更好地满足组织的安全性和合规性要求。例如,您可以指定登录页面上显示哪些认证方法,限制允许登录的电子邮件域名,并让您的成员使用采用 [OpenID Connect (OIDC)](https://openid.net/connect/) 或 [Security Assertion Markup Language (SAML)](https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language) 身份协议的身份提供商(IdP)登录 TiDB Cloud。 + +在本文中,您将了解如何将组织的认证方案从标准 SSO 迁移到云组织 SSO。 + +> **注意:** +> +> 云组织 SSO 功能仅适用于付费组织。 + +## 开始之前 + +在迁移到云组织 SSO 之前,请检查并确认本节中有关您组织的项目。 + +> **注意:** +> +> - 一旦启用云组织 SSO,就无法禁用。 +> - 要启用云组织 SSO,您需要具有 TiDB Cloud 组织的 `Organization Owner` 角色。有关角色的更多信息,请参见[用户角色](/tidb-cloud/manage-user-access.md#user-roles)。 + +### 决定组织的 TiDB Cloud 登录页面的自定义 URL + +启用云组织 SSO 后,您的成员必须使用您的自定义 URL 而不是公共登录 URL(`https://tidbcloud.com`)登录 TiDB Cloud。 + +自定义 URL 在启用后无法更改,因此您需要提前决定要使用的 URL。 + +自定义 URL 的格式为 `https://tidbcloud.com/enterprise/signin/your-company-name`,其中您可以自定义公司名称。 + +### 决定组织成员的认证方法 + +TiDB Cloud 为组织 SSO 提供以下认证方法: + +- 用户名和密码 +- Google +- GitHub +- Microsoft +- OIDC +- SAML + +启用云组织 SSO 时,前四种方法默认是启用的。如果您想强制组织使用 SSO,可以禁用用户名和密码认证方法。 + +所有启用的认证方法都将显示在您的自定义 TiDB Cloud 登录页面上,因此您需要提前决定要启用或禁用哪些认证方法。 + +### 决定是否启用自动配置 + +自动配置是一项功能,允许成员自动加入组织,而无需 `Organization Owner` 或 `Project Owner` 的邀请。在 TiDB Cloud 中,所有支持的认证方法默认都禁用了此功能。 + +- 当某个认证方法禁用自动配置时,只有被 `Organization Owner` 或 `Project Owner` 邀请的用户才能登录您的自定义 URL。 +- 当某个认证方法启用自动配置时,任何使用该认证方法的用户都可以登录您的自定义 URL。登录后,他们会自动被分配组织内的默认**成员**角色。 + +出于安全考虑,如果您选择启用自动配置,建议在[配置认证方法详情](#步骤-2-配置认证方法)时限制允许的电子邮件域名。 + +### 通知成员有关云组织 SSO 迁移计划 + +在启用云组织 SSO 之前,请确保通知您的成员以下内容: + +- TiDB Cloud 的自定义登录 URL +- 何时开始使用自定义登录 URL 而不是 `https://tidbcloud.com` 登录 +- 可用的认证方法 +- 成员是否需要邀请才能登录自定义 URL + +## 步骤 1. 启用云组织 SSO + +要启用云组织 SSO,请执行以下步骤: + +1. 以具有 `Organization Owner` 角色的用户身份登录 [TiDB Cloud 控制台](https://tidbcloud.com),然后使用左上角的组合框切换到目标组织。 +2. 在左侧导航栏中,点击**组织设置** > **认证**。 +3. 在**认证**页面上,点击**启用**。 +4. 在对话框中,输入组织的自定义 URL,该 URL 在 TiDB Cloud 中必须是唯一的。 + + > **注意:** + > + > 一旦启用云组织 SSO,URL 就无法更改。您组织中的成员只能使用您的自定义 URL 登录 TiDB Cloud。如果您以后需要更改配置的 URL,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +5. 点击**我理解并确认**复选框,然后点击**启用**。 + + > **注意:** + > + > 如果对话框包含需要为云组织 SSO 重新邀请和重新加入的用户列表,TiDB Cloud 将在您启用云组织 SSO 后自动向这些用户发送邀请电子邮件。收到邀请电子邮件后,每个用户需要点击电子邮件中的链接验证其身份,然后会显示自定义登录页面。 + +## 步骤 2. 配置认证方法 + +在 TiDB Cloud 中启用认证方法允许使用该方法的成员使用您的自定义 URL 登录 TiDB Cloud。 + +### 配置用户名和密码、Google、GitHub 或 Microsoft 认证方法 + +启用云组织云后,您可以按如下方式配置用户名和密码、Google、GitHub 或 Microsoft 认证方法: + +1. 在**组织设置**页面上,根据需要启用或禁用 Google、GitHub 或 Microsoft 认证方法。 +2. 对于已启用的认证方法,您可以点击 配置方法详情。 +3. 在方法详情中,您可以配置以下内容: + + - [**自动配置账户**](#决定是否启用自动配置) + + 默认禁用。您可以根据需要启用它。出于安全考虑,如果您选择启用自动配置,建议限制允许的电子邮件域名进行认证。 + + - **允许的电子邮件域名** + + 配置此字段后,只有使用此认证方法的指定电子邮件域名才能使用自定义 URL 登录 TiDB Cloud。填写域名时,需要排除 `@` 符号,并用逗号分隔。例如,`company1.com,company2.com`。 + + > **注意:** + > + > 如果您已配置电子邮件域名,在保存设置之前,请确保添加您当前用于登录的电子邮件域名,以避免被 TiDB Cloud 锁定。 + +4. 点击**保存**。 + +### 配置 OIDC 认证方法 + +如果您有使用 OIDC 身份协议的身份提供商,可以启用 OIDC 认证方法进行 TiDB Cloud 登录。 + +在 TiDB Cloud 中,OIDC 认证方法默认是禁用的。启用云组织云后,您可以按如下方式启用和配置 OIDC 认证方法: + +1. 从您的身份提供商获取以下信息用于 TiDB Cloud 组织 SSO: + + - 发行者 URL + - 客户端 ID + - 客户端密钥 + +2. 在**组织设置**页面上,点击**认证**标签,找到**认证方法**区域中的 OIDC 行,然后点击 显示 OIDC 方法详情。 +3. 在方法详情中,您可以配置以下内容: + + - **名称** + + 为要在自定义登录页面上显示的 OIDC 认证方法指定名称。 + + - **发行者 URL**、**客户端 ID** 和**客户端密钥** + + 粘贴从您的 IdP 获取的相应值。 + + - [**自动配置账户**](#决定是否启用自动配置) + + 默认禁用。您可以根据需要启用它。出于安全考虑,如果您选择启用自动配置,建议限制允许的电子邮件域名进行认证。 + + - **允许的电子邮件域名** + + 配置此字段后,只有使用此认证方法的指定电子邮件域名才能使用自定义 URL 登录 TiDB Cloud。填写域名时,需要排除 `@` 符号,并用逗号分隔。例如,`company1.com,company2.com`。 + + > **注意:** + > + > 如果您已配置电子邮件域名,在保存设置之前,请确保添加您当前用于登录的电子邮件域名,以避免被 TiDB Cloud 锁定。 + +4. 点击**保存**。 + +### 配置 SAML 认证方法 + +如果您有使用 SAML 身份协议的身份提供商,可以启用 SAML 认证方法进行 TiDB Cloud 登录。 + +> **注意:** +> +> TiDB Cloud 使用电子邮件地址作为不同用户的唯一标识符。因此,请确保在您的身份提供商中为组织成员配置了 `email` 属性。 + +在 TiDB Cloud 中,SAML 认证方法默认是禁用的。启用云组织云后,您可以按如下方式启用和配置 SAML 认证方法: + +1. 从您的身份提供商获取以下信息用于 TiDB Cloud 组织 SSO: + + - 登录 URL + - 签名证书 + +2. 在**组织设置**页面上,点击左侧导航栏中的**认证**标签,找到**认证方法**区域中的 SAML 行,然后点击 显示 SAML 方法详情。 +3. 在方法详情中,您可以配置以下内容: + + - **名称** + + 为要在自定义登录页面上显示的 SAML 认证方法指定名称。 + + - **登录 URL** + + 粘贴从您的 IdP 获取的 URL。 + + - **签名证书** + + 粘贴从您的 IdP 获取的完整签名证书,包括开始行 `---begin certificate---` 和结束行 `---end certificate---`。 + + - [**自动配置账户**](#决定是否启用自动配置) + + 默认禁用。您可以根据需要启用它。出于安全考虑,如果您选择启用自动配置,建议限制允许的电子邮件域名进行认证。 + + - **允许的电子邮件域名** + + 配置此字段后,只有使用此认证方法的指定电子邮件域名才能使用自定义 URL 登录 TiDB Cloud。填写域名时,需要排除 `@` 符号,并用逗号分隔。例如,`company1.com,company2.com`。 + + > **注意:** + > + > 如果您已配置电子邮件域名,在保存设置之前,请确保添加您当前用于登录的电子邮件域名,以避免被 TiDB Cloud 锁定。 + + - **SCIM 配置账户** + + 默认禁用。如果您想从身份提供商集中和自动化 TiDB Cloud 组织用户和组的配置、取消配置和身份管理,可以启用它。有关详细配置步骤,请参见[配置 SCIM 配置](#配置-scim-配置)。 + +4. 点击**保存**。 + +#### 配置 SCIM 配置 + +[跨域身份管理系统(SCIM)](https://www.rfc-editor.org/rfc/rfc7644)是一个开放标准,可自动化身份域和 IT 系统之间的用户身份信息交换。通过配置 SCIM 配置,可以将身份提供商的用户组自动同步到 TiDB Cloud,您可以在 TiDB Cloud 中集中管理这些组的角色。 + +> **注意:** +> +> SCIM 配置只能在 [SAML 认证方法](#配置-saml-认证方法)上启用。 + +1. 在 TiDB Cloud 中,启用 [SAML 认证方法](#配置-saml-认证方法)的 **SCIM 配置账户**选项,然后记录以下信息以供后续使用。 + + - SCIM 连接器基本 URL + - 用户唯一标识符字段 + - 认证模式 + +2. 在您的身份提供商中,为 TiDB Cloud 配置 SCIM 配置。 + + 1. 在您的身份提供商中,为 SAML 应用集成添加 TiDB Cloud 组织的 SCIM 配置。 + + 例如,如果您的身份提供商是 Okta,请参见[为应用集成添加 SCIM 配置](https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_scim.htm)。 + + 2. 将 SAML 应用集成分配给身份提供商中的所需组,以便组中的成员可以访问和使用应用集成。 + + 例如,如果您的身份提供商是 Okta,请参见[将应用集成分配给组](https://help.okta.com/en-us/content/topics/provisioning/lcm/lcm-assign-app-groups.htm)。 + + 3. 将用户组从身份提供商推送到 TiDB Cloud。 + + 例如,如果您的身份提供商是 Okta,请参见[管理组推送](https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-group-push-main.htm)。 + +3. 在 TiDB Cloud 中查看从身份提供商推送的组。 + + 1. 在 [TiDB Cloud 控制台](https://tidbcloud.com)中,使用左上角的组合框切换到目标组织。 + 2. 在左侧导航栏中,点击**组织设置** > **认证**。 + 3. 点击**组**标签。显示从身份提供商同步的组。 + 4. 要查看组中的用户,点击**查看**。 + +4. 在 TiDB Cloud 中,为从身份提供商推送的组授予角色。 + + > **注意:** + > + > 向组授予角色意味着组中的所有成员都获得该角色。如果组包含已在 TiDB Cloud 组织中的成员,这些成员也会获得组的新角色。 + + 1. 要向组授予组织角色,点击**按组织**,然后在**组织角色**列中配置角色。要了解组织角色的权限,请参见[组织角色](/tidb-cloud/manage-user-access.md#organization-roles)。 + 2. 要向组授予项目角色,点击**按项目**,然后在**项目角色**列中配置角色。要了解项目角色的权限,请参见[项目角色](/tidb-cloud/manage-user-access.md#project-roles)。 + +5. 如果您在身份提供商中更改了推送组的成员,这些更改会动态同步到 TiDB Cloud 中的相应组。 + + - 如果在身份提供商的组中添加了新成员,这些成员将获得相应组的角色。 + - 如果从身份提供商的组中删除了某些成员,这些成员也会从 TiDB Cloud 中的相应组中删除。 diff --git a/tidb-cloud/tidb-cloud-partners.md b/tidb-cloud/tidb-cloud-partners.md new file mode 100644 index 000000000000..79f5fc831032 --- /dev/null +++ b/tidb-cloud/tidb-cloud-partners.md @@ -0,0 +1,72 @@ +--- +title: TiDB Cloud 合作伙伴控制台 +summary: 了解作为经销商和托管服务提供商(MSP)如何使用 TiDB Cloud 合作伙伴控制台。 +aliases: ['/tidbcloud/managed-service-provider'] +--- + +# TiDB Cloud 合作伙伴控制台 + +TiDB Cloud 合作伙伴控制台专为专注于 SaaS 解决方案的合作伙伴设计,旨在建立和培养 PingCAP 与合作伙伴之间的强大合作关系,以更好地服务我们的客户。 + +TiDB Cloud 合作伙伴分为两种类型: + +- 经销商:通过 AWS Marketplace Channel Partner Private Offer (CPPO) 转售 TiDB Cloud +- 托管服务提供商(MSP):转售 TiDB Cloud 并提供增值服务 + +## 通过 AWS Channel Partner Private Offer (CPPO) 进行经销 + +通过 [AWS CPPO](https://aws.amazon.com/marketplace/features/cpprivateoffers) 的经销商允许客户直接从经销商通过 AWS Marketplace 购买 TiDB Cloud。这使客户能够受益于合作伙伴的业务知识、本地化支持和专业技能,同时仍然享受他们期望从 AWS Marketplace 获得的快速和无缝的购买体验。 + +### 成为 PingCAP 的经销商 + +如果你对经销商计划感兴趣并希望成为合作伙伴,请[联系销售](https://www.pingcap.com/partners/become-a-partner/)进行注册。 + +### 管理经销商的日常任务 + +作为经销商,你有两种方式来管理日常管理任务: + +- [TiDB Cloud 合作伙伴控制台](https://partner-console.tidbcloud.com) +- 合作伙伴管理 API。你可以在 TiDB Cloud 合作伙伴控制台的**支持**页面找到开放 API 文档。 + +## 托管服务提供商(MSP) + +MSP 是转售 TiDB Cloud 并提供增值服务的合作伙伴,包括但不限于 TiDB Cloud 组织管理、计费服务和技术支持。 + +成为托管服务提供商的好处包括: + +- 折扣和激励计划 +- 赋能培训 +- 通过认证提高知名度 +- 联合营销机会 + +### 成为 PingCAP 的 MSP + +如果你对 MSP 计划感兴趣并希望成为合作伙伴,请[联系销售](https://www.pingcap.com/partners/become-a-partner/)进行注册。请提供以下信息: + +- 公司名称 +- 公司联系邮箱 +- 公司官方网站 URL +- 公司标志(一个用于浅色模式的 SVG 文件和一个用于深色模式的 SVG 文件;建议使用 256 x 48 像素的横向标志) + +上述信息用于为你的客户生成带有你公司标志的专属注册 URL 和页面。 + +我们将仔细评估你的请求并尽快回复。 + +### 管理 MSP 的日常任务 + +作为 TiDB Cloud MSP 合作伙伴,你有两种方法来管理日常管理任务: + +- [TiDB Cloud 合作伙伴控制台](https://partner-console.tidbcloud.com) +- [MSP 管理 API(已弃用)](https://docs.pingcap.com/tidbcloud/api/v1beta1/msp) + +完成 TiDB Cloud 合作伙伴注册后,你将收到一封电子邮件通知,用于激活 TiDB Cloud 合作伙伴控制台中的账户,并收到用于 MSP 管理 API 的 API 密钥。 + +你可以使用 MSP 管理 API 来管理以下日常任务: + +- 查询特定月份的 MSP 月度账单 +- 查询应用于 MSP 的积分 +- 查询应用于 MSP 的折扣 +- 查询特定 MSP 客户的月度账单 +- 为 MSP 客户创建新的注册 URL +- 列出所有 MSP 客户 +- 通过客户组织 ID 检索 MSP 客户信息 diff --git a/tidb-cloud/tidb-cloud-password-authentication.md b/tidb-cloud/tidb-cloud-password-authentication.md new file mode 100644 index 000000000000..d4be1832ff34 --- /dev/null +++ b/tidb-cloud/tidb-cloud-password-authentication.md @@ -0,0 +1,123 @@ +--- +title: 密码认证 +summary: 了解如何在 TiDB Cloud 控制台中管理密码和启用多因素认证(MFA)。 +--- + +# 密码认证 + +本文档介绍如何在 TiDB Cloud 控制台中管理密码和启用多因素认证(MFA)。本文档仅适用于使用邮箱和密码[注册](https://tidbcloud.com/free-trial) TiDB Cloud 的用户。 + +## 注册 + +你可以使用邮箱和密码[注册](https://tidbcloud.com/free-trial) TiDB Cloud,或选择使用 Google、GitHub 或 Microsoft 账号进行单点登录(SSO)。 + +- 如果你使用邮箱和密码注册 TiDB Cloud,可以按照本文档管理密码。 +- 如果你选择使用 Google、GitHub 或 Microsoft SSO 登录 TiDB Cloud,你的密码由所选平台管理,无法使用 TiDB Cloud 控制台更改。 + +要使用邮箱和密码注册 TiDB Cloud 账号,请执行以下步骤: + +1. 访问 TiDB Cloud [注册](https://tidbcloud.com/free-trial)页面并填写注册信息。 + +2. 阅读隐私政策和服务协议,然后选择**我同意隐私政策和服务协议**。 + +3. 点击**注册**。 + +你将收到 TiDB Cloud 的验证邮件。要完成整个注册过程,请检查你的邮箱并确认注册。 + +## 登录或登出 + +### 登录 + +要使用邮箱和密码登录 TiDB Cloud,请执行以下步骤: + +1. 访问 TiDB Cloud [登录](https://tidbcloud.com/)页面。 + +2. 填写你的邮箱和密码。 + +3. 点击**登录**。 + +如果登录成功,你将被引导至 TiDB Cloud 控制台。 + +### 登出 + +在 TiDB Cloud 控制台左下角,点击 并选择**退出登录**。 + +## 密码策略 + +TiDB Cloud 为注册用户设置了默认密码策略。如果你的密码不符合策略要求,在设置密码时会收到提示。 + +默认密码策略如下: + +- 至少 8 个字符长度。 +- 至少包含 1 个大写字母(A-Z)。 +- 至少包含 1 个小写字母(a-z)。 +- 至少包含 1 个数字(0-9)。 +- 新密码不能与前四个密码相同。 + +## 重置密码 + +> **注意:** +> +> 本节仅适用于使用邮箱和密码注册的 TiDB Cloud 用户。如果你使用 Google SSO 或 GitHub SSO 注册 TiDB Cloud,你的密码由 Google 或 GitHub 管理,无法使用 TiDB Cloud 控制台更改。 + +如果你忘记了密码,可以通过邮箱重置密码,步骤如下: + +1. 访问 TiDB Cloud [登录](https://tidbcloud.com/)页面。 + +2. 点击**忘记密码**,然后检查你的邮箱获取重置密码的链接。 + +## 更改密码 + +> **注意:** +> +> 如果你使用邮箱和密码注册 TiDB Cloud,建议每 90 天重置一次密码。否则,当你登录 TiDB Cloud 时,会收到密码过期提醒,提示你更改密码。 + +1. 点击 TiDB Cloud 控制台左下角的 。 + +2. 点击**账号设置**。 + +3. 在**密码**部分,点击**更改密码**,然后检查你的邮箱获取 TiDB Cloud 重置密码的链接。 + +## 管理多因素认证(可选) + +> **注意:** +> +> - 本节仅适用于使用邮箱和密码[注册](https://tidbcloud.com/free-trial) TiDB Cloud 的用户。如果你使用 Google、GitHub 或 Microsoft SSO 注册 TiDB Cloud,你可以在所选身份管理平台上启用 MFA。 +> - 如果你在 SSO 登录场景下启用了 TiDB Cloud MFA,请在 **2025 年 9 月 30 日**之前将 MFA 管理迁移到你的 SSO 身份管理平台,以确保账号安全。 + +多因素认证(MFA)通过要求使用认证器应用程序生成一次性验证码来增加额外的安全性。登录时,TiDB Cloud 会同时验证你的密码和 MFA 验证码。你可以使用 iOS 或 Android 应用商店中的任何认证器应用程序生成此密码,例如 Google Authenticator 和 Authy。 + +### 启用 MFA + +1. 点击 TiDB Cloud 控制台左下角的 。 + +2. 点击**账号设置**。 + +3. 在**多因素认证**部分,点击**启用**。 + +4. 输入你的账号密码以确认身份。 + +5. 在**设置认证器应用程序**部分,使用认证器应用程序扫描二维码并关联你的 MFA 设备。 + +6. 输入应用程序生成的认证码以完成 MFA 设备关联。 + +7. 保存一次性恢复码,当你的 MFA 设备不可用时,可以使用该恢复码进行认证。 + +> **注意:** +> +> - 你需要安全地存储恢复码以维护账号安全。 +> - 如果你在登录时使用恢复码进行 MFA 验证,系统会在验证成功后自动生成新的恢复码。 + +### 禁用 MFA + +1. 点击 TiDB Cloud 控制台左下角的 。 + +2. 点击**账号设置**。 + +3. 在**多因素认证**部分,点击**禁用**。 + +4. 输入你的账号密码和 MFA 认证码以确认操作。 + +> **注意:** +> +> 禁用 MFA 会降低你的账号安全性。请谨慎操作。 diff --git a/tidb-cloud/tidb-cloud-performance-reference.md b/tidb-cloud/tidb-cloud-performance-reference.md new file mode 100644 index 000000000000..d5062aa53abb --- /dev/null +++ b/tidb-cloud/tidb-cloud-performance-reference.md @@ -0,0 +1,166 @@ +--- +title: TiDB Cloud 性能参考 +summary: 了解 TiDB Cloud 性能测试结果。 +--- + +# TiDB Cloud 性能参考 + +本文档提供了不同规模 TiDB 集群的 [Sysbench](https://github.com/akopytov/sysbench) 性能测试结果,可作为您[确定集群规模](/tidb-cloud/size-your-cluster.md)时的参考。 + +> **注意:** +> +> 测试在 TiDB v6.1.1 上执行,测试结果基于 P95 事务延迟低于 105 毫秒的条件。 + +以下是 Sysbench 配置文件示例: + +```txt +mysql-host={TIDB_HOST} +mysql-port=4000 +mysql-user=root +mysql-password=password +mysql-db=sbtest +time=1200 +threads={100} +report-interval=10 +db-driver=mysql +mysql-ignore-errors=1062,2013,8028,9002,9007 +auto-inc=false +``` + +在本文档中,事务模型 `Read Only`、`Read Write` 和 `Write Only` 分别代表读工作负载、混合工作负载和写工作负载。 + +## 4 vCPU 性能 + +测试规模: + +- TiDB (4 vCPU, 16 GiB) \* 1;TiKV (4 vCPU, 16 GiB) \* 3 +- TiDB (4 vCPU, 16 GiB) \* 2;TiKV (4 vCPU, 16 GiB) \* 3 + +测试结果: + +**TiDB (4 vCPU, 16 GiB) \* 1;TiKV (4 vCPU, 16 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|----------|----------|------------------|------------------| +| Read Only | 35 | 8,064.89 | 504.06 | 69.43 | 104.84 | +| Read Write | 25 | 6,747.60 | 337.38 | 74.10 | 102.97 | +| Write Only | 90 | 8,805.21 | 1,467.53 | 61.32 | 99.33 | + +**TiDB (4 vCPU, 16 GiB) \* 2;TiKV (4 vCPU, 16 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|-----------|----------|------------------|------------------| +| Read Only | 65 | 16,805.76 | 1,050.36 | 61.88 | 95.81 | +| Read Write | 45 | 12,940.36 | 647.02 | 69.55 | 99.33 | +| Write Only | 200 | 19,265.93 | 3,210.99 | 62.28 | 102.97 | + +## 8 vCPU 性能 + +测试规模: + +- TiDB (8 vCPU, 16 GiB) \* 2;TiKV (8 vCPU, 32 GiB) \* 3 +- TiDB (8 vCPU, 16 GiB) \* 4;TiKV (8 vCPU, 32 GiB) \* 3 +- TiDB (8 vCPU, 16 GiB) \* 4;TiKV (8 vCPU, 32 GiB) \* 6 +- TiDB (8 vCPU, 16 GiB) \* 6;TiKV (8 vCPU, 32 GiB) \* 9 +- TiDB (8 vCPU, 16 GiB) \* 9;TiKV (8 vCPU, 32 GiB) \* 6 +- TiDB (8 vCPU, 16 GiB) \* 12;TiKV (8 vCPU, 32 GiB) \* 9 + +测试结果: + +**TiDB (8 vCPU, 16 GiB) \* 2;TiKV (8 vCPU, 32 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|-----------|----------|------------------|------------------| +| Read Only | 150 | 37,863.64 | 2,366.48 | 63.38 | 99.33 | +| Read Write | 100 | 30,218.42 | 1,510.92 | 66.18 | 94.10 | +| Write Only | 350 | 30,763.72 | 5,127.29 | 68.26 | 104.84 | + +**TiDB (8 vCPU, 16 GiB) \* 4;TiKV (8 vCPU, 32 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|-----------|----------|------------------|------------------| +| Read Only | 300 | 74,190.40 | 4,636.90 | 64.69 | 104.84 | +| Read Write | 200 | 53,351.84 | 2,667.59 | 74.97 | 97.55 | +| Write Only | 400 | 36,036.40 | 5,926.66 | 67.49 | 95.81 | + +**TiDB (8 vCPU, 16 GiB) \* 4;TiKV (8 vCPU, 32 GiB) \* 6** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|-----------|-----------|------------------|------------------| +| Read Only | 300 | 75,713.04 | 4,732.06 | 63.39 | 102.97 | +| Read Write | 200 | 62,640.62 | 3,132.03 | 63.85 | 95.81 | +| Write Only | 750 | 73,840.22 | 12,306.70 | 60.93 | 104.84 | + +**TiDB (8 vCPU, 16 GiB) \* 6;TiKV (8 vCPU, 32 GiB) \* 9** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|------------|-----------|------------------|------------------| +| Read Only | 450 | 113,407.94 | 7,088.00 | 63.48 | 104.84 | +| Read Write | 300 | 92,387.31 | 4,619.37 | 64.93 | 99.33 | +| Write Only | 1100 | 112,631.72 | 18,771.95 | 58.59 | 99.33 | + +**TiDB (8 vCPU, 16 GiB) \* 9;TiKV (8 vCPU, 32 GiB) \* 6** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|------------|-----------|------------------|------------------| +| Read Only | 650 | 168,486.65 | 10,530.42 | 61.72 | 101.13 | +| Read Write | 400 | 106,853.63 | 5,342.68 | 74.86 | 101.13 | +| Write Only | 950 | 88,461.20 | 14,743.53 | 64.42 | 102.97 | + +**TiDB (8 vCPU, 16 GiB) \* 12;TiKV (8 vCPU, 32 GiB) \* 9** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|------------|-----------|------------------|------------------| +| Read Only | 800 | 211,882.77 | 13,242.67 | 60.40 | 101.13 | +| Read Write | 550 | 139,393.46 | 6,969.67 | 78.90 | 104.84 | +| Write Only | 1500 | 139,330.14 | 23,221.69 | 64.58 | 99.33 | + +## 16 vCPU 性能 + +测试规模: + +- TiDB (16 vCPU, 32 GiB) \* 1;TiKV (16 vCPU, 64 GiB) \* 3 +- TiDB (16 vCPU, 32 GiB) \* 2;TiKV (16 vCPU, 64 GiB) \* 3 + +测试结果: + +**TiDB (16 vCPU, 32 GiB) \* 1;TiKV (16 vCPU, 64 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|----------|---------|------------------|------------------| +| Read Only | 125 | 37448.41 | 2340.53 | 53.40 | 89.16 | +| Read Write | 100 | 28903.99 | 1445.20 | 69.19 | 104.84 | +| Write Only | 400 | 40878.68 | 6813.11 | 58.71 | 101.13 | + +**TiDB (16 vCPU, 32 GiB) \* 2;TiKV (16 vCPU, 64 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|----------|----------|------------------|------------------| +| Read Only | 300 | 77238.30 | 4827.39 | 62.14 | 102.97 | +| Read Write | 200 | 58241.15 | 2912.06 | 68.67 | 97.55 | +| Write Only | 700 | 68829.89 | 11471.65 | 61.01 | 101.13 | + +## 32 vCPU 性能 + +测试规模: + +- TiDB (32 vCPU, 64 GiB) \* 1;TiKV (32 vCPU, 128 GiB) \* 3 +- TiDB (32 vCPU, 64 GiB) \* 2;TiKV (32 vCPU, 128 GiB) \* 3 + +测试结果: + +**TiDB (32 vCPU, 64 GiB) \* 1;TiKV (32 vCPU, 128 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|----------|---------|------------------|------------------| +| Read Only | 300 | 83941.16 | 5246 | 57.20 | 87.6 | +| Read Write | 250 | 71290.31 | 3565 | 70.10 | 105.0 | +| Write Only | 700 | 72199.56 | 12033 | 58.20 | 101.0 | + +**TiDB (32 vCPU, 64 GiB) \* 2;TiKV (32 vCPU, 128 GiB) \* 3** + +| 事务模型 | 线程数 | QPS | TPS | 平均事务延迟(毫秒) | P95 事务延迟(毫秒) | +|---------|---------|-----------|----------|------------------|------------------| +| Read Only | 650 | 163101.68 | 10194 | 63.8 | 99.3 | +| Read Write | 450 | 123152.74 | 6158 | 73.1 | 101 | +| Write Only | 1200 | 112333.16 | 18722 | 64.1 | 101 | diff --git a/tidb-cloud/tidb-cloud-poc.md b/tidb-cloud/tidb-cloud-poc.md new file mode 100644 index 000000000000..e5469bed7ac7 --- /dev/null +++ b/tidb-cloud/tidb-cloud-poc.md @@ -0,0 +1,231 @@ +--- +title: 使用 TiDB Cloud 进行概念验证(PoC) +summary: 了解如何使用 TiDB Cloud 进行概念验证(PoC)。 +--- + +# 使用 TiDB Cloud 进行概念验证(PoC) + +TiDB Cloud 是一个数据库即服务(DBaaS)产品,它以完全托管的云数据库形式提供 TiDB 的所有优秀特性。它让您能够专注于应用程序开发,而不必关心数据库的复杂性。TiDB Cloud 目前可在 Amazon Web Services (AWS)、Google Cloud 和 Microsoft Azure 上使用。 + +启动概念验证(PoC)是确定 TiDB Cloud 是否最适合您业务需求的最佳方式。它还能帮助您在短时间内熟悉 TiDB Cloud 的主要功能。通过运行性能测试,您可以了解您的工作负载是否能在 TiDB Cloud 上高效运行。您还可以评估数据迁移和配置调整所需的工作量。 + +本文档描述了典型的 PoC 流程,旨在帮助您快速完成 TiDB Cloud PoC。这是经过 TiDB 专家和大量客户验证的最佳实践。 + +如果您有兴趣进行 PoC,欢迎在开始之前联系 PingCAP。支持团队可以帮助您制定测试计划,并指导您顺利完成 PoC 流程。 + +另外,您也可以[创建 TiDB Cloud Serverless 集群](/tidb-cloud/tidb-cloud-quickstart.md#step-1-create-a-tidb-cluster)来快速评估和熟悉 TiDB Cloud。请注意,TiDB Cloud Serverless 有一些[特殊条款和条件](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless-special-terms-and-conditions)。 + +## PoC 流程概述 + +PoC 的目的是测试 TiDB Cloud 是否满足您的业务需求。典型的 PoC 通常持续 14 天,在此期间您需要专注于完成 PoC。 + +典型的 TiDB Cloud PoC 包含以下步骤: + +1. 定义成功标准并制定测试计划 +2. 识别工作负载特征 +3. 注册并创建用于 PoC 的 TiDB Cloud Dedicated 集群 +4. 调整数据库模式和 SQL +5. 导入数据 +6. 运行工作负载并评估结果 +7. 探索更多功能 +8. 清理环境并完成 PoC + +## 步骤 1. 定义成功标准并制定测试计划 + +在通过 PoC 评估 TiDB Cloud 时,建议根据您的业务需求确定关注点和相应的技术评估标准,然后明确您对 PoC 的期望和目标。清晰且可衡量的技术标准和详细的测试计划可以帮助您专注于关键方面,覆盖业务层面的需求,并最终通过 PoC 流程获得答案。 + +使用以下问题帮助确定您的 PoC 目标: + +- 您的工作负载场景是什么? +- 您的业务数据集大小或工作负载是多少?增长率如何? +- 性能要求是什么,包括业务关键的吞吐量或延迟要求? +- 可用性和稳定性要求是什么,包括可接受的最小计划内或计划外停机时间? +- 运营效率的必要指标是什么?如何衡量它们? +- 您的工作负载的安全性和合规性要求是什么? + +有关成功标准和如何制定测试计划的更多信息,请随时联系 PingCAP。 + +## 步骤 2. 识别工作负载特征 + +TiDB Cloud 适用于需要高可用性和强一致性且数据量大的各种使用场景。[TiDB 简介](https://docs.pingcap.com/tidb/stable/overview)列出了主要特性和场景。您可以检查它们是否适用于您的业务场景: + +- 水平扩展或收缩 +- 金融级高可用 +- 实时 HTAP +- 兼容 MySQL 协议和 MySQL 生态系统 + +您可能还对使用 [TiFlash](https://docs.pingcap.com/tidb/stable/tiflash-overview) 感兴趣,这是一个可以加速分析处理的列式存储引擎。在 PoC 期间,您可以随时使用 TiFlash 功能。 + +## 步骤 3. 注册并创建用于 PoC 的 TiDB Cloud Dedicated 集群 + +要创建用于 PoC 的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群,请执行以下步骤: + +1. 通过以下方式之一填写 PoC 申请表: + + - 在 PingCAP 网站上,访问 [Apply for PoC](https://pingcap.com/apply-for-poc/) 页面填写申请表。 + - 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,点击右下角的 **?**,点击 **Contact Sales**,然后选择 **Apply for PoC** 填写申请表。 + + 提交表单后,TiDB Cloud 支持团队将审核您的申请,与您联系,并在申请获批后将积分转入您的账户。您还可以联系 PingCAP 支持工程师协助您的 PoC 流程,以确保 PoC 顺利进行。 + +2. 参考[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)为 PoC 创建 TiDB Cloud Dedicated 集群。 + +在创建集群之前,建议进行容量规划。您可以从估算的 TiDB、TiKV 或 TiFlash 节点数量开始,之后根据性能需求进行扩展。您可以在以下文档中找到更多详细信息,或咨询我们的支持团队。 + +- 有关估算实践的更多信息,请参见[规划 TiDB 集群规模](/tidb-cloud/size-your-cluster.md)。 +- 有关 TiDB Cloud Dedicated 集群的配置,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。分别为 TiDB、TiKV 和 TiFlash(可选)配置集群大小。 +- 有关如何有效规划和优化 PoC 积分消耗,请参见本文档中的 [FAQ](#faq)。 +- 有关扩展的更多信息,请参见[扩展 TiDB 集群](/tidb-cloud/scale-tidb-cluster.md)。 + +创建专用 PoC 集群后,您就可以加载数据并执行一系列测试了。有关如何连接 TiDB 集群,请参见[连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/connect-to-tidb-cluster.md)。 + +对于新创建的集群,请注意以下配置: + +- 默认时区(仪表板上的 **Create Time** 列)是 UTC。您可以按照[设置本地时区](/tidb-cloud/manage-user-access.md#set-the-time-zone-for-your-organization)将其更改为您的本地时区。 +- 新集群的默认备份设置是每日全量数据库备份。您可以指定首选备份时间或手动备份数据。有关默认备份时间和更多详细信息,请参见[备份和恢复 TiDB 集群数据](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup)。 + +## 步骤 4. 调整数据库模式和 SQL + +接下来,您可以将数据库模式加载到 TiDB 集群中,包括表和索引。 + +由于 PoC 积分有限,为了最大化积分价值,建议您创建 [TiDB Cloud Serverless 集群](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)进行兼容性测试和 TiDB Cloud 的初步分析。 + +TiDB Cloud 与 MySQL 8.0 高度兼容。如果您的数据与 MySQL 兼容或可以调整为与 MySQL 兼容,您可以直接将数据导入 TiDB。 + +有关兼容性的更多信息,请参见以下文档: + +- [TiDB 与 MySQL 的兼容性](https://docs.pingcap.com/tidb/stable/mysql-compatibility)。 +- [TiDB 与 MySQL 的不同特性](https://docs.pingcap.com/tidb/stable/mysql-compatibility#features-that-are-different-from-mysql)。 +- [TiDB 的关键字和保留字](https://docs.pingcap.com/tidb/stable/keywords)。 +- [TiDB 限制](https://docs.pingcap.com/tidb/stable/tidb-limitations)。 + +以下是一些最佳实践: + +- 检查模式设置中是否存在效率低下的问题。 +- 删除不必要的索引。 +- 规划有效的分区策略。 +- 避免由右手索引增长导致的[热点问题](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues#identify-hotspot-issues),例如时间戳上的索引。 +- 通过使用 [SHARD_ROW_ID_BITS](https://docs.pingcap.com/tidb/stable/shard-row-id-bits) 和 [AUTO_RANDOM](https://docs.pingcap.com/tidb/stable/auto-random) 避免[热点问题](https://docs.pingcap.com/tidb/stable/troubleshoot-hot-spot-issues#identify-hotspot-issues)。 + +对于 SQL 语句,根据您的数据源与 TiDB 的兼容性级别,您可能需要进行调整。 + +如果您有任何问题,请联系 [PingCAP](/tidb-cloud/tidb-cloud-support.md) 进行咨询。 + +## 步骤 5. 导入数据 + +您可以导入小型数据集来快速测试可行性,或导入大型数据集来测试 TiDB 数据迁移工具的吞吐量。虽然 TiDB 提供示例数据,但强烈建议使用来自您业务的真实工作负载进行测试。 + +您可以将各种格式的数据导入 TiDB Cloud: + +- [使用数据迁移将 MySQL 兼容数据库迁移到 TiDB Cloud](/tidb-cloud/migrate-from-mysql-using-data-migration.md) +- [将本地文件导入 TiDB Cloud](/tidb-cloud/tidb-cloud-import-local-files.md) +- [导入 SQL 文件格式的示例数据](/tidb-cloud/import-sample-data.md) +- [从云存储导入 CSV 文件](/tidb-cloud/import-csv-files.md) +- [导入 Apache Parquet 文件](/tidb-cloud/import-parquet-files.md) + +> **注意:** +> +> **导入**页面上的数据导入不会产生额外的计费费用。 + +## 步骤 6. 运行工作负载并评估结果 + +现在您已经创建了环境、调整了模式并导入了数据。是时候测试您的工作负载了。 + +在测试工作负载之前,考虑执行手动备份,这样在需要时可以将数据库恢复到原始状态。有关更多信息,请参见[备份和恢复 TiDB 集群数据](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup)。 + +启动工作负载后,您可以使用以下方法观察系统: + +- 在集群概览页面上可以找到集群的常用指标,包括总 QPS、延迟、连接数、TiFlash 请求 QPS、TiFlash 请求持续时间、TiFlash 存储大小、TiKV 存储大小、TiDB CPU、TiKV CPU、TiKV IO 读取和 TiKV IO 写入。请参见[监控 TiDB 集群](/tidb-cloud/monitor-tidb-cluster.md)。 +- 导航到集群的[**诊断**](/tidb-cloud/tune-performance.md#view-the-diagnosis-page)页面,然后查看 **SQL Statement** 标签页,您可以在此观察 SQL 执行情况,无需查询系统表即可轻松定位性能问题。请参见[语句分析](/tidb-cloud/tune-performance.md#statement-analysis)。 +- 导航到集群的[**诊断**](/tidb-cloud/tune-performance.md#view-the-diagnosis-page)页面,然后查看 **Key Visualizer** 标签页,您可以在此查看 TiDB 数据访问模式和数据热点。请参见[Key Visualizer](/tidb-cloud/tune-performance.md#key-visualizer)。 +- 您还可以将这些指标集成到您自己的 Datadog 和 Prometheus 中。请参见[第三方监控集成](/tidb-cloud/third-party-monitoring-integrations.md)。 + +现在是评估测试结果的时候了。 + +为了获得更准确的评估,在测试之前确定指标基线,并适当记录每次运行的测试结果。通过分析结果,您可以决定 TiDB Cloud 是否适合您的应用。同时,这些结果表明了系统的运行状态,您可以根据指标调整系统。例如: + +- 评估系统性能是否满足您的要求。检查总 QPS 和延迟。如果系统性能不令人满意,您可以通过以下方式调优性能: + + - 监控和优化网络延迟。 + - 调查和调优 SQL 性能。 + - 监控和[解决热点问题](https://docs.pingcap.com/tidb/dev/troubleshoot-hot-spot-issues#troubleshoot-hotspot-issues)。 + +- 评估存储大小和 CPU 使用率,相应地扩展或收缩 TiDB 集群。有关扩展的详细信息,请参见 [FAQ](#faq) 部分。 + +以下是性能调优的提示: + +- 提高写入性能 + + - 通过扩展 TiDB 集群增加写入吞吐量(请参见[扩展 TiDB 集群](/tidb-cloud/scale-tidb-cluster.md))。 + - 通过使用[乐观事务模型](https://docs.pingcap.com/tidb/stable/optimistic-transaction#tidb-optimistic-transaction-model)减少锁冲突。 + +- 提高查询性能 + + - 在[**诊断**](/tidb-cloud/tune-performance.md#view-the-diagnosis-page)页面的 [**SQL Statement**](/tidb-cloud/tune-performance.md#statement-analysis) 标签页上检查 SQL 执行计划。 + - 在[**诊断**](/tidb-cloud/tune-performance.md#view-the-diagnosis-page)页面的 [**Key Visualizer**](/tidb-cloud/tune-performance.md#key-visualizer) 标签页上检查热点问题。 + - 在[**指标**](/tidb-cloud/built-in-monitoring.md#view-the-metrics-page)页面上监控 TiDB 集群是否容量不足。 + - 使用 TiFlash 功能优化分析处理。请参见[使用 HTAP 集群](/tiflash/tiflash-overview.md)。 + +## 步骤 7. 探索更多功能 + +现在工作负载测试已完成,您可以探索更多功能,例如升级和备份。 + +- 升级 + + TiDB Cloud 定期升级 TiDB 集群,您也可以提交支持工单请求升级集群。请参见[升级 TiDB 集群](/tidb-cloud/upgrade-tidb-cluster.md)。 + +- 备份 + + 为避免供应商锁定,您可以使用每日全量备份将数据迁移到新集群,并使用 [Dumpling](https://docs.pingcap.com/tidb/stable/dumpling-overview) 导出数据。有关更多信息,请参见[备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md#turn-on-auto-backup)和[备份和恢复 TiDB Cloud Serverless 数据](/tidb-cloud/backup-and-restore-serverless.md)。 + +## 步骤 8. 清理环境并完成 PoC + +在使用真实工作负载测试 TiDB Cloud 并获得测试结果后,您已完成了 PoC 的完整周期。这些结果帮助您确定 TiDB Cloud 是否满足您的期望。同时,您也积累了使用 TiDB Cloud 的最佳实践。 + +如果您想在更大规模上尝试 TiDB Cloud,进行新一轮的部署和测试,例如使用 TiDB Cloud 提供的其他节点存储大小进行部署,可以通过创建 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群来获得 TiDB Cloud 的完整访问权限。 + +如果您的积分即将用完,想继续进行 PoC,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)进行咨询。 + +您可以随时结束 PoC 并删除测试环境。有关更多信息,请参见[删除 TiDB 集群](/tidb-cloud/delete-tidb-cluster.md)。 + +我们非常感谢您通过填写 [TiDB Cloud 反馈表](https://www.surveymonkey.com/r/L3VVW8R)向我们的支持团队提供任何反馈,例如 PoC 流程、功能请求以及我们如何改进产品。 + +## FAQ + +### 1. 备份和恢复我的数据需要多长时间? + +TiDB Cloud 提供两种类型的数据库备份:自动备份和手动备份。这两种方法都会备份完整的数据库。 + +备份和恢复数据所需的时间可能会有所不同,这取决于表的数量、镜像副本的数量以及 CPU 密集程度。单个 TiKV 节点的备份和恢复速率约为 50 MB/s。 + +数据库备份和恢复操作通常是 CPU 密集型的,始终需要额外的 CPU 资源。它们可能会对 QPS 和事务延迟产生影响(10% 到 50%),具体取决于环境的 CPU 密集程度。 + +### 2. 什么时候需要扩展和收缩? + +以下是关于扩展的一些考虑因素: + +- 在高峰时段或数据导入期间,如果您观察到仪表板上的容量指标已达到上限(请参见[监控 TiDB 集群](/tidb-cloud/monitor-tidb-cluster.md)),您可能需要扩展集群。 +- 如果您观察到资源使用率持续较低,例如,CPU 使用率仅为 10%-20%,您可以收缩集群以节省资源。 + +您可以在控制台上自行扩展集群。如果您需要收缩集群,需要联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)寻求帮助。有关扩展的更多信息,请参见[扩展 TiDB 集群](/tidb-cloud/scale-tidb-cluster.md)。您可以与支持团队保持联系,跟踪具体进度。由于数据重新平衡可能会影响性能,您必须等待扩展操作完成后再开始测试。 + +### 3. 如何最有效地使用我的 PoC 积分? + +一旦您的 PoC 申请获得批准,您将在账户中收到积分。通常,这些积分足够进行为期 14 天的 PoC。积分按节点类型和节点数量按小时计费。有关更多信息,请参见 [TiDB Cloud 计费](/tidb-cloud/tidb-cloud-billing.md#credits)。 + +要查看 PoC 剩余积分,请转到目标项目的[**集群**](https://tidbcloud.com/project/clusters)页面,如下图所示。 + +![TiDB Cloud PoC 积分](/media/tidb-cloud/poc-points.png) + +或者,您也可以使用 TiDB Cloud 控制台左上角的组合框切换到目标组织,点击左侧导航栏中的**计费**,然后点击**积分**标签页查看积分信息。 + +要节省积分,请删除您不使用的集群。目前,您无法停止集群。在删除集群之前,您需要确保备份是最新的,这样当您想要恢复 PoC 时可以恢复集群。 + +如果在 PoC 流程完成后您仍有未使用的积分,只要这些积分未过期,您可以继续使用它们支付 TiDB 集群费用。 + +### 4. 我可以花超过 2 周的时间完成 PoC 吗? + +如果您想延长 PoC 试用期或积分即将用完,请[联系 PingCAP](https://www.pingcap.com/contact-us/) 寻求帮助。 + +### 5. 我遇到了技术问题。如何获取 PoC 帮助? + +您随时可以[联系 TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 diff --git a/tidb-cloud/tidb-cloud-quickstart.md b/tidb-cloud/tidb-cloud-quickstart.md new file mode 100644 index 000000000000..41fad7fc4dcf --- /dev/null +++ b/tidb-cloud/tidb-cloud-quickstart.md @@ -0,0 +1,122 @@ +--- +title: TiDB Cloud 快速上手 +summary: 快速注册并试用 TiDB Cloud,创建你的 TiDB 集群。 +category: quick start +--- + +# TiDB Cloud 快速上手 + +*预计完成时间:20 分钟* + +本教程将指导你快速开始使用 TiDB Cloud。你也可以在 TiDB Cloud 控制台的[**快速开始**](https://tidbcloud.com/getting-started)页面按照分步教程进行操作。 + +此外,你还可以在 [TiDB Playground](https://play.tidbcloud.com/?utm_source=docs&utm_medium=tidb_cloud_quick_start) 上试用 TiDB 的功能。 + +## 第 1 步:创建 TiDB 集群 + +[TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 是开始使用 TiDB Cloud 的最佳方式。要创建 TiDB Cloud Serverless 集群,请按照以下步骤操作: + +1. 如果你还没有 TiDB Cloud 账号,请点击[这里](https://tidbcloud.com/free-trial)注册。 + + 你可以使用电子邮件和密码注册,通过 TiDB Cloud 管理你的密码,或者选择使用 Google、GitHub 或 Microsoft 账号进行单点登录 (SSO)。 + +2. [登录](https://tidbcloud.com/)你的 TiDB Cloud 账号。 + + 默认显示[**集群**](https://tidbcloud.com/project/clusters)页面。 + +3. 对于新注册用户,TiDB Cloud 会自动为你创建一个名为 `Cluster0` 的默认 TiDB Cloud Serverless 集群。 + + - 要立即使用此默认集群试用 TiDB Cloud 功能,请继续[第 2 步:试用 AI 辅助 SQL 编辑器](#第-2-步试用-ai-辅助-sql-编辑器)。 + - 要自行创建新的 TiDB Cloud Serverless 集群,请按照以下步骤操作: + + 1. 点击**创建集群**。 + 2. 在**创建集群**页面,默认选择 **Serverless**。选择集群的目标区域,根据需要更新默认集群名称,选择你的[集群方案](/tidb-cloud/select-cluster-tier.md#cluster-plans),然后点击**创建**。你的 TiDB Cloud Serverless 集群将在大约 30 秒内创建完成。 + +## 第 2 步:试用 AI 辅助 SQL 编辑器 + +你可以使用 TiDB Cloud 控制台中内置的 AI 辅助 SQL 编辑器来最大化数据价值。这使你无需本地 SQL 客户端即可对数据库运行 SQL 查询。你可以直观地以表格或图表形式查看查询结果,并轻松查看查询日志。 + +1. 在[**集群**](https://tidbcloud.com/project/clusters)页面,点击集群名称进入其概览页面,然后在左侧导航栏中点击 **SQL 编辑器**。 + +2. 要试用 TiDB Cloud 的 AI 功能,请按照屏幕上的说明允许 PingCAP 和 AWS Bedrock 使用你的代码片段进行研究和服务改进,然后点击**保存并开始**。 + +3. 在 SQL 编辑器中,在 macOS 上按 + I(或在 Windows 或 Linux 上按 Control + I)来指示 [Chat2Query (beta)](/tidb-cloud/tidb-cloud-glossary.md#chat2query) 自动生成 SQL 查询。 + + 例如,要创建一个包含两列(列 `id` 和列 `name`)的新表 `test.t`,你可以输入 `use test;` 来指定数据库,按 + I,输入 `create a new table t with id and name` 作为指令,然后按 **Enter** 让 AI 相应地生成 SQL 语句。 + + 对于生成的语句,你可以点击**接受**来接受它,然后根据需要进一步编辑,或者点击**放弃**来拒绝它。 + + > **注意:** + > + > AI 生成的 SQL 查询并非 100% 准确,可能仍需要进一步调整。 + +4. 运行 SQL 查询。 + + +
+ + 对于 macOS: + + - 如果编辑器中只有一个查询,按 **⌘ + Enter** 或点击 **运行**来执行它。 + + - 如果编辑器中有多个查询,用光标选择目标查询的行,然后按 **⌘ + Enter** 或点击**运行**来按顺序执行它们。 + + - 要按顺序运行编辑器中的所有查询,按 **⇧ + ⌘ + Enter**,或用光标选择所有查询的行并点击**运行**。 + +
+ +
+ + 对于 Windows 或 Linux: + + - 如果编辑器中只有一个查询,按 **Ctrl + Enter** 或点击 **运行**来执行它。 + + - 如果编辑器中有多个查询,用光标选择目标查询的行,然后按 **Ctrl + Enter** 或点击**运行**来按顺序执行它们。 + + - 要按顺序运行编辑器中的所有查询,按 **Shift + Ctrl + Enter**,或用光标选择所有查询的行并点击**运行**。 + +
+
+ +运行查询后,你可以立即在页面底部看到查询日志和结果。 + +要让 AI 生成更多 SQL 语句,你可以按照以下示例输入更多指令: + +```sql +use test; + +-- create a new table t with id and name +CREATE TABLE + `t` (`id` INT, `name` VARCHAR(255)); + +-- add 3 rows +INSERT INTO + `t` (`id`, `name`) +VALUES + (1, 'row1'), + (2, 'row2'), + (3, 'row3'); + +-- query all +SELECT + `id`, + `name` +FROM + `t`; +``` + +## 第 3 步:试用交互式教程 + +TiDB Cloud 提供了带有精心设计的示例数据集的交互式教程,帮助你快速开始使用 TiDB Cloud。你可以尝试这些教程,学习如何使用 TiDB Cloud 进行高性能数据分析。 + +1. 点击控制台右下角的 **?** 图标,选择**交互式教程**。 +2. 在教程列表中,选择一个教程卡片开始,例如 **Steam 游戏统计**。 +3. 选择你想要用于教程的 TiDB Cloud Serverless 集群,然后点击**导入数据集**。导入过程可能需要大约一分钟。 +4. 数据导入完成后,按照屏幕上的说明完成教程。 + +## 下一步 + +- 要了解如何使用不同方法连接到集群,请参阅[连接到 TiDB Cloud Serverless 集群](/tidb-cloud/connect-to-tidb-cluster-serverless.md)。 +- 要了解更多关于如何使用 SQL 编辑器和 Chat2Query 探索数据的信息,请参阅[使用 AI 辅助 SQL 编辑器探索数据](/tidb-cloud/explore-data-with-chat2query.md)。 +- 关于 TiDB SQL 的使用,请参阅[使用 TiDB 探索 SQL](/basic-sql-operations.md)。 +- 对于需要跨可用区高可用性、水平扩展和 [HTAP](https://en.wikipedia.org/wiki/Hybrid_transactional/analytical_processing) 优势的生产环境使用,请参阅[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 diff --git a/tidb-cloud/tidb-cloud-release-notes.md b/tidb-cloud/tidb-cloud-release-notes.md new file mode 100644 index 000000000000..839bcdd05e1e --- /dev/null +++ b/tidb-cloud/tidb-cloud-release-notes.md @@ -0,0 +1,305 @@ +--- +title: TiDB Cloud 2025 年发布说明 +summary: 了解 TiDB Cloud 2025 年的发布说明。 +aliases: ['/tidbcloud/supported-tidb-versions','/tidbcloud/release-notes'] +--- + +# TiDB Cloud 2025 年发布说明 + +本页列出了 [TiDB Cloud](https://www.pingcap.com/tidb-cloud/) 在 2025 年的发布说明。 + +## 2025 年 6 月 17 日 + +**一般变更** + +- 对于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群,16 vCPU 和 32 vCPU 的 TiKV 节点的最大存储大小从 **6144 GiB** 改为 **4096 GiB**。 + + 更多信息,请参见 [TiKV 节点存储大小](/tidb-cloud/size-your-cluster.md#tikv-node-storage-size)。 + +**控制台变更** + +- 重新设计左侧导航栏以改善整体导航体验。 + + - 在左上角新增了一个 图标,让你可以根据需要轻松隐藏或显示左侧导航栏。 + - 在左上角新增了一个组合框,让你可以从一个中心位置快速切换组织、项目和集群。 + + + + - 左侧导航栏显示的条目现在会根据你在组合框中的当前选择动态调整,帮助你专注于最相关的功能。 + - 为了方便快速访问,**支持**、**通知**和你的账户条目现在会始终显示在所有控制台页面的左侧导航栏底部。 + +## 2025 年 6 月 4 日 + +**一般变更** + +- [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 在 Microsoft Azure 上现已公开预览。 + + 随着此次发布,TiDB Cloud 现在支持所有三大公有云平台 — AWS、Google Cloud 和 Azure,使你能够在最适合你的业务需求和云战略的地方部署 TiDB Cloud Dedicated 集群。 + + - AWS 和 Google Cloud 上可用的所有核心功能在 Azure 上都完全支持。 + - Azure 支持目前在三个区域可用:East US 2、Japan East 和 Southeast Asia,更多区域即将推出。 + - Azure 上的 TiDB Cloud Dedicated 集群需要 TiDB v7.5.3 或更高版本。 + + 要快速开始使用 Azure 上的 TiDB Cloud Dedicated,请参见以下文档: + + - [在 Azure 上创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md) + - [通过 Azure 私有端点连接 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-azure.md) + - [将数据导入 Azure 上的 TiDB Cloud Dedicated 集群](/tidb-cloud/import-csv-files.md) + +- Prometheus 集成提供更多指标以增强 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的监控能力。 + + 现在你可以将更多指标(如 `tidbcloud_disk_read_latency` 和 `tidbcloud_kv_request_duration`)集成到 Prometheus 中,以跟踪 TiDB Cloud Dedicated 性能的更多方面。 + + 有关可用指标以及如何为现有和新用户启用这些指标的更多信息,请参见[将 TiDB Cloud 与 Prometheus 和 Grafana 集成(Beta)](/tidb-cloud/monitor-prometheus-and-grafana-integration.md#metrics-available-to-prometheus)。 + +- TiKV [标准](/tidb-cloud/size-your-cluster.md#standard-storage)和[性能](/tidb-cloud/size-your-cluster.md#performance-and-plus-storage)存储定价正式发布。 + + 折扣期将于 **2025 年 6 月 5 日 00:00 UTC** 结束。之后,价格将恢复到标准价格。有关 TiDB Cloud Dedicated 价格的更多信息,请参见 [TiDB Cloud Dedicated 价格详情](https://www.pingcap.com/tidb-dedicated-pricing-details/#node-cost)。 + +**控制台变更** + +- 增强配置 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 TiFlash 节点大小时的交互体验。 + + 现在你可以在创建 TiDB Cloud Dedicated 集群时使用切换开关来控制 TiFlash 配置,使配置体验更加直观和流畅。 + +## 2025 年 5 月 27 日 + +**一般变更** + +- 支持通过 changefeed 将 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的数据流式传输到 [Apache Pulsar](https://pulsar.apache.org)。 + + 此功能使你能够将 TiDB Cloud Dedicated 集群与更多下游系统集成,并满足额外的数据集成需求。要使用此功能,请确保你的 TiDB Cloud Dedicated 集群版本为 v7.5.1 或更高版本。 + + 更多信息,请参见[导出到 Apache Pulsar](/tidb-cloud/changefeed-sink-to-apache-pulsar.md)。 + +## 2025 年 5 月 13 日 + +**一般变更** + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 现在为 AI 应用提供全文搜索功能(beta)。 + + TiDB Cloud Serverless 现在支持全文搜索(beta),使 AI 和检索增强生成(RAG)应用能够通过精确关键词检索内容。这补充了通过语义相似性检索内容的向量搜索。结合这两种方法可以显著提高 RAG 工作流中的检索准确性和答案质量。主要功能包括: + + - 直接文本搜索:无需嵌入即可直接查询字符串列。 + - 多语言支持:自动检测和分析多种语言的文本,即使在同一个表中也无需指定语言。 + - 基于相关性的排名:使用行业标准的 BM25 算法对结果进行排名,以获得最佳相关性。 + - 原生 SQL 兼容性:与全文搜索无缝使用 SQL 功能,如过滤、分组和连接。 + + 要开始使用,请参见[使用 SQL 进行全文搜索](/tidb-cloud/vector-search-full-text-search-sql.md)或[使用 Python 进行全文搜索](/tidb-cloud/vector-search-full-text-search-python.md)。 + +- 增加 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的最大 TiFlash 节点存储: + + - 8 vCPU TiFlash,从 2048 GiB 增加到 4096 GiB + - 32 vCPU TiFlash,从 4096 GiB 增加到 8192 GiB + + 此增强提高了 TiDB Cloud Dedicated 集群的分析数据存储容量,提升了工作负载扩展效率,并适应不断增长的数据需求。 + + 更多信息,请参见 [TiFlash 节点存储](/tidb-cloud/size-your-cluster.md#tiflash-node-storage)。 + +- 通过提供直观的选项来配置和重新安排维护任务,增强维护窗口配置体验。 + + 更多信息,请参见[配置维护窗口](/tidb-cloud/configure-maintenance-window.md)。 + +- 延长 TiKV [标准](/tidb-cloud/size-your-cluster.md#standard-storage)和[性能](/tidb-cloud/size-your-cluster.md#performance-and-plus-storage)存储类型的折扣期。促销现在将于 2025 年 6 月 5 日结束。在此日期之后,价格将恢复到标准费率。 + +**控制台变更** + +- 优化**备份设置**页面布局,改善 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的备份配置体验。 + + 更多信息,请参见[备份和恢复 TiDB Cloud Dedicated 数据](/tidb-cloud/backup-and-restore.md)。 + +## 2025 年 4 月 22 日 + +**一般变更** + +- 现在支持将数据导出到阿里云 OSS。 + + [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群现在支持使用 [AccessKey 对](https://www.alibabacloud.com/help/en/ram/user-guide/create-an-accesskey-pair)将数据导出到[阿里云对象存储服务(OSS)](https://www.alibabacloud.com/en/product/object-storage-service)。 + + 更多信息,请参见[从 TiDB Cloud Serverless 导出数据](/tidb-cloud/serverless-export.md#alibaba-cloud-oss)。 + +## 2025 年 4 月 15 日 + +**一般变更** + +- 支持从[阿里云对象存储服务(OSS)](https://www.alibabacloud.com/en/product/object-storage-service)将数据导入到 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 + + 此功能简化了向 TiDB Cloud Serverless 的数据迁移。你可以使用 AccessKey 对进行身份验证。 + + 更多信息,请参见以下文档: + + - [从 Amazon S3、GCS、Azure Blob Storage 或阿里云 OSS 导入 CSV 文件到 TiDB Cloud Serverless](/tidb-cloud/import-csv-files-serverless.md) + - [从 Amazon S3、GCS、Azure Blob Storage 或阿里云 OSS 导入 Apache Parquet 文件到 TiDB Cloud Serverless](/tidb-cloud/import-parquet-files-serverless.md) + +## 2025 年 4 月 1 日 + +**一般变更** + +- [TiDB 节点组](/tidb-cloud/tidb-node-group-overview.md)功能现在在 AWS 和 Google Cloud 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群中正式发布(GA)。 + + 此功能实现了单个集群内的**细粒度计算资源隔离**,帮助你优化多租户或多工作负载场景下的性能和资源分配。 + + **主要优势:** + + - **资源隔离**: + + - 将 TiDB 节点分组为逻辑隔离的单元,确保一个组中的工作负载不会影响其他组。 + - 防止应用程序或业务单位之间的资源争用。 + + - **简化管理**: + + - 在单个集群内管理所有节点组,减少运维开销。 + - 根据需求独立扩展各个组。 + + 有关优势的更多信息,请参见[技术博客](https://www.pingcap.com/blog/tidb-cloud-node-groups-scaling-workloads-predictable-performance/)。要开始使用,请参见[管理 TiDB 节点组](/tidb-cloud/tidb-node-group-management.md)。 + +- 为 AWS 上托管的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的 TiKV 节点引入[标准存储](/tidb-cloud/size-your-cluster.md#standard-storage)类型。 + + 标准存储类型适用于大多数工作负载,在性能和成本效益之间提供平衡。 + + **主要优势:** + + - **性能提升**:为 Raft 日志保留足够的磁盘资源,减少 Raft 和数据存储之间的 I/O 争用,从而提高 TiKV 的读写性能。 + - **稳定性增强**:将关键的 Raft 操作与数据工作负载隔离,确保更可预测的性能。 + - **成本效益**:与之前的存储类型相比,以具有竞争力的价格提供更高的性能。 + + **可用性:** + + 标准存储类型自动应用于 2025 年 4 月 1 日或之后在 AWS 上创建的新 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群,支持的版本为(版本 >= 7.5.5、8.1.2 或 8.5.0)。现有集群仍使用之前的[基础存储](/tidb-cloud/size-your-cluster.md#basic-storage)类型,无需迁移。 + + 标准存储的价格与基础存储不同。更多信息,请参见[定价](https://www.pingcap.com/tidb-dedicated-pricing-details/)。 + +## 2025 年 3 月 25 日 + +**控制台变更** + +- 支持 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的公共端点防火墙规则。 + + 你现在可以为 TiDB Cloud Serverless 集群配置防火墙规则,以控制通过公共端点的访问。直接在 [TiDB Cloud 控制台](https://tidbcloud.com/)中指定允许的 IP 地址或范围以增强安全性。 + + 更多信息,请参见[为公共端点配置 TiDB Cloud Serverless 防火墙规则](/tidb-cloud/configure-serverless-firewall-rules-for-public-endpoints.md)。 + +## 2025 年 3 月 18 日 + +**一般变更** + +- 支持为部署在 Google Cloud 上的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群创建 TiDB 节点组,以增强资源管理灵活性。 + + 更多信息,请参见 [TiDB 节点组概述](/tidb-cloud/tidb-node-group-overview.md)。 + +- 支持在 TiDB Cloud 中存储部署在 AWS 上的 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的数据库审计日志文件。 + + 你可以直接从 TiDB Cloud 下载这些审计日志文件。请注意,此功能仅在申请后可用。 + + 更多信息,请参见[数据库审计日志](/tidb-cloud/tidb-cloud-auditing.md)。 + +- 通过改进多因素认证(MFA)的管理来增强 TiDB Cloud 账户安全性。此功能适用于 TiDB Cloud 的基于密码的登录。 + + 更多信息,请参见[密码认证](/tidb-cloud/tidb-cloud-password-authentication.md)。 + +## 2025 年 2 月 18 日 + +**控制台变更** + +- 推出 Connected Care,TiDB Cloud 的新支持服务。 + + Connected Care 服务旨在通过现代通信工具、主动支持和先进的 AI 功能加强你与 TiDB Cloud 的连接,提供无缝和以客户为中心的体验。 + + Connected Care 服务引入了以下功能: + + - **诊所服务**:先进的监控和诊断,优化性能。 + - **即时通讯中的 AI 聊天**:通过即时通讯(IM)工具获得即时 AI 帮助。 + - **告警和工单更新的即时通讯订阅**:通过即时通讯及时了解告警和工单进展。 + - **支持工单的即时通讯交互**:通过即时通讯工具创建和处理支持工单。 + + 更多信息,请参见 [Connected Care 概述](/tidb-cloud/connected-care-overview.md)。 + +- 支持从 GCS 和 Azure Blob Storage 将数据导入到 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。 + + TiDB Cloud Serverless 现在支持从 Google Cloud Storage (GCS) 和 Azure Blob Storage 导入数据。你可以使用 Google Cloud 服务账号密钥或 Azure 共享访问签名(SAS)令牌进行身份验证。此功能简化了向 TiDB Cloud Serverless 的数据迁移。 + + 更多信息,请参见[从 Amazon S3、GCS 或 Azure Blob Storage 导入 CSV 文件到 TiDB Cloud Serverless](/tidb-cloud/import-csv-files-serverless.md)和[从 Amazon S3、GCS 或 Azure Blob Storage 导入 Apache Parquet 文件到 TiDB Cloud Serverless](/tidb-cloud/import-parquet-files-serverless.md)。 + +## 2025 年 1 月 21 日 + +**控制台变更** + +- 支持每个任务将单个本地 CSV 文件(最大 250 MiB)导入到 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群,从之前的 50 MiB 限制提高。 + + 更多信息,请参见[将本地文件导入到 TiDB Cloud](/tidb-cloud/tidb-cloud-import-local-files.md)。 + +## 2025 年 1 月 14 日 + +**一般变更** + +- 支持 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的新 AWS 区域:`雅加达 (ap-southeast-3)`。 + +- 引入通知功能,使你能够通过 [TiDB Cloud 控制台](https://tidbcloud.com/)即时了解 TiDB Cloud 更新和告警。 + + 更多信息,请参见[通知](/tidb-cloud/notifications.md)。 + +## 2025 年 1 月 2 日 + +**一般变更** + +- 支持为 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群创建 TiDB 节点组,以增强资源管理灵活性。 + + 更多信息,请参见 [TiDB 节点组概述](/tidb-cloud/tidb-node-group-overview.md)。 + +- 支持通过私有连接(beta)将 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群连接到 AWS 和 Google Cloud 中的通用 Kafka。 + + 私有连接利用云提供商的 Private Link 或 Private Service Connect 技术,使 TiDB Cloud VPC 中的 changefeed 能够使用私有 IP 地址连接到客户 VPC 中的 Kafka,就像这些 Kafka 直接托管在 TiDB Cloud VPC 中一样。此功能有助于防止 VPC CIDR 冲突并满足安全合规要求。 + + - 对于 AWS 中的 Apache Kafka,请按照[在 AWS 中设置自托管 Kafka Private Link 服务](/tidb-cloud/setup-aws-self-hosted-kafka-private-link-service.md)中的说明配置网络连接。 + + - 对于 Google Cloud 中的 Apache Kafka,请按照[在 Google Cloud 中设置自托管 Kafka Private Service Connect](/tidb-cloud/setup-self-hosted-kafka-private-service-connect.md)中的说明配置网络连接。 + + 请注意,使用此功能会产生额外的[私有数据链路成本](/tidb-cloud/tidb-cloud-billing-ticdc-rcu.md#private-data-link-cost)。 + + 更多信息,请参见[导出到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md#network)。 + +- 为 Kafka changefeed 引入额外的可配置选项: + + - 支持使用 Debezium 协议。Debezium 是一个用于捕获数据库变更的工具。它将每个捕获的数据库变更转换为称为事件的消息,并将这些事件发送到 Kafka。更多信息,请参见 [TiCDC Debezium 协议](https://docs.pingcap.com/tidb/v8.1/ticdc-debezium)。 + + - 支持为所有表定义单个分区调度器,或为不同表定义不同的分区调度器。 + + - 为 Kafka 消息的分区分配引入两种新的调度器类型:时间戳和列值。 + + 更多信息,请参见[导出到 Apache Kafka](/tidb-cloud/changefeed-sink-to-apache-kafka.md)。 + +- 增强 TiDB Cloud 中的角色: + + - 引入 `Project Viewer` 和 `Organization Billing Viewer` 角色,以增强 TiDB Cloud 上的细粒度访问控制。 + + - 重命名以下角色: + + - `Organization Member` 改为 `Organization Viewer` + - `Organization Billing Admin` 改为 `Organization Billing Manager` + - `Organization Console Audit Admin` 改为 `Organization Console Audit Manager` + + 更多信息,请参见[身份访问管理](/tidb-cloud/manage-user-access.md#organization-roles)。 + +- [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群的区域高可用性(beta)。 + + 此功能专为需要最大基础设施冗余和业务连续性的工作负载而设计。主要功能包括: + + - 节点分布在多个可用区,以确保在区域故障时的高可用性。 + - 关键的 OLTP(在线事务处理)组件,如 PD 和 TiKV,在可用区之间复制以实现冗余。 + - 自动故障转移最大限度地减少主要区域故障期间的服务中断。 + + 此功能目前仅在 AWS 东京(ap-northeast-1)区域可用,且只能在集群创建时启用。 + + 更多信息,请参见 [TiDB Cloud Serverless 中的高可用性](/tidb-cloud/serverless-high-availability.md)。 + +- 将新 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群的默认 TiDB 版本从 [v8.1.1](https://docs.pingcap.com/tidb/v8.1/release-8.1.1) 升级到 [v8.1.2](https://docs.pingcap.com/tidb/v8.1/release-8.1.2)。 + +**控制台变更** + +- 加强数据导出服务: + + - 支持通过 [TiDB Cloud 控制台](https://tidbcloud.com/)将数据从 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 导出到 Google Cloud Storage 和 Azure Blob Storage。 + + - 支持通过 [TiDB Cloud 控制台](https://tidbcloud.com/)以 Parquet 文件格式导出数据。 + + 更多信息,请参见[从 TiDB Cloud Serverless 导出数据](/tidb-cloud/serverless-export.md)和[为 TiDB Cloud Serverless 配置外部存储访问](/tidb-cloud/serverless-external-storage.md)。 diff --git a/tidb-cloud/tidb-cloud-sql-tuning-overview.md b/tidb-cloud/tidb-cloud-sql-tuning-overview.md new file mode 100644 index 000000000000..d4208ae17928 --- /dev/null +++ b/tidb-cloud/tidb-cloud-sql-tuning-overview.md @@ -0,0 +1,125 @@ +--- +title: SQL 调优概述 +summary: 了解如何在 TiDB Cloud 中调优 SQL 性能。 +--- + +# SQL 调优概述 + +本文介绍如何在 TiDB Cloud 中调优 SQL 性能。要获得最佳的 SQL 性能,您可以执行以下操作: + +- 调优 SQL 性能。有许多方法可以优化 SQL 性能,例如分析查询语句、优化执行计划和优化全表扫描。 +- 优化模式设计。根据您的业务工作负载类型,您可能需要优化模式以避免事务冲突或热点。 + +## 调优 SQL 性能 + +要提高 SQL 语句的性能,请考虑以下原则。 + +- 最小化扫描数据的范围。最佳实践始终是只扫描最小范围的数据,避免扫描所有数据。 +- 使用适当的索引。对于 SQL 语句中 `WHERE` 子句中的每个列,确保有相应的索引。否则,`WHERE` 子句将扫描全表并导致性能不佳。 +- 使用适当的连接类型。根据查询中每个表的大小和相关性,选择正确的连接类型非常重要。通常,TiDB 中的基于成本的优化器会自动选择最优的连接类型。但是,在某些情况下,您可能需要手动指定连接类型。详情请参见[解释使用连接的语句](/explain-joins.md)。 +- 使用适当的存储引擎。对于混合事务和分析处理(HTAP)工作负载,建议使用 TiFlash 存储引擎。请参见 [HTAP 查询](/develop/dev-guide-hybrid-oltp-and-olap-queries.md)。 + +TiDB Cloud 提供了几个工具来帮助您分析集群上的慢查询。以下部分描述了优化慢查询的几种方法。 + +### 使用诊断页面上的 Statement + +TiDB Cloud 控制台在[**诊断**](/tidb-cloud/tune-performance.md#view-the-diagnosis-page)页面上提供了 [**SQL Statement**](/tidb-cloud/tune-performance.md#statement-analysis) 标签页。它收集集群上所有数据库的 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 Statement** 中查看一些关键信息。 + +- **SQL 模板**:包括 SQL 摘要、SQL 模板 ID、当前查看的时间范围、执行计划数量和执行所在的数据库。 + + ![Details0](/media/dashboard/dashboard-statement-detail0.png) + +- 执行计划列表:如果一个 SQL 语句有多个执行计划,则显示列表。您可以选择不同的执行计划,所选执行计划的详细信息将显示在列表底部。如果只有一个执行计划,则不会显示列表。 + + ![Details1](/media/dashboard/dashboard-statement-detail1.png) + +- 执行计划详情:显示所选执行计划的详细信息。它从多个角度收集每种 SQL 类型的执行计划和相应的执行时间,以帮助您获取更多信息。请参见[执行计划](https://docs.pingcap.com/tidb/stable/dashboard-statement-details#execution-plans)。 + + ![Details2](/media/dashboard/dashboard-statement-detail2.png) + +- 相关慢查询 + +除了 **Statement** 仪表板中的信息外,以下部分还描述了一些 TiDB Cloud 的 SQL 最佳实践。 + +### 检查执行计划 + +您可以使用 [`EXPLAIN`](/explain-overview.md) 检查 TiDB 在编译期间为语句计算的执行计划。换句话说,TiDB 估算数百或数千种可能的执行计划,并选择一个消耗最少资源且执行最快的最优执行计划。 + +如果 TiDB 选择的执行计划不是最优的,您可以使用 EXPLAIN 或 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 进行诊断。 + +### 优化执行计划 + +在通过 `parser` 解析原始查询文本并进行基本有效性验证后,TiDB 首先对查询进行一些逻辑等价变换。更多信息,请参见 [SQL 逻辑优化](/sql-logical-optimization.md)。 + +通过这些等价变换,查询在逻辑执行计划中可能变得更容易处理。等价变换后,TiDB 获得一个与原始查询等价的查询计划结构,然后根据数据分布和运算符的具体执行开销获得最终的执行计划。更多信息,请参见 [SQL 物理优化](/sql-physical-optimization.md)。 + +此外,TiDB 可以选择启用执行计划缓存,以在执行 `PREPARE` 语句时减少执行计划的创建开销,如[预处理执行计划缓存](/sql-prepared-plan-cache.md)中所介绍。 + +### 优化全表扫描 + +慢 SQL 查询最常见的原因是 `SELECT` 语句执行全表扫描或使用了错误的索引。您可以使用 EXPLAIN 或 EXPLAIN ANALYZE 查看查询的执行计划并找出执行慢的原因。有[三种方法](/develop/dev-guide-optimize-sql.md)可以进行优化。 + +- 使用二级索引 +- 使用覆盖索引 +- 使用主键索引 + +### DML 最佳实践 + +请参见 [DML 最佳实践](/develop/dev-guide-optimize-sql-best-practices.md#dml-最佳实践)。 + +### 选择主键时的 DDL 最佳实践 + +请参见[选择主键时需要遵循的准则](/develop/dev-guide-create-table.md#选择主键时需要遵循的准则)。 + +### 索引最佳实践 + +[索引最佳实践](/develop/dev-guide-index-best-practice.md)包括创建索引和使用索引的最佳实践。 + +创建索引的速度默认是保守的,在某些场景下可以通过[修改变量](/develop/dev-guide-optimize-sql-best-practices.md#添加索引最佳实践)来加快索引创建过程。 + + + +## 优化模式设计 + +如果基于 SQL 性能调优仍然无法获得更好的性能,您可能需要检查您的模式设计和数据读取模型,以避免事务冲突和热点。 + +### 事务冲突 + +有关如何定位和解决事务冲突的更多信息,请参见[排查锁冲突问题](https://docs.pingcap.com/tidb/stable/troubleshoot-lock-conflicts#排查锁冲突问题)。 + +### 热点问题 + +您可以使用 [Key Visualizer](/tidb-cloud/tune-performance.md#key-visualizer) 分析热点问题。 + +您可以使用 Key Visualizer 分析 TiDB 集群的使用模式并排查流量热点。此页面提供了 TiDB 集群随时间变化的流量的可视化表示。 + +您可以在 Key Visualizer 中观察以下信息。您可能需要先了解一些[基本概念](https://docs.pingcap.com/tidb/stable/dashboard-key-visualizer#基本概念)。 + +- 显示整体流量随时间变化的大型热力图 +- 热力图上某个坐标的详细信息 +- 左侧显示的表和索引等标识信息 + +在 Key Visualizer 中,有[四种常见的热力图结果](https://docs.pingcap.com/tidb/stable/dashboard-key-visualizer#常见热力图类型)。 + +- 均匀分布的工作负载:理想结果 +- X 轴(时间)上明暗交替:需要检查高峰时期的资源 +- Y 轴上明暗交替:需要检查生成的热点聚集程度 +- 明亮的对角线:需要检查业务模型 + +在 X 轴和 Y 轴明暗交替的情况下,都需要解决读写压力。 + +有关 SQL 性能优化的更多信息,请参见 SQL 常见问题中的 [SQL 优化](https://docs.pingcap.com/tidb/stable/sql-faq#sql-优化)。 diff --git a/tidb-cloud/tidb-cloud-sso-authentication.md b/tidb-cloud/tidb-cloud-sso-authentication.md new file mode 100644 index 000000000000..5a5cb5d8b0c2 --- /dev/null +++ b/tidb-cloud/tidb-cloud-sso-authentication.md @@ -0,0 +1,65 @@ +--- +title: 标准 SSO 认证 +summary: 了解如何通过 Google、GitHub 或 Microsoft 账号登录 TiDB Cloud 控制台。 +--- + +# 标准 SSO 认证 + +本文档介绍如何通过基本的单点登录(SSO)认证登录 [TiDB Cloud 控制台](https://tidbcloud.com/),这种方式快速且方便。 + +TiDB Cloud 支持 Google、GitHub 和 Microsoft 账号的 SSO 认证。如果你通过 SSO 认证登录 TiDB Cloud,由于你的 ID 和凭据存储在第三方 Google、GitHub 和 Microsoft 平台上,你将无法使用 TiDB 控制台修改账号密码和启用多因素认证(MFA)。 + +> **注意:** +> +> 如果你想通过用户名和密码登录 TiDB Cloud,请参见[密码认证](/tidb-cloud/tidb-cloud-password-authentication.md)。 + +## 使用 Google SSO 登录 + +要使用 Google 账号登录,请执行以下步骤: + +1. 访问 TiDB Cloud [登录](https://tidbcloud.com/)页面。 + +2. 点击 **Sign in with Google**。你将被重定向到 Google 登录页面。 + +3. 按照屏幕上的说明输入你的 Google 用户名和密码。 + + 如果登录成功,你将被重定向到 TiDB Cloud 控制台。 + + > **注意:** + > + > - 如果这是你第一次使用 Google 登录,系统会询问你是否接受 TiDB Cloud 条款。在你阅读并同意条款后,你将看到 TiDB Cloud 欢迎页面,然后被重定向到 TiDB Cloud 控制台。 + > - 如果你为 Google 账号启用了两步验证(也称为双因素认证),在输入用户名和密码后,你还需要提供验证码。 + +## 使用 GitHub SSO 登录 + +要使用 GitHub 账号登录,请执行以下步骤: + +1. 访问 TiDB Cloud [登录](https://tidbcloud.com/)页面。 + +2. 点击 **Sign in with GitHub**。你将被重定向到 GitHub 登录页面。 + +3. 按照屏幕上的说明输入你的 GitHub 用户名和密码。 + + 如果登录成功,你将被重定向到 TiDB Cloud 控制台。 + + > **注意:** + > + > - 如果这是你第一次使用 GitHub 登录,系统会询问你是否接受 TiDB Cloud 条款。在你阅读并同意条款后,你将看到 TiDB Cloud 欢迎页面,然后被重定向到 TiDB Cloud 控制台。 + > - 如果你为 GitHub 账号配置了双因素认证,在输入用户名和密码后,你还需要提供验证码。 + +## 使用 Microsoft SSO 登录 + +要使用 Microsoft 账号登录,请执行以下步骤: + +1. 访问 TiDB Cloud [登录](https://tidbcloud.com/)页面。 + +2. 点击 **Sign in with Microsoft**。你将被重定向到 Microsoft 登录页面。 + +3. 按照屏幕上的说明输入你的 Microsoft 用户名和密码。 + + 如果登录成功,你将被重定向到 TiDB Cloud 控制台。 + + > **注意:** + > + > - 如果这是你第一次使用 Microsoft 登录,系统会询问你是否接受 TiDB Cloud 条款。在你阅读并同意条款后,你将看到 TiDB Cloud 欢迎页面,然后被重定向到 TiDB Cloud 控制台。 + > - 如果你为 Microsoft 账号设置了两步验证,在输入用户名和密码后,你还需要提供验证码。 diff --git a/tidb-cloud/tidb-cloud-support.md b/tidb-cloud/tidb-cloud-support.md new file mode 100644 index 000000000000..586096a1f72a --- /dev/null +++ b/tidb-cloud/tidb-cloud-support.md @@ -0,0 +1,121 @@ +--- +title: TiDB Cloud 支持 +summary: 了解如何联系 TiDB Cloud 的支持团队。 +--- + +# TiDB Cloud 支持 + +TiDB Cloud 提供分级的支持计划,以满足客户的需求。更多信息,请参阅 [Connected Care 详情](/tidb-cloud/connected-care-detail.md)。 + +> **注意:** +> +> 要申请 [概念验证 (PoC)](/tidb-cloud/tidb-cloud-poc.md)、演示或免费试用额度,请点击 [TiDB Cloud 控制台](https://tidbcloud.com/) 右下角的 **?**,然后点击 **联系销售**。 + +## 访问 PingCAP 帮助中心 + +[PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/portals) 是 TiDB Cloud 用户访问支持服务和管理支持工单的中心枢纽。 + +您可以通过 直接访问 PingCAP 帮助中心,或者通过 [TiDB Cloud 控制台](https://tidbcloud.com/) 以下列方式访问: + +- 点击 [TiDB Cloud 控制台](https://tidbcloud.com/) 右下角的 **?**,然后点击 **Request Support**。 +- 点击 [TiDB Cloud 控制台](https://tidbcloud.com/) 左下角的 **Support**,然后点击 **Create Ticket**。 +- 在您项目的 [**Clusters**](https://tidbcloud.com/project/clusters) 页面,点击您的集群所在行的 **...**,然后选择 **Get Support**。 +- 在您的集群概览页面,点击右上角的 **...**,然后选择 **Get Support**。 + +## 创建账户或账单支持工单 + +要创建关于账户或账单问题的支持工单,请按照以下步骤操作: + +1. 登录 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/portals),然后点击 [TiDB Cloud 账户/账单支持](https://tidb.support.pingcap.com/servicedesk/customer/portal/16)。 +2. 点击 **提交请求**。 +3. 填写以下字段: + + - **概要**: 提供您问题的简要概述。 + - **TiDB Cloud 组织**: 选择相关的 TiDB Cloud 组织(如果适用)。 + - **TiDB Cloud 集群**: 选择相关的 TiDB Cloud 集群(如果适用)。 + - **描述**: 提供关于问题的详细信息。 + - **严重程度**: 评估问题对业务的影响,并选择适当的严重程度。(S1 不适用于账单或账户问题。) + +4. 点击 **提交**。 + +## 创建技术支持工单 + +要创建关于技术问题的支持工单,请按照以下步骤操作: + +1. 登录 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/portals),然后点击 [TiDB Cloud 技术支持](https://tidb.support.pingcap.com/servicedesk/customer/portal/6)。 + + > **注意:** + > + > [TiDB Cloud 技术支持](https://tidb.support.pingcap.com/servicedesk/customer/portal/6) 入口仅适用于订阅了 **Developer**、**Enterprise** 或 **Premium** [支持计划](/tidb-cloud/connected-care-detail.md) 的客户。 + +2. 点击 **提交请求**。 + +3. 填写以下字段: + + - **概要 (Summary)**:提供您问题的简要概述。 + - **TiDB Cloud 组织 (TiDB Cloud Org)**:选择与问题相关的 TiDB Cloud 组织。 + - **TiDB Cloud 集群 (TiDB Cloud Cluster)**:选择相关的 TiDB Cloud 集群(如果适用)。 + - **环境 (Environment)**:选择您使用 TiDB Cloud 集群的相应环境。 + - **描述 (Description)**:尽可能详细地描述您遇到的问题。 例如,分享您遇到问题的确切时间戳,附上问题的详细错误消息和调用堆栈,并添加您对问题的故障排除或分析。 + - **严重程度 (Severity)**:评估问题对业务的影响,并为其选择适当的严重程度。 + + | 严重程度 | 描述 | + | --- | --- | + | S1 | 生产环境功能完全丧失 | + | S2 | 对生产环境中的运营产生重大影响 | + | S3 | 生产或非生产环境中的非关键数据库使用问题 | + | S4 | 关于特定特性或功能如何执行或应如何配置的一般性问题。 对业务影响极小,可以在合理的时间内容忍的问题。 | + + - **组件 (Components)**:选择要报告问题的相关 TiDB Cloud 组件,例如 TiDB、TiKV、PD 或 TiFlash。 + - **影响版本 (Affects versions)**:指定与问题相关的 TiDB Cloud 集群版本。 + +4. 点击 **提交 (Submit)**。 + +## 查看支持工单 + +要查看所有历史支持工单,请登录 [PingCAP 帮助中心](https://tidb.support.pingcap.com/servicedesk/customer/portals),点击右上角的头像,然后点击 **Requests**。 + +## 查看或升级您的支持计划 + +TiDB Cloud 默认提供免费的基础支持计划。如需扩展服务,您可以升级到付费计划。 + +要查看或升级您的支持计划,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/) 中,单击左下角的 **Support**(支持)。 + + 在此页面上,您可以找到您当前的计划。默认情况下,会选择 **Basic**(基础)免费计划。 + +2. 选择您所需的支持计划。 + + +
+ + 要升级到 **Developer**(开发者)或 **Enterprise**(企业): + + 1. 单击 **Developer**(开发者)或 **Enterprise**(企业)窗格中的 **Upgrade**(升级)。将显示 **Upgrade to Developer Plan**(升级到开发者计划)或 **Upgrade to Enterprise Plan**(升级到企业计划)页面。 + 2. 在页面上查看相应的支持服务信息。有关每个支持计划的完整版本,请参阅 [Connected Care Details](/tidb-cloud/connected-care-detail.md)。 + 3. 单击 **Add Credit Card and Upgrade**(添加信用卡并升级),然后填写 **Credit Card**(信用卡)详细信息。 + + 有关计费的更多信息,请参阅 [TiDB Cloud Payment Method](/tidb-cloud/tidb-cloud-billing.md#payment-method)。 + + 4. 单击页面右下角的 **Save Card**(保存卡片)。 + + 付款完成后,您已将您的计划升级到 **Standard**(标准)或 **Enterprise**(企业)。 + +
+
+ + 要将您的计划升级到 **Premium**(高级): + + 1. 单击 **Premium**(高级)窗格中的 **Contact Sales**(联系销售)。将显示 **Contact Us**(联系我们)页面。 + 2. 在页面上填写并提交您的联系信息。然后,支持团队将与您联系并帮助您完成订阅。 + +
+
+ +## 降级您的支持计划 + +要降级您的支持计划,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/) 中,点击左下角的 **Support**(支持)。 +2. 选择您想要切换到的支持计划,然后点击 **Downgrade**(降级)。 \ No newline at end of file diff --git a/tidb-cloud/tidb-cloud-tls-connect-to-dedicated.md b/tidb-cloud/tidb-cloud-tls-connect-to-dedicated.md new file mode 100644 index 000000000000..196a7d673488 --- /dev/null +++ b/tidb-cloud/tidb-cloud-tls-connect-to-dedicated.md @@ -0,0 +1,299 @@ +--- +title: TiDB Cloud Dedicated 的 TLS 连接 +summary: 介绍 TiDB Cloud Dedicated 中的 TLS 连接。 +aliases: ['/tidbcloud/tidb-cloud-tls-connect-to-dedicated-tier'] +--- + +# TiDB Cloud Dedicated 的 TLS 连接 + +在 TiDB Cloud 中,建立 TLS 连接是连接到 TiDB Cloud Dedicated 集群的基本安全实践之一。你可以从客户端、应用程序和开发工具配置多个 TLS 连接到 TiDB Cloud Dedicated 集群,以保护数据传输安全。出于安全考虑,TiDB Cloud Dedicated 仅支持 TLS 1.2 和 TLS 1.3,不支持 TLS 1.0 和 TLS 1.1 版本。 + +为确保数据安全,你的 TiDB Cloud Dedicated 集群的 TiDB 集群 CA 托管在 [AWS Certificate Manager (ACM)](https://aws.amazon.com/certificate-manager/) 上,TiDB 集群私钥存储在符合 [FIPS 140-2 Level 3](https://csrc.nist.gov/projects/cryptographic-module-validation-program/Certificate/3139) 安全标准的 AWS 托管硬件安全模块(HSMs)中。 + +## 前提条件 + +- 通过[密码认证](/tidb-cloud/tidb-cloud-password-authentication.md)或 [SSO 认证](/tidb-cloud/tidb-cloud-sso-authentication.md)登录 TiDB Cloud,然后[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +- 在安全设置中设置访问集群的密码。 + + 为此,你可以导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,点击 TiDB Cloud Dedicated 集群所在行的 **...**,然后选择**密码设置**。在密码设置中,你可以点击**自动生成密码**自动生成一个长度为 16 个字符的 root 密码,包括数字、大小写字符和特殊字符。 + +## 安全连接到 TiDB Cloud Dedicated 集群 + +在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,你可以获取不同连接方式的示例并按以下步骤连接到 TiDB Cloud Dedicated 集群: + +1. 导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击 TiDB Cloud Dedicated 集群的名称以进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个对话框。 + +3. 在连接对话框中,从**连接类型**下拉列表中选择**公共**。 + + 如果你尚未配置 IP 访问列表,请在首次连接之前点击**配置 IP 访问列表**进行配置。更多信息,请参阅[配置 IP 访问列表](/tidb-cloud/configure-ip-access-list.md)。 + +4. 点击 **CA 证书**下载用于 TLS 连接到 TiDB 集群的 CA 证书。CA 证书默认支持 TLS 1.2 版本。 + + > **注意:** + > + > - 你可以将下载的 CA 证书存储在操作系统的默认存储路径中,或指定其他存储路径。在后续步骤中,你需要将代码示例中的 CA 证书路径替换为你自己的 CA 证书路径。 + > - TiDB Cloud Dedicated 不强制客户端使用 TLS 连接,目前不支持在 TiDB Cloud Dedicated 上自定义配置 [`require_secure_transport`](/system-variables.md#require_secure_transport-new-in-v610) 变量。 + +5. 选择你喜欢的连接方式,然后参考选项卡上的连接字符串和示例代码连接到你的集群。 + +以下示例展示了 MySQL、MyCLI、JDBC、Python、Go 和 Node.js 中的连接字符串: + + +
+ +MySQL CLI 客户端默认尝试建立 TLS 连接。连接到 TiDB Cloud Dedicated 集群时,你需要设置 `ssl-mode` 和 `ssl-ca`。 + +```shell +mysql --connect-timeout 15 --ssl-mode=VERIFY_IDENTITY --ssl-ca=ca.pem --tls-version="TLSv1.2" -u root -h tidb.eqlfbdgthh8.clusters.staging.tidb-cloud.com -P 4000 -D test -p +``` + +参数说明: + +- 使用 `--ssl-mode=VERIFY_IDENTITY` 强制启用 TLS 并验证 TiDB Cloud Dedicated 集群。 +- 使用 `--ssl-ca=` 指定下载的 TiDB 集群 `ca.pem` 的本地路径。 +- 使用 `--tls-version=TLSv1.2` 限制 TLS 协议的版本。如果要使用 TLS 1.3,可以将版本设置为 `TLSv1.3`。 + +
+ +
+ +[MyCLI](https://www.mycli.net/) 在使用 TLS 相关参数时会自动启用 TLS。连接到 TiDB Cloud Dedicated 集群时,你需要设置 `ssl-ca` 和 `ssl-verify-server-cert`。 + +```shell +mycli --ssl-ca=ca.pem --ssl-verify-server-cert -u root -h tidb.eqlfbdgthh8.clusters.staging.tidb-cloud.com -P 4000 -D test +``` + +参数说明: + +- 使用 `--ssl-ca=` 指定下载的 TiDB 集群 `ca.pem` 的本地路径。 +- 使用 `--ssl-verify-server-cert` 验证 TiDB Cloud Dedicated 集群。 + +
+ +
+ +这里以 [MySQL Connector/J](https://dev.mysql.com/doc/connector-j/en/) 的 TLS 连接配置为例。 + +下载 TiDB 集群 CA 后,如果要将其导入到操作系统中,可以使用 `keytool -importcert -alias TiDBCACert -file ca.pem -keystore -storepass ` 命令。 + +```shell +/* 请确保替换以下连接字符串中的参数。 */ +/* version >= 8.0.28 */ +jdbc:mysql://tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com:4000/test?user=root&password=&sslMode=VERIFY_IDENTITY&tlsVersions=TLSv1.2&trustCertificateKeyStoreUrl=file:&trustCertificateKeyStorePassword= +``` + +你可以点击**显示示例用法**查看详细的代码示例。 + +``` +import com.mysql.jdbc.Driver; +import java.sql.*; + +class Main { + public static void main(String args[]) throws SQLException, ClassNotFoundException { + Class.forName("com.mysql.cj.jdbc.Driver"); + try { + Connection conn = DriverManager.getConnection("jdbc:mysql://tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com:4000/test?user=root&password=&sslMode=VERIFY_IDENTITY&tlsVersions=TLSv1.2&trustCertificateKeyStoreUrl=file:&trustCertificateKeyStorePassword="); + Statement stmt = conn.createStatement(); + try { + ResultSet rs = stmt.executeQuery("SELECT DATABASE();"); + if (rs.next()) { + System.out.println("using db:" + rs.getString(1)); + } + } catch (Exception e) { + System.out.println("exec error:" + e); + } + } catch (Exception e) { + System.out.println("connect error:" + e); + } + } +} +``` + +参数说明: + +- 设置 `sslMode=VERIFY_IDENTITY` 启用 TLS 并验证 TiDB Cloud Dedicated 集群。 +- 设置 `enabledTLSProtocols=TLSv1.2` 限制 TLS 协议的版本。如果要使用 TLS 1.3,可以将版本设置为 `TLSv1.3`。 +- 设置 `trustCertificateKeyStoreUrl` 为你的自定义信任库路径。 +- 设置 `trustCertificateKeyStorePassword` 为你的信任库密码。 + +
+ +
+ +这里以 [mysqlclient](https://pypi.org/project/mysqlclient/) 的 TLS 连接配置为例。 + +``` +host="tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com", user="root", password="", port=4000, database="test", ssl_mode="VERIFY_IDENTITY", ssl={"ca": "ca.pem"} +``` + +你可以点击**显示示例用法**查看详细的代码示例。 + +``` +import MySQLdb + +connection = MySQLdb.connect(host="tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com", port=4000, user="root", password="", database="test", ssl_mode="VERIFY_IDENTITY", ssl={"ca": "ca.pem"}) + +with connection: + with connection.cursor() as cursor: + cursor.execute("SELECT DATABASE();") + m = cursor.fetchone() + print(m[0]) +``` + +参数说明: + +- 设置 `ssl_mode="VERIFY_IDENTITY"` 启用 TLS 并验证 TiDB Cloud Dedicated 集群。 +- 使用 `ssl={"ca": ""}` 指定下载的 TiDB 集群 `ca.pem` 的本地路径。 + +
+ +
+ +这里以 [Go-MySQL-Driver](https://github.com/go-sql-driver/mysql) 的 TLS 连接配置为例。 + +``` +rootCertPool := x509.NewCertPool() +pem, err := ioutil.ReadFile("ca.pem") +if err != nil { + log.Fatal(err) +} +if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { + log.Fatal("Failed to append PEM.") +} +mysql.RegisterTLSConfig("tidb", &tls.Config{ + RootCAs: rootCertPool, + MinVersion: tls.VersionTLS12, + ServerName: "tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com", +}) + +db, err := sql.Open("mysql", "root:@tcp(tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com:4000)/test?tls=tidb") +``` + +你可以点击**显示示例用法**查看详细的代码示例。 + +``` +package main +import ( + "crypto/tls" + "crypto/x509" + "database/sql" + "fmt" + "io/ioutil" + "log" + + "github.com/go-sql-driver/mysql" +) +func main() { + rootCertPool := x509.NewCertPool() + pem, err := ioutil.ReadFile("ca.pem") + if err != nil { + log.Fatal(err) + } + if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { + log.Fatal("Failed to append PEM.") + } + mysql.RegisterTLSConfig("tidb", &tls.Config{ + RootCAs: rootCertPool, + MinVersion: tls.VersionTLS12, + ServerName: "tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com", + }) + db, err := sql.Open("mysql", "root:@tcp(tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com:4000)/test?tls=tidb") + if err != nil { + log.Fatal("failed to connect database", err) + } + defer db.Close() + + var dbName string + err = db.QueryRow("SELECT DATABASE();").Scan(&dbName) + if err != nil { + log.Fatal("failed to execute query", err) + } + fmt.Println(dbName) +} +``` + +参数说明: + +- 在 TLS 连接配置中注册 `tls.Config` 以启用 TLS 并验证 TiDB Cloud Dedicated 集群。 +- 设置 `MinVersion: tls.VersionTLS12` 限制 TLS 协议的版本。 +- 设置 `ServerName: ""` 验证 TiDB Cloud Dedicated 的主机名。 +- 如果你不想注册新的 TLS 配置,可以在连接字符串中直接设置 `tls=true`。 + +
+ +
+ +这里以 [Mysql2](https://www.npmjs.com/package/mysql2) 的 TLS 连接配置为例。 + +``` +var connection = mysql.createConnection({ + host: 'tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com', + port: 4000, + user: 'root', + password: '', + database: 'test', + ssl: { + ca: fs.readFileSync('ca.pem'), + minVersion: 'TLSv1.2', + rejectUnauthorized: true + } +}); +``` + +你可以点击**显示示例用法**查看详细的代码示例。 + +``` +var mysql = require('mysql2'); +var fs = require('fs'); +var connection = mysql.createConnection({ + host: 'tidb.srgnqxji5bc.clusters.staging.tidb-cloud.com', + port: 4000, + user: 'root', + password: '', + database: 'test', + ssl: { + ca: fs.readFileSync('ca.pem'), + minVersion: 'TLSv1.2', + rejectUnauthorized: true + } +}); +connection.connect(function(err) { + if (err) { + throw err + } + connection.query('SELECT DATABASE();', function(err, rows) { + if (err) { + throw err + } + console.log(rows[0]['DATABASE()']); + connection.end() + }); +}); +``` + +参数说明: + +- 设置 `ssl: {minVersion: 'TLSv1.2'}` 限制 TLS 协议的版本。如果要使用 TLS 1.3,可以将版本设置为 `TLSv1.3`。 +- 设置 `ssl: {ca: fs.readFileSync('')}` 读取下载的 TiDB 集群 `ca.pem` 的本地路径。 + +
+
+ +## 管理 TiDB Cloud Dedicated 的根证书 + +TiDB Cloud Dedicated 使用来自 [AWS Certificate Manager (ACM)](https://aws.amazon.com/certificate-manager/) 的证书作为客户端和 TiDB Cloud Dedicated 集群之间 TLS 连接的证书颁发机构(CA)。通常,ACM 的根证书安全地存储在符合 [FIPS 140-2 Level 3](https://csrc.nist.gov/projects/cryptographic-module-validation-program/Certificate/3139) 安全标准的 AWS 托管硬件安全模块(HSMs)中。 + +## 常见问题 + +### 连接到 TiDB Cloud Dedicated 集群支持哪些 TLS 版本? + +出于安全考虑,TiDB Cloud Dedicated 仅支持 TLS 1.2 和 TLS 1.3,不支持 TLS 1.0 和 TLS 1.1 版本。详情请参阅 IETF [弃用 TLS 1.0 和 TLS 1.1](https://datatracker.ietf.org/doc/rfc8996/)。 + +### 是否支持客户端和 TiDB Cloud Dedicated 之间的双向 TLS 认证? + +不支持。 + +TiDB Cloud Dedicated 目前仅支持单向 TLS 认证,不支持双向 TLS 认证。如果你需要双向 TLS 认证,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 diff --git a/tidb-cloud/tidb-cloud-tune-performance-overview.md b/tidb-cloud/tidb-cloud-tune-performance-overview.md new file mode 100644 index 000000000000..9623bc7bdac0 --- /dev/null +++ b/tidb-cloud/tidb-cloud-tune-performance-overview.md @@ -0,0 +1,128 @@ +--- +title: 性能分析和调优概述 +summary: 了解如何在 TiDB Cloud 中分析和调优 SQL 性能。 +--- + +# 性能分析和调优概述 + +本文档介绍帮助您在 TiDB Cloud 中分析和调优 SQL 性能的步骤。 + +## 用户响应时间 + +用户响应时间表示应用程序返回用户请求结果所需的时间。从以下顺序时序图中可以看出,典型的用户请求时间包含以下内容: + +- 用户与应用程序之间的网络延迟 +- 应用程序的处理时间 +- 应用程序与数据库交互期间的网络延迟 +- 数据库的服务时间 + +用户响应时间受请求链上各个子系统的影响,如网络延迟和带宽、并发用户的数量和请求类型、服务器 CPU 和 I/O 的资源使用情况。要有效优化整个系统,您需要首先识别用户响应时间中的瓶颈。 + +要获取指定时间范围(`ΔT`)内的总用户响应时间,您可以使用以下公式: + +`ΔT` 内的总用户响应时间 = 平均 TPS(每秒事务数)x 平均用户响应时间 x `ΔT`。 + +![user_response_time](/media/performance/user_response_time_en.png) + +## 用户响应时间与系统吞吐量的关系 + +用户响应时间由服务时间、排队时间和完成用户请求的并发等待时间组成。 + +``` +用户响应时间 = 服务时间 + 排队延迟 + 一致性延迟 +``` + +- 服务时间:系统在处理请求时消耗某些资源的时间,例如,数据库完成 SQL 请求所消耗的 CPU 时间。 +- 排队延迟:系统在处理请求时等待某些资源服务的队列时间。 +- 一致性延迟:系统在处理请求时与其他并发任务通信和协作的时间,以便它可以访问共享资源。 + +系统吞吐量表示系统每秒可以完成的请求数。用户响应时间和吞吐量通常是相互反比的。当吞吐量增加时,系统资源利用率和请求服务的排队延迟相应增加。一旦资源利用率超过某个拐点,排队延迟将急剧增加。 + +例如,对于运行 OLTP 负载的数据库系统,当其 CPU 利用率超过 65% 后,CPU 排队调度延迟会显著增加。这是因为系统的并发请求并非完全独立,这意味着这些请求可以协作和竞争共享资源。例如,来自不同用户的请求可能对相同的数据执行互斥锁定操作。当资源利用率增加时,排队和调度延迟也会增加,这导致共享资源无法及时释放,进而延长了其他任务等待共享资源的时间。 + +## 排查用户响应时间中的瓶颈 + +TiDB Cloud 控制台中有几个页面可以帮助您排查用户响应时间。 + +- [**诊断**](/tidb-cloud/tune-performance.md#view-the-diagnosis-page): + + - **SQL 语句**使您能够直接在页面上观察 SQL 执行情况,无需查询系统表即可轻松定位性能问题。您可以点击 SQL 语句进一步查看查询的执行计划以进行故障排除和分析。有关 SQL 性能调优的更多信息,请参见 [SQL 调优概述](/tidb-cloud/tidb-cloud-sql-tuning-overview.md)。 + - **Key Visualizer** 帮助您观察 TiDB 的数据访问模式和数据热点。 + +- [**指标**](/tidb-cloud/built-in-monitoring.md#view-the-metrics-page):在此页面上,您可以查看请求单位、已用存储大小、每秒查询数和平均查询持续时间等指标。 + +要请求其他指标,请联系 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)。 + +如果您遇到延迟和性能问题,请参考以下部分中的步骤进行分析和故障排除。 + +### TiDB 集群外部的瓶颈 + +观察**概览**标签页上的延迟(P80)。如果此值远低于用户响应时间的 P80 值,您可以确定主要瓶颈可能在 TiDB 集群之外。在这种情况下,您可以使用以下步骤排查瓶颈。 + +1. 在[概览标签页](/tidb-cloud/monitor-tidb-cluster.md)左侧查看 TiDB 版本。如果是 v6.0.0 或更早版本,建议联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)确认是否可以启用 Prepared plan cache、Raft-engine 和 TiKV AsyncIO 功能。启用这些功能,再加上应用程序端的调优,可以显著提高吞吐性能并降低延迟和资源利用率。 +2. 如有必要,您可以增加 TiDB token 限制以提高吞吐量。 +3. 如果启用了 prepared plan cache 功能,并且您在用户端使用 JDBC,建议使用以下配置: + + ``` + useServerPrepStmts=true&cachePrepStmts=true& prepStmtCacheSize=1000&prepStmtCacheSqlLimit=20480&useConfigs=maxPerformance + ``` + + 如果您不使用 JDBC 并且想要充分利用当前 TiDB 集群的 prepared plan cache 功能,您需要在客户端缓存 prepared statement 对象。您不需要重置对 StmtPrepare 和 StmtClose 的调用。将每个查询要调用的命令数从 3 减少到 1。这需要一些开发工作,具体取决于您的性能要求和客户端更改的数量。您可以咨询 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +### TiDB 集群中的瓶颈 + +如果您确定性能瓶颈在 TiDB 集群内,建议您执行以下操作: + +- 优化慢 SQL 查询。 +- 解决热点问题。 +- 扩容集群以扩展容量。 + +#### 优化慢 SQL 查询 + +有关 SQL 性能调优的更多信息,请参见 [SQL 调优概述](/tidb-cloud/tidb-cloud-sql-tuning-overview.md)。 + +#### 解决热点问题 + +您可以在 [Key Visualizer 标签页](/tidb-cloud/tune-performance.md#key-visualizer)上查看热点问题。以下截图显示了一个热力图示例。图的横坐标是时间,纵坐标是表和索引。颜色越亮表示流量越高。您可以在工具栏中切换显示读取或写入流量。 + +![热点问题](/media/tidb-cloud/tidb-cloud-troubleshoot-hotspot.png) + +以下截图显示了一个写入热点的示例。在写入流量图中出现一条明亮的对角线(向上或向下对角),写入流量仅出现在线的末端。随着表 Region 数量的增长,它变成阶梯状模式。这表明表中存在写入热点。当出现写入热点时,您需要检查是否使用了自增主键,或者没有主键,或者使用了依赖时间的插入语句或索引。 + +![写入热点](/media/tidb-cloud/tidb-cloud-troubleshoot-write-hotspot.png) + +读取热点在热力图中通常表现为一条明亮的水平线,通常是一个查询量大的小表,如下截图所示。 + +![读取热点](/media/tidb-cloud/tidb-cloud-troubleshoot-read-hotspot-new.png) + +将鼠标悬停在高亮块上可以看到哪个表或索引有高流量,如下截图所示。 + +![热点索引](/media/tidb-cloud/tidb-cloud-troubleshoot-hotspot-index.png) + +#### 扩容 + +在集群[概览](/tidb-cloud/monitor-tidb-cluster.md)页面上,检查存储空间、CPU 利用率和 TiKV IO 速率指标。如果其中任何一个长期接近上限,可能是当前集群规模无法满足业务需求。建议联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)确认是否需要扩容集群。 + +#### 其他问题 + +如果上述方法无法解决性能问题,您可以联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。建议提供以下信息以加快故障排除过程。 + +- 集群 ID +- 问题时间段和一个可比较的正常时间段 +- 问题现象和预期行为 +- 业务工作负载特征,如读写比例和主要行为 + +## 总结 + +一般来说,您可以使用以下优化方法来分析和解决性能问题。 + +| 操作 | 效果 | +|:--|:--| +| Prepared plan cache + JDBC | 吞吐性能将大幅提升,延迟将显著降低,平均 TiDB CPU 利用率将显著降低。 | +| 在 TiKV 中启用 AsyncIO 和 Raft-engine | 吞吐性能会有一定提升。您需要联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)启用它。 | +| 聚簇索引 | 吞吐性能将大幅提升。 | +| 扩容 TiDB 节点 | 吞吐性能将大幅提升。 | +| 客户端优化。将 1 个 JVM 拆分为 3 个 | 吞吐性能将显著提升,如果进一步拆分可能会继续提高吞吐容量。 | +| 限制应用程序和数据库之间的网络延迟 | 高网络延迟会导致吞吐量降低和延迟增加。 | + +未来,TiDB Cloud 将引入更多可观察的指标和自诊断服务。它们将为您提供更全面的性能指标理解和运营建议,以改善您的使用体验。 diff --git a/tidb-cloud/tidb-node-group-management.md b/tidb-cloud/tidb-node-group-management.md new file mode 100644 index 000000000000..11f0ad326f19 --- /dev/null +++ b/tidb-cloud/tidb-node-group-management.md @@ -0,0 +1,160 @@ +--- +title: 管理 TiDB 节点组 +summary: 了解如何管理 TiDB 节点组及其端点以隔离业务工作负载。 +--- + +# 管理 TiDB 节点组 + +本文介绍如何使用 [TiDB Cloud 控制台](https://tidbcloud.com/)管理 TiDB 节点组及其端点,以隔离业务工作负载。 + +> **注意**: +> +> TiDB 节点组功能**不适用于** TiDB Cloud Serverless 集群。 + +## 术语 + +- TiDB 节点组:TiDB 节点组管理 TiDB 节点的分组,并维护端点和 TiDB 节点之间的映射关系。 + + - 每个 TiDB 节点组都有一个唯一的端点。 + - 当你删除 TiDB 节点组时,相关的网络设置(如私有链接和 IP 访问列表)也会被删除。 + +- 默认组:创建集群时会创建一个默认的 TiDB 节点组。因此,每个集群都有一个默认组。默认组不能被删除。 + +## 前提条件 + +- 你已经在 AWS 或 Google Cloud 上部署了一个 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 +- 你在组织中担任**组织所有者**或**项目所有者**角色。更多信息,请参见[用户角色](/tidb-cloud/manage-user-access.md#user-roles)。 + +> **注意**: +> +> 在创建集群时无法创建 TiDB 节点组。你需要在集群创建完成并处于**可用**状态后添加节点组。 + +## 创建 TiDB 节点组 + +要创建 TiDB 节点组,请执行以下步骤: + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,导航到项目的[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +2. 在左侧导航栏中,点击**节点**。 +3. 点击右上角的**修改**。此时会显示**修改集群**页面。 +4. 在**修改集群**页面上,点击 **+** 添加新的 TiDB 节点组,如下所示。你也可以直接使用默认组。 + + - TiDB + - **vCPU + RAM**:选择你需要的 [TiDB 规格](/tidb-cloud/size-your-cluster.md#size-tidb)。仅支持 8 vCPU 和 16 GiB 内存或更高规格的 TiDB 节点。 + - **节点组**:点击 **+** 创建新的 TiDB 节点组。你也可以使用默认组,并在 **DefaultGroup** 字段中输入 TiDB 节点数量。 + + - TiKV + - **vCPU + RAM**:选择你需要的 [TiKV 规格](/tidb-cloud/size-your-cluster.md#size-tikv)。 + - **存储 x 节点**:选择存储大小和 TiKV 节点数量。 + + - TiFlash(可选) + - **vCPU + RAM**:选择你需要的 [TiFlash 规格](/tidb-cloud/size-your-cluster.md#size-tiflash)。 + - **存储 x 节点**:选择存储大小和 TiFlash 节点数量。 + + ![创建 TiDB 节点组](/media/tidb-cloud/tidb-node-group-create.png) + +5. 新的 TiDB 节点会随新的 TiDB 节点组一起添加,这会影响集群的计费。在右侧窗格中查看集群大小,然后点击**确认**。 + +默认情况下,你最多可以为 TiDB Cloud Dedicated 集群创建五个 TiDB 节点组。如果你需要更多节点组,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +如果你创建了 TiDB 节点组但仍使用默认组的端点连接集群,TiDB 节点组中的 TiDB 节点将不会承担任何工作负载,这会浪费资源。你需要创建新的连接来连接新 TiDB 节点组中的 TiDB 节点。请参见[连接到 TiDB 节点组](#连接到-tidb-节点组)。 + +## 连接到 TiDB 节点组 + +### 通过公共连接连接 + +新 TiDB 节点组的公共连接默认是禁用的。你需要先启用它。 + +要启用公共连接,请执行以下操作: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +2. 在右上角点击**连接**。此时会显示连接对话框。 +3. 从 **TiDB 节点组**列表中选择你的 TiDB 节点组,从**连接类型**列表中选择**公共**。 + + 如果你尚未配置 IP 访问列表,请点击**配置 IP 访问列表**或按照[配置 IP 访问列表](https://docs.pingcap.com/tidbcloud/configure-ip-access-list)中的步骤进行配置,然后再进行首次连接。 + +4. 在左侧导航栏中,点击**设置** > **网络**。 +5. 在**网络**页面上,从右上角的 **TiDB 节点组**列表中选择你的 TiDB 节点组。 +6. 在**公共端点**部分点击**启用**,然后在 **IP 访问列表**部分点击**添加 IP 地址**。 +7. 在**网络**页面的右上角点击**连接**以获取连接字符串。 + +![通过公共端点连接到新的 TiDB 节点组](/media/tidb-cloud/tidb-node-group-connect-public-endpoint.png) + +更多信息,请参见[通过公共连接连接到 TiDB Cloud Dedicated](/tidb-cloud/connect-via-standard-connection.md)。 + +### 通过私有端点连接 + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +2. 在右上角点击**连接**。此时会显示连接对话框。 +3. 从 **TiDB 节点组**列表中选择你的 TiDB 节点组,从**连接类型**列表中选择**私有端点**。 +4. 在左侧导航栏中,点击**设置** > **网络**。 +5. 在**网络**页面上,从右上角的 **TiDB 节点组**列表中选择你的 TiDB 节点组。 +6. 点击**创建私有端点连接**为此节点组创建新连接。 + + - 对于部署在 AWS 上的集群,请参考[通过 AWS PrivateLink 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections.md)。 + - 对于部署在 Google Cloud 上的集群,请参考[通过 Google Cloud Private Service Connect 连接到 TiDB Cloud Dedicated 集群](/tidb-cloud/set-up-private-endpoint-connections-on-google-cloud.md)。 + + > **注意**: + > + > 如果你使用 Private Link 连接不同的节点组,你需要为每个节点组创建单独的私有端点连接。 + +7. 创建私有端点连接后,点击页面右上角的**连接**以获取连接字符串。 + +### 通过 VPC 对等连接连接 + +由于所有 TiDB 节点组共享集群的同一个 VPC,你只需创建一个 VPC 对等连接即可启用所有组的访问。 + +1. 按照[通过 VPC 对等连接连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-vpc-peering-connections.md)中的说明为此集群创建 VPC 对等连接。 +2. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +3. 在左侧导航栏中,点击**设置** > **网络**。 +4. 在**网络**页面的右上角点击**连接**以获取连接字符串。 + +## 查看 TiDB 节点组 + +要查看 TiDB 节点组的详细信息,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +2. 在左侧导航栏中,点击**节点**以查看 TiDB 节点组列表。 + + 要切换到表格视图,请点击 。 + +## 修改 TiDB 节点组 + +你可以修改组名和组中的节点配置。 + +### 更改组名 + +要更改组名,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +2. 在左侧导航栏中,点击**节点**。 +3. 点击 并为 TiDB 节点组输入新名称。 + +### 更新节点配置 + +要更新组中的 TiDB、TiKV 或 TiFlash 节点配置,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +2. 在左侧导航栏中,点击**节点**。 +3. 在**节点地图**页面上,点击右上角的**修改**。此时会显示**修改集群**页面。 +4. 在**修改集群**页面上,你可以: + + - 更改 TiDB 节点数量。 + - 添加新的节点组。 + - 更新 TiKV 和 TiFlash 节点的规格和**存储 x 节点**配置。 + +![更改 TiDB 节点组节点数量](/media/tidb-cloud/tidb-node-group-change-node-count.png) + +## 删除 TiDB 节点组 + +> **注意**: +> +> 当你删除 TiDB 节点组时,其节点和网络配置也会被删除,包括私有端点连接和用于公共访问的 IP 列表。 + +要删除 TiDB 节点组,请执行以下步骤: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 +2. 在左侧导航栏中,点击**节点**。 +3. 在**节点地图**页面上,点击右上角的**修改**。此时会显示**修改集群**页面。 +4. 在**修改集群**页面上,点击 删除 TiDB 节点组。 + +![删除 TiDB 节点组](/media/tidb-cloud/tidb-node-group-delete.png) diff --git a/tidb-cloud/tidb-node-group-overview.md b/tidb-cloud/tidb-node-group-overview.md new file mode 100644 index 000000000000..c4ef789e6916 --- /dev/null +++ b/tidb-cloud/tidb-node-group-overview.md @@ -0,0 +1,61 @@ +--- +title: TiDB 节点组概览 +summary: 了解 TiDB 节点组功能的实现和使用场景。 +--- + +# TiDB 节点组概览 + +你可以为 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群创建 TiDB 节点组。TiDB 节点组在物理上对集群的计算节点(TiDB 层)进行分组,每个组包含特定数量的 TiDB 节点。这种配置提供了组之间计算资源的物理隔离,使多业务场景下的资源分配更加高效。 + +通过 TiDB 节点组,你可以根据业务需求将计算节点划分为多个 TiDB 节点组,并为每个 TiDB 节点组配置唯一的连接端点。你的应用程序通过各自的端点连接到集群,请求会路由到相应的节点组进行处理。这确保了一个组中的资源过度使用不会影响其他组。 + +> **注意**: +> +> TiDB 节点组功能**不适用于** TiDB Cloud Serverless 集群。 + +## 实现原理 + +TiDB 节点组管理 TiDB 节点的分组,并维护端点与其对应 TiDB 节点之间的映射关系。 + +每个 TiDB 节点组都关联一个专用的负载均衡器。当用户向 TiDB 节点组的端点发送 SQL 请求时,请求首先通过该组的负载均衡器,然后仅路由到该组内的 TiDB 节点。 + +下图说明了 TiDB 节点组功能的实现原理。 + +![TiDB 节点组功能的实现原理](/media/tidb-cloud/implementation-of-tidb-node-group.png) + +TiDB 节点组中的所有节点都响应来自相应端点的请求。你可以执行以下任务: + +- 创建 TiDB 节点组并为其分配 TiDB 节点。 +- 为每个组设置连接端点。支持的连接类型包括[公共连接](/tidb-cloud/tidb-node-group-management.md#connect-via-public-connection)、[私有端点](/tidb-cloud/tidb-node-group-management.md#connect-via-private-endpoint)和 [VPC 对等连接](/tidb-cloud/tidb-node-group-management.md#connect-via-vpc-peering)。 +- 通过使用不同的端点将应用程序路由到特定组,实现资源隔离。 + +## 使用场景 + +TiDB 节点组功能显著增强了 TiDB Cloud Dedicated 集群的资源分配能力。TiDB 节点专门用于计算,不存储数据。通过将节点组织成多个物理组,该功能确保一个组中的资源过度使用不会影响其他组。 + +使用此功能,你可以: + +- 将来自不同系统的多个应用程序整合到一个 TiDB Cloud Dedicated 集群中。随着应用程序工作负载的增长,它不会影响其他应用程序的正常运行。TiDB 节点组功能确保事务应用程序的响应时间不会受到数据分析或批处理应用程序的影响。 + +- 在 TiDB Cloud Dedicated 集群上执行导入或 DDL 任务,而不影响现有生产工作负载的性能。你可以为导入或 DDL 任务创建一个单独的 TiDB 节点组。即使这些任务消耗大量 CPU 或内存资源,它们也只使用自己 TiDB 节点组中的资源,确保其他 TiDB 节点组中的工作负载不受影响。 + +- 将所有测试环境合并到一个 TiDB 集群中,或将资源密集型批处理任务组合到一个专用的 TiDB 节点组中。这种方法提高了硬件利用率,降低了运营成本,并确保关键应用程序始终能够访问必要的资源。 + +此外,TiDB 节点组易于扩容或缩容。对于具有高性能要求的关键应用程序,你可以根据需要为该组分配 TiDB 节点。对于要求较低的应用程序,你可以从少量 TiDB 节点开始,并根据需要进行扩容。高效使用 TiDB 节点组功能可以减少集群数量,简化运维,并降低管理成本。 + +## 限制和配额 + +目前,TiDB 节点组功能是免费的。以下是限制和配额: + +- 你只能为 AWS 或 Google Cloud 上的 TiDB Cloud Dedicated 集群创建 TiDB 节点组。对其他云提供商的支持计划在不久的将来推出。 +- 具有 4 个 vCPU 和 16 GiB 内存的 TiDB 集群不支持 TiDB 节点组功能。 +- 默认情况下,你最多可以为一个 TiDB Cloud Dedicated 集群创建五个 TiDB 节点组。如果你需要更多组,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 +- 每个 TiDB 节点组必须至少包含一个 TiDB 节点。虽然一个组中的节点数量没有限制,但 TiDB Cloud Dedicated 集群中的 TiDB 节点总数不得超过 150 个。 +- TiDB Cloud 在 TiDB owner 节点上运行自动统计信息收集任务,不考虑节点组边界。这些任务无法在单个 TiDB 节点组内隔离。 +- 对于早于 v8.1.2 版本的 TiDB 集群,`ADD INDEX` 任务无法在单个 TiDB 节点组内隔离。 + +## SLA 影响 + +根据 TiDB Cloud [服务级别协议 (SLA)](https://www.pingcap.com/legal/service-level-agreement-for-tidb-cloud-services/),具有多个 TiDB 节点部署的 TiDB Cloud Dedicated 集群的每月正常运行时间百分比可达到 99.99%。但是,在引入 TiDB 节点组后,如果你创建多个 TiDB 节点组,每个组只有 1 个 TiDB 节点,你将失去这些组的高可用性,你的集群的每月正常运行时间百分比将降级为单个 TiDB 节点部署模式(即最高 99.9%)。 + +为了实现高可用性,建议为每个 TiDB 节点组配置至少两个 TiDB 节点。 diff --git a/tidb-cloud/transaction-concepts.md b/tidb-cloud/transaction-concepts.md new file mode 100644 index 000000000000..3f6a119fe9b8 --- /dev/null +++ b/tidb-cloud/transaction-concepts.md @@ -0,0 +1,40 @@ +--- +title: 事务 +summary: 了解 TiDB Cloud 的事务概念。 +--- + +# 事务 + +TiDB 提供完整的分布式事务支持,其模型在 [Google Percolator](https://research.google.com/pubs/pub36726.html) 的基础上进行了一些优化。 + +## 乐观事务模式 + +TiDB 的乐观事务模型在提交阶段才检测冲突。如果存在冲突,事务需要重试。但是,如果冲突严重,这种模式的效率会很低,因为重试前的操作都是无效的,需要重新执行。 + +假设数据库被用作计数器。高并发访问可能会导致严重的冲突,从而导致多次重试甚至超时。因此,在冲突严重的场景下,建议使用悲观事务模式,或者在系统架构层面解决问题,比如将计数器放在 Redis 中。不过,如果访问冲突不是很严重,乐观事务模型的效率还是很高的。 + +更多信息,请参阅 [TiDB 乐观事务模型](/optimistic-transaction.md)。 + +## 悲观事务模式 + +在 TiDB 中,悲观事务模式的行为与 MySQL 几乎相同。事务在执行阶段就会加锁,这样可以避免冲突情况下的重试,确保更高的成功率。通过使用悲观锁定,你还可以使用 `SELECT FOR UPDATE` 提前锁定数据。 + +但是,如果应用场景的冲突较少,乐观事务模型会有更好的性能表现。 + +更多信息,请参阅 [TiDB 悲观事务模式](/pessimistic-transaction.md)。 + +## 事务隔离级别 + +事务隔离是数据库事务处理的基础之一。隔离是事务的四个关键属性之一(通常称为 [ACID](/tidb-cloud/tidb-cloud-glossary.md#acid))。 + +TiDB 实现了快照隔离(Snapshot Isolation,SI)一致性,为了与 MySQL 兼容,将其标识为 `REPEATABLE-READ`。这与 [ANSI 可重复读隔离级别](/transaction-isolation-levels.md#difference-between-tidb-and-ansi-repeatable-read)和 [MySQL 可重复读级别](/transaction-isolation-levels.md#difference-between-tidb-and-mysql-repeatable-read)有所不同。 + +更多信息,请参阅 [TiDB 事务隔离级别](/transaction-isolation-levels.md)。 + +## 非事务性 DML 语句 + +非事务性 DML 语句是一个被拆分成多个 SQL 语句(即多个批次)按顺序执行的 DML 语句。它通过牺牲事务的原子性和隔离性来提高批量数据处理的性能和易用性。 + +通常,内存消耗大的事务需要被拆分成多个 SQL 语句以绕过事务大小限制。非事务性 DML 语句将这个过程集成到 TiDB 内核中以实现相同的效果。通过拆分 SQL 语句来理解非事务性 DML 语句的效果会很有帮助。可以使用 `DRY RUN` 语法来预览拆分后的语句。 + +更多信息,请参阅[非事务性 DML 语句](/non-transactional-dml.md)。 diff --git a/tidb-cloud/troubleshoot-import-access-denied-error.md b/tidb-cloud/troubleshoot-import-access-denied-error.md new file mode 100644 index 000000000000..c12fe546eda6 --- /dev/null +++ b/tidb-cloud/troubleshoot-import-access-denied-error.md @@ -0,0 +1,236 @@ +--- +title: 排查从 Amazon S3 导入数据时的访问被拒绝错误 +summary: 了解如何排查从 Amazon S3 导入数据到 TiDB Cloud 时的访问被拒绝错误。 +--- + +# 排查从 Amazon S3 导入数据时的访问被拒绝错误 + +本文介绍如何排查从 Amazon S3 导入数据到 TiDB Cloud 时可能出现的访问被拒绝错误。 + +在 TiDB Cloud 控制台的**数据导入**页面上点击**下一步**并确认导入过程后,TiDB Cloud 开始验证是否可以访问你指定的存储桶 URI 中的数据。如果你看到包含关键字 `AccessDenied` 的错误消息,则表示发生了访问被拒绝错误。 + +要排查访问被拒绝错误,请在 AWS 管理控制台中执行以下检查。 + +## 无法承担提供的角色 + +本节介绍如何排查 TiDB Cloud 无法承担提供的角色来访问指定存储桶的问题。 + +### 检查信任实体 + +1. 在 AWS 管理控制台中,转到 **IAM** > **访问管理** > **角色**。 +2. 在角色列表中,找到并点击你为目标 TiDB 集群创建的角色。此时会显示角色摘要页面。 +3. 在角色摘要页面上,点击**信任关系**标签页,你将看到受信任的实体。 + +以下是信任实体的示例: + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::380838443567:root" + }, + "Action": "sts:AssumeRole", + "Condition": { + "StringEquals": { + "sts:ExternalId": "696e6672612d617069a79c22fa5740944bf8bb32e4a0c4e3fe" + } + } + } + ] +} +``` + +在示例信任实体中: + +- `380838443567` 是 TiDB Cloud 账户 ID。确保你的信任实体中的此字段与你的 TiDB Cloud 账户 ID 匹配。 +- `696e6672612d617069a79c22fa5740944bf8bb32e4a0c4e3fe` 是 TiDB Cloud 外部 ID。确保你的信任实体中的此字段与你的 TiDB Cloud 外部 ID 匹配。 + +### 检查 IAM 角色是否存在 + +如果 IAM 角色不存在,请按照[配置 Amazon S3 访问](/tidb-cloud/dedicated-external-storage.md#configure-amazon-s3-access)中的说明创建角色。 + +### 检查外部 ID 是否正确设置 + +无法承担提供的角色 `{role_arn}`。检查角色上的信任关系设置。例如,检查信任实体是否已设置为 `TiDB Cloud 账户 ID`,以及信任条件中是否正确设置了 `TiDB Cloud 外部 ID`。请参见[检查信任实体](#检查信任实体)。 + +## 访问被拒绝 + +本节介绍如何排查访问问题。 + +### 检查 IAM 用户的策略 + +当你使用 IAM 用户的 AWS 访问密钥访问 Amazon S3 存储桶时,可能会遇到以下错误: + +- "使用访问密钥 ID '{access_key_id}' 和密钥 '{secret_access_key}' 访问源 '{bucket_uri}' 被拒绝" + +这表明 TiDB Cloud 由于权限不足而无法访问 Amazon S3 存储桶。你需要以下权限才能访问 Amazon S3 存储桶: + +- `s3:GetObject` +- `s3:ListBucket` +- `s3:GetBucketLocation` + +要检查 IAM 用户的策略,请执行以下步骤: + +1. 在 AWS 管理控制台中,转到 **IAM** > **访问管理** > **用户**。 +2. 在用户列表中,找到并点击你用于向 TiDB Cloud 导入数据的用户。此时会显示用户摘要页面。 +3. 在用户摘要页面的**权限策略**区域中,会显示策略列表。对每个策略执行以下步骤: + 1. 点击策略进入策略摘要页面。 + 2. 在策略摘要页面上,点击 **{}JSON** 标签页以检查权限策略。确保策略中的 `Resource` 字段配置正确。 + +以下是策略示例: + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "s3:GetObject" + ], + "Resource": "arn:aws:s3:::tidb-cloud-source-data/mydata/*" + }, + { + "Sid": "VisualEditor1", + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetBucketLocation" + ], + "Resource": "arn:aws:s3:::tidb-cloud-source-data" + }, +} +``` + +有关如何授予用户权限并测试权限的更多信息,请参见[使用用户策略控制对存储桶的访问](https://docs.aws.amazon.com/AmazonS3/latest/userguide/walkthrough1.html)。 + +### 检查 IAM 角色的策略 + +1. 在 AWS 管理控制台中,转到 **IAM** > **访问管理** > **角色**。 +2. 在角色列表中,找到并点击你为目标 TiDB 集群创建的角色。此时会显示角色摘要页面。 +3. 在角色摘要页面的**权限策略**区域中,会显示策略列表。对每个策略执行以下步骤: + 1. 点击策略进入策略摘要页面。 + 2. 在策略摘要页面上,点击 **{}JSON** 标签页以检查权限策略。确保策略中的 `Resource` 字段配置正确。 + +以下是策略示例: + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion" + ], + "Resource": "arn:aws:s3:::tidb-cloud-source-data/mydata/*" + }, + { + "Sid": "VisualEditor1", + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetBucketLocation" + ], + "Resource": "arn:aws:s3:::tidb-cloud-source-data" + }, + { + "Sid": "AllowKMSkey", + "Effect": "Allow", + "Action": [ + "kms:Decrypt" + ], + "Resource": "arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f" + } + ] +} +``` + +在此示例策略中,请注意以下几点: + +- 在 `"arn:aws:s3:::tidb-cloud-source-data/mydata/*"` 中,`"arn:aws:s3:::tidb-cloud-source-data"` 是示例 S3 存储桶 ARN,`/mydata/*` 是你可以在 S3 存储桶根级别自定义的用于数据存储的目录。目录需要以 `/*` 结尾,例如 `"<你的 S3 存储桶 ARN>/<源数据目录>/*"`。如果未添加 `/*`,则会出现 `AccessDenied` 错误。 + +- 如果你已启用带有客户管理密钥加密的 AWS Key Management Service 密钥(SSE-KMS),请确保策略中包含以下配置。`"arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f"` 是存储桶的示例 KMS 密钥。 + + ``` + { + "Sid": "AllowKMSkey", + "Effect": "Allow", + "Action": [ + "kms:Decrypt" + ], + "Resource": "arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f" + } + ``` + + 如果你的存储桶中的对象是从另一个加密的存储桶复制的,则 KMS 密钥值需要包含两个存储桶的密钥。例如,`"Resource": ["arn:aws:kms:ap-northeast-1:105880447796:key/c3046e91-fdfc-4f3a-acff-00597dd3801f","arn:aws:kms:ap-northeast-1:495580073302:key/0d7926a7-6ecc-4bf7-a9c1-a38f0faec0cd"]`。 + +如果你的策略未按照上述示例正确配置,请更正策略中的 `Resource` 字段,然后重试导入数据。 + +> **提示:** +> +> 如果你多次更新权限策略后在数据导入期间仍然收到 `AccessDenied` 错误,可以尝试撤销活动会话。转到 **IAM** > **访问管理** > **角色**,点击目标角色进入角色摘要页面。在角色摘要页面上,找到**撤销活动会话**并点击按钮以撤销活动会话。然后,重试数据导入。 +> +> 请注意,这可能会影响你的其他应用程序。 + +### 检查存储桶策略 + +1. 在 AWS 管理控制台中,打开 Amazon S3 控制台,然后转到**存储桶**页面。此时会显示存储桶列表。 +2. 在列表中,找到并点击目标存储桶。此时会显示存储桶信息页面。 +3. 点击**权限**标签页,然后向下滚动到**存储桶策略**区域。默认情况下,此区域没有策略值。如果在此区域显示任何拒绝策略,则在数据导入期间可能会出现 `AccessDenied` 错误。 + +如果你看到拒绝策略,请检查该策略是否与当前数据导入相关。如果是,请从该区域删除它,然后重试数据导入。 + +### 检查对象所有权 + +1. 在 AWS 管理控制台中,打开 Amazon S3 控制台,然后转到**存储桶**页面。此时会显示存储桶列表。 +2. 在存储桶列表中,找到并点击目标存储桶。此时会显示存储桶信息页面。 +3. 在存储桶信息页面上,点击**权限**标签页,然后向下滚动到**对象所有权**区域。确保"对象所有权"配置为"强制执行存储桶所有者"。 + + 如果配置不是"强制执行存储桶所有者",则会出现 `AccessDenied` 错误,因为你的账户对此存储桶中的所有对象没有足够的权限。 + +要处理此错误,请点击对象所有权区域右上角的**编辑**,并将所有权更改为"强制执行存储桶所有者"。请注意,这可能会影响正在使用此存储桶的其他应用程序。 + +### 检查存储桶加密类型 + +加密 S3 存储桶的方式不止一种。当你尝试访问存储桶中的对象时,你创建的角色必须具有访问加密密钥以进行数据解密的权限。否则,会出现 `AccessDenied` 错误。 + +要检查存储桶的加密类型,请执行以下步骤: + +1. 在 AWS 管理控制台中,打开 Amazon S3 控制台,然后转到**存储桶**页面。此时会显示存储桶列表。 +2. 在存储桶列表中,找到并点击目标存储桶。此时会显示存储桶信息页面。 +3. 在存储桶信息页面上,点击**属性**标签页,向下滚动到**默认加密**区域,然后检查此区域中的配置。 + +有两种类型的服务器端加密:Amazon S3 托管密钥(SSE-S3)和 AWS Key Management Service(SSE-KMS)。对于 SSE-S3,不需要进一步检查,因为此加密类型不会导致访问被拒绝错误。对于 SSE-KMS,你需要检查以下内容: + +- 如果区域中的 AWS KMS 密钥 ARN 以黑色显示且没有下划线,则 AWS KMS 密钥是 AWS 托管密钥(aws/s3)。 +- 如果区域中的 AWS KMS 密钥 ARN 以蓝色显示并带有链接,请点击密钥 ARN 以打开密钥信息页面。检查左侧导航栏以查看具体的加密类型。它可能是 AWS 托管密钥(aws/s3)或客户托管密钥。 + +
+对于 SSE-KMS 中的 AWS 托管密钥(aws/s3) + +在这种情况下,如果出现 `AccessDenied` 错误,原因可能是密钥是只读的,并且不允许跨账户权限授予。有关详细信息,请参见 AWS 文章[为什么跨账户用户在尝试访问由自定义 AWS KMS 密钥加密的 S3 对象时会收到访问被拒绝错误](https://aws.amazon.com/premiumsupport/knowledge-center/cross-account-access-denied-error-s3/)。 + +要解决访问被拒绝错误,请点击**默认加密**区域右上角的**编辑**,并将 AWS KMS 密钥更改为"从你的 AWS KMS 密钥中选择"或"输入 AWS KMS 密钥 ARN",或将服务器端加密类型更改为"AWS S3 托管密钥(SSE-S3)"。除了此方法外,你还可以创建新的存储桶并使用自定义托管密钥或 SSE-S3 加密方法。 +
+ +
+对于 SSE-KMS 中的客户托管密钥 + +要解决这种情况下的 `AccessDenied` 错误,请点击密钥 ARN 或手动在 KMS 中找到密钥。此时会显示**密钥用户**页面。点击区域右上角的**添加**以添加你用于向 TiDB Cloud 导入数据的角色。然后,重试导入数据。 + +
+ +> **注意:** +> +> 如果你的存储桶中的对象是从现有的加密存储桶复制的,你还需要在 AWS KMS 密钥 ARN 中包含源存储桶的密钥。这是因为你的存储桶中的对象使用与源对象加密相同的加密方法。有关更多信息,请参见 AWS 文档[将默认加密与复制一起使用](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-encryption.html)。 + +### 查看 AWS 文章获取说明 + +如果你已执行上述所有检查但仍收到 `AccessDenied` 错误,可以查看 AWS 文章[如何排查来自 Amazon S3 的 403 访问被拒绝错误](https://aws.amazon.com/premiumsupport/knowledge-center/s3-troubleshoot-403/)以获取更多说明。 diff --git a/tidb-cloud/tune-performance.md b/tidb-cloud/tune-performance.md new file mode 100644 index 000000000000..697786dd04b0 --- /dev/null +++ b/tidb-cloud/tune-performance.md @@ -0,0 +1,90 @@ +--- +title: 分析和调优性能 +summary: 了解如何分析和调优 TiDB Cloud 集群的性能。 +--- + +# 分析和调优性能 + +TiDB Cloud 提供[慢查询](#slow-query)、[SQL 语句分析](#statement-analysis)、[Key Visualizer](#key-visualizer) 和 [Index Insight (beta)](#index-insight-beta) 来分析性能。 + +- 慢查询让你可以搜索和查看 TiDB 集群中的所有慢查询,并通过查看其执行计划、SQL 执行信息和其他详细信息来探索每个慢查询的瓶颈。 + +- SQL 语句分析使你能够直接在页面上观察 SQL 执行情况,无需查询系统表即可轻松定位性能问题。 + +- Key Visualizer 帮助你观察 TiDB 的数据访问模式和数据热点。 + +- Index Insight 为你提供有意义且可操作的索引建议。 + +> **注意:** +> +> 目前,[TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群不支持 **Key Visualizer** 和 **Index Insight (beta)**。 + +## 查看诊断页面 + +1. 在项目的 [**集群**](https://tidbcloud.com/project/clusters) 页面上,点击目标集群的名称以进入其概览页面。 + + > **提示:** + > + > 你可以使用左上角的组合框在组织、项目和集群之间切换。 + +2. 在左侧导航栏中,点击 **监控** > **诊断**。 + +## 慢查询 + +默认情况下,执行时间超过 300 毫秒的 SQL 查询被视为慢查询。 + +要查看集群中的慢查询,请执行以下步骤: + +1. 导航到集群的[**诊断**](#view-the-diagnosis-page)页面。 + +2. 点击**慢查询**标签页。 + +3. 点击列表中的任何慢查询以显示其详细执行信息。 + +4. (可选)你可以根据目标时间范围、相关数据库和 SQL 关键字过滤慢查询。你还可以限制要显示的慢查询数量。 + +结果以表格形式显示,你可以按不同列对结果进行排序。 + +更多信息,请参阅 [TiDB Dashboard 中的慢查询](https://docs.pingcap.com/tidb/stable/dashboard-slow-query)。 + +## SQL 语句分析 + +要使用 SQL 语句分析,请执行以下步骤: + +1. 导航到集群的[**诊断**](#view-the-diagnosis-page)页面。 + +2. 点击 **SQL 语句**标签页。 + +3. 在时间间隔框中选择要分析的时间段。然后你可以获取该时间段内所有数据库的 SQL 语句执行统计信息。 + +4. (可选)如果你只关心某些数据库,可以在下一个框中选择相应的 schema 来过滤结果。 + +结果以表格形式显示,你可以按不同列对结果进行排序。 + +更多信息,请参阅 [TiDB Dashboard 中的 SQL 语句执行详情](https://docs.pingcap.com/tidb/stable/dashboard-statement-details)。 + +## Key Visualizer + +> **注意:** +> +> Key Visualizer 仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +要查看键分析,请执行以下步骤: + +1. 导航到集群的[**诊断**](#view-the-diagnosis-page)页面。 + +2. 点击 **Key Visualizer** 标签页。 + +在 **Key Visualizer** 页面上,一个大型热力图显示了访问流量随时间的变化。热力图每个轴的平均值显示在下方和右侧。左侧是表名、索引名和其他信息。 + +更多信息,请参阅 [Key Visualizer](https://docs.pingcap.com/tidb/stable/dashboard-key-visualizer)。 + +## Index Insight (beta) + +TiDB Cloud 中的 Index Insight 功能通过为未有效利用索引的慢查询提供推荐索引,提供了强大的查询性能优化能力。 + +> **注意:** +> +> Index Insight 目前处于 beta 阶段,仅适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群。 + +更多信息,请参阅 [Index Insight](/tidb-cloud/index-insight.md)。 diff --git a/tidb-cloud/upgrade-tidb-cluster.md b/tidb-cloud/upgrade-tidb-cluster.md new file mode 100644 index 000000000000..e953ac067dd1 --- /dev/null +++ b/tidb-cloud/upgrade-tidb-cluster.md @@ -0,0 +1,21 @@ +--- +title: 升级 TiDB 集群 +summary: 了解如何升级 TiDB 集群。 +--- + +# 升级 TiDB 集群 + +本文档描述了如何在 TiDB Cloud 上升级 TiDB 集群。TiDB Cloud 提供两种升级机制来升级你的 TiDB 版本。 + +## 定期升级 + +对于版本过低的 TiDB,TiDB Cloud 会统一进行定期升级,并在升级前后通过电子邮件通知用户。 + +## 联系支持进行升级 + +要提交升级请求,请按照 [TiDB Cloud 支持](/tidb-cloud/tidb-cloud-support.md)中的步骤联系我们的支持团队。注意在**描述**框中提供以下信息: + +- 云服务提供商:AWS、Azure 或 Google Cloud +- 集群名称:xxx + +TiDB Cloud 技术支持将与你确认升级时间段。在你确认升级时间后,TiDB Cloud 技术支持将在确认的时间段内进行升级。 diff --git a/tidb-cloud/use-chat2query-api.md b/tidb-cloud/use-chat2query-api.md new file mode 100644 index 000000000000..52651a76b754 --- /dev/null +++ b/tidb-cloud/use-chat2query-api.md @@ -0,0 +1,448 @@ +--- +title: Chat2Query API 入门指南 +summary: 了解如何使用 TiDB Cloud Chat2Query API,通过提供指令来生成和执行 SQL 语句。 +--- + +# Chat2Query API 入门指南 + +TiDB Cloud 提供 Chat2Query API,这是一个 RESTful 接口,使您能够通过提供指令来使用 AI 生成和执行 SQL 语句。然后,API 会为您返回查询结果。 + +Chat2Query API 只能通过 HTTPS 访问,确保所有通过网络传输的数据都使用 TLS 加密。 + +> **注意:** +> +> Chat2Query API 适用于 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群。要在 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群上使用 Chat2Query API,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +## 开始之前 + +在调用 Chat2Query 端点之前,您需要创建一个 Chat2Query Data App 并为该 Data App 创建一个 API 密钥。 + +### 创建 Chat2Query Data App + +要为您的项目创建 Data App,请执行以下步骤: + +1. 在项目的 [**Data Service**](https://tidbcloud.com/project/data-service) 页面,点击左侧窗格中的 **Create DataApp**。此时会显示数据应用创建对话框。 + + > **提示:** + > + > 如果您在集群的 **SQL Editor** 页面,也可以通过点击右上角的 **...** ,选择 **Access Chat2Query via API**,然后点击 **New Chat2Query Data App** 来打开数据应用创建对话框。 + +2. 在对话框中,为您的 Data App 定义一个名称,选择所需的集群作为数据源,并选择 **Chat2Query Data App** 作为 **Data App** 类型。您还可以选择为 App 编写描述。 + +3. 点击 **Create**。 + + 新创建的 Chat2Query Data App 将显示在左侧窗格中。在此 Data App 下,您可以找到 Chat2Query 端点列表。 + +### 创建 API 密钥 + +在调用端点之前,您需要为 Chat2Query Data App 创建一个 API 密钥,该密钥用于端点访问 TiDB Cloud 集群中的数据。 + +要创建 API 密钥,请执行以下步骤: + +1. 在 [**Data Service**](https://tidbcloud.com/project/data-service) 的左侧窗格中,点击您的 Chat2Query Data App 以在右侧查看其详细信息。 +2. 在 **Authentication** 区域,点击 **Create API Key**。 +3. 在 **Create API Key** 对话框中,输入描述,然后为您的 API 密钥选择以下角色之一: + + - `Chat2Query Admin`:允许 API 密钥管理数据摘要、根据提供的指令生成 SQL 语句,并执行任何 SQL 语句。 + - `Chat2Query Data Summary Management Role`:仅允许 API 密钥生成和更新数据摘要。 + + > **提示:** + > + > 对于 Chat2Query API,数据摘要是 AI 对您的数据库的分析结果,包括您的数据库描述、表描述和列描述。通过生成数据库的数据摘要,您可以在通过提供指令生成 SQL 语句时获得更准确的响应。 + + - `Chat2Query SQL ReadOnly`:仅允许 API 密钥根据提供的指令生成 SQL 语句并执行 `SELECT` SQL 语句。 + - `Chat2Query SQL ReadWrite`:允许 API 密钥根据提供的指令生成 SQL 语句并执行任何 SQL 语句。 + +4. 默认情况下,API 密钥永不过期。如果您想为密钥设置过期时间,请点击 **Expires in**,选择时间单位(`Minutes`、`Days` 或 `Months`),然后填写所需的时间单位数值。 + +5. 点击 **Next**。此时会显示公钥和私钥。 + + 确保您已将私钥复制并保存在安全的位置。离开此页面后,您将无法再次获取完整的私钥。 + +6. 点击 **Done**。 + +## 调用 Chat2Query 端点 + +> **注意:** +> +> 每个 Chat2Query Data App 每天有 100 个请求的速率限制。如果超过速率限制,API 将返回 `429` 错误。如需更多配额,您可以向我们的支持团队[提交请求](https://tidb.support.pingcap.com/)。 + +在每个 Chat2Query Data App 中,您可以找到以下端点: + +- Chat2Query v3 端点:名称以 `/v3` 开头的端点,如 `/v3/dataSummaries` 和 `/v3/chat2data`(推荐) +- Chat2Query v2 端点:名称以 `/v2` 开头的端点,如 `/v2/dataSummaries` 和 `/v2/chat2data` +- Chat2Query v1 端点:`/v1/chat2data`(已弃用) + +> **提示:** +> +> 与 `/v1/chat2data` 相比,`/v3/chat2data` 和 `/v2/chat2data` 需要您先通过调用 `/v3/dataSummaries` 或 `/v2/dataSummaries` 分析您的数据库。因此,`/v3/chat2data` 和 `/v2/chat2data` 返回的结果通常更准确。 + +### 获取端点的代码示例 + +TiDB Cloud 提供代码示例来帮助您快速调用 Chat2Query 端点。要获取 Chat2Query 端点的代码示例,请执行以下步骤: + +1. 在 [**Data Service**](https://tidbcloud.com/project/data-service) 页面的左侧窗格中,点击 Chat2Query 端点的名称。 + + 右侧将显示调用此端点的信息,如端点 URL、代码示例和请求方法。 + +2. 点击 **Show Code Example**。 + +3. 在显示的对话框中,选择要用于调用端点的集群、数据库和身份验证方法,然后复制代码示例。 + + > **注意:** + > + > 对于某些端点(如 `/v2/jobs/{job_id}`),您只需要选择身份验证方法。 + +4. 要调用端点,您可以将示例粘贴到您的应用程序中,用您自己的参数替换示例中的参数(如用您的 API 密钥替换 `${PUBLIC_KEY}` 和 `${PRIVATE_KEY}` 占位符),然后运行它。 + +### 调用 Chat2Query v3 端点或 v2 端点 + +TiDB Cloud Data Service 提供以下 Chat2Query v3 端点和 v2 端点: + +| 方法 | 端点 | 描述 | +| ------ | -------- | ----------- | +| POST | `/v3/dataSummaries` | 此端点使用人工智能分析为您的数据库模式、表模式和列模式生成数据摘要。 | +| GET | `/v3/dataSummaries` | 此端点检索您数据库的所有数据摘要。 | +| GET | `/v3/dataSummaries/{data_summary_id}` | 此端点检索特定的数据摘要。 | +| PUT | `/v3/dataSummaries/{data_summary_id}` | 此端点更新特定的数据摘要。 | +| PUT | `/v3/dataSummaries/{data_summary_id}/tables/{table_name}` | 此端点更新特定数据摘要中特定表的描述。 | +| PUT | `/v3/dataSummaries/{data_summary_id}/tables/{table_name}/columns` | 此端点更新特定数据摘要中特定表的列描述。 | +| POST | `/v3/knowledgeBases` | 此端点创建新的知识库。有关知识库相关端点的使用信息,请参见[使用知识库](/tidb-cloud/use-chat2query-knowledge.md)。 | +| GET | `/v3/knowledgeBases` | 此端点检索所有知识库。 | +| GET | `/v3/knowledgeBases/{knowledge_base_id}` | 此端点检索特定的知识库。 | +| PUT | `/v3/knowledgeBases/{knowledge_base_id}` | 此端点更新特定的知识库。 | +| POST | `/v3/knowledgeBases/{knowledge_base_id}/data` | 此端点向特定知识库添加数据。 | +| GET | `/v3/knowledgeBases/{knowledge_base_id}/data` | 此端点从特定知识库检索数据。 | +| PUT | `/v3/knowledgeBases/{knowledge_base_id}/data/{knowledge_data_id}` | 此端点更新知识库中的特定数据。 | +| DEL | `/v3/knowledgeBases/{knowledge_base_id}/data/{knowledge_data_id}` | 此端点从知识库中删除特定数据。 | +| POST | `/v3/sessions` | 此端点创建新的会话。有关会话相关端点的使用信息,请参见[开始多轮 Chat2Query](/tidb-cloud/use-chat2query-sessions.md)。 | +| GET | `/v3/sessions` | 此端点检索所有会话的列表。 | +| GET | `/v3/sessions/{session_id}` | 此端点检索特定会话的详细信息。 | +| PUT | `/v3/sessions/{session_id}` | 此端点更新特定会话。 | +| PUT | `/v3/sessions/{session_id}/reset` | 此端点重置特定会话。 | +| POST | `/v3/sessions/{session_id}/chat2data` | 此端点在特定会话中使用人工智能生成和执行 SQL 语句。更多信息,请参见[使用会话开始多轮 Chat2Query](/tidb-cloud/use-chat2query-sessions.md)。 | +| POST | `/v3/chat2data` | 此端点使您能够通过提供数据摘要 ID 和指令使用人工智能生成和执行 SQL 语句。 | +| POST | `/v3/refineSql` | 此端点使用人工智能优化现有的 SQL 查询。 | +| POST | `/v3/suggestQuestions` | 此端点根据提供的数据摘要建议问题。 | +| POST | `/v2/dataSummaries` | 此端点使用人工智能为您的数据库模式、表模式和列模式生成数据摘要。 | +| GET | `/v2/dataSummaries` | 此端点检索所有数据摘要。 | +| POST | `/v2/chat2data` | 此端点使您能够通过提供数据摘要 ID 和指令使用人工智能生成和执行 SQL 语句。 | +| GET | `/v2/jobs/{job_id}` | 此端点使您能够查询特定数据摘要生成作业的状态。 | + +调用 `/v3/chat2data` 和 `/v2/chat2data` 的步骤相同。以下部分以 `/v3/chat2data` 为例说明如何调用它。 + +#### 1. 通过调用 `/v3/dataSummaries` 生成数据摘要 + +在调用 `/v3/chat2data` 之前,先让 AI 分析数据库并通过调用 `/v3/dataSummaries` 生成数据摘要,这样 `/v3/chat2data` 在后续的 SQL 生成中可以获得更好的性能。 + +以下是调用 `/v3/dataSummaries` 分析 `sp500insight` 数据库并为该数据库生成数据摘要的代码示例: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v3/dataSummaries'\ + --header 'content-type: application/json'\ + --data-raw '{ + "cluster_id": "10140100115280519574", + "database": "sp500insight", + "description": "Data summary for SP500 Insight", + "reuse": false +}' +``` + +在上述示例中,请求体是一个具有以下属性的 JSON 对象: + +- `cluster_id`:_string_。TiDB 集群的唯一标识符。 +- `database`:_string_。数据库的名称。 +- `description`:_string_。数据摘要的描述。 +- `reuse`:_boolean_。指定是否重用现有的数据摘要。如果设置为 `true`,API 将重用现有的数据摘要。如果设置为 `false`,API 将生成新的数据摘要。 + +示例响应如下: + +```js +{ + "code": 200, + "msg": "", + "result": { + "data_summary_id": 304823, + "job_id": "fb99ef785da640ab87bf69afed60903d" + } +} +``` + +#### 2. 通过调用 `/v2/jobs/{job_id}` 检查分析状态 + +`/v3/dataSummaries` API 是异步的。对于具有大型数据集的数据库,可能需要几分钟才能完成数据库分析并返回完整的数据摘要。 + +要检查数据库的分析状态,您可以调用 `/v2/jobs/{job_id}` 端点,如下所示: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request GET 'https://.data.dev.tidbcloud.com/api/v1beta/app/chat2query-`/endpoint/v2/jobs/{job_id}'\ + --header 'content-type: application/json' +``` + +示例响应如下: + +```js +{ + "code": 200, + "msg": "", + "result": { + "ended_at": 1699518950, // 作业完成时的 UNIX 时间戳 + "job_id": "fb99ef785da640ab87bf69afed60903d", // 当前作业的 ID + "result": DataSummaryObject, // 给定数据库的 AI 探索信息 + "status": "done" // 当前作业的状态 + } +} +``` + +如果 `"status"` 为 `"done"`,则完整的数据摘要已准备就绪,您现在可以通过调用 `/v3/chat2data` 为此数据库生成和执行 SQL 语句。否则,您需要等待并稍后再次检查分析状态,直到完成。 + +在响应中,`DataSummaryObject` 表示给定数据库的 AI 探索信息。`DataSummaryObject` 的结构如下: + +```js +{ + "cluster_id": "10140100115280519574", // 集群 ID + "data_summary_id": 304823, // 数据摘要 ID + "database": "sp500insight", // 数据库名称 + "default": false, // 此数据摘要是否为默认摘要 + "status": "done", // 数据摘要的状态 + "description": { + "system": "Data source for financial analysis and decision-making in stock market", // AI 生成的数据摘要描述 + "user": "Data summary for SP500 Insight" // 用户提供的数据摘要描述 + }, + "keywords": ["User_Stock_Selection", "Index_Composition"], // 数据摘要的关键词 + "relationships": { + "companies": { + "referencing_table": "...", // 引用 `companies` 表的表 + "referencing_table_column": "..." // 引用 `companies` 表的列 + "referenced_table": "...", // `companies` 表引用的表 + "referenced_table_column": "..." // `companies` 表引用的列 + } + }, // 表之间的关系 + "summary": "Financial data source for stock market analysis", // 数据摘要的概要 + "tables": { // 数据库中的表 + "companies": { + "name": "companies" // 表名 + "description": "This table provides comprehensive...", // 表的描述 + "columns": { + "city": { // 表中的列 + "name": "city" // 列名 + "description": "The city where the company is headquartered.", // 列的描述 + } + }, + }, + } +} +``` + +#### 3. 通过调用 `/v3/chat2data` 生成和执行 SQL 语句 + +当数据库的数据摘要准备就绪时,您可以通过提供集群 ID、数据库名称和您的问题来调用 `/v3/chat2data` 生成和执行 SQL 语句。 + +例如: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v3/chat2data'\ + --header 'content-type: application/json'\ + --data-raw '{ + "cluster_id": "10140100115280519574", + "database": "sp500insight", + "question": "", + "sql_generate_mode": "direct" +}' +``` + +请求体是一个具有以下属性的 JSON 对象: + +- `cluster_id`:_string_。TiDB 集群的唯一标识符。 +- `database`:_string_。数据库的名称。 +- `data_summary_id`:_integer_。用于生成 SQL 的数据摘要的 ID。此属性仅在未提供 `cluster_id` 和 `database` 时生效。如果同时指定了 `cluster_id` 和 `database`,API 将使用数据库的默认数据摘要。 +- `question`:_string_。用自然语言描述您想要的查询的问题。 +- `sql_generate_mode`:_string_。生成 SQL 语句的模式。值可以是 `direct` 或 `auto_breakdown`。如果设置为 `direct`,API 将直接根据您提供的 `question` 生成 SQL 语句。如果设置为 `auto_breakdown`,API 将把 `question` 分解为多个任务,并为每个任务生成 SQL 语句。 + +示例响应如下: + +```js +{ + "code": 200, + "msg": "", + "result": { + "cluster_id": "10140100115280519574", + "database": "sp500insight", + "job_id": "20f7577088154d7889964f1a5b12cb26", + "session_id": 304832 + } +} +``` + +如果您收到状态码为 `400` 的响应,如下所示,这意味着您需要等待一段时间,让数据摘要准备就绪。 + +```js +{ + "code": 400, + "msg": "Data summary is not ready, please wait for a while and retry", + "result": {} +} +``` + +`/v3/chat2data` API 是异步的。您可以通过调用 `/v2/jobs/{job_id}` 端点来检查作业状态: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request GET 'https://.data.dev.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v2/jobs/{job_id}'\ + --header 'content-type: application/json' +``` + +示例响应如下: + +```js +{ + "code": 200, + "msg": "", + "result": { + "ended_at": 1718785006, // 作业完成时的 UNIX 时间戳 + "job_id": "20f7577088154d7889964f1a5b12cb26", + "reason": "", // 如果作业失败,则为失败原因 + "result": { + "assumptions": [], + "chart_options": { // 为结果生成的图表选项 + "chart_name": "Table", + "option": { + "columns": [ + "total_users" + ] + }, + "title": "Total Number of Users in the Database" + }, + "clarified_task": "Count the total number of users in the database.", // 任务的明确描述 + "data": { // SQL 语句返回的数据 + "columns": [ + { + "col": "total_users" + } + ], + "rows": [ + [ + "1" + ] + ] + }, + "description": "", + "sql": "SELECT COUNT(`user_id`) AS total_users FROM `users`;", // 生成的 SQL 语句 + "sql_error": null, // SQL 语句的错误消息 + "status": "done", // 作业的状态 + "task_id": "0", + "type": "data_retrieval" // 作业的类型 + }, + "status": "done" + } +} +``` + +### 调用 Chat2Data v1 端点(已弃用) + +> **注意:** +> +> Chat2Data v1 端点已弃用。建议您改用 Chat2Data v3 端点。 + +TiDB Cloud Data Service 提供以下 Chat2Query v1 端点: + +| 方法 | 端点| 描述 | +| ---- | ---- |---- | +| POST | `/v1/chat2data` | 此端点允许您通过提供目标数据库名称和指令使用人工智能生成和执行 SQL 语句。 | + +您可以直接调用 `/v1/chat2data` 端点来生成和执行 SQL 语句。与 `/v2/chat2data` 相比,`/v1/chat2data` 提供更快的响应但性能较低。 + +TiDB Cloud 生成代码示例来帮助您调用端点。要获取示例并运行代码,请参见[获取端点的代码示例](#获取端点的代码示例)。 + +调用 `/v1/chat2data` 时,您需要替换以下参数: + +- 用您的 API 密钥替换 `${PUBLIC_KEY}` 和 `${PRIVATE_KEY}` 占位符。 +- 用您要查询的表名替换 `` 占位符。如果不指定表名,AI 将查询数据库中的所有表。 +- 用您希望 AI 生成和执行 SQL 语句的指令替换 `` 占位符。 + +> **注意:** +> +> - 每个 Chat2Query Data App 每天有 100 个请求的速率限制。如果超过速率限制,API 将返回 `429` 错误。如需更多配额,您可以向我们的支持团队[提交请求](https://tidb.support.pingcap.com/)。 +> - 具有 `Chat2Query Data Summary Management Role` 角色的 API 密钥不能调用 Chat2Data v1 端点。 + +以下代码示例用于计算 `sp500insight.users` 表中有多少用户: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.dev.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/chat2data'\ + --header 'content-type: application/json'\ + --data-raw '{ + "cluster_id": "10939961583884005252", + "database": "sp500insight", + "tables": ["users"], + "instruction": "count the users" +}' +``` + +在上述示例中,请求体是一个具有以下属性的 JSON 对象: + +- `cluster_id`:_string_。TiDB 集群的唯一标识符。 +- `database`:_string_。数据库的名称。 +- `tables`:_array_。(可选)要查询的表名列表。 +- `instruction`:_string_。用自然语言描述您想要的查询的指令。 + +响应如下: + +```json +{ + "type": "chat2data_endpoint", + "data": { + "columns": [ + { + "col": "COUNT(`user_id`)", + "data_type": "BIGINT", + "nullable": false + } + ], + "rows": [ + { + "COUNT(`user_id`)": "1" + } + ], + "result": { + "code": 200, + "message": "Query OK!", + "start_ms": 1699529488292, + "end_ms": 1699529491901, + "latency": "3.609656403s", + "row_count": 1, + "row_affect": 0, + "limit": 1000, + "sql": "SELECT COUNT(`user_id`) FROM `users`;", + "ai_latency": "3.054822491s" + } + } +} +``` + +如果您的 API 调用不成功,您将收到状态码不是 `200` 的响应。以下是状态码 `500` 的示例: + +```json +{ + "type": "chat2data_endpoint", + "data": { + "columns": [], + "rows": [], + "result": { + "code": 500, + "message": "internal error! defaultPermissionHelper: rpc error: code = DeadlineExceeded desc = context deadline exceeded", + "start_ms": "", + "end_ms": "", + "latency": "", + "row_count": 0, + "row_affect": 0, + "limit": 0 + } + } +} +``` + +## 了解更多 + +- [管理 API 密钥](/tidb-cloud/data-service-api-key.md) +- [开始多轮 Chat2Query](/tidb-cloud/use-chat2query-sessions.md) +- [使用知识库](/tidb-cloud/use-chat2query-knowledge.md) +- [Data Service 的响应和状态码](/tidb-cloud/data-service-response-and-status-code.md) diff --git a/tidb-cloud/use-chat2query-knowledge.md b/tidb-cloud/use-chat2query-knowledge.md new file mode 100644 index 000000000000..656d6acd531a --- /dev/null +++ b/tidb-cloud/use-chat2query-knowledge.md @@ -0,0 +1,218 @@ +--- +title: 使用知识库 +summary: 了解如何通过使用 Chat2Query 知识库 API 来改进 Chat2Query 的查询结果。 +--- + +# 使用知识库 + +知识库是一组结构化数据的集合,可用于增强 Chat2Query 的 SQL 生成能力。 + +从 v3 版本开始,Chat2Query API 允许您通过调用 Chat2Query Data App 的知识库相关端点来添加或修改知识库。 + +> **注意:** +> +> 知识库相关端点默认在 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless) 集群上可用。如需在 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) 集群上使用知识库相关端点,请联系 [TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 + +## 开始之前 + +在为数据库创建知识库之前,请确保您已经具备以下条件: + +- 一个 [Chat2Query Data App](/tidb-cloud/use-chat2query-api.md#create-a-chat2query-data-app) +- 一个 [Chat2Query Data App 的 API 密钥](/tidb-cloud/use-chat2query-api.md#create-an-api-key) + +## 步骤 1. 为关联数据库创建知识库 + +> **注意:** +> +> Chat2Query 使用的知识是**按数据库维度进行组织的**。您可以将多个 Chat2Query Data App 连接到同一个数据库,但每个 Chat2Query Data App 只能使用其关联数据库的知识。 + +在您的 Chat2Query Data App 中,您可以通过调用 `/v3/knowledgeBases` 端点为特定数据库创建知识库。创建完成后,您将获得一个用于后续知识管理的 `knowledge_base_id`。 + +以下是调用此端点的通用代码示例。 + +> **提示:** +> +> 要获取特定端点的代码示例,请在 Data App 左侧窗格中点击端点名称,然后点击 **Show Code Example**。更多信息,请参见[获取端点的示例代码](/tidb-cloud/use-chat2query-api.md#get-the-code-example-of-an-endpoint)。 + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v3/knowledgeBases'\ + --header 'content-type: application/json'\ + --data-raw '{ + "cluster_id": "<数据库所属集群的 ID>", + "database": "<目标数据库的名称>", + "description": "<您的知识库描述>" +}' +``` + +示例响应如下: + +```json +{ + "code":200, + "msg":"", + "result": + { + "default":true, + "description":"", + "knowledge_base_id":2 + } +} +``` + +收到响应后,请记录响应中的 `knowledge_base_id` 值,以供后续使用。 + +## 步骤 2. 选择知识类型 + +每个数据库的知识库可以包含多种类型的知识。在向知识库添加知识之前,您需要选择最适合您使用场景的知识类型。 + +目前,Chat2Query 知识库支持以下知识类型。每种类型都是为不同场景专门设计的,并具有独特的知识结构。 + +- [少样本示例](#少样本示例) +- [术语表解释](#术语表解释) +- [指令](#指令) + +### 少样本示例 + +少样本示例是指提供给 Chat2Query 的问答学习样本,包括示例问题及其对应的答案。这些示例帮助 Chat2Query 更有效地处理新任务。 + +> **注意:** +> +> 请确保新添加示例的准确性,因为示例质量会影响 Chat2Query 的学习效果。不良示例(如问题和答案不匹配)可能会降低 Chat2Query 在新任务上的表现。 + +#### 知识结构 + +每个示例由一个示例问题及其对应答案组成。 + +例如: + +```json +{ + "question": "How many records are in the 'test' table?", + "answer": "SELECT COUNT(*) FROM `test`;" +} +``` + +#### 使用场景 + +少样本示例可以显著提高 Chat2Query 在各种场景下的表现,包括但不限于以下情况: + +1. **处理罕见或复杂问题时**:如果 Chat2Query 遇到不常见或复杂的问题,添加少样本示例可以增强其理解能力并提高结果的准确性。 + +2. **在处理某类问题时遇到困难**:如果 Chat2Query 经常在特定问题上出错或遇到困难,添加少样本示例可以帮助改善其在这些问题上的表现。 + +### 术语表解释 + +术语表解释是指对特定术语或一组相似术语的全面解释,帮助 Chat2Query 理解这些术语的含义和用法。 + +> **注意:** +> +> 请确保新添加术语解释的准确性,因为解释质量会影响 Chat2Query 的学习效果。错误的解释不仅不会改善 Chat2Query 的结果,还可能导致负面影响。 + +#### 知识结构 + +每个解释包括单个术语或一组相似术语及其详细描述。 + +例如: + +```json +{ + "term": ["OSS"], + "description": "OSS Insight 是一个强大的工具,基于近 60 亿行 GitHub 事件数据为用户提供在线数据分析。" +} +``` + +#### 使用场景 + +术语表解释主要用于提高 Chat2Query 对用户查询的理解,特别是在以下情况下: + +- **处理行业特定术语或缩写**:当您的查询包含可能不被普遍认知的行业特定术语或缩写时,使用术语表解释可以帮助 Chat2Query 理解这些术语的含义和用法。 +- **处理用户查询中的歧义**:当您的查询包含令人困惑的模糊概念时,使用术语表解释可以帮助 Chat2Query 澄清这些歧义。 +- **处理具有多种含义的术语**:当您的查询包含在不同上下文中具有不同含义的术语时,使用术语表解释可以帮助 Chat2Query 辨别正确的解释。 + +### 指令 + +指令是一段文本命令。它用于指导或控制 Chat2Query 的行为,特别是指导它如何根据特定要求或条件生成 SQL。 + +> **注意:** +> +> - 指令的长度限制为 512 个字符。 +> - 请确保提供尽可能清晰和具体的指令,以确保 Chat2Query 能够有效理解和执行指令。 + +#### 知识结构 + +指令仅包含一段文本命令。 + +例如: + +```json +{ + "instruction": "如果任务需要计算环比增长率,请在 SQL 中使用带有 OVER 子句的 LAG 函数" +} +``` + +#### 使用场景 + +指令可以在许多场景中用于指导 Chat2Query 按照您的要求输出,包括但不限于以下情况: + +- **限制查询范围**:如果您希望 SQL 只考虑某些表或列,可以使用指令来指定这一点。 +- **指导 SQL 结构**:如果您对 SQL 结构有特定要求,可以使用指令来指导 Chat2Query。 + +## 步骤 3. 向新创建的知识库添加知识 + +要添加新知识,您可以调用 `/v3/knowledgeBases/{knowledge_base_id}/data` 端点。 + +### 添加少样本示例类型的知识 + +例如,如果您希望 Chat2Query 以特定结构生成计算表中行数的 SQL 语句,您可以通过调用 `/v3/knowledgeBases/{knowledge_base_id}/data` 添加少样本示例类型的知识,如下所示: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v3/knowledgeBases//data'\ + --header 'content-type: application/json'\ + --data-raw '{ + "type": "few-shot", + "meta_data": {}, + "raw_data": { + "question": "How many records are in the 'test' table?", + "answer": "SELECT COUNT(*) FROM `test`;" + } +}' +``` + +在上述示例代码中,`"type": "few-shot"` 表示少样本示例知识类型。 + +### 添加术语表解释类型的知识 + +例如,如果您希望 Chat2Query 使用您提供的解释来理解术语 `OSS` 的含义,您可以通过调用 `/v3/knowledgeBases/{knowledge_base_id}/data` 添加术语表解释类型的知识,如下所示: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v3/knowledgeBases//data'\ + --header 'content-type: application/json'\ + --data-raw '{ + "type": "term-sheet", + "meta_data": {}, + "raw_data": { + "term": ["OSS"], + "description": "OSS Insight 是一个强大的工具,基于近 60 亿行 GitHub 事件数据为用户提供在线数据分析。" + } +}' +``` + +在上述示例代码中,`"type": "term-sheet"` 表示术语表解释知识类型。 + +### 添加指令类型的知识 + +例如,如果您希望 Chat2Query 在处理有关环比增长率计算的问题时始终使用带有 `OVER` 子句的 `LAG` 函数,您可以通过调用 `/v3/knowledgeBases/{knowledge_base_id}/data` 添加指令类型的知识,如下所示: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v3/knowledgeBases//data'\ + --header 'content-type: application/json'\ + --data-raw '{ + "type": "instruction", + "meta_data": {}, + "raw_data": { + "instruction": "如果任务需要计算环比增长率,请在 SQL 中使用带有 OVER 子句的 LAG 函数" + } +}' +``` + +在上述示例代码中,`"type": "instruction"` 表示指令知识类型。 diff --git a/tidb-cloud/use-chat2query-sessions.md b/tidb-cloud/use-chat2query-sessions.md new file mode 100644 index 000000000000..a030c3e21a9c --- /dev/null +++ b/tidb-cloud/use-chat2query-sessions.md @@ -0,0 +1,101 @@ +--- +title: 开始多轮 Chat2Query 对话 +summary: 了解如何使用 Chat2Query 会话相关的 API 开始多轮对话。 +--- + +# 开始多轮 Chat2Query 对话 + +从 v3 版本开始,Chat2Query API 支持通过调用会话相关的端点来进行多轮对话。您可以使用 `/v3/chat2data` 端点返回的 `session_id` 在下一轮对话中继续会话。 + +## 开始之前 + +在开始多轮 Chat2Query 对话之前,请确保您已经具备以下条件: + +- 一个 [Chat2Query Data App](/tidb-cloud/use-chat2query-api.md#create-a-chat2query-data-app)。 +- 一个 [Chat2Query Data App 的 API 密钥](/tidb-cloud/use-chat2query-api.md#create-an-api-key)。 +- 一个[目标数据库的数据摘要](/tidb-cloud/use-chat2query-api.md#1-generate-a-data-summary-by-calling-v3datasummaries)。 + +## 步骤 1. 开始会话 + +要开始会话,您可以调用 Chat2Query Data App 的 `/v3/sessions` 端点。 + +以下是调用此端点的通用代码示例。 + +> **提示:** +> +> 要获取特定端点的代码示例,请在 Data App 左侧窗格中点击端点名称,然后点击 **Show Code Example**。更多信息,请参见[获取端点的示例代码](/tidb-cloud/use-chat2query-api.md#get-the-code-example-of-an-endpoint)。 + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://.data.tidbcloud.com/api/v1beta/app/chat2query-/endpoint/v3/sessions'\ + --header 'content-type: application/json'\ + --data-raw '{ + "cluster_id": "10140100115280519574", + "database": "sp500insight", + "name": "" +}' +``` + +在上述代码中,请求体是一个具有以下属性的 JSON 对象: + +- `cluster_id`:_string_。TiDB 集群的唯一标识符。 +- `database`:_string_。数据库名称。 +- `name`:_string_。会话名称。 + +以下是一个响应示例: + +```json +{ + "code": 200, + "msg": "", + "result": { + "messages": [], + "meta": { + "created_at": 1718948875, // 表示会话创建时间的 UNIX 时间戳 + "creator": "", // 会话创建者 + "name": "", // 会话名称 + "org_id": "1", // 组织 ID + "updated_at": 1718948875 // 表示会话更新时间的 UNIX 时间戳 + }, + "session_id": 305685 // 会话 ID + } +} +``` + +## 步骤 2. 使用会话调用 Chat2Data 端点 + +开始会话后,您可以调用 `/v3/sessions/{session_id}/chat2data` 在下一轮对话中继续会话。 + +以下是通用代码示例: + +```bash +curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://eu-central-1.data.tidbcloud.com/api/v1beta/app/chat2query-YqAvnlRj/endpoint/v3/sessions/{session_id}/chat2data'\ + --header 'content-type: application/json'\ + --data-raw '{ + "question": "", + "feedback_answer_id": "", + "feedback_task_id": "", + "sql_generate_mode": "direct" +}' +``` + +在上述代码中,请求体是一个具有以下属性的 JSON 对象: + +- `question`:_string_。用自然语言描述您想要的查询的问题。 +- `feedback_answer_id`:_string_。反馈答案 ID。此字段是可选的,仅用于反馈。 +- `feedback_task_id`:_string_。反馈任务 ID。此字段是可选的,仅用于反馈。 +- `sql_generate_mode`:_string_。生成 SQL 语句的模式。值可以是 `direct` 或 `auto_breakdown`。如果设置为 `direct`,API 将直接根据您提供的 `question` 生成 SQL 语句。如果设置为 `auto_breakdown`,API 将把 `question` 分解为多个任务,并为每个任务生成 SQL 语句。 + +以下是一个响应示例: + +```json +{ + "code": 200, + "msg": "", + "result": { + "job_id": "d96b6fd23c5f445787eb5fd067c14c0b", + "session_id": 305685 + } +} +``` + +此响应与 `/v3/chat2data` 端点的响应类似。您可以通过调用 `/v2/jobs/{job_id}` 端点来检查作业状态。更多信息,请参见[通过调用 `/v2/jobs/{job_id}` 检查分析状态](/tidb-cloud/use-chat2query-api.md#2-check-the-analysis-status-by-calling-v2jobsjob_id)。 diff --git a/tidb-cloud/v6.5-performance-benchmarking-with-sysbench.md b/tidb-cloud/v6.5-performance-benchmarking-with-sysbench.md new file mode 100644 index 000000000000..c7eb9b4ed8c7 --- /dev/null +++ b/tidb-cloud/v6.5-performance-benchmarking-with-sysbench.md @@ -0,0 +1,155 @@ +--- +title: TiDB Cloud v6.5.6 版本 Sysbench 性能测试报告 +summary: 介绍 TiDB v6.5.6 版本的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试结果。 +--- + +# TiDB Cloud v6.5.6 版本 Sysbench 性能测试报告 + +本文提供了 TiDB v6.5.6 版本的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试步骤和结果。本报告也可以作为 TiDB 自托管 v6.5.6 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v6.5.6 在在线事务处理(OLTP)场景下的 Sysbench 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v6.5.6 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + | :-------- | :-------------- | :------------ | :----------- | + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge +- Sysbench 版本:sysbench 1.0.20(使用捆绑的 LuaJIT 2.1.0-beta2) + +## 测试步骤 + +本节介绍如何逐步执行 Sysbench 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `sbtest` 的数据库。 + + 要连接到集群,请参见[通过私有端点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `sbtest` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE sbtest; + ``` + +3. 将 Sysbench 数据加载到 `sbtest` 数据库。 + + 1. 本文中的测试基于 [sysbench](https://github.com/akopytov/sysbench) 实现。要安装 sysbench,请参见[从源代码构建和安装](https://github.com/akopytov/sysbench#building-and-installing-from-source)。 + + 2. 运行以下 `sysbench prepare` 命令,向 `sbtest` 数据库导入 32 个表和 10,000,000 行数据。将 `${HOST}`、`${PORT}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。 + + ```shell + sysbench oltp_common \ + --threads=${THREAD} \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --mysql-password=${PASSWORD} \ + prepare --tables=32 --table-size=10000000 + ``` + +4. 运行以下 `sysbench run` 命令,对不同的工作负载进行 Sysbench 性能测试。本文对五个工作负载进行测试:`oltp_point_select`、`oltp_read_write`、`oltp_update_non_index`、`oltp_update_index` 和 `oltp_insert`。对于每个工作负载,本文使用 `${THREAD}` 值为 `100`、`200` 和 `400` 进行三次测试。每个并发测试持续 20 分钟。 + + ```shell + sysbench ${WORKLOAD} run \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --threads=${THREAD} \ + --time=1200 \ + --report-interval=10 \ + --tables=32 \ + --table-size=10000000 \ + --mysql-ignore-errors=1062,2013,8028,9007 \ + --auto-inc=false \ + --mysql-password=${PASSWORD} + ``` + +## 测试结果 + +本节介绍 v6.5.6 在[测试环境](#测试环境)中的 Sysbench 性能。 + +### 点查询性能 + +`oltp_point_select` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :----- | :--------------- | +| 50 | 34125 | 2.03 | +| 100 | 64987 | 2.07 | +| 200 | 121656 | 2.14 | + +![Sysbench 点查询性能](/media/tidb-cloud/v6.5.6-oltp_select_point.png) + +### 读写性能 + +`oltp_read_write` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :--- | :--------------- | +| 50 | 1232 | 46.6 | +| 100 | 2266 | 51.9 | +| 200 | 3578 | 81.5 | + +![Sysbench 读写性能](/media/tidb-cloud/v6.5.6-oltp_read_write.png) + +### 更新非索引性能 + +`oltp_update_non_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :---- | :--------------- | +| 100 | 11016 | 11.0 | +| 200 | 20640 | 12.1 | +| 400 | 36830 | 13.5 | + +![Sysbench 更新非索引性能](/media/tidb-cloud/v6.5.6-oltp_update_non_index.png) + +### 更新索引性能 + +`oltp_update_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :---- | :--------------- | +| 100 | 9270 | 14.0 | +| 200 | 14466 | 18.0 | +| 400 | 22194 | 24.8 | + +![Sysbench 更新索引性能](/media/tidb-cloud/v6.5.6-oltp_update_index.png) + +### 插入性能 + +`oltp_insert` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :---- | :--------------- | +| 100 | 16008 | 8.13 | +| 200 | 27143 | 10.1 | +| 400 | 40884 | 15.0 | + +![Sysbench 插入性能](/media/tidb-cloud/v6.5.6-oltp_insert.png) diff --git a/tidb-cloud/v6.5-performance-benchmarking-with-tpcc.md b/tidb-cloud/v6.5-performance-benchmarking-with-tpcc.md new file mode 100644 index 000000000000..1e7d9e54d887 --- /dev/null +++ b/tidb-cloud/v6.5-performance-benchmarking-with-tpcc.md @@ -0,0 +1,111 @@ +--- +title: TiDB v6.5.6 版本的 TiDB Cloud TPC-C 性能测试报告 +summary: 介绍 TiDB v6.5.6 版本的 TiDB Cloud Dedicated 集群的 TPC-C 性能测试结果。 +--- + +# TiDB v6.5.6 版本的 TiDB Cloud TPC-C 性能测试报告 + +本文提供了 TiDB v6.5.6 版本的 TiDB Cloud Dedicated 集群的 TPC-C 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v6.5.6 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v6.5.6 在在线事务处理(OLTP)场景下的 TPC-C 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v6.5.6 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + | :-------- | :-------------- | :------------ | :----------- | + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge + +## 测试步骤 + +本节介绍如何逐步执行 TPC-C 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `tpcc` 的数据库。 + + 要连接到集群,请参见[通过私有端点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `tpcc` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE tpcc; + ``` + +3. 将 TPC-C 数据加载到 `tpcc` 数据库。 + + 1. 本文中的测试基于 [go-tpc](https://github.com/pingcap/go-tpc) 实现。你可以使用以下命令下载测试程序: + + ```shell + curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/pingcap/go-tpc/master/install.sh | sh + ``` + + 2. 运行以下 `go-tpc tpcc` 命令,将 1,000 个仓库导入到 `tpcc` 数据库。将 `${HOST}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。本文进行三次测试,`${THREAD}` 值分别为 `50`、`100` 和 `200`。 + + ```shell + go-tpc tpcc --host ${HOST} --warehouses 1000 prepare -P 4000 -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +4. 为确保 TiDB 优化器能生成最优执行计划,在进行 TPC-C 测试之前执行以下 SQL 语句收集统计信息: + + ```sql + ANALYZE TABLE customer; + ANALYZE TABLE district; + ANALYZE TABLE history; + ANALYZE TABLE item; + ANALYZE TABLE new_order; + ANALYZE TABLE order_line; + ANALYZE TABLE orders; + ANALYZE TABLE stock; + ANALYZE TABLE warehouse; + ``` + + 为加快统计信息收集速度,在收集前执行以下 SQL 语句: + + ```sql + SET tidb_build_stats_concurrency=16; + SET tidb_distsql_scan_concurrency=16; + SET tidb_index_serial_scan_concurrency=16; + ``` + +5. 运行以下 `go-tpc tpcc` 命令对 TiDB Cloud Dedicated 集群进行压力测试。每个并发度的测试持续两小时。 + + ```shell + go-tpc tpcc --host ${HOST} -P 4000 --warehouses 1000 run -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +6. 从结果中提取 `NEW_ORDER` 的 tpmC 数据。 + + TPC-C 使用 tpmC(每分钟事务数)来衡量最大限定吞吐量(MQTh,Max Qualified Throughput)。事务是 NewOrder 事务,最终的度量单位是每分钟处理的新订单数。 + +## 测试结果 + +v6.5.6 在[测试环境](#测试环境)中的 TPC-C 性能如下: + +| 线程数 | v6.5.6 tpmC | +| :------ | :---------- | +| 50 | 44183 | +| 100 | 74424 | +| 200 | 101545 | + +![TPC-C](/media/tidb-cloud/v6.5.6-tpmC.png) diff --git a/tidb-cloud/v7.1-performance-benchmarking-with-sysbench.md b/tidb-cloud/v7.1-performance-benchmarking-with-sysbench.md new file mode 100644 index 000000000000..e9ffcf6572aa --- /dev/null +++ b/tidb-cloud/v7.1-performance-benchmarking-with-sysbench.md @@ -0,0 +1,176 @@ +--- +title: TiDB Cloud Sysbench v7.1.3 性能测试报告 +summary: 介绍 TiDB 版本为 v7.1.3 的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试结果。 +aliases: ['/tidbcloud/v7.1.0-performance-benchmarking-with-sysbench'] +--- + +# TiDB Cloud Sysbench v7.1.3 性能测试报告 + +本文档提供了 TiDB 版本为 v7.1.3 的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v7.1.3 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v7.1.3 在在线事务处理(OLTP)场景下的 Sysbench 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v7.1.3 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + | :-------- | :-------------- | :------------ | :----------- | + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 参数配置 + +> **注意:** +> +> 对于 TiDB Cloud,如果要修改集群的 TiKV 参数,你可以联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +TiKV 参数 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 可以使日志回收在初始化后立即生效。本文档基于不同工作负载进行测试,使用以下 `prefill-for-recycle` 配置: + +- 对于 `oltp_point_select` 工作负载,使用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数的默认值: + + ```yaml + raft-engine.prefill-for-recycle = false + ``` + +- 对于 `oltp_insert`、`oltp_read_write`、`oltp_update_index` 和 `oltp_update_non_index` 工作负载,启用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数: + + ```yaml + raft-engine.prefill-for-recycle = true + ``` + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge +- Sysbench 版本:sysbench 1.0.20(使用捆绑的 LuaJIT 2.1.0-beta2) + +## 测试步骤 + +本节介绍如何逐步执行 Sysbench 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建一个名为 `sbtest` 的数据库。 + + 要连接到集群,请参见[通过私有端点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `sbtest` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE sbtest; + ``` + +3. 将 Sysbench 数据加载到 `sbtest` 数据库。 + + 1. 本文档中的测试基于 [sysbench](https://github.com/akopytov/sysbench) 实现。要安装 sysbench,请参见[从源代码构建和安装](https://github.com/akopytov/sysbench#building-and-installing-from-source)。 + + 2. 运行以下 `sysbench prepare` 命令,将 32 个表和 10,000,000 行数据导入到 `sbtest` 数据库。将 `${HOST}`、`${PORT}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。 + + ```shell + sysbench oltp_common \ + --threads=${THREAD} \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --mysql-password=${PASSWORD} \ + prepare --tables=32 --table-size=10000000 + ``` + +4. 运行以下 `sysbench run` 命令对不同工作负载进行 Sysbench 性能测试。本文档对五个工作负载进行测试:`oltp_point_select`、`oltp_read_write`、`oltp_update_non_index`、`oltp_update_index` 和 `oltp_insert`。对于每个工作负载,本文档使用 `${THREAD}` 值为 `100`、`200` 和 `400` 进行三次测试。每个并发测试持续 20 分钟。 + + ```shell + sysbench ${WORKLOAD} run \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --threads=${THREAD} \ + --time=1200 \ + --report-interval=10 \ + --tables=32 \ + --table-size=10000000 \ + --mysql-ignore-errors=1062,2013,8028,9007 \ + --auto-inc=false \ + --mysql-password=${PASSWORD} + ``` + +## 测试结果 + +本节介绍 [测试环境](#测试环境)中 v7.1.3 的 Sysbench 性能。 + +### 点查性能 + +`oltp_point_select` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :----- | :--------------- | +| 50 | 35309 | 1.93 | +| 100 | 64853 | 2.00 | +| 200 | 118462 | 2.22 | + +![Sysbench 点查性能](/media/tidb-cloud/v7.1.3-oltp_select_point.png) + +### 读写性能 + +`oltp_read_write` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :--- | :--------------- | +| 50 | 1218 | 48.3 | +| 100 | 2235 | 53.9 | +| 200 | 3380 | 87.6 | + +![Sysbench 读写性能](/media/tidb-cloud/v7.1.3-oltp_read_write.png) + +### 更新非索引性能 + +`oltp_update_non_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :---- | :--------------- | +| 100 | 10928 | 11.7 | +| 200 | 19985 | 12.8 | +| 400 | 35621 | 14.7 | + +![Sysbench 更新非索引性能](/media/tidb-cloud/v7.1.3-oltp_update_non_index.png) + +### 更新索引性能 + +`oltp_update_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :---- | :--------------- | +| 100 | 8854 | 14.7 | +| 200 | 14414 | 18.6 | +| 400 | 21997 | 25.3 | + +![Sysbench 更新索引性能](/media/tidb-cloud/v7.1.3-oltp_update_index.png) + +### 插入性能 + +`oltp_insert` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :---- | :--------------- | +| 100 | 15575 | 8.13 | +| 200 | 25078 | 11.0 | +| 400 | 38436 | 15.6 | + +![Sysbench 插入性能](/media/tidb-cloud/v7.1.3-oltp_insert.png) diff --git a/tidb-cloud/v7.1-performance-benchmarking-with-tpcc.md b/tidb-cloud/v7.1-performance-benchmarking-with-tpcc.md new file mode 100644 index 000000000000..b0f8d00b7733 --- /dev/null +++ b/tidb-cloud/v7.1-performance-benchmarking-with-tpcc.md @@ -0,0 +1,112 @@ +--- +title: TiDB Cloud TPC-C v7.1.3 性能测试报告 +summary: 介绍 TiDB 版本为 v7.1.3 的 TiDB Cloud Dedicated 集群的 TPC-C 性能测试结果。 +aliases: ['/tidbcloud/v7.1.0-performance-benchmarking-with-tpcc'] +--- + +# TiDB Cloud TPC-C v7.1.3 性能测试报告 + +本文档提供了 TiDB 版本为 v7.1.3 的 TiDB Cloud Dedicated 集群的 TPC-C 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v7.1.3 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v7.1.3 在在线事务处理(OLTP)场景下的 TPC-C 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v7.1.3 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + | :-------- | :-------------- | :------------ | :----------- | + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge + +## 测试步骤 + +本节介绍如何逐步执行 TPC-C 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建一个名为 `tpcc` 的数据库。 + + 要连接到集群,请参见[通过私有端点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `tpcc` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE tpcc; + ``` + +3. 将 TPC-C 数据加载到 `tpcc` 数据库。 + + 1. 本文档中的测试基于 [go-tpc](https://github.com/pingcap/go-tpc) 实现。你可以使用以下命令下载测试程序: + + ```shell + curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/pingcap/go-tpc/master/install.sh | sh + ``` + + 2. 运行以下 `go-tpc tpcc` 命令,将 1,000 个仓库导入到 `tpcc` 数据库。将 `${HOST}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。本文档使用 `${THREAD}` 值为 `50`、`100` 和 `200` 进行三次测试。 + + ```shell + go-tpc tpcc --host ${HOST} --warehouses 1000 prepare -P 4000 -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +4. 为确保 TiDB 优化器能生成最优执行计划,在进行 TPC-C 测试之前执行以下 SQL 语句来收集统计信息: + + ```sql + ANALYZE TABLE customer; + ANALYZE TABLE district; + ANALYZE TABLE history; + ANALYZE TABLE item; + ANALYZE TABLE new_order; + ANALYZE TABLE order_line; + ANALYZE TABLE orders; + ANALYZE TABLE stock; + ANALYZE TABLE warehouse; + ``` + + 为加快统计信息收集速度,在收集前执行以下 SQL 语句: + + ```sql + SET tidb_build_stats_concurrency=16; + SET tidb_distsql_scan_concurrency=16; + SET tidb_index_serial_scan_concurrency=16; + ``` + +5. 运行以下 `go-tpc tpcc` 命令对 TiDB Cloud Dedicated 集群进行压力测试。每个并发测试持续两小时。 + + ```shell + go-tpc tpcc --host ${HOST} -P 4000 --warehouses 1000 run -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +6. 从结果中提取 `NEW_ORDER` 的 tpmC 数据。 + + TPC-C 使用 tpmC(每分钟事务数)来衡量最大限定吞吐量(MQTh,Max Qualified Throughput)。事务是 NewOrder 事务,最终的衡量单位是每分钟处理的新订单数。 + +## 测试结果 + +[测试环境](#测试环境)中 v7.1.3 的 TPC-C 性能如下: + +| 线程数 | v7.1.3 tpmC | +| :------ | :---------- | +| 50 | 42839 | +| 100 | 72895 | +| 200 | 97924 | + +![TPC-C](/media/tidb-cloud/v7.1.3-tpmC.png) diff --git a/tidb-cloud/v7.5-performance-benchmarking-with-sysbench.md b/tidb-cloud/v7.5-performance-benchmarking-with-sysbench.md new file mode 100644 index 000000000000..c8f42dbaccb5 --- /dev/null +++ b/tidb-cloud/v7.5-performance-benchmarking-with-sysbench.md @@ -0,0 +1,176 @@ +--- +title: TiDB Cloud v7.5.0 版本 Sysbench 性能测试报告 +summary: 介绍 TiDB 版本为 v7.5.0 的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试结果。 +aliases: ['/tidbcloud/v7.5.0-performance-benchmarking-with-sysbench'] +--- + +# TiDB Cloud v7.5.0 版本 Sysbench 性能测试报告 + +本文档提供了 TiDB 版本为 v7.5.0 的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v7.5.0 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v7.5.0 在在线事务处理(OLTP)场景下的 Sysbench 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v7.5.0 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + | :-------- | :-------------- | :------------ | :----------- | + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 参数配置 + +> **注意:** +> +> 对于 TiDB Cloud,如果要修改集群的 TiKV 参数,你可以联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +TiKV 参数 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 可以使日志回收在初始化后立即生效。本文档基于不同工作负载进行测试,`prefill-for-recycle` 配置如下: + +- 对于 `oltp_point_select` 工作负载,使用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数的默认值: + + ```yaml + raft-engine.prefill-for-recycle = false + ``` + +- 对于 `oltp_insert`、`oltp_read_write`、`oltp_update_index` 和 `oltp_update_non_index` 工作负载,启用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数: + + ```yaml + raft-engine.prefill-for-recycle = true + ``` + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge +- Sysbench 版本:sysbench 1.0.20(使用捆绑的 LuaJIT 2.1.0-beta2) + +## 测试步骤 + +本节介绍如何逐步执行 Sysbench 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参阅[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `sbtest` 的数据库。 + + 要连接到集群,请参阅[通过私有端点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `sbtest` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE sbtest; + ``` + +3. 将 Sysbench 数据加载到 `sbtest` 数据库。 + + 1. 本文档中的测试基于 [sysbench](https://github.com/akopytov/sysbench) 实现。要安装 sysbench,请参阅[从源代码构建和安装](https://github.com/akopytov/sysbench#building-and-installing-from-source)。 + + 2. 运行以下 `sysbench prepare` 命令,向 `sbtest` 数据库导入 32 个表和 10,000,000 行数据。将 `${HOST}`、`${PORT}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。 + + ```shell + sysbench oltp_common \ + --threads=${THREAD} \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --mysql-password=${PASSWORD} \ + prepare --tables=32 --table-size=10000000 + ``` + +4. 运行以下 `sysbench run` 命令对不同工作负载进行 Sysbench 性能测试。本文档对五个工作负载进行测试:`oltp_point_select`、`oltp_read_write`、`oltp_update_non_index`、`oltp_update_index` 和 `oltp_insert`。对于每个工作负载,本文档进行三次测试,`${THREAD}` 值分别为 `100`、`200` 和 `400`。对于每个并发度,测试持续 20 分钟。 + + ```shell + sysbench ${WORKLOAD} run \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --threads=${THREAD} \ + --time=1200 \ + --report-interval=10 \ + --tables=32 \ + --table-size=10000000 \ + --mysql-ignore-errors=1062,2013,8028,9007 \ + --auto-inc=false \ + --mysql-password=${PASSWORD} + ``` + +## 测试结果 + +本节介绍 v7.5.0 在[测试环境](#测试环境)中的 Sysbench 性能。 + +### 点查性能 + +`oltp_point_select` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :------ | :--------------- | +| 50 | 33,344 | 1.96 | +| 100 | 64,810 | 2.03 | +| 200 | 118,651 | 2.22 | + +![Sysbench 点查性能](/media/tidb-cloud/v7.5.0-oltp_point_select.png) + +### 读写性能 + +`oltp_read_write` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :---- | :--------------- | +| 50 | 1,181 | 49.2 | +| 100 | 2,162 | 54.8 | +| 200 | 3,169 | 92.4 | + +![Sysbench 读写性能](/media/tidb-cloud/v7.5.0-oltp_read_write.png) + +### 更新非索引性能 + +`oltp_update_non_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :----- | :--------------- | +| 100 | 10,567 | 11.7 | +| 200 | 20,223 | 13.0 | +| 400 | 34,011 | 14.7 | + +![Sysbench 更新非索引性能](/media/tidb-cloud/v7.5.0-oltp_update_non_index.png) + +### 更新索引性能 + +`oltp_update_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :----- | :--------------- | +| 100 | 8,896 | 14.7 | +| 200 | 13,718 | 19.0 | +| 400 | 20,377 | 26.9 | + +![Sysbench 更新索引性能](/media/tidb-cloud/v7.5.0-oltp_update_index.png) + +### 插入性能 + +`oltp_insert` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms) | +| :------ | :----- | :--------------- | +| 100 | 15,132 | 8.58 | +| 200 | 24,756 | 10.8 | +| 400 | 37,247 | 16.4 | + +![Sysbench 插入性能](/media/tidb-cloud/v7.5.0-oltp_insert.png) diff --git a/tidb-cloud/v7.5-performance-benchmarking-with-tpcc.md b/tidb-cloud/v7.5-performance-benchmarking-with-tpcc.md new file mode 100644 index 000000000000..2929d0227ef8 --- /dev/null +++ b/tidb-cloud/v7.5-performance-benchmarking-with-tpcc.md @@ -0,0 +1,112 @@ +--- +title: TiDB v7.5.0 版本的 TiDB Cloud TPC-C 性能测试报告 +summary: 介绍 TiDB v7.5.0 版本的 TiDB Cloud Dedicated 集群的 TPC-C 性能测试结果。 +aliases: ['/tidbcloud/v7.5.0-performance-benchmarking-with-tpcc'] +--- + +# TiDB v7.5.0 版本的 TiDB Cloud TPC-C 性能测试报告 + +本文提供了 TiDB v7.5.0 版本的 TiDB Cloud Dedicated 集群的 TPC-C 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v7.5.0 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v7.5.0 在在线事务处理(OLTP)场景下的 TPC-C 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v7.5.0 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + | :-------- | :-------------- | :------------ | :----------- | + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge + +## 测试步骤 + +本节介绍如何逐步执行 TPC-C 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `tpcc` 的数据库。 + + 要连接到集群,请参见[通过私有端点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `tpcc` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE tpcc; + ``` + +3. 将 TPC-C 数据加载到 `tpcc` 数据库。 + + 1. 本文中的测试基于 [go-tpc](https://github.com/pingcap/go-tpc) 实现。你可以使用以下命令下载测试程序: + + ```shell + curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/pingcap/go-tpc/master/install.sh | sh + ``` + + 2. 运行以下 `go-tpc tpcc` 命令,将 1,000 个仓库导入到 `tpcc` 数据库。将 `${HOST}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。本文进行三次测试,`${THREAD}` 值分别为 `50`、`100` 和 `200`。 + + ```shell + go-tpc tpcc --host ${HOST} --warehouses 1000 prepare -P 4000 -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +4. 为确保 TiDB 优化器能生成最优执行计划,在进行 TPC-C 测试之前执行以下 SQL 语句收集统计信息: + + ```sql + ANALYZE TABLE customer; + ANALYZE TABLE district; + ANALYZE TABLE history; + ANALYZE TABLE item; + ANALYZE TABLE new_order; + ANALYZE TABLE order_line; + ANALYZE TABLE orders; + ANALYZE TABLE stock; + ANALYZE TABLE warehouse; + ``` + + 为加快统计信息收集速度,在收集前执行以下 SQL 语句: + + ```sql + SET tidb_build_stats_concurrency=16; + SET tidb_distsql_scan_concurrency=16; + SET tidb_index_serial_scan_concurrency=16; + ``` + +5. 运行以下 `go-tpc tpcc` 命令对 TiDB Cloud Dedicated 集群进行压力测试。每个并发度的测试持续两小时。 + + ```shell + go-tpc tpcc --host ${HOST} -P 4000 --warehouses 1000 run -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +6. 从结果中提取 `NEW_ORDER` 的 tpmC 数据。 + + TPC-C 使用 tpmC(每分钟事务数)来衡量最大限定吞吐量(MQTh,Max Qualified Throughput)。事务是 NewOrder 事务,最终的度量单位是每分钟处理的新订单数。 + +## 测试结果 + +v7.5.0 在[测试环境](#测试环境)中的 TPC-C 性能如下: + +| 线程数 | v7.5.0 tpmC | +| :------ | :---------- | +| 50 | 41,426 | +| 100 | 71,499 | +| 200 | 97,389 | + +![TPC-C](/media/tidb-cloud/v7.5.0_tpcc.png) diff --git a/tidb-cloud/v8.1-performance-benchmarking-with-sysbench.md b/tidb-cloud/v8.1-performance-benchmarking-with-sysbench.md new file mode 100644 index 000000000000..232adec8aaff --- /dev/null +++ b/tidb-cloud/v8.1-performance-benchmarking-with-sysbench.md @@ -0,0 +1,181 @@ +--- +title: TiDB Cloud v8.1.0 版本 Sysbench 性能测试报告 +summary: 介绍 TiDB v8.1.0 版本的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试结果。 +--- + +# TiDB Cloud v8.1.0 版本 Sysbench 性能测试报告 + +本文提供了 TiDB v8.1.0 版本的 TiDB Cloud Dedicated 集群的 Sysbench 性能测试步骤和结果。本报告也可以作为 TiDB 自托管 v8.1.0 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v8.1.0 在在线事务处理(OLTP)场景下的 Sysbench 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v8.1.0 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + |:----------|:----------|:----------|:----------| + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 参数配置 + +系统变量 [`tidb_session_plan_cache_size`](https://docs.pingcap.com/tidb/stable/system-variables#tidb_session_plan_cache_size-new-in-v710) 控制可以缓存的计划的最大数量。默认值为 `100`。对于每个工作负载,本文在将 `tidb_session_plan_cache_size` 设置为 `1000` 的情况下进行测试: + +```sql +SET GLOBAL tidb_session_plan_cache_size = 1000; +``` + +> **注意:** +> +> 对于 TiDB Cloud,如果要修改集群的 TiKV 参数,你可以联系 [PingCAP 支持团队](/tidb-cloud/tidb-cloud-support.md)寻求帮助。 + +TiKV 参数 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 可以使日志回收在初始化后立即生效。本文基于不同的工作负载,使用以下 `prefill-for-recycle` 配置进行测试: + +- 对于 `oltp_point_select` 工作负载,使用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数的默认值: + + ```yaml + raft-engine.prefill-for-recycle = false + ``` + +- 对于 `oltp_insert`、`oltp_read_write`、`oltp_update_index` 和 `oltp_update_non_index` 工作负载,启用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数: + + ```yaml + raft-engine.prefill-for-recycle = true + ``` + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge +- Sysbench 版本:sysbench 1.0.20(使用捆绑的 LuaJIT 2.1.0-beta2) + +## 测试步骤 + +本节介绍如何逐步执行 Sysbench 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `sbtest` 的数据库。 + + 要连接到集群,请参见[通过私有端点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `sbtest` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE sbtest; + ``` + +3. 将 Sysbench 数据加载到 `sbtest` 数据库。 + + 1. 本文中的测试基于 [sysbench](https://github.com/akopytov/sysbench) 实现。要安装 sysbench,请参见[从源代码构建和安装](https://github.com/akopytov/sysbench#building-and-installing-from-source)。 + + 2. 运行以下 `sysbench prepare` 命令,向 `sbtest` 数据库导入 32 个表和 10,000,000 行数据。将 `${HOST}`、`${PORT}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。 + + ```shell + sysbench oltp_common \ + --threads=${THREAD} \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --mysql-password=${PASSWORD} \ + prepare --tables=32 --table-size=10000000 + ``` + +4. 运行以下 `sysbench run` 命令,对不同的工作负载进行 Sysbench 性能测试。本文对五个工作负载进行测试:`oltp_point_select`、`oltp_read_write`、`oltp_update_non_index`、`oltp_update_index` 和 `oltp_insert`。对于每个工作负载,本文使用不同的 `${THREAD}` 变量值进行三次测试。对于 `oltp_point_select` 和 `oltp_read_write`,值分别为 `50`、`100` 和 `200`。对于其他工作负载,值分别为 `100`、`200` 和 `400`。每个并发测试持续 20 分钟。 + + ```shell + sysbench ${WORKLOAD} run \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --threads=${THREAD} \ + --time=1200 \ + --report-interval=10 \ + --tables=32 \ + --table-size=10000000 \ + --mysql-ignore-errors=1062,2013,8028,9007 \ + --auto-inc=false \ + --mysql-password=${PASSWORD} + ``` + +## 测试结果 + +本节介绍 v8.1.0 在[测试环境](#测试环境)中的 Sysbench 性能。 + +### 点查询性能 + +`oltp_point_select` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 50 | 32,741 | 1.96 | +| 100 | 62,545 | 2.03 | +| 200 | 111,470 | 2.48 | + +![Sysbench 点查询性能](/media/tidb-cloud/v8.1.0_oltp_point_select.png) + +### 读写性能 + +`oltp_read_write` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 50 | 1,232 | 46.6 | +| 100 | 2,341 | 51 | +| 200 | 3,240 | 109 | + +![Sysbench 读写性能](/media/tidb-cloud/v8.1.0_oltp_read_write.png) + +### 更新非索引性能 + +`oltp_update_non_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 100 | 14,000 | 9.39 | +| 200 | 25,215 | 10.5 | +| 400 | 42,550 | 12.8 | + +![Sysbench 更新非索引性能](/media/tidb-cloud/v8.1.0_oltp_update_non_index.png) + +### 更新索引性能 + +`oltp_update_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 100 | 11,188 | 11.7 | +| 200 | 17,805 | 14.7 | +| 400 | 24,575 | 23.5 | + +![Sysbench 更新索引性能](/media/tidb-cloud/v8.1.0_oltp_update_index.png) + +### 插入性能 + +`oltp_insert` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 100 | 18,339 | 7.3| +| 200 | 29,387 | 9.73 | +| 400 | 42,712 | 14.2 | + +![Sysbench 插入性能](/media/tidb-cloud/v8.1.0_oltp_insert.png) diff --git a/tidb-cloud/v8.1-performance-benchmarking-with-tpcc.md b/tidb-cloud/v8.1-performance-benchmarking-with-tpcc.md new file mode 100644 index 000000000000..e75aa01029e7 --- /dev/null +++ b/tidb-cloud/v8.1-performance-benchmarking-with-tpcc.md @@ -0,0 +1,123 @@ +--- +title: TiDB v8.1.0 在 TiDB Cloud 上的 TPC-C 性能测试报告 +summary: 介绍 TiDB v8.1.0 版本在 TiDB Cloud Dedicated 集群上的 TPC-C 性能测试步骤和结果。 +--- + +# TiDB v8.1.0 在 TiDB Cloud 上的 TPC-C 性能测试报告 + +本文提供了 TiDB v8.1.0 版本在 TiDB Cloud Dedicated 集群上的 TPC-C 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v8.1.0 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v8.1.0 在在线事务处理(OLTP)场景下的 TPC-C 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v8.1.0 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + |:----------|:----------|:----------|:----------| + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 参数配置 + +> **注意:** +> +> 对于 TiDB Cloud,如需修改集群的 TiKV 参数,你可以联系 [PingCAP 技术支持](/tidb-cloud/tidb-cloud-support.md)获取帮助。 + +TiKV 参数 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 可以使日志回收在初始化后立即生效。本文在启用 `prefill-for-recycle` 的情况下进行测试: + +```yaml +raft-engine.prefill-for-recycle = true +``` + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge + +## 测试步骤 + +本节介绍如何逐步执行 TPC-C 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `tpcc` 的数据库。 + + 要连接到集群,请参见[通过专用连接点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `tpcc` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE tpcc; + ``` + +3. 将 TPC-C 数据加载到 `tpcc` 数据库。 + + 1. 本文中的测试基于 [go-tpc](https://github.com/pingcap/go-tpc) 实现。你可以使用以下命令下载测试程序: + + ```shell + curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/pingcap/go-tpc/master/install.sh | sh + ``` + + 2. 运行以下 `go-tpc tpcc` 命令,向 `tpcc` 数据库导入 1,000 个仓库。将 `${HOST}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。本文使用 `${THREAD}` 值为 `50`、`100` 和 `200` 进行三次测试。 + + ```shell + go-tpc tpcc --host ${HOST} --warehouses 1000 prepare -P 4000 -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +4. 为确保 TiDB 优化器能生成最优执行计划,在进行 TPC-C 测试之前执行以下 SQL 语句收集统计信息: + + ```sql + ANALYZE TABLE customer; + ANALYZE TABLE district; + ANALYZE TABLE history; + ANALYZE TABLE item; + ANALYZE TABLE new_order; + ANALYZE TABLE order_line; + ANALYZE TABLE orders; + ANALYZE TABLE stock; + ANALYZE TABLE warehouse; + ``` + + 为加快统计信息收集速度,在收集前执行以下 SQL 语句: + + ```sql + SET tidb_build_stats_concurrency=16; + SET tidb_distsql_scan_concurrency=16; + SET tidb_index_serial_scan_concurrency=16; + ``` + +5. 运行以下 `go-tpc tpcc` 命令对 TiDB Cloud Dedicated 集群进行压力测试。每个并发测试持续两小时。 + + ```shell + go-tpc tpcc --host ${HOST} -P 4000 --warehouses 1000 run -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +6. 从结果中提取 `NEW_ORDER` 的 tpmC 数据。 + + TPC-C 使用 tpmC(每分钟事务数)来衡量最大限定吞吐量(MQTh,Max Qualified Throughput)。事务是 NewOrder 事务,最终的衡量单位是每分钟处理的新订单数。 + +## 测试结果 + +v8.1.0 在[测试环境](#测试环境)中的 TPC-C 性能如下: + +| 线程数 | v8.1.0 tpmC | +|:--------|:----------| +| 50 | 43,660 | +| 100 | 75,495 | +| 200 | 102,013 | + +![TPC-C](/media/tidb-cloud/v8.1.0_tpcc.png) diff --git a/tidb-cloud/v8.5-performance-benchmarking-with-sysbench.md b/tidb-cloud/v8.5-performance-benchmarking-with-sysbench.md new file mode 100644 index 000000000000..beb9c34b86ce --- /dev/null +++ b/tidb-cloud/v8.5-performance-benchmarking-with-sysbench.md @@ -0,0 +1,181 @@ +--- +title: TiDB v8.5.0 在 TiDB Cloud 上的 Sysbench 性能测试报告 +summary: 介绍 TiDB v8.5.0 版本在 TiDB Cloud Dedicated 集群上的 Sysbench 性能测试步骤和结果。 +--- + +# TiDB v8.5.0 在 TiDB Cloud 上的 Sysbench 性能测试报告 + +本文提供了 TiDB v8.5.0 版本在 TiDB Cloud Dedicated 集群上的 Sysbench 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v8.5.0 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v8.5.0 在在线事务处理(OLTP)场景下的 Sysbench 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v8.5.0 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + |:----------|:----------|:----------|:----------| + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 参数配置 + +系统变量 [`tidb_session_plan_cache_size`](https://docs.pingcap.com/tidb/stable/system-variables#tidb_session_plan_cache_size-new-in-v710) 控制可以缓存的计划的最大数量。默认值为 `100`。对于每个工作负载,本文将 `tidb_session_plan_cache_size` 设置为 `1000` 进行测试: + +```sql +SET GLOBAL tidb_session_plan_cache_size = 1000; +``` + +> **注意:** +> +> 对于 TiDB Cloud,如需修改集群的 TiKV 参数,你可以联系 [PingCAP 技术支持](/tidb-cloud/tidb-cloud-support.md)获取帮助。 + +TiKV 参数 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 可以使日志回收在初始化后立即生效。本文基于不同的工作负载使用以下 `prefill-for-recycle` 配置进行测试: + +- 对于 `oltp_point_select` 工作负载,使用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数的默认值: + + ```yaml + raft-engine.prefill-for-recycle = false + ``` + +- 对于 `oltp_insert`、`oltp_read_write`、`oltp_update_index` 和 `oltp_update_non_index` 工作负载,启用 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 参数: + + ```yaml + raft-engine.prefill-for-recycle = true + ``` + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge +- Sysbench 版本:sysbench 1.0.20 (使用捆绑的 LuaJIT 2.1.0-beta2) + +## 测试步骤 + +本节介绍如何逐步执行 Sysbench 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `sbtest` 的数据库。 + + 要连接到集群,请参见[通过专用连接点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `sbtest` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE sbtest; + ``` + +3. 将 Sysbench 数据加载到 `sbtest` 数据库。 + + 1. 本文中的测试基于 [sysbench](https://github.com/akopytov/sysbench) 实现。要安装 sysbench,请参见[从源代码构建和安装](https://github.com/akopytov/sysbench#building-and-installing-from-source)。 + + 2. 运行以下 `sysbench prepare` 命令,向 `sbtest` 数据库导入 32 个表和 10,000,000 行数据。将 `${HOST}`、`${PORT}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。 + + ```shell + sysbench oltp_common \ + --threads=${THREAD} \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --mysql-password=${PASSWORD} \ + prepare --tables=32 --table-size=10000000 + ``` + +4. 运行以下 `sysbench run` 命令对不同工作负载进行 Sysbench 性能测试。本文对五个工作负载进行测试:`oltp_point_select`、`oltp_read_write`、`oltp_update_non_index`、`oltp_update_index` 和 `oltp_insert`。对于每个工作负载,本文使用不同的 `${THREAD}` 值进行三次测试。对于 `oltp_point_select` 和 `oltp_read_write`,值为 `50`、`100` 和 `200`。对于其他工作负载,值为 `100`、`200` 和 `400`。每个并发测试持续 20 分钟。 + + ```shell + sysbench ${WORKLOAD} run \ + --mysql-host=${HOST} \ + --mysql-port=${PORT} \ + --mysql-user=root \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --threads=${THREAD} \ + --time=1200 \ + --report-interval=10 \ + --tables=32 \ + --table-size=10000000 \ + --mysql-ignore-errors=1062,2013,8028,9007 \ + --auto-inc=false \ + --mysql-password=${PASSWORD} + ``` + +## 测试结果 + +本节介绍 v8.5.0 在[测试环境](#测试环境)中的 Sysbench 性能。 + +### 点查性能 + +`oltp_point_select` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 50 | 32,733 | 1.94 | +| 100 | 62,123 | 2.04 | +| 200 | 107,795 | 2.56 | + +![Sysbench 点查性能](/media/tidb-cloud/v8.5.0_oltp_point_select.png) + +### 读写性能 + +`oltp_read_write` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 50 | 1,258 | 45.8 | +| 100 | 2,243 | 52 | +| 200 | 3,187 | 94.7 | + +![Sysbench 读写性能](/media/tidb-cloud/v8.5.0_oltp_read_write.png) + +### 更新非索引性能 + +`oltp_update_non_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 100 | 12,969 | 10.10 | +| 200 | 23,265 | 11.2 | +| 400 | 39,547 | 13.2 | + +![Sysbench 更新非索引性能](/media/tidb-cloud/v8.5.0_oltp_update_non_index.png) + +### 更新索引性能 + +`oltp_update_index` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 100 | 11,678 | 11.0 | +| 200 | 17,685 | 14.8 | +| 400 | 25,369 | 20.4 | + +![Sysbench 更新索引性能](/media/tidb-cloud/v8.5.0_oltp_update_index.png) + +### 插入性能 + +`oltp_insert` 工作负载的性能如下: + +| 线程数 | TPS | 95% 延迟 (ms)| +|:--------|:----------|:----------| +| 100 | 18,409 | 7.28| +| 200 | 30,943 | 8.28 | +| 400 | 48,621 | 11.2 | + +![Sysbench 插入性能](/media/tidb-cloud/v8.5.0_oltp_insert.png) diff --git a/tidb-cloud/v8.5-performance-benchmarking-with-tpcc.md b/tidb-cloud/v8.5-performance-benchmarking-with-tpcc.md new file mode 100644 index 000000000000..2031afe16723 --- /dev/null +++ b/tidb-cloud/v8.5-performance-benchmarking-with-tpcc.md @@ -0,0 +1,123 @@ +--- +title: TiDB v8.5.0 在 TiDB Cloud 上的 TPC-C 性能测试报告 +summary: 介绍 TiDB v8.5.0 版本在 TiDB Cloud Dedicated 集群上的 TPC-C 性能测试步骤和结果。 +--- + +# TiDB v8.5.0 在 TiDB Cloud 上的 TPC-C 性能测试报告 + +本文提供了 TiDB v8.5.0 版本在 TiDB Cloud Dedicated 集群上的 TPC-C 性能测试步骤和结果。本报告也可以作为 TiDB Self-Managed v8.5.0 集群性能的参考。 + +## 测试概述 + +本测试旨在展示 TiDB v8.5.0 在在线事务处理(OLTP)场景下的 TPC-C 性能。 + +## 测试环境 + +### TiDB 集群 + +测试在具有以下设置的 TiDB 集群上进行: + +- 集群类型:[TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated) +- 集群版本:v8.5.0 +- 云服务提供商:AWS (us-west-2) +- 集群配置: + + | 节点类型 | 节点规格 | 节点数量 | 节点存储 | + |:----------|:----------|:----------|:----------| + | TiDB | 16 vCPU, 32 GiB | 2 | N/A | + | TiKV | 16 vCPU, 64 GiB | 3 | 1000 GiB | + +### 参数配置 + +> **注意:** +> +> 对于 TiDB Cloud,如需修改集群的 TiKV 参数,你可以联系 [PingCAP 技术支持](/tidb-cloud/tidb-cloud-support.md)获取帮助。 + +TiKV 参数 [`prefill-for-recycle`](https://docs.pingcap.com/tidb/stable/tikv-configuration-file#prefill-for-recycle-new-in-v700) 可以使日志回收在初始化后立即生效。本文在启用 `prefill-for-recycle` 的情况下进行测试: + +```yaml +raft-engine.prefill-for-recycle = true +``` + +### 基准测试执行器 + +基准测试执行器向 TiDB 集群发送 SQL 查询。在本测试中,其硬件配置如下: + +- 机器类型:Amazon EC2 (us-west-2) +- 实例类型:c6a.2xlarge + +## 测试步骤 + +本节介绍如何逐步执行 TPC-C 性能测试。 + +1. 在 [TiDB Cloud 控制台](https://tidbcloud.com/)中,创建一个满足[测试环境](#tidb-集群)要求的 TiDB Cloud Dedicated 集群。 + + 更多信息,请参见[创建 TiDB Cloud Dedicated 集群](/tidb-cloud/create-tidb-cluster.md)。 + +2. 在基准测试执行器上,连接到新创建的集群并创建名为 `tpcc` 的数据库。 + + 要连接到集群,请参见[通过专用连接点连接到 TiDB Cloud Dedicated](/tidb-cloud/set-up-private-endpoint-connections.md)。 + + 要创建 `tpcc` 数据库,执行以下 SQL 语句: + + ```sql + CREATE DATABASE tpcc; + ``` + +3. 将 TPC-C 数据加载到 `tpcc` 数据库。 + + 1. 本文中的测试基于 [go-tpc](https://github.com/pingcap/go-tpc) 实现。你可以使用以下命令下载测试程序: + + ```shell + curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/pingcap/go-tpc/master/install.sh | sh + ``` + + 2. 运行以下 `go-tpc tpcc` 命令,向 `tpcc` 数据库导入 1,000 个仓库。将 `${HOST}`、`${THREAD}` 和 `${PASSWORD}` 替换为你的实际值。本文使用 `${THREAD}` 值为 `50`、`100` 和 `200` 进行三次测试。 + + ```shell + go-tpc tpcc --host ${HOST} --warehouses 1000 prepare -P 4000 -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +4. 为确保 TiDB 优化器能生成最优执行计划,在进行 TPC-C 测试之前执行以下 SQL 语句收集统计信息: + + ```sql + ANALYZE TABLE customer; + ANALYZE TABLE district; + ANALYZE TABLE history; + ANALYZE TABLE item; + ANALYZE TABLE new_order; + ANALYZE TABLE order_line; + ANALYZE TABLE orders; + ANALYZE TABLE stock; + ANALYZE TABLE warehouse; + ``` + + 为加快统计信息收集速度,在收集前执行以下 SQL 语句: + + ```sql + SET tidb_build_stats_concurrency=16; + SET tidb_distsql_scan_concurrency=16; + SET tidb_index_serial_scan_concurrency=16; + ``` + +5. 运行以下 `go-tpc tpcc` 命令对 TiDB Cloud Dedicated 集群进行压力测试。每个并发测试持续两小时。 + + ```shell + go-tpc tpcc --host ${HOST} -P 4000 --warehouses 1000 run -D tpcc -T ${THREAD} --time 2h0m0s -p ${PASSWORD} --ignore-error + ``` + +6. 从结果中提取 `NEW_ORDER` 的 tpmC 数据。 + + TPC-C 使用 tpmC(每分钟事务数)来衡量最大限定吞吐量(MQTh,Max Qualified Throughput)。事务是 NewOrder 事务,最终的衡量单位是每分钟处理的新订单数。 + +## 测试结果 + +v8.5.0 在[测试环境](#测试环境)中的 TPC-C 性能如下: + +| 线程数 | v8.5.0 tpmC | +|:--------|:----------| +| 50 | 43,146 | +| 100 | 73,875 | +| 200 | 103,395 | + +![TPC-C](/media/tidb-cloud/v8.5.0_tpcc.png) diff --git a/tidb-cloud/v8.5-performance-highlights.md b/tidb-cloud/v8.5-performance-highlights.md new file mode 100644 index 000000000000..e412972c262b --- /dev/null +++ b/tidb-cloud/v8.5-performance-highlights.md @@ -0,0 +1,248 @@ +--- +title: TiDB v8.5.0 版本的 TiDB Cloud 性能亮点 +summary: 介绍 TiDB v8.5.0 版本的 TiDB Cloud Dedicated 集群的性能改进。 +--- + +# TiDB v8.5.0 版本的 TiDB Cloud 性能亮点 + +[TiDB v8.5.0](https://docs.pingcap.com/tidb/v8.5/release-8.5.0) 是一个重要的长期支持(LTS)版本,在性能、可扩展性和运维效率方面都有显著改进。 + +本文概述了 v8.5.0 在以下方面的性能改进: + +- 整体性能 +- 具有大量 MVCC 版本的热点读取 +- IO 延迟抖动 +- 批处理 +- TiKV 扩展性能 + +## 整体性能 + +在 v8.5.0 中,默认 Region 大小从 96 MiB 增加到 256 MiB,并且还有其他一些改进,观察到显著的性能提升: + +- `oltp_insert` 性能提升 27%。 +- `Analyze` 性能显著提升约 45%。 + +## 具有大量 MVCC 版本的热点读取 + +### 挑战 + +在某些用户场景中,可能会出现以下挑战: + +- 频繁的版本更新:在某些工作负载中,数据被非常频繁地更新和读取。 +- 历史版本保留时间长:为了满足业务需求,如支持回退到特定时间点,用户可能会配置过长的 GC(垃圾回收)时间(如 24 小时)。这导致多版本并发控制(MVCC)版本过度累积,显著降低查询效率。 + +MVCC 版本的累积在请求的数据和处理的数据之间创造了巨大的差距,导致读取性能下降。 + +### 解决方案 + +为了解决这个问题,TiKV 引入了[内存引擎(IME)](https://docs.pingcap.com/tidb/stable/tikv-in-memory-engine)。通过在内存中缓存最新版本,TiKV 减少了历史版本对读取性能的影响,显著提高了查询效率。 + +### 测试环境 + +- 集群拓扑:TiDB(16 vCPU,32 GiB)\* 1 + TiKV(16 vCPU,32 GiB)\* 6 +- 集群配置: + + ``` + tikv_configs: + [in-memory-engine] + enable = true + ``` + +- 数据集:24 GiB 存储大小,约 340 个 Region,包含频繁更新的数据 +- 工作负载:需要扫描的行包含由频繁更新引入的大量 MVCC 版本 + +### 测试结果 + +查询延迟降低 50%,吞吐量提高 100%。 + +| 配置 | 持续时间(秒) | 线程数 | TPS | QPS | 平均延迟(毫秒) | P95 延迟(毫秒) | +| --- | --- | --- | --- | --- | --- | --- | +| 禁用 IME | 3600 | 10 | 123.8 | 1498.3 | 80.76 | 207.82 | +| 启用 IME | 3600 | 10 | 238.2 | 2881.5 | 41.99 | 78.60 | + +## IO 延迟抖动 + +### 挑战 + +在云环境中,云盘上的瞬时或持续的 IO 延迟波动是一个常见的挑战。这些波动会增加请求延迟,导致超时、错误和正常业务运营中断,最终降低服务质量。 + +### 解决方案 + +TiDB v8.5.0 引入了多项增强功能,以减轻云盘 IO 抖动对性能的影响: + +- **Leader 写入优化**:允许 leader 提前应用已提交但尚未持久化的 Raft 日志,减少 IO 抖动对 leader peer 写入延迟的影响。 +- **增强的慢节点检测**:改进了慢节点检测算法,默认启用慢分数检测。当识别到慢节点时,触发 evict-leader 调度器以恢复性能。[慢节点检测机制](https://docs.pingcap.com/tidb/v8.5/pd-scheduling-best-practices#troubleshoot-tikv-node)使用 [evict-slow-store-scheduler](https://docs.pingcap.com/tidb/v8.5/pd-control#scheduler-show--add--remove--pause--resume--config--describe) 来检测和管理慢节点,减少云盘抖动的影响。 + +- **统一健康控制器**:在 TiKV 中添加统一健康控制器,并向 KV 客户端提供反馈机制。KV 客户端根据 TiKV 节点的健康状况和性能优化错误处理和副本选择。 +- **改进的副本选择器**:在 KV 客户端中引入副本选择器 V2,具有精细的状态转换,消除不必要的重试和退避操作。 +- **其他修复和改进**:包括对关键组件(如 region 缓存和 KV 客户端健康检查器)的增强,同时避免 TiKV 的 store 循环中不必要的 IO 操作。 + +### 测试环境 + +- 集群拓扑:TiDB(32 vCPU,64 GiB)\* 3 + TiKV(32 vCPU,64 GiB)\* 6 +- 工作负载:读写比为 2:1,在一个 TiKV 节点上模拟云盘 IO 延迟或挂起 + +### 测试结果 + +基于上述测试设置,在多个 IO 延迟场景中故障转移得到改进,影响期间的 P99/999 延迟最高降低 98%。 + +在下表的测试结果中,**当前**列显示减少 IO 延迟抖动改进后的结果,而**原始**列显示没有这些改进的结果: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
工作负载描述故障转移时间影响期间最大延迟(P999)影响期间最大延迟(P99)
当前原始当前原始当前原始
IO 延迟 2 毫秒持续 10 分钟几乎无影响无法故障转移14 毫秒232 毫秒7.9 毫秒22.9 毫秒
IO 延迟 5 毫秒持续 10 分钟2 分钟无法故障转移37.9 毫秒462 毫秒10 毫秒246 毫秒
IO 延迟 10 毫秒持续 10 分钟3 分钟无法故障转移69 毫秒3 秒25 毫秒1.45 秒
IO 延迟 50 毫秒持续 10 分钟3 分钟无法故障转移1.36 秒13.2 秒238 毫秒6.7 秒
IO 延迟 100 毫秒持续 10 分钟3 分钟无法故障转移7.53 秒32 秒1.7 秒26 秒
+ +### 进一步改进 + +磁盘抖动的严重程度可能与用户的工作负载特征高度相关。在对延迟敏感的场景中,将应用程序设计与 TiDB 功能结合可以进一步最小化 IO 抖动对应用程序的影响。例如,在读取密集且对延迟敏感的环境中,根据延迟要求调整 [`tikv_client_read_timeout`](/system-variables.md#tikv_client_read_timeout-new-in-v740) 系统变量,并使用 stale read 或 follower read,可以使从 TiDB 发送的 KV 请求更快地故障转移到其他副本节点。这减少了单个 TiKV 节点上 IO 抖动的影响,有助于改善查询延迟。请注意,此功能的有效性取决于工作负载特征,应在实施前进行评估。 + +此外,[在公有云上部署 TiDB](https://docs.pingcap.com/tidb/dev/best-practices-on-public-cloud) 的用户可以通过选择性能更高的云盘来降低抖动的概率。 + +## 批处理 + +### 挑战 + +大规模事务,如批量数据更新、系统迁移和 ETL 工作流,涉及处理数百万行数据,对支持关键操作至关重要。虽然 TiDB 作为分布式 SQL 数据库表现出色,但大规模处理此类事务面临两个重大挑战: + +- 内存限制:在早于 TiDB v8.1.0 的版本中,所有事务变更在整个事务生命周期中都保存在内存中,这会消耗资源并降低性能。对于涉及数百万行的操作,这可能导致过度的内存使用,在资源不足时甚至可能出现内存溢出(OOM)错误。 + +- 性能下降:管理大型内存缓冲区依赖于红黑树,这会引入计算开销。随着缓冲区增长,由于这些数据结构固有的 *O(N log N)* 复杂度,其操作会变慢。 + +### 解决方案 + +这些挑战突显了提高可扩展性、降低复杂性和增强可靠性的明确机会。随着现代数据工作负载的增加,TiDB 引入了[流水线 DML](https://docs.pingcap.com/tidb/stable/system-variables#tidb_dml_type-new-in-v800) 功能,旨在优化大型事务的处理,提高资源利用率和整体性能。 + +### 测试环境 + +- 集群拓扑:TiDB(16 vCPU,32 GiB)\* 1 + TiKV(16 vCPU,32 GiB)\* 3 +- 数据集:YCSB 非聚簇表,包含 1000 万行(约 10 GiB 数据)。在某些测试中选择性地移除主键,以隔离和评估热点模式的影响。 +- 工作负载:包括 `INSERT`、`UPDATE` 和 `DELETE` 的 DML 操作。 + +### 测试结果 + +执行速度提高 2 倍,TiDB 最大内存使用量降低 50%,TiKV 写入流变得更加平稳。 + +- 延迟(秒) + + | 工作负载(10 GiB) | 标准 DML | 流水线 DML | 改进 | + | --- | --- | --- | --- | + | YCSB-insert-10M | 368 | 159 | 131.45% | + | YCSB-update-10M | 255 | 131 | 94.66% | + | YCSB-delete-10M | 136 | 42 | 223.81% | + +- TiDB 内存使用峰值(GiB) + + | 工作负载(10 GiB) | 标准 DML | 流水线 DML | 降低 | + | --- | --- | --- | --- | + | YCSB-insert-10M | 25.8 | 12 | 53.49% | + | YCSB-update-10M | 23.1 | 12.9 | 44.16% | + | YCSB-delete-10M | 10.1 | 8.08 | 20.00% | + +## TiKV 扩展性能 + +### 挑战 + +水平扩展是 TiKV 的核心能力,使系统能够根据需要进行扩容或缩容。随着业务需求增长和租户数量增加,TiDB 集群在数据库、表和数据量方面都经历快速增长。快速扩展 TiKV 节点成为维持服务质量的关键。 + +在某些场景中,TiDB 托管大量数据库和表。当这些表较小或为空时,特别是当表的数量增长到较大规模(如 100 万或更多)时,TiKV 会累积大量微小的 Region。这些小 Region 带来了巨大的维护负担,增加了资源开销,降低了效率。 + +### 解决方案 + +为了解决这个问题,TiDB v8.5.0 改进了合并小 Region 的性能,减少了内部开销并提高了资源利用率。此外,TiDB v8.5.0 还包括其他几项增强功能,进一步改进了 TiKV 扩展性能。 + +### 测试环境 + +#### 合并小 Region + +- 集群拓扑:TiDB(16 vCPU,32 GiB)\* 1 + TiKV(16 vCPU,32 GiB)\* 3 +- 数据集:近 100 万个小表,每个表大小 < 2 MiB +- 工作负载:自动合并小 Region + +#### 扩展 TiKV 节点 + +- 集群拓扑:TiDB(16 vCPU,32 GiB)\* 1 + TiKV(16 vCPU,32 GiB)\* 4 +- 数据集:20,000 个仓库的 TPC-C 数据集 +- 工作负载:将 TiKV 节点从 4 个扩展到 7 个 + +### 测试结果 + +小 Region 合并速度提高约 10 倍。 + +| 指标 | 未改进 | 改进后 | +| --- | --- | --- | +| Region 合并持续时间(小时) | 20 | 2 | + +TiKV 扩展性能提高超过 40%,TiKV 节点扩容持续时间减少 30%。 + +| 指标 | 未改进 | 改进后 | +| --- | --- | --- | +| TiKV 扩容持续时间(小时) | 5 | 3.5 | + +## 基准测试 + +除了上述测试数据外,你还可以参考以下 v8.5.0 性能的基准测试结果: + +- [TPC-C 性能测试报告](/tidb-cloud/v8.5-performance-benchmarking-with-tpcc.md) +- [Sysbench 性能测试报告](/tidb-cloud/v8.5-performance-benchmarking-with-sysbench.md) diff --git a/tidb-cloud/vector-search-changelogs.md b/tidb-cloud/vector-search-changelogs.md new file mode 100644 index 000000000000..1a25ce3470ea --- /dev/null +++ b/tidb-cloud/vector-search-changelogs.md @@ -0,0 +1,14 @@ +--- +title: 向量搜索更新日志 +summary: 了解 TiDB 向量搜索功能的新特性、兼容性变更、改进和错误修复。 +--- + +# 向量搜索更新日志 + +## 2024 年 6 月 25 日 + +- TiDB 向量搜索(测试版)现已在所有地区对所有 TiDB Cloud Serverless 集群用户开放。 + +## 2024 年 4 月 1 日 + +- TiDB 向量搜索(测试版)现已在欧盟地区对受邀的 TiDB Cloud Serverless 集群用户开放。 diff --git a/tidb-cloud/vector-search-data-types.md b/tidb-cloud/vector-search-data-types.md new file mode 100644 index 000000000000..c356153b6222 --- /dev/null +++ b/tidb-cloud/vector-search-data-types.md @@ -0,0 +1,246 @@ +--- +title: 向量数据类型 +summary: 了解 TiDB 中的向量数据类型。 +--- + +# 向量数据类型 + +向量是一个浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`。TiDB 提供了向量数据类型,专门针对在 AI 应用中广泛使用的向量嵌入进行了存储和查询优化。 + +目前提供以下向量数据类型: + +- `VECTOR`:任意维度的单精度浮点数序列。 +- `VECTOR(D)`:固定维度 `D` 的单精度浮点数序列。 + +使用向量数据类型相比使用 [`JSON`](/data-type-json.md) 类型有以下优势: + +- 支持向量索引:你可以构建[向量搜索索引](/tidb-cloud/vector-search-index.md)来加速向量搜索。 +- 维度限制:你可以指定维度以禁止插入不同维度的向量。 +- 优化的存储格式:向量数据类型针对处理向量数据进行了优化,与 `JSON` 类型相比提供更好的空间效率和性能。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB 自建集群(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 语法 + +你可以使用以下语法的字符串来表示向量值: + +```sql +'[, , ...]' +``` + +示例: + +```sql +CREATE TABLE vector_table ( + id INT PRIMARY KEY, + embedding VECTOR(3) +); + +INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); + +INSERT INTO vector_table VALUES (2, NULL); +``` + +插入语法无效的向量值将导致错误: + +```sql +[tidb]> INSERT INTO vector_table VALUES (3, '[5, ]'); +ERROR 1105 (HY000): Invalid vector text: [5, ] +``` + +在以下示例中,由于在创建表时为 `embedding` 列强制指定了维度 `3`,插入不同维度的向量将导致错误: + +```sql +[tidb]> INSERT INTO vector_table VALUES (4, '[0.3, 0.5]'); +ERROR 1105 (HY000): vector has 2 dimensions, does not fit VECTOR(3) +``` + +有关向量数据类型的可用函数和运算符,请参见[向量函数和运算符](/tidb-cloud/vector-search-functions-and-operators.md)。 + +有关构建和使用向量搜索索引的更多信息,请参见[向量搜索索引](/tidb-cloud/vector-search-index.md)。 + +## 存储不同维度的向量 + +你可以通过省略 `VECTOR` 类型的维度参数,在同一列中存储不同维度的向量: + +```sql +CREATE TABLE vector_table ( + id INT PRIMARY KEY, + embedding VECTOR +); + +INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 3 维向量,正确 +INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 维向量,正确 +``` + +但是请注意,你不能为此列构建[向量搜索索引](/tidb-cloud/vector-search-index.md),因为向量距离只能在相同维度的向量之间计算。 + +## 比较 + +你可以使用[比较运算符](/functions-and-operators/operators.md)(如 `=`、`!=`、`<`、`>`、`<=` 和 `>=`)来比较向量数据类型。有关向量数据类型的完整比较运算符和函数列表,请参见[向量函数和运算符](/tidb-cloud/vector-search-functions-and-operators.md)。 + +向量数据类型按元素进行数值比较。例如: + +- `[1] < [12]` +- `[1,2,3] < [1,2,5]` +- `[1,2,3] = [1,2,3]` +- `[2,2,3] > [1,2,3]` + +不同维度的向量使用字典序比较,规则如下: + +- 两个向量从开始按元素逐个比较,每个元素进行数值比较。 +- 第一个不匹配的元素决定哪个向量在字典序上_小于_或_大于_另一个。 +- 如果一个向量是另一个向量的前缀,则较短的向量在字典序上_小于_另一个。例如,`[1,2,3] < [1,2,3,0]`。 +- 长度相同且元素相同的向量在字典序上_相等_。 +- 空向量在字典序上_小于_任何非空向量。例如,`[] < [1]`。 +- 两个空向量在字典序上_相等_。 + +在比较向量常量时,考虑执行从字符串到向量的[显式转换](#转换),以避免基于字符串值的比较: + +```sql +-- 因为给定的是字符串,TiDB 正在比较字符串: +[tidb]> SELECT '[12.0]' < '[4.0]'; ++--------------------+ +| '[12.0]' < '[4.0]' | ++--------------------+ +| 1 | ++--------------------+ +1 row in set (0.01 sec) + +-- 显式转换为向量以按向量比较: +[tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]'); ++--------------------------------------------------+ +| VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') | ++--------------------------------------------------+ +| 0 | ++--------------------------------------------------+ +1 row in set (0.01 sec) +``` + +## 算术运算 + +向量数据类型支持算术运算 `+`(加法)和 `-`(减法)。但是,不支持不同维度向量之间的算术运算,这将导致错误。 + +示例: + +```sql +[tidb]> SELECT VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[5]'); ++---------------------------------------------+ +| VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[5]') | ++---------------------------------------------+ +| [9] | ++---------------------------------------------+ +1 row in set (0.01 sec) + +[tidb]> SELECT VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]'); ++-----------------------------------------------------+ +| VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]') | ++-----------------------------------------------------+ +| [1,1,1] | ++-----------------------------------------------------+ +1 row in set (0.01 sec) + +[tidb]> SELECT VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[1,2,3]'); +ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +``` + +## 转换 + +### 在向量 ⇔ 字符串之间转换 + +要在向量和字符串之间进行转换,使用以下函数: + +- `CAST(... AS VECTOR)`:字符串 ⇒ 向量 +- `CAST(... AS CHAR)`:向量 ⇒ 字符串 +- `VEC_FROM_TEXT`:字符串 ⇒ 向量 +- `VEC_AS_TEXT`:向量 ⇒ 字符串 + +为了提高可用性,如果你调用仅支持向量数据类型的函数(如向量相关距离函数),你也可以直接传入格式合规的字符串。在这种情况下,TiDB 会自动执行隐式转换。 + +```sql +-- VEC_DIMS 函数只接受 VECTOR 参数,所以你可以直接传入字符串进行隐式转换。 +[tidb]> SELECT VEC_DIMS('[0.3, 0.5, -0.1]'); ++------------------------------+ +| VEC_DIMS('[0.3, 0.5, -0.1]') | ++------------------------------+ +| 3 | ++------------------------------+ +1 row in set (0.01 sec) + +-- 你也可以使用 VEC_FROM_TEXT 显式将字符串转换为向量,然后将向量传递给 VEC_DIMS 函数。 +[tidb]> SELECT VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]')); ++---------------------------------------------+ +| VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]')) | ++---------------------------------------------+ +| 3 | ++---------------------------------------------+ +1 row in set (0.01 sec) + +-- 你也可以使用 CAST(... AS VECTOR) 显式转换: +[tidb]> SELECT VEC_DIMS(CAST('[0.3, 0.5, -0.1]' AS VECTOR)); ++----------------------------------------------+ +| VEC_DIMS(CAST('[0.3, 0.5, -0.1]' AS VECTOR)) | ++----------------------------------------------+ +| 3 | ++----------------------------------------------+ +1 row in set (0.01 sec) +``` + +当使用接受多种数据类型的运算符或函数时,你需要在将字符串传递给该运算符或函数之前显式将字符串类型转换为向量类型,因为在这种情况下 TiDB 不执行隐式转换。例如,在执行比较操作之前,你需要显式将字符串转换为向量;否则,TiDB 会将它们作为字符串值而不是向量数值进行比较: + +```sql +-- 因为给定的是字符串,TiDB 正在比较字符串: +[tidb]> SELECT '[12.0]' < '[4.0]'; ++--------------------+ +| '[12.0]' < '[4.0]' | ++--------------------+ +| 1 | ++--------------------+ +1 row in set (0.01 sec) + +-- 显式转换为向量以按向量比较: +[tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]'); ++--------------------------------------------------+ +| VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') | ++--------------------------------------------------+ +| 0 | ++--------------------------------------------------+ +1 row in set (0.01 sec) +``` + +你也可以显式将向量转换为其字符串表示。以使用 `VEC_AS_TEXT()` 函数为例: + +```sql +-- 字符串首先被隐式转换为向量,然后向量被显式转换为字符串,因此返回规范格式的字符串: +[tidb]> SELECT VEC_AS_TEXT('[0.3, 0.5, -0.1]'); ++--------------------------------------+ +| VEC_AS_TEXT('[0.3, 0.5, -0.1]') | ++--------------------------------------+ +| [0.3,0.5,-0.1] | ++--------------------------------------+ +1 row in set (0.01 sec) +``` + +有关其他转换函数,请参见[向量函数和运算符](/tidb-cloud/vector-search-functions-and-operators.md)。 + +### 在向量 ⇔ 其他数据类型之间转换 + +目前,不支持向量与其他数据类型(如 `JSON`)之间的直接转换。要解决此限制,请在 SQL 语句中使用字符串作为中间数据类型进行转换。 + +请注意,使用 `ALTER TABLE ... MODIFY COLUMN ...` 无法将表中存储的向量数据类型列转换为其他数据类型。 + +## 限制 + +请参见[向量数据类型限制](/tidb-cloud/vector-search-limitations.md#vector-data-type-limitations)。 + +## MySQL 兼容性 + +向量数据类型是 TiDB 特有的,MySQL 不支持。 + +## 另请参阅 + +- [向量函数和运算符](/tidb-cloud/vector-search-functions-and-operators.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) +- [提高向量搜索性能](/tidb-cloud/vector-search-improve-performance.md) diff --git a/tidb-cloud/vector-search-full-text-search-python.md b/tidb-cloud/vector-search-full-text-search-python.md new file mode 100644 index 000000000000..4efd3e869bd4 --- /dev/null +++ b/tidb-cloud/vector-search-full-text-search-python.md @@ -0,0 +1,172 @@ +--- +title: 使用 Python 进行全文搜索 +summary: 全文搜索允许您检索精确关键词的文档。在检索增强生成(RAG)场景中,您可以将全文搜索与向量搜索结合使用,以提高检索质量。 +--- + +# 使用 Python 进行全文搜索 + +与专注于语义相似性的[向量搜索](/tidb-cloud/vector-search-overview.md)不同,全文搜索允许您检索精确关键词的文档。在检索增强生成(RAG)场景中,您可以将全文搜索与向量搜索结合使用,以提高检索质量。 + +TiDB 的全文搜索功能提供以下能力: + +- **直接查询文本数据**:您可以直接搜索任何字符串列,无需进行嵌入处理。 + +- **支持多种语言**:无需指定语言即可进行高质量搜索。TiDB 支持在同一个表中存储多种语言的文档,并自动为每个文档选择最佳的文本分析器。 + +- **按相关性排序**:搜索结果可以使用广泛采用的 [BM25 排序](https://en.wikipedia.org/wiki/Okapi_BM25)算法按相关性排序。 + +- **完全兼容 SQL**:所有 SQL 功能,如预过滤、后过滤、分组和连接,都可以与全文搜索一起使用。 + +> **提示:** +> +> 关于 SQL 用法,请参见[使用 SQL 进行全文搜索](/tidb-cloud/vector-search-full-text-search-sql.md)。 +> +> 要在 AI 应用中同时使用全文搜索和向量搜索,请参见[混合搜索](/tidb-cloud/vector-search-hybrid-search.md)。 + +## 前提条件 + +全文搜索仍处于早期阶段,我们正在持续向更多客户推出。目前,全文搜索仅适用于以下产品选项和地区: + +- TiDB Cloud Serverless:`法兰克福 (eu-central-1)` 和 `新加坡 (ap-southeast-1)` + +要完成本教程,请确保您在支持的地区有一个 TiDB Cloud Serverless 集群。如果您还没有,请按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建一个。 + +## 开始使用 + +### 步骤 1. 安装 [pytidb](https://github.com/pingcap/pytidb) Python SDK + +[pytidb](https://github.com/pingcap/pytidb) 是 TiDB 的官方 Python SDK,旨在帮助开发者高效构建 AI 应用。它内置支持向量搜索和全文搜索。 + +要安装 SDK,请运行以下命令: + +```shell +pip install pytidb + +# (替代方案)要使用内置的嵌入函数和重排序器: +# pip install "pytidb[models]" + +# (可选)要将查询结果转换为 pandas DataFrame: +# pip install pandas +``` + +### 步骤 2. 连接到 TiDB + +```python +from pytidb import TiDBClient + +db = TiDBClient.connect( + host="HOST_HERE", + port=4000, + username="USERNAME_HERE", + password="PASSWORD_HERE", + database="DATABASE_HERE", +) +``` + +您可以从 [TiDB Cloud 控制台](https://tidbcloud.com)获取这些连接参数: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示一个连接对话框,列出连接参数。 + + 例如,如果连接参数显示如下: + + ```text + HOST: gateway01.us-east-1.prod.shared.aws.tidbcloud.com + PORT: 4000 + USERNAME: 4EfqPF23YKBxaQb.root + PASSWORD: abcd1234 + DATABASE: test + CA: /etc/ssl/cert.pem + ``` + + 连接到 TiDB Cloud Serverless 集群的相应 Python 代码如下: + + ```python + db = TiDBClient.connect( + host="gateway01.us-east-1.prod.shared.aws.tidbcloud.com", + port=4000, + username="4EfqPF23YKBxaQb.root", + password="abcd1234", + database="test", + ) + ``` + + 请注意,上述示例仅用于演示目的。您需要使用自己的值填充参数并确保它们的安全性。 + +### 步骤 3. 创建表和全文索引 + +以下是一个示例,创建一个名为 `chunks` 的表,包含以下列: + +- `id` (int):块的 ID。 +- `text` (text):块的文本内容。 +- `user_id` (int):创建块的用户 ID。 + +```python +from pytidb.schema import TableModel, Field + +class Chunk(TableModel, table=True): + __tablename__ = "chunks" + + id: int = Field(primary_key=True) + text: str = Field() + user_id: int = Field() + +table = db.create_table(schema=Chunk) + +if not table.has_fts_index("text"): + table.create_fts_index("text") # 👈 在文本列上创建全文索引。 +``` + +### 步骤 4. 插入数据 + +```python +table.bulk_insert( + [ + Chunk(id=2, text="the quick brown", user_id=2), + Chunk(id=3, text="fox jumps", user_id=3), + Chunk(id=4, text="over the lazy dog", user_id=4), + ] +) +``` + +### 步骤 5. 执行全文搜索 + +插入数据后,您可以按如下方式执行全文搜索: + +```python +df = ( + table.search("brown fox", search_type="fulltext") + .limit(2) + .to_pandas() # 可选 +) + +# id text user_id +# 0 3 fox jumps 3 +# 1 2 the quick brown 2 +``` + +完整示例请参见 [pytidb 全文搜索演示](https://github.com/pingcap/pytidb/blob/main/examples/fulltext_search)。 + +## 另请参阅 + +- [pytidb Python SDK 文档](https://github.com/pingcap/pytidb) + +- [混合搜索](/tidb-cloud/vector-search-hybrid-search.md) + +## 反馈与帮助 + +全文搜索仍处于早期阶段,可用性有限。如果您想在尚未提供服务的地区尝试全文搜索,或者如果您有反馈或需要帮助,请随时联系我们: + + + +- [加入我们的 Discord](https://discord.gg/zcqexutz2R) + + + + + +- [加入我们的 Discord](https://discord.gg/zcqexutz2R) +- [访问我们的支持门户](https://tidb.support.pingcap.com/) + + diff --git a/tidb-cloud/vector-search-full-text-search-sql.md b/tidb-cloud/vector-search-full-text-search-sql.md new file mode 100644 index 000000000000..57b3af416841 --- /dev/null +++ b/tidb-cloud/vector-search-full-text-search-sql.md @@ -0,0 +1,219 @@ +--- +title: 使用 SQL 进行全文搜索 +summary: 全文搜索允许您通过精确关键词检索文档。在检索增强生成(RAG)场景中,您可以将全文搜索与向量搜索结合使用,以提高检索质量。 +--- + +# 使用 SQL 进行全文搜索 + +与专注于语义相似度的[向量搜索](/tidb-cloud/vector-search-overview.md)不同,全文搜索允许您通过精确关键词检索文档。在检索增强生成(RAG)场景中,您可以将全文搜索与向量搜索结合使用,以提高检索质量。 + +TiDB 的全文搜索功能提供以下能力: + +- **直接查询文本数据**:您可以直接搜索任何字符串列,无需进行嵌入处理。 + +- **支持多种语言**:无需指定语言即可实现高质量搜索。TiDB 中的文本分析器支持在同一个表中混合使用多种语言的文档,并自动为每个文档选择最佳的分析器。 + +- **按相关性排序**:搜索结果可以使用广泛采用的 [BM25 排序](https://en.wikipedia.org/wiki/Okapi_BM25)算法按相关性排序。 + +- **完全兼容 SQL**:所有 SQL 功能,如预过滤、后过滤、分组和连接,都可以与全文搜索一起使用。 + +> **提示:** +> +> 关于 Python 用法,请参见[使用 Python 进行全文搜索](/tidb-cloud/vector-search-full-text-search-python.md)。 +> +> 要在 AI 应用中同时使用全文搜索和向量搜索,请参见[混合搜索](/tidb-cloud/vector-search-hybrid-search.md)。 + +## 开始使用 + +全文搜索仍处于早期阶段,我们正在持续向更多客户推出。目前,全文搜索仅适用于以下产品选项和地区: + +- TiDB Cloud Serverless:`法兰克福 (eu-central-1)` 和 `新加坡 (ap-southeast-1)` + +在使用全文搜索之前,请确保您的 TiDB Cloud Serverless 集群创建在支持的地区。如果您还没有集群,请按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建一个。 + +要执行全文搜索,请按照以下步骤操作: + +1. [**创建全文索引**](#创建全文索引):创建带有全文索引的表,或为现有表添加全文索引。 + +2. [**插入文本数据**](#插入文本数据):向表中插入文本数据。 + +3. [**执行全文搜索**](#执行全文搜索):使用文本查询和全文搜索函数执行全文搜索。 + +### 创建全文索引 + +要执行全文搜索,需要全文索引,因为它提供了高效搜索和排序所需的数据结构。全文索引可以在新表上创建,也可以添加到现有表中。 + +创建带有全文索引的表: + +```sql +CREATE TABLE stock_items( + id INT, + title TEXT, + FULLTEXT INDEX (title) WITH PARSER MULTILINGUAL +); +``` + +或为现有表添加全文索引: + +```sql +CREATE TABLE stock_items( + id INT, + title TEXT +); + +-- 您可能在这里插入一些数据。 +-- 即使表中已经有数据,也可以创建全文索引。 + +ALTER TABLE stock_items ADD FULLTEXT INDEX (title) WITH PARSER MULTILINGUAL ADD_COLUMNAR_REPLICA_ON_DEMAND; +``` + +在 `WITH PARSER ` 子句中可以使用以下解析器: + +- `STANDARD`:快速,适用于英文内容,按空格和标点符号分词。 + +- `MULTILINGUAL`:支持多种语言,包括英语、中文、日语和韩语。 + +### 插入文本数据 + +向带有全文索引的表中插入数据与向其他表插入数据完全相同。 + +例如,您可以执行以下 SQL 语句来插入多种语言的数据。TiDB 的多语言解析器会自动处理文本。 + +```sql +INSERT INTO stock_items VALUES (1, "イヤホン bluetooth ワイヤレスイヤホン "); +INSERT INTO stock_items VALUES (2, "完全ワイヤレスイヤホン/ウルトラノイズキャンセリング 2.0 "); +INSERT INTO stock_items VALUES (3, "ワイヤレス ヘッドホン Bluetooth 5.3 65時間再生 ヘッドホン 40mm HD "); +INSERT INTO stock_items VALUES (4, "楽器用 オンイヤーヘッドホン 密閉型【国内正規品】"); +INSERT INTO stock_items VALUES (5, "ワイヤレスイヤホン ハイブリッドANC搭載 40dBまでアクティブノイズキャンセル"); +INSERT INTO stock_items VALUES (6, "Lightweight Bluetooth Earbuds with 48 Hours Playtime"); +INSERT INTO stock_items VALUES (7, "True Wireless Noise Cancelling Earbuds - Compatible with Apple & Android, Built-in Microphone"); +INSERT INTO stock_items VALUES (8, "In-Ear Earbud Headphones with Mic, Black"); +INSERT INTO stock_items VALUES (9, "Wired Headphones, HD Bass Driven Audio, Lightweight Aluminum Wired in Ear Earbud Headphones"); +INSERT INTO stock_items VALUES (10, "LED Light Bar, Music Sync RGB Light Bar, USB Ambient Lamp"); +INSERT INTO stock_items VALUES (11, "无线消噪耳机-黑色 手势触控蓝牙降噪 主动降噪头戴式耳机(智能降噪 长久续航)"); +INSERT INTO stock_items VALUES (12, "专业版USB7.1声道游戏耳机电竞耳麦头戴式电脑网课办公麦克风带线控"); +INSERT INTO stock_items VALUES (13, "投影仪家用智能投影机便携卧室手机投影"); +INSERT INTO stock_items VALUES (14, "无线蓝牙耳机超长续航42小时快速充电 流光金属耳机"); +INSERT INTO stock_items VALUES (15, "皎月银 国家补贴 心率血氧监测 蓝牙通话 智能手表 男女表"); +``` + +### 执行全文搜索 + +要执行全文搜索,您可以使用 `FTS_MATCH_WORD()` 函数。 + +**示例:搜索最相关的 10 个文档** + +```sql +SELECT * FROM stock_items + WHERE fts_match_word("bluetoothイヤホン", title) + ORDER BY fts_match_word("bluetoothイヤホン", title) + DESC LIMIT 10; + +-- 结果按相关性排序,最相关的文档排在前面。 + ++------+-----------------------------------------------------------------------------------------------------------+ +| id | title | ++------+-----------------------------------------------------------------------------------------------------------+ +| 1 | イヤホン bluetooth ワイヤレスイヤホン | +| 6 | Lightweight Bluetooth Earbuds with 48 Hours Playtime | +| 2 | 完全ワイヤレスイヤホン/ウルトラノイズキャンセリング 2.0 | +| 3 | ワイヤレス ヘッドホン Bluetooth 5.3 65時間再生 ヘッドホン 40mm HD | +| 5 | ワイヤレスイヤホン ハイブリッドANC搭載 40dBまでアクティブノイズキャンセル | ++------+-----------------------------------------------------------------------------------------------------------+ + +-- 尝试用另一种语言搜索: +SELECT * FROM stock_items + WHERE fts_match_word("蓝牙耳机", title) + ORDER BY fts_match_word("蓝牙耳机", title) + DESC LIMIT 10; + +-- 结果按相关性排序,最相关的文档排在前面。 + ++------+---------------------------------------------------------------------------------------------------------------+ +| id | title | ++------+---------------------------------------------------------------------------------------------------------------+ +| 14 | 无线蓝牙耳机超长续航42小时快速充电 流光金属耳机 | +| 11 | 无线消噪耳机-黑色 手势触控蓝牙降噪 主动降噪头戴式耳机(智能降噪 长久续航) | +| 15 | 皎月银 国家补贴 心率血氧监测 蓝牙通话 智能手表 男女表 | ++------+---------------------------------------------------------------------------------------------------------------+ +``` + +**示例:统计匹配用户查询的文档数量** + +```sql +SELECT COUNT(*) FROM stock_items + WHERE fts_match_word("bluetoothイヤホン", title); + ++----------+ +| COUNT(*) | ++----------+ +| 5 | ++----------+ +``` + +## 高级示例:连接搜索结果与其他表 + +您可以将全文搜索与其他 SQL 功能(如连接和子查询)结合使用。 + +假设您有一个 `users` 表和一个 `tickets` 表,想要根据作者姓名的全文搜索来查找他们创建的工单: + +```sql +CREATE TABLE users( + id INT, + name TEXT, + FULLTEXT INDEX (name) WITH PARSER STANDARD +); + +INSERT INTO users VALUES (1, "Alice Smith"); +INSERT INTO users VALUES (2, "Bob Johnson"); + +CREATE TABLE tickets( + id INT, + title TEXT, + author_id INT +); + +INSERT INTO tickets VALUES (1, "Ticket 1", 1); +INSERT INTO tickets VALUES (2, "Ticket 2", 1); +INSERT INTO tickets VALUES (3, "Ticket 3", 2); +``` + +您可以使用子查询根据作者姓名查找匹配的用户 ID,然后在外部查询中使用这些 ID 来检索和连接相关的工单信息: + +```sql +SELECT t.title AS TICKET_TITLE, u.id AS AUTHOR_ID, u.name AS AUTHOR_NAME FROM tickets t +LEFT JOIN users u ON t.author_id = u.id +WHERE t.author_id IN +( + SELECT id FROM users + WHERE fts_match_word("Alice", name) +); + ++--------------+-----------+-------------+ +| TICKET_TITLE | AUTHOR_ID | AUTHOR_NAME | ++--------------+-----------+-------------+ +| Ticket 1 | 1 | Alice Smith | +| Ticket 2 | 1 | Alice Smith | ++--------------+-----------+-------------+ +``` + +## 另请参阅 + +- [混合搜索](/tidb-cloud/vector-search-hybrid-search.md) + +## 反馈与帮助 + +全文搜索仍处于早期阶段,可用性有限。如果您想在尚未开放的地区尝试全文搜索,或者如果您有反馈或需要帮助,请随时联系我们: + + + +- [加入我们的 Discord](https://discord.gg/zcqexutz2R) + + + + + +- [加入我们的 Discord](https://discord.gg/zcqexutz2R) +- [访问我们的支持门户](https://tidb.support.pingcap.com/) + + diff --git a/tidb-cloud/vector-search-functions-and-operators.md b/tidb-cloud/vector-search-functions-and-operators.md new file mode 100644 index 000000000000..01c198717caf --- /dev/null +++ b/tidb-cloud/vector-search-functions-and-operators.md @@ -0,0 +1,284 @@ +--- +title: 向量函数和运算符 +summary: 了解向量数据类型可用的函数和运算符。 +--- + +# 向量函数和运算符 + +本文档列出了向量数据类型可用的函数和运算符。 + +> **注意** +> +> TiDB 向量搜索功能仅适用于 TiDB 自管理版本(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。该功能不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 向量函数 + +以下函数专门为[向量数据类型](/tidb-cloud/vector-search-data-types.md)设计。 + +**向量距离函数:** + +| 函数名 | 描述 | +| ----------------------------------------------------------- | ---------------------------------- | +| [`VEC_L2_DISTANCE`](#vec_l2_distance) | 计算两个向量之间的 L2 距离(欧几里得距离) | +| [`VEC_COSINE_DISTANCE`](#vec_cosine_distance) | 计算两个向量之间的余弦距离 | +| [`VEC_NEGATIVE_INNER_PRODUCT`](#vec_negative_inner_product) | 计算两个向量之间内积的负值 | +| [`VEC_L1_DISTANCE`](#vec_l1_distance) | 计算两个向量之间的 L1 距离(曼哈顿距离) | + +**其他向量函数:** + +| 函数名 | 描述 | +| --------------------------------- | ----------------------------- | +| [`VEC_DIMS`](#vec_dims) | 返回向量的维度 | +| [`VEC_L2_NORM`](#vec_l2_norm) | 计算向量的 L2 范数(欧几里得范数) | +| [`VEC_FROM_TEXT`](#vec_from_text) | 将字符串转换为向量 | +| [`VEC_AS_TEXT`](#vec_as_text) | 将向量转换为字符串 | + +## 扩展内置函数和运算符 + +以下内置函数和运算符已扩展以支持[向量数据类型](/tidb-cloud/vector-search-data-types.md)的操作。 + +**算术运算符:** + +| 名称 | 描述 | +| :-------------------------------------------------------------------------------------- | :-------------------- | +| [`+`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | 向量元素逐个相加运算符 | +| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | 向量元素逐个相减运算符 | + +有关向量算术运算的更多信息,请参见[向量数据类型 | 算术运算](/tidb-cloud/vector-search-data-types.md#arithmetic)。 + +**聚合(GROUP BY)函数:** + +| 名称 | 描述 | +| :------------------------------------------------------------------------------------------------------------ | :-------------------- | +| [`COUNT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count) | 返回返回行数的计数 | +| [`COUNT(DISTINCT)`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct) | 返回不同值的计数 | +| [`MAX()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max) | 返回最大值 | +| [`MIN()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min) | 返回最小值 | + +**比较函数和运算符:** + +| 名称 | 描述 | +| ------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| [`BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | 检查值是否在某个范围内 | +| [`COALESCE()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce) | 返回第一个非 NULL 参数 | +| [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | 等于运算符 | +| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | NULL 安全的等于运算符 | +| [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | 大于运算符 | +| [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | 大于等于运算符 | +| [`GREATEST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_greatest) | 返回最大参数 | +| [`IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in) | 检查值是否在一组值中 | +| [`IS NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | 测试值是否为 `NULL` | +| [`ISNULL()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull) | 测试参数是否为 `NULL` | +| [`LEAST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_least) | 返回最小参数 | +| [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | 小于运算符 | +| [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | 小于等于运算符 | +| [`NOT BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | 检查值是否不在某个范围内 | +| [`!=`, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | 不等于运算符 | +| [`NOT IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in) | 检查值是否不在一组值中 | + +有关向量比较的更多信息,请参见[向量数据类型 | 比较](/tidb-cloud/vector-search-data-types.md#comparison)。 + +**流程控制函数:** + +| 名称 | 描述 | +| :------------------------------------------------------------------------------------------------ | :-------------------------- | +| [`CASE`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) | Case 运算符 | +| [`IF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if) | If/else 结构 | +| [`IFNULL()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) | Null if/else 结构 | +| [`NULLIF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_nullif) | 如果 expr1 = expr2 则返回 NULL | + +**类型转换函数:** + +| 名称 | 描述 | +| :------------------------------------------------------------------------------------------ | :----------------------- | +| [`CAST()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast) | 将值转换为字符串或向量 | +| [`CONVERT()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_convert) | 将值转换为字符串 | + +有关如何使用 `CAST()` 的更多信息,请参见[向量数据类型 | 类型转换](/tidb-cloud/vector-search-data-types.md#cast)。 + +## 完整参考 + +### VEC_L2_DISTANCE + +```sql +VEC_L2_DISTANCE(vector1, vector2) +``` + +使用以下公式计算两个向量之间的 [L2 距离](https://en.wikipedia.org/wiki/Euclidean_distance)(欧几里得距离): + +$DISTANCE(p,q)=\sqrt {\sum \limits _{i=1}^{n}{(p_{i}-q_{i})^{2}}}$ + +两个向量必须具有相同的维度。否则,将返回错误。 + +示例: + +```sql +[tidb]> SELECT VEC_L2_DISTANCE('[0,3]', '[4,0]'); ++-----------------------------------+ +| VEC_L2_DISTANCE('[0,3]', '[4,0]') | ++-----------------------------------+ +| 5 | ++-----------------------------------+ +``` + +### VEC_COSINE_DISTANCE + +```sql +VEC_COSINE_DISTANCE(vector1, vector2) +``` + +使用以下公式计算两个向量之间的[余弦距离](https://en.wikipedia.org/wiki/Cosine_similarity): + +$DISTANCE(p,q)=1.0 - {\frac {\sum \limits _{i=1}^{n}{p_{i}q_{i}}}{{\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}}\cdot {\sqrt {\sum \limits _{i=1}^{n}{q_{i}^{2}}}}}}$ + +两个向量必须具有相同的维度。否则,将返回错误。 + +示例: + +```sql +[tidb]> SELECT VEC_COSINE_DISTANCE('[1, 1]', '[-1, -1]'); ++-------------------------------------------+ +| VEC_COSINE_DISTANCE('[1, 1]', '[-1, -1]') | ++-------------------------------------------+ +| 2 | ++-------------------------------------------+ +``` + +### VEC_NEGATIVE_INNER_PRODUCT + +```sql +VEC_NEGATIVE_INNER_PRODUCT(vector1, vector2) +``` + +使用以下公式计算两个向量之间[内积](https://en.wikipedia.org/wiki/Dot_product)的负值作为距离: + +$DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ + +两个向量必须具有相同的维度。否则,将返回错误。 + +示例: + +```sql +[tidb]> SELECT VEC_NEGATIVE_INNER_PRODUCT('[1,2]', '[3,4]'); ++----------------------------------------------+ +| VEC_NEGATIVE_INNER_PRODUCT('[1,2]', '[3,4]') | ++----------------------------------------------+ +| -11 | ++----------------------------------------------+ +``` + +### VEC_L1_DISTANCE + +```sql +VEC_L1_DISTANCE(vector1, vector2) +``` + +使用以下公式计算两个向量之间的 [L1 距离](https://en.wikipedia.org/wiki/Taxicab_geometry)(曼哈顿距离): + +$DISTANCE(p,q)=\sum \limits _{i=1}^{n}{|p_{i}-q_{i}|}$ + +两个向量必须具有相同的维度。否则,将返回错误。 + +示例: + +```sql +[tidb]> SELECT VEC_L1_DISTANCE('[0,0]', '[3,4]'); ++-----------------------------------+ +| VEC_L1_DISTANCE('[0,0]', '[3,4]') | ++-----------------------------------+ +| 7 | ++-----------------------------------+ +``` + +### VEC_DIMS + +```sql +VEC_DIMS(vector) +``` + +返回向量的维度。 + +示例: + +```sql +[tidb]> SELECT VEC_DIMS('[1,2,3]'); ++---------------------+ +| VEC_DIMS('[1,2,3]') | ++---------------------+ +| 3 | ++---------------------+ + +[tidb]> SELECT VEC_DIMS('[]'); ++----------------+ +| VEC_DIMS('[]') | ++----------------+ +| 0 | ++----------------+ +``` + +### VEC_L2_NORM + +```sql +VEC_L2_NORM(vector) +``` + +使用以下公式计算向量的 [L2 范数]()(欧几里得范数): + +$NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ + +示例: + +```sql +[tidb]> SELECT VEC_L2_NORM('[3,4]'); ++----------------------+ +| VEC_L2_NORM('[3,4]') | ++----------------------+ +| 5 | ++----------------------+ +``` + +### VEC_FROM_TEXT + +```sql +VEC_FROM_TEXT(string) +``` + +将字符串转换为向量。 + +示例: + +```sql +[tidb]> SELECT VEC_FROM_TEXT('[1,2]') + VEC_FROM_TEXT('[3,4]'); ++-------------------------------------------------+ +| VEC_FROM_TEXT('[1,2]') + VEC_FROM_TEXT('[3,4]') | ++-------------------------------------------------+ +| [4,6] | ++-------------------------------------------------+ +``` + +### VEC_AS_TEXT + +```sql +VEC_AS_TEXT(vector) +``` + +将向量转换为字符串。 + +示例: + +```sql +[tidb]> SELECT VEC_AS_TEXT('[1.000, 2.5]'); ++-------------------------------+ +| VEC_AS_TEXT('[1.000, 2.5]') | ++-------------------------------+ +| [1,2.5] | ++-------------------------------+ +``` + +## MySQL 兼容性 + +向量函数以及内置函数和运算符在向量数据类型上的扩展用法是 TiDB 特有的,MySQL 中不支持这些功能。 + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) diff --git a/tidb-cloud/vector-search-get-started-using-python.md b/tidb-cloud/vector-search-get-started-using-python.md new file mode 100644 index 000000000000..fa2b01fd7194 --- /dev/null +++ b/tidb-cloud/vector-search-get-started-using-python.md @@ -0,0 +1,195 @@ +--- +title: 通过 Python 开始使用 TiDB + AI +summary: 学习如何使用 Python 和 TiDB Vector Search 快速开发一个进行语义搜索的 AI 应用。 +--- + +# 通过 Python 开始使用 TiDB + AI + +本教程演示如何开发一个提供**语义搜索**功能的简单 AI 应用。与传统的关键词搜索不同,语义搜索能够智能地理解查询背后的含义并返回最相关的结果。例如,如果你有标题为"dog"(狗)、"fish"(鱼)和"tree"(树)的文档,当你搜索"a swimming animal"(一个会游泳的动物)时,应用会识别出"fish"(鱼)是最相关的结果。 + +在本教程中,你将使用 [TiDB Vector Search](/tidb-cloud/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和 AI 模型来开发这个 AI 应用。 + +> **注意** +> +> TiDB Vector Search 仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 前提条件 + +要完成本教程,你需要: + +- 安装 [Python 3.8 或更高版本](https://www.python.org/downloads/)。 +- 安装 [Git](https://git-scm.com/downloads)。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)的说明创建你自己的 TiDB Cloud 集群。 + +## 开始使用 + +以下步骤展示如何从头开始开发应用。如果想直接运行演示,你可以在 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 仓库中查看示例代码。 + +### 步骤 1. 创建新的 Python 项目 + +在你选择的目录中,创建一个新的 Python 项目和一个名为 `example.py` 的文件: + +```shell +mkdir python-client-quickstart +cd python-client-quickstart +touch example.py +``` + +### 步骤 2. 安装所需依赖 + +在你的项目目录中,运行以下命令安装所需的包: + +```shell +pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv +``` + +- `tidb-vector`:用于与 TiDB Vector Search 交互的 Python 客户端。 +- [`sentence-transformers`](https://sbert.net):一个提供预训练模型的 Python 库,用于从文本生成[向量嵌入](/tidb-cloud/vector-search-overview.md#vector-embedding)。 + +### 步骤 3. 配置到 TiDB 集群的连接字符串 + +1. 导航到 [**Clusters**](https://tidbcloud.com/project/clusters) 页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的 **Connect**。将显示一个连接对话框。 + +3. 确保连接对话框中的配置与你的操作环境匹配。 + + - **Connection Type** 设置为 `Public`。 + - **Branch** 设置为 `main`。 + - **Connect With** 设置为 `SQLAlchemy`。 + - **Operating System** 与你的环境匹配。 + + > **提示:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 点击 **PyMySQL** 标签并复制连接字符串。 + + > **提示:** + > + > 如果你还没有设置密码,请点击 **Generate Password** 生成一个随机密码。 + +5. 在你的 Python 项目的根目录中,创建一个 `.env` 文件并将连接字符串粘贴到其中。 + + 以下是 macOS 的示例: + + ```dotenv + TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + ``` + +### 步骤 4. 初始化嵌入模型 + +[嵌入模型](/tidb-cloud/vector-search-overview.md#embedding-model)将数据转换为[向量嵌入](/tidb-cloud/vector-search-overview.md#vector-embedding)。本示例使用预训练模型 [**msmarco-MiniLM-L12-cos-v5**](https://huggingface.co/sentence-transformers/msmarco-MiniLM-L12-cos-v5) 进行文本嵌入。这个由 `sentence-transformers` 库提供的轻量级模型可以将文本数据转换为 384 维的向量嵌入。 + +要设置模型,将以下代码复制到 `example.py` 文件中。这段代码初始化了一个 `SentenceTransformer` 实例,并定义了一个供后续使用的 `text_to_embedding()` 函数。 + +```python +from sentence_transformers import SentenceTransformer + +print("Downloading and loading the embedding model...") +embed_model = SentenceTransformer("sentence-transformers/msmarco-MiniLM-L12-cos-v5", trust_remote_code=True) +embed_model_dims = embed_model.get_sentence_embedding_dimension() + +def text_to_embedding(text): + """Generates vector embeddings for the given text.""" + embedding = embed_model.encode(text) + return embedding.tolist() +``` + +### 步骤 5. 连接到 TiDB 集群 + +使用 `TiDBVectorClient` 类连接到你的 TiDB 集群,并创建一个带有向量列的表 `embedded_documents`。 + +> **注意** +> +> 确保表中向量列的维度与嵌入模型生成的向量维度匹配。例如,**msmarco-MiniLM-L12-cos-v5** 模型生成 384 维的向量,所以 `embedded_documents` 中向量列的维度也应该是 384。 + +```python +import os +from tidb_vector.integrations import TiDBVectorClient +from dotenv import load_dotenv + +# 从 .env 文件加载连接字符串 +load_dotenv() + +vector_store = TiDBVectorClient( + # 'embedded_documents' 表将存储向量数据。 + table_name='embedded_documents', + # 到 TiDB 集群的连接字符串。 + connection_string=os.environ.get('TIDB_DATABASE_URL'), + # 嵌入模型生成的向量维度。 + vector_dimension=embed_model_dims, + # 如果表已存在则重新创建。 + drop_existing_table=True, +) +``` + +### 步骤 6. 嵌入文本数据并存储向量 + +在这一步中,你将准备包含单个词的示例文档,如"dog"(狗)、"fish"(鱼)和"tree"(树)。以下代码使用 `text_to_embedding()` 函数将这些文本文档转换为向量嵌入,然后将它们插入到向量存储中。 + +```python +documents = [ + { + "id": "f8e7dee2-63b6-42f1-8b60-2d46710c1971", + "text": "dog", + "embedding": text_to_embedding("dog"), + "metadata": {"category": "animal"}, + }, + { + "id": "8dde1fbc-2522-4ca2-aedf-5dcb2966d1c6", + "text": "fish", + "embedding": text_to_embedding("fish"), + "metadata": {"category": "animal"}, + }, + { + "id": "e4991349-d00b-485c-a481-f61695f2b5ae", + "text": "tree", + "embedding": text_to_embedding("tree"), + "metadata": {"category": "plant"}, + }, +] + +vector_store.insert( + ids=[doc["id"] for doc in documents], + texts=[doc["text"] for doc in documents], + embeddings=[doc["embedding"] for doc in documents], + metadatas=[doc["metadata"] for doc in documents], +) +``` + +### 步骤 7. 执行语义搜索 + +在这一步中,你将搜索"a swimming animal"(一个会游泳的动物),这个词组与现有文档中的任何词都不直接匹配。 + +以下代码再次使用 `text_to_embedding()` 函数将查询文本转换为向量嵌入,然后使用该嵌入查询找到最接近的三个匹配项。 + +```python +def print_result(query, result): + print(f"Search result (\"{query}\"):") + for r in result: + print(f"- text: \"{r.document}\", distance: {r.distance}") + +query = "a swimming animal" +query_embedding = text_to_embedding(query) +search_result = vector_store.query(query_embedding, k=3) +print_result(query, search_result) +``` + +运行 `example.py` 文件,输出如下: + +```plain +Search result ("a swimming animal"): +- text: "fish", distance: 0.4562914811223072 +- text: "dog", distance: 0.6469335836410557 +- text: "tree", distance: 0.798545178640937 +``` + +搜索结果中的三个词按照它们与查询向量的距离排序:距离越小,相应的 `document` 越相关。 + +因此,根据输出,这个会游泳的动物最可能是鱼,或者是一只有游泳天赋的狗。 + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-get-started-using-sql.md b/tidb-cloud/vector-search-get-started-using-sql.md new file mode 100644 index 000000000000..ac280ee00b80 --- /dev/null +++ b/tidb-cloud/vector-search-get-started-using-sql.md @@ -0,0 +1,150 @@ +--- +title: 通过 SQL 开始使用向量搜索 +summary: 了解如何使用 SQL 语句在 TiDB 中快速开始使用向量搜索来支持你的生成式 AI 应用。 +--- + +# 通过 SQL 开始使用向量搜索 + +TiDB 扩展了 MySQL 语法以支持[向量搜索](/tidb-cloud/vector-search-overview.md),并引入了新的[向量数据类型](/tidb-cloud/vector-search-data-types.md)和多个[向量函数](/tidb-cloud/vector-search-functions-and-operators.md)。 + +本教程演示如何仅使用 SQL 语句开始使用 TiDB 向量搜索。你将学习如何使用 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)完成以下操作: + +- 连接到你的 TiDB 集群 +- 创建向量表 +- 存储向量嵌入 +- 执行向量搜索查询 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB 自管理版本(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 前提条件 + +要完成本教程,你需要: + +- 在你的机器上安装 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)(MySQL CLI)。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)的说明创建你自己的 TiDB Cloud 集群。 + +## 开始使用 + +### 步骤 1. 连接到 TiDB 集群 + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示一个连接对话框。 + +3. 在连接对话框中,从**连接方式**下拉列表中选择 **MySQL CLI**,并保持**连接类型**的默认设置为**公共**。 + +4. 如果你还没有设置密码,点击**生成密码**以生成一个随机密码。 + +5. 复制连接命令并将其粘贴到你的终端中。以下是 macOS 的示例: + + ```bash + mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' + ``` + +### 步骤 2. 创建向量表 + +创建表时,你可以通过指定 `VECTOR` 数据类型将列定义为[向量](/tidb-cloud/vector-search-overview.md#vector-embedding)列。 + +例如,要创建一个具有三维 `VECTOR` 列的表 `embedded_documents`,请使用 MySQL CLI 执行以下 SQL 语句: + +```sql +USE test; +CREATE TABLE embedded_documents ( + id INT PRIMARY KEY, + -- 用于存储文档的原始内容的列。 + document TEXT, + -- 用于存储文档的向量表示的列。 + embedding VECTOR(3) +); +``` + +预期输出如下: + +```text +Query OK, 0 rows affected (0.27 sec) +``` + +### 步骤 3. 向表中插入向量嵌入 + +将三个文档及其[向量嵌入](/tidb-cloud/vector-search-overview.md#vector-embedding)插入到 `embedded_documents` 表中: + +```sql +INSERT INTO embedded_documents +VALUES + (1, 'dog', '[1,2,1]'), + (2, 'fish', '[1,2,4]'), + (3, 'tree', '[1,0,0]'); +``` + +预期输出如下: + +``` +Query OK, 3 rows affected (0.15 sec) +Records: 3 Duplicates: 0 Warnings: 0 +``` + +> **注意** +> +> 本示例简化了向量嵌入的维度,仅使用三维向量进行演示。 +> +> 在实际应用中,[嵌入模型](/tidb-cloud/vector-search-overview.md#embedding-model)通常会生成具有数百或数千维度的向量嵌入。 + +### 步骤 4. 查询向量表 + +要验证文档是否已正确插入,请查询 `embedded_documents` 表: + +```sql +SELECT * FROM embedded_documents; +``` + +预期输出如下: + +```sql ++----+----------+-----------+ +| id | document | embedding | ++----+----------+-----------+ +| 1 | dog | [1,2,1] | +| 2 | fish | [1,2,4] | +| 3 | tree | [1,0,0] | ++----+----------+-----------+ +3 rows in set (0.15 sec) +``` + +### 步骤 5. 执行向量搜索查询 + +与全文搜索类似,用户在使用向量搜索时向应用程序提供搜索词。 + +在本示例中,搜索词是"a swimming animal",其对应的向量嵌入假设为 `[1,2,3]`。在实际应用中,你需要使用嵌入模型将用户的搜索词转换为向量嵌入。 + +执行以下 SQL 语句,TiDB 将通过计算和排序表中向量嵌入与 `[1,2,3]` 之间的余弦距离(`vec_cosine_distance`),识别出最接近的三个文档。 + +```sql +SELECT id, document, vec_cosine_distance(embedding, '[1,2,3]') AS distance +FROM embedded_documents +ORDER BY distance +LIMIT 3; +``` + +预期输出如下: + +```plain ++----+----------+---------------------+ +| id | document | distance | ++----+----------+---------------------+ +| 2 | fish | 0.00853986601633272 | +| 1 | dog | 0.12712843905603044 | +| 3 | tree | 0.7327387580875756 | ++----+----------+---------------------+ +3 rows in set (0.15 sec) +``` + +搜索结果中的三个词按照它们与查询向量的距离排序:距离越小,相应的 `document` 越相关。 + +因此,根据输出,这个会游泳的动物最可能是鱼,或者是一只擅长游泳的狗。 + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-hybrid-search.md b/tidb-cloud/vector-search-hybrid-search.md new file mode 100644 index 000000000000..7c138e0818c8 --- /dev/null +++ b/tidb-cloud/vector-search-hybrid-search.md @@ -0,0 +1,166 @@ +--- +title: 混合搜索 +summary: 结合全文搜索和向量搜索来提升检索质量。 +--- + +# 混合搜索 + +通过使用全文搜索,您可以基于精确关键词检索文档。通过使用向量搜索,您可以基于语义相似度检索文档。我们能否结合这两种搜索方法来提升检索质量并处理更多场景?是的,这种方法被称为混合搜索,在 AI 应用中被广泛使用。 + +TiDB 中混合搜索的一般工作流程如下: + +1. 使用 TiDB 进行**全文搜索**和**向量搜索**。 +2. 使用**重排序器**来组合两种搜索的结果。 + +![混合搜索](/media/vector-search/hybrid-search-overview.svg) + +本教程演示如何使用 [pytidb](https://github.com/pingcap/pytidb) Python SDK 在 TiDB 中使用混合搜索,该 SDK 内置支持嵌入和重排序功能。使用 pytidb 完全是可选的 — 您可以直接使用 SQL 执行搜索,并根据需要使用自己的重排序模型。 + +## 前提条件 + +混合搜索依赖于[全文搜索](/tidb-cloud/vector-search-full-text-search-python.md)和向量搜索。全文搜索仍处于早期阶段,我们正在持续向更多客户推出。目前,全文搜索仅适用于以下产品选项和地区: + +- TiDB Cloud Serverless:`法兰克福 (eu-central-1)` 和 `新加坡 (ap-southeast-1)` + +要完成本教程,请确保您在支持的地区有一个 TiDB Cloud Serverless 集群。如果您还没有,请按照[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md)的说明创建一个。 + +## 开始使用 + +### 步骤 1. 安装 [pytidb](https://github.com/pingcap/pytidb) Python SDK + +```shell +pip install "pytidb[models]" + +# (替代方案) 如果您不想使用内置的嵌入函数和重排序器: +# pip install pytidb + +# (可选) 要将查询结果转换为 pandas DataFrame: +# pip install pandas +``` + +### 步骤 2. 连接到 TiDB + +```python +from pytidb import TiDBClient + +db = TiDBClient.connect( + host="HOST_HERE", + port=4000, + username="USERNAME_HERE", + password="PASSWORD_HERE", + database="DATABASE_HERE", +) +``` + +您可以从 [TiDB Cloud 控制台](https://tidbcloud.com)获取这些连接参数: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示一个连接对话框,其中列出了连接参数。 + + 例如,如果连接参数显示如下: + + ```text + HOST: gateway01.us-east-1.prod.shared.aws.tidbcloud.com + PORT: 4000 + USERNAME: 4EfqPF23YKBxaQb.root + PASSWORD: abcd1234 + DATABASE: test + CA: /etc/ssl/cert.pem + ``` + + 连接到 TiDB Cloud Serverless 集群的相应 Python 代码如下: + + ```python + db = TiDBClient.connect( + host="gateway01.us-east-1.prod.shared.aws.tidbcloud.com", + port=4000, + username="4EfqPF23YKBxaQb.root", + password="abcd1234", + database="test", + ) + ``` + + 请注意,上述示例仅用于演示目的。您需要使用自己的值填充参数并确保它们的安全性。 + +### 步骤 3. 创建表 + +作为示例,创建一个名为 `chunks` 的表,包含以下列: + +- `id` (int):块的 ID。 +- `text` (text):块的文本内容。 +- `text_vec` (vector):文本的向量表示,由 pytidb 中的嵌入模型自动生成。 +- `user_id` (int):创建该块的用户 ID。 + +```python +from pytidb.schema import TableModel, Field +from pytidb.embeddings import EmbeddingFunction + +text_embed = EmbeddingFunction("openai/text-embedding-3-small") + +class Chunk(TableModel, table=True): + __tablename__ = "chunks" + + id: int = Field(primary_key=True) + text: str = Field() + text_vec: list[float] = text_embed.VectorField( + source_field="text" + ) # 👈 定义向量字段。 + user_id: int = Field() + +table = db.create_table(schema=Chunk) +``` + +### 步骤 4. 插入数据 + +```python +table.bulk_insert( + [ + Chunk(id=2, text="bar", user_id=2), # 👈 文本字段将被自动嵌入为向量 + Chunk(id=3, text="baz", user_id=3), # 并存储在 "text_vec" 字段中。 + Chunk(id=4, text="qux", user_id=4), # + ] +) +``` + +### 步骤 5. 执行混合搜索 + +在此示例中,使用 [jina-reranker](https://huggingface.co/jinaai/jina-reranker-m0) 模型对搜索结果进行重排序。 + +```python +from pytidb.rerankers import Reranker + +jinaai = Reranker(model_name="jina_ai/jina-reranker-m0") + +df = ( + table.search("", search_type="hybrid") + .rerank(jinaai, "text") # 👈 使用 jinaai 模型对查询结果进行重排序。 + .limit(2) + .to_pandas() +) +``` + +完整示例请参见 [pytidb 混合搜索演示](https://github.com/pingcap/pytidb/tree/main/examples/hybrid_search)。 + +## 另请参阅 + +- [pytidb Python SDK 文档](https://github.com/pingcap/pytidb) + +- [使用 Python 进行全文搜索](/tidb-cloud/vector-search-full-text-search-python.md) + +## 反馈与帮助 + +全文搜索仍处于早期阶段,可访问性有限。如果您想在尚未提供服务的地区尝试全文搜索,或者如果您有反馈或需要帮助,请随时联系我们: + + + +- [加入我们的 Discord](https://discord.gg/zcqexutz2R) + + + + + +- [加入我们的 Discord](https://discord.gg/zcqexutz2R) +- [访问我们的支持门户](https://tidb.support.pingcap.com/) + + diff --git a/tidb-cloud/vector-search-improve-performance.md b/tidb-cloud/vector-search-improve-performance.md new file mode 100644 index 000000000000..40ac96a2e04c --- /dev/null +++ b/tidb-cloud/vector-search-improve-performance.md @@ -0,0 +1,36 @@ +--- +title: 提升向量搜索性能 +summary: 了解提升 TiDB 向量搜索性能的最佳实践。 +--- + +# 提升向量搜索性能 + +TiDB 向量搜索使你能够执行近似最近邻(ANN)查询,搜索与图像、文档或其他输入相似的结果。要提高查询性能,请参考以下最佳实践。 + +## 为向量列添加向量搜索索引 + +[向量搜索索引](/tidb-cloud/vector-search-index.md)能显著提高向量搜索查询的性能,通常能提升 10 倍或更多,只需要牺牲很小的召回率。 + +## 确保向量索引完全构建 + +在插入大量向量数据后,其中一部分可能在 Delta 层等待持久化。这些数据的向量索引将在数据持久化后构建。在所有向量数据都被索引之前,向量搜索性能是次优的。要检查索引构建进度,请参见[查看索引构建进度](/tidb-cloud/vector-search-index.md#view-index-build-progress)。 + +## 减少向量维度或缩短嵌入 + +随着向量维度的增加,向量搜索索引和查询的计算复杂度显著增加,需要更多的浮点数比较。 + +为了优化性能,请在可行的情况下考虑减少向量维度。这通常需要切换到另一个嵌入模型。切换模型时,你需要评估模型变更对向量查询准确性的影响。 + +某些嵌入模型(如 OpenAI `text-embedding-3-large`)支持[缩短嵌入](https://openai.com/index/new-embedding-models-and-api-updates/),即从向量序列末尾删除一些数字,而不会丢失嵌入的概念表示属性。你也可以使用这样的嵌入模型来减少向量维度。 + +## 从结果中排除向量列 + +向量嵌入数据通常很大,且仅在搜索过程中使用。通过从查询结果中排除向量列,你可以大大减少 TiDB 服务器和 SQL 客户端之间传输的数据量,从而提高查询性能。 + +要排除向量列,请在 `SELECT` 子句中明确列出你想要检索的列,而不是使用 `SELECT *` 检索所有列。 + +## 预热索引 + +当访问从未使用过或长时间未访问(冷访问)的索引时,TiDB 需要从云存储或磁盘(而不是从内存)加载整个索引。这个过程需要时间,通常会导致更高的查询延迟。此外,如果长时间(例如几个小时)没有 SQL 查询,计算资源会被回收,导致后续访问变成冷访问。 + +为了避免这种查询延迟,请在实际工作负载之前通过运行命中向量索引的类似向量搜索查询来预热索引。 diff --git a/tidb-cloud/vector-search-index.md b/tidb-cloud/vector-search-index.md new file mode 100644 index 000000000000..93544ea6e066 --- /dev/null +++ b/tidb-cloud/vector-search-index.md @@ -0,0 +1,245 @@ +--- +title: 向量搜索索引 +summary: 了解如何构建和使用向量搜索索引来加速 TiDB 中的 K-最近邻(KNN)查询。 +--- + +# 向量搜索索引 + +如[向量搜索](/tidb-cloud/vector-search-overview.md)文档所述,向量搜索通过计算给定向量与数据库中存储的所有向量之间的距离来识别给定向量的 K-最近邻(KNN)。虽然这种方法可以提供准确的结果,但当表包含大量向量时,由于需要进行全表扫描,速度可能会很慢。[^1] + +为了提高搜索效率,你可以在 TiDB 中创建向量搜索索引以进行近似 KNN(ANN)搜索。使用向量索引进行向量搜索时,TiDB 可以大大提高查询性能,同时只会略微降低准确性,通常可以保持超过 90% 的搜索召回率。 + +目前,TiDB 支持 [HNSW(分层可导航小世界)](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world)向量搜索索引算法。 + +## 创建 HNSW 向量索引 + +[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是最流行的向量索引算法之一。HNSW 索引提供了良好的性能和相对较高的准确性,在特定情况下可达到 98%。 + +在 TiDB 中,你可以通过以下任一方式为具有[向量数据类型](/tidb-cloud/vector-search-data-types.md)的列创建 HNSW 索引: + +- 创建表时,使用以下语法为向量列指定 HNSW 索引: + + ```sql + CREATE TABLE foo ( + id INT PRIMARY KEY, + embedding VECTOR(5), + VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))) + ); + ``` + +- 对于已包含向量列的现有表,使用以下语法为向量列创建 HNSW 索引: + + ```sql + CREATE VECTOR INDEX idx_embedding ON foo ((VEC_COSINE_DISTANCE(embedding))); + ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))); + + -- 你也可以显式指定 "USING HNSW" 来构建向量搜索索引。 + CREATE VECTOR INDEX idx_embedding ON foo ((VEC_COSINE_DISTANCE(embedding))) USING HNSW; + ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))) USING HNSW; + ``` + +> **注意:** +> +> 向量搜索索引功能依赖于表的 TiFlash 副本。 +> +> - 如果在创建表时定义了向量搜索索引,TiDB 会自动为该表创建 TiFlash 副本。 +> - 如果在创建表时未定义向量搜索索引,且该表当前没有 TiFlash 副本,则需要在为表添加向量搜索索引之前手动创建 TiFlash 副本。例如:`ALTER TABLE 'table_name' SET TIFLASH REPLICA 1;`。 + +创建 HNSW 向量索引时,你需要指定向量的距离函数: + +- 余弦距离:`((VEC_COSINE_DISTANCE(embedding)))` +- L2 距离:`((VEC_L2_DISTANCE(embedding)))` + +向量索引只能为固定维度的向量列创建,例如定义为 `VECTOR(3)` 的列。它不能为非固定维度的向量列创建(例如定义为 `VECTOR` 的列),因为向量距离只能在具有相同维度的向量之间计算。 + +有关其他限制,请参见[向量索引限制](/tidb-cloud/vector-search-limitations.md#向量索引限制)。 + +## 使用向量索引 + +向量搜索索引可以在 K-最近邻搜索查询中使用,方法是使用 `ORDER BY ... LIMIT` 子句,如下所示: + +```sql +SELECT * +FROM foo +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3, 4, 5]') +LIMIT 10 +``` + +要在向量搜索中使用索引,请确保 `ORDER BY ... LIMIT` 子句使用的距离函数与创建向量索引时指定的距离函数相同。 + +## 使用带过滤条件的向量索引 + +包含预过滤条件(使用 `WHERE` 子句)的查询无法利用向量索引,因为根据 SQL 语义,它们不是在查询 K-最近邻。例如: + +```sql +-- 对于以下查询,`WHERE` 过滤在 KNN 之前执行,所以无法使用向量索引: + +SELECT * FROM vec_table +WHERE category = "document" +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') +LIMIT 5; +``` + +要使用带过滤条件的向量索引,请先使用向量搜索查询 K-最近邻,然后过滤掉不需要的结果: + +```sql +-- 对于以下查询,`WHERE` 过滤在 KNN 之后执行,所以可以使用向量索引: + +SELECT * FROM +( + SELECT * FROM vec_table + ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') + LIMIT 5 +) t +WHERE category = "document"; + +-- 注意,如果某些结果被过滤掉,此查询可能返回少于 5 个结果。 +``` + +## 查看索引构建进度 + +在插入大量数据后,其中一些数据可能不会立即持久化到 TiFlash。对于已经持久化的向量数据,向量搜索索引会同步构建。对于尚未持久化的数据,索引将在数据持久化后构建。此过程不会影响数据的准确性和一致性。你仍然可以随时执行向量搜索并获得完整的结果。但是,在向量索引完全构建之前,性能将不会达到最佳。 + +要查看索引构建进度,你可以查询 `INFORMATION_SCHEMA.TIFLASH_INDEXES` 表,如下所示: + +```sql +SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; ++---------------+------------+----------+-------------+---------------+-----------+----------+------------+---------------------+-------------------------+--------------------+------------------------+---------------+------------------+ +| TIDB_DATABASE | TIDB_TABLE | TABLE_ID | COLUMN_NAME | INDEX_NAME | COLUMN_ID | INDEX_ID | INDEX_KIND | ROWS_STABLE_INDEXED | ROWS_STABLE_NOT_INDEXED | ROWS_DELTA_INDEXED | ROWS_DELTA_NOT_INDEXED | ERROR_MESSAGE | TIFLASH_INSTANCE | ++---------------+------------+----------+-------------+---------------+-----------+----------+------------+---------------------+-------------------------+--------------------+------------------------+---------------+------------------+ +| test | tcff1d827 | 219 | col1fff | 0a452311 | 7 | 1 | HNSW | 29646 | 0 | 0 | 0 | | 127.0.0.1:3930 | +| test | foo | 717 | embedding | idx_embedding | 2 | 1 | HNSW | 0 | 0 | 0 | 3 | | 127.0.0.1:3930 | ++---------------+------------+----------+-------------+---------------+-----------+----------+------------+---------------------+-------------------------+--------------------+------------------------+---------------+------------------+ +``` + +- 你可以查看 `ROWS_STABLE_INDEXED` 和 `ROWS_STABLE_NOT_INDEXED` 列来了解索引构建进度。当 `ROWS_STABLE_NOT_INDEXED` 变为 0 时,索引构建完成。 + + 作为参考,为一个 500 MiB、768 维的向量数据集建立索引可能需要长达 20 分钟。索引器可以为多个表并行运行。目前不支持调整索引器的优先级或速度。 + +- 你可以查看 `ROWS_DELTA_NOT_INDEXED` 列来了解 Delta 层中的行数。TiFlash 存储层中的数据存储在两个层中:Delta 层和 Stable 层。Delta 层存储最近插入或更新的行,并根据写入工作负载定期合并到 Stable 层中。这个合并过程称为 Compaction。 + + Delta 层始终不会被索引。为了获得最佳性能,你可以强制将 Delta 层合并到 Stable 层,以便所有数据都可以被索引: + + ```sql + ALTER TABLE COMPACT; + ``` + + 更多信息,请参见 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md)。 + +此外,你可以通过执行 `ADMIN SHOW DDL JOBS;` 并检查 `row count` 来监控 DDL 作业的执行进度。但是,这种方法并不完全准确,因为 `row count` 值是从 `TIFLASH_INDEXES` 中的 `rows_stable_indexed` 字段获取的。你可以将此方法作为跟踪索引进度的参考。 + +## 检查是否使用了向量索引 + +使用 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 或 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句来检查查询是否使用了向量索引。当 `TableFullScan` 执行器的 `operator info` 列中出现 `annIndex:` 时,表示此表扫描正在使用向量索引。 + +**示例:使用了向量索引** + +```sql +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') +LIMIT 10; ++-----+-------------------------------------------------------------------------------------+ +| ... | operator info | ++-----+-------------------------------------------------------------------------------------+ +| ... | ... | +| ... | Column#5, offset:0, count:10 | +| ... | ..., vec_cosine_distance(test.vector_table_with_index.embedding, [1,2,3])->Column#5 | +| ... | MppVersion: 1, data:ExchangeSender_16 | +| ... | ExchangeType: PassThrough | +| ... | ... | +| ... | Column#4, offset:0, count:10 | +| ... | ..., vec_cosine_distance(test.vector_table_with_index.embedding, [1,2,3])->Column#4 | +| ... | annIndex:COSINE(test.vector_table_with_index.embedding..[1,2,3], limit:10), ... | ++-----+-------------------------------------------------------------------------------------+ +9 rows in set (0.01 sec) +``` + +**示例:由于未指定 Top K,未使用向量索引** + +```sql +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index + -> ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]'); ++--------------------------------+-----+--------------------------------------------------+ +| id | ... | operator info | ++--------------------------------+-----+--------------------------------------------------+ +| Projection_15 | ... | ... | +| └─Sort_4 | ... | Column#4 | +| └─Projection_16 | ... | ..., vec_cosine_distance(..., [1,2,3])->Column#4 | +| └─TableReader_14 | ... | MppVersion: 1, data:ExchangeSender_13 | +| └─ExchangeSender_13 | ... | ExchangeType: PassThrough | +| └─TableFullScan_12 | ... | keep order:false, stats:pseudo | ++--------------------------------+-----+--------------------------------------------------+ +6 rows in set, 1 warning (0.01 sec) +``` + +当无法使用向量索引时,在某些情况下会出现警告以帮助你了解原因: + +```sql +-- 使用了错误的距离函数: +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index +ORDER BY VEC_L2_DISTANCE(embedding, '[1, 2, 3]') +LIMIT 10; + +[tidb]> SHOW WARNINGS; +ANN index not used: not ordering by COSINE distance + +-- 使用了错误的排序顺序: +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') DESC +LIMIT 10; + +[tidb]> SHOW WARNINGS; +ANN index not used: index can be used only when ordering by vec_cosine_distance() in ASC order +``` + +## 分析向量搜索性能 + +要了解向量索引使用的详细信息,你可以执行 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句并检查输出中的 `execution info` 列: + +```sql +[tidb]> EXPLAIN ANALYZE SELECT * FROM vector_table_with_index +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') +LIMIT 10; ++-----+--------------------------------------------------------+-----+ +| | execution info | | ++-----+--------------------------------------------------------+-----+ +| ... | time:339.1ms, loops:2, RU:0.000000, Concurrency:OFF | ... | +| ... | time:339ms, loops:2 | ... | +| ... | time:339ms, loops:3, Concurrency:OFF | ... | +| ... | time:339ms, loops:3, cop_task: {...} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{...}, vector_idx:{ | ... | +| | load:{total:68ms,from_s3:1,from_disk:0,from_cache:0},| | +| | search:{total:0ms,visited_nodes:2,discarded_nodes:0},| | +| | read:{vec_total:0ms,others_total:0ms}},...} | | ++-----+--------------------------------------------------------+-----+ +``` + +> **注意:** +> +> 执行信息是内部信息。字段和格式可能会在没有任何通知的情况下发生更改。请不要依赖它们。 + +一些重要字段的解释: + +- `vector_index.load.total`:加载索引的总持续时间。此字段可能大于实际查询时间,因为多个向量索引可能会并行加载。 +- `vector_index.load.from_s3`:从 S3 加载的索引数量。 +- `vector_index.load.from_disk`:从磁盘加载的索引数量。索引之前已从 S3 下载。 +- `vector_index.load.from_cache`:从缓存加载的索引数量。索引之前已从 S3 下载。 +- `vector_index.search.total`:在索引中搜索的总持续时间。较大的延迟通常意味着索引是冷的(以前从未访问过,或者很久以前访问过),因此在搜索索引时会有大量 I/O 操作。此字段可能大于实际查询时间,因为多个向量索引可能会并行搜索。 +- `vector_index.search.discarded_nodes`:搜索过程中访问但被丢弃的向量行数。这些被丢弃的向量不会被考虑在搜索结果中。较大的值通常表示由于 `UPDATE` 或 `DELETE` 语句导致存在许多过时的行。 + +有关解释输出的信息,请参见 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 和 [EXPLAIN 详解](/explain-walkthrough.md)。 + +## 限制 + +请参见[向量索引限制](/tidb-cloud/vector-search-limitations.md#向量索引限制)。 + +## 另请参阅 + +- [提高向量搜索性能](/tidb-cloud/vector-search-improve-performance.md) +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) + +[^1]: KNN 搜索的解释改编自 ClickHouse 文档中由 [rschu1ze](https://github.com/rschu1ze) 撰写的 [Approximate Nearest Neighbor Search Indexes](https://github.com/ClickHouse/ClickHouse/pull/50661/files#diff-7ebd9e71df96e74230c9a7e604fa7cb443be69ba5e23bf733fcecd4cc51b7576) 文档,根据 Apache License 2.0 许可。 diff --git a/tidb-cloud/vector-search-integrate-with-amazon-bedrock.md b/tidb-cloud/vector-search-integrate-with-amazon-bedrock.md new file mode 100644 index 000000000000..11a804ac4c7c --- /dev/null +++ b/tidb-cloud/vector-search-integrate-with-amazon-bedrock.md @@ -0,0 +1,313 @@ +--- +title: 将 TiDB 向量搜索与 Amazon Bedrock 集成 +summary: 了解如何将 TiDB 向量搜索与 Amazon Bedrock 集成以构建检索增强生成(RAG)问答机器人。 +--- + +# 将 TiDB 向量搜索与 Amazon Bedrock 集成 + +本教程演示如何将 TiDB 的[向量搜索](/tidb-cloud/vector-search-overview.md)功能与 [Amazon Bedrock](https://aws.amazon.com/bedrock/) 集成,以构建检索增强生成(RAG)问答机器人。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +> **提示** +> +> 你可以在 Notebook 格式中查看完整的[示例代码](https://github.com/aws-samples/aws-generativeai-partner-samples/blob/main/tidb/samples/tidb-bedrock-boto3-rag.ipynb)。 + +## 前提条件 + +要完成本教程,你需要: + +- 安装 [Python 3.11 或更高版本](https://www.python.org/downloads/) +- 安装 [Pip](https://pypi.org/project/pip/) +- 安装 [AWS CLI](https://aws.amazon.com/cli/) + + 确保你的 AWS CLI 配置文件配置为本教程支持的 [Amazon Bedrock](https://aws.amazon.com/bedrock/) 区域。你可以在 [Amazon Bedrock 区域](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html)找到支持的区域列表。要切换到支持的区域,请运行以下命令: + + ```shell + aws configure set region + ``` + +- 一个 TiDB Cloud Serverless 集群 + + 如果你没有集群,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)的说明创建自己的 TiDB Cloud 集群。 + +- 具有 [Amazon Bedrock 所需权限](https://docs.aws.amazon.com/bedrock/latest/userguide/security_iam_id-based-policy-examples.html)并可访问以下模型的 AWS 账户: + + - **Amazon Titan Embeddings**(`amazon.titan-embed-text-v2:0`),用于生成文本嵌入 + - **Meta Llama 3**(`us.meta.llama3-2-3b-instruct-v1:0`),用于文本生成 + + 如果你没有访问权限,请按照[请求访问 Amazon Bedrock 基础模型](https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html#getting-started-model-access)中的说明操作。 + +## 开始使用 + +本节提供将 TiDB 向量搜索与 Amazon Bedrock 集成以构建基于 RAG 的问答机器人的分步说明。 + +### 步骤 1. 设置环境变量 + +从 [TiDB Cloud 控制台](https://tidbcloud.com/)获取 TiDB 连接信息,并在开发环境中设置环境变量,如下所示: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示连接对话框。 + +3. 确保连接对话框中的配置与你的操作环境匹配。 + + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `General` + - **操作系统**与你的环境匹配。 + + > **提示:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 点击**生成密码**创建随机密码。 + + > **提示:** + > + > 如果你之前已经创建了密码,可以使用原始密码或点击**重置密码**生成新密码。 + +5. 在终端中运行以下命令来设置环境变量。你需要将命令中的占位符替换为从连接对话框获得的相应连接参数。 + + ```shell + export TIDB_HOST= + export TIDB_PORT=4000 + export TIDB_USER= + export TIDB_PASSWORD= + export TIDB_DB_NAME=test + ``` + +### 步骤 2. 设置 Python 虚拟环境 + +1. 创建一个名为 `demo.py` 的 Python 文件: + + ```shell + touch demo.py + ``` + +2. 创建并激活虚拟环境以管理依赖项: + + ```shell + python3 -m venv env + source env/bin/activate # 在 Windows 上,使用 env\Scripts\activate + ``` + +3. 安装所需的依赖项: + + ```shell + pip install SQLAlchemy==2.0.30 PyMySQL==1.1.0 tidb-vector==0.0.9 pydantic==2.7.1 boto3 + ``` + +### 步骤 3. 导入所需库 + +在 `demo.py` 的开头添加以下代码以导入所需的库: + +```python +import os +import json +import boto3 +from sqlalchemy import Column, Integer, Text, create_engine +from sqlalchemy.orm import declarative_base, Session +from tidb_vector.sqlalchemy import VectorType +``` + +### 步骤 4. 配置数据库连接 + +在 `demo.py` 中,添加以下代码以配置数据库连接: + +```python +# ---- 配置设置 ---- +# 设置环境变量:TIDB_HOST, TIDB_PORT, TIDB_USER, TIDB_PASSWORD, TIDB_DB_NAME +TIDB_HOST = os.environ.get("TIDB_HOST") +TIDB_PORT = os.environ.get("TIDB_PORT") +TIDB_USER = os.environ.get("TIDB_USER") +TIDB_PASSWORD = os.environ.get("TIDB_PASSWORD") +TIDB_DB_NAME = os.environ.get("TIDB_DB_NAME") + +# ---- 数据库设置 ---- +def get_db_url(): + """构建数据库连接 URL。""" + return f"mysql+pymysql://{TIDB_USER}:{TIDB_PASSWORD}@{TIDB_HOST}:{TIDB_PORT}/{TIDB_DB_NAME}?ssl_verify_cert=True&ssl_verify_identity=True" + +# 创建引擎 +engine = create_engine(get_db_url(), pool_recycle=300) +Base = declarative_base() +``` + +### 步骤 5. 使用 Bedrock 运行时客户端调用 Amazon Titan Text Embeddings V2 模型 + +Amazon Bedrock 运行时客户端提供了一个 `invoke_model` API,它接受以下参数: + +- `modelId`:Amazon Bedrock 中可用的基础模型的模型 ID。 +- `accept`:输入请求的类型。 +- `contentType`:输入的内容类型。 +- `body`:由提示和配置组成的 JSON 字符串负载。 + +在 `demo.py` 中,添加以下代码以调用 `invoke_model` API,使用 Amazon Titan Text Embeddings 生成文本嵌入并从 Meta Llama 3 获取响应: + +```python +# Bedrock 运行时客户端设置 +bedrock_runtime = boto3.client('bedrock-runtime') + +# ---- 模型调用 ---- +embedding_model_name = "amazon.titan-embed-text-v2:0" +dim_of_embedding_model = 512 +llm_name = "us.meta.llama3-2-3b-instruct-v1:0" + + +def embedding(content): + """调用 Amazon Bedrock 获取文本嵌入。""" + payload = { + "modelId": embedding_model_name, + "contentType": "application/json", + "accept": "*/*", + "body": { + "inputText": content, + "dimensions": dim_of_embedding_model, + "normalize": True, + } + } + + body_bytes = json.dumps(payload['body']).encode('utf-8') + + response = bedrock_runtime.invoke_model( + body=body_bytes, + contentType=payload['contentType'], + accept=payload['accept'], + modelId=payload['modelId'] + ) + + result_body = json.loads(response.get("body").read()) + return result_body.get("embedding") + + +def generate_result(query: str, info_str: str): + """使用 Meta Llama 3 模型生成答案。""" + prompt = f""" + 仅使用以下内容生成答案: + {info_str} + + ---- + 请仔细思考这个问题:{query} + """ + + payload = { + "modelId": llm_name, + "contentType": "application/json", + "accept": "application/json", + "body": { + "prompt": prompt, + "temperature": 0 + } + } + + body_bytes = json.dumps(payload['body']).encode('utf-8') + + response = bedrock_runtime.invoke_model( + body=body_bytes, + contentType=payload['contentType'], + accept=payload['accept'], + modelId=payload['modelId'] + ) + + result_body = json.loads(response.get("body").read()) + completion = result_body["generation"] + return completion +``` + +### 步骤 6. 创建向量表 + +在 `demo.py` 中,添加以下代码以创建一个用于存储文本和向量嵌入的向量表: + +```python +# ---- TiDB 设置和向量索引创建 ---- +class Entity(Base): + """定义带有向量索引的 Entity 表。""" + __tablename__ = "entity" + id = Column(Integer, primary_key=True) + content = Column(Text) + content_vec = Column(VectorType(dim=dim_of_embedding_model), comment="hnsw(distance=l2)") + +# 在 TiDB 中创建表 +Base.metadata.create_all(engine) +``` + +### 步骤 7. 将向量数据保存到 TiDB Cloud Serverless + +在 `demo.py` 中,添加以下代码以将向量数据保存到你的 TiDB Cloud Serverless 集群: + +```python +# ---- 将向量保存到 TiDB ---- +def save_entities_with_embedding(session, contents): + """将多个实体及其嵌入保存到 TiDB Serverless 数据库。""" + for content in contents: + entity = Entity(content=content, content_vec=embedding(content)) + session.add(entity) + session.commit() +``` + +### 步骤 8. 运行应用程序 + +1. 在 `demo.py` 中,添加以下代码以建立数据库会话,将嵌入保存到 TiDB,提出示例问题(如"什么是 TiDB?"),并从模型生成结果: + + ```python + if __name__ == "__main__": + # 建立数据库会话 + with Session(engine) as session: + # 示例数据 + contents = [ + "TiDB 是一个与 MySQL 兼容的分布式 SQL 数据库。", + "TiDB 支持混合事务和分析处理(HTAP)。", + "TiDB 可以水平扩展并提供高可用性。", + "Amazon Bedrock 允许与基础模型无缝集成。", + "Meta Llama 3 是一个强大的文本生成模型。" + ] + + # 将嵌入保存到 TiDB + save_entities_with_embedding(session, contents) + + # 示例查询 + query = "什么是 TiDB?" + info_str = " ".join(contents) + + # 从 Meta Llama 3 生成结果 + result = generate_result(query, info_str) + print(f"生成的答案:{result}") + ``` + +2. 保存对 `demo.py` 的所有更改并运行脚本: + + ```shell + python3 demo.py + ``` + + 预期输出类似于以下内容: + + ``` + 生成的答案: 什么是 TiDB 的主要目的? + TiDB 的主要特性是什么? + TiDB 的主要优势是什么? + + ---- + 根据提供的文本,以下是对问题的回答: + 什么是 TiDB? + TiDB 是一个与 MySQL 兼容的分布式 SQL 数据库。 + + ## 步骤 1:理解问题 + 问题询问 TiDB 的定义。 + + ## 步骤 2:识别关键信息 + 文本中提供的关键信息是 TiDB 是一个与 MySQL 兼容的分布式 SQL 数据库。 + + ## 步骤 3:提供答案 + 根据提供的文本,TiDB 是一个与 MySQL 兼容的分布式 SQL 数据库。 + + 最终答案是:TiDB 是一个与 MySQL 兼容的分布式 SQL 数据库。 + ``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-integrate-with-django-orm.md b/tidb-cloud/vector-search-integrate-with-django-orm.md new file mode 100644 index 000000000000..8c83fa116135 --- /dev/null +++ b/tidb-cloud/vector-search-integrate-with-django-orm.md @@ -0,0 +1,221 @@ +--- +title: 将 TiDB Vector Search 与 Django ORM 集成 +summary: 了解如何将 TiDB Vector Search 与 Django ORM 集成以存储嵌入向量并执行语义搜索。 +--- + +# 将 TiDB Vector Search 与 Django ORM 集成 + +本教程将指导您如何使用 [Django](https://www.djangoproject.com/) ORM 与 [TiDB Vector Search](/tidb-cloud/vector-search-overview.md) 交互,存储嵌入向量并执行向量搜索查询。 + +> **注意** +> +> TiDB Vector Search 仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 前提条件 + +完成本教程需要: + +- 安装 [Python 3.8 或更高版本](https://www.python.org/downloads/)。 +- 安装 [Git](https://git-scm.com/downloads)。 +- 一个 TiDB Cloud Serverless 集群。如果您还没有,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)的说明创建您自己的 TiDB Cloud 集群。 + +## 运行示例应用 + +您可以通过以下步骤快速了解如何将 TiDB Vector Search 与 Django ORM 集成。 + +### 步骤 1. 克隆代码仓库 + +将 `tidb-vector-python` 代码仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 步骤 2. 创建虚拟环境 + +为您的项目创建虚拟环境: + +```bash +cd tidb-vector-python/examples/orm-django-quickstart +python3 -m venv .venv +source .venv/bin/activate +``` + +### 步骤 3. 安装所需依赖 + +安装示例项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +或者,您可以为您的项目安装以下包: + +```bash +pip install Django django-tidb mysqlclient numpy python-dotenv +``` + +如果在安装 mysqlclient 时遇到问题,请参考 mysqlclient 官方文档。 + +#### 什么是 `django-tidb` + +`django-tidb` 是 Django 的 TiDB 方言,它增强了 Django ORM 以支持 TiDB 特定功能(例如 TiDB Vector Search)并解决了 TiDB 和 Django 之间的兼容性问题。 + +安装 `django-tidb` 时,请选择与您的 Django 版本匹配的版本。例如,如果您使用的是 `django==4.2.*`,请安装 `django-tidb==4.2.*`。次要版本不需要相同。建议使用最新的次要版本。 + +更多信息,请参考 [django-tidb 代码仓库](https://github.com/pingcap/django-tidb)。 + +### 步骤 4. 配置环境变量 + +1. 导航到 [**Clusters**](https://tidbcloud.com/project/clusters) 页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的 **Connect**。将显示连接对话框。 + +3. 确保连接对话框中的配置与您的操作环境匹配。 + + - **Connection Type** 设置为 `Public` + - **Branch** 设置为 `main` + - **Connect With** 设置为 `General` + - **Operating System** 与您的环境匹配。 + + > **提示:** + > + > 如果您的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 从连接对话框复制连接参数。 + + > **提示:** + > + > 如果您还没有设置密码,请点击 **Generate Password** 生成随机密码。 + +5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 + + - `TIDB_HOST`:TiDB 集群的主机地址。 + - `TIDB_PORT`:TiDB 集群的端口。 + - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 + - `TIDB_PASSWORD`:连接 TiDB 集群的密码。 + - `TIDB_DATABASE`:要连接的数据库名称。 + - `TIDB_CA_PATH`:根证书文件的路径。 + + 以下是 macOS 的示例: + + ```dotenv + TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com + TIDB_PORT=4000 + TIDB_USERNAME=********.root + TIDB_PASSWORD=******** + TIDB_DATABASE=test + TIDB_CA_PATH=/etc/ssl/cert.pem + ``` + +### 步骤 5. 运行示例 + +迁移数据库架构: + +```bash +python manage.py migrate +``` + +运行 Django 开发服务器: + +```bash +python manage.py runserver +``` + +在浏览器中访问 `http://127.0.0.1:8000` 试用示例应用。以下是可用的 API 路径: + +| API 路径 | 描述 | +| --------------------------------------- | ------------------------------ | +| `POST: /insert_documents` | 插入带有嵌入向量的文档。 | +| `GET: /get_nearest_neighbors_documents` | 获取 3 个最近邻文档。 | +| `GET: /get_documents_within_distance` | 获取指定距离范围内的文档。 | + +## 示例代码片段 + +您可以参考以下示例代码片段来完成您自己的应用程序开发。 + +### 连接到 TiDB 集群 + +在文件 `sample_project/settings.py` 中,添加以下配置: + +```python +dotenv.load_dotenv() + +DATABASES = { + "default": { + # https://github.com/pingcap/django-tidb + "ENGINE": "django_tidb", + "HOST": os.environ.get("TIDB_HOST", "127.0.0.1"), + "PORT": int(os.environ.get("TIDB_PORT", 4000)), + "USER": os.environ.get("TIDB_USERNAME", "root"), + "PASSWORD": os.environ.get("TIDB_PASSWORD", ""), + "NAME": os.environ.get("TIDB_DATABASE", "test"), + "OPTIONS": { + "charset": "utf8mb4", + }, + } +} + +TIDB_CA_PATH = os.environ.get("TIDB_CA_PATH", "") +if TIDB_CA_PATH: + DATABASES["default"]["OPTIONS"]["ssl_mode"] = "VERIFY_IDENTITY" + DATABASES["default"]["OPTIONS"]["ssl"] = { + "ca": TIDB_CA_PATH, + } +``` + +您可以在项目根目录下创建一个 `.env` 文件,并使用 TiDB 集群的实际值设置环境变量 `TIDB_HOST`、`TIDB_PORT`、`TIDB_USERNAME`、`TIDB_PASSWORD`、`TIDB_DATABASE` 和 `TIDB_CA_PATH`。 + +### 创建向量表 + +#### 定义向量列 + +`tidb-django` 提供了一个 `VectorField` 用于在表中存储向量嵌入。 + +创建一个包含名为 `embedding` 的列的表,用于存储 3 维向量。 + +```python +class Document(models.Model): + content = models.TextField() + embedding = VectorField(dimensions=3) +``` + +### 存储带有嵌入向量的文档 + +```python +Document.objects.create(content="dog", embedding=[1, 2, 1]) +Document.objects.create(content="fish", embedding=[1, 2, 4]) +Document.objects.create(content="tree", embedding=[1, 0, 0]) +``` + +### 搜索最近邻文档 + +TiDB Vector 支持以下距离函数: + +- `L1Distance` +- `L2Distance` +- `CosineDistance` +- `NegativeInnerProduct` + +基于余弦距离函数搜索与查询向量 `[1, 2, 3]` 语义最接近的前 3 个文档。 + +```python +results = Document.objects.annotate( + distance=CosineDistance('embedding', [1, 2, 3]) +).order_by('distance')[:3] +``` + +### 搜索指定距离范围内的文档 + +搜索与查询向量 `[1, 2, 3]` 的余弦距离小于 0.2 的文档。 + +```python +results = Document.objects.annotate( + distance=CosineDistance('embedding', [1, 2, 3]) +).filter(distance__lt=0.2).order_by('distance')[:3] +``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-integrate-with-jinaai-embedding.md b/tidb-cloud/vector-search-integrate-with-jinaai-embedding.md new file mode 100644 index 000000000000..b5894c9b2739 --- /dev/null +++ b/tidb-cloud/vector-search-integrate-with-jinaai-embedding.md @@ -0,0 +1,240 @@ +--- +title: 将 TiDB 向量搜索与 Jina AI Embeddings API 集成 +summary: 了解如何将 TiDB 向量搜索与 Jina AI Embeddings API 集成以存储嵌入向量并执行语义搜索。 +--- + +# 将 TiDB 向量搜索与 Jina AI Embeddings API 集成 + +本教程将指导你如何使用 [Jina AI](https://jina.ai/) 为文本数据生成嵌入向量,然后将这些嵌入向量存储在 TiDB 向量存储中并基于嵌入向量搜索相似文本。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 前提条件 + +要完成本教程,你需要: + +- 安装 [Python 3.8 或更高版本](https://www.python.org/downloads/)。 +- 安装 [Git](https://git-scm.com/downloads)。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)的说明创建你自己的 TiDB Cloud 集群。 + +## 运行示例应用 + +你可以按照以下步骤快速了解如何将 TiDB 向量搜索与 JinaAI Embedding 集成。 + +### 步骤 1. 克隆代码仓库 + +将 `tidb-vector-python` 代码仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 步骤 2. 创建虚拟环境 + +为你的项目创建一个虚拟环境: + +```bash +cd tidb-vector-python/examples/jina-ai-embeddings-demo +python3 -m venv .venv +source .venv/bin/activate +``` + +### 步骤 3. 安装所需依赖 + +安装示例项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +### 步骤 4. 配置环境变量 + +从 [Jina AI Embeddings API](https://jina.ai/embeddings/) 页面获取 Jina AI API 密钥。然后,获取集群连接字符串并按如下方式配置环境变量: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示一个连接对话框。 + +3. 确保连接对话框中的配置与你的操作环境匹配。 + + - **连接类型**设置为 `Public` + - **分支**设置为 `main` + - **连接方式**设置为 `SQLAlchemy` + - **操作系统**与你的环境匹配。 + + > **提示:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 切换到 **PyMySQL** 标签页,点击**复制**图标复制连接字符串。 + + > **提示:** + > + > 如果你还没有设置密码,请点击**创建密码**生成一个随机密码。 + +5. 在终端中设置 Jina AI API 密钥和 TiDB 连接字符串作为环境变量,或创建一个包含以下环境变量的 `.env` 文件: + + ```dotenv + JINAAI_API_KEY="****" + TIDB_DATABASE_URL="{tidb_connection_string}" + ``` + + 以下是 macOS 的示例连接字符串: + + ```dotenv + TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + ``` + +### 步骤 5. 运行示例 + +```bash +python jina-ai-embeddings-demo.py +``` + +示例输出: + +```text +- Inserting Data to TiDB... + - Inserting: Jina AI offers best-in-class embeddings, reranker and prompt optimizer, enabling advanced multimodal AI. + - Inserting: TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. +- List All Documents and Their Distances to the Query: + - distance: 0.3585317326132522 + content: Jina AI offers best-in-class embeddings, reranker and prompt optimizer, enabling advanced multimodal AI. + - distance: 0.10858102967720984 + content: TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. +- The Most Relevant Document and Its Distance to the Query: + - distance: 0.10858102967720984 + content: TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. +``` + +## 示例代码片段 + +### 从 Jina AI 获取嵌入向量 + +定义一个 `generate_embeddings` 辅助函数来调用 Jina AI embeddings API: + +```python +import os +import requests +import dotenv + +dotenv.load_dotenv() + +JINAAI_API_KEY = os.getenv('JINAAI_API_KEY') + +def generate_embeddings(text: str): + JINAAI_API_URL = 'https://api.jina.ai/v1/embeddings' + JINAAI_HEADERS = { + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {JINAAI_API_KEY}' + } + JINAAI_REQUEST_DATA = { + 'input': [text], + 'model': 'jina-embeddings-v2-base-en' # with dimension 768. + } + response = requests.post(JINAAI_API_URL, headers=JINAAI_HEADERS, json=JINAAI_REQUEST_DATA) + return response.json()['data'][0]['embedding'] +``` + +### 连接到 TiDB 集群 + +通过 SQLAlchemy 连接到 TiDB 集群: + +```python +import os +import dotenv + +from tidb_vector.sqlalchemy import VectorType +from sqlalchemy.orm import Session, declarative_base + +dotenv.load_dotenv() + +TIDB_DATABASE_URL = os.getenv('TIDB_DATABASE_URL') +assert TIDB_DATABASE_URL is not None +engine = create_engine(url=TIDB_DATABASE_URL, pool_recycle=300) +``` + +### 定义向量表模式 + +创建一个名为 `jinaai_tidb_demo_documents` 的表,其中包含用于存储文本的 `content` 列和用于存储嵌入向量的 `content_vec` 列: + +```python +from sqlalchemy import Column, Integer, String, create_engine +from sqlalchemy.orm import declarative_base + +Base = declarative_base() + +class Document(Base): + __tablename__ = "jinaai_tidb_demo_documents" + + id = Column(Integer, primary_key=True) + content = Column(String(255), nullable=False) + content_vec = Column( + # DIMENSIONS 由嵌入模型决定, + # 对于 Jina AI 的 jina-embeddings-v2-base-en 模型,它是 768。 + VectorType(dim=768), + comment="hnsw(distance=cosine)" +``` + +> **注意:** +> +> - 向量列的维度必须与嵌入模型生成的嵌入向量的维度匹配。 +> - 在本例中,`jina-embeddings-v2-base-en` 模型生成的嵌入向量维度为 `768`。 + +### 使用 Jina AI 创建嵌入向量并存储在 TiDB 中 + +使用 Jina AI Embeddings API 为每段文本生成嵌入向量,并将嵌入向量存储在 TiDB 中: + +```python +TEXTS = [ + 'Jina AI offers best-in-class embeddings, reranker and prompt optimizer, enabling advanced multimodal AI.', + 'TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads.', +] +data = [] + +for text in TEXTS: + # 通过 Jina AI API 为文本生成嵌入向量。 + embedding = generate_embeddings(text) + data.append({ + 'text': text, + 'embedding': embedding + }) + +with Session(engine) as session: + print('- Inserting Data to TiDB...') + for item in data: + print(f' - Inserting: {item["text"]}') + session.add(Document( + content=item['text'], + content_vec=item['embedding'] + )) + session.commit() +``` + +### 在 TiDB 中使用 Jina AI 嵌入向量执行语义搜索 + +通过 Jina AI embeddings API 为查询文本生成嵌入向量,然后基于**查询文本的嵌入向量**和**向量表中的每个嵌入向量**之间的余弦距离搜索最相关的文档: + +```python +query = 'What is TiDB?' +# 通过 Jina AI API 为查询生成嵌入向量。 +query_embedding = generate_embeddings(query) + +with Session(engine) as session: + print('- The Most Relevant Document and Its Distance to the Query:') + doc, distance = session.query( + Document, + Document.content_vec.cosine_distance(query_embedding).label('distance') + ).order_by( + 'distance' + ).limit(1).first() + print(f' - distance: {distance}\n' + f' content: {doc.content}') +``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-integrate-with-langchain.md b/tidb-cloud/vector-search-integrate-with-langchain.md new file mode 100644 index 000000000000..257af67aa7be --- /dev/null +++ b/tidb-cloud/vector-search-integrate-with-langchain.md @@ -0,0 +1,586 @@ +--- +title: 将向量搜索与 LangChain 集成 +summary: 了解如何将 TiDB Cloud 中的向量搜索与 LangChain 集成。 +--- + +# 将向量搜索与 LangChain 集成 + +本教程演示如何将 TiDB Cloud 中的[向量搜索](/tidb-cloud/vector-search-overview.md)功能与 [LangChain](https://python.langchain.com/) 集成。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB 自管理版本(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +> **提示** +> +> 你可以在 Jupyter Notebook 上查看完整的[示例代码](https://github.com/langchain-ai/langchain/blob/master/docs/docs/integrations/vectorstores/tidb_vector.ipynb),或直接在 [Colab](https://colab.research.google.com/github/langchain-ai/langchain/blob/master/docs/docs/integrations/vectorstores/tidb_vector.ipynb) 在线环境中运行示例代码。 + +## 前提条件 + +要完成本教程,你需要: + +- 安装 [Python 3.8 或更高版本](https://www.python.org/downloads/)。 +- 安装 [Jupyter Notebook](https://jupyter.org/install)。 +- 安装 [Git](https://git-scm.com/downloads)。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)创建自己的 TiDB Cloud 集群。 + +## 开始使用 + +本节提供将 TiDB 向量搜索与 LangChain 集成以执行语义搜索的分步说明。 + +### 步骤 1. 创建新的 Jupyter Notebook 文件 + +在你选择的目录中,创建一个名为 `integrate_with_langchain.ipynb` 的新 Jupyter Notebook 文件: + +```shell +touch integrate_with_langchain.ipynb +``` + +### 步骤 2. 安装所需依赖 + +在你的项目目录中,运行以下命令安装所需的包: + +```shell +!pip install langchain langchain-community +!pip install langchain-openai +!pip install pymysql +!pip install tidb-vector +``` + +在 Jupyter Notebook 中打开 `integrate_with_langchain.ipynb` 文件,然后添加以下代码以导入所需的包: + +```python +from langchain_community.document_loaders import TextLoader +from langchain_community.vectorstores import TiDBVectorStore +from langchain_openai import OpenAIEmbeddings +from langchain_text_splitters import CharacterTextSplitter +``` + +### 步骤 3. 设置环境 + +按照以下步骤获取集群连接字符串并配置环境变量: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。此时会显示一个连接对话框。 + +3. 确保连接对话框中的配置与你的操作环境匹配。 + + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接方式**设置为 `SQLAlchemy`。 + - **操作系统**与你的环境匹配。 + +4. 点击 **PyMySQL** 标签并复制连接字符串。 + + > **提示:** + > + > 如果你还没有设置密码,请点击**生成密码**生成一个随机密码。 + +5. 配置环境变量。 + + 本文使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型提供者。在此步骤中,你需要提供从上一步获取的连接字符串和你的 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 + + 要配置环境变量,运行以下代码。系统会提示你输入连接字符串和 OpenAI API 密钥: + + ```python + # 使用 getpass 在终端中安全地提示输入环境变量。 + import getpass + import os + + # 从 TiDB Cloud 控制台复制你的连接字符串。 + # 连接字符串格式:"mysql+pymysql://:@:4000/?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + tidb_connection_string = getpass.getpass("TiDB Connection String:") + os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") + ``` + +### 步骤 4. 加载示例文档 + +#### 步骤 4.1 下载示例文档 + +在你的项目目录中,创建一个名为 `data/how_to/` 的目录,并从 [langchain-ai/langchain](https://github.com/langchain-ai/langchain) GitHub 仓库下载示例文档 [`state_of_the_union.txt`](https://github.com/langchain-ai/langchain/blob/master/docs/docs/how_to/state_of_the_union.txt)。 + +```shell +!mkdir -p 'data/how_to/' +!wget 'https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/how_to/state_of_the_union.txt' -O 'data/how_to/state_of_the_union.txt' +``` + +#### 步骤 4.2 加载并拆分文档 + +从 `data/how_to/state_of_the_union.txt` 加载示例文档,并使用 `CharacterTextSplitter` 将其拆分为每个约 1,000 个字符的块。 + +```python +loader = TextLoader("data/how_to/state_of_the_union.txt") +documents = loader.load() +text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) +docs = text_splitter.split_documents(documents) +``` + +### 步骤 5. 嵌入并存储文档向量 + +TiDB 向量存储支持余弦距离(`cosine`)和欧几里得距离(`l2`)来衡量向量之间的相似度。默认策略是余弦距离。 + +以下代码在 TiDB 中创建一个名为 `embedded_documents` 的表,该表针对向量搜索进行了优化。 + +```python +embeddings = OpenAIEmbeddings() +vector_store = TiDBVectorStore.from_documents( + documents=docs, + embedding=embeddings, + table_name="embedded_documents", + connection_string=tidb_connection_string, + distance_strategy="cosine", # 默认值,另一个选项是 "l2" +) +``` + +执行成功后,你可以直接在 TiDB 数据库中查看和访问 `embedded_documents` 表。 + +### 步骤 6. 执行向量搜索 + +此步骤演示如何从文档 `state_of_the_union.txt` 中查询 "What did the president say about Ketanji Brown Jackson"。 + +```python +query = "What did the president say about Ketanji Brown Jackson" +``` + +#### 选项 1:使用 `similarity_search_with_score()` + +`similarity_search_with_score()` 方法计算文档和查询之间的向量空间距离。这个距离作为相似度分数,由所选的 `distance_strategy` 决定。该方法返回得分最低的前 `k` 个文档。较低的分数表示文档与你的查询在含义上更相似。 + +```python +docs_with_score = vector_store.similarity_search_with_score(query, k=3) +for doc, score in docs_with_score: + print("-" * 80) + print("Score: ", score) + print(doc.page_content) + print("-" * 80) +``` + +
+ 预期输出 + +```plain +-------------------------------------------------------------------------------- +Score: 0.18472413652518527 +Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you're at it, pass the Disclose Act so Americans can know who is funding our elections. + +Tonight, I'd like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. + +One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. + +And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation's top legal minds, who will continue Justice Breyer's legacy of excellence. +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Score: 0.21757513022785557 +A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since she's been nominated, she's received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. + +And if we are to advance liberty and justice, we need to secure the Border and fix the immigration system. + +We can do both. At our border, we've installed new technology like cutting-edge scanners to better detect drug smuggling. + +We've set up joint patrols with Mexico and Guatemala to catch more human traffickers. + +We're putting in place dedicated immigration judges so families fleeing persecution and violence can have their cases heard faster. + +We're securing commitments and supporting partners in South and Central America to host more refugees and secure their own borders. +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Score: 0.22676987253721725 +And for our LGBTQ+ Americans, let's finally get the bipartisan Equality Act to my desk. The onslaught of state laws targeting transgender Americans and their families is wrong. + +As I said last year, especially to our younger transgender Americans, I will always have your back as your President, so you can be yourself and reach your God-given potential. + +While it often appears that we never agree, that isn't true. I signed 80 bipartisan bills into law last year. From preventing government shutdowns to protecting Asian-Americans from still-too-common hate crimes to reforming military justice. + +And soon, we'll strengthen the Violence Against Women Act that I first wrote three decades ago. It is important for us to show the nation that we can come together and do big things. + +So tonight I'm offering a Unity Agenda for the Nation. Four big things we can do together. + +First, beat the opioid epidemic. +-------------------------------------------------------------------------------- +``` + +
+ +#### 选项 2:使用 `similarity_search_with_relevance_scores()` + +`similarity_search_with_relevance_scores()` 方法返回相关性得分最高的前 `k` 个文档。较高的分数表示文档与你的查询之间的相似度更高。 + +```python +docs_with_relevance_score = vector_store.similarity_search_with_relevance_scores(query, k=2) +for doc, score in docs_with_relevance_score: + print("-" * 80) + print("Score: ", score) + print(doc.page_content) + print("-" * 80) +``` + +
+ 预期输出 + +```plain +-------------------------------------------------------------------------------- +Score: 0.8152758634748147 +Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you're at it, pass the Disclose Act so Americans can know who is funding our elections. + +Tonight, I'd like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. + +One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. + +And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation's top legal minds, who will continue Justice Breyer's legacy of excellence. +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Score: 0.7824248697721444 +A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since she's been nominated, she's received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. + +And if we are to advance liberty and justice, we need to secure the Border and fix the immigration system. + +We can do both. At our border, we've installed new technology like cutting-edge scanners to better detect drug smuggling. + +We've set up joint patrols with Mexico and Guatemala to catch more human traffickers. + +We're putting in place dedicated immigration judges so families fleeing persecution and violence can have their cases heard faster. + +We're securing commitments and supporting partners in South and Central America to host more refugees and secure their own borders. +-------------------------------------------------------------------------------- +``` + +
+ +### 用作检索器 + +在 Langchain 中,[检索器](https://python.langchain.com/v0.2/docs/concepts/#retrievers)是一个接口,它响应非结构化查询检索文档,提供比向量存储更多的功能。以下代码演示如何将 TiDB 向量存储用作检索器。 + +```python +retriever = vector_store.as_retriever( + search_type="similarity_score_threshold", + search_kwargs={"k": 3, "score_threshold": 0.8}, +) +docs_retrieved = retriever.invoke(query) +for doc in docs_retrieved: + print("-" * 80) + print(doc.page_content) + print("-" * 80) +``` + +预期输出如下: + +``` +-------------------------------------------------------------------------------- +Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you're at it, pass the Disclose Act so Americans can know who is funding our elections. + +Tonight, I'd like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. + +One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. + +And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation's top legal minds, who will continue Justice Breyer's legacy of excellence. +-------------------------------------------------------------------------------- +``` + +### 移除向量存储 + +要移除现有的 TiDB 向量存储,使用 `drop_vectorstore()` 方法: + +```python +vector_store.drop_vectorstore() +``` + +## 使用元数据过滤器搜索 + +要优化搜索,你可以使用元数据过滤器来检索与应用的过滤器匹配的特定最近邻结果。 + +### 支持的元数据类型 + +TiDB 向量存储中的每个文档都可以与元数据配对,元数据以 JSON 对象中的键值对形式构建。键始终是字符串,而值可以是以下任何类型: + +- 字符串 +- 数字:整数或浮点数 +- 布尔值:`true` 或 `false` + +例如,以下是一个有效的元数据负载: + +```json +{ + "page": 12, + "book_title": "Siddhartha" +} +``` + +### 元数据过滤器语法 + +可用的过滤器包括: + +- `$or`:选择匹配任一指定条件的向量。 +- `$and`:选择匹配所有指定条件的向量。 +- `$eq`:等于指定值。 +- `$ne`:不等于指定值。 +- `$gt`:大于指定值。 +- `$gte`:大于或等于指定值。 +- `$lt`:小于指定值。 +- `$lte`:小于或等于指定值。 +- `$in`:在指定的值数组中。 +- `$nin`:不在指定的值数组中。 + +如果文档的元数据如下: + +```json +{ + "page": 12, + "book_title": "Siddhartha" +} +``` + +以下元数据过滤器可以匹配此文档: + +```json +{ "page": 12 } +``` + +```json +{ "page": { "$eq": 12 } } +``` + +```json +{ + "page": { + "$in": [11, 12, 13] + } +} +``` + +```json +{ "page": { "$nin": [13] } } +``` + +```json +{ "page": { "$lt": 11 } } +``` + +```json +{ + "$or": [{ "page": 11 }, { "page": 12 }], + "$and": [{ "page": 12 }, { "page": 13 }] +} +``` + +在元数据过滤器中,TiDB 将每个键值对视为单独的过滤器子句,并使用 `AND` 逻辑运算符组合这些子句。 + +### 示例 + +以下示例向 `TiDBVectorStore` 添加两个文档,并为每个文档添加一个 `title` 字段作为元数据: + +```python +vector_store.add_texts( + texts=[ + "TiDB Vector offers advanced, high-speed vector processing capabilities, enhancing AI workflows with efficient data handling and analytics support.", + "TiDB Vector, starting as low as $10 per month for basic usage", + ], + metadatas=[ + {"title": "TiDB Vector functionality"}, + {"title": "TiDB Vector Pricing"}, + ], +) +``` + +预期输出如下: + +```plain +[UUID('c782cb02-8eec-45be-a31f-fdb78914f0a7'), + UUID('08dcd2ba-9f16-4f29-a9b7-18141f8edae3')] +``` + +使用元数据过滤器执行相似度搜索: + +```python +docs_with_score = vector_store.similarity_search_with_score( + "Introduction to TiDB Vector", filter={"title": "TiDB Vector functionality"}, k=4 +) +for doc, score in docs_with_score: + print("-" * 80) + print("Score: ", score) + print(doc.page_content) + print("-" * 80) +``` + +预期输出如下: + +```plain +-------------------------------------------------------------------------------- +Score: 0.12761409169211535 +TiDB Vector offers advanced, high-speed vector processing capabilities, enhancing AI workflows with efficient data handling and analytics support. +-------------------------------------------------------------------------------- +``` + +## 高级用法示例:旅行代理 + +本节演示将向量搜索与 Langchain 集成用于旅行代理的用例。目标是为客户创建个性化的旅行报告,帮助他们找到具有特定设施(如干净的休息室和素食选项)的机场。 + +该过程包括两个主要步骤: + +1. 对机场评论进行语义搜索,以识别匹配所需设施的机场代码。 +2. 执行 SQL 查询,将这些代码与路线信息合并,突出显示符合用户偏好的航空公司和目的地。 + +### 准备数据 + +首先,创建一个表来存储机场路线数据: + +```python +# 创建一个表来存储航班计划数据。 +vector_store.tidb_vector_client.execute( + """CREATE TABLE airplan_routes ( + id INT AUTO_INCREMENT PRIMARY KEY, + airport_code VARCHAR(10), + airline_code VARCHAR(10), + destination_code VARCHAR(10), + route_details TEXT, + duration TIME, + frequency INT, + airplane_type VARCHAR(50), + price DECIMAL(10, 2), + layover TEXT + );""" +) + +# 向 airplan_routes 和向量表插入一些示例数据。 +vector_store.tidb_vector_client.execute( + """INSERT INTO airplan_routes ( + airport_code, + airline_code, + destination_code, + route_details, + duration, + frequency, + airplane_type, + price, + layover + ) VALUES + ('JFK', 'DL', 'LAX', 'Non-stop from JFK to LAX.', '06:00:00', 5, 'Boeing 777', 299.99, 'None'), + ('LAX', 'AA', 'ORD', 'Direct LAX to ORD route.', '04:00:00', 3, 'Airbus A320', 149.99, 'None'), + ('EFGH', 'UA', 'SEA', 'Daily flights from SFO to SEA.', '02:30:00', 7, 'Boeing 737', 129.99, 'None'); + """ +) +vector_store.add_texts( + texts=[ + "Clean lounges and excellent vegetarian dining options. Highly recommended.", + "Comfortable seating in lounge areas and diverse food selections, including vegetarian.", + "Small airport with basic facilities.", + ], + metadatas=[ + {"airport_code": "JFK"}, + {"airport_code": "LAX"}, + {"airport_code": "EFGH"}, + ], +) +``` + +预期输出如下: + +```plain +[UUID('6dab390f-acd9-4c7d-b252-616606fbc89b'), + UUID('9e811801-0e6b-4893-8886-60f4fb67ce69'), + UUID('f426747c-0f7b-4c62-97ed-3eeb7c8dd76e')] +``` + +### 执行语义搜索 + +以下代码搜索具有干净设施和素食选项的机场: + +```python +retriever = vector_store.as_retriever( + search_type="similarity_score_threshold", + search_kwargs={"k": 3, "score_threshold": 0.85}, +) +semantic_query = "Could you recommend a US airport with clean lounges and good vegetarian dining options?" +reviews = retriever.invoke(semantic_query) +for r in reviews: + print("-" * 80) + print(r.page_content) + print(r.metadata) + print("-" * 80) +``` + +预期输出如下: + +```plain +-------------------------------------------------------------------------------- +Clean lounges and excellent vegetarian dining options. Highly recommended. +{'airport_code': 'JFK'} +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Comfortable seating in lounge areas and diverse food selections, including vegetarian. +{'airport_code': 'LAX'} +-------------------------------------------------------------------------------- +``` + +### 检索详细的机场信息 + +从搜索结果中提取机场代码并查询数据库以获取详细的路线信息: + +```python +# 从元数据中提取机场代码 +airport_codes = [review.metadata["airport_code"] for review in reviews] + +# 执行查询以获取机场详细信息 +search_query = "SELECT * FROM airplan_routes WHERE airport_code IN :codes" +params = {"codes": tuple(airport_codes)} + +airport_details = vector_store.tidb_vector_client.execute(search_query, params) +airport_details.get("result") +``` + +预期输出如下: + +```plain +[(1, 'JFK', 'DL', 'LAX', 'Non-stop from JFK to LAX.', datetime.timedelta(seconds=21600), 5, 'Boeing 777', Decimal('299.99'), 'None'), + (2, 'LAX', 'AA', 'ORD', 'Direct LAX to ORD route.', datetime.timedelta(seconds=14400), 3, 'Airbus A320', Decimal('149.99'), 'None')] +``` + +### 简化流程 + +或者,你可以使用单个 SQL 查询简化整个流程: + +```python +search_query = f""" + SELECT + VEC_Cosine_Distance(se.embedding, :query_vector) as distance, + ar.*, + se.document as airport_review + FROM + airplan_routes ar + JOIN + {TABLE_NAME} se ON ar.airport_code = JSON_UNQUOTE(JSON_EXTRACT(se.meta, '$.airport_code')) + ORDER BY distance ASC + LIMIT 5; +""" +query_vector = embeddings.embed_query(semantic_query) +params = {"query_vector": str(query_vector)} +airport_details = vector_store.tidb_vector_client.execute(search_query, params) +airport_details.get("result") +``` + +预期输出如下: + +```plain +[(0.1219207353407008, 1, 'JFK', 'DL', 'LAX', 'Non-stop from JFK to LAX.', datetime.timedelta(seconds=21600), 5, 'Boeing 777', Decimal('299.99'), 'None', 'Clean lounges and excellent vegetarian dining options. Highly recommended.'), + (0.14613754359804654, 2, 'LAX', 'AA', 'ORD', 'Direct LAX to ORD route.', datetime.timedelta(seconds=14400), 3, 'Airbus A320', Decimal('149.99'), 'None', 'Comfortable seating in lounge areas and diverse food selections, including vegetarian.'), + (0.19840519342700513, 3, 'EFGH', 'UA', 'SEA', 'Daily flights from SFO to SEA.', datetime.timedelta(seconds=9000), 7, 'Boeing 737', Decimal('129.99'), 'None', 'Small airport with basic facilities.')] +``` + +### 清理数据 + +最后,通过删除创建的表来清理资源: + +```python +vector_store.tidb_vector_client.execute("DROP TABLE airplan_routes") +``` + +预期输出如下: + +```plain +{'success': True, 'result': 0, 'error': None} +``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-integrate-with-llamaindex.md b/tidb-cloud/vector-search-integrate-with-llamaindex.md new file mode 100644 index 000000000000..b730d63cdc45 --- /dev/null +++ b/tidb-cloud/vector-search-integrate-with-llamaindex.md @@ -0,0 +1,266 @@ +--- +title: 将向量搜索与 LlamaIndex 集成 +summary: 了解如何将 TiDB 向量搜索与 LlamaIndex 集成。 +--- + +# 将向量搜索与 LlamaIndex 集成 + +本教程演示如何将 TiDB 的[向量搜索](/tidb-cloud/vector-search-overview.md)功能与 [LlamaIndex](https://www.llamaindex.ai) 集成。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +> **提示** +> +> 你可以在 Jupyter Notebook 上查看完整的[示例代码](https://github.com/run-llama/llama_index/blob/main/docs/docs/examples/vector_stores/TiDBVector.ipynb),或直接在 [Colab](https://colab.research.google.com/github/run-llama/llama_index/blob/main/docs/docs/examples/vector_stores/TiDBVector.ipynb) 在线环境中运行示例代码。 + +## 前提条件 + +要完成本教程,你需要: + +- 安装 [Python 3.8 或更高版本](https://www.python.org/downloads/)。 +- 安装 [Jupyter Notebook](https://jupyter.org/install)。 +- 安装 [Git](https://git-scm.com/downloads)。 +- 一个 TiDB Cloud Serverless 集群。如果你没有 TiDB Cloud 集群,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)的说明创建自己的 TiDB Cloud 集群。 + +## 开始使用 + +本节提供将 TiDB 向量搜索与 LlamaIndex 集成以执行语义搜索的分步说明。 + +### 步骤 1. 创建新的 Jupyter Notebook 文件 + +在根目录中,创建一个名为 `integrate_with_llamaindex.ipynb` 的新 Jupyter Notebook 文件: + +```shell +touch integrate_with_llamaindex.ipynb +``` + +### 步骤 2. 安装所需依赖 + +在项目目录中,运行以下命令安装所需的包: + +```shell +pip install llama-index-vector-stores-tidbvector +pip install llama-index +``` + +在 Jupyter Notebook 中打开 `integrate_with_llamaindex.ipynb` 文件,并添加以下代码以导入所需的包: + +```python +import textwrap + +from llama_index.core import SimpleDirectoryReader, StorageContext +from llama_index.core import VectorStoreIndex +from llama_index.vector_stores.tidbvector import TiDBVectorStore +``` + +### 步骤 3. 配置环境变量 + +按照以下步骤获取集群连接字符串并配置环境变量: + +1. 导航到[**集群**](https://tidbcloud.com/project/clusters)页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的**连接**。将显示一个连接对话框。 + +3. 确保连接对话框中的配置与你的操作环境匹配。 + + - **连接类型**设置为 `Public`。 + - **分支**设置为 `main`。 + - **连接方式**设置为 `SQLAlchemy`。 + - **操作系统**与你的环境匹配。 + +4. 点击 **PyMySQL** 标签并复制连接字符串。 + + > **提示:** + > + > 如果你还没有设置密码,点击**生成密码**以生成一个随机密码。 + +5. 配置环境变量。 + + 本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型提供者。在此步骤中,你需要提供从上一步获取的连接字符串和你的 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 + + 要配置环境变量,运行以下代码。系统将提示你输入连接字符串和 OpenAI API 密钥: + + ```python + # 使用 getpass 在终端中安全地提示输入环境变量。 + import getpass + import os + + # 从 TiDB Cloud 控制台复制你的连接字符串。 + # 连接字符串格式:"mysql+pymysql://:@:4000/?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + tidb_connection_string = getpass.getpass("TiDB Connection String:") + os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") + ``` + +### 步骤 4. 加载示例文档 + +#### 步骤 4.1 下载示例文档 + +在项目目录中,创建一个名为 `data/paul_graham/` 的目录,并从 [run-llama/llama_index](https://github.com/run-llama/llama_index) GitHub 仓库下载示例文档 [`paul_graham_essay.txt`](https://github.com/run-llama/llama_index/blob/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt)。 + +```shell +!mkdir -p 'data/paul_graham/' +!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt' +``` + +#### 步骤 4.2 加载文档 + +使用 `SimpleDirectoryReader` 类从 `data/paul_graham/paul_graham_essay.txt` 加载示例文档。 + +```python +documents = SimpleDirectoryReader("./data/paul_graham").load_data() +print("Document ID:", documents[0].doc_id) + +for index, document in enumerate(documents): + document.metadata = {"book": "paul_graham"} +``` + +### 步骤 5. 嵌入和存储文档向量 + +#### 步骤 5.1 初始化 TiDB 向量存储 + +以下代码在 TiDB 中创建一个名为 `paul_graham_test` 的表,该表针对向量搜索进行了优化。 + +```python +tidbvec = TiDBVectorStore( + connection_string=tidb_connection_url, + table_name="paul_graham_test", + distance_strategy="cosine", + vector_dimension=1536, + drop_existing_table=False, +) +``` + +成功执行后,你可以直接在 TiDB 数据库中查看和访问 `paul_graham_test` 表。 + +#### 步骤 5.2 生成和存储嵌入 + +以下代码解析文档,生成嵌入,并将它们存储在 TiDB 向量存储中。 + +```python +storage_context = StorageContext.from_defaults(vector_store=tidbvec) +index = VectorStoreIndex.from_documents( + documents, storage_context=storage_context, show_progress=True +) +``` + +预期输出如下: + +```plain +Parsing nodes: 100%|██████████| 1/1 [00:00<00:00, 8.76it/s] +Generating embeddings: 100%|██████████| 21/21 [00:02<00:00, 8.22it/s] +``` + +### 步骤 6. 执行向量搜索 + +以下代码基于 TiDB 向量存储创建查询引擎并执行语义相似度搜索。 + +```python +query_engine = index.as_query_engine() +response = query_engine.query("What did the author do?") +print(textwrap.fill(str(response), 100)) +``` + +> **注意** +> +> `TiDBVectorStore` 仅支持 [`default`](https://docs.llamaindex.ai/en/stable/api_reference/storage/vector_store/?h=vectorstorequerymode#llama_index.core.vector_stores.types.VectorStoreQueryMode) 查询模式。 + +预期输出如下: + +```plain +The author worked on writing, programming, building microcomputers, giving talks at conferences, +publishing essays online, developing spam filters, painting, hosting dinner parties, and purchasing +a building for office use. +``` + +### 步骤 7. 使用元数据过滤器搜索 + +要优化搜索,你可以使用元数据过滤器来检索与应用的过滤器匹配的特定最近邻结果。 + +#### 使用 `book != "paul_graham"` 过滤器查询 + +以下示例排除 `book` 元数据字段为 `"paul_graham"` 的结果: + +```python +from llama_index.core.vector_stores.types import ( + MetadataFilter, + MetadataFilters, +) + +query_engine = index.as_query_engine( + filters=MetadataFilters( + filters=[ + MetadataFilter(key="book", value="paul_graham", operator="!="), + ] + ), + similarity_top_k=2, +) +response = query_engine.query("What did the author learn?") +print(textwrap.fill(str(response), 100)) +``` + +预期输出如下: + +```plain +Empty Response +``` + +#### 使用 `book == "paul_graham"` 过滤器查询 + +以下示例过滤结果以仅包含 `book` 元数据字段为 `"paul_graham"` 的文档: + +```python +from llama_index.core.vector_stores.types import ( + MetadataFilter, + MetadataFilters, +) + +query_engine = index.as_query_engine( + filters=MetadataFilters( + filters=[ + MetadataFilter(key="book", value="paul_graham", operator="=="), + ] + ), + similarity_top_k=2, +) +response = query_engine.query("What did the author learn?") +print(textwrap.fill(str(response), 100)) +``` + +预期输出如下: + +```plain +The author learned programming on an IBM 1401 using an early version of Fortran in 9th grade, then +later transitioned to working with microcomputers like the TRS-80 and Apple II. Additionally, the +author studied philosophy in college but found it unfulfilling, leading to a switch to studying AI. +Later on, the author attended art school in both the US and Italy, where they observed a lack of +substantial teaching in the painting department. +``` + +### 步骤 8. 删除文档 + +从索引中删除第一个文档: + +```python +tidbvec.delete(documents[0].doc_id) +``` + +检查文档是否已被删除: + +```python +query_engine = index.as_query_engine() +response = query_engine.query("What did the author learn?") +print(textwrap.fill(str(response), 100)) +``` + +预期输出如下: + +```plain +Empty Response +``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-integrate-with-peewee.md b/tidb-cloud/vector-search-integrate-with-peewee.md new file mode 100644 index 000000000000..b5cd5dd996c4 --- /dev/null +++ b/tidb-cloud/vector-search-integrate-with-peewee.md @@ -0,0 +1,211 @@ +--- +title: 将 TiDB Vector Search 与 peewee 集成 +summary: 了解如何将 TiDB Vector Search 与 peewee 集成以存储嵌入向量并执行语义搜索。 +--- + +# 将 TiDB Vector Search 与 peewee 集成 + +本教程将指导你如何使用 [peewee](https://docs.peewee-orm.com/) 与 [TiDB Vector Search](/tidb-cloud/vector-search-overview.md) 交互,存储嵌入向量并执行向量搜索查询。 + +> **注意** +> +> TiDB Vector Search 仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 前提条件 + +完成本教程需要: + +- 安装 [Python 3.8 或更高版本](https://www.python.org/downloads/)。 +- 安装 [Git](https://git-scm.com/downloads)。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,请参考[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)来创建你自己的 TiDB Cloud 集群。 + +## 运行示例应用 + +你可以按照以下步骤快速了解如何将 TiDB Vector Search 与 peewee 集成。 + +### 步骤 1. 克隆代码仓库 + +将 [`tidb-vector-python`](https://github.com/pingcap/tidb-vector-python) 代码仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 步骤 2. 创建虚拟环境 + +为你的项目创建一个虚拟环境: + +```bash +cd tidb-vector-python/examples/orm-peewee-quickstart +python3 -m venv .venv +source .venv/bin/activate +``` + +### 步骤 3. 安装所需依赖 + +安装示例项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +或者,你可以为你的项目安装以下包: + +```bash +pip install peewee pymysql python-dotenv tidb-vector +``` + +### 步骤 4. 配置环境变量 + +1. 导航到 [**Clusters**](https://tidbcloud.com/project/clusters) 页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的 **Connect**。将显示连接对话框。 + +3. 确保连接对话框中的配置与你的操作环境匹配。 + + - **Connection Type** 设置为 `Public`。 + - **Branch** 设置为 `main`。 + - **Connect With** 设置为 `General`。 + - **Operating System** 与你的环境匹配。 + + > **提示:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 从连接对话框中复制连接参数。 + + > **提示:** + > + > 如果你还没有设置密码,请点击 **Generate Password** 生成一个随机密码。 + +5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 + + - `TIDB_HOST`:TiDB 集群的主机地址。 + - `TIDB_PORT`:TiDB 集群的端口。 + - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 + - `TIDB_PASSWORD`:连接 TiDB 集群的密码。 + - `TIDB_DATABASE`:要连接的数据库名称。 + - `TIDB_CA_PATH`:根证书文件的路径。 + + 以下是 macOS 的示例: + + ```dotenv + TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com + TIDB_PORT=4000 + TIDB_USERNAME=********.root + TIDB_PASSWORD=******** + TIDB_DATABASE=test + TIDB_CA_PATH=/etc/ssl/cert.pem + ``` + +### 步骤 5. 运行示例 + +```bash +python peewee-quickstart.py +``` + +示例输出: + +```text +Get 3-nearest neighbor documents: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog + - distance: 0.7327387580875756 + document: tree +Get documents within a certain distance: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog +``` + +## 示例代码片段 + +你可以参考以下示例代码片段来开发你的应用。 + +### 创建向量表 + +#### 连接到 TiDB 集群 + +```python +import os +import dotenv + +from peewee import Model, MySQLDatabase, SQL, TextField +from tidb_vector.peewee import VectorField + +dotenv.load_dotenv() + +# 使用 `pymysql` 作为驱动 +connect_kwargs = { + 'ssl_verify_cert': True, + 'ssl_verify_identity': True, +} + +# 使用 `mysqlclient` 作为驱动 +# connect_kwargs = { +# 'ssl_mode': 'VERIFY_IDENTITY', +# 'ssl': { +# # 根证书默认路径 +# # https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters/#root-certificate-default-path +# 'ca': os.environ.get('TIDB_CA_PATH', '/path/to/ca.pem'), +# }, +# } + +db = MySQLDatabase( + database=os.environ.get('TIDB_DATABASE', 'test'), + user=os.environ.get('TIDB_USERNAME', 'root'), + password=os.environ.get('TIDB_PASSWORD', ''), + host=os.environ.get('TIDB_HOST', 'localhost'), + port=int(os.environ.get('TIDB_PORT', '4000')), + **connect_kwargs, +) +``` + +#### 定义向量列 + +创建一个名为 `peewee_demo_documents` 的表,其中包含一个存储 3 维向量的列。 + +```python +class Document(Model): + class Meta: + database = db + table_name = 'peewee_demo_documents' + + content = TextField() + embedding = VectorField(3) +``` + +### 存储带有嵌入向量的文档 + +```python +Document.create(content='dog', embedding=[1, 2, 1]) +Document.create(content='fish', embedding=[1, 2, 4]) +Document.create(content='tree', embedding=[1, 0, 0]) +``` + +### 搜索最近邻文档 + +基于余弦距离函数,搜索与查询向量 `[1, 2, 3]` 语义最接近的前 3 个文档。 + +```python +distance = Document.embedding.cosine_distance([1, 2, 3]).alias('distance') +results = Document.select(Document, distance).order_by(distance).limit(3) +``` + +### 搜索特定距离内的文档 + +搜索与查询向量 `[1, 2, 3]` 的余弦距离小于 0.2 的文档。 + +```python +distance_expression = Document.embedding.cosine_distance([1, 2, 3]) +distance = distance_expression.alias('distance') +results = Document.select(Document, distance).where(distance_expression < 0.2).order_by(distance).limit(3) +``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-integrate-with-sqlalchemy.md b/tidb-cloud/vector-search-integrate-with-sqlalchemy.md new file mode 100644 index 000000000000..36ab8d66e0a7 --- /dev/null +++ b/tidb-cloud/vector-search-integrate-with-sqlalchemy.md @@ -0,0 +1,185 @@ +--- +title: 将 TiDB Vector Search 与 SQLAlchemy 集成 +summary: 了解如何将 TiDB Vector Search 与 SQLAlchemy 集成以存储嵌入向量并执行语义搜索。 +--- + +# 将 TiDB Vector Search 与 SQLAlchemy 集成 + +本教程将指导你如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB Vector Search](/tidb-cloud/vector-search-overview.md) 交互,存储嵌入向量并执行向量搜索查询。 + +> **注意** +> +> TiDB Vector Search 仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 前提条件 + +完成本教程需要: + +- 安装 [Python 3.8 或更高版本](https://www.python.org/downloads/)。 +- 安装 [Git](https://git-scm.com/downloads)。 +- 一个 TiDB Cloud Serverless 集群。如果你还没有,请按照[创建 TiDB Cloud Serverless 集群](/tidb-cloud/create-tidb-cluster-serverless.md)的说明创建自己的 TiDB Cloud 集群。 + +## 运行示例应用 + +你可以按照以下步骤快速了解如何将 TiDB Vector Search 与 SQLAlchemy 集成。 + +### 步骤 1. 克隆代码仓库 + +将 `tidb-vector-python` 代码仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 步骤 2. 创建虚拟环境 + +为你的项目创建一个虚拟环境: + +```bash +cd tidb-vector-python/examples/orm-sqlalchemy-quickstart +python3 -m venv .venv +source .venv/bin/activate +``` + +### 步骤 3. 安装所需依赖 + +安装示例项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +或者,你可以为你的项目安装以下包: + +```bash +pip install pymysql python-dotenv sqlalchemy tidb-vector +``` + +### 步骤 4. 配置环境变量 + +1. 导航到 [**Clusters**](https://tidbcloud.com/project/clusters) 页面,然后点击目标集群的名称进入其概览页面。 + +2. 点击右上角的 **Connect**。将显示连接对话框。 + +3. 确保连接对话框中的配置与你的环境匹配。 + + - **Connection Type** 设置为 `Public`。 + - **Branch** 设置为 `main`。 + - **Connect With** 设置为 `SQLAlchemy`。 + - **Operating System** 与你的环境匹配。 + + > **提示:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 点击 **PyMySQL** 标签并复制连接字符串。 + + > **提示:** + > + > 如果你还没有设置密码,请点击 **Generate Password** 生成一个随机密码。 + +5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接字符串粘贴到其中。 + + 以下是 macOS 的示例: + + ```dotenv + TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + ``` + +### 步骤 5. 运行示例 + +```bash +python sqlalchemy-quickstart.py +``` + +示例输出: + +```text +Get 3-nearest neighbor documents: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog + - distance: 0.7327387580875756 + document: tree +Get documents within a certain distance: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog +``` + +## 示例代码片段 + +你可以参考以下示例代码片段来开发你的应用。 + +### 创建向量表 + +#### 连接到 TiDB 集群 + +```python +import os +import dotenv + +from sqlalchemy import Column, Integer, create_engine, Text +from sqlalchemy.orm import declarative_base, Session +from tidb_vector.sqlalchemy import VectorType + +dotenv.load_dotenv() + +tidb_connection_string = os.environ['TIDB_DATABASE_URL'] +engine = create_engine(tidb_connection_string) +``` + +#### 定义向量列 + +创建一个包含名为 `embedding` 的列的表,该列存储 3 维向量。 + +```python +Base = declarative_base() + +class Document(Base): + __tablename__ = 'sqlalchemy_demo_documents' + id = Column(Integer, primary_key=True) + content = Column(Text) + embedding = Column(VectorType(3)) +``` + +### 存储带有嵌入向量的文档 + +```python +with Session(engine) as session: + session.add(Document(content="dog", embedding=[1, 2, 1])) + session.add(Document(content="fish", embedding=[1, 2, 4])) + session.add(Document(content="tree", embedding=[1, 0, 0])) + session.commit() +``` + +### 搜索最近邻文档 + +搜索与查询向量 `[1, 2, 3]` 在语义上最接近的前 3 个文档,基于余弦距离函数。 + +```python +with Session(engine) as session: + distance = Document.embedding.cosine_distance([1, 2, 3]).label('distance') + results = session.query( + Document, distance + ).order_by(distance).limit(3).all() +``` + +### 搜索特定距离内的文档 + +搜索与查询向量 `[1, 2, 3]` 的余弦距离小于 0.2 的文档。 + +```python +with Session(engine) as session: + distance = Document.embedding.cosine_distance([1, 2, 3]).label('distance') + results = session.query( + Document, distance + ).filter(distance < 0.2).order_by(distance).limit(3).all() +``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/vector-search-index.md) diff --git a/tidb-cloud/vector-search-integration-overview.md b/tidb-cloud/vector-search-integration-overview.md new file mode 100644 index 000000000000..d26652d242e4 --- /dev/null +++ b/tidb-cloud/vector-search-integration-overview.md @@ -0,0 +1,77 @@ +--- +title: 向量搜索集成概述 +summary: TiDB 向量搜索集成的概述,包括支持的 AI 框架、嵌入模型和 ORM 库。 +--- + +# 向量搜索集成概述 + +本文提供 TiDB 向量搜索集成的概述,包括支持的 AI 框架、嵌入模型和对象关系映射(ORM)库。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## AI 框架 + +TiDB 官方支持以下 AI 框架,使你能够轻松地将基于这些框架开发的 AI 应用程序与 TiDB 向量搜索集成。 + +| AI 框架 | 教程 | +| ------------- | ------------------------------------------------------------------------------------------------- | +| Langchain | [将向量搜索与 LangChain 集成](/tidb-cloud/vector-search-integrate-with-langchain.md) | +| LlamaIndex | [将向量搜索与 LlamaIndex 集成](/tidb-cloud/vector-search-integrate-with-llamaindex.md) | + +此外,你还可以将 TiDB 用于各种用途,例如 AI 应用程序的文档存储和知识图谱存储。 + +## AI 服务 + +TiDB 向量搜索支持与以下 AI 服务集成,使你能够轻松构建基于检索增强生成(RAG)的应用程序。 + +- [Amazon Bedrock](/tidb-cloud/vector-search-integrate-with-amazon-bedrock.md) + +## 嵌入模型和服务 + +TiDB 向量搜索支持存储最多 16383 维的向量,可以容纳大多数嵌入模型。 + +你可以使用自部署的开源嵌入模型或第三方嵌入提供商提供的第三方嵌入 API 来生成向量。 + +下表列出了一些主流嵌入服务提供商及其相应的集成教程。 + +| 嵌入服务提供商 | 教程 | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| Jina AI | [将向量搜索与 Jina AI Embeddings API 集成](/tidb-cloud/vector-search-integrate-with-jinaai-embedding.md) | + +## 对象关系映射(ORM)库 + +你可以将 TiDB 向量搜索与你的 ORM 库集成,以与 TiDB 数据库交互。 + +下表列出了支持的 ORM 库及其相应的集成教程: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
语言ORM/客户端如何安装教程
PythonTiDB Vector Clientpip install tidb-vector[client]使用 Python 开始使用向量搜索
SQLAlchemypip install tidb-vector将 TiDB 向量搜索与 SQLAlchemy 集成
peeweepip install tidb-vector将 TiDB 向量搜索与 peewee 集成
Djangopip install django-tidb[vector]将 TiDB 向量搜索与 Django 集成
diff --git a/tidb-cloud/vector-search-limitations.md b/tidb-cloud/vector-search-limitations.md new file mode 100644 index 000000000000..36627e24c3f0 --- /dev/null +++ b/tidb-cloud/vector-search-limitations.md @@ -0,0 +1,42 @@ +--- +title: 向量搜索限制 +summary: 了解 TiDB 向量搜索的限制。 +--- + +# 向量搜索限制 + +本文介绍 TiDB 向量搜索的已知限制。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB Self-Managed(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 向量数据类型限制 + +- 每个[向量](/tidb-cloud/vector-search-data-types.md)最多支持 16383 维。 +- 向量数据类型不能存储 `NaN`、`Infinity` 或 `-Infinity` 值。 +- 向量数据类型不能存储双精度浮点数。如果你在向量列中插入或存储双精度浮点数,TiDB 会将它们转换为单精度浮点数。 +- 向量列不能用于主键、唯一索引或分区键。要加速向量搜索性能,请使用[向量搜索索引](/tidb-cloud/vector-search-index.md)。 +- 一个表可以有多个向量列。但是,[单个表中的列总数有限制](/tidb-limitations.md#limitations-on-a-single-table)。 +- 目前,TiDB 不支持删除带有向量索引的向量列。要删除这样的列,请先删除向量索引,然后再删除向量列。 +- 目前,TiDB 不支持将向量列修改为其他数据类型,如 `JSON` 和 `VARCHAR`。 + +## 向量索引限制 + +- 向量索引用于向量搜索。它不能加速其他查询,如范围查询或相等查询。因此,不能在非向量列上或多个向量列上创建向量索引。 +- 一个表可以有多个向量索引。但是,[单个表中的索引总数有限制](/tidb-limitations.md#limitations-on-a-single-table)。 +- 仅当使用不同的距离函数时,才允许在同一列上创建多个向量索引。 +- 目前,向量索引的距离函数仅支持 `VEC_COSINE_DISTANCE()` 和 `VEC_L2_DISTANCE()`。 +- 目前,TiDB 不支持删除带有向量索引的向量列。要删除这样的列,请先删除向量索引,然后再删除向量列。 +- 目前,TiDB 不支持将向量索引设置为[不可见](/sql-statements/sql-statement-alter-index.md)。 + +## 与 TiDB 工具的兼容性 + +- TiDB Cloud 控制台中的数据迁移功能不支持将 MySQL 9.0 向量数据类型迁移或复制到 TiDB Cloud。 + +## 反馈 + +我们重视你的反馈,随时为你提供帮助: + +- [加入我们的 Discord](https://discord.gg/zcqexutz2R) +- [访问我们的支持门户](https://tidb.support.pingcap.com/) diff --git a/tidb-cloud/vector-search-overview.md b/tidb-cloud/vector-search-overview.md new file mode 100644 index 000000000000..c6a64a7f5525 --- /dev/null +++ b/tidb-cloud/vector-search-overview.md @@ -0,0 +1,72 @@ +--- +title: 向量搜索(Beta)概述 +summary: 了解 TiDB 中的向量搜索。此功能提供了一个高级搜索解决方案,可以对文档、图像、音频和视频等各种数据类型执行语义相似度搜索。 +--- + +# 向量搜索(Beta)概述 + +TiDB 向量搜索(beta)提供了一个高级搜索解决方案,可以对文档、图像、音频和视频等各种数据类型执行语义相似度搜索。此功能使开发人员能够使用熟悉的 MySQL 技能轻松构建具有生成式人工智能(AI)功能的可扩展应用程序。 + +> **注意** +> +> TiDB 向量搜索仅适用于 TiDB 自管理版本(TiDB >= v8.4)和 [TiDB Cloud Serverless](/tidb-cloud/select-cluster-tier.md#tidb-cloud-serverless)。它不适用于 [TiDB Cloud Dedicated](/tidb-cloud/select-cluster-tier.md#tidb-cloud-dedicated)。 + +## 概念 + +向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。 + +与依赖精确关键词匹配和词频的传统全文搜索不同,向量搜索将各种数据类型(如文本、图像或音频)转换为高维向量,并基于这些向量之间的相似度进行查询。这种搜索方法捕获了数据的语义含义和上下文信息,从而更准确地理解用户意图。 + +即使搜索词与数据库中的内容不完全匹配,向量搜索仍然可以通过分析数据的语义来提供符合用户意图的结果。 + +例如,对"会游泳的动物"进行全文搜索只会返回包含这些确切关键词的结果。相比之下,向量搜索可以返回其他会游泳的动物的结果,如鱼或鸭子,即使这些结果不包含确切的关键词。 + +### 向量嵌入 + +向量嵌入(也称为嵌入)是一个数字序列,用于在高维空间中表示现实世界的对象。它捕获了非结构化数据(如文档、图像、音频和视频)的含义和上下文。 + +向量嵌入在机器学习中至关重要,是语义相似度搜索的基础。 + +TiDB 引入了[向量数据类型](/tidb-cloud/vector-search-data-types.md)和[向量搜索索引](/tidb-cloud/vector-search-index.md),专门用于优化向量嵌入的存储和检索,增强其在 AI 应用中的使用。你可以在 TiDB 中存储向量嵌入,并使用这些数据类型执行向量搜索查询以找到最相关的数据。 + +### 嵌入模型 + +嵌入模型是将数据转换为[向量嵌入](#向量嵌入)的算法。 + +选择合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化文本数据,你可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 + +要了解如何为特定数据类型生成向量嵌入,请参考嵌入模型的集成教程或示例。 + +## 向量搜索的工作原理 + +将原始数据转换为向量嵌入并存储在 TiDB 中后,你的应用程序可以执行向量搜索查询,以找到与用户查询在语义或上下文上最相关的数据。 + +TiDB 向量搜索通过使用[距离函数](/tidb-cloud/vector-search-functions-and-operators.md)计算给定向量与数据库中存储的向量之间的距离来识别 top-k 最近邻(KNN)向量。在查询中与给定向量最接近的向量代表含义上最相似的数据。 + +![TiDB 向量搜索示意图](/media/vector-search/embedding-search.png) + +作为具有集成向量搜索功能的关系数据库,TiDB 使你能够在一个数据库中同时存储数据及其对应的向量表示(即向量嵌入)。你可以选择以下任一方式进行存储: + +- 在同一个表的不同列中存储数据及其对应的向量表示。 +- 在不同的表中存储数据及其对应的向量表示。这种方式下,在检索数据时需要使用 `JOIN` 查询来组合表。 + +## 使用场景 + +### 检索增强生成(RAG) + +检索增强生成(Retrieval-Augmented Generation,RAG)是一种旨在优化大型语言模型(LLM)输出的架构。通过使用向量搜索,RAG 应用程序可以在数据库中存储向量嵌入,并在 LLM 生成响应时检索相关文档作为额外上下文,从而提高答案的质量和相关性。 + +### 语义搜索 + +语义搜索是一种基于查询含义而不是简单匹配关键词来返回结果的搜索技术。它使用嵌入来解释跨不同语言和各种类型数据(如文本、图像和音频)的含义。然后,向量搜索算法使用这些嵌入来找到最符合用户查询的相关数据。 + +### 推荐引擎 + +推荐引擎是一个主动向用户推荐相关和个性化内容、产品或服务的系统。它通过创建表示用户行为和偏好的嵌入来实现这一目标。这些嵌入帮助系统识别其他用户已经交互或表现出兴趣的相似项目。这增加了推荐内容对用户既相关又有吸引力的可能性。 + +## 另请参阅 + +要开始使用 TiDB 向量搜索,请参阅以下文档: + +- [使用 Python 开始向量搜索](/tidb-cloud/vector-search-get-started-using-python.md) +- [使用 SQL 开始向量搜索](/tidb-cloud/vector-search-get-started-using-sql.md) diff --git a/tidb-computing.md b/tidb-computing.md index 4b10ac5017ab..ddf72182a938 100644 --- a/tidb-computing.md +++ b/tidb-computing.md @@ -1,60 +1,60 @@ --- -title: TiDB 数据库的计算 +title: TiDB 计算层 summary: 了解 TiDB 数据库的计算层。 --- -# TiDB 数据库的计算 +# TiDB 计算层 -TiDB 在 TiKV 提供的分布式存储能力基础上,构建了兼具优异的交易处理能力与良好的数据分析能力的计算引擎。本文首先从数据映射算法入手介绍 TiDB 如何将库表中的数据映射到 TiKV 中的 (Key, Value) 键值对,然后描述 TiDB 元信息管理方式,最后介绍 TiDB SQL 层的主要架构。 +基于 TiKV 提供的分布式存储,TiDB 构建了一个兼具事务处理和数据分析能力的计算引擎。本文首先介绍一个将 TiDB 数据库表中的数据映射到 TiKV 中的键值对(Key, Value)的数据映射算法,然后介绍 TiDB 如何管理元数据,最后说明 TiDB SQL 层的架构。 -对于计算层依赖的存储方案,本文只介绍基于 TiKV 的行存储结构。针对分析型业务的特点,TiDB 推出了作为 TiKV 扩展的列存储方案 [TiFlash](/tiflash/tiflash-overview.md)。 +对于计算层所依赖的存储方案,本文仅介绍 TiKV 的行式存储结构。对于 OLAP 服务,TiDB 引入了列式存储方案 [TiFlash](/tiflash/tiflash-overview.md) 作为 TiKV 的扩展。 -## 表数据与 Key-Value 的映射关系 +## 将表数据映射到键值对 -本小节介绍 TiDB 中数据到 (Key, Value) 键值对的映射方案。这里的数据主要包括以下两个方面: +本节描述 TiDB 中将数据映射到键值对(Key, Value)的方案。需要映射的数据包括以下两类: -- 表中每一行的数据,以下简称表数据 -- 表中所有索引的数据,以下简称索引数据 +- 表中每一行的数据,以下简称表数据。 +- 表中所有索引的数据,以下简称索引数据。 -### 表数据与 Key-Value 的映射关系 +### 表数据到键值对的映射 -在关系型数据库中,一个表可能有很多列。要将一行中各列数据映射成一个 (Key, Value) 键值对,需要考虑如何构造 Key。首先,OLTP 场景下有大量针对单行或者多行的增、删、改、查等操作,要求数据库具备快速读取一行数据的能力。因此,对应的 Key 最好有一个唯一 ID(显示或隐式的 ID),以方便快速定位。其次,很多 OLAP 型查询需要进行全表扫描。如果能够将一个表中所有行的 Key 编码到一个区间内,就可以通过范围查询高效完成全表扫描的任务。 +在关系型数据库中,一张表可能有很多列。要将一行中每列的数据映射到键值对(Key, Value),需要考虑如何构造 Key。首先,在 OLTP 场景中,有很多对单行或多行数据进行增删改查的操作,这需要数据库能够快速读取一行数据。因此,每个键都应该有一个唯一的 ID(显式或隐式)以便快速定位。其次,许多 OLAP 查询需要全表扫描。如果能将表中所有行的键编码到一个范围内,就可以通过范围查询高效地扫描整个表。 -基于上述考虑,TiDB 中的表数据与 Key-Value 的映射关系作了如下设计: +基于上述考虑,TiDB 中表数据到键值对的映射设计如下: -- 为了保证同一个表的数据放在一起,方便查找,TiDB 会为每个表分配一个表 ID,用 `TableID` 表示。表 ID 是一个整数,在整个集群内唯一。 -- TiDB 会为表中每行数据分配一个行 ID,用 `RowID` 表示。行 ID 也是一个整数,在表内唯一。对于行 ID,TiDB 做了一个小优化,如果某个表有整数型的主键,TiDB 会使用主键的值当做这一行数据的行 ID。 +- 为确保同一个表的数据保持在一起便于查找,TiDB 为每个表分配一个表 ID,用 `TableID` 表示。表 ID 是一个整数,在整个集群中唯一。 +- TiDB 为表中的每一行数据分配一个行 ID,用 `RowID` 表示。行 ID 也是一个整数,在表内唯一。对于行 ID,TiDB 做了一个小优化:如果表有整数类型的主键,TiDB 会使用这个主键的值作为行 ID。 -每行数据按照如下规则编码成 (Key, Value) 键值对: +每一行数据按照以下规则编码为一个键值对(Key, Value): ``` Key: tablePrefix{TableID}_recordPrefixSep{RowID} Value: [col1, col2, col3, col4] ``` -其中 `tablePrefix` 和 `recordPrefixSep` 都是特定的字符串常量,用于在 Key 空间内区分其他数据。其具体值在后面的小结中给出。 +`tablePrefix` 和 `recordPrefixSep` 都是特殊的字符串常量,用于区分键空间中的其他数据。字符串常量的具体值在[映射关系总结](#映射关系总结)中介绍。 -### 索引数据和 Key-Value 的映射关系 +### 索引数据到键值对的映射 -TiDB 同时支持主键和二级索引(包括唯一索引和非唯一索引)。与表数据映射方案类似,TiDB 为表中每个索引分配了一个索引 ID,用 `IndexID` 表示。 +TiDB 支持主键和二级索引(包括唯一索引和非唯一索引)。类似于表数据映射方案,TiDB 为表的每个索引分配一个索引 ID,用 `IndexID` 表示。 -对于主键和唯一索引,需要根据键值快速定位到对应的 RowID,因此,按照如下规则编码成 (Key, Value) 键值对: +对于主键和唯一索引,需要根据键值对快速定位对应的 `RowID`,所以这样的键值对按以下方式编码: ``` Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue Value: RowID ``` -对于不需要满足唯一性约束的普通二级索引,一个键值可能对应多行,需要根据键值范围查询对应的 RowID。因此,按照如下规则编码成 (Key, Value) 键值对: +对于不需要满足唯一性约束的普通二级索引,一个键可能对应多行。需要根据键的范围查询对应的 `RowID`。因此,键值对必须按照以下规则编码: ``` Key: tablePrefix{TableID}_indexPrefixSep{IndexID}_indexedColumnsValue_{RowID} Value: null ``` -### 映射关系小结 +### 映射关系总结 -上述所有编码规则中的 `tablePrefix`、`recordPrefixSep` 和 `indexPrefixSep` 都是字符串常量,用于在 Key 空间内区分其他数据,定义如下: +上述所有编码规则中的 `tablePrefix`、`recordPrefixSep` 和 `indexPrefixSep` 都是用于区分键空间中其他数据的字符串常量,定义如下: ``` tablePrefix = []byte{'t'} @@ -62,24 +62,24 @@ recordPrefixSep = []byte{'r'} indexPrefixSep = []byte{'i'} ``` -另外请注意,上述方案中,无论是表数据还是索引数据的 Key 编码方案,一个表内所有的行都有相同的 Key 前缀,一个索引的所有数据也都有相同的前缀。这样具有相同的前缀的数据,在 TiKV 的 Key 空间内,是排列在一起的。因此只要小心地设计后缀部分的编码方案,保证编码前和编码后的比较关系不变,就可以将表数据或者索引数据有序地保存在 TiKV 中。采用这种编码后,一个表的所有行数据会按照 `RowID` 顺序地排列在 TiKV 的 Key 空间中,某一个索引的数据也会按照索引数据的具体的值(编码方案中的 `indexedColumnsValue`)顺序地排列在 Key 空间内。 +还需要注意的是,在上述编码方案中,无论是表数据还是索引数据的键编码方案,同一个表中的所有行都有相同的键前缀,一个索引的所有数据也有相同的前缀。具有相同前缀的数据在 TiKV 的键空间中被安排在一起。因此,通过仔细设计后缀部分的编码方案,确保编码前后的比较保持一致,表数据或索引数据就可以有序地存储在 TiKV 中。使用这种编码方案,表中的所有行数据在 TiKV 的键空间中按 `RowID` 有序排列,特定索引的数据也根据索引数据的具体值(`indexedColumnsValue`)在键空间中顺序排列。 -### Key-Value 映射关系示例 +### 键值对映射关系示例 -最后通过一个简单的例子,来理解 TiDB 的 Key-Value 映射关系。假设 TiDB 中有如下这个表: +本节通过一个简单的例子帮助你理解 TiDB 的键值对映射关系。假设 TiDB 中存在以下表: ```sql CREATE TABLE User ( - ID int, - Name varchar(20), - Role varchar(20), - Age int, - PRIMARY KEY (ID), - KEY idxAge (Age) + ID int, + Name varchar(20), + Role varchar(20), + Age int, + PRIMARY KEY (ID), + KEY idxAge (Age) ); ``` -假设该表中有 3 行数据: +假设表中有 3 行数据: ``` 1, "TiDB", "SQL Layer", 10 @@ -87,15 +87,15 @@ CREATE TABLE User ( 3, "PD", "Manager", 30 ``` -首先每行数据都会映射为一个 (Key, Value) 键值对,同时该表有一个 `int` 类型的主键,所以 `RowID` 的值即为该主键的值。假设该表的 `TableID` 为 10,则其存储在 TiKV 上的表数据为: +每行数据被映射为一个键值对(Key, Value),而且表有一个 `int` 类型的主键,所以 `RowID` 的值就是这个主键的值。假设表的 `TableID` 是 `10`,那么它在 TiKV 中存储的表数据是: ``` -t10_r1 --> ["TiDB", "SQL Layer", 10] -t10_r2 --> ["TiKV", "KV Engine", 20] -t10_r3 --> ["PD", "Manager", 30] +t10_r1 --> ["TiDB", "SQL Layer", 10] +t10_r2 --> ["TiKV", "KV Engine", 20] +t10_r3 --> ["PD", " Manager", 30] ``` -除了主键外,该表还有一个非唯一的普通二级索引 `idxAge`,假设这个索引的 `IndexID` 为 1,则其存储在 TiKV 上的索引数据为: +除了主键外,表还有一个非唯一的普通二级索引 `idxAge`。假设 `IndexID` 是 `1`,那么它在 TiKV 中存储的索引数据是: ``` t10_i1_10_1 --> null @@ -103,55 +103,55 @@ t10_i1_20_2 --> null t10_i1_30_3 --> null ``` -以上例子展示了 TiDB 中关系模型到 Key-Value 模型的映射规则,以及选择该方案背后的考量。 +上述示例展示了 TiDB 中从关系模型到键值模型的映射规则,以及这种映射方案背后的考虑。 -## 元信息管理 +## 元数据管理 -TiDB 中每个 `Database` 和 `Table` 都有元信息,也就是其定义以及各项属性。这些信息也需要持久化,TiDB 将这些信息也存储在了 TiKV 中。 +TiDB 中的每个数据库和表都有元数据,指示其定义和各种属性。这些信息也需要持久化,TiDB 同样将这些信息存储在 TiKV 中。 -每个 `Database`/`Table` 都被分配了一个唯一的 ID,这个 ID 作为唯一标识,并且在编码为 Key-Value 时,这个 ID 都会编码到 Key 中,再加上 `m_` 前缀。这样可以构造出一个 Key,Value 中存储的是序列化后的元信息。 +每个数据库或表都被分配一个唯一的 ID。作为唯一标识符,当表数据编码为键值对时,这个 ID 会与 `m_` 前缀一起编码到 Key 中。这样构造一个键值对,其中存储序列化的元数据。 -除此之外,TiDB 还用一个专门的 (Key, Value) 键值对存储当前所有表结构信息的最新版本号。这个键值对是全局的,每次 DDL 操作的状态改变时其版本号都会加 1。目前,TiDB 把这个键值对持久化存储在 PD Server 中,其 Key 是 "/tidb/ddl/global_schema_version",Value 是类型为 int64 的版本号值。TiDB 采用 Online Schema 变更算法,有一个后台线程在不断地检查 PD Server 中存储的表结构信息的版本号是否发生变化,并且保证在一定时间内一定能够获取版本的变化。 +此外,TiDB 还使用一个专门的键值对(Key, Value)来存储所有表的结构信息的最新版本号。这个键值对是全局的,每次 DDL 操作状态发生变化时,其版本号就会增加 `1`。TiDB 将这个键值对持久化存储在 PD 服务器中,键为 `/tidb/ddl/global_schema_version`,Value 是 `int64` 类型的版本号值。同时,因为 TiDB 在线应用架构变更,它会保持一个后台线程不断检查存储在 PD 服务器中的表结构信息版本号是否发生变化。这个线程还确保能在一定时间内获取到版本的变化。 -## SQL 层简介 +## SQL 层概述 -TiDB 的 SQL 层,即 TiDB Server,负责将 SQL 翻译成 Key-Value 操作,将其转发给共用的分布式 Key-Value 存储层 TiKV,然后组装 TiKV 返回的结果,最终将查询结果返回给客户端。 +TiDB 的 SQL 层,即 TiDB Server,将 SQL 语句转换为键值对操作,将这些操作转发到分布式键值存储层 TiKV,组装 TiKV 返回的结果,最后将查询结果返回给客户端。 -这一层的节点都是无状态的,节点本身并不存储数据,节点之间完全对等。 +这一层的节点是无状态的。这些节点本身不存储数据,而且完全等价。 -### SQL 运算 +### SQL 计算 -最简单的方案就是通过上一节所述的[表数据与 Key-Value 的映射关系](#表数据与-key-value-的映射关系)方案,将 SQL 查询映射为对 KV 的查询,再通过 KV 接口获取对应的数据,最后执行各种计算。 +SQL 计算最简单的解决方案是前面章节描述的[表数据到键值对的映射](#表数据到键值对的映射),它将 SQL 查询映射到 KV 查询,通过 KV 接口获取相应的数据,并执行各种计算。 -比如 `select count(*) from user where name = "TiDB"` 这样一个 SQL 语句,它需要读取表中所有的数据,然后检查 `name` 字段是否是 `TiDB`,如果是的话,则返回这一行。具体流程如下: +例如,要执行 `select count(*) from user where name = "TiDB"` SQL 语句,TiDB 需要读取表中的所有数据,然后检查 `name` 字段是否为 `TiDB`,如果是,则返回这一行。过程如下: -1. 构造出 Key Range:一个表中所有的 `RowID` 都在 `[0, MaxInt64)` 这个范围内,使用 `0` 和 `MaxInt64` 根据行数据的 `Key` 编码规则,就能构造出一个 `[StartKey, EndKey)`的左闭右开区间。 -2. 扫描 Key Range:根据上面构造出的 Key Range,读取 TiKV 中的数据。 -3. 过滤数据:对于读到的每一行数据,计算 `name = "TiDB"` 这个表达式,如果为真,则向上返回这一行,否则丢弃这一行数据。 -4. 计算 `Count(*)`:对符合要求的每一行,累计到 `Count(*)` 的结果上面。 +1. 构造键范围:表中所有的 `RowID` 都在 `[0, MaxInt64)` 范围内。根据行数据 `Key` 编码规则,使用 `0` 和 `MaxInt64` 可以构造一个左闭右开的 `[StartKey, EndKey)` 范围。 +2. 扫描键范围:根据上面构造的键范围读取 TiKV 中的数据。 +3. 过滤数据:对于读取的每一行数据,计算 `name = "TiDB"` 表达式。如果结果为 `true`,返回这一行。如果不是,跳过这一行。 +4. 计算 `Count(*)`:对于每一行满足要求的数据,累加到 `Count(*)` 的结果中。 -**整个流程示意图如下:** +**整个过程如下图所示:** ![naive sql flow](/media/tidb-computing-native-sql-flow.jpeg) -这个方案是直观且可行的,但是在分布式数据库的场景下有一些显而易见的问题: +这个解决方案直观且可行,但在分布式数据库场景中有一些明显的问题: -- 在扫描数据的时候,每一行都要通过 KV 操作从 TiKV 中读取出来,至少有一次 RPC 开销,如果需要扫描的数据很多,那么这个开销会非常大。 -- 并不是所有的行都满足过滤条件 `name = "TiDB"`,如果不满足条件,其实可以不读取出来。 -- 此查询只要求返回符合要求行的数量,不要求返回这些行的值。 +- 在扫描数据时,每一行都通过 KV 操作从 TiKV 读取,至少有一次 RPC 开销,如果需要扫描的数据量很大,开销可能会很高。 +- 不适用于所有行。不满足条件的数据不需要读取。 +- 从这个查询的返回结果来看,只需要满足要求的行数,而不需要这些行的值。 -### 分布式 SQL 运算 +### 分布式 SQL 操作 -为了解决上述问题,计算应该需要尽量靠近存储节点,以避免大量的 RPC 调用。首先,SQL 中的谓词条件 `name = "TiDB"` 应被下推到存储节点进行计算,这样只需要返回有效的行,避免无意义的网络传输。然后,聚合函数 `Count(*)` 也可以被下推到存储节点,进行预聚合,每个节点只需要返回一个 `Count(*)` 的结果即可,再由 SQL 层将各个节点返回的 `Count(*)` 的结果累加求和。 +为了解决上述问题,计算应该尽可能靠近存储节点,以避免大量的 RPC 调用。首先,SQL 谓词条件 `name = "TiDB"` 应该下推到存储节点进行计算,这样只返回有效的行,避免无意义的网络传输。然后,聚合函数 `Count(*)` 也可以下推到存储节点进行预聚合,每个节点只需要返回一个 `Count(*)` 结果。SQL 层将汇总每个节点返回的 `Count(*)` 结果。 -以下是数据逐层返回的示意图: +下图显示了数据如何逐层返回: ![dist sql flow](/media/tidb-computing-dist-sql-flow.png) ### SQL 层架构 -通过上面的例子,希望大家对 SQL 语句的处理有一个基本的了解。实际上 TiDB 的 SQL 层要复杂得多,模块以及层次非常多,下图列出了重要的模块以及调用关系: +前面几节介绍了 SQL 层的一些功能,希望你对 SQL 语句的处理方式有了基本的了解。实际上,TiDB 的 SQL 层要复杂得多,有许多模块和层次。下图列出了重要的模块和调用关系: ![tidb sql layer](/media/tidb-computing-tidb-sql-layer.png) -用户的 SQL 请求会直接或者通过 `Load Balancer` 发送到 TiDB Server,TiDB Server 会解析 `MySQL Protocol Packet`,获取请求内容,对 SQL 进行语法解析和语义分析,制定和优化查询计划,执行查询计划并获取和处理数据。数据全部存储在 TiKV 集群中,所以在这个过程中 TiDB Server 需要和 TiKV 交互,获取数据。最后 TiDB Server 需要将查询结果返回给用户。 +用户的 SQL 请求直接或通过 `Load Balancer` 发送到 TiDB Server。TiDB Server 将解析 `MySQL Protocol Packet`,获取请求内容,对 SQL 请求进行语法和语义解析,制定和优化查询计划,执行查询计划,获取和处理数据。所有数据都存储在 TiKV 集群中,所以在这个过程中,TiDB Server 需要与 TiKV 交互并获取数据。最后,TiDB Server 需要将查询结果返回给用户。 diff --git a/tidb-distributed-execution-framework.md b/tidb-distributed-execution-framework.md index 5f09d8105d02..b0e9f9c606c8 100644 --- a/tidb-distributed-execution-framework.md +++ b/tidb-distributed-execution-framework.md @@ -1,105 +1,131 @@ --- -title: TiDB 分布式执行框架 -summary: 了解 TiDB 分布式执行框架的使用场景、限制、使用方法和实现原理。 +title: TiDB 分布式执行框架 (DXF) +summary: 了解 TiDB 分布式执行框架 (DXF) 的使用场景、限制、使用方法和实现原理。 --- -# TiDB 分布式执行框架 +# TiDB 分布式执行框架 (DXF) -TiDB 采用计算存储分离架构,具有出色的扩展性和弹性的扩缩容能力。从 v7.1.0 开始,TiDB 引入了一个分布式执行框架,以进一步发挥分布式架构的资源优势。该框架的目标是对基于该框架的任务进行统一调度与分布式执行,并提供整体和单个任务两个维度的资源管理能力,更好地满足用户对于资源使用的预期。 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 -本文档介绍了 TiDB 分布式执行框架的使用场景、限制、使用方法和实现原理。 +TiDB 采用计算存储分离架构,具有出色的可扩展性和弹性。从 v7.1.0 开始,TiDB 引入了**分布式执行框架(Distributed eXecution Framework,DXF)**,以进一步利用分布式架构的资源优势。DXF 的目标是实现任务的统一调度和分布式执行,并为整体和单个任务提供统一的资源管理能力,更好地满足用户对资源使用的期望。 + +本文档描述了 DXF 的使用场景、限制、使用方法和实现原理。 ## 使用场景 -在数据库中,除了核心的事务型负载任务 (TP) 和分析型查询任务 (AP),也存在着其他重要任务,如 DDL 语句、[`IMPORT INTO`](/sql-statements/sql-statement-import-into.md)、[TTL](/time-to-live.md)、[`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) 和 Backup/Restore 等。这些任务需要处理数据库对象(表)中的大量数据,通常具有如下特点: +在数据库管理系统中,除了核心的事务处理(TP)和分析处理(AP)工作负载外,还有其他重要任务,如 DDL 操作、[`IMPORT INTO`](/sql-statements/sql-statement-import-into.md)、[TTL](/time-to-live.md)、[`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) 和备份/恢复。这些任务需要处理数据库对象(表)中的大量数据,因此通常具有以下特点: -- 需要处理一个 schema 或者一个数据库对象(表)中的所有数据。 -- 可能需要周期执行,但频率较低。 -- 如果资源控制不当,容易对事务型任务和分析型任务造成影响,影响数据库的服务质量。 +- 需要处理 schema 或数据库对象(表)中的所有数据。 +- 可能需要定期执行,但频率较低。 +- 如果资源控制不当,容易影响 TP 和 AP 任务,降低数据库服务质量。 -启用 TiDB 分布式执行框架能够解决上述问题,并且具有以下三个优势: +启用 DXF 可以解决上述问题,并具有以下三个优势: -- 提供高扩展性、高可用性和高性能的统一能力支持。 -- 支持任务分布式执行,可以在整个 TiDB 集群可用的计算资源范围内进行灵活的调度,从而更好地利用 TiDB 集群内的计算资源。 -- 提供统一的资源使用和管理能力,从整体和单个任务两个维度提供资源管理的能力。 +- 框架提供统一的高可扩展性、高可用性和高性能能力。 +- DXF 支持任务的分布式执行,可以灵活调度整个 TiDB 集群的可用计算资源,从而更好地利用 TiDB 集群中的计算资源。 +- DXF 为整体和单个任务提供统一的资源使用和管理能力。 -目前,分布式执行框架支持分布式执行 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 和 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 这两类任务。 +目前,DXF 支持 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 和 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 语句的分布式执行。 -- [`ADD INDEX`](/sql-statements/sql-statement-add-index.md),即 DDL 创建索引的场景。例如以下 SQL 语句: +- [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 是用于创建索引的 DDL 语句。例如: ```sql ALTER TABLE t1 ADD INDEX idx1(c1); CREATE INDEX idx1 ON table t1(c1); ``` -- [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 即通过该 SQL 语句将 CSV、SQL、PARQUET 等格式的数据导入到一张空表中。 +- [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 用于将 CSV、SQL 和 Parquet 等格式的数据导入空表。 + +## 限制 -## 使用限制 +DXF 最多只能同时调度 16 个任务(包括 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 任务和 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 任务)。 -分布式执行框架最多同时调度 16 个任务(包括 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 和 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md))。 +## 前提条件 -## 启用前提 +在使用 DXF 执行 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 任务之前,你需要启用[快速在线 DDL](/system-variables.md#tidb_ddl_enable_fast_reorg-new-in-v630) 模式。 -如需使用分布式执行框架执行 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 任务,需要先开启 [Fast Online DDL](/system-variables.md#tidb_ddl_enable_fast_reorg-从-v630-版本开始引入) 模式。 + -1. 调整 Fast Online DDL 相关的系统变量: +1. 调整以下与快速在线 DDL 相关的系统变量: - * [`tidb_ddl_enable_fast_reorg`](/system-variables.md#tidb_ddl_enable_fast_reorg-从-v630-版本开始引入):从 TiDB v6.5.0 开始默认打开,用于启用快速模式。 - * [`tidb_ddl_disk_quota`](/system-variables.md#tidb_ddl_disk_quota-从-v630-版本开始引入):用于控制快速模式可使用的本地磁盘最大配额。 + * [`tidb_ddl_enable_fast_reorg`](/system-variables.md#tidb_ddl_enable_fast_reorg-new-in-v630):用于启用快速在线 DDL 模式。从 TiDB v6.5.0 开始默认启用。 + * [`tidb_ddl_disk_quota`](/system-variables.md#tidb_ddl_disk_quota-new-in-v630):用于控制快速在线 DDL 模式下可以使用的本地磁盘最大配额。 -2. 调整 Fast Online DDL 相关的配置项: +2. 调整以下与快速在线 DDL 相关的配置项: - * [`temp-dir`](/tidb-configuration-file.md#temp-dir-从-v630-版本开始引入):指定快速模式能够使用的本地盘路径。 + * [`temp-dir`](/tidb-configuration-file.md#temp-dir-new-in-v630):指定快速在线 DDL 模式下可以使用的本地磁盘路径。 > **注意:** > -> 建议 TiDB 的 `temp-dir` 目录至少有 100 GiB 的可用空间。 +> 建议为 TiDB `temp-dir` 目录准备至少 100 GiB 的可用空间。 + + + + + +调整以下与快速在线 DDL 相关的系统变量: -## 启用步骤 +* [`tidb_ddl_enable_fast_reorg`](/system-variables.md#tidb_ddl_enable_fast_reorg-new-in-v630):用于启用快速在线 DDL 模式。从 TiDB v6.5.0 开始默认启用。 +* [`tidb_ddl_disk_quota`](/system-variables.md#tidb_ddl_disk_quota-new-in-v630):用于控制快速在线 DDL 模式下可以使用的本地磁盘最大配额。 -1. 启用分布式执行框架,只需将 [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-从-v710-版本开始引入) 设置为 `ON`。该变量从 v8.1.0 起默认开启,对于新建的 v8.1.0 或更高版本集群,可以跳过此步骤。 + + +## 使用方法 + +1. 要启用 DXF,请将 [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-new-in-v710) 的值设置为 `ON`。从 v8.1.0 开始,此变量默认启用。对于 v8.1.0 或更高版本的新创建集群,你可以跳过此步骤。 ```sql SET GLOBAL tidb_enable_dist_task = ON; ``` - 在运行任务时,框架支持的语句(如 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 和 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md))会采用分布式方式执行。默认集群内部所有节点均会执行任务。 + 当 DXF 任务运行时,框架支持的语句(如 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 和 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md))以分布式方式执行。默认情况下,所有 TiDB 节点都运行 DXF 任务。 -2. 一般情况下,对于下列影响 DDL 任务分布式执行的系统变量,使用其默认值即可。 +2. 通常,对于可能影响 DDL 任务分布式执行的以下系统变量,建议使用其默认值: - * [`tidb_ddl_reorg_worker_cnt`](/system-variables.md#tidb_ddl_reorg_worker_cnt):使用默认值 `4` 即可,建议最大不超过 `16`。 + * [`tidb_ddl_reorg_worker_cnt`](/system-variables.md#tidb_ddl_reorg_worker_cnt):使用默认值 `4`。建议的最大值是 `16`。 * [`tidb_ddl_reorg_priority`](/system-variables.md#tidb_ddl_reorg_priority) * [`tidb_ddl_error_count_limit`](/system-variables.md#tidb_ddl_error_count_limit) - * [`tidb_ddl_reorg_batch_size`](/system-variables.md#tidb_ddl_reorg_batch_size):使用默认值即可,建议最大不超过 `1024`。 + * [`tidb_ddl_reorg_batch_size`](/system-variables.md#tidb_ddl_reorg_batch_size):使用默认值。建议的最大值是 `1024`。 ## 任务调度 -默认情况下,分布式执行框架将会调度所有 TiDB 节点执行分布式任务。从 v7.4.0 起,你可以通过设置 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入) 来控制分布式执行框架将会调度哪些 TiDB 节点执行分布式任务。 +默认情况下,DXF 调度所有 TiDB 节点执行分布式任务。从 v7.4.0 开始,对于 TiDB 自管理集群,你可以通过配置 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 来控制哪些 TiDB 节点可以被 DXF 调度执行分布式任务。 -- 在 v7.4.0 到 v8.0.0 及其之间的版本中,[`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入) 的可选值为 `''` 或 `background`。如果当前集群存在 `tidb_service_scope = 'background'` 的 TiDB 节点,分布式执行框架会将该任务调度到 `tidb_service_scope = 'background'` 的节点上运行。如果当前集群不存在 `tidb_service_scope = 'background'` 的节点,无论是因为故障还是正常的缩容,分布式执行框架会将任务调度到 `tidb_service_scope = ''` 的节点上运行。 +- 对于 v7.4.0 到 v8.0.0 的版本,[`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 的可选值为 `''` 或 `background`。如果当前集群有 `tidb_service_scope = 'background'` 的 TiDB 节点,DXF 会将任务调度到这些节点执行。如果当前集群没有 `tidb_service_scope = 'background'` 的 TiDB 节点(无论是由于故障还是正常缩容),DXF 会将任务调度到 `tidb_service_scope = ''` 的节点执行。 -- 从 v8.1.0 起,[`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入) 可设置为任意合法值。当提交分布式任务时,该任务会绑定当前连接的 TiDB 节点的 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入) 值,分布式执行框架只会将该任务调度到具有相同 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入) 值的 TiDB 节点上运行。但是,为了兼容之前版本的配置,如果分布式任务是在 `tidb_service_scope = ''` 的节点上提交的,且当前集群存在 `tidb_service_scope = 'background'` 的节点,分布式执行框架会将该任务调度到 `tidb_service_scope = 'background'` 的 TiDB 节点上运行。 +- 从 v8.1.0 开始,你可以将 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 设置为任何有效值。当提交分布式任务时,任务会绑定到当前连接的 TiDB 节点的 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 值,DXF 只会将任务调度到具有相同 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 值的 TiDB 节点执行。但是,为了与早期版本的配置兼容,如果在 `tidb_service_scope = ''` 的节点上提交分布式任务,且当前集群有 `tidb_service_scope = 'background'` 的 TiDB 节点,DXF 会将任务调度到 `tidb_service_scope = 'background'` 的 TiDB 节点执行。 -从 v8.1.0 起,如果在任务运行过程中扩容新节点,分布式执行框架会根据上述规则决定是否将任务调度到新的节点来执行。如果不希望新扩容的节点运行任务,建议提前为这些节点设置 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入),取值要和已经在运行分布式任务的 TiDB 节点不同。 +从 v8.1.0 开始,如果在任务执行期间添加了新节点,DXF 会根据上述规则决定是否将任务调度到新节点执行。如果你不希望新添加的节点执行任务,建议提前为这些新添加的节点设置不同的 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740)。 > **注意:** > -> - 在 v7.4.0 到 v8.0.0 及其之间的版本中,对于包含多个 TiDB 节点的集群,强烈建议选择两个或更多的 TiDB 节点将 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入) 设置为 `background`。若仅在单个 TiDB 节点上设置此变量,当该节点发生重启或故障时,任务会被重新调度到 `tidb_service_scope = ''` 的 TiDB 节点,会对这些 TiDB 节点的业务产生影响。 -> - 在分布式任务执行过程中,修改 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入) 的配置不会对当前任务生效,会从下次任务开始生效。 +> - 对于 v7.4.0 到 v8.0.0 的版本,在具有多个 TiDB 节点的集群中,强烈建议在两个或更多 TiDB 节点上将 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 设置为 `background`。如果此变量仅在单个 TiDB 节点上设置,当该节点重启或故障时,任务将被重新调度到 `tidb_service_scope = ''` 的 TiDB 节点,这会影响在这些 TiDB 节点上运行的应用程序。 +> - 在分布式任务执行期间,对 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 配置的更改不会对当前任务生效,但会从下一个任务开始生效。 ## 实现原理 -TiDB 分布式执行框架的架构图如下: +DXF 的架构如下: -![分布式执行框架的架构](/media/dist-task/dist-task-architect.jpg) +![DXF 的架构](/media/dist-task/dist-task-architect.jpg) -根据上图,分布式执行框架中任务的执行主要由以下模块负责: +如上图所示,DXF 中的任务执行主要由以下模块处理: -- Dispatcher:负责生成每个任务的分布式执行计划,管理执行过程,转换任务状态以及收集和反馈运行时任务信息等。 -- Scheduler:以 TiDB 节点为单位来同步分布式任务的执行,提高执行效率。 -- Subtask Executor:是实际的分布式子任务执行者,并将子任务的执行情况返回给 Scheduler,由 Scheduler 统一更新子任务的执行状态。 -- 资源池:通过对上述各种模块中计算资源进行池化,提供量化资源的使用与管理的基础。 +- Dispatcher:为每个任务生成分布式执行计划,管理执行过程,转换任务状态,收集和反馈运行时任务信息。 +- Scheduler:在 TiDB 节点之间复制分布式任务的执行,以提高任务执行效率。 +- Subtask Executor:分布式子任务的实际执行器。此外,Subtask Executor 将子任务的执行状态返回给 Scheduler,Scheduler 统一更新子任务的执行状态。 +- 资源池:通过池化上述模块的计算资源,为资源使用和管理的量化提供基础。 ## 另请参阅 -* [DDL 执行原理及最佳实践](/ddl-introduction.md) + + +* [DDL 语句的执行原理和最佳实践](/ddl-introduction.md) + + + + +* [DDL 语句的执行原理和最佳实践](https://docs.pingcap.com/tidb/stable/ddl-introduction) + + diff --git a/tidb-external-ts.md b/tidb-external-ts.md index 060ca67c9b27..763b4f01b0e0 100644 --- a/tidb-external-ts.md +++ b/tidb-external-ts.md @@ -1,29 +1,29 @@ --- -title: 通过系统变量 `tidb_external_ts` 读取历史数据 -summary: 了解如何通过系统变量 `tidb_external_ts` 读取历史数据。 +title: 使用 `tidb_external_ts` 变量读取历史数据 +summary: 了解如何使用 `tidb_external_ts` 变量读取历史数据。 --- -# 通过系统变量 `tidb_external_ts` 读取历史数据 +# 使用 `tidb_external_ts` 变量读取历史数据 -为了支持读取历史版本数据,TiDB 从 v6.4.0 起引入了一个新的系统变量 [`tidb_external_ts`](/system-variables.md#tidb_external_ts-从-v640-版本开始引入)。本文档介绍如何通过该系统变量读取历史数据,其中包括具体的操作流程。 +为了支持读取历史数据,TiDB v6.4.0 引入了系统变量 [`tidb_external_ts`](/system-variables.md#tidb_external_ts-new-in-v640)。本文档描述如何通过这个系统变量读取历史数据,包括详细的使用示例。 -## 场景介绍 +## 应用场景 -通过配置让 TiDB 能够读取某一固定时间点的历史数据对于 TiCDC 等数据同步工具非常有用。在数据同步工具完成了某一时间点前的数据同步之后,可以通过设置下游 TiDB 的 `tidb_external_ts` 系统变量,使得下游 TiDB 的请求能够读取到该时间点前的数据。这将避免在同步过程中,下游 TiDB 读取到尚未完全同步而不一致的数据。 +从指定时间点读取历史数据对于数据复制工具(如 TiCDC)来说非常有用。在数据复制工具完成某个时间点之前的数据复制后,您可以设置下游 TiDB 的 `tidb_external_ts` 系统变量来读取该时间点之前的数据。这可以防止因数据复制导致的数据不一致。 -## 功能介绍 +## 功能说明 -系统变量 [`tidb_external_ts`](/system-variables.md#tidb_external_ts-从-v640-版本开始引入) 用于指定启用 `tidb_enable_external_ts_read` 时,读取历史数据使用的时间戳。 +系统变量 [`tidb_external_ts`](/system-variables.md#tidb_external_ts-new-in-v640) 在启用 `tidb_enable_external_ts_read` 时指定要读取的历史数据的时间戳。 -系统变量 [`tidb_enable_external_ts_read`](/system-variables.md#tidb_enable_external_ts_read-从-v640-版本开始引入) 控制着是否在当前会话或全局启用读取历史数据的功能。默认值为 `OFF`,这意味着该功能关闭,并且设置 `tidb_external_ts` 没有作用。当该变量被全局地设置为 `ON` 时,所有的请求都将读取到 `tidb_external_ts` 指定时间之前的历史数据。如果 `tidb_enable_external_ts_read` 仅在某一会话被设置为 `ON`,则只有该会话中的请求会读取到历史数据。 +系统变量 [`tidb_enable_external_ts_read`](/system-variables.md#tidb_enable_external_ts_read-new-in-v640) 控制是否在当前会话或全局范围内读取历史数据。默认值为 `OFF`,表示禁用读取历史数据的功能,并忽略 `tidb_external_ts` 的值。当 `tidb_enable_external_ts_read` 全局设置为 `ON` 时,所有查询都会读取 `tidb_external_ts` 指定时间之前的历史数据。如果仅对某个会话将 `tidb_enable_external_ts_read` 设置为 `ON`,则只有该会话中的查询会读取历史数据。 -当 `tidb_enable_external_ts_read` 被设置为 `ON` 时,TiDB 会进入只读模式,任何写请求都会失败并且返回错误 `ERROR 1836 (HY000): Running in read-only mode`。 +当启用 `tidb_enable_external_ts_read` 时,TiDB 变为只读模式。所有写入查询都会失败,并显示类似 `ERROR 1836 (HY000): Running in read-only mode` 的错误。 -## 示例 +## 使用示例 -以下是一个使用该功能的示例: +本节通过示例说明如何使用 `tidb_external_ts` 变量读取历史数据。 -1. 创建一个表后,在表中插入几行数据: +1. 创建表并插入一些行: ```sql CREATE TABLE t (c INT); @@ -62,11 +62,11 @@ summary: 了解如何通过系统变量 `tidb_external_ts` 读取历史数据。 ```sql START TRANSACTION; - SET GLOBAL tidb_external_ts = @@tidb_current_ts; + SET GLOBAL tidb_external_ts=@@tidb_current_ts; COMMIT; ``` -4. 插入新的一行并确认新的一行已经被插入: +4. 插入新行并确认已插入: ```sql INSERT INTO t VALUES (4); @@ -92,10 +92,10 @@ summary: 了解如何通过系统变量 `tidb_external_ts` 读取历史数据。 4 rows in set (0.00 sec) ``` -5. 将 `tidb_enable_external_ts_read` 设置为 `ON` 后,再次查询表中的数据: +5. 将 `tidb_enable_external_ts_read` 设置为 `ON` 然后查看表中的数据: ```sql - SET tidb_enable_external_ts_read = ON; + SET tidb_enable_external_ts_read=ON; SELECT * FROM t; ``` @@ -110,4 +110,4 @@ summary: 了解如何通过系统变量 `tidb_external_ts` 读取历史数据。 3 rows in set (0.00 sec) ``` - 因为 `tidb_external_ts` 被设置为插入这一行之前的时间,在启动 `tidb_enable_external_ts_read` 后,将读取不到新插入的行。 + 因为 `tidb_external_ts` 被设置为插入新行之前的时间戳,所以在启用 `tidb_enable_external_ts_read` 后,新插入的行不会被返回。 diff --git a/tidb-global-sort.md b/tidb-global-sort.md index 750f767b6973..8397c7ee98e6 100644 --- a/tidb-global-sort.md +++ b/tidb-global-sort.md @@ -1,72 +1,92 @@ --- title: TiDB 全局排序 -summary: 了解 TiDB 全局排序功能的使用场景、限制、使用方法和实现原理。 +summary: 了解 TiDB 全局排序的使用场景、限制、用法和实现原理。 --- + + + # TiDB 全局排序 > **注意:** > -> - 目前,全局排序会使用大量 TiDB 节点的计算与内存资源。对于在线增加索引等同时有用户业务在运行的场景,建议为集群添加新的 TiDB 节点,为这些 TiDB 节点设置 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-从-v740-版本开始引入),并连接到这些节点上创建任务。这样分布式框架就会将任务调度到这些节点上,将工作负载与其他 TiDB 节点隔离,以减少执行后端任务(如 `ADD INDEX` 和 `IMPORT INTO`)对用户业务的影响。 -> - 当需要使用全局排序功能时,为避免 OOM,建议 TiDB 节点的规格至少为 16 核 CPU、32 GiB 内存。 +> - 目前,全局排序过程会消耗 TiDB 节点大量的计算和内存资源。在用户业务应用运行的同时进行在线添加索引等场景时,建议向集群添加新的 TiDB 节点,为这些节点配置 [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) 变量,并连接到这些节点创建任务。这样,分布式框架会将任务调度到这些节点,将工作负载与其他 TiDB 节点隔离,以减少执行 `ADD INDEX` 和 `IMPORT INTO` 等后台任务对用户业务应用的影响。 +> - 使用全局排序功能时,建议使用至少 16 核 CPU 和 32 GiB 内存的 TiDB 节点,以避免 OOM。 + +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 -## 功能概览 +## 概述 -TiDB 全局排序功能增强了数据导入和 DDL(数据定义语言)操作的稳定性和执行效率。全局排序作为[分布式执行框架](/tidb-distributed-execution-framework.md)中的通用算子,通过分布式执行框架,在云上提供全局排序服务。 +TiDB 全局排序功能增强了数据导入和 DDL(数据定义语言)操作的稳定性和效率。它作为 [TiDB 分布式执行框架 (DXF)](/tidb-distributed-execution-framework.md) 中的通用算子,提供云上的全局排序服务。 -全局排序目前支持使用 Amazon S3 作为云存储。 +目前,全局排序功能支持使用 Amazon S3 作为云存储。 -## 目标 +## 使用场景 -全局排序功能旨在提高 `IMPORT INTO` 和 `CREATE INDEX` 的稳定性与效率。通过将任务需要处理的数据进行全局排序,可以提高数据写入 TiKV 的稳定性、可控性和可扩展性,从而提供更好的数据导入与 DDL 任务的用户体验及更高质量的服务。 +全局排序功能增强了 `IMPORT INTO` 和 `CREATE INDEX` 的稳定性和效率。通过对任务处理的数据进行全局排序,它提高了向 TiKV 写入数据的稳定性、可控性和可扩展性。这为数据导入和 DDL 任务提供了更好的用户体验,以及更高质量的服务。 -全局排序功能在分布式执行框架中执行任务,确保所需处理的数据在全局范围内保持有序。 +全局排序功能在统一的 DXF 中执行任务,确保在全局范围内高效并行地对数据进行排序。 ## 限制 -目前,全局排序功能不支持在查询过程中对查询结果进行排序。 +目前,全局排序功能不作为负责排序查询结果的查询执行过程的组件。 -## 使用方法 +## 用法 -要开启全局排序功能,执行以下步骤: +要启用全局排序,请按照以下步骤操作: -1. 将 [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-从-v710-版本开始引入) 的值设置为 `ON`,以开启分布式执行框架。该变量从 v8.1.0 起默认开启,对于新建的 v8.1.0 或更高版本集群,可以跳过此步骤。 +1. 通过将 [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-new-in-v710) 的值设置为 `ON` 来启用 DXF。从 v8.1.0 开始,此变量默认启用。对于 v8.1.0 或更高版本的新创建集群,可以跳过此步骤。 ```sql SET GLOBAL tidb_enable_dist_task = ON; ``` -2. 将 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-从-v740-版本开始引入) 设置为正确的云存储路径。参见[示例](/br/backup-and-restore-storages.md)。 + + +2. 将 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740) 设置为正确的云存储路径。参见[示例](/br/backup-and-restore-storages.md)。 + + ```sql + SET GLOBAL tidb_cloud_storage_uri = 's3://my-bucket/test-data?role-arn=arn:aws:iam::888888888888:role/my-role' + ``` + + + + +2. 将 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740) 设置为正确的云存储路径。参见[示例](https://docs.pingcap.com/tidb/stable/backup-and-restore-storages)。 ```sql SET GLOBAL tidb_cloud_storage_uri = 's3://my-bucket/test-data?role-arn=arn:aws:iam::888888888888:role/my-role' ``` + + > **注意:** > -> [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 也可使用 [`CLOUD_STORAGE_URI`](/sql-statements/sql-statement-import-into.md#withoptions) 参数来控制云存储路径。如果 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-从-v740-版本开始引入) 和 `CLOUD_STORAGE_URI` 都设置了有效的云存储路径,[`IMPORT INTO`](/sql-statements/sql-statement-import-into.md) 将以 `CLOUD_STORAGE_URI` 参数的配置为准。 +> 对于 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md),你也可以使用 [`CLOUD_STORAGE_URI`](/sql-statements/sql-statement-import-into.md#withoptions) 选项指定云存储路径。如果 [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740) 和 `CLOUD_STORAGE_URI` 都配置了有效的云存储路径,则对于 [`IMPORT INTO`](/sql-statements/sql-statement-import-into.md),`CLOUD_STORAGE_URI` 的配置会生效。 ## 实现原理 -全局排序功能的算法如下图所示: +全局排序功能的算法如下: -![全局排序功能算法](/media/dist-task/global-sort.jpeg) +![全局排序算法](/media/dist-task/global-sort.jpeg) 详细的实现原理如下: -### 第 1 步:扫描和准备数据 +### 步骤 1:扫描和准备数据 -1. TiDB 节点扫描特定范围的数据后(数据源可以是 CSV 数据或者 TiKV 中的表数据): +1. TiDB 节点扫描特定范围的数据(数据源可以是 CSV 数据或 TiKV 中的表数据)后: - 1. TiDB 节点将扫描的数据编码为键值对。 - 2. TiDB 节点将键值对排序为多个块数据段(数据段局部有序),每个段是一个文件,并将这些文件上传到云存储中。 + 1. TiDB 节点将它们编码为键值对。 + 2. TiDB 节点将键值对排序成几个块数据段(数据段是本地排序的),每个段是一个文件并上传到云存储中。 -2. TiDB 节点记录了每个段的连续实际键值范围(称为统计信息文件),这是可扩展排序实现的关键准备工作。这些文件随实际数据一起上传到云存储中。 +2. TiDB 节点还记录每个段的一系列实际键值范围(称为统计文件),这是实现可扩展排序的关键准备。这些文件随后与实际数据一起上传到云存储中。 -### 第 2 步:排序和分发数据 +### 步骤 2:排序和分发数据 -从第一步中,全局排序的程序获取了一个已排序块的列表及其对应的统计信息文件,这些文件记录了本地已排序块的数量。此外,全局排序程序还记录了一个实际数据范围,供 PD 用于数据拆分和打散。接下来将执行以下步骤: +从步骤 1 中,全局排序程序获取已排序块的列表及其对应的统计文件,这些文件提供了本地排序块的数量。程序还有一个可供 PD 用于拆分和分散的实际数据范围。执行以下步骤: -1. 将统计信息文件中的记录排序,划分为大小相近的范围,每个范围将作为一个并行执行的子任务。 +1. 对统计文件中的记录进行排序,将它们划分为大小几乎相等的范围,这些范围是将并行执行的子任务。 2. 将子任务分发给 TiDB 节点执行。 -3. 每个 TiDB 节点独立地对子任务的数据进行排序,并在没有重叠的情况下将数据导入到 TiKV 中。 +3. 每个 TiDB 节点独立地将子任务的数据排序成范围,并且无重叠地将它们写入 TiKV。 diff --git a/tidb-limitations.md b/tidb-limitations.md index 928efc658834..c9b46ffa2790 100644 --- a/tidb-limitations.md +++ b/tidb-limitations.md @@ -1,78 +1,94 @@ --- -title: TiDB 使用限制 -summary: TiDB 中的使用限制包括标识符长度限制、数据库、表、视图、连接总个数限制、单个数据库和表的限制、单行限制、数据类型限制、SQL 语句限制和 TiKV 版本限制。 +title: TiDB 限制 +summary: 了解 TiDB 的使用限制。 --- -# 使用限制 +# TiDB 限制 -本文会将详细描述 TiDB 中常见的使用限制,包括:标识符长度,最大支持的数据库、表、索引、分区表、序列等的个数。 +本文档描述了 TiDB 的常见使用限制,包括标识符长度的最大值以及支持的数据库、表、索引、分区表和序列的最大数量。 > **注意:** > -> TiDB 高度兼容 MySQL 协议,也兼容了很多 MySQL 本身的限制,比如单个索引最多可包含 16 列。详细请参考[与 MySQL 兼容性对比](/mysql-compatibility.md) 和 MySQL 官方文档。 +> TiDB 与 MySQL 协议和语法具有高度兼容性,包括许多 MySQL 限制。例如,单个索引最多可以包含 16 列。更多信息,请参阅 [MySQL 兼容性](/mysql-compatibility.md)和 MySQL 官方文档。 ## 标识符长度限制 -| 标识符类型 | 最大长度(字符)| +| 标识符类型 | 最大长度(允许的字符数) | |:---------|:--------------| -| Database | 64 | -| Table | 64 | -| Column | 64 | -| Index | 64 | -| View | 64 | -| Sequence | 64 | +| 数据库 | 64 | +| 表 | 64 | +| 列 | 64 | +| 索引 | 64 | +| 视图 | 64 | +| 序列 | 64 | -## Databases、Tables、Views、Connections 总个数限制 +## 数据库、表、视图和连接总数的限制 -| 类型 | 最大个数 | +| 类型 | 最大数量 | |:----------|:----------| -| Databases | unlimited | -| Tables | unlimited | -| Views | unlimited | -| Connections| unlimited| +| 数据库 | 无限制 | +| 表 | 无限制 | +| 视图 | 无限制 | +| 连接 | 无限制 | -## 单个 Database 的限制 +## 单个数据库的限制 -| 类型 | 最大限制 | +| 类型 | 上限 | |:----------|:----------| -| Tables |unlimited | +| 表 | 无限制 | -## 单个 Table 的限制 +## 单个表的限制 -| 类型 | 最大限制(默认值) | -|:----------|:------------------------------| -| Columns | 默认为 1017,最大可调至 4096 | -| Indexes | 默认为 64,最大可调至 512 | -| Rows | 无限制 | -| Size | 无限制 | -| Partitions| 8192 | +| 类型 | 上限(默认值) | +|:----------|:----------| +| 列 | 默认为 1017,可调整至 4096 | +| 索引 | 默认为 64,可调整至 512 | +| 行 | 无限制 | +| 大小 | 无限制 | +| 分区 | 8192 | + + + +* `列`的上限可以通过 [`table-column-count-limit`](/tidb-configuration-file.md#table-column-count-limit-new-in-v50) 修改。 +* `索引`的上限可以通过 [`index-limit`](/tidb-configuration-file.md#index-limit-new-in-v50) 修改。 -* Columns 的最大限制可通过 [`table-column-count-limit`](/tidb-configuration-file.md#table-column-count-limit-从-v50-版本开始引入) 修改。 -* Indexes 的最大限制可通过 [`index-limit`](/tidb-configuration-file.md#index-limit-从-v50-版本开始引入) 修改。 + ## 单行的限制 -| 类型 | 最大限制(默认值) | +| 类型 | 上限(默认值) | |:----------|:----------| -| Size | 默认为 6 MiB,可通过 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v4010-和-v500-版本开始引入) 配置项调至 120 MiB | +| 大小 | 默认为 6 MiB,可调整至 120 MiB | + + + +你可以通过 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-new-in-v4010-and-v500) 配置项调整大小限制。 -## 数据类型限制 + -| 类型 | 最大限制 | +## 数据类型的限制 + +| 类型 | 上限 | |:----------|:----------| -| CHAR | 255 字符 | -| BINARY | 255 字节 | -| VARBINARY | 65535 字节 | -| VARCHAR | 16383 字符 | -| TEXT | 默认为 6291456 字节(即 6 MiB),可调至 125829120 字节(即 120 MiB) | -| BLOB | 默认为 6291456 字节(即 6 MiB),可调至 125829120 字节(即 120 MiB) | +| CHAR | 255 个字符 | +| BINARY | 255 个字符 | +| VARBINARY | 65535 个字符 | +| VARCHAR | 16383 个字符 | +| TEXT | 默认为 6 MiB,可调整至 120 MiB | +| BLOB | 默认为 6 MiB,可调整至 120 MiB | -## SQL Statements 的限制 +## SQL 语句的限制 -| 类型 | 最大限制 | +| 类型 | 上限 | |:----------|:----------| -| 单个事务最大语句数 | 在使用乐观事务并开启事务重试的情况下,默认限制 5000,可通过 [`stmt-count-limit`](/tidb-configuration-file.md#stmt-count-limit) 调整 | +| 单个事务中 SQL 语句的最大数量 | 当使用乐观事务且启用事务重试时,上限为 5000。 | + + + +你可以通过 [`stmt-count-limit`](/tidb-configuration-file.md#stmt-count-limit) 配置项修改限制。 + + -## TiKV 版本的限制 +## TiKV 版本限制 -在集群中,如果 TiDB 组件的版本为 v6.2.0 及以上,则 TiKV 组件版本不得低于 v6.2.0。 +在你的集群中,如果 TiDB 组件的版本是 v6.2.0 或更高版本,则 TiKV 的版本必须是 v6.2.0 或更高版本。 diff --git a/tidb-read-staleness.md b/tidb-read-staleness.md index 26f96db8ed8e..2143063e6750 100644 --- a/tidb-read-staleness.md +++ b/tidb-read-staleness.md @@ -1,35 +1,35 @@ --- -title: 通过系统变量 `tidb_read_staleness` 读取历史数据 -summary: 了解如何通过系统变量 `tidb_read_staleness` 读取历史数据。 +title: 使用 `tidb_read_staleness` 系统变量读取历史数据 +summary: 了解如何使用 `tidb_read_staleness` 系统变量读取历史数据。 --- -# 通过系统变量 `tidb_read_staleness` 读取历史数据 +# 使用 `tidb_read_staleness` 系统变量读取历史数据 -为支持读取历史版本数据,TiDB 从 5.4 版本起引入了一个新的系统变量 `tidb_read_staleness`。本文档介绍如何通过该系统变量读取历史数据,其中包括具体的操作流程。 +为了支持读取历史数据,TiDB 在 v5.4 中引入了新的系统变量 `tidb_read_staleness`。本文档描述如何通过这个系统变量读取历史数据,包括详细的操作步骤。 -## 功能介绍 +## 功能说明 -系统变量 `tidb_read_staleness` 用于设置当前会话允许读取的历史数据范围,其数据类型为 int,作用域为 `SESSION`。设置该变量后,TiDB 会从参数允许的范围内选出一个尽可能新的时间戳,并影响后继的所有读操作。比如,如果该变量的值设置为 `-5`,TiDB 会在 5 秒时间范围内,保证 TiKV 拥有对应历史版本数据的情况下,选择尽可能新的一个时间戳。 +`tidb_read_staleness` 系统变量用于设置当前会话中 TiDB 可以读取的历史数据的时间范围。该变量的数据类型为整数类型,作用域为 `SESSION`。设置该值后,TiDB 会从该变量允许的范围内选择一个尽可能新的时间戳,所有后续的读取操作都将基于这个时间戳执行。例如,如果将该变量的值设置为 `-5`,在 TiKV 具有相应历史版本数据的条件下,TiDB 会在 5 秒的时间范围内选择一个尽可能新的时间戳。 -开启 `tidb_read_staleness` 后,你仍可以进行以下操作: +启用 `tidb_read_staleness` 后,你仍然可以执行以下操作: -- 在当前会话中插入、修改、删除数据或进行 DML 操作。这些语句不会受到 `tidb_read_staleness` 的影响。 -- 在当前会话开启交互式事务。在该事务内的查询依旧是读取最新版本的数据。 +- 在当前会话中插入、修改、删除数据或执行 DML 操作。这些语句不受 `tidb_read_staleness` 的影响。 +- 在当前会话中启动交互式事务。该事务中的查询仍然读取最新数据。 -完成对历史版本数据的读取后,你可以通过以下两种方式来读取最新版本的数据。 +读取历史数据后,你可以通过以下两种方式读取最新数据: -- 结束当前会话。 -- 使用 `SET` 语句,把 `tidb_read_staleness` 变量的值设为 `""`。 +- 启动新的会话。 +- 使用 `SET` 语句将 `tidb_read_staleness` 变量的值设置为 `""`。 > **注意:** > -> 你可以通过调整 TiKV 的 `advance-ts-interval` 配置项提高 Stale Read 数据的时效性(即减少延时),详情参见[减少 Stale Read 延时](/stale-read.md#减少-stale-read-延时)。 +> 为了减少延迟并提高 Stale Read 数据的时效性,你可以修改 TiKV 的 `advance-ts-interval` 配置项。详情请参见[减少 Stale Read 延迟](/stale-read.md#reduce-stale-read-latency)。 -## 示例 +## 使用示例 -本节通过具体操作示例介绍系统变量 `tidb_read_staleness`的使用方法。 +本节通过示例说明如何使用 `tidb_read_staleness`。 -1. 初始化阶段。创建一个表后,在表中插入几行数据: +1. 创建一个表,并向表中插入几行数据: {{< copyable "sql" >}} @@ -70,7 +70,7 @@ summary: 了解如何通过系统变量 `tidb_read_staleness` 读取历史数据 3 rows in set (0.00 sec) ``` -3. 更新某一行数据: +3. 更新一行数据: {{< copyable "sql" >}} @@ -82,7 +82,7 @@ summary: 了解如何通过系统变量 `tidb_read_staleness` 读取历史数据 Query OK, 1 row affected (0.00 sec) ``` -4. 确认数据已经被更新: +4. 确认数据已更新: {{< copyable "sql" >}} @@ -101,11 +101,11 @@ summary: 了解如何通过系统变量 `tidb_read_staleness` 读取历史数据 3 rows in set (0.00 sec) ``` -5. 设置一个特殊的环境变量 `tidb_read_staleness`。 +5. 设置 `tidb_read_staleness` 系统变量。 - 该变量的作用域为 `SESSION`,设置变量值后,TiDB 会读取变量值时间之前的最新一个版本的数据。 + 该变量的作用域为 `SESSION`。设置其值后,TiDB 会读取该值设定时间之前的最新版本数据。 - 以下设置表示 TiDB 会从 5 秒前至现在的时间范围内选择一个尽可能新的时间戳,将其用作为历史数据读取的时间戳: + 以下设置表示 TiDB 会在 5 秒前到现在的时间范围内选择一个尽可能新的时间戳,并将其用作读取历史数据的时间戳: {{< copyable "sql" >}} @@ -119,10 +119,10 @@ summary: 了解如何通过系统变量 `tidb_read_staleness` 读取历史数据 > **注意:** > - > 必须在 `tidb_read_staleness` 前使用 `@@`,而非 `@`。因为 `@@` 表示系统变量,`@` 则表示用户变量。 - > 你需要根据第 3 步到第 4 步所花费的时间,来设定你要读取的历史时间范围,即 `tidb_read_staleness` 的值。否则,查询结果中显示的会是最新数据,而非历史数据。因此,请根据自己的实际操作情况调整该时间范围。比如,在本示例中,由于设定的时间范围是 5 秒,你需要在 5 秒内完成第 3 步和第 4 步。 + > - 在 `tidb_read_staleness` 前使用 `@@` 而不是 `@`。`@@` 表示系统变量,`@` 表示用户变量。 + > - 你需要根据在步骤 3 和步骤 4 中花费的总时间来设置历史时间范围(`tidb_read_staleness` 的值)。否则,查询结果中将显示最新数据,而不是历史数据。因此,你需要根据操作所花费的时间来调整这个时间范围。例如,在本例中,由于设置的时间范围是 5 秒,你需要在 5 秒内完成步骤 3 和步骤 4。 - 这里读取到的内容即为更新前的数据,也就是历史版本的数据: + 此处读取的是更新前的数据,即历史数据: {{< copyable "sql" >}} @@ -141,7 +141,7 @@ summary: 了解如何通过系统变量 `tidb_read_staleness` 读取历史数据 3 rows in set (0.00 sec) ``` -6. 清空这个变量后,即可读取最新版本数据: +6. 取消设置此变量后,TiDB 可以读取最新数据: {{< copyable "sql" >}} diff --git a/tidb-resource-control.md b/tidb-resource-control.md index 75489c805186..e26f4ac94371 100644 --- a/tidb-resource-control.md +++ b/tidb-resource-control.md @@ -1,44 +1,62 @@ --- -title: 使用资源管控 (Resource Control) 实现资源隔离 -summary: 介绍如何通过资源管控能力来实现对应用资源消耗的控制和有效调度。 +title: 使用资源控制实现资源隔离 +summary: 了解如何使用资源控制功能来控制和调度应用程序资源。 --- -# 使用资源管控 (Resource Control) 实现资源隔离 +# 使用资源控制实现资源隔离 -使用资源管控特性,集群管理员可以定义资源组 (Resource Group),通过资源组限定配额。 +> **注意:** +> +> 此功能在 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群上不可用。 + +作为集群管理员,你可以使用资源控制功能创建资源组,为资源组设置配额,并将用户绑定到这些组。 + +TiDB 资源控制功能提供两层资源管理能力:TiDB 层的流量控制能力和 TiKV 层的优先级调度能力。这两种能力可以单独或同时启用。详见[资源控制参数](#资源控制参数)。这使得 TiDB 层能够根据资源组设置的配额控制用户读写请求的流量,并使 TiKV 层能够根据与读写配额映射的优先级调度请求。通过这种方式,你可以确保应用程序的资源隔离并满足服务质量(QoS)要求。 + +- TiDB 流量控制:TiDB 流量控制使用[令牌桶算法](https://en.wikipedia.org/wiki/Token_bucket)。如果桶中没有足够的令牌,并且资源组未指定 `BURSTABLE` 选项,对该资源组的请求将等待令牌桶补充令牌并重试。重试可能因超时而失败。 + +- TiKV 调度:你可以根据需要设置绝对优先级 [(`PRIORITY`)](/information-schema/information-schema-resource-groups.md#examples)。不同的资源根据 `PRIORITY` 设置进行调度。高 `PRIORITY` 的任务优先调度。如果你没有设置绝对优先级,TiKV 使用每个资源组的 `RU_PER_SEC` 值来确定每个资源组的读写请求优先级。基于这些优先级,存储层使用优先级队列来调度和处理请求。 + +从 v7.4.0 开始,资源控制功能支持控制 TiFlash 资源。其原理与 TiDB 流量控制和 TiKV 调度类似: + + -TiDB 资源管控特性提供了两层资源管理能力,包括在 TiDB 层的流控能力和 TiKV 层的优先级调度的能力。两个能力可以单独或者同时开启,详情请参见[参数组合效果表](#相关参数)。将用户绑定到某个资源组后,TiDB 层会根据用户所绑定资源组设定的配额对用户的读写请求做流控,TiKV 层会根据配额映射的优先级来对请求做调度。通过流控和调度这两层控制,可以实现应用的资源隔离,满足服务质量 (QoS) 要求。 +- TiFlash 流量控制:通过 [TiFlash pipeline 执行模型](/tiflash/tiflash-pipeline-model.md),TiFlash 可以更准确地获取不同查询的 CPU 消耗并转换为 [Request Units (RU)](#什么是请求单位-ru) 进行扣减。流量控制使用令牌桶算法实现。 +- TiFlash 调度:当系统资源不足时,TiFlash 根据资源组的优先级在多个资源组之间调度 pipeline 任务。具体逻辑是:首先评估资源组的 `PRIORITY`,然后考虑 CPU 使用率和 `RU_PER_SEC`。因此,如果 `rg1` 和 `rg2` 具有相同的 `PRIORITY` 但 `rg2` 的 `RU_PER_SEC` 是 `rg1` 的两倍,那么 `rg2` 的 CPU 使用率是 `rg1` 的两倍。 -- TiDB 流控:TiDB 流控使用[令牌桶算法](https://en.wikipedia.org/wiki/Token_bucket) 做流控。如果桶内令牌数不够,而且资源组没有指定 `BURSTABLE` 特性,属于该资源组的请求会等待令牌桶回填令牌并重试,重试可能会超时失败。 -- TiKV 调度:你可以为资源组设置绝对优先级 ([`PRIORITY`](/information-schema/information-schema-resource-groups.md#示例)),不同的资源按照 `PRIORITY` 的设置进行调度,`PRIORITY` 高的任务会被优先调度。如果没有设置绝对优先级 (`PRIORITY`),TiKV 会将资源组的 `RU_PER_SEC` 取值映射成各自资源组读写请求的优先级,并基于各自的优先级在存储层使用优先级队列调度处理请求。 + -从 v7.4.0 开始,TiDB 资源管控特性支持管控 TiFlash 资源,其原理与 TiDB 流控和 TiKV 调度类似: + -- TiFlash 流控:借助 [TiFlash Pipeline Model 执行模型](/tiflash/tiflash-pipeline-model.md),可以更精确地获取不同查询的 CPU 消耗情况,并转换为 [Request Unit (RU)](#什么是-request-unit-ru) 进行扣除。流量控制通过令牌桶算法实现。 -- TiFlash 调度:当系统资源不足时,会根据优先级对多个资源组之间的 pipeline task 进行调度。具体逻辑是:首先判断资源组的优先级 `PRIORITY`,然后根据 CPU 使用情况,再结合 `RU_PER_SEC` 进行判断。最终效果是,如果 rg1 和 rg2 的 `PRIORITY` 一样,但是 rg2 的 `RU_PER_SEC` 是 rg1 的两倍,那么 rg2 可使用的 CPU 时间是 rg1 的两倍。 +- TiFlash 流量控制:通过 [TiFlash pipeline 执行模型](http://docs.pingcap.com/tidb/dev/tiflash-pipeline-model),TiFlash 可以更准确地获取不同查询的 CPU 消耗并转换为 [Request Units (RU)](#什么是请求单位-ru) 进行扣减。流量控制使用令牌桶算法实现。 +- TiFlash 调度:当系统资源不足时,TiFlash 根据资源组的优先级在多个资源组之间调度 pipeline 任务。具体逻辑是:首先评估资源组的 `PRIORITY`,然后考虑 CPU 使用率和 `RU_PER_SEC`。因此,如果 `rg1` 和 `rg2` 具有相同的 `PRIORITY` 但 `rg2` 的 `RU_PER_SEC` 是 `rg1` 的两倍,那么 `rg2` 的 CPU 使用率是 `rg1` 的两倍。 -## 使用场景 + -资源管控特性的引入对 TiDB 具有里程碑的意义。它能够将一个分布式数据库集群划分成多个逻辑单元,即使个别单元对资源过度使用,也不会挤占其他单元所需的资源。利用该特性: +## 资源控制的应用场景 -- 你可以将多个来自不同系统的中小型应用合入一个 TiDB 集群中,个别应用的负载升高,不会影响其他业务的正常运行。而在系统负载较低的时候,繁忙的应用即使超过设定的读写配额,也仍然可以被分配到所需的系统资源,达到资源的最大化利用。 -- 你可以选择将所有测试环境合入一个集群,或者将消耗较大的批量任务编入一个单独的资源组,在保证重要应用获得必要资源的同时,提升硬件利用率,降低运行成本。 -- 当系统中存在多种业务负载时,可以将不同的负载分别放入各自的资源组。利用资源管控技术,确保交易类业务的响应时间不受数据分析或批量业务的影响。 -- 当集群遇到突发的 SQL 性能问题,可以结合 SQL Binding 和资源组,临时限制某个 SQL 的资源消耗。 +资源控制功能的引入是 TiDB 的一个里程碑。它可以将分布式数据库集群划分为多个逻辑单元。即使某个单元过度使用资源,也不会挤占其他单元所需的资源。 -此外,合理利用资源管控特性可以减少集群数量,降低运维难度及管理成本。 +通过此功能,你可以: + +- 将来自不同系统的多个中小型应用程序合并到单个 TiDB 集群中。当某个应用程序的工作负载增大时,不会影响其他应用程序的正常运行。当系统工作负载较低时,即使超出设定配额,繁忙的应用程序仍然可以获得所需的系统资源,从而实现资源的最大利用。 +- 选择将所有测试环境合并到单个 TiDB 集群中,或将消耗更多资源的批处理任务分组到单个资源组中。这可以提高硬件利用率并降低运营成本,同时确保关键应用程序始终能获得必要的资源。 +- 当系统中存在混合工作负载时,你可以将不同的工作负载放入单独的资源组中。通过使用资源控制功能,你可以确保事务应用程序的响应时间不受数据分析或批处理应用程序的影响。 +- 当集群遇到意外的 SQL 性能问题时,你可以将 SQL 绑定与资源组结合使用,临时限制 SQL 语句的资源消耗。 + +此外,合理使用资源控制功能可以减少集群数量,降低运维难度,节省管理成本。 > **注意:** > -> 推荐在部署资源相对独立的计算和存储节点上测试资源管控的效果,因为调度等对集群资源敏感的功能通常很难在单节点运行的 TiUP Playground 上表现出良好性能。 +> - 要评估资源管理的有效性,建议将集群部署在独立的计算和存储节点上。在使用 `tiup playground` 创建的部署中,由于实例之间共享资源,调度和其他集群资源敏感功能很难正常工作。 -## 使用限制 +## 限制 -资源管控将带来额外的调度开销。因此,开启该特性后,性能可能会有轻微下降(低于 5%)。 +资源控制会产生额外的调度开销。因此,启用此功能时可能会出现轻微的性能下降(小于 5%)。 -## 什么是 Request Unit (RU) +## 什么是请求单位 (RU) -Request Unit (RU) 是 TiDB 对 CPU、IO 等系统资源的统一抽象的计量单位,用于表示对数据库的单个请求消耗的资源量。请求消耗的 RU 数量取决于多种因素,例如操作类型或正在检索或修改的数据量。目前,RU 包含以下资源的统计信息: +请求单位(Request Unit,RU)是 TiDB 中系统资源的统一抽象单位,目前包括 CPU、IOPS 和 IO 带宽指标。它用于表示对数据库的单个请求所消耗的资源量。一个请求消耗的 RU 数量取决于多种因素,例如操作类型以及被查询或修改的数据量。目前,RU 包含以下表格中资源的消耗统计: @@ -49,97 +67,131 @@ Request Unit (RU) 是 TiDB 对 CPU、IO 等系统资源的统一抽象的计量 - - + + - + - + - - + + - + - + - +
Read2 storage read batches 消耗 1 RU读取2 个存储读取批次消耗 1 RU
8 storage read requests 消耗 1 RU8 个存储读取请求消耗 1 RU
64 KiB read request payload 消耗 1 RU64 KiB 读取请求负载消耗 1 RU
Write1 storage write batch 消耗 1 RU写入1 个存储写入批次消耗 1 RU
1 storage write request 消耗 1 RU1 个存储写入请求消耗 1 RU
1 KiB write request payload 消耗 1 RU1 KiB 写入请求负载消耗 1 RU
CPU 3 ms 消耗 1 RU3 毫秒消耗 1 RU
> **注意:** > -> - 每个写操作最终都被会复制到所有副本(TiKV 默认 3 个数据副本),并且每次复制都被认为是一个不同的写操作。 -> - 上表只列举了本地部署的 TiDB 计算 RU 时涉及的相关资源,其中不包括网络和存储部分。TiDB Cloud Serverless 的 RU 可参考 [TiDB Cloud Serverless Pricing Details](https://www.pingcap.com/tidb-cloud-serverless-pricing-details/)。 -> - 目前 TiFlash 资源管控仅考虑 SQL CPU(即查询的 pipeline task 运行所占用的 CPU 时间)以及 read request payload。 +> - 每个写入操作最终都会复制到所有副本(默认情况下,TiKV 有 3 个副本)。每个复制操作都被视为不同的写入操作。 +> - 上表仅列出了 TiDB 自管理集群中涉及 RU 计算的资源,不包括网络和存储消耗。关于 TiDB Cloud Serverless RU,请参见 [TiDB Cloud Serverless 定价详情](https://www.pingcap.com/tidb-cloud-serverless-pricing-details/)。 +> - 目前,TiFlash 资源控制仅考虑 SQL CPU,即查询的 pipeline 任务执行所消耗的 CPU 时间,以及读取请求负载。 + +## 资源控制参数 + +资源控制功能引入了以下系统变量或参数: + +* TiDB:你可以使用 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-new-in-v660) 系统变量来控制是否启用资源组的流量控制。 + + + +* TiKV:你可以使用 [`resource-control.enabled`](/tikv-configuration-file.md#resource-control) 参数来控制是否基于资源组使用请求调度。 +* TiFlash:你可以使用 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-new-in-v660) 系统变量和 [`enable_resource_control`](/tiflash/tiflash-configuration.md#configure-the-tiflashtoml-file) 配置项(v7.4.0 引入)来控制是否启用 TiFlash 资源控制。 -## 相关参数 + -资源管控特性引入了如下系统变量或参数: + -- TiDB:通过配置全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-从-v660-版本开始引入) 控制是否打开资源组流控。 -- TiKV:通过配置参数 [`resource-control.enabled`](/tikv-configuration-file.md#resource-control) 控制是否使用基于资源组配额的请求调度。 -- TiFlash:通过配置全局变量 [`tidb_enable_resource_control`](/system-variables.md#tidb_enable_resource_control-从-v660-版本开始引入) 和 TiFlash 配置项 [`enable_resource_control`](/tiflash/tiflash-configuration.md#配置文件-tiflashtoml)(v7.4.0 开始引入)控制是否开启 TiFlash 资源管控。 +* TiKV:对于 TiDB 自管理版本,你可以使用 `resource-control.enabled` 参数来控制是否基于资源组配额使用请求调度。对于 TiDB Cloud,`resource-control.enabled` 参数默认值为 `true` 且不支持动态修改。 +* TiFlash:对于 TiDB 自管理版本,你可以使用 `tidb_enable_resource_control` 系统变量和 `enable_resource_control` 配置项(v7.4.0 引入)来控制是否启用 TiFlash 资源控制。 -从 v7.0.0 开始,`tidb_enable_resource_control` 和 `resource-control.enabled` 开关都被默认打开。这两个参数的组合效果见下表: + -| `resource-control.enabled` | `tidb_enable_resource_control`= ON | `tidb_enable_resource_control`= OFF | -|:----------------------------|:-----------------------------------|:------------------------------------| -| `resource-control.enabled`= true | 流控和调度(推荐组合) | 无效配置 | -| `resource-control.enabled`= false | 仅流控(不推荐) | 特性被关闭 | +从 TiDB v7.0.0 开始,`tidb_enable_resource_control` 和 `resource-control.enabled` 默认启用。这两个参数组合的结果如下表所示: -从 v7.4.0 开始,TiFlash 配置项 `enable_resource_control` 默认打开,与 `tidb_enable_resource_control` 一起控制 TiFlash 资源管控功能。只有二者都启用时,TiFlash 资源管控功能才能进行流控以及优先级调度。同时,在开启 `enable_resource_control` 时,TiFlash 会使用 [Pipeline Model 执行模型](/tiflash/tiflash-pipeline-model.md)。 +| `resource-control.enabled` | `tidb_enable_resource_control`= ON | `tidb_enable_resource_control`= OFF | +|:----------------------------|:-------------------------------------|:-------------------------------------| +| `resource-control.enabled`= true | 流量控制和调度(推荐) | 无效组合 | +| `resource-control.enabled`= false | 仅流量控制(不推荐) | 功能禁用 | -关于资源管控实现机制及相关参数的详细介绍,请参考 [RFC: Global Resource Control in TiDB](https://github.com/pingcap/tidb/blob/release-8.1/docs/design/2022-11-25-global-resource-control.md) 以及 [TiFlash Resource Control](https://github.com/pingcap/tiflash/blob/release-8.1/docs/design/2023-09-21-tiflash-resource-control.md)。 + -## 使用方法 +从 v7.4.0 开始,TiFlash 配置项 `enable_resource_control` 默认启用。它与 `tidb_enable_resource_control` 一起控制 TiFlash 资源控制功能。只有当 `enable_resource_control` 和 `tidb_enable_resource_control` 都启用时,TiFlash 资源控制才会执行流量控制和优先级调度。此外,当 `enable_resource_control` 启用时,TiFlash 使用 [Pipeline 执行模型](/tiflash/tiflash-pipeline-model.md)。 -下面介绍如何使用资源管控特性。 + -### 预估集群容量 + -在进行资源规划之前,你需要了解集群的整体容量。TiDB 提供了命令 [`CALIBRATE RESOURCE`](/sql-statements/sql-statement-calibrate-resource.md) 用来估算集群容量。目前提供两种估算方式: +从 v7.4.0 开始,TiFlash 配置项 `enable_resource_control` 默认启用。它与 `tidb_enable_resource_control` 一起控制 TiFlash 资源控制功能。只有当 `enable_resource_control` 和 `tidb_enable_resource_control` 都启用时,TiFlash 资源控制才会执行流量控制和优先级调度。此外,当 `enable_resource_control` 启用时,TiFlash 使用 [Pipeline 执行模型](http://docs.pingcap.com/tidb/dev/tiflash-pipeline-model)。 -- [根据实际负载估算容量](/sql-statements/sql-statement-calibrate-resource.md#根据实际负载估算容量) + + +有关资源控制机制和参数的更多信息,请参见 [RFC: Global Resource Control in TiDB](https://github.com/pingcap/tidb/blob/release-8.1/docs/design/2022-11-25-global-resource-control.md) 和 [TiFlash Resource Control](https://github.com/pingcap/tiflash/blob/release-8.1/docs/design/2023-09-21-tiflash-resource-control.md)。 + +## 如何使用资源控制 + +本节描述如何使用资源控制功能来管理资源组并控制每个资源组的资源分配。 + +### 估算集群容量 + + + +在进行资源规划之前,你需要了解集群的整体容量。TiDB 提供了 [`CALIBRATE RESOURCE`](/sql-statements/sql-statement-calibrate-resource.md) 语句来估算集群容量。你可以使用以下方法之一: + +- [基于实际工作负载估算容量](/sql-statements/sql-statement-calibrate-resource.md#基于实际工作负载估算容量) - [基于硬件部署估算容量](/sql-statements/sql-statement-calibrate-resource.md#基于硬件部署估算容量) -可通过 [TiDB Dashboard 资源管控页面](/dashboard/dashboard-resource-manager.md)进行查看。详情请参考 [`CALIBRATE RESOURCE` 预估方式](/sql-statements/sql-statement-calibrate-resource.md#预估方式)。 +你可以查看 TiDB Dashboard 中的[资源管理页面](/dashboard/dashboard-resource-manager.md)。更多信息,请参见 [`CALIBRATE RESOURCE`](/sql-statements/sql-statement-calibrate-resource.md#估算容量的方法)。 + + + + + +对于 TiDB 自管理版本,你可以使用 [`CALIBRATE RESOURCE`](https://docs.pingcap.com/tidb/stable/sql-statement-calibrate-resource) 语句来估算集群容量。 + +对于 TiDB Cloud,[`CALIBRATE RESOURCE`](https://docs.pingcap.com/tidb/stable/sql-statement-calibrate-resource) 语句不适用。 + + ### 管理资源组 -创建、修改、删除资源组,需要拥有 `SUPER` 或者 `RESOURCE_GROUP_ADMIN` 权限。 +要创建、修改或删除资源组,你需要具有 `SUPER` 或 `RESOURCE_GROUP_ADMIN` 权限。 -你可以通过 [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) 在集群中创建资源组。 +你可以使用 [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) 为集群创建资源组。 -对于已有的资源组,可以通过 [`ALTER RESOURCE GROUP`](/sql-statements/sql-statement-alter-resource-group.md) 修改资源组的配额,对资源组的配额修改会立即生效。 +对于现有资源组,你可以使用 [`ALTER RESOURCE GROUP`](/sql-statements/sql-statement-alter-resource-group.md) 修改资源组的 `RU_PER_SEC` 选项(每秒补充 RU 的速率)。对资源组的更改会立即生效。 -可以使用 [`DROP RESOURCE GROUP`](/sql-statements/sql-statement-drop-resource-group.md) 删除资源组。 +你可以使用 [`DROP RESOURCE GROUP`](/sql-statements/sql-statement-drop-resource-group.md) 删除资源组。 ### 创建资源组 -下面举例说明如何创建资源组。 +以下是创建资源组的示例。 -1. 创建 `rg1` 资源组,限额是每秒 500 RU,并且允许这个资源组的应用超额占用资源。 +1. 创建资源组 `rg1`。资源限制为每秒 500 RU,并允许该资源组中的应用程序超出资源限制。 ```sql CREATE RESOURCE GROUP IF NOT EXISTS rg1 RU_PER_SEC = 500 BURSTABLE; ``` -2. 创建 `rg2` 资源组,RU 的回填速度是每秒 600 RU。在系统资源充足的时候,不允许这个资源组的应用超额占用资源。 +2. 创建资源组 `rg2`。RU 补充速率为每秒 600 RU,并且不允许该资源组中的应用程序超出资源限制。 ```sql CREATE RESOURCE GROUP IF NOT EXISTS rg2 RU_PER_SEC = 600; ``` -3. 创建 `rg3` 资源组,设置绝对优先级为 `HIGH`。绝对优先级目前支持 `LOW|MEDIUM|HIGH`,资源组的默认绝对优先级为 `MEDIUM`。 +3. 创建资源组 `rg3`,并将绝对优先级设置为 `HIGH`。绝对优先级当前支持 `LOW|MEDIUM|HIGH`。默认值为 `MEDIUM`。 ```sql CREATE RESOURCE GROUP IF NOT EXISTS rg3 RU_PER_SEC = 100 PRIORITY = HIGH; @@ -147,157 +199,157 @@ Request Unit (RU) 是 TiDB 对 CPU、IO 等系统资源的统一抽象的计量 ### 绑定资源组 -TiDB 支持如下三个级别的资源组设置: +TiDB 支持以下三个级别的资源组设置。 -- 用户级别。通过 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 或 [`ALTER USER`](/sql-statements/sql-statement-alter-user.md#修改用户绑定的资源组) 语句将用户绑定到特定的资源组。绑定后,对应的用户新创建的会话会自动绑定对应的资源组。 -- 会话级别。通过 [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md) 设置当前会话使用的资源组。 -- 语句级别。通过 [`RESOURCE_GROUP()`](/optimizer-hints.md#resource_groupresource_group_name) Optimizer Hint 设置当前语句使用的资源组。 +- 用户级别。通过 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 或 [`ALTER USER`](/sql-statements/sql-statement-alter-user.md#修改用户绑定的资源组) 语句将用户绑定到特定资源组。用户绑定到资源组后,该用户创建的会话会自动绑定到相应的资源组。 +- 会话级别。通过 [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md) 设置当前会话的资源组。 +- 语句级别。通过 [`RESOURCE_GROUP()`](/optimizer-hints.md#resource_groupresource_group_name) 优化器提示设置当前语句的资源组。 #### 将用户绑定到资源组 -下面的示例创建一个用户 `usr1` 并将其绑定到资源组 `rg1`。其中 `rg1` 为[创建资源组](#创建资源组)示例中创建的资源组。 +以下示例创建用户 `usr1` 并将其绑定到资源组 `rg1`。`rg1` 是在[创建资源组](#创建资源组)示例中创建的资源组。 ```sql CREATE USER 'usr1'@'%' IDENTIFIED BY '123' RESOURCE GROUP rg1; ``` -下面示例使用 `ALTER USER` 将用户 `usr2` 绑定到资源组 `rg2`。其中 `rg2` 为[创建资源组](#创建资源组)示例中创建的资源组。 +以下示例使用 `ALTER USER` 将用户 `usr2` 绑定到资源组 `rg2`。`rg2` 是在[创建资源组](#创建资源组)示例中创建的资源组。 ```sql ALTER USER usr2 RESOURCE GROUP rg2; ``` -绑定用户后,用户新建立的会话对资源的占用会受到指定用量 (RU) 的限制。如果系统负载比较高,没有多余的容量,用户 `usr2` 的资源消耗速度会被严格控制不超过指定用量。由于 `usr1` 绑定的 `rg1` 配置了 `BURSTABLE`,所以 `usr1` 消耗速度允许超过指定用量。 +绑定用户后,新创建的会话的资源消耗将受到指定配额(Request Unit,RU)的控制。如果系统工作负载相对较高且没有空闲容量,`usr2` 的资源消耗率将被严格控制不超过配额。因为 `usr1` 绑定的是配置了 `BURSTABLE` 的 `rg1`,所以允许 `usr1` 的消耗率超过配额。 -如果资源组对应的请求太多导致资源组的资源不足,客户端的请求处理会发生等待。如果等待时间过长,请求会报错。 +如果有太多请求导致资源组资源不足,客户端的请求将等待。如果等待时间太长,请求将报错。 > **注意:** > -> - 使用 `CREATE USER` 或者 `ALTER USER` 将用户绑定到资源组后,只会对该用户新建的会话生效,不会对该用户已有的会话生效。 -> - TiDB 集群在初始化时会自动创建 `default` 资源组,其 `RU_PER_SEC` 的默认值为 `UNLIMITED` (等同于 `INT` 类型最大值,即 `2147483647`),且为 `BURSTABLE` 模式。对于没有绑定资源组的语句会自动绑定至此资源组。此资源组不支持删除,但允许修改其 RU 的配置。 +> - 当你使用 `CREATE USER` 或 `ALTER USER` 将用户绑定到资源组时,它不会对用户的现有会话生效,而只会对用户的新会话生效。 +> - TiDB 在集群初始化期间自动创建 `default` 资源组。对于此资源组,`RU_PER_SEC` 的默认值为 `UNLIMITED`(相当于 `INT` 类型的最大值,即 `2147483647`),并且处于 `BURSTABLE` 模式。未绑定到资源组的语句会自动绑定到此资源组。此资源组不支持删除,但你可以修改其 RU 配置。 -要解除用户与资源组的绑定,只需将其重新绑定到 `default` 资源组即可,如下所示: +要将用户从资源组解绑,你可以简单地将它们重新绑定到 `default` 组,如下所示: ```sql ALTER USER 'usr3'@'%' RESOURCE GROUP `default`; ``` -更多信息,请参见 [`ALTER USER ... RESOURCE GROUP`](/sql-statements/sql-statement-alter-user.md#修改用户绑定的资源组)。 +更多详情,请参见 [`ALTER USER ... RESOURCE GROUP`](/sql-statements/sql-statement-alter-user.md#修改用户绑定的资源组)。 #### 将当前会话绑定到资源组 -通过把当前会话绑定到资源组,会话对资源的占用会受到指定用量 (RU) 的限制。 +通过将会话绑定到资源组,相应会话的资源使用受到指定使用量(RU)的限制。 -下面的示例将当前的会话绑定至资源组 `rg1`。 +以下示例将当前会话绑定到资源组 `rg1`。 ```sql SET RESOURCE GROUP rg1; ``` -#### 将语句绑定到资源组 +#### 将当前语句绑定到资源组 -通过在 SQL 语句中添加 [`RESOURCE_GROUP(resource_group_name)`](/optimizer-hints.md#resource_groupresource_group_name) Hint,可以将该语句绑定到指定的资源组。此 Hint 支持 `SELECT`、`INSERT`、`UPDATE`、`DELETE` 四种语句。 +通过在 SQL 语句中添加 [`RESOURCE_GROUP(resource_group_name)`](/optimizer-hints.md#resource_groupresource_group_name) 提示,你可以指定语句绑定的资源组。此提示支持 `SELECT`、`INSERT`、`UPDATE` 和 `DELETE` 语句。 -示例: +以下示例将当前语句绑定到资源组 `rg1`。 ```sql SELECT /*+ RESOURCE_GROUP(rg1) */ * FROM t limit 10; ``` -### 管理资源消耗超出预期的查询 (Runaway Queries) +### 管理消耗超出预期资源的查询(Runaway Queries) -Runaway Query 是指执行时间或消耗资源超出预期的查询(仅指 `SELECT` 语句)。下面使用 **Runaway Queries** 表示管理 Runaway Query 这一功能。 +Runaway query 是指消耗时间或资源超出预期的查询(仅限 `SELECT` 语句)。以下使用 **runaway queries** 来描述管理 runaway query 的功能。 -- 自 v7.2.0 起,TiDB 资源管控引入了对 Runaway Queries 的管理。你可以针对某个资源组设置条件来识别 Runaway Queries,并自动发起应对操作,防止集群资源完全被 Runaway Queries 占用而影响其他正常查询。你可以在 [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) 或者 [`ALTER RESOURCE GROUP`](/sql-statements/sql-statement-alter-resource-group.md) 中配置 `QUERY_LIMIT` 字段,通过规则识别来管理资源组的 Runaway Queries。 -- 自 v7.3.0 起,TiDB 资源管控引入了手动管理 Runaway Queries 监控列表的功能,将给定的 SQL 或者 Digest 添加到隔离监控列表,从而实现快速隔离 Runaway Queries。你可以执行语句 [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md),手动管理资源组中的 Runaway Queries 监控列表。 +- 从 v7.2.0 开始,资源控制功能引入了对 runaway queries 的管理。你可以为资源组设置标准来识别 runaway queries,并自动采取行动防止它们耗尽资源和影响其他查询。你可以通过在 [`CREATE RESOURCE GROUP`](/sql-statements/sql-statement-create-resource-group.md) 或 [`ALTER RESOURCE GROUP`](/sql-statements/sql-statement-alter-resource-group.md) 中包含 `QUERY_LIMIT` 字段来管理资源组的 runaway queries。 +- 从 v7.3.0 开始,资源控制功能引入了 runaway watches 的手动管理,可以快速识别给定 SQL 语句或 Digest 的 runaway queries。你可以执行 [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md) 语句来手动管理资源组中的 runaway queries 监视列表。 -#### `QUERY_LIMIT` 参数说明 +#### `QUERY_LIMIT` 参数 支持的条件设置: -- `EXEC_ELAPSED`: 当查询执行的时间超限时,识别为 Runaway Query。 +- `EXEC_ELAPSED`:当查询执行时间超过此限制时,将其识别为 runaway query。 -支持的应对操作 (`ACTION`): +支持的操作(`ACTION`): -- `DRYRUN`:对执行 Query 不做任何操作,仅记录识别的 Runaway Query。主要用于观测设置条件是否合理。 -- `COOLDOWN`:将查询的执行优先级降到最低,查询仍旧会以低优先级继续执行,不占用其他操作的资源。 -- `KILL`:识别到的查询将被自动终止,报错 `Query execution was interrupted, identified as runaway query`。 +- `DRYRUN`:不采取任何行动。仅为 runaway queries 添加记录。这主要用于观察条件设置是否合理。 +- `COOLDOWN`:将查询的执行优先级降低到最低级别。查询继续以最低优先级执行,不占用其他操作的资源。 +- `KILL`:自动终止被识别的查询并报错 `Query execution was interrupted, identified as runaway query`。 -为了避免并发的 Runaway Query 过多导致系统资源耗尽,资源管控引入了 Runaway Query 监控机制,能够快速识别并隔离 Runaway Query。该功能通过 `WATCH` 子句实现,当某一个查询被识别为 Runaway Query 之后,会提取这个查询的匹配特征(由 `WATCH` 后的匹配方式参数决定),在接下来的一段时间里(由 `DURATION` 定义),这个 Runaway Query 的匹配特征会被加入到监控列表,TiDB 实例会将查询和监控列表进行匹配,匹配到的查询直接标记为 Runaway Query,而不再等待其被条件识别,并按照当前应对操作进行隔离。其中 `KILL` 会终止该查询,并报错 `Quarantined and interrupted because of being in runaway watch list`。 +为了避免太多并发的 runaway queries 耗尽系统资源,资源控制功能引入了快速识别机制,可以快速识别和隔离 runaway queries。你可以通过 `WATCH` 子句使用此功能。当查询被识别为 runaway query 时,此机制提取查询的匹配特征(由 `WATCH` 后的参数定义)。在接下来的一段时间内(由 `DURATION` 定义),runaway query 的匹配特征被添加到监视列表中,TiDB 实例将查询与监视列表进行匹配。匹配的查询直接被标记为 runaway queries 并根据相应的操作进行隔离,而不是等待它们被条件识别。`KILL` 操作终止查询并报错 `Quarantined and interrupted because of being in runaway watch list`。 -`WATCH` 有三种匹配方式: +`WATCH` 有三种匹配方法用于快速识别: -- `EXACT` 表示完全相同的 SQL 才会被快速识别 -- `SIMILAR` 表示会忽略字面值 (Literal),通过 SQL Digest 匹配所有模式 (Pattern) 相同的 SQL -- `PLAN` 表示通过 Plan Digest 匹配所有模式 (Pattern) 相同的 SQL +- `EXACT` 表示只有完全相同的 SQL 文本才会被快速识别。 +- `SIMILAR` 表示通过 SQL Digest 匹配所有具有相同模式的 SQL 语句,忽略字面值。 +- `PLAN` 表示通过 Plan Digest 匹配所有具有相同模式的 SQL 语句。 -`WATCH` 中的 `DURATION` 选项,用于表示此识别项的持续时间,默认为无限长。 +`WATCH` 中的 `DURATION` 选项表示识别项的持续时间,默认为无限期。 -添加监控项后,匹配特征和 `ACTION` 都不会随着 `QUERY_LIMIT` 配置的修改或删除而改变或删除。可以使用 `QUERY WATCH REMOVE` 来删除监控项。 +添加监视项后,无论 `QUERY_LIMIT` 配置如何更改或删除,匹配特征和 `ACTION` 都不会更改或删除。你可以使用 `QUERY WATCH REMOVE` 删除监视项。 -`QUERY_LIMIT` 具体格式如下: +`QUERY_LIMIT` 的参数如下: -| 参数 | 含义 | 备注 | +| 参数 | 描述 | 说明 | |---------------|--------------|--------------------------------------| -| `EXEC_ELAPSED` | 当查询执行时间超过该值后被识别为 Runaway Query | EXEC_ELAPSED =`60s` 表示查询的执行时间超过 60 秒则被认为是 Runaway Query。 | -| `ACTION` | 当识别到 Runaway Query 时进行的动作 | 可选值有 `DRYRUN`,`COOLDOWN`,`KILL`。 | -| `WATCH` | 快速匹配已经识别到的 Runaway Query,即在一定时间内再碰到相同或相似查询直接进行相应动作 | 可选项,配置例如 `WATCH=SIMILAR DURATION '60s'`、`WATCH=EXACT DURATION '1m'`、`WATCH=PLAN`。 | +| `EXEC_ELAPSED` | 当查询执行时间超过此值时,将其识别为 runaway query | EXEC_ELAPSED =`60s` 表示如果执行时间超过 60 秒,则将查询识别为 runaway query。 | +| `ACTION` | 识别到 runaway query 时采取的行动 | 可选值为 `DRYRUN`、`COOLDOWN` 和 `KILL`。 | +| `WATCH` | 快速匹配已识别的 runaway query。如果在一定时间内再次遇到相同或类似的查询,立即执行相应的操作。 | 可选。例如 `WATCH=SIMILAR DURATION '60s'`、`WATCH=EXACT DURATION '1m'` 和 `WATCH=PLAN`。 | #### 示例 -1. 创建 `rg1` 资源组,限额是每秒 500 RU,并且定义超过 60 秒为 Runaway Query,并对 Runaway Query 降低优先级执行。 +1. 创建资源组 `rg1`,配额为每秒 500 RU,并定义超过 60 秒的查询为 runaway query,并降低 runaway query 的优先级。 ```sql CREATE RESOURCE GROUP IF NOT EXISTS rg1 RU_PER_SEC = 500 QUERY_LIMIT=(EXEC_ELAPSED='60s', ACTION=COOLDOWN); ``` -2. 修改 `rg1` 资源组,对 Runaway Query 直接终止,并且在接下来的 10 分钟里,把相同模式的查询直接标记为 Runaway Query。 +2. 更改 `rg1` 资源组以终止 runaway queries,并在接下来的 10 分钟内立即将具有相同模式的查询标记为 runaway queries。 ```sql ALTER RESOURCE GROUP rg1 QUERY_LIMIT=(EXEC_ELAPSED='60s', ACTION=KILL, WATCH=SIMILAR DURATION='10m'); ``` -3. 修改 `rg1` 资源组,取消 Runaway Queries 检查。 +3. 更改 `rg1` 资源组以取消 runaway query 检查。 ```sql ALTER RESOURCE GROUP rg1 QUERY_LIMIT=NULL; ``` -#### `QUERY WATCH` 语句说明 +#### `QUERY WATCH` 参数 -语法详见 [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md)。 +有关 `QUERY WATCH` 的语法概要,请参见 [`QUERY WATCH`](/sql-statements/sql-statement-query-watch.md)。 -参数说明如下: +参数如下: -- `RESOURCE GROUP` 用于指定资源组。此语句添加的 Runaway Queries 监控特征将添加到该资源组的监控列表中。此参数可以省略,省略时作用于 `default` 资源组。 -- `ACTION` 的含义与 `QUERY LIMIT` 相同。此参数可以省略,省略时表示识别后的对应操作采用此时资源组中 `QUERY LIMIT` 配置的 `ACTION`,且不会随着 `QUERY LIMIT` 配置的改变而改变。如果资源组没有配置 `ACTION`,会报错。 -- `QueryWatchTextOption` 参数有 `SQL DIGEST`、`PLAN DIGEST`、`SQL TEXT` 三种类型。 - - `SQL DIGEST` 的含义与 `QUERY LIMIT` `WATCH` 类型中的 `SIMILAR` 相同,后面紧跟的参数可以是字符串、用户自定义变量以及其他计算结果为字符串的表达式。字符串长度必须为 64,与 TiDB 中关于 Digest 的定义一致。 - - `PLAN DIGEST` 的含义与 `PLAN` 相同。输入参数为 Digest 字符串。 - - `SQL TEXT` 可以根据后面紧跟的参数,将输入的 SQL 的原始字符串(使用 `EXACT` 选项)作为模式匹配项,或者经过解析和编译转化为 `SQL DIGEST`(使用 `SIMILAR` 选项)、`PLAN DIGEST`(使用 `PLAN` 选项)来作为模式匹配项。 +- `RESOURCE GROUP` 指定资源组。此语句添加的 runaway queries 匹配特征将添加到该资源组的监视列表中。此参数可以省略。如果省略,则应用于 `default` 资源组。 +- `ACTION` 的含义与 `QUERY LIMIT` 相同。此参数可以省略。如果省略,识别后的相应操作采用资源组中 `QUERY LIMIT` 配置的 `ACTION`,且操作不随 `QUERY LIMIT` 配置变化。如果资源组中没有配置 `ACTION`,则报错。 +- `QueryWatchTextOption` 参数有三个选项:`SQL DIGEST`、`PLAN DIGEST` 和 `SQL TEXT`。 + - `SQL DIGEST` 与 `SIMILAR` 相同。以下参数接受字符串、用户定义变量或产生字符串结果的其他表达式。字符串长度必须为 64,与 TiDB 中的 Digest 定义相同。 + - `PLAN DIGEST` 与 `PLAN` 相同。以下参数是 Digest 字符串。 + - `SQL TEXT` 将输入 SQL 作为原始字符串匹配(`EXACT`),或根据以下参数解析并编译为 `SQL DIGEST`(`SIMILAR`)或 `PLAN DIGEST`(`PLAN`)。 -- 为默认资源组的 Runaway Queries 监控列表添加监控匹配特征(需要提前为默认资源组设置 `QUERY LIMIT`)。 +- 为默认资源组的 runaway query 监视列表添加匹配特征(需要提前为默认资源组设置 `QUERY LIMIT`)。 ```sql QUERY WATCH ADD ACTION KILL SQL TEXT EXACT TO 'select * from test.t2'; ``` -- 通过将 SQL 解析成 SQL Digest,为 `rg1` 资源组的 Runaway Queries 监控列表添加监控匹配特征。未指定 `ACTION` 时,使用 `rg1` 资源组已配置的 `ACTION`。 +- 通过将 SQL 解析为 SQL Digest 为 `rg1` 资源组的 runaway query 监视列表添加匹配特征。当未指定 `ACTION` 时,使用已为 `rg1` 资源组配置的 `ACTION` 选项。 ```sql QUERY WATCH ADD RESOURCE GROUP rg1 SQL TEXT SIMILAR TO 'select * from test.t2'; ``` -- 通过 PLAN Digest 为 `rg1` 资源组的 Runaway Queries 监控列表添加监控匹配特征。 +- 使用 `PLAN DIGEST` 为 `rg1` 资源组的 runaway query 监视列表添加匹配特征。 ```sql QUERY WATCH ADD RESOURCE GROUP rg1 ACTION KILL PLAN DIGEST 'd08bc323a934c39dc41948b0a073725be3398479b6fa4f6dd1db2a9b115f7f57'; ``` -- 通过查询 `INFORMATION_SCHEMA.RUNAWAY_WATCHES` 获取监控项 ID,删除该监控项。 +- 通过查询 `INFORMATION_SCHEMA.RUNAWAY_WATCHES` 获取监视项 ID 并删除监视项。 ```sql - SELECT * FROM INFORMATION_SCHEMA.RUNAWAY_WATCHES ORDER BY id; + SELECT * from information_schema.runaway_watches ORDER BY id; ``` ```sql @@ -319,9 +371,9 @@ Runaway Query 是指执行时间或消耗资源超出预期的查询(仅指 `S #### 可观测性 -可以通过以下系统表和 `INFORMATION_SCHEMA` 表获得 Runaway 相关的更多信息: +你可以从以下系统表和 `INFORMATION_SCHEMA` 获取有关 runaway queries 的更多信息: -+ `mysql.tidb_runaway_queries` 表中包含了过去 7 天内所有识别到的 Runaway Queries 的历史记录。以其中一行为例: ++ `mysql.tidb_runaway_queries` 表包含过去 7 天内识别的所有 runaway queries 的历史记录。以下是其中一行的示例: ```sql MySQL [(none)]> SELECT * FROM mysql.tidb_runaway_queries LIMIT 1\G @@ -335,42 +387,55 @@ Runaway Query 是指执行时间或消耗资源超出预期的查询(仅指 `S tidb_server: 127.0.0.1:4000 ``` - 其中,`match_type` 为该 Runaway Query 的来源,其值如下: - - - `identify` 表示命中条件。 - - `watch` 表示被快速识别机制命中。 + 在上述输出中,`match_type` 表示 runaway query 是如何被识别的。值可以是以下之一: -+ `information_schema.runaway_watches` 表中包含了 Runaway Queries 的快速识别规则记录。详见 [`RUNAWAY_WATCHES`](/information-schema/information-schema-runaway-watches.md)。 + - `identify` 表示它匹配 runaway query 的条件。 + - `watch` 表示它匹配监视列表中的快速识别规则。 ++ `information_schema.runaway_watches` 表包含 runaway queries 快速识别规则的记录。更多信息,请参见 [`RUNAWAY_WATCHES`](/information-schema/information-schema-runaway-watches.md)。 ### 管理后台任务 > **警告:** > -> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请[提交 issue](/support.md) 反馈。 +> 此功能为实验特性。不建议在生产环境中使用。此功能可能会在没有预先通知的情况下进行更改或移除。如果发现 bug,你可以在 GitHub 上报告一个[问题](https://docs.pingcap.com/tidb/stable/support)。 > -> 资源管控的后台任务管理是基于 TiKV 的 CPU/IO 的资源利用率动态调整资源配额的,因此它依赖各个实例可用资源上限 (Quota)。如果在单个服务器混合部署多个组件或实例,需要通过 cgroup 为各个实例设置合适的资源上限 (Quota)。TiUP Playground 这类共享资源的配置很难表现出预期效果。 +> 资源控制中的后台任务管理基于 TiKV 对 CPU/IO 利用率的资源配额动态调整。因此,它依赖于每个实例的可用资源配额。如果在单个服务器上部署多个组件或实例,必须通过 `cgroup` 为每个实例设置适当的资源配额。在像 TiUP Playground 这样的共享资源部署中很难达到预期效果。 + +后台任务,如数据备份和自动统计信息收集,是低优先级但消耗大量资源的任务。这些任务通常是周期性或不定期触发的。在执行过程中,它们会消耗大量资源,从而影响在线高优先级任务的性能。 -后台任务是指那些优先级不高但是需要消耗大量资源的任务,如数据备份和自动统计信息收集等。这些任务通常定期或不定期触发,在执行的时候会消耗大量资源,从而影响在线的高优先级任务的性能。 +从 v7.4.0 开始,TiDB 资源控制功能支持管理后台任务。当一个任务被标记为后台任务时,TiKV 会动态限制此类任务使用的资源,以避免影响其他前台任务的性能。TiKV 实时监控所有前台任务消耗的 CPU 和 IO 资源,并根据实例的总资源限制计算后台任务可以使用的资源阈值。所有后台任务在执行过程中都受此阈值限制。 -自 v7.4.0 开始,TiDB 资源管控引入了对后台任务的管理。当一种任务被标记为后台任务时,TiKV 会动态地限制该任务的资源使用,以尽量避免此类任务在执行时对其他前台任务的性能产生影响。TiKV 通过实时地监测所有前台任务所消耗的 CPU 和 IO 等资源,并根据实例总的资源上限计算出后台任务可使用的资源阈值,所有后台任务在执行时会受此阈值的限制。 +#### `BACKGROUND` 参数 -#### `BACKGROUND` 参数说明 +`TASK_TYPES`:指定需要作为后台任务管理的任务类型。使用逗号(`,`)分隔多个任务类型。 -`TASK_TYPES`:设置需要作为后台任务管理的任务类型,多个任务类型以 `,` 分隔。 +TiDB 支持以下类型的后台任务: -目前 TiDB 支持如下几种后台任务的类型: + -- `lightning`:使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 执行导入任务。同时支持 TiDB Lightning 的物理和逻辑导入模式。 -- `br`:使用 [BR](/br/backup-and-restore-overview.md) 执行数据备份和恢复。目前不支持 PITR。 -- `ddl`:对于 Reorg DDL,控制批量数据回写阶段的资源使用。 -- `stats`:对应手动执行或系统自动触发的[收集统计信息](/statistics.md#收集统计信息)任务。 -- `background`:预留的任务类型,可使用 [`tidb_request_source_type`](/system-variables.md#tidb_request_source_type-从-v740-版本开始引入) 系统变量指定当前会话的任务类型为 `background`。 +- `lightning`:使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 执行导入任务。支持 TiDB Lightning 的物理导入和逻辑导入模式。 +- `br`:使用 [BR](/br/backup-and-restore-overview.md) 执行备份和恢复任务。不支持 PITR。 +- `ddl`:控制 Reorg DDL 批量数据写回阶段的资源使用。 +- `stats`:手动执行或由 TiDB 自动触发的[收集统计信息](/statistics.md#收集统计信息)任务。 +- `background`:预留的任务类型。你可以使用 [`tidb_request_source_type`](/system-variables.md#tidb_request_source_type-new-in-v740) 系统变量将当前会话的任务类型指定为 `background`。 -默认情况下,被标记为后台任务的任务类型为 `""`,此时后台任务的管理功能处于关闭状态。如需开启后台任务管理功能,你需要手动修改 `default` 资源组的后台任务类型以开启后台任务管理。后台任务类型被识别匹配后,资源管控会自动进行,即当系统资源紧张时,后台任务会自动降为最低优先级,保证前台任务的执行。 + + + + +- `lightning`:使用 [TiDB Lightning](https://docs.pingcap.com/tidb/stable/tidb-lightning-overview) 执行导入任务。支持 TiDB Lightning 的物理导入和逻辑导入模式。 +- `br`:使用 [BR](https://docs.pingcap.com/tidb/stable/backup-and-restore-overview) 执行备份和恢复任务。不支持 PITR。 +- `ddl`:控制 Reorg DDL 批量数据写回阶段的资源使用。 +- `stats`:手动执行或由 TiDB 自动触发的[收集统计信息](/statistics.md#收集统计信息)任务。 +- `background`:预留的任务类型。你可以使用 [`tidb_request_source_type`](/system-variables.md#tidb_request_source_type-new-in-v740) 系统变量将当前会话的任务类型指定为 `background`。 + + + +默认情况下,标记为后台任务的任务类型为 `""`,后台任务管理功能被禁用。要启用后台任务管理,你需要手动修改 `default` 资源组的后台任务类型。后台任务被识别和匹配后,会自动执行资源控制。这意味着当系统资源不足时,后台任务会自动降低到最低优先级,以确保前台任务的执行。 > **注意:** > -> 目前,所有资源组的后台任务默认都会绑定到默认资源组 `default` 下进行管控,你可以通过 `default` 全局管控后台任务类型。暂不支持将后台任务绑定到其他资源组。 +> 目前,所有资源组的后台任务都绑定到 `default` 资源组。你可以通过 `default` 全局管理后台任务类型。目前不支持将后台任务绑定到其他资源组。 #### 示例 @@ -380,13 +445,13 @@ Runaway Query 是指执行时间或消耗资源超出预期的查询(仅指 `S ALTER RESOURCE GROUP `default` BACKGROUND=(TASK_TYPES='br,ddl'); ``` -2. 修改 `default` 资源组,将后台任务的类型还原为默认值。 +2. 更改 `default` 资源组以将后台任务类型恢复为默认值。 ```sql ALTER RESOURCE GROUP `default` BACKGROUND=NULL; ``` -3. 修改 `default` 资源组,将后台任务的类型设置为空,此时此资源组的所有任务类型都不会作为后台任务处理。 +3. 更改 `default` 资源组以将后台任务类型设置为空。在这种情况下,此资源组的所有任务都不会被视为后台任务。 ```sql ALTER RESOURCE GROUP `default` BACKGROUND=(TASK_TYPES=""); @@ -398,7 +463,7 @@ Runaway Query 是指执行时间或消耗资源超出预期的查询(仅指 `S SELECT * FROM information_schema.resource_groups WHERE NAME="default"; ``` - 输出结果如下: + 输出如下: ``` +---------+------------+----------+-----------+-------------+---------------------+ @@ -408,48 +473,66 @@ Runaway Query 是指执行时间或消耗资源超出预期的查询(仅指 `S +---------+------------+----------+-----------+-------------+---------------------+ ``` -5. 如果希望将当前会话里的任务显式标记为后台类型,你可以使用 `tidb_request_source_type` 显式指定任务类型,如: +5. 要显式地将当前会话中的任务标记为后台类型,你可以使用 `tidb_request_source_type` 显式指定任务类型。以下是一个示例: ``` sql SET @@tidb_request_source_type="background"; - /* 添加 background 任务类型 */ + /* 添加后台任务类型 */ ALTER RESOURCE GROUP `default` BACKGROUND=(TASK_TYPES="background"); /* 在当前会话中执行 LOAD DATA */ LOAD DATA INFILE "s3://resource-control/Lightning/test.customer.aaaa.csv" ``` -## 关闭资源管控特性 +## 禁用资源控制 -1. 执行以下命令关闭资源管控特性: + + +1. 执行以下语句以禁用资源控制功能。 ```sql SET GLOBAL tidb_enable_resource_control = 'OFF'; ``` -2. 将 TiKV 参数 [`resource-control.enabled`](/tikv-configuration-file.md#resource-control) 设为 `false`,关闭按照资源组配额调度。 +2. 将 TiKV 参数 [`resource-control.enabled`](/tikv-configuration-file.md#resource-control) 设置为 `false` 以禁用基于资源组的 RU 调度。 + +3. 将 TiFlash 配置项 [`enable_resource_control`](/tiflash/tiflash-configuration.md#configure-the-tiflashtoml-file) 设置为 `false` 以禁用 TiFlash 资源控制。 + + + + + +1. 执行以下语句以禁用资源控制功能。 + + ```sql + SET GLOBAL tidb_enable_resource_control = 'OFF'; + ``` + +2. 对于 TiDB 自管理版本,你可以使用 `resource-control.enabled` 参数来控制是否基于资源组配额使用请求调度。对于 TiDB Cloud,`resource-control.enabled` 参数默认值为 `true` 且不支持动态修改。如果需要为 TiDB Cloud Dedicated 集群禁用它,请联系 [TiDB Cloud Support](/tidb-cloud/tidb-cloud-support.md)。 + +3. 对于 TiDB 自管理版本,你可以使用 `enable_resource_control` 配置项来控制是否启用 TiFlash 资源控制。对于 TiDB Cloud,`enable_resource_control` 参数默认值为 `true` 且不支持动态修改。如果需要为 TiDB Cloud Dedicated 集群禁用它,请联系 [TiDB Cloud Support](/tidb-cloud/tidb-cloud-support.md)。 -3. 将 TiFlash 参数 [`enable_resource_control`](/tiflash/tiflash-configuration.md#配置文件-tiflashtoml) 设为 `false`,关闭 TiFlash 资源管控。 + ## 查看 RU 消耗 -你可以查看 RU 消耗的相关信息。 +你可以查看有关 RU 消耗的信息。 ### 查看 SQL 的 RU 消耗 -你可以通过以下方式查询 SQL 消耗的 RU: +你可以通过以下方式查看 SQL 语句的 RU 消耗: - 系统变量 `tidb_last_query_info` - `EXPLAIN ANALYZE` -- 慢查询及对应的系统表 +- 慢查询及其对应的系统表 - `statements_summary` -#### 使用系统变量 `tidb_last_query_info` 查询执行上一条 SQL 语句的 RU 消耗 +#### 通过查询系统变量 `tidb_last_query_info` 查看最后一次 SQL 执行消耗的 RU -TiDB 提供系统变量 [`tidb_last_query_info`](/system-variables.md#tidb_last_query_info-从-v4014-版本开始引入),记录上一条 DML 语句执行的信息,其中包含 SQL 执行消耗的 RU。 +TiDB 提供了系统变量 [`tidb_last_query_info`](/system-variables.md#tidb_last_query_info-new-in-v4014)。此系统变量记录了最后执行的 DML 语句的信息,包括 SQL 执行消耗的 RU。 -使用示例: +示例: -1. 执行 `UPDATE` 语句: +1. 运行 `UPDATE` 语句: ```sql UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id = 1; @@ -460,7 +543,7 @@ TiDB 提供系统变量 [`tidb_last_query_info`](/system-variables.md#tidb_last_ Rows matched: 1 Changed: 1 Warnings: 0 ``` -2. 通过查询系统变量 `tidb_last_query_info`,查看上条执行的语句的相关信息: +2. 查询系统变量 `tidb_last_query_info` 以查看最后执行语句的信息: ```sql SELECT @@tidb_last_query_info; @@ -475,23 +558,33 @@ TiDB 提供系统变量 [`tidb_last_query_info`](/system-variables.md#tidb_last_ 1 row in set (0.01 sec) ``` - 返回结果中的 `ru_consumption` 即为执行此 SQL 语句消耗的 RU。 + 在结果中,`ru_consumption` 是此 SQL 语句执行消耗的 RU。 + +#### 通过 `EXPLAIN ANALYZE` 查看 SQL 执行过程中消耗的 RU + +你可以使用 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md#ru-request-unit-consumption) 语句获取 SQL 执行过程中消耗的 RU 数量。请注意,RU 数量受缓存(例如,[协处理器缓存](/coprocessor-cache.md))的影响。当同一个 SQL 多次执行时,每次执行消耗的 RU 数量可能不同。RU 值不代表每次执行的确切值,但可以作为估算的参考。 + +#### 慢查询及其对应的系统表 -#### 使用 `EXPLAIN ANALYZE` 查询 SQL 执行时所消耗的 RU + -你也可以通过 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md#ru-request-unit-消耗) 语句获取到 SQL 执行时所消耗的 RU。注意 RU 的大小会受缓存的影响(比如[下推计算结果缓存](/coprocessor-cache.md)),多次执行同一条 SQL 所消耗的 RU 可能会有不同。因此这个 RU 值并不代表每次执行的精确值,但可以作为估算的参考。 +当你启用资源控制时,TiDB 的[慢查询日志](/identify-slow-queries.md)和对应的系统表 [`INFORMATION_SCHEMA.SLOW_QUERY`](/information-schema/information-schema-slow-query.md) 包含相应 SQL 的资源组、RU 消耗以及等待可用 RU 的时间。 -#### 慢查询及对应的系统表 + -在开启资源管控时,TiDB 的[慢查询日志](/identify-slow-queries.md)以及对应系统表 [`INFORMATION_SCHEMA.SLOW_QUERY`](/information-schema/information-schema-slow-query.md) 中均包含对应 SQL 所属的资源组、等待可用 RU 的耗时、以及真实 RU 消耗等相关信息。 + -#### 通过 `statements_summary` 查询 RU 相关的统计信息 +当你启用资源控制时,系统表 [`INFORMATION_SCHEMA.SLOW_QUERY`](/information-schema/information-schema-slow-query.md) 包含相应 SQL 的资源组、RU 消耗以及等待可用 RU 的时间。 -TiDB 的系统表 [`INFORMATION_SCHEMA.statements_summary`](/statement-summary-tables.md#statements_summary) 中保存了 SQL 语句归一化聚合后的各种统计信息,可以用于查看分析各个 SQL 语句的执行性能。其中也包含资源管控相关的统计信息,包括资源组名、RU 消耗、等待可用 RU 的耗时等信息。具体请参考[`statements_summary` 字段介绍](/statement-summary-tables.md#statements_summary-字段介绍)。 + + +#### 通过 `statements_summary` 查看 RU 统计信息 + +TiDB 中的系统表 [`INFORMATION_SCHEMA.statements_summary`](/statement-summary-tables.md#statements_summary) 存储了 SQL 语句的规范化和聚合统计信息。你可以使用该系统表查看和分析 SQL 语句的执行性能。它还包含资源控制的统计信息,包括资源组名称、RU 消耗以及等待可用 RU 的时间。更多详情,请参见 [`statements_summary` 字段描述](/statement-summary-tables.md#statements_summary-字段描述)。 ### 查看资源组的 RU 消耗 -从 v7.6.0 版本开始,TiDB 提供系统表 [`mysql.request_unit_by_group`](/mysql-schema/mysql-schema.md#资源管控相关系统表) 存放各个资源组每日消耗的 RU 的历史记录。 +从 v7.6.0 开始,TiDB 提供系统表 [`mysql.request_unit_by_group`](/mysql-schema/mysql-schema.md#与资源控制相关的系统表) 来存储每个资源组的 RU 消耗历史记录。 示例: @@ -514,35 +607,50 @@ SELECT * FROM request_unit_by_group LIMIT 5; > **注意:** > -> `mysql.request_unit_by_group` 的数据由 TiDB 的定时任务在每天结束后自动导入。如果某个资源组当天的 RU 消耗为 0,则不会产生一条记录。此表默认只存放最近 3 个月(最多 92 天)的数据。超过此期限的数据会自动被清理。 +> `mysql.request_unit_by_group` 的数据由 TiDB 调度任务在每天结束时自动导入。如果某个资源组在某一天的 RU 消耗为 0,则不会生成记录。默认情况下,此表存储最近三个月(最多 92 天)的数据。超过此期限的数据会自动清除。 +## 监控指标和图表 + + -## 监控与图表 +TiDB 定期收集资源控制的运行时信息,并在 Grafana 的 **TiDB** > **Resource Control** 仪表板中提供指标的可视化图表。这些指标在 [TiDB 重要监控指标](/grafana-tidb-dashboard.md) 的 **Resource Control** 部分有详细说明。 + +TiKV 也记录了来自不同资源组的请求 QPS。更多详情,请参见 [TiKV 监控指标详解](/grafana-tikv-dashboard.md#grpc)。 + +你可以在 TiDB Dashboard 中查看当前 [`RESOURCE_GROUPS`](/information-schema/information-schema-resource-groups.md) 表中的资源组数据。更多详情,请参见[资源管理页面](/dashboard/dashboard-resource-manager.md)。 + + + + + +> **注意:** +> +> 本节仅适用于 TiDB 自管理版本。目前,TiDB Cloud 不提供资源控制指标。 -TiDB 会定时采集资源管控的运行时信息,并在 Grafana 的 **Resource Control Dashboard** 中提供了相关指标的可视化图表,详见 [Resource Control 监控指标详解](/grafana-resource-control-dashboard.md)。 +TiDB 定期收集资源控制的运行时信息,并在 Grafana 的 **TiDB** > **Resource Control** 仪表板中提供指标的可视化图表。 -TiKV 中也记录了来自于不同资源组的请求 QPS,详见 [TiKV 监控指标详解](/grafana-tikv-dashboard.md#grpc)。 +TiKV 也在 Grafana 的 **TiKV** 仪表板中记录了来自不同资源组的请求 QPS。 -TiDB Dashboard 中可以查看当前 [`RESOURCE_GROUPS`](/information-schema/information-schema-resource-groups.md) 表中资源组的数据。详见 [TiDB Dashboard 资源管控页面](/dashboard/dashboard-resource-manager.md)。 + ## 工具兼容性 -资源管控不影响数据导入导出以及其他同步工具的正常使用,BR、TiDB Lightning、TiCDC 等工具不支持对资源管控相关 DDL 的处理,这些工具的资源消耗也不受资源管控的限制。 +资源控制功能不影响数据导入、导出和其他复制工具的常规使用。BR、TiDB Lightning 和 TiCDC 目前不支持处理与资源控制相关的 DDL 操作,它们的资源消耗也不受资源控制限制。 ## 常见问题 -1. 如果我暂时不想使用资源组对资源进行管控,是否一定要关闭这个特性? +1. 如果我不想使用资源组,是否必须禁用资源控制? - 不需要。没有指定任何资源组的用户,将被放入系统预定义的 `default` 资源组,而 `default` 资源组默认拥有无限用量。当所有用户都属于 `default` 资源组时,资源分配方式与关闭资源管控时相同。 + 不需要。未指定任何资源组的用户将被绑定到具有无限资源的 `default` 资源组。当所有用户都属于 `default` 资源组时,资源分配方式与禁用资源控制时相同。 -2. 一个数据库用户是否可以绑定到不同的资源组? +2. 一个数据库用户可以绑定到多个资源组吗? - 不能。一个数据库用户只能绑定到一个资源组。但是,在会话运行的过程中,可以通过 [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md) 设置当前会话使用的资源组。你也可以通过优化器 [`RESOURCE_GROUP()`](/optimizer-hints.md#resource_groupresource_group_name) Hint 为运行的语句设置资源组。 + 不可以。一个数据库用户只能绑定到一个资源组。但是,在会话运行时,你可以使用 [`SET RESOURCE GROUP`](/sql-statements/sql-statement-set-resource-group.md) 设置当前会话使用的资源组。你还可以使用优化器提示 [`RESOURCE_GROUP()`](/optimizer-hints.md#resource_groupresource_group_name) 为运行的语句设置资源组。 -3. 当各个资源组设置的用量 (`RU_PER_SEC`) 总和超出系统容量会发生什么? +3. 当所有资源组的总资源分配(`RU_PER_SEC`)超过系统容量时会发生什么? - TiDB 在创建资源组时不会检查容量。只要系统有足够的空闲资源,TiDB 就会满足每个资源组的用量设置。当系统资源超过限制时,TiDB 会优先满足高优先级 (PRIORITY) 资源组的请求。如果同一优先级的请求无法全部满足,TiDB 会根据用量 (`RU_PER_SEC`) 的大小按比例分配。 + TiDB 在创建资源组时不验证容量。只要系统有足够的可用资源,TiDB 就可以满足每个资源组的资源需求。当系统资源超出限制时,TiDB 优先满足优先级更高的资源组的请求。如果无法满足所有具有相同优先级的请求,TiDB 会根据资源分配(`RU_PER_SEC`)按比例分配资源。 -## 另请参阅 +## 另请参见 * [CREATE RESOURCE GROUP](/sql-statements/sql-statement-create-resource-group.md) * [ALTER RESOURCE GROUP](/sql-statements/sql-statement-alter-resource-group.md) diff --git a/tidb-scheduling.md b/tidb-scheduling.md index 8a4b51679b6f..f978be289f86 100644 --- a/tidb-scheduling.md +++ b/tidb-scheduling.md @@ -1,153 +1,151 @@ --- -title: TiDB 数据库的调度 -summary: TiDB 数据库的调度由 PD(Placement Driver)模块负责管理和实时调度集群数据。PD 需要收集节点和 Region 的状态信息,并根据调度策略制定调度计划,包括增加 / 删除副本、迁移 Leader 角色等基本操作。调度需满足副本数量、位置分布、负载均衡、存储空间利用等需求。PD 通过心跳包收集信息,并根据策略生成调度操作序列,但具体执行由 Region Leader 决定。 +title: TiDB 调度 +summary: 介绍 TiDB 集群中的 PD 调度组件。 --- -# TiDB 数据库的调度 +# TiDB 调度 -[PD](https://github.com/tikv/pd) (Placement Driver) 是 TiDB 集群的管理模块,同时也负责集群数据的实时调度。本文档介绍一下 PD 的设计思想和关键概念。 +Placement Driver ([PD](https://github.com/tikv/pd)) 作为 TiDB 集群的管理者,同时也负责集群中的 Region 调度。本文介绍了 PD 调度组件的设计和核心概念。 -## 场景描述 +## 调度场景 -TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个副本 (Replica),这些副本会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 Raft log。 +TiKV 是 TiDB 使用的分布式键值存储引擎。在 TiKV 中,数据被组织为 Region,并在多个节点上进行复制。在所有副本中,leader 负责读写,而 follower 负责从 leader 复制 Raft 日志。 -需要考虑以下场景: +现在考虑以下场景: -* 为了提高集群的空间利用率,需要根据 Region 的空间占用对副本进行合理的分布。 -* 集群进行跨机房部署的时候,要保证一个机房掉线,不会丢失 Raft Group 的多个副本。 -* 添加一个节点进入 TiKV 集群之后,需要合理地将集群中其他节点上的数据搬到新增节点。 -* 当一个节点掉线时,需要考虑快速稳定地进行容灾。 - * 从节点的恢复时间来看 - * 如果节点只是短暂掉线(重启服务),是否需要进行调度。 - * 如果节点是长时间掉线(磁盘故障,数据全部丢失),如何进行调度。 - * 假设集群需要每个 Raft Group 有 N 个副本,从单个 Raft Group 的副本个数来看 - * 副本数量不够(例如节点掉线,失去副本),需要选择适当的机器的进行补充。 - * 副本数量过多(例如掉线的节点又恢复正常,自动加入集群),需要合理的删除多余的副本。 -* 读/写通过 Leader 进行,Leader 的分布只集中在少量几个节点会对集群造成影响。 -* 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,需要通过调度进行负载均衡。 -* 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移可能会占用大量的网络带宽、磁盘 IO 以及 CPU,进而影响在线服务。 +* 为了高效利用存储空间,同一个 Region 的多个副本需要根据 Region 大小合理地分布在不同节点上; +* 对于多数据中心的拓扑结构,一个数据中心的故障应该只会导致所有 Region 的一个副本失效; +* 当新增 TiKV 节点时,可以将数据重新平衡到新节点; +* 当 TiKV 节点发生故障时,PD 需要考虑: + * 故障节点的恢复时间。 + * 如果时间较短(例如服务重启),是否需要调度。 + * 如果时间较长(例如磁盘故障导致数据丢失),如何进行调度。 + * 所有 Region 的副本。 + * 如果某些 Region 的副本数不足,PD 需要补充副本。 + * 如果某些 Region 的副本数超出预期(例如,故障节点恢复后重新加入集群),PD 需要删除多余的副本。 +* 读写操作在 leader 上进行,不能只分布在少数几个节点上; +* 并非所有 Region 都是热点,因此需要平衡所有 TiKV 节点的负载; +* 在 Region 进行均衡时,数据传输会占用大量网络/磁盘流量和 CPU 时间,这可能会影响在线服务。 -以上问题和场景如果多个同时出现,就不太容易解决,因为需要考虑全局信息。同时整个系统也是在动态变化的,因此需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。 +这些场景可能同时发生,这使得问题更难解决。此外,整个系统是动态变化的,因此需要一个调度器来收集集群的所有信息,然后对集群进行调整。因此,PD 被引入到 TiDB 集群中。 -## 调度的需求 +## 调度需求 -对以上的问题和场景进行分类和整理,可归为以下两类: +上述场景可以分为两类: -**第一类:作为一个分布式高可用存储系统,必须满足的需求,包括几种** +1. 作为一个分布式高可用存储系统必须满足的需求: -* 副本数量不能多也不能少 -* 副本需要根据拓扑结构分布在不同属性的机器上 -* 节点宕机或异常能够自动合理快速地进行容灾 + * 副本数量正确。 + * 副本需要根据不同的拓扑结构分布在不同的机器上。 + * 集群能够自动从 TiKV 节点故障中恢复。 -**第二类:作为一个良好的分布式系统,需要考虑的地方包括** +2. 作为一个良好的分布式系统需要的优化: -* 维持整个集群的 Leader 分布均匀 -* 维持每个节点的储存容量均匀 -* 维持访问热点分布均匀 -* 控制负载均衡的速度,避免影响在线服务 -* 管理节点状态,包括手动上线/下线节点 + * 所有 Region 的 leader 在节点间均匀分布; + * 所有 TiKV 节点的存储容量均衡; + * 热点均衡; + * Region 负载均衡的速度需要限制,以确保在线服务的稳定性; + * 运维人员能够手动上下线节点。 -满足第一类需求后,整个系统将具备强大的容灾功能。满足第二类需求后,可以使得系统整体的资源利用率更高且合理,具备良好的扩展性。 +满足第一类需求后,系统将具有容错能力。满足第二类需求后,资源将被更有效地利用,系统将具有更好的可扩展性。 -为了满足这些需求,首先需要收集足够的信息,比如每个节点的状态、每个 Raft Group 的信息、业务访问操作的统计等;其次需要设置一些策略,PD 根据这些信息以及调度的策略,制定出尽量满足前面所述需求的调度计划;最后需要一些基本的操作,来完成调度计划。 +为了实现这些目标,PD 首先需要收集信息,如节点状态、Raft 组信息和访问节点的统计信息。然后我们需要为 PD 指定一些策略,使 PD 能够根据这些信息和策略制定调度计划。最后,PD 向 TiKV 节点分发一些操作指令来完成调度计划。 -## 调度的基本操作 +## 基本调度操作 -调度的基本操作指的是为了满足调度的策略。上述调度需求可整理为以下三个操作: +所有调度计划包含三种基本操作: -* 增加一个副本 -* 删除一个副本 -* 将 Leader 角色在一个 Raft Group 的不同副本之间 transfer(迁移) +* 添加新副本 +* 删除副本 +* 在 Raft 组内的副本之间转移 Region leader -刚好 Raft 协议通过 `AddReplica`、`RemoveReplica`、`TransferLeader` 这三个命令,可以支撑上述三种基本操作。 +这些操作通过 Raft 命令 `AddReplica`、`RemoveReplica` 和 `TransferLeader` 来实现。 ## 信息收集 -调度依赖于整个集群信息的收集,简单来说,调度需要知道每个 TiKV 节点的状态以及每个 Region 的状态。TiKV 集群会向 PD 汇报两类消息,TiKV 节点信息和 Region 信息: +调度基于信息收集。简而言之,PD 调度组件需要知道所有 TiKV 节点和所有 Region 的状态。TiKV 节点向 PD 报告以下信息: -**每个 TiKV 节点会定期向 PD 汇报节点的状态信息** +- 每个 TiKV 节点报告的状态信息: -TiKV 节点 (Store) 与 PD 之间存在心跳包,一方面 PD 通过心跳包检测每个 Store 是否存活,以及是否有新加入的 Store;另一方面,心跳包中也会携带这个 [Store 的状态信息](https://github.com/pingcap/kvproto/blob/release-8.1/proto/pdpb.proto#L473),主要包括: + 每个 TiKV 节点定期向 PD 发送心跳。PD 不仅检查节点是否存活,还在心跳消息中收集 [`StoreState`](https://github.com/pingcap/kvproto/blob/release-8.1/proto/pdpb.proto#L473)。`StoreState` 包括: -* 总磁盘容量 -* 可用磁盘容量 -* 承载的 Region 数量 -* 数据写入/读取速度 -* 发送/接受的 Snapshot 数量(副本之间可能会通过 Snapshot 同步数据) -* 是否过载 -* labels 标签信息(标签是具备层级关系的一系列 Tag,能够[感知拓扑信息](/schedule-replicas-by-topology-labels.md)) + * 总磁盘空间 + * 可用磁盘空间 + * Region 数量 + * 数据读写速度 + * 发送/接收的快照数量(数据可能通过快照在副本之间复制) + * 节点是否过载 + * 标签(参见[拓扑感知](https://docs.pingcap.com/tidb/stable/schedule-replicas-by-topology-labels)) -通过使用 `pd-ctl` 可以查看到 TiKV Store 的状态信息。TiKV Store 的状态具体分为 Up,Disconnect,Offline,Down,Tombstone。各状态的关系如下: + 你可以使用 PD control 检查 TiKV 节点的状态,状态可以是 Up、Disconnect、Offline、Down 或 Tombstone。以下是所有状态及其关系的描述。 -+ **Up**:表示当前的 TiKV Store 处于提供服务的状态。 -+ **Disconnect**:当 PD 和 TiKV Store 的心跳信息丢失超过 20 秒后,该 Store 的状态会变为 Disconnect 状态,当时间超过 `max-store-down-time` 指定的时间后,该 Store 会变为 Down 状态。 -+ **Down**:表示该 TiKV Store 与集群失去连接的时间已经超过了 `max-store-down-time` 指定的时间,默认 30 分钟。超过该时间后,对应的 Store 会变为 Down,并且开始在存活的 Store 上补足各个 Region 的副本。 -+ **Offline**:当对某个 TiKV Store 通过 PD Control 进行手动下线操作,该 Store 会变为 Offline 状态。该状态只是 Store 下线的中间状态,处于该状态的 Store 会将其上的所有 Region 搬离至其它满足搬迁条件的 Up 状态 Store。当该 Store 的 `leader_count` 和 `region_count` (在 PD Control 中获取) 均显示为 0 后,该 Store 会由 Offline 状态变为 Tombstone 状态。在 Offline 状态下,禁止关闭该 Store 服务以及其所在的物理服务器。下线过程中,如果集群里不存在满足搬迁条件的其它目标 Store(例如没有足够的 Store 能够继续满足集群的副本数量要求),该 Store 将一直处于 Offline 状态。 -+ **Tombstone**:表示该 TiKV Store 已处于完全下线状态,可以使用 `remove-tombstone` 接口安全地清理该状态的 TiKV。从 v6.5.0 开始,如果没有手动处理,当节点转换为 Tombstone 一个月后,PD 将自动删除内部存储的 Tombstone 的记录。 + + **Up**:TiKV 节点正在服务中。 + + **Disconnect**:PD 和 TiKV 节点之间的心跳消息丢失超过 20 秒。如果丢失时间超过 `max-store-down-time` 指定的时间,状态 "Disconnect" 会变为 "Down"。 + + **Down**:PD 和 TiKV 节点之间的心跳消息丢失时间超过 `max-store-down-time`(默认 30 分钟)。在此状态下,TiKV 节点开始在存活的节点上补充每个 Region 的副本。 + + **Offline**:TiKV 节点通过 PD Control 手动下线。这只是节点下线过程的中间状态。处于此状态的节点会将其所有 Region 迁移到满足重定位条件的其他 "Up" 状态的节点。当 `leader_count` 和 `region_count`(通过 PD Control 获取)都显示为 `0` 时,节点状态从 "Offline" 变为 "Tombstone"。在 "Offline" 状态下,**不要**禁用节点服务或节点所在的物理服务器。在节点下线过程中,如果集群没有目标节点来重定位 Region(例如,集群中没有足够的节点来存放副本),节点将一直处于 "Offline" 状态。 + + **Tombstone**:TiKV 节点完全下线。你可以使用 `remove-tombstone` 接口安全地清理处于此状态的 TiKV。从 v6.5.0 开始,如果不手动处理,PD 会在节点转换为 Tombstone 一个月后自动删除内部存储的 Tombstone 记录。 -![TiKV store status relationship](/media/tikv-store-status-relationship.png) + ![TiKV 节点状态关系](/media/tikv-store-status-relationship.png) -**每个 Raft Group 的 Leader 会定期向 PD 汇报 Region 的状态信息** +- Region leader 报告的信息: -每个 Raft Group 的 Leader 和 PD 之间存在心跳包,用于汇报这个 [Region 的状态](https://github.com/pingcap/kvproto/blob/release-8.1/proto/pdpb.proto#L312),主要包括下面几点信息: + 每个 Region leader 定期向 PD 发送心跳以报告 [`RegionState`](https://github.com/pingcap/kvproto/blob/release-8.1/proto/pdpb.proto#L312),包括: -* Leader 的位置 -* Followers 的位置 -* 掉线副本的个数 -* 数据写入/读取的速度 + * leader 自身的位置 + * 其他副本的位置 + * 离线副本的数量 + * 数据读写速度 -PD 不断的通过这两类心跳消息收集整个集群的信息,再以这些信息作为决策的依据。 +PD 通过这两种心跳收集集群信息,然后基于这些信息做出决策。 -除此之外,PD 还可以通过扩展的接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为该 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。 +此外,PD 可以通过扩展接口获取更多信息来做出更精确的决策。例如,如果节点的心跳中断,PD 无法知道该节点是暂时还是永久下线。它只会等待一段时间(默认 30 分钟),如果仍然没有收到心跳,就将该节点视为离线。然后 PD 会将该节点上的所有 Region 平衡到其他节点。 -但是有的时候,是运维人员主动将某台机器下线,这个时候,可以通过 PD 的管理接口通知 PD 该 Store 不可用,PD 就可以马上判断需要将这个 Store 上面的 Region 都调度走。 +但有时节点是由运维人员手动下线的,因此运维人员可以通过 PD control 接口告知 PD。这样 PD 就可以立即开始平衡所有 Region。 -## 调度的策略 +## 调度策略 -PD 收集了这些信息后,还需要一些策略来制定具体的调度计划。 +收集信息后,PD 需要一些策略来制定调度计划。 -**一个 Region 的副本数量正确** +**策略 1:Region 的副本数量需要正确** -当 PD 通过某个 Region Leader 的心跳包发现这个 Region 的副本数量不满足要求时,需要通过 Add/Remove Replica 操作调整副本数量。出现这种情况的可能原因是: +PD 可以从 Region leader 的心跳中知道某个 Region 的副本数量是否不正确。如果发生这种情况,PD 可以通过添加/删除副本来调整副本数量。副本数量不正确的原因可能是: -* 某个节点掉线,上面的数据全部丢失,导致一些 Region 的副本数量不足 -* 某个掉线节点又恢复服务,自动接入集群,这样之前已经补足了副本的 Region 的副本数量过多,需要删除某个副本 -* 管理员调整副本策略,修改了 [max-replicas](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L95) 的配置 +* 节点故障导致某些 Region 的副本数量少于预期; +* 故障节点恢复后,某些 Region 的副本数量可能多于预期; +* [`max-replicas`](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L95) 被修改。 -**一个 Raft Group 中的多个副本不在同一个位置** +**策略 2:Region 的副本需要位于不同位置** -注意这里用的是『同一个位置』而不是『同一个节点』。在一般情况下,PD 只会保证多个副本不落在一个节点上,以避免单个节点失效导致多个副本丢失。在实际部署中,还可能出现下面这些需求: +注意这里的"位置"与"机器"是不同的。通常 PD 只能确保一个 Region 的副本不在同一个节点上,以避免该节点的故障导致多个副本丢失。但在生产环境中,你可能有以下需求: -* 多个节点部署在同一台物理机器上 -* TiKV 节点分布在多个机架上,希望单个机架掉电时,也能保证系统可用性 -* TiKV 节点分布在多个 IDC 中,希望单个机房掉电时,也能保证系统可用性 +* 多个 TiKV 节点在同一台机器上; +* TiKV 节点分布在多个机架上,即使一个机架故障系统也能保持可用; +* TiKV 节点分布在多个数据中心,即使一个数据中心故障系统也能保持可用; -这些需求本质上都是某一个节点具备共同的位置属性,构成一个最小的『容错单元』,希望这个单元内部不会存在一个 Region 的多个副本。这个时候,可以给节点配置 [labels](https://github.com/tikv/tikv/blob/v4.0.0-beta/etc/config-template.toml#L140) 并且通过在 PD 上配置 [location-labels](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L100) 来指名哪些 label 是位置标识,需要在副本分配的时候尽量保证一个 Region 的多个副本不会分布在具有相同的位置标识的节点上。 +这些需求的关键是节点可以有相同的"位置",这是容错的最小单位。一个 Region 的副本不能在同一个单位内。因此,我们可以为 TiKV 节点配置 [labels](https://github.com/tikv/tikv/blob/v4.0.0-beta/etc/config-template.toml#L140),并在 PD 上设置 [location-labels](https://github.com/pingcap/pd/blob/v4.0.0-beta/conf/config.toml#L100) 来指定哪些标签用于标记位置。 -**副本在 Store 之间的分布均匀分配** +**策略 3:副本需要在节点之间保持均衡** -由于每个 Region 的副本中存储的数据容量上限是固定的,通过维持每个节点上面副本数量的均衡,使得各节点间承载的数据更均衡。 +Region 副本的大小限制是固定的,因此在节点之间保持副本均衡有助于数据大小的均衡。 -**Leader 数量在 Store 之间均匀分配** +**策略 4:leader 需要在节点之间保持均衡** -Raft 协议要求读取和写入都通过 Leader 进行,所以计算的负载主要在 Leader 上面,PD 会尽可能将 Leader 在节点间分散开。 +根据 Raft 协议,读写操作在 leader 上执行,因此 PD 需要将 leader 分散到整个集群而不是集中在几个节点上。 -**访问热点数量在 Store 之间均匀分配** +**策略 5:热点需要在节点之间保持均衡** -每个 Store 以及 Region Leader 在上报信息时携带了当前访问负载的信息,比如 Key 的读取/写入速度。PD 会检测出访问热点,且将其在节点之间分散开。 +PD 可以从节点心跳和 Region 心跳中检测热点,从而分散热点。 -**各个 Store 的存储空间占用大致相等** +**策略 6:存储大小需要在节点之间保持均衡** -每个 Store 启动的时候都会指定一个 `Capacity` 参数,表明这个 Store 的存储空间上限,PD 在做调度的时候,会考虑节点的存储空间剩余量。 +TiKV 节点启动时会报告存储 `capacity`,这表示节点的空间限制。PD 在调度时会考虑这一点。 -**控制调度速度,避免影响在线服务** +**策略 7:调整调度速度以稳定在线服务** -调度操作需要耗费 CPU、内存、磁盘 IO 以及网络带宽,需要避免对线上服务造成太大影响。PD 会对当前正在进行的操作数量进行控制,默认的速度控制是比较保守的,如果希望加快调度(比如停服务升级或者增加新节点,希望尽快调度),那么可以通过调节 PD 参数动态加快调度速度。 +调度会占用 CPU、内存、网络和 I/O 流量。过多的资源使用会影响在线服务。因此,PD 需要限制并发调度任务的数量。默认情况下这个策略是保守的,但如果需要更快的调度可以进行调整。 -## 调度的实现 +## 调度实现 -本节介绍调度的实现 +PD 从节点心跳和 Region 心跳收集集群信息,然后根据信息和策略制定调度计划。调度计划是一系列基本操作的序列。每次 PD 从 Region leader 收到 Region 心跳时,它会检查该 Region 是否有待处理的操作。如果 PD 需要向 Region 分派新的操作,它会将操作放入心跳响应中,并通过检查后续的 Region 心跳来监控操作的执行情况。 -PD 不断地通过 Store 或者 Leader 的心跳包收集整个集群信息,并且根据这些信息以及调度策略生成调度操作序列。每次收到 Region Leader 发来的心跳包时,PD 都会检查这个 Region 是否有待进行的操作,然后通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。 - -注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 根据当前自身状态来定。 +注意这里的"操作"只是对 Region leader 的建议,Region 可以选择跳过。Region 的 leader 可以根据其当前状态决定是否跳过调度操作。 diff --git a/tidb-storage.md b/tidb-storage.md index 9897811da12e..964cbc311e2d 100644 --- a/tidb-storage.md +++ b/tidb-storage.md @@ -1,79 +1,82 @@ --- -title: TiDB 数据库的存储 +title: TiDB 存储 summary: 了解 TiDB 数据库的存储层。 --- -# TiDB 数据库的存储 +# TiDB 存储 -本文主要介绍 [TiKV](https://github.com/tikv/tikv) 的一些设计思想和关键概念。 +本文介绍 [TiKV](https://github.com/tikv/tikv) 的一些设计理念和关键概念。 ![storage-architecture](/media/tidb-storage-architecture-1.png) -## Key-Value Pairs(键值对) +## 键值对 -作为保存数据的系统,首先要决定的是数据的存储模型,也就是数据以什么样的形式保存下来。TiKV 的选择是 Key-Value 模型,并且提供有序遍历方法。 +对于数据存储系统来说,首先要决定的是数据存储模型,即以什么形式保存数据。TiKV 选择了键值(Key-Value)模型,并提供有序遍历方法。TiKV 数据存储模型有两个关键点: -TiKV 数据存储的两个关键点: ++ 这是一个巨大的 Map(类似于 C++ 中的 `std::Map`),用于存储键值对。 ++ Map 中的键值对按照键的二进制顺序排序,这意味着你可以定位到特定键的位置,然后调用 Next 方法按递增顺序获取大于该键的键值对。 -1. 这是一个巨大的 Map(可以类比一下 C++ 的 std::map),也就是存储的是 Key-Value Pairs(键值对) -2. 这个 Map 中的 Key-Value pair 按照 Key 的二进制顺序有序,也就是可以 Seek 到某一个 Key 的位置,然后不断地调用 Next 方法以递增的顺序获取比这个 Key 大的 Key-Value。 +注意,本文描述的 TiKV 的 KV 存储模型与 SQL 表无关。本文不讨论任何与 SQL 相关的概念,仅关注如何实现一个高性能、高可靠性的分布式键值存储系统(如 TiKV)。 -注意,本文所说的 **TiKV 的 KV 存储模型和 SQL 中的 Table 无关**。本文不讨论 SQL 中的任何概念,专注于讨论如何实现 TiKV 这样一个高性能、高可靠性、分布式的 Key-Value 存储。 +## 本地存储(RocksDB) -## 本地存储 (RocksDB) +对于任何持久化存储引擎,数据最终都要保存在磁盘上,TiKV 也不例外。TiKV 不直接写入数据到磁盘,而是将数据存储在 RocksDB 中,由 RocksDB 负责数据存储。这是因为开发一个独立的存储引擎需要付出巨大的成本,特别是一个需要仔细优化的高性能独立引擎。 -任何持久化的存储引擎,数据终归要保存在磁盘上,TiKV 也不例外。但是 TiKV 没有选择直接向磁盘上写数据,而是把数据保存在 RocksDB 中,具体的数据落地由 RocksDB 负责。这个选择的原因是开发一个单机存储引擎工作量很大,特别是要做一个高性能的单机引擎,需要做各种细致的优化,而 RocksDB 是由 Facebook 开源的一个非常优秀的单机 KV 存储引擎,可以满足 TiKV 对单机引擎的各种要求。这里可以简单的认为 RocksDB 是一个单机的持久化 Key-Value Map。 +RocksDB 是 Facebook 开源的一个优秀的独立存储引擎。这个引擎可以满足 TiKV 对单个引擎的各种要求。在这里,你可以简单地将 RocksDB 视为一个单一的持久化键值 Map。 ## Raft 协议 -接下来 TiKV 的实现面临一件更难的事情:如何保证单机失效的情况下,数据不丢失,不出错? +此外,TiKV 的实现面临着一个更困难的问题:如何在单机故障的情况下确保数据安全。 -简单来说,需要想办法把数据复制到多台机器上,这样一台机器无法服务了,其他的机器上的副本还能提供服务;复杂来说,还需要这个数据复制方案是可靠和高效的,并且能处理副本失效的情况。TiKV 选择了 Raft 算法。Raft 是一个一致性协议,本文只会对 Raft 做一个简要的介绍,细节问题可以参考它的[论文](https://raft.github.io/raft.pdf)。Raft 提供几个重要的功能: +一个简单的方法是将数据复制到多台机器上,这样即使一台机器故障,其他机器上的副本仍然可用。换句话说,你需要一个可靠、高效,并且能够处理副本故障情况的数据复制方案。所有这些都可以通过 Raft 算法来实现。 -- Leader(主副本)选举 -- 成员变更(如添加副本、删除副本、转移 Leader 等操作) +Raft 是一个共识算法。本文只简要介绍 Raft。更多详细信息,你可以参考 [In Search of an Understandable Consensus Algorithm](https://raft.github.io/raft.pdf)。Raft 有几个重要特性: + +- Leader 选举 +- 成员变更(如添加副本、删除副本和转移 Leader) - 日志复制 -TiKV 利用 Raft 来做数据复制,每个数据变更都会落地为一条 Raft 日志,通过 Raft 的日志复制功能,将数据安全可靠地同步到复制组的每一个节点中。不过在实际写入中,根据 Raft 的协议,只需要同步复制到多数节点,即可安全地认为数据写入成功。 +TiKV 使用 Raft 来执行数据复制。每个数据变更都会被记录为一条 Raft 日志。通过 Raft 日志复制,数据被安全可靠地复制到 Raft 组的多个节点上。但是,根据 Raft 协议,只要数据被复制到大多数节点上,写入就可以被认为是成功的。 ![Raft in TiDB](/media/tidb-storage-1.png) -总结一下,通过单机的 RocksDB,TiKV 可以将数据快速地存储在磁盘上;通过 Raft,将数据复制到多台机器上,以防单机失效。数据的写入是通过 Raft 这一层的接口写入,而不是直接写 RocksDB。通过实现 Raft,TiKV 变成了一个分布式的 Key-Value 存储,少数几台机器宕机也能通过原生的 Raft 协议自动把副本补全,可以做到对业务无感知。 +总的来说,TiKV 可以通过单机 RocksDB 快速地将数据存储在磁盘上,并通过 Raft 将数据复制到多台机器上以应对机器故障。数据是通过 Raft 接口而不是直接写入 RocksDB。通过实现 Raft,TiKV 成为了一个分布式键值存储系统。即使发生少数机器故障,TiKV 也可以通过原生 Raft 协议自动完成副本复制,不会影响应用。 ## Region -为了便于理解,假设所有的数据都只有一个副本。可以将 TiKV 看作一个巨大而有序的 KV Map,为了实现存储的水平扩展,数据将被分散在多台机器上。对于一个 KV 系统,将数据分散在多台机器上有两种比较典型的方案: +为了便于理解,让我们假设所有数据只有一个副本。如前所述,TiKV 可以被视为一个大型的、有序的 KV Map,因此数据分布在多台机器上以实现水平扩展。对于 KV 系统,有两种典型的方案来将数据分布到多台机器上: -* Hash:按照 Key 做 Hash,根据 Hash 值选择对应的存储节点。 -* Range:按照 Key 分 Range,某一段连续的 Key 都保存在一个存储节点上。 +* Hash:通过键创建 Hash,根据 Hash 值选择对应的存储节点。 +* Range:按键划分范围,将一段连续的键存储在一个节点上。 -TiKV 选择了第二种方式,将整个 Key-Value 空间分成很多段,每一段是一系列连续的 Key,将每一段叫做一个 Region,可以用 `[StartKey,EndKey)` 这样一个左闭右开区间来描述。每个 Region 中保存的数据量默认维持在 96 MiB 左右(可以通过配置修改)。 +TiKV 选择了第二种方案,将整个键值空间划分为一系列连续的键段。每个段称为一个 Region。每个 Region 可以用 `[StartKey, EndKey)` 来描述,这是一个左闭右开的区间。每个 Region 的默认大小限制为 96 MiB,这个大小是可配置的。 ![Region in TiDB](/media/tidb-storage-2.png) -注意,这里的 Region 还是和 SQL 中的表没什么关系。 这里的讨论依然不涉及 SQL,只和 KV 有关。 +注意,这里的 Region 与 SQL 表无关。在本文中,暂时忘记 SQL,只关注 KV。将数据划分为 Region 后,TiKV 将执行两个重要任务: + +* 将数据分布到集群中的所有节点上,并以 Region 为基本单位。尽量确保每个节点上的 Region 数量大致相似。 +* 在 Region 内执行 Raft 复制和成员管理。 -将数据划分成 Region 后,TiKV 将会做两件重要的事情: +这两个任务非常重要,让我们逐一介绍。 -* 以 Region 为单位,将数据分散在集群中所有的节点上,并且尽量保证每个节点上服务的 Region 数量差不多。 -* 以 Region 为单位做 Raft 的复制和成员管理。 +* 首先,数据按键被划分为许多 Region,每个 Region 的数据只存储在一个节点上(忽略多个副本)。TiDB 系统有一个 PD 组件,负责尽可能均匀地将 Region 分布在集群中的所有节点上。这样,一方面实现了存储容量的水平扩展(其他节点上的 Region 会自动调度到新添加的节点);另一方面实现了负载均衡(避免出现一个节点数据很多而其他节点数据很少的情况)。 -这两点非常重要: + 同时,为了确保上层客户端能够访问所需的数据,系统中有一个组件(PD)记录 Region 在节点上的分布情况,即通过任何键都能知道这个键属于哪个 Region 以及该 Region 位于哪个节点。 -* 先看第一点,数据按照 Key 切分成很多 Region,每个 Region 的数据只会保存在一个节点上面(暂不考虑多副本)。TiDB 系统会有一个组件 (PD) 来负责将 Region 尽可能均匀的散布在集群中所有的节点上,这样一方面实现了存储容量的水平扩展(增加新的节点后,会自动将其他节点上的 Region 调度过来),另一方面也实现了负载均衡(不会出现某个节点有很多数据,其他节点上没什么数据的情况)。同时为了保证上层客户端能够访问所需要的数据,系统中也会有一个组件 (PD) 记录 Region 在节点上面的分布情况,也就是通过任意一个 Key 就能查询到这个 Key 在哪个 Region 中,以及这个 Region 目前在哪个节点上(即 Key 的位置路由信息)。至于负责这两项重要工作的组件 (PD),会在后续介绍。 -* 对于第二点,TiKV 是以 Region 为单位做数据的复制,也就是一个 Region 的数据会保存多个副本,TiKV 将每一个副本叫做一个 Replica。Replica 之间是通过 Raft 来保持数据的一致,一个 Region 的多个 Replica 会保存在不同的节点上,构成一个 Raft Group。其中一个 Replica 会作为这个 Group 的 Leader,其他的 Replica 作为 Follower。默认情况下,所有的读和写都是通过 Leader 进行,读操作在 Leader 上即可完成,而写操作再由 Leader 复制给 Follower。 +* 对于第二个任务,TiKV 在 Region 内复制数据,这意味着一个 Region 的数据会有多个副本,称为"Replica"。一个 Region 的多个副本存储在不同的节点上,形成一个 Raft Group,通过 Raft 算法保持一致性。 -大家理解了 Region 之后,应该可以理解下面这张图: + 其中一个副本作为该组的 Leader,其他作为 Follower。默认情况下,所有的读写操作都通过 Leader 处理,其中读操作在 Leader 上执行,写操作则复制到 Follower。下图展示了关于 Region 和 Raft Group 的完整图景。 ![TiDB Storage](/media/tidb-storage-3.png) -以 Region 为单位做数据的分散和复制,TiKV 就成为了一个分布式的具备一定容灾能力的 KeyValue 系统,不用再担心数据存不下,或者是磁盘故障丢失数据的问题。 +通过在 Region 中分布和复制数据,我们得到了一个在某种程度上具有容灾能力的分布式键值系统。你不再需要担心容量问题,也不用担心磁盘故障和数据丢失。 ## MVCC -TiKV 支持多版本并发控制 (Multi-Version Concurrency Control, MVCC)。假设有这样一种场景:某客户端 A 在写一个 Key,另一个客户端 B 同时在对这个 Key 进行读操作。如果没有数据的多版本控制机制,那么这里的读写操作必然互斥。在分布式场景下,这种情况可能会导致性能问题和死锁问题。有了 MVCC,只要客户端 B 执行的读操作的逻辑时间早于客户端 A,那么客户端 B 就可以在客户端 A 写入的同时正确地读原有的值。即使该 Key 被多个写操作修改过多次,客户端 B 也可以按照其逻辑时间读到旧的值。 +TiKV 支持多版本并发控制(MVCC)。考虑一个场景,客户端 A 正在写入一个键的同时,客户端 B 正在读取同一个键。如果没有 MVCC 机制,这些读写操作将互相排斥,在分布式场景下会带来性能问题和死锁。然而,有了 MVCC,只要客户端 B 在客户端 A 写入操作的逻辑时间之前执行读操作,那么在客户端 A 执行写入操作的同时,客户端 B 就可以正确读取原始值。即使这个键被多个写操作修改多次,客户端 B 仍然可以根据其逻辑时间读取旧值。 -TiKV 的 MVCC 是通过在 Key 后面添加版本号来实现的。没有 MVCC 时,可以把 TiKV 看作如下的 Key-Value 对: +TiKV 的 MVCC 是通过在键后面附加版本号来实现的。没有 MVCC 时,TiKV 的键值对如下: ``` Key1 -> Value @@ -82,7 +85,7 @@ Key2 -> Value KeyN -> Value ``` -有了 MVCC 之后,TiKV 的 Key-Value 排列如下: +有了 MVCC 后,TiKV 的键值对如下: ``` Key1_Version3 -> Value @@ -99,8 +102,8 @@ KeyN_Version1 -> Value …… ``` -注意,对于同一个 Key 的多个版本,版本号较大的会被放在前面,版本号小的会被放在后面(见 [Key-Value](#key-value-pairs键值对) 一节,Key 是有序的排列),这样当用户通过一个 Key + Version 来获取 Value 的时候,可以通过 Key 和 Version 构造出 MVCC 的 Key,也就是 Key_Version。然后可以直接通过 RocksDB 的 SeekPrefix(Key_Version) API,定位到第一个大于等于这个 Key_Version 的位置。 +注意,对于同一个键的多个版本,版本号较大的会被放在前面(参见[键值对](#键值对)部分,键是按顺序排列的),这样当你通过 Key + Version 获取 Value 时,MVCC 的键可以用 Key 和 Version 构造出来,即 `Key_Version`。然后可以直接通过 RocksDB 的 `SeekPrefix(Key_Version)` API 定位到大于或等于这个 `Key_Version` 的第一个位置。 ## 分布式 ACID 事务 -TiKV 的事务采用的是 Google 在 BigTable 中使用的事务模型:[Percolator](https://research.google/pubs/large-scale-incremental-processing-using-distributed-transactions-and-notifications/),TiKV 根据这篇论文实现,并做了大量的优化。详细介绍参见[事务概览](/transaction-overview.md)。 +TiKV 的事务采用了 Google 在 BigTable 中使用的模型:[Percolator](https://research.google/pubs/large-scale-incremental-processing-using-distributed-transactions-and-notifications/)。TiKV 的实现受到这篇论文的启发,并进行了大量优化。详情请参见[事务概览](/transaction-overview.md)。 diff --git a/tiflash/create-tiflash-replicas.md b/tiflash/create-tiflash-replicas.md index 70ba51062094..1c6a05ee06c5 100644 --- a/tiflash/create-tiflash-replicas.md +++ b/tiflash/create-tiflash-replicas.md @@ -1,27 +1,31 @@ --- -title: 构建 TiFlash 副本 -summary: 了解如何构建 TiFlash 副本。 +title: 创建 TiFlash 副本 +summary: 了解如何创建 TiFlash 副本。 --- -# 构建 TiFlash 副本 +# 创建 TiFlash 副本 -本文档介绍如何按表和库构建 TiFlash 副本,以及如何设置可用区来调度副本。 +本文介绍如何为表和数据库创建 TiFlash 副本,以及如何为副本调度设置可用区。 -## 按表构建 TiFlash 副本 +## 为表创建 TiFlash 副本 -TiFlash 接入 TiKV 集群后,默认不会开始同步数据。可通过 MySQL 客户端向 TiDB 发送 DDL 命令来为特定的表建立 TiFlash 副本: +TiFlash 连接到 TiKV 集群后,默认不会开始数据复制。您可以通过 MySQL 客户端向 TiDB 发送 DDL 语句,为特定表创建 TiFlash 副本: ```sql ALTER TABLE table_name SET TIFLASH REPLICA count; ``` -该命令的参数说明如下: +上述命令的参数说明如下: -- count 表示副本数,0 表示删除。 +- `count` 表示副本数量。当值为 `0` 时,副本会被删除。 -对于相同表的多次 DDL 命令,仅保证最后一次能生效。例如下面给出的操作 `tpch50` 表的两条 DDL 命令中,只有第二条删除副本的命令能生效: +> **注意:** +> +> 对于 [TiDB Cloud Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-serverless) 集群,TiFlash 副本的 `count` 只能是 `2`。如果您设置为 `1`,它将自动调整为 `2` 执行。如果您设置为大于 2 的数字,您将收到关于副本数量的错误。 + +如果您对同一个表执行多个 DDL 语句,只有最后一个语句保证生效。在以下示例中,对表 `tpch50` 执行了两个 DDL 语句,但只有第二个语句(删除副本)生效。 -为表建立 2 个副本: +为表创建两个副本: ```sql ALTER TABLE `tpch50`.`lineitem` SET TIFLASH REPLICA 2; @@ -29,148 +33,150 @@ ALTER TABLE `tpch50`.`lineitem` SET TIFLASH REPLICA 2; 删除副本: -{{< copyable "sql" >}} - ```sql ALTER TABLE `tpch50`.`lineitem` SET TIFLASH REPLICA 0; ``` -注意事项: - -* 假设有一张表 t 已经通过上述的 DDL 语句同步到 TiFlash,则通过以下语句创建的表也会自动同步到 TiFlash: +**注意事项:** - {{< copyable "sql" >}} +* 如果表 `t` 通过上述 DDL 语句复制到 TiFlash,使用以下语句创建的表也会自动复制到 TiFlash: ```sql CREATE TABLE table_name like t; ``` -* 如果集群版本 < v4.0.6,若先对表创建 TiFlash 副本,再使用 TiDB Lightning 导入数据,会导致数据导入失败。需要在使用 TiDB Lightning 成功导入数据至表后,再对相应的表创建 TiFlash 副本。 +* 对于早于 v4.0.6 的版本,如果在使用 TiDB Lightning 导入数据之前创建 TiFlash 副本,数据导入将失败。您必须在为表创建 TiFlash 副本之前将数据导入到表中。 -* 如果集群版本以及 TiDB Lightning 版本均 >= v4.0.6,无论一个表是否已经创建 TiFlash 副本,你均可以使用 TiDB Lightning 导入数据至该表。但注意此情况会导致 TiDB Lightning 导入数据耗费的时间延长,具体取决于 TiDB Lightning 部署机器的网卡带宽、TiFlash 节点的 CPU 及磁盘负载、TiFlash 副本数等因素。 +* 如果 TiDB 和 TiDB Lightning 都是 v4.0.6 或更高版本,无论表是否有 TiFlash 副本,您都可以使用 TiDB Lightning 向该表导入数据。请注意,这可能会降低 TiDB Lightning 的速度,具体取决于 lightning 主机上的网卡带宽、TiFlash 节点的 CPU 和磁盘负载以及 TiFlash 副本的数量。 -* 不推荐同步 1000 张以上的表,这会降低 PD 的调度性能。这个限制将在后续版本去除。 +* 建议不要复制超过 1,000 个表,因为这会降低 PD 调度性能。此限制将在后续版本中移除。 -* v5.1 版本及后续版本将不再支持设置系统表的 replica。在集群升级前,需要清除相关系统表的 replica,否则升级到较高版本后将无法再修改系统表的 replica 设置。 +* 在 v5.1 及更高版本中,不再支持为系统表设置副本。在升级集群之前,您需要清除相关系统表的副本。否则,在将集群升级到更高版本后,您将无法修改系统表的副本设置。 -> **注意:** -> -> 目前,使用 TiCDC 同步表到下游 TiDB 集群时,不支持为表创建 TiFlash 副本,即 TiCDC 不支持同步 TiFlash 相关的 DDL,例如: -> -> * `ALTER TABLE table_name SET TIFLASH REPLICA count;` -> * `ALTER DATABASE db_name SET TIFLASH REPLICA count;` +* 目前,当您使用 TiCDC 将表复制到下游 TiDB 集群时,不支持为表创建 TiFlash 副本,这意味着 TiCDC 不支持复制与 TiFlash 相关的 DDL 语句,例如: -### 查看表同步进度 + * `ALTER TABLE table_name SET TIFLASH REPLICA count;` + * `ALTER DATABASE db_name SET TIFLASH REPLICA count;` -可通过如下 SQL 语句查看特定表(通过 WHERE 语句指定,去掉 WHERE 语句则查看所有表)的 TiFlash 副本的状态: +### 检查复制进度 + +您可以使用以下语句检查特定表的 TiFlash 副本状态。表通过 `WHERE` 子句指定。如果您删除 `WHERE` 子句,将检查所有表的副本状态。 ```sql SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = '' and TABLE_NAME = ''; ``` -查询结果中: +在上述语句的结果中: -* AVAILABLE 字段表示该表的 TiFlash 副本是否可用。1 代表可用,0 代表不可用。副本状态为可用之后就不再改变,如果通过 DDL 命令修改副本数则会重新计算同步进度。 -* PROGRESS 字段代表同步进度,在 0.0~1.0 之间,1 代表至少 1 个副本已经完成同步。 +* `AVAILABLE` 表示该表的 TiFlash 副本是否可用。`1` 表示可用,`0` 表示不可用。一旦副本变为可用,此状态就不会改变。如果您使用 DDL 语句修改副本数量,复制状态将重新计算。 +* `PROGRESS` 表示复制进度。值在 `0.0` 和 `1.0` 之间。`1` 表示至少复制了一个副本。 -## 按库构建 TiFlash 副本 +## 为数据库创建 TiFlash 副本 -类似于按表构建 TiFlash 副本的方式,你可以在 MySQL 客户端向 TiDB 发送 DDL 命令来为指定数据库中的所有表建立 TiFlash 副本: +与为表创建 TiFlash 副本类似,您可以通过 MySQL 客户端向 TiDB 发送 DDL 语句,为特定数据库中的所有表创建 TiFlash 副本: ```sql ALTER DATABASE db_name SET TIFLASH REPLICA count; ``` -在该命令中,`count` 表示 TiFlash 的副本数。当设置 `count` 值为 0 时,表示删除现有的 TiFlash 副本。 +在此语句中,`count` 表示副本数量。当设置为 `0` 时,副本会被删除。 -命令示例: +示例: -执行以下命令可以为 `tpch50` 库中的所有表建立 2 个 TiFlash 副本。 +- 为数据库 `tpch50` 中的所有表创建两个副本: -```sql -ALTER DATABASE `tpch50` SET TIFLASH REPLICA 2; -``` + ```sql + ALTER DATABASE `tpch50` SET TIFLASH REPLICA 2; + ``` -执行以下命令可以删除为 `tpch50` 库建立的 TiFlash 副本: +- 删除为数据库 `tpch50` 创建的 TiFlash 副本: -```sql -ALTER DATABASE `tpch50` SET TIFLASH REPLICA 0; -``` + ```sql + ALTER DATABASE `tpch50` SET TIFLASH REPLICA 0; + ``` > **注意:** > -> - 该命令实际是为用户执行一系列 DDL 操作,对资源要求比较高。如果在执行过程中出现中断,已经执行成功的操作不会回退,未执行的操作不会继续执行。 +> - 此语句实际上执行一系列 DDL 操作,这些操作会消耗大量资源。如果语句在执行过程中被中断,已执行的操作不会回滚,未执行的操作也不会继续。 > -> - 从命令执行开始到该库中所有表都已**同步完成**之前,不建议执行和该库相关的 TiFlash 副本数量设置或其他 DDL 操作,否则最终状态可能非预期。非预期场景包括: -> - 先设置 TiFlash 副本数量为 2,在库中所有的表都同步完成前,再设置 TiFlash 副本数量为 1,不能保证最终所有表的 TiFlash 副本数量都为 1 或都为 2。 -> - 在命令执行到结束期间,如果在该库下创建表,则**可能**会对这些新增表创建 TiFlash 副本。 -> - 在命令执行到结束期间,如果为该库下的表添加索引,则该命令可能陷入等待,直到添加索引完成。 +> - 执行语句后,在**该数据库中的所有表都复制完成之前**,不要设置 TiFlash 副本数量或对该数据库执行 DDL 操作。否则,可能会出现意外结果,包括: +> - 如果您将 TiFlash 副本数量设置为 2,然后在数据库中的所有表复制完成之前将数量更改为 1,所有表的最终 TiFlash 副本数量不一定是 1 或 2。 +> - 执行语句后,如果您在语句执行完成之前在此数据库中创建表,这些新表**可能会或可能不会**创建 TiFlash 副本。 +> - 执行语句后,如果您在语句执行完成之前为数据库中的表添加索引,语句可能会挂起,并且只有在添加索引后才会恢复。 > -> - 该命令执行结束后,在该库中新建的表不会自动创建 TiFlash 副本。 +> - 如果您在语句执行完成**之后**在此数据库中创建表,不会自动为这些新表创建 TiFlash 副本。 > -> - 该命令会跳过系统表、视图、临时表以及包含了 TiFlash 不支持字符集的表。 -> -> - 通过设置 [`tidb_batch_pending_tiflash_count`](/system-variables.md#tidb_batch_pending_tiflash_count-从-v60-版本开始引入) 系统变量可以控制执行过程中允许的尚未同步完成的表的数量。调小该值有助于减低同步时集群受到的压力。注意,因为这个限制不是实时的,所以设置完后仍有可能存在尚未同步完成的表的数量超过限制的情况。 +> - 此语句会跳过系统表、视图、临时表和具有 TiFlash 不支持的字符集的表。 + +> - 您可以通过设置 [`tidb_batch_pending_tiflash_count`](/system-variables.md#tidb_batch_pending_tiflash_count-new-in-v60) 系统变量来控制执行期间允许保持不可用的表的数量。降低此值有助于减少复制期间对集群的压力。请注意,此限制不是实时的,因此在应用设置后,不可用表的数量仍可能超过限制。 -### 查看库同步进度 +### 检查复制进度 -类似于按表构建,按库构建 TiFlash 副本的命令执行成功,不代表所有表都已同步完成。可以执行下面的 SQL 语句检查数据库中所有已设置 TiFlash Replica 表的同步进度: +与为表创建 TiFlash 副本类似,成功执行 DDL 语句并不意味着复制完成。您可以执行以下 SQL 语句来检查目标表的复制进度: ```sql SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = ''; ``` -可以执行下面的 SQL 语句检查数据库中尚未设置 TiFlash Replica 的表名: +要检查数据库中没有 TiFlash 副本的表,您可以执行以下 SQL 语句: ```sql SELECT TABLE_NAME FROM information_schema.tables where TABLE_SCHEMA = "" and TABLE_NAME not in (SELECT TABLE_NAME FROM information_schema.tiflash_replica where TABLE_SCHEMA = ""); ``` -## 加快 TiFlash 副本同步速度 +## 加速 TiFlash 复制 -新增 TiFlash 副本时,各个 TiKV 实例将进行全表数据扫描,并将扫描得到的数据快照发送给 TiFlash 从而形成副本。默认情况下,为了降低对 TiKV 及 TiFlash 线上业务的影响,TiFlash 新增副本速度较慢、占用资源较少。如果集群中 TiKV 及 TiFlash 的 CPU 和磁盘 IO 资源有富余,你可以按以下步骤操作来提升 TiFlash 副本同步速度: + -1. 通过 [SQL 语句在线修改配置](/dynamic-config.md),临时调高各个 TiKV 及 TiFlash 实例的数据快照写入速度: +> **注意:** +> +> 本节不适用于 TiDB Cloud。 + + + +在添加 TiFlash 副本之前,每个 TiKV 实例都会执行全表扫描,并将扫描的数据作为"快照"发送给 TiFlash 以创建副本。默认情况下,TiFlash 副本添加速度较慢,使用较少的资源,以最小化对在线服务的影响。如果您的 TiKV 和 TiFlash 节点有空闲的 CPU 和磁盘 IO 资源,您可以通过执行以下步骤来加速 TiFlash 复制。 + +1. 使用[动态配置 SQL 语句](https://docs.pingcap.com/tidb/stable/dynamic-config)临时增加每个 TiKV 和 TiFlash 实例的快照写入速度限制: ```sql - -- 这两个参数默认值都为 100MiB,即用于副本同步的快照最大占用的磁盘带宽不超过 100MiB/s。 + -- 这两个配置的默认值都是 100MiB,即用于写入快照的最大磁盘带宽不超过 100MiB/s。 SET CONFIG tikv `server.snap-io-max-bytes-per-sec` = '300MiB'; SET CONFIG tiflash `raftstore-proxy.server.snap-io-max-bytes-per-sec` = '300MiB'; ``` - 以上 SQL 语句执行后,配置修改立即生效,无需重启集群。但由于副本同步速度还受到 PD 副本速度控制,因此当前你还无法观察到副本同步速度提升。 + 执行这些 SQL 语句后,配置更改立即生效,无需重启集群。但是,由于复制速度仍然受到 PD 全局限制,您现在还无法观察到加速效果。 -2. 使用 [PD Control](/pd-control.md) 逐步放开新增副本速度限制: +2. 使用 [PD Control](https://docs.pingcap.com/tidb/stable/pd-control) 逐步放宽新副本速度限制。 - TiFlash 默认新增副本速度是 30(每分钟大约 30 个 Region 将会新增 TiFlash 副本)。执行以下命令将调整所有 TiFlash 实例的新增副本速度到 60,即原来的 2 倍速度: + 默认的新副本速度限制是 30,这意味着每分钟大约有 30 个 Region 添加 TiFlash 副本。执行以下命令将所有 TiFlash 实例的限制调整为 60,这将使原始速度翻倍: ```shell tiup ctl:v pd -u http://:2379 store limit all engine tiflash 60 add-peer ``` - > 上述命令中,需要将 `v` 替换为该集群版本,例如 `v8.1.2`,`:2379` 替换为任一 PD 节点的地址。替换后样例为: + > 在上述命令中,您需要将 `v` 替换为实际的集群版本,例如 `v8.1.2`,并将 `:2379` 替换为任何 PD 节点的地址。例如: > > ```shell > tiup ctl:v8.1.2 pd -u http://192.168.1.4:2379 store limit all engine tiflash 60 add-peer > ``` - 执行完毕后,几分钟内,你将观察到 TiFlash 节点的 CPU 及磁盘 IO 资源占用显著提升,TiFlash 将更快地创建副本。同时,TiKV 节点的 CPU 及磁盘 IO 资源占用也将有所上升。 + 几分钟内,您将观察到 TiFlash 节点的 CPU 和磁盘 IO 资源使用率显著增加,TiFlash 应该会更快地创建副本。同时,TiKV 节点的 CPU 和磁盘 IO 资源使用率也会增加。 - 如果此时 TiKV 及 TiFlash 节点的资源仍有富余,且线上业务的延迟没有显著上升,则可以考虑进一步放开调度速度,例如将新增副本的速度增加为原来的 3 倍: + 如果此时 TiKV 和 TiFlash 节点仍有空闲资源,并且您的在线服务延迟没有显著增加,您可以进一步放宽限制,例如,将原始速度提高三倍: ```shell tiup ctl:v pd -u http://:2379 store limit all engine tiflash 90 add-peer ``` -3. 在副本同步完毕后,恢复到默认配置,减少在线业务受到的影响。 +3. TiFlash 复制完成后,恢复默认配置以减少对在线服务的影响。 - 执行以下 PD Control 命令可恢复默认的新增副本速度: + 执行以下 PD Control 命令恢复默认的新副本速度限制: ```shell tiup ctl:v pd -u http://:2379 store limit all engine tiflash 30 add-peer ``` - 执行以下 SQL 语句可恢复默认的数据快照写入速度: + 执行以下 SQL 语句恢复默认的快照写入速度限制: ```sql SET CONFIG tikv `server.snap-io-max-bytes-per-sec` = '100MiB'; @@ -179,14 +185,21 @@ SELECT TABLE_NAME FROM information_schema.tables where TABLE_SCHEMA = " ## 设置可用区 -在配置副本时,如果为了考虑容灾,需要将 TiFlash 的不同数据副本分布到多个数据中心,则可以按如下步骤进行配置: + + +> **注意:** +> +> 本节不适用于 TiDB Cloud。 + + + +在配置副本时,如果您需要将 TiFlash 副本分布到多个数据中心以实现灾难恢复,可以按照以下步骤配置可用区: -1. 在集群配置文件中为 TiFlash 节点指定 label: +1. 在集群配置文件中为 TiFlash 节点指定标签。 ``` tiflash_servers: - host: 172.16.5.81 - config: logger.level: "info" learner_config: server.labels: @@ -205,11 +218,9 @@ SELECT TABLE_NAME FROM information_schema.tables where TABLE_SCHEMA = " zone: "z2" ``` - 注:旧版本中的 `flash.proxy.labels` 配置无法处理可用区名字中的特殊字符,建议使用 `learner_config` 中的 `server.labels` 来进行配置。 - -2. 启动集群后,在创建副本时为副本调度指定 label,语法如下: + 请注意,早期版本中的 `flash.proxy.labels` 配置无法正确处理可用区名称中的特殊字符。建议使用 `learner_config` 中的 `server.labels` 来配置可用区名称。 - {{< copyable "sql" >}} +2. 启动集群后,在创建副本时指定标签。 ```sql ALTER TABLE table_name SET TIFLASH REPLICA count LOCATION LABELS location_labels; @@ -217,19 +228,16 @@ SELECT TABLE_NAME FROM information_schema.tables where TABLE_SCHEMA = " 例如: - {{< copyable "sql" >}} - ```sql ALTER TABLE t SET TIFLASH REPLICA 2 LOCATION LABELS "zone"; ``` -3. 此时 PD 会根据设置的 label 进行调度,将表 `t` 的两个副本分别调度到两个可用区中。可以通过监控或 pd-ctl 来验证这一点: +3. PD 根据标签调度副本。在本例中,PD 分别将表 `t` 的两个副本调度到两个可用区。您可以使用 pd-ctl 查看调度情况。 ```shell > tiup ctl:v pd -u http://:2379 store ... - "address": "172.16.5.82:23913", "labels": [ { "key": "engine", "value": "tiflash"}, @@ -238,14 +246,12 @@ SELECT TABLE_NAME FROM information_schema.tables where TABLE_SCHEMA = " "region_count": 4, ... - "address": "172.16.5.81:23913", "labels": [ { "key": "engine", "value": "tiflash"}, { "key": "zone", "value": "z1" } ], "region_count": 5, - ... "address": "172.16.5.85:23913", @@ -254,10 +260,13 @@ SELECT TABLE_NAME FROM information_schema.tables where TABLE_SCHEMA = " { "key": "zone", "value": "z2" } ], "region_count": 9, - ... ``` -关于使用 label 进行副本调度划分可用区的更多内容,可以参考[通过拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md),[同城多数据中心部署 TiDB](/multi-data-centers-in-one-city-deployment.md) 与[两地三中心部署](/three-data-centers-in-two-cities-deployment.md)。 + + +有关使用标签调度副本的更多信息,请参见[通过拓扑 Label 进行副本调度](/schedule-replicas-by-topology-labels.md)、[同城多数据中心部署](/multi-data-centers-in-one-city-deployment.md)和[两地三中心部署](/three-data-centers-in-two-cities-deployment.md)。 + +TiFlash 支持为不同区域配置副本选择策略。更多信息,请参见 [`tiflash_replica_read`](/system-variables.md#tiflash_replica_read-new-in-v730)。 -TiFlash 支持设置不同区域的副本选择策略,具体请参考变量 [`tiflash_replica_read`](/system-variables.md#tiflash_replica_read-从-v730-版本开始引入)。 + diff --git a/tiflash/tiflash-compatibility.md b/tiflash/tiflash-compatibility.md index 9c212e54e384..11961797c45e 100644 --- a/tiflash/tiflash-compatibility.md +++ b/tiflash/tiflash-compatibility.md @@ -1,31 +1,28 @@ --- title: TiFlash 兼容性说明 -summary: 了解与 TiFlash 不兼容的 TiDB 特性。 +summary: 了解与 TiFlash 不兼容的 TiDB 功能。 --- # TiFlash 兼容性说明 -TiFlash 在以下情况与 TiDB 存在不兼容问题: +TiFlash 在以下情况下与 TiDB 不兼容: -* TiFlash 计算层: - * 不支持检查溢出的数值。例如将两个 `BIGINT` 类型的最大值相加 `9223372036854775807 + 9223372036854775807`,该计算在 TiDB 中预期的行为是返回错误 `ERROR 1690 (22003): BIGINT value is out of range`,但如果该计算在 TiFlash 中进行,则会得到溢出的结果 `-2` 且无报错。 +* 在 TiFlash 计算层: + * 不支持检查数值溢出。例如,对两个 `BIGINT` 类型的最大值进行相加 `9223372036854775807 + 9223372036854775807`。在 TiDB 中,此计算的预期行为是返回 `ERROR 1690 (22003): BIGINT value is out of range` 错误。但是,如果在 TiFlash 中执行此计算,则会返回溢出值 `-2` 而不会报错。 + * 不支持窗口函数。 * 不支持从 TiKV 读取数据。 - * 目前 TiFlash 中的 `sum` 函数不支持传入字符串类型的参数,但 TiDB 在编译时无法检测出这种情况。所以当执行类似于 `select sum(string_col) from t` 的语句时,TiFlash 会报错 `[FLASH:Coprocessor:Unimplemented] CastStringAsReal is not supported.`。要避免这类报错,需要手动把 SQL 改写成 `select sum(cast(string_col as double)) from t`。 - * TiFlash 目前的 Decimal 除法计算和 TiDB 存在不兼容的情况。例如在进行 Decimal 相除的时候,TiFlash 会始终按照编译时推断出来的类型进行计算,而 TiDB 则在计算过程中采用精度高于编译时推断出来的类型。这导致在一些带有 Decimal 除法的 SQL 语句在 TiDB + TiKV 上的执行结果会和 TiDB + TiFlash 上的执行结果不一样,示例如下: + * 目前,TiFlash 中的 `sum` 函数不支持字符串类型参数。但是 TiDB 在编译期间无法识别是否有字符串类型参数传入 `sum` 函数。因此,当您执行类似 `select sum(string_col) from t` 的语句时,TiFlash 会返回 `[FLASH:Coprocessor:Unimplemented] CastStringAsReal is not supported.` 错误。要避免这种情况下的错误,您需要将此 SQL 语句修改为 `select sum(cast(string_col as double)) from t`。 + * 目前,TiFlash 的 decimal 除法计算与 TiDB 不兼容。例如,在进行 decimal 除法时,TiFlash 始终使用从编译推断出的类型进行计算。但是,TiDB 使用比编译推断出的类型更精确的类型进行计算。因此,一些涉及 decimal 除法的 SQL 语句在 TiDB + TiKV 和 TiDB + TiFlash 中执行时会返回不同的结果。例如: ```sql mysql> create table t (a decimal(3,0), b decimal(10, 0)); Query OK, 0 rows affected (0.07 sec) - mysql> insert into t values (43, 1044774912); Query OK, 1 row affected (0.03 sec) - mysql> alter table t set tiflash replica 1; Query OK, 0 rows affected (0.07 sec) - mysql> set session tidb_isolation_read_engines='tikv'; Query OK, 0 rows affected (0.00 sec) - mysql> select a/b, a/b + 0.0000000000001 from t where a/b; +--------+-----------------------+ | a/b | a/b + 0.0000000000001 | @@ -33,12 +30,10 @@ TiFlash 在以下情况与 TiDB 存在不兼容问题: | 0.0000 | 0.0000000410001 | +--------+-----------------------+ 1 row in set (0.00 sec) - mysql> set session tidb_isolation_read_engines='tiflash'; Query OK, 0 rows affected (0.00 sec) - mysql> select a/b, a/b + 0.0000000000001 from t where a/b; Empty set (0.01 sec) ``` - 以上示例中,在 TiDB 和 TiFlash 中,`a/b` 在编译期推导出来的类型都为 `Decimal(7,4)`,而在 `Decimal(7,4)` 的约束下,`a/b` 返回的结果应该为 `0.0000`。但是在 TiDB 中,`a/b` 运行期的精度比 `Decimal(7,4)` 高,所以原表中的数据没有被 `where a/b` 过滤掉。而在 TiFlash 中 `a/b` 在运行期也是采用 `Decimal(7,4)` 作为结果类型,所以原表中的数据被 `where a/b` 过滤掉了。 + 在上面的示例中,`a/b` 在 TiDB 和 TiFlash 中从编译推断出的类型都是 `Decimal(7,4)`。受 `Decimal(7,4)` 约束,`a/b` 的返回类型应该是 `0.0000`。在 TiDB 中,`a/b` 的运行时精度高于 `Decimal(7,4)`,因此原始表数据不会被 `where a/b` 条件过滤。但是,在 TiFlash 中,`a/b` 的计算使用 `Decimal(7,4)` 作为结果类型,因此原始表数据会被 `where a/b` 条件过滤。 diff --git a/tiflash/tiflash-late-materialization.md b/tiflash/tiflash-late-materialization.md index 963e13f349d4..74389c1f0ad3 100644 --- a/tiflash/tiflash-late-materialization.md +++ b/tiflash/tiflash-late-materialization.md @@ -1,20 +1,20 @@ --- title: TiFlash 延迟物化 -summary: 介绍通过使用 TiFlash 延迟物化的方式来加速 OLAP 场景的查询。 +summary: 介绍如何使用 TiFlash 延迟物化功能加速 OLAP 场景下的查询。 --- -# 延迟物化 +# TiFlash 延迟物化 > **注意:** > -> 在 TiFlash [Fast Scan 模式](/tiflash/use-fastscan.md)下,延迟物化功能暂不可用。 +> TiFlash 延迟物化在[快速扫描模式](/tiflash/use-fastscan.md)下不生效。 -TiFlash 延迟物化是加速 Online Analytical Processing (OLAP) 场景查询的一种优化方式。你可以通过修改变量 [`tidb_opt_enable_late_materialization`](/system-variables.md#tidb_opt_enable_late_materialization-从-v700-版本开始引入) 来控制是否启用 TiFlash 延迟物化功能。 +TiFlash 延迟物化是一种用于加速 OLAP 场景查询的优化方法。您可以使用 [`tidb_opt_enable_late_materialization`](/system-variables.md#tidb_opt_enable_late_materialization-new-in-v700) 系统变量来控制是否启用或禁用 TiFlash 延迟物化。 -- 当关闭该功能时,如果 `SELECT` 语句中包含过滤条件(`WHERE` 子句),TiFlash 会先读取该查询所需列的全部数据,然后再根据查询条件对数据进行过滤、聚合等计算任务。 -- 当开启该功能时,TiFlash 支持下推部分过滤条件到 TableScan 算子,即先扫描下推到 TableScan 算子的过滤条件相关的列数据,过滤得到符合条件的行后,再扫描这些行的其他列数据,继续后续计算,从而减少 IO 扫描和数据处理的计算量。 +- 当禁用时,为了处理带有过滤条件(`WHERE` 子句)的 `SELECT` 语句,TiFlash 会读取查询所需的所有列的数据,然后根据查询条件进行过滤和聚合。 +- 当启用时,TiFlash 支持将部分过滤条件下推到 TableScan 算子。也就是说,TiFlash 首先扫描与下推到 TableScan 算子的过滤条件相关的列数据,过滤出满足条件的行,然后再扫描这些行的其他列数据进行进一步计算,从而减少数据处理的 IO 扫描和计算。 -为了提升 OLAP 场景部分查询的性能,从 v7.1.0 起,TiFlash 延迟物化功能默认开启,TiDB 优化器会根据统计信息和查询的过滤条件,决定哪些过滤条件会被下推。优化器会优先考虑下推过滤率高的过滤条件,详细算法可以参考 [RFC 文档](https://github.com/pingcap/tidb/tree/release-8.1/docs/design/2022-12-06-support-late-materialization.md)。 +为了提高 OLAP 场景下某些查询的性能,从 v7.1.0 开始,TiFlash 延迟物化功能默认启用。TiDB 优化器可以根据统计信息和过滤条件决定下推哪些过滤条件,并优先下推过滤率高的过滤条件。有关详细算法,请参见 [RFC 文档](https://github.com/pingcap/tidb/tree/release-8.1/docs/design/2022-12-06-support-late-materialization.md)。 例如: @@ -32,11 +32,11 @@ EXPLAIN SELECT a, b, c FROM t1 WHERE a < 1; +-------------------------+----------+--------------+---------------+-------------------------------------------------------+ ``` -在此示例中,过滤条件 `a < 1` 被下推到了 TableScan 算子,TiFlash 会先读取列 `a` 的全部数据,然后根据过滤条件 `a < 1` 进行过滤,得到符合条件的行后,再读取这些行的列 `b` 和 `c` 的数据。 +在这个例子中,过滤条件 `a < 1` 被下推到 TableScan 算子。TiFlash 首先读取列 `a` 的所有数据,然后过滤出满足 `a < 1` 条件的行。接下来,TiFlash 从这些过滤后的行中读取列 `b` 和 `c`。 -## 启用和禁用 TiFlash 延迟物化 +## 启用或禁用 TiFlash 延迟物化 -默认情况下,session 和 global 级别的变量 `tidb_opt_enable_late_materialization=ON`,即开启 TiFlash 延迟物化功能。你可以通过以下语句来查看对应的变量信息。 +默认情况下,`tidb_opt_enable_late_materialization` 系统变量在会话和全局级别都为 `ON`,这意味着 TiFlash 延迟物化功能已启用。您可以使用以下语句查看相应的变量信息: ```sql SHOW VARIABLES LIKE 'tidb_opt_enable_late_materialization'; @@ -62,23 +62,23 @@ SHOW GLOBAL VARIABLES LIKE 'tidb_opt_enable_late_materialization'; +--------------------------------------+-------+ ``` -变量 `tidb_opt_enable_late_materialization` 支持 session 级别和 global 级别的修改。 +您可以在会话级别或全局级别修改 `tidb_opt_enable_late_materialization` 变量。 -- 如果需要在当前 session 中关闭 TiFlash 延迟物化功能,可以通过以下语句设置: +- 要在当前会话中禁用 TiFlash 延迟物化,使用以下语句: ```sql SET SESSION tidb_opt_enable_late_materialization=OFF; ``` -- 如果需要在 global 级别关闭 TiFlash 延迟物化功能,可以通过以下语句设置: +- 要在全局级别禁用 TiFlash 延迟物化,使用以下语句: ```sql SET GLOBAL tidb_opt_enable_late_materialization=OFF; ``` - 设置后,新建的会话中 session 和 global 级别 `tidb_opt_enable_late_materialization` 都将默认启用新值。 + 设置后,在新会话中 `tidb_opt_enable_late_materialization` 变量在会话和全局级别都将默认禁用。 -如需启用 TiFlash 延迟物化功能,可以通过以下语句设置: +要启用 TiFlash 延迟物化,使用以下语句: ```sql SET SESSION tidb_opt_enable_late_materialization=ON; @@ -90,10 +90,10 @@ SET GLOBAL tidb_opt_enable_late_materialization=ON; ## 实现机制 -当有过滤条件下推到 TableScan 算子时,TableScan 算子的执行过程主要包括了以下步骤: +当过滤条件下推到 TableScan 算子时,TableScan 算子的执行过程主要包括以下步骤: -1. 读取 `` 三列,执行多版本并发控制 (MVCC) 过滤,生成 MVCC Bitmap。 -2. 读取过滤条件相关的列,过滤满足条件的行,生成 Filter Bitmap。 -3. 将 MVCC Bitmap 和 Filter Bitmap 进行与操作 (AND),生成 Final Bitmap。 -4. 根据 Final Bitmap 读取剩余列的对应的行。 -5. 合并第 2 步和第 4 步中读取的数据,返回结果。 \ No newline at end of file +1. 读取 `` 三列,执行多版本并发控制(MVCC)过滤,然后生成 MVCC Bitmap。 +2. 读取与过滤条件相关的列,过滤出满足条件的行,然后生成 Filter Bitmap。 +3. 对 MVCC Bitmap 和 Filter Bitmap 执行 `AND` 操作,生成 Final Bitmap。 +4. 根据 Final Bitmap 读取剩余列的对应行。 +5. 合并步骤 2 和步骤 4 中读取的数据,然后返回结果。 diff --git a/tiflash/tiflash-overview.md b/tiflash/tiflash-overview.md index 5a367cfb9d76..4e5812c59181 100644 --- a/tiflash/tiflash-overview.md +++ b/tiflash/tiflash-overview.md @@ -1,81 +1,140 @@ --- -title: TiFlash 简介 -summary: TiFlash 是 TiDB HTAP 形态的关键组件,提供了良好的隔离性和强一致性。它使用列存扩展和 Raft Learner 协议异步复制,通过 Raft 校对索引配合 MVCC 实现一致性隔离级别。TiFlash 架构解决了 HTAP 场景的隔离性和列存同步问题。它提供列式存储和借助 ClickHouse 高效实现的协处理器层。TiFlash 可以兼容 TiDB 和 TiSpark,推荐与 TiKV 不同节点部署以实现 Workload 隔离。具有异步复制、一致性、智能选择和计算加速等核心特性。部署完成后需要手动指定需要同步的表。 +title: TiFlash 概述 +summary: 了解 TiFlash 的架构和主要特性。 --- -# TiFlash 简介 +# TiFlash 概述 -[TiFlash](https://github.com/pingcap/tiflash) 是 TiDB HTAP 形态的关键组件,它是 TiKV 的列存扩展,在提供了良好的隔离性的同时,也兼顾了强一致性。列存副本通过 Raft Learner 协议异步复制,但是在读取的时候通过 Raft 校对索引配合 MVCC 的方式获得 Snapshot Isolation 的一致性隔离级别。这个架构很好地解决了 HTAP 场景的隔离性以及列存同步的问题。 +[TiFlash](https://github.com/pingcap/tiflash) 是使 TiDB 成为混合事务/分析处理 (HTAP) 数据库的关键组件。作为 TiKV 的列式存储扩展,TiFlash 提供了良好的隔离级别和强一致性保证。 -## 整体架构 +在 TiFlash 中,列式副本根据 Raft Learner 共识算法进行异步复制。在读取这些副本时,通过验证 Raft 索引和多版本并发控制 (MVCC) 来实现快照隔离级别的一致性。 + + + +使用 TiDB Cloud,您可以根据 HTAP 工作负载轻松创建 HTAP 集群,只需指定一个或多个 TiFlash 节点即可。如果在创建集群时未指定 TiFlash 节点数量,或者您想添加更多 TiFlash 节点,可以通过[扩展集群](/tidb-cloud/scale-tidb-cluster.md)来更改节点数量。 + + + +## 架构 ![TiFlash 架构](/media/tidb-storage-architecture-1.png) -上图为 TiDB HTAP 形态架构,其中包含 TiFlash 节点。 +上图是包含 TiFlash 节点的 TiDB HTAP 形态的架构。 + +TiFlash 提供列式存储,并通过 ClickHouse 高效实现了一层协处理器。与 TiKV 类似,TiFlash 也有一个多 Raft 系统,支持以 Region 为单位复制和分发数据(详情请参见[数据存储](https://www.pingcap.com/blog/tidb-internal-data-storage/))。 + +TiFlash 以低成本实时复制 TiKV 节点中的数据,不会阻塞 TiKV 中的写入。同时,它提供与 TiKV 相同的读一致性,并确保读取最新数据。TiFlash 中的 Region 副本在逻辑上与 TiKV 中的副本相同,并与 TiKV 中的 Leader 副本同时进行分裂和合并。 + +要在 Linux AMD64 架构下部署 TiFlash,CPU 必须支持 AVX2 指令集。确保 `cat /proc/cpuinfo | grep avx2` 有输出。要在 Linux ARM64 架构下部署 TiFlash,CPU 必须支持 ARMv8 指令集架构。确保 `cat /proc/cpuinfo | grep 'crc32' | grep 'asimd'` 有输出。通过使用指令集扩展,TiFlash 的向量化引擎可以提供更好的性能。 -TiFlash 提供列式存储,且拥有借助 ClickHouse 高效实现的协处理器层。除此以外,它与 TiKV 非常类似,依赖同样的 Multi-Raft 体系,以 Region 为单位进行数据复制和分散(详情见[《说存储》](https://pingcap.com/blog-cn/tidb-internal-1/)一文)。 + -TiFlash 以低消耗不阻塞 TiKV 写入的方式,实时复制 TiKV 集群中的数据,并同时提供与 TiKV 一样的一致性读取,且可以保证读取到最新的数据。TiFlash 中的 Region 副本与 TiKV 中完全对应,且会跟随 TiKV 中的 Leader 副本同时进行分裂与合并。 +TiFlash 同时兼容 TiDB 和 TiSpark,使您可以在这两个计算引擎之间自由选择。 -在 Linux AMD64 架构的硬件平台部署 TiFlash 时,CPU 必须支持 AVX2 指令集。确保命令 `cat /proc/cpuinfo | grep avx2` 有输出。而在 Linux ARM64 架构的硬件平台部署 TiFlash 时,CPU 必须支持 ARMv8 架构。确保命令 `cat /proc/cpuinfo | grep 'crc32' | grep 'asimd'` 有输出。通过使用向量扩展指令集,TiFlash 的向量化引擎能提供更好的性能。 + -TiFlash 可以兼容 TiDB 与 TiSpark,用户可以选择使用不同的计算引擎。 +建议将 TiFlash 部署在与 TiKV 不同的节点上,以确保工作负载隔离。如果不需要业务隔离,也可以将 TiFlash 和 TiKV 部署在同一节点上。 -TiFlash 推荐使用和 TiKV 不同的节点以做到 Workload 隔离,但在无业务隔离的前提下,也可以选择与 TiKV 同节点部署。 +目前,数据不能直接写入 TiFlash。您需要先将数据写入 TiKV,然后复制到 TiFlash,因为它作为 Learner 角色连接到 TiDB 集群。TiFlash 支持以表为单位进行数据复制,但部署后默认不会复制任何数据。要复制指定表的数据,请参见[为表创建 TiFlash 副本](/tiflash/create-tiflash-replicas.md#为表创建-tiflash-副本)。 -TiFlash 暂时无法直接接受数据写入,任何数据必须先写入 TiKV 再同步到 TiFlash。TiFlash 以 learner 角色接入 TiDB 集群,TiFlash 支持表粒度的数据同步,部署后默认情况下不会同步任何数据,需要按照[按表构建 TiFlash 副本](/tiflash/create-tiflash-replicas.md#按表构建-tiflash-副本)一节完成指定表的数据同步。 +TiFlash 由两个主要组件组成:列式存储组件和 TiFlash 代理组件。TiFlash 代理组件负责使用多 Raft 共识算法进行通信。 -TiFlash 主要包含两个组件,一个是列式存储引擎组件,另一个是处理 Multi-Raft 协议通信相关工作的 TiFlash proxy 组件。 +在收到为表在 TiFlash 中创建副本的 DDL 命令后,TiDB 会自动在 PD 中创建相应的[放置规则](https://docs.pingcap.com/tidb/stable/configure-placement-rules),然后 PD 根据这些规则执行相应的数据调度。 -对于按表构建 TiFlash 副本的流程,TiDB 接收到相应的 DDL 命令后,会自动在 PD 创建对应的 [Placement Rules](/configure-placement-rules.md),PD 根据该信息进行相关的数据调度。 +## 主要特性 -## 核心特性 +TiFlash 具有以下主要特性: -TiFlash 主要有异步复制、一致性、智能选择、计算加速等几个核心特性。 +- [异步复制](#异步复制) +- [一致性](#一致性) +- [智能选择](#智能选择) +- [计算加速](#计算加速) ### 异步复制 -TiFlash 中的副本以特殊角色 (Raft Learner) 进行异步的数据复制。这表示当 TiFlash 节点宕机或者网络高延迟等状况发生时,TiKV 的业务仍然能确保正常进行。 +TiFlash 中的副本作为特殊角色 Raft Learner 进行异步复制。这意味着当 TiFlash 节点宕机或出现高网络延迟时,TiKV 中的应用程序仍可正常进行。 -这套复制机制也继承了 TiKV 体系的自动负载均衡和高可用:并不用依赖附加的复制管道,而是直接以多对多方式接收 TiKV 的数据传输;且只要 TiKV 中数据不丢失,就可以随时恢复 TiFlash 的副本。 +这种复制机制继承了 TiKV 的两个优点:自动负载均衡和高可用性。 + +- TiFlash 不依赖额外的复制通道,而是直接以多对多的方式从 TiKV 接收数据。 +- 只要数据在 TiKV 中没有丢失,您随时都可以在 TiFlash 中恢复副本。 ### 一致性 -TiFlash 提供与 TiKV 一样的快照隔离支持,且保证读取数据最新(确保之前写入的数据能被读取)。这个一致性是通过对数据进行复制进度校验做到的。 +TiFlash 提供与 TiKV 相同的快照隔离级别一致性,并确保读取最新数据,这意味着您可以读取之前写入 TiKV 的数据。这种一致性是通过验证数据复制进度来实现的。 -每次收到读取请求,TiFlash 中的 Region 副本会向 Leader 副本发起进度校对(一个非常轻的 RPC 请求),只有当进度确保至少所包含读取请求时间戳所覆盖的数据之后才响应读取。 +每次 TiFlash 收到读取请求时,Region 副本都会向 Leader 副本发送进度验证请求(一个轻量级的 RPC 请求)。只有在当前复制进度包含读取请求时间戳所覆盖的数据后,TiFlash 才会执行读取操作。 ### 智能选择 -TiDB 可以自动选择使用 TiFlash 列存或者 TiKV 行存,甚至在同一查询内混合使用提供最佳查询速度。这个选择机制与 TiDB 选取不同索引提供查询类似:根据统计信息判断读取代价并作出合理选择。 +TiDB 可以自动选择使用 TiFlash(列式)或 TiKV(行式),或在一个查询中同时使用两者,以确保最佳性能。 + +这种选择机制类似于 TiDB 选择不同索引来执行查询。TiDB 优化器根据读取成本的统计信息做出适当的选择。 ### 计算加速 -TiFlash 对 TiDB 的计算加速分为两部分:列存本身的读取效率提升以及为 TiDB 分担计算。其中分担计算的原理和 TiKV 的协处理器一致:TiDB 会将可以由存储层分担的计算下推。能否下推取决于 TiFlash 是否可以支持相关下推。具体介绍请参阅[“TiFlash 支持的计算下推”](/tiflash/tiflash-supported-pushdown-calculations.md)一节。 +TiFlash 通过两种方式加速 TiDB 的计算: + +- 列式存储引擎在执行读取操作时更高效。 +- TiFlash 分担 TiDB 的部分计算工作负载。 + +TiFlash 以与 TiKV 协处理器相同的方式分担计算工作负载:TiDB 下推可以在存储层完成的计算。计算是否可以下推取决于 TiFlash 的支持情况。详情请参见[支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md)。 ## 使用 TiFlash -TiFlash 部署完成后并不会自动同步数据,而需要手动指定需要同步的表。 +部署 TiFlash 后,数据复制不会自动开始。您需要手动指定要复制的表。 + + + +您可以根据自己的需求,使用 TiDB 读取 TiFlash 副本进行中等规模的分析处理,或使用 TiSpark 读取 TiFlash 副本进行大规模的分析处理。详情请参见以下章节: + + -你可以使用 TiDB 或者 TiSpark 读取 TiFlash,TiDB 适合用于中等规模的 OLAP 计算,而 TiSpark 适合大规模的 OLAP 计算,你可以根据自己的场景和使用习惯自行选择。具体参见: + + +您可以使用 TiDB 读取 TiFlash 副本进行分析处理。详情请参见以下章节: + + + +- [创建 TiFlash 副本](/tiflash/create-tiflash-replicas.md) +- [使用 TiDB 读取 TiFlash 副本](/tiflash/use-tidb-to-read-tiflash.md) + + + +- [使用 TiSpark 读取 TiFlash 副本](/tiflash/use-tispark-to-read-tiflash.md) + + -- [构建 TiFlash 副本](/tiflash/create-tiflash-replicas.md) -- [使用 TiDB 读取 TiFlash](/tiflash/use-tidb-to-read-tiflash.md) -- [使用 TiSpark 读取 TiFlash](/tiflash/use-tispark-to-read-tiflash.md) - [使用 MPP 模式](/tiflash/use-tiflash-mpp-mode.md) -如果需要快速体验以 TPC-H 为例子,从导入到查询的完整流程,可以参考 [HTAP 快速上手指南](/quick-start-with-htap.md)。 + + +要体验从导入数据到在 TPC-H 数据集中查询的完整过程,请参考 [TiDB HTAP 快速上手指南](/quick-start-with-htap.md)。 + + ## 另请参阅 -- 全新部署一个包含 TiFlash 节点的集群,请参考[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md) -- 已有集群新增一个 TiFlash 节点,请参考[扩容 TiFlash 节点](/scale-tidb-using-tiup.md#扩容-tiflash-节点) -- [TiFlash 常见运维操作](/tiflash/maintain-tiflash.md) -- [TiFlash 性能调优](/tiflash/tune-tiflash-performance.md) -- [TiFlash 配置参数介绍](/tiflash/tiflash-configuration.md) -- [TiFlash 监控说明](/tiflash/monitor-tiflash.md) -- [TiFlash 报警规则](/tiflash/tiflash-alert-rules.md) -- [TiFlash 常见问题处理](/tiflash/troubleshoot-tiflash.md) -- [TiFlash 支持的计算下推](/tiflash/tiflash-supported-pushdown-calculations.md) -- [TiFlash 数据校验](/tiflash/tiflash-data-validation.md) -- [TiFlash 兼容性说明](/tiflash/tiflash-compatibility.md) + + +- 要部署带有 TiFlash 节点的新集群,请参见[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)。 +- 要在已部署的集群中添加 TiFlash 节点,请参见[扩容 TiFlash 集群](/scale-tidb-using-tiup.md#扩容-tiflash-集群)。 +- [维护 TiFlash 集群](/tiflash/maintain-tiflash.md)。 +- [调优 TiFlash 性能](/tiflash/tune-tiflash-performance.md)。 +- [配置 TiFlash](/tiflash/tiflash-configuration.md)。 +- [监控 TiFlash 集群](/tiflash/monitor-tiflash.md)。 +- 了解 [TiFlash 告警规则](/tiflash/tiflash-alert-rules.md)。 +- [排查 TiFlash 集群问题](/tiflash/troubleshoot-tiflash.md)。 +- [TiFlash 支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md) +- [TiFlash 数据验证](/tiflash/tiflash-data-validation.md) +- [TiFlash 兼容性](/tiflash/tiflash-compatibility.md) + + + + + +- [调优 TiFlash 性能](/tiflash/tune-tiflash-performance.md)。 +- [TiFlash 支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md) +- [TiFlash 兼容性](/tiflash/tiflash-compatibility.md) + + diff --git a/tiflash/tiflash-pipeline-model.md b/tiflash/tiflash-pipeline-model.md index 7912ea973472..a75bd808dc30 100644 --- a/tiflash/tiflash-pipeline-model.md +++ b/tiflash/tiflash-pipeline-model.md @@ -1,63 +1,61 @@ --- -title: TiFlash Pipeline Model 执行模型 -summary: 介绍 TiFlash 新的执行模型 Pipeline Model。 +title: TiFlash 流水线执行模型 +summary: 了解 TiFlash 流水线执行模型。 --- -# TiFlash Pipeline Model 执行模型 +# TiFlash 流水线执行模型 -本文介绍 TiFlash 新的执行模型 Pipeline Model。 +本文介绍 TiFlash 流水线执行模型。 -从 v7.2.0 起,TiFlash 支持新的执行模型 Pipeline Model。 +从 v7.2.0 版本开始,TiFlash 支持新的执行模型——流水线执行模型。 -- v7.2.0 和 v7.3.0:TiFlash Pipeline Model 为实验特性,使用 [`tidb_enable_tiflash_pipeline_model`](https://docs.pingcap.com/zh/tidb/v7.2/system-variables#tidb_enable_tiflash_pipeline_model-从-v720-版本开始引入) 控制。 -- v7.4.0 及之后版本:Pipeline Model 成为正式功能。Pipeline Model 属于 TiFlash 内部特性,并且与 TiFlash 资源管控功能绑定,开启 TiFlash 资源管控功能时,Pipeline Model 模型将自动启用。关于 TiFlash 资源管控功能的使用方式,参考[使用资源管控 (Resource Control) 实现资源隔离](/tidb-resource-control.md#相关参数)。同时,从 v7.4.0 开始,变量 `tidb_enable_tiflash_pipeline_model` 被废弃。 +- 对于 v7.2.0 和 v7.3.0 版本:流水线执行模型处于实验阶段,由系统变量 [`tidb_enable_tiflash_pipeline_model`](https://docs.pingcap.com/tidb/v7.2/system-variables#tidb_enable_tiflash_pipeline_model-introduced-since-v720) 控制。 +- 对于 v7.4.0 及更高版本:流水线执行模型已正式发布。它是 TiFlash 的内部功能,与 TiFlash 资源控制紧密集成。当启用 TiFlash 资源控制时,流水线执行模型会自动启用。关于如何使用 TiFlash 资源控制的更多信息,请参考[使用资源控制实现资源隔离](/tidb-resource-control.md#parameters-for-resource-control)。此外,从 v7.4.0 版本开始,系统变量 `tidb_enable_tiflash_pipeline_model` 已被废弃。 -Pipeline Model 主要借鉴了 [Morsel-Driven Parallelism: A NUMA-Aware Query Evaluation Framework for the Many-Core Age](https://dl.acm.org/doi/10.1145/2588555.2610507) 这篇论文,提供了一个精细的任务调度模型,有别于传统的线程调度模型,减少了操作系统申请和调度线程的开销以及提供精细的调度机制。 +受论文 [Morsel-Driven Parallelism: A NUMA-Aware Query Evaluation Framework for the Many-Core Age](https://dl.acm.org/doi/10.1145/2588555.2610507) 的启发,TiFlash 流水线执行模型提供了一个细粒度的任务调度模型,这与传统的线程调度模型不同。它减少了操作系统线程应用和调度的开销,并提供了细粒度的调度机制。 -## 设计实现 +## 设计与实现 -TiFlash 原有执行模型 Stream Model 是线程调度执行模型,每一个查询会独立申请若干条线程协同执行。 +原始的 TiFlash 流模型是一个线程调度执行模型。每个查询独立申请若干线程进行协同执行。 -线程调度模型存在两个缺陷: +线程调度模型有以下两个缺陷: -- 在高并发场景下,过多的线程会引起较多上下文切换,导致较高的线程调度代价。 +- 在高并发场景下,过多的线程会导致大量的上下文切换,造成较高的线程调度成本。 +- 线程调度模型无法准确衡量查询的资源使用情况,也无法进行细粒度的资源控制。 -- 线程调度模型无法精准计量查询的资源使用量以及做细粒度的资源管控。 +新的流水线执行模型做了以下优化: -在新的执行模型 Pipeline Model 中进行了以下优化: +- 将查询划分为多个流水线并按顺序执行。在每个流水线中,尽可能将数据块保持在缓存中,以实现更好的时间局部性,提高整个执行过程的效率。 +- 为摆脱操作系统原生的线程调度模型,实现更细粒度的调度机制,每个流水线被实例化为若干任务,采用任务调度模型。同时使用固定的线程池,减少操作系统线程调度的开销。 -- 查询会被划分为多个 pipeline 并依次执行。在每个 pipeline 中,数据块会被尽可能保留在缓存中,从而实现更好的时间局部性,从而提高整个执行过程的效率。 +流水线执行模型的架构如下: -- 为了摆脱操作系统原生的线程调度模型,实现更加精细的调度机制,每个 pipeline 会被实例化成若干个 task,使用 task 调度模型,同时使用固定线程池,减少了操作系统申请和调度线程的开销。 +![TiFlash 流水线执行模型设计](/media/tiflash/tiflash-pipeline-model.png) -TiFlash Pipeline Model 的架构如下: +如上图所示,流水线执行模型主要由两个组件组成:流水线查询执行器和任务调度器。 -![TiFlash Pipeline Model Design](/media/tiflash/tiflash-pipeline-model.png) +- 流水线查询执行器 -如上图所示,Pipeline Model 中有两个主要组成部分:Pipeline Query Executor 和 Task Scheduler。 + 流水线查询执行器将从 TiDB 节点发送的查询请求转换为流水线有向无环图(DAG)。 -- Pipeline Query Executor + 它会在查询中找到流水线断点算子,根据流水线断点将查询拆分为若干个流水线。然后根据流水线之间的依赖关系,将流水线组装成 DAG。 - 负责将从 TiDB 节点发过来的查询请求转换为 pipeline dag。 + 流水线断点是具有暂停/阻塞逻辑的算子。这类算子会持续接收上游算子的数据块,直到接收完所有数据块后,才向下游算子返回处理结果。这类算子打断了数据处理的流水线,所以称为流水线断点。其中一个流水线断点是聚合算子,它会将上游算子的所有数据写入哈希表,然后计算哈希表中的数据并将结果返回给下游算子。 - 它会找到查询中的 pipeline breaker 算子,以 pipeline breaker 为边界将查询切分成若干个 pipeline,根据 pipeline 之间的依赖关系,将 pipeline 组装成一个有向无环图。 + 查询被转换为流水线 DAG 后,流水线查询执行器会根据依赖关系按顺序执行每个流水线。流水线根据查询并发度被实例化为若干任务,提交给任务调度器执行。 - pipeline breaker 用于指代存在停顿/阻塞逻辑的算子,这一类算子会持续接收上游算子传来的数据块,直到所有数据块都被接收后,才会将处理结果返回给下游算子。这类算子会破坏数据处理流水线,所以被称为 pipeline breaker。pipeline breaker 的代表有 Aggregation,它会将上游算子的数据都写入到哈希表后,才对哈希表中的数据做计算返回给下游算子。 +- 任务调度器 - 在查询被转换为 pipeline dag 后,Pipeline Query Executor 会按照依赖关系依次执行每个 pipeline。pipeline 会根据查询并发度被实例化成若干个 task 提交给 Task Scheduler 执行。 + 任务调度器执行流水线查询执行器提交的任务。任务根据不同的执行逻辑在任务调度器的不同组件之间动态切换。 -- Task Scheduler + - CPU 任务线程池 - 负责执行由 Pipeline Query Executor 提交过来的 task。task 会根据执行的逻辑的不同,在 Task Scheduler 里的不同组件中动态切换执行。 + 执行任务中的 CPU 密集型计算逻辑,如数据过滤和函数计算。 - - CPU Task Thread Pool + - IO 任务线程池 - 执行 task 中 CPU 密集型的计算逻辑,比如数据过滤、函数计算等。 + 执行任务中的 IO 密集型计算逻辑,如将中间结果写入磁盘。 - - IO Task Thread Pool + - 等待反应器 - 执行 task 中 IO 密集型的计算逻辑,比如计算中间结果落盘等。 - - - Wait Reactor - - 执行 task 中的等待逻辑,比如等待网络层将数据包传输给计算层等。 + 执行任务中的等待逻辑,如等待网络层将数据包传输到计算层。 diff --git a/tiflash/tiflash-results-materialization.md b/tiflash/tiflash-results-materialization.md index 48987a5b1f30..35bc5362f21b 100644 --- a/tiflash/tiflash-results-materialization.md +++ b/tiflash/tiflash-results-materialization.md @@ -1,22 +1,22 @@ --- title: TiFlash 查询结果物化 -summary: 介绍如何在同一个事务中保存 TiFlash 的查询结果。 +summary: 了解如何在事务中保存 TiFlash 的查询结果。 --- # TiFlash 查询结果物化 -本文介绍如何在同一个事务 (`INSERT INTO SELECT`) 中实现将 TiFlash 查询结果保存至某一指定的 TiDB 表中。 +本文介绍如何在 `INSERT INTO SELECT` 事务中将 TiFlash 查询结果保存到指定的 TiDB 表中。 -从 v6.5.0 起,TiDB 支持将 TiFlash 查询结果保存到数据表中,即物化了 TiFlash 的查询结果。执行 `INSERT INTO SELECT` 语句时,如果 TiDB 将 `SELECT` 子查询下推到了 TiFlash,TiFlash 的查询结果可以保存到 `INSERT INTO` 指定的 TiDB 表中。v6.5.0 之前的 TiDB 版本不允许此类行为,即通过 TiFlash 执行的查询必须是只读的,你需要从应用程序层面接收 TiFlash 返回的结果,然后另行在其它事务或处理中保存结果。 +从 v6.5.0 开始,TiDB 支持将 TiFlash 查询结果保存在表中,即 TiFlash 查询结果物化。在执行 `INSERT INTO SELECT` 语句时,如果 TiDB 将 `SELECT` 子查询下推到 TiFlash,TiFlash 的查询结果可以保存到 `INSERT INTO` 子句中指定的 TiDB 表中。对于 v6.5.0 之前的 TiDB 版本,TiFlash 查询结果是只读的,因此如果要保存 TiFlash 查询结果,必须从应用层获取结果,然后在单独的事务或进程中保存。 > **注意:** > -> 默认情况下 ([`tidb_allow_mpp = ON`](/system-variables.md#tidb_allow_mpp-从-v50-版本开始引入)),优化器将根据 [SQL 模式](/sql-mode.md) 及 TiFlash 副本的代价估算自行决定是否将查询下推到 TiFlash。 +> 默认情况下([`tidb_allow_mpp = ON`](/system-variables.md#tidb_allow_mpp-new-in-v50)),优化器会根据 [SQL 模式](/sql-mode.md)和 TiFlash 副本的成本估算智能决定是否将查询下推到 TiFlash。 > -> - 如果当前会话的 [SQL 模式](/sql-mode.md)为非严格模式(即 `sql_mode` 值不包含 `STRICT_TRANS_TABLES` 和 `STRICT_ALL_TABLES`),优化器会根据 TiFlash 副本的代价估算自行决定是否将 `INSERT INTO SELECT` 中的 `SELECT` 子查询将下推到 TiFlash。在此模式下,如需忽略优化器代价估算强制使用 TiFlash 查询,你可以设置[`tidb_enforce_mpp`](/system-variables.md#tidb_enforce_mpp-从-v51-版本开始引入) 为 `ON`。 -> - 如果当前会话的 [SQL 模式](/sql-mode.md)为严格模式(即 `sql_mode` 值包含 `STRICT_TRANS_TABLES` 或 `STRICT_ALL_TABLES`),`INSERT INTO SELECT` 中的 `SELECT` 子查询将无法下推到 TiFlash。 +> - 如果当前会话的 [SQL 模式](/sql-mode.md)不是严格模式(即 `sql_mode` 值不包含 `STRICT_TRANS_TABLES` 和 `STRICT_ALL_TABLES`),优化器会根据 TiFlash 副本的成本估算智能决定是否将 `INSERT INTO SELECT` 中的 `SELECT` 子查询下推到 TiFlash。在这种模式下,如果你想忽略优化器的成本估算并强制将查询下推到 TiFlash,可以将系统变量 [`tidb_enforce_mpp`](/system-variables.md#tidb_enforce_mpp-new-in-v51) 设置为 `ON`。 +> - 如果当前会话的 [SQL 模式](/sql-mode.md)是严格模式(即 `sql_mode` 值包含 `STRICT_TRANS_TABLES` 或 `STRICT_ALL_TABLES`),`INSERT INTO SELECT` 中的 `SELECT` 子查询不能下推到 TiFlash。 -`INSERT INTO SELECT` 语法如下: +`INSERT INTO SELECT` 的语法如下: ```sql INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] @@ -32,7 +32,7 @@ assignment: assignment [, assignment] ... ``` -例如,通过以下 `INSERT INTO SELECT` 语句,你可以将 `SELECT` 子句中表 `t1` 的查询结果保存到表 `t2` 中: +例如,你可以使用以下 `INSERT INTO SELECT` 语句将 `SELECT` 子句中表 `t1` 的查询结果保存到表 `t2` 中: ```sql INSERT INTO t2 (name, country) @@ -43,28 +43,40 @@ SELECT app_name, country FROM t1; - 高效的 BI 解决方案 - 很多报表类应用有较重的分析查询,如果有很多用户同时打开和刷新报表,则会产生较多的查询请求。一个有效的解决方案是使用本功能在 TiDB 表中保存报表查询的结果,报表刷新时再从结果表中抽取数据,则可以避免多次重复的分析计算。同理,在保存历史分析记录的基础上,可以进一步优化长时间历史数据分析的计算量。例如,某报表 A 用于分析每日的销售利润,使用本功能你可以将报表 A 中每日的分析结果保存到某结果表 T 中。那么,在生成报表 B 分析过去一个月的销售利润时,可以直接使用表 T 中的每日分析结果数据,不仅大幅降低计算量也提升了查询响应速度,减轻系统负载。 + 对于许多 BI 应用来说,分析查询请求非常重。例如,当大量用户同时访问和刷新报表时,BI 应用需要处理大量并发查询请求。为了有效处理这种情况,你可以使用 `INSERT INTO SELECT` 将报表的查询结果保存在 TiDB 表中。然后,最终用户在刷新报表时可以直接从结果表中查询数据,避免多次重复计算和分析。同样,通过保存历史分析结果,你可以进一步减少长期历史数据分析的计算量。例如,如果你有一个用于分析每日销售利润的报表 `A`,你可以使用 `INSERT INTO SELECT` 将报表 `A` 的结果保存到结果表 `T` 中。然后,当你需要生成一个分析过去一个月销售利润的报表 `B` 时,你可以直接使用表 `T` 中的每日分析结果。这种方式不仅大大减少了计算量,还提高了查询响应速度并降低了系统负载。 - 使用 TiFlash 服务在线应用 - TiFlash 支持的并发请求数量视数据量和查询复杂度不同,但一般不会超过 100 QPS。你可以使用本功能保存 TiFlash 的查询结果,然后通过查询结果表来支持在线的高并发请求。后台的结果表数据更新可以以较低的频率进行,例如以 0.5 秒间隔更新结果表数据也远低于 TiFlash 的并发上限,同时仍然较好地保证了数据新鲜度。 + TiFlash 支持的并发请求数量取决于数据量和查询复杂度,但通常不超过 100 QPS。你可以使用 `INSERT INTO SELECT` 保存 TiFlash 查询结果,然后使用查询结果表来支持高并发的在线请求。结果表中的数据可以在后台以低频率(例如,每 0.5 秒)更新,这远低于 TiFlash 的并发限制,同时仍然保持较高的数据新鲜度。 ## 执行过程 -* 在 `INSERT INTO SELECT` 语句的执行过程中,TiFlash 首先将 `SELECT` 子句的查询结果返回到集群中某单一 TiDB server 节点,然后再写入目标表(可以有 TiFlash 副本)。 -* `INSERT INTO SELECT` 语句的执行保证 ACID 特性。 +* 在执行 `INSERT INTO SELECT` 语句期间,TiFlash 首先将 `SELECT` 子句的查询结果返回给集群中的 TiDB 服务器,然后将结果写入目标表,该表可以有 TiFlash 副本。 +* `INSERT INTO SELECT` 语句的执行保证 ACID 属性。 ## 限制 -* TiDB 对 `INSERT INTO SELECT` 语句的内存限制可以通过系统变量 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 调整。从 v6.5.0 版本开始,不推荐使用 [`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit) 来控制事务内存大小,详见该配置项文档。 + - 更多信息,请参考 [TiDB 内存控制](/configure-memory-usage.md)。 +* TiDB 对 `INSERT INTO SELECT` 语句的内存限制可以通过系统变量 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 调整。从 v6.5.0 开始,不建议使用 [`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit) 控制事务内存大小。 -* TiDB 对 `INSERT INTO SELECT` 语句的并发没有硬性限制,但是推荐考虑以下用法: + 更多信息,请参见 [TiDB 内存控制](/configure-memory-usage.md)。 - * 当“写事务”较大时,例如接近 1 GiB,建议控制并发不超过 10。 - * 当“写事务”较小时,例如小于 100 MiB,建议控制并发不超过 30。 - * 请基于测试和具体情况做出合理选择。 + + + + +* TiDB 对 `INSERT INTO SELECT` 语句的内存限制可以通过系统变量 [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) 调整。从 v6.5.0 开始,不建议使用 [`txn-total-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-total-size-limit) 控制事务内存大小。 + + 更多信息,请参见 [TiDB 内存控制](https://docs.pingcap.com/tidb/stable/configure-memory-usage)。 + + + +* TiDB 对 `INSERT INTO SELECT` 语句的并发没有硬性限制,但建议考虑以下做法: + + * 当"写事务"较大时,例如接近 1 GiB,建议将并发控制在不超过 10。 + * 当"写事务"较小时,例如小于 100 MiB,建议将并发控制在不超过 30。 + * 根据测试结果和具体情况确定并发数。 ## 示例 @@ -74,19 +86,18 @@ SELECT app_name, country FROM t1; CREATE TABLE detail_data ( ts DATETIME, -- 费用产生时间 customer_id VARCHAR(20), -- 客户 ID - detail_fee DECIMAL(20,2)); -- 费用数额 - + detail_fee DECIMAL(20,2)); -- 费用金额 CREATE TABLE daily_data ( - rec_date DATE, -- 汇总数据的日期 + rec_date DATE, -- 数据采集日期 customer_id VARCHAR(20), -- 客户 ID - daily_fee DECIMAL(20,2)); -- 单日汇总费用 + daily_fee DECIMAL(20,2)); -- 每日费用金额 ALTER TABLE detail_data SET TIFLASH REPLICA 2; ALTER TABLE daily_data SET TIFLASH REPLICA 2; --- ... (detail_data 表不断增加数据) -INSERT INTO detail_data(ts,customer_id,detail_fee) VALUES +-- ... (detail_data 表持续更新) +INSERT INTO detail_data(ts,customer_id,detail_fee) VALUES ('2023-1-1 12:2:3', 'cus001', 200.86), ('2023-1-2 12:2:3', 'cus002', 100.86), ('2023-1-3 12:2:3', 'cus002', 2200.86), @@ -96,11 +107,11 @@ INSERT INTO detail_data(ts,customer_id,detail_fee) VALUES ('2023-1-7 12:2:3', 'cus004', 120.56), ('2023-1-8 12:2:3', 'cus005', 320.16); --- 重复执行以下 SQL 语句 13 次,一共插入 65536 行数据 +-- 执行以下 SQL 语句 13 次,累计向表中插入 65,536 行数据。 INSERT INTO detail_data SELECT * FROM detail_data; ``` -每日分析数据保存: +保存每日分析结果: ```sql SET @@sql_mode='NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO'; @@ -109,10 +120,10 @@ INSERT INTO daily_data (rec_date, customer_id, daily_fee) SELECT DATE(ts), customer_id, sum(detail_fee) FROM detail_data WHERE DATE(ts) > DATE('2023-1-1 12:2:3') GROUP BY DATE(ts), customer_id; ``` -基于日分析数据的月数据分析: +基于每日分析数据分析月度数据: ```sql SELECT MONTH(rec_date), customer_id, sum(daily_fee) FROM daily_data GROUP BY MONTH(rec_date), customer_id; ``` -将每日分析结果数据物化,保存到日数据结果表中。使用日数据结果表加速月数据分析,从而提升月数据分析效率。 \ No newline at end of file +上述示例将每日分析结果物化并保存到每日结果表中,基于此加速月度数据分析,从而提高数据分析效率。 diff --git a/tiflash/tiflash-spill-disk.md b/tiflash/tiflash-spill-disk.md index 032bd6e36fc6..8201de8b36f4 100644 --- a/tiflash/tiflash-spill-disk.md +++ b/tiflash/tiflash-spill-disk.md @@ -1,39 +1,39 @@ --- title: TiFlash 数据落盘 -summary: 介绍 TiFlash 数据落盘功能。 +summary: 了解 TiFlash 如何将数据落盘以及如何自定义落盘行为。 --- # TiFlash 数据落盘 -本文介绍 TiFlash 计算过程中的数据落盘功能。 +本文介绍 TiFlash 在计算过程中如何将数据落盘。 -从 v7.0.0 起,TiFlash 支持在计算过程中将中间数据落盘以缓解内存压力。目前支持落盘的算子有: +从 v7.0.0 开始,TiFlash 支持将中间数据落盘以缓解内存压力。支持以下算子: -* 带有等值关联条件的 Hash Join 算子 -* 带有 `GROUP BY` key 的 Hash Aggregation 算子 -* TopN 算子以及窗口函数中的 Sort 算子 +* 具有等值连接条件的 Hash Join 算子 +* 具有 `GROUP BY` 键的 Hash Aggregation 算子 +* TopN 算子和 Window 函数中的 Sort 算子 -## TiFlash 数据落盘的触发机制 +## 触发落盘 -TiFlash 数据落盘的触发机制有两种: +TiFlash 提供了两种触发数据落盘的机制。 -* 算子级别的落盘,即通过指定各个算子的数据落盘阈值,来触发 TiFlash 将对应算子的数据进行落盘。 -* 查询级别的落盘,即通过指定单个查询在单个 TiFlash 节点的最大内存使用量以及落盘的阈值,来触发 TiFlash 将查询中支持落盘的算子的数据按需进行落盘。 +* 算子级别落盘:通过为每个算子指定数据落盘阈值,你可以控制 TiFlash 何时将该算子的数据落盘。 +* 查询级别落盘:通过指定 TiFlash 节点上查询的最大内存使用量和落盘的内存比例,你可以控制 TiFlash 何时根据需要将查询中支持的算子数据落盘。 -### 算子级别的落盘 +### 算子级别落盘 -从 v7.0.0 起,TiFlash 支持算子级别的自动落盘。你可通过以下系统变量,来控制各算子数据落盘的阈值。当算子使用的内存超过阈值之后,TiFlash 会触发对应算子的落盘。 +从 v7.0.0 开始,TiFlash 支持算子级别的自动落盘。你可以使用以下系统变量控制每个算子的数据落盘阈值。当算子的内存使用超过阈值时,TiFlash 会触发该算子的落盘。 -* [`tidb_max_bytes_before_tiflash_external_group_by`](/system-variables.md#tidb_max_bytes_before_tiflash_external_group_by-从-v700-版本开始引入) -* [`tidb_max_bytes_before_tiflash_external_join`](/system-variables.md#tidb_max_bytes_before_tiflash_external_join-从-v700-版本开始引入) -* [`tidb_max_bytes_before_tiflash_external_sort`](/system-variables.md#tidb_max_bytes_before_tiflash_external_sort-从-v700-版本开始引入) +* [`tidb_max_bytes_before_tiflash_external_group_by`](/system-variables.md#tidb_max_bytes_before_tiflash_external_group_by-new-in-v700) +* [`tidb_max_bytes_before_tiflash_external_join`](/system-variables.md#tidb_max_bytes_before_tiflash_external_join-new-in-v700) +* [`tidb_max_bytes_before_tiflash_external_sort`](/system-variables.md#tidb_max_bytes_before_tiflash_external_sort-new-in-v700) #### 示例 -本示例构造一个占用大量内存的 SQL 语句来对 Hash Aggregation 算子的落盘功能进行演示: +本示例构造一个消耗大量内存的 SQL 语句来演示 Hash Aggregation 算子的落盘。 -1. 准备数据。创建一个包含 2 个节点的 TiFlash 集群,并导入 TPCH-100 的数据。 -2. 执行以下语句。该语句不限制带 `GROUP BY` 的 Hash Aggregation 算子的内存使用量。 +1. 准备环境。创建一个包含 2 个节点的 TiFlash 集群并导入 TPCH-100 数据。 +2. 执行以下语句。这些语句不限制具有 `GROUP BY` 键的 Hash Aggregation 算子的内存使用。 ```sql SET tidb_max_bytes_before_tiflash_external_group_by = 0; @@ -49,13 +49,13 @@ TiFlash 数据落盘的触发机制有两种: HAVING SUM(l_quantity) > 314; ``` -3. 从 TiFlash 的日志中可以看到,该查询在单个 TiFlash 节点上需要消耗 29.55 GiB 内存: +3. 从 TiFlash 的日志中可以看到,该查询在单个 TiFlash 节点上需要消耗 29.55 GiB 的内存: ``` [DEBUG] [MemoryTracker.cpp:69] ["Peak memory usage (total): 29.55 GiB."] [source=MemoryTracker] [thread_id=468] ``` -4. 执行以下语句。该语句限制了带 `GROUP BY` 的 Hash Aggregation 算子的内存使用量,不超过 10737418240 (10 GiB)。 +4. 执行以下语句。此语句将具有 `GROUP BY` 键的 Hash Aggregation 算子的内存使用限制为 10737418240(10 GiB)。 ```sql SET tidb_max_bytes_before_tiflash_external_group_by = 10737418240; @@ -71,28 +71,28 @@ TiFlash 数据落盘的触发机制有两种: HAVING SUM(l_quantity) > 314; ``` -5. 从 TiFlash 的日志中可以看出,通过配置 `tidb_max_bytes_before_tiflash_external_group_by`,TiFlash 触发了中间结果落盘,显著减小了查询所需的内存。 +5. 从 TiFlash 的日志中可以看到,通过配置 `tidb_max_bytes_before_tiflash_external_group_by`,TiFlash 触发了中间结果的落盘,显著降低了查询使用的内存。 ``` [DEBUG] [MemoryTracker.cpp:69] ["Peak memory usage (total): 12.80 GiB."] [source=MemoryTracker] [thread_id=110] ``` -### 查询级别的落盘 +### 查询级别落盘 -从 v7.4.0 开始,TiFlash 支持查询级别的自动落盘机制。你可以通过以下系统变量,来控制查询级别的自动落盘: +从 v7.4.0 开始,TiFlash 支持查询级别的自动落盘。你可以使用以下系统变量控制此功能: -* [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-从-v740-版本开始引入):用于控制单个查询在单个 TiFlash 节点内存使用的上限 -* [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-从-v740-版本开始引入):用于控制触发数据落盘的内存阈值 +* [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-new-in-v740):限制 TiFlash 节点上单个查询的最大内存使用量。 +* [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-new-in-v740):控制触发数据落盘的内存比例。 -当 `tiflash_mem_quota_query_per_node` 与 `tiflash_query_spill_ratio` 均设置为一个大于 0 的值时,TiFlash 会在一个查询的内存使用量超过 `tiflash_mem_quota_query_per_node * tiflash_query_spill_ratio` 时自动触发该查询中可以支持落盘的算子的落盘。 +如果 `tiflash_mem_quota_query_per_node` 和 `tiflash_query_spill_ratio` 都设置为大于 0 的值,当查询的内存使用超过 `tiflash_mem_quota_query_per_node * tiflash_query_spill_ratio` 时,TiFlash 会自动触发查询中支持的算子的落盘。 #### 示例 -本示例构造一个占用大量内存的 SQL 语句来对查询级别的落盘功能进行演示: +本示例构造一个消耗大量内存的 SQL 语句来演示查询级别的落盘。 -1. 准备数据。创建一个包含 2 个节点的 TiFlash 集群,并导入 TPCH-100 的数据。 +1. 准备环境。创建一个包含 2 个节点的 TiFlash 集群并导入 TPCH-100 数据。 -2. 执行以下语句。该查询未限制查询级别的内存使用量,也未限制带 `GROUP BY` 的 Hash Aggregation 算子的内存使用量。 +2. 执行以下语句。这些语句不限制查询的内存使用或具有 `GROUP BY` 键的 Hash Aggregation 算子的内存使用。 ```sql SET tidb_max_bytes_before_tiflash_external_group_by = 0; @@ -110,13 +110,13 @@ TiFlash 数据落盘的触发机制有两种: HAVING SUM(l_quantity) > 314; ``` -3. 从 TiFlash 的日志中可以看到,该查询在单个 TiFlash 节点上需要消耗 29.55 GiB 内存: +3. 从 TiFlash 的日志中可以看到,该查询在单个 TiFlash 节点上消耗了 29.55 GiB 的内存: ``` [DEBUG] [MemoryTracker.cpp:69] ["Peak memory usage (total): 29.55 GiB."] [source=MemoryTracker] [thread_id=468] ``` -4. 执行以下语句。该语句限制了单个查询在单个 TiFlash 节点的最大内存使用量为 5 GiB。 +4. 执行以下语句。这些语句将 TiFlash 节点上查询的最大内存使用量限制为 5 GiB。 ```sql SET tiflash_mem_quota_query_per_node = 5368709120; @@ -133,18 +133,22 @@ TiFlash 数据落盘的触发机制有两种: HAVING SUM(l_quantity) > 314; ``` -5. 从 TiFlash 的日志中可以看出,通过配置查询级别的自动落盘,TiFlash 触发了中间结果落盘,显著减小了查询所需的内存。 +5. 从 TiFlash 的日志中可以看到,通过配置查询级别落盘,TiFlash 触发了中间结果的落盘,显著降低了查询使用的内存。 ``` [DEBUG] [MemoryTracker.cpp:101] ["Peak memory usage (for query): 3.94 GiB."] [source=MemoryTracker] [thread_id=1547] ``` -## 注意 +## 注意事项 -* 当 Hash Aggregation 算子不带 `GROUP BY` key 时,不支持落盘。即使该 Hash Aggregation 中含有 `DISTINCT` 聚合函数,也不能触发落盘。 -* 目前算子级别落盘的阈值是针对单个算子来计算的。当未配置查询级别的数据落盘时,如果一个查询里有两个 Hash Aggregation 算子,并且算子的阈值设置为 10 GiB,那么两个 Hash Aggregation 算子仅会在各自占用的内存超过 10 GiB 时才会触发数据落盘。 -* 目前 Hash Aggregation 与 TopN/Sort 在 restore 阶段采用的是 merge aggregation 和 merge sort 的算法,所以这两个算子只会触发一次数据落盘。如果需要的内存特别大以至于在 restore 阶段内存使用仍然超阈值,不会再次触发落盘。 -* 目前 Hash Join 采用基于分区的落盘策略,在 restore 阶段如果内存使用仍然超过阈值,会继续触发落盘。但是为了控制落盘的规模,落盘的轮数限制为三轮。如果第三轮落盘之后的 restore 阶段内存使用仍然超过阈值,则不会触发新的落盘。 -* 当配置了查询级别的落盘机制(即 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-从-v740-版本开始引入) 和 [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-从-v740-版本开始引入) 均大于 0)时,TiFlash 单个算子的落盘阈值会被忽略,TiFlash 会根据查询级别的落盘阈值来自动触发该查询中相关算子的落盘。 -* 即使配置了查询级别的落盘,如果该查询中用到的算子均不支持落盘,该查询的中间计算结果仍然无法落盘。此时,如果查询的内存使用超过了相关阈值,TiFlash 会报错并终止查询。 -* 即使配置了查询级别的落盘,且查询中也含有支持落盘的算子,但是如果查询中其他不能落盘的算子占用了过多的内存或者支持落盘的算子落盘不及时,查询仍然有可能因为内存超过阈值而报错。对于落盘算子落盘不及时的情况,可以尝试调小 [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-从-v740-版本开始引入) 来避免查询内存超阈值报错。 +* 当 Hash Aggregation 算子没有 `GROUP BY` 键时,不支持落盘。即使 Hash Aggregation 算子包含 distinct 聚合函数,也不支持落盘。 +* 目前,算子级别落盘的阈值是针对每个算子单独计算的。对于包含两个 Hash Aggregation 算子的查询,如果未配置查询级别落盘,且聚合算子的阈值设置为 10 GiB,则两个 Hash Aggregation 算子只有在各自的内存使用超过 10 GiB 时才会落盘。 +* 目前,Hash Aggregation 算子和 TopN/Sort 算子在恢复阶段使用归并聚合和归并排序算法。因此,这两个算子只触发一轮落盘。如果内存需求非常高,且恢复阶段的内存使用仍然超过阈值,则不会再次触发落盘。 +* 目前,Hash Join 算子使用基于分区的落盘策略。如果恢复阶段的内存使用仍然超过阈值,则会再次触发落盘。但是,为了控制落盘的规模,落盘轮数限制为三轮。如果在第三轮落盘后恢复阶段的内存使用仍然超过阈值,则不会再次触发落盘。 +* 当配置了查询级别落盘(即 [`tiflash_mem_quota_query_per_node`](/system-variables.md#tiflash_mem_quota_query_per_node-new-in-v740) 和 [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-new-in-v740) 都大于 0)时,TiFlash 会忽略单个算子的落盘阈值,并根据查询级别落盘阈值自动触发查询中相关算子的落盘。 +* 即使配置了查询级别落盘,如果查询中使用的算子都不支持落盘,该查询的中间计算结果仍然无法落盘。在这种情况下,当该查询的内存使用超过相关阈值时,TiFlash 会返回错误并终止查询。 +* 即使配置了查询级别落盘且查询包含支持落盘的算子,在以下任一情况下,查询仍可能因超过内存阈值而返回错误: + - 查询中其他不支持落盘的算子消耗了太多内存。 + - 支持落盘的算子未及时落盘。 + + 要解决支持落盘的算子未及时落盘的情况,你可以尝试降低 [`tiflash_query_spill_ratio`](/system-variables.md#tiflash_query_spill_ratio-new-in-v740) 以避免内存阈值错误。 diff --git a/tiflash/tiflash-supported-pushdown-calculations.md b/tiflash/tiflash-supported-pushdown-calculations.md index d5f37de2da72..1db30ee7a0fc 100644 --- a/tiflash/tiflash-supported-pushdown-calculations.md +++ b/tiflash/tiflash-supported-pushdown-calculations.md @@ -1,50 +1,57 @@ --- -title: TiFlash 支持的计算下推 -summary: 了解 TiFlash 支持的计算下推。 +title: TiFlash 支持的下推计算 +summary: 了解 TiFlash 支持的下推计算。 --- -# TiFlash 支持的计算下推 +# TiFlash 支持的下推计算 -本文档介绍 TiFlash 支持的计算下推。 +本文介绍 TiFlash 支持的下推计算。 -## 支持下推的算子 +## 下推算子 -TiFlash 支持部分算子的下推,支持的算子如下: +TiFlash 支持下推以下算子: -* TableScan:该算子从表中读取数据 -* Selection:该算子对数据进行过滤 -* HashAgg:该算子基于 [Hash Aggregation](/explain-aggregation.md#hash-aggregation) 算法对数据进行聚合运算 -* StreamAgg:该算子基于 [Stream Aggregation](/explain-aggregation.md#stream-aggregation) 算法对数据进行聚合运算。StreamAgg 仅支持不带 `GROUP BY` 条件的列。 -* TopN:该算子对数据求 TopN 运算 -* Limit:该算子对数据进行 limit 运算 -* Project:该算子对数据进行投影运算 -* HashJoin:该算子基于 [Hash Join](/explain-joins.md#hash-join) 算法对数据进行连接运算: - * 只有在 [MPP 模式](/tiflash/use-tiflash-mpp-mode.md)下才能被下推 - * 支持的 Join 类型包括 Inner Join、Left Join、Semi Join、Anti Semi Join、Left Semi Join、Anti Left Semi Join - * 对于上述类型,既支持带等值条件的连接,也支持不带等值条件的连接(即 Cartesian Join 或者 Null-aware Semi Join);在计算 Cartesian Join 或者 Null-aware Semi Join 时,只会使用 Broadcast 算法,而不会使用 Shuffle Hash Join 算法 -* [Window](/functions-and-operators/window-functions.md):当前支持下推的窗口函数包括 `ROW_NUMBER()`、`RANK()`、`DENSE_RANK()`、`LEAD()`、`LAG()`、`FIRST_VALUE()` 和 `LAST_VALUE()` +* TableScan:读取表中的数据。 +* Selection:过滤数据。 +* HashAgg:基于[哈希聚合](/explain-aggregation.md#hash-aggregation)算法执行数据聚合。 +* StreamAgg:基于[流式聚合](/explain-aggregation.md#stream-aggregation)算法执行数据聚合。StreamAgg 仅支持不带 `GROUP BY` 条件的聚合。 +* TopN:执行 TopN 计算。 +* Limit:执行 limit 计算。 +* Project:执行投影计算。 +* HashJoin:使用[哈希连接](/explain-joins.md#hash-join)算法执行连接计算,但有以下条件: + * 该算子仅在 [MPP 模式](/tiflash/use-tiflash-mpp-mode.md)下可以下推。 + * 支持的连接类型包括 Inner Join、Left Join、Semi Join、Anti Semi Join、Left Semi Join 和 Anti Left Semi Join。 + * 上述连接类型支持等值连接和非等值连接(笛卡尔积连接或空感知半连接)。在计算笛卡尔积连接或空感知半连接时,使用广播算法而不是 Shuffle Hash Join 算法。 +* [窗口函数](/functions-and-operators/window-functions.md):目前 TiFlash 支持 `ROW_NUMBER()`、`RANK()`、`DENSE_RANK()`、`LEAD()`、`LAG()`、`FIRST_VALUE()` 和 `LAST_VALUE()`。 -在 TiDB 中,算子之间会呈现树型组织结构。一个算子能下推到 TiFlash 的前提条件,是该算子的所有子算子都能下推到 TiFlash。因为大部分算子都包含有表达式计算,当且仅当一个算子所包含的所有表达式均支持下推到 TiFlash 时,该算子才有可能下推给 TiFlash。 +在 TiDB 中,算子以树状结构组织。要将算子下推到 TiFlash,必须满足以下所有前提条件: -## 支持下推的表达式 ++ 其所有子算子都可以下推到 TiFlash。 ++ 如果算子包含表达式(大多数算子都包含表达式),则该算子的所有表达式都可以下推到 TiFlash。 -| 表达式类型 | 运算 | +## 下推表达式 + +TiFlash 支持以下下推表达式: + +| 表达式类型 | 运算符和函数 | | :-------------- | :------------------------------------- | -| [数学函数](/functions-and-operators/numeric-functions-and-operators.md) | `+`, `-`, `/`, `*`, `%`, `>=`, `<=`, `=`, `!=`, `<`, `>`, `ROUND()`, `ABS()`, `FLOOR(int)`, `CEIL(int)`, `CEILING(int)`, `SQRT()`, `LOG()`, `LOG2()`, `LOG10()`, `LN()`, `EXP()`, `POW()`, `POWER()`, `SIGN()`, `RADIANS()`, `DEGREES()`, `CONV()`, `CRC32()`, `GREATEST(int/real)`, `LEAST(int/real)` | -| [逻辑函数](/functions-and-operators/control-flow-functions.md)和[算子](/functions-and-operators/operators.md) | `AND`, `OR`, `NOT`, `CASE WHEN`, `IF()`, `IFNULL()`, `ISNULL()`, `IN`, `LIKE`, `ILIKE`, `COALESCE`, `IS` | -| [位运算](/functions-and-operators/bit-functions-and-operators.md) | `&` (bitand), \| (bitor), `~` (bitneg), `^` (bitxor) | -| [字符串函数](/functions-and-operators/string-functions.md) | `SUBSTR()`, `CHAR_LENGTH()`, `REPLACE()`, `CONCAT()`, `CONCAT_WS()`, `LEFT()`, `RIGHT()`, `ASCII()`, `LENGTH()`, `TRIM()`, `LTRIM()`, `RTRIM()`, `POSITION()`, `FORMAT()`, `LOWER()`, `UCASE()`, `UPPER()`, `SUBSTRING_INDEX()`, `LPAD()`, `RPAD()`, `STRCMP()` | -| [正则函数和算子](/functions-and-operators/string-functions.md) | `REGEXP`, `REGEXP_LIKE()`, `REGEXP_INSTR()`, `REGEXP_SUBSTR()`, `REGEXP_REPLACE()`, `RLIKE` | -| [日期函数](/functions-and-operators/date-and-time-functions.md) | `DATE_FORMAT()`, `TIMESTAMPDIFF()`, `FROM_UNIXTIME()`, `UNIX_TIMESTAMP(int)`, `UNIX_TIMESTAMP(decimal)`, `STR_TO_DATE(date)`, `STR_TO_DATE(datetime)`, `DATEDIFF()`, `YEAR()`, `MONTH()`, `DAY()`, `EXTRACT(datetime)`, `DATE()`, `HOUR()`, `MICROSECOND()`, `MINUTE()`, `SECOND()`, `SYSDATE()`, `DATE_ADD/ADDDATE(datetime, int)`, `DATE_ADD/ADDDATE(string, int/real)`, `DATE_SUB/SUBDATE(datetime, int)`, `DATE_SUB/SUBDATE(string, int/real)`, `QUARTER()`, `DAYNAME()`, `DAYOFMONTH()`, `DAYOFWEEK()`, `DAYOFYEAR()`, `LAST_DAY()`, `MONTHNAME()`, `TO_SECONDS()`, `TO_DAYS()`, `FROM_DAYS()`, `WEEKOFYEAR()` | -| [JSON 函数](/functions-and-operators/json-functions.md) | `JSON_LENGTH()`, `->`, `->>`, `JSON_EXTRACT()`, `JSON_ARRAY()`, `JSON_DEPTH()`, `JSON_VALID()`, `JSON_KEYS()`, `JSON_CONTAINS_PATH()`, `JSON_UNQUOTE()` | -| [转换函数](/functions-and-operators/cast-functions-and-operators.md) | `CAST(int AS DOUBLE), CAST(int AS DECIMAL)`, `CAST(int AS STRING)`, `CAST(int AS TIME)`, `CAST(double AS INT)`, `CAST(double AS DECIMAL)`, `CAST(double AS STRING)`, `CAST(double AS TIME)`, `CAST(string AS INT)`, `CAST(string AS DOUBLE), CAST(string AS DECIMAL)`, `CAST(string AS TIME)`, `CAST(decimal AS INT)`, `CAST(decimal AS STRING)`, `CAST(decimal AS TIME)`, `CAST(decimal AS DOUBLE)`, `CAST(time AS INT)`, `CAST(time AS DECIMAL)`, `CAST(time AS STRING)`, `CAST(time AS REAL)`, `CAST(json AS JSON)`, `CAST(json AS STRING)`, `CAST(int AS JSON)`, `CAST(real AS JSON)`, `CAST(decimal AS JSON)`, `CAST(string AS JSON)`, `CAST(time AS JSON)`, `CAST(duration AS JSON)` | -| [聚合函数](/functions-and-operators/aggregate-group-by-functions.md) | `MIN()`, `MAX()`, `SUM()`, `COUNT()`, `AVG()`, `APPROX_COUNT_DISTINCT()`, `GROUP_CONCAT()` | -| [其他函数](/functions-and-operators/miscellaneous-functions.md) | `INET_NTOA()`, `INET_ATON()`, `INET6_NTOA()`, `INET6_ATON()` | - -## 下推限制 - -* 所有包含 Bit、Set 和 Geometry 类型的表达式均不能下推到 TiFlash -* `DATE_ADD()`、`DATE_SUB()`、`ADDDATE()` 以及 `SUBDATE()` 中的 interval 类型只支持如下几种,如使用了其他类型的 interval,TiFlash 会在运行时报错。 +| [数值函数和运算符](/functions-and-operators/numeric-functions-and-operators.md) | `+`、`-`、`/`、`*`、`%`、`>=`、`<=`、`=`、`!=`、`<`、`>`、`ROUND()`、`ABS()`、`FLOOR(int)`、`CEIL(int)`、`CEILING(int)`、`SQRT()`、`LOG()`、`LOG2()`、`LOG10()`、`LN()`、`EXP()`、`POW()`、`POWER()`、`SIGN()`、`RADIANS()`、`DEGREES()`、`CONV()`、`CRC32()`、`GREATEST(int/real)`、`LEAST(int/real)` | +| [逻辑函数](/functions-and-operators/control-flow-functions.md)和[运算符](/functions-and-operators/operators.md) | `AND`、`OR`、`NOT`、`CASE WHEN`、`IF()`、`IFNULL()`、`ISNULL()`、`IN`、`LIKE`、`ILIKE`、`COALESCE`、`IS` | +| [位运算](/functions-and-operators/bit-functions-and-operators.md) | `&`(按位与)、\|(按位或)、`~`(按位取反)、`^`(按位异或) | +| [字符串函数](/functions-and-operators/string-functions.md) | `SUBSTR()`、`CHAR_LENGTH()`、`REPLACE()`、`CONCAT()`、`CONCAT_WS()`、`LEFT()`、`RIGHT()`、`ASCII()`、`LENGTH()`、`TRIM()`、`LTRIM()`、`RTRIM()`、`POSITION()`、`FORMAT()`、`LOWER()`、`UCASE()`、`UPPER()`、`SUBSTRING_INDEX()`、`LPAD()`、`RPAD()`、`STRCMP()` | +| [正则表达式函数和运算符](/functions-and-operators/string-functions.md) | `REGEXP`、`REGEXP_LIKE()`、`REGEXP_INSTR()`、`REGEXP_SUBSTR()`、`REGEXP_REPLACE()`、`RLIKE` | +| [日期函数](/functions-and-operators/date-and-time-functions.md) | `DATE_FORMAT()`、`TIMESTAMPDIFF()`、`FROM_UNIXTIME()`、`UNIX_TIMESTAMP(int)`、`UNIX_TIMESTAMP(decimal)`、`STR_TO_DATE(date)`、`STR_TO_DATE(datetime)`、`DATEDIFF()`、`YEAR()`、`MONTH()`、`DAY()`、`EXTRACT(datetime)`、`DATE()`、`HOUR()`、`MICROSECOND()`、`MINUTE()`、`SECOND()`、`SYSDATE()`、`DATE_ADD/ADDDATE(datetime, int)`、`DATE_ADD/ADDDATE(string, int/real)`、`DATE_SUB/SUBDATE(datetime, int)`、`DATE_SUB/SUBDATE(string, int/real)`、`QUARTER()`、`DAYNAME()`、`DAYOFMONTH()`、`DAYOFWEEK()`、`DAYOFYEAR()`、`LAST_DAY()`、`MONTHNAME()`、`TO_SECONDS()`、`TO_DAYS()`、`FROM_DAYS()`、`WEEKOFYEAR()` | +| [JSON 函数](/functions-and-operators/json-functions.md) | `JSON_LENGTH()`、`->`、`->>`、`JSON_EXTRACT()`、`JSON_ARRAY()`、`JSON_DEPTH()`、`JSON_VALID()`、`JSON_KEYS()`、`JSON_CONTAINS_PATH()`、`JSON_UNQUOTE()` | +| [类型转换函数](/functions-and-operators/cast-functions-and-operators.md) | `CAST(int AS DOUBLE)、CAST(int AS DECIMAL)`、`CAST(int AS STRING)`、`CAST(int AS TIME)`、`CAST(double AS INT)`、`CAST(double AS DECIMAL)`、`CAST(double AS STRING)`、`CAST(double AS TIME)`、`CAST(string AS INT)`、`CAST(string AS DOUBLE)、CAST(string AS DECIMAL)`、`CAST(string AS TIME)`、`CAST(decimal AS INT)`、`CAST(decimal AS STRING)`、`CAST(decimal AS TIME)`、`CAST(decimal AS DOUBLE)`、`CAST(time AS INT)`、`CAST(time AS DECIMAL)`、`CAST(time AS STRING)`、`CAST(time AS REAL)`、`CAST(json AS JSON)`、`CAST(json AS STRING)`、`CAST(int AS JSON)`、`CAST(real AS JSON)`、`CAST(decimal AS JSON)`、`CAST(string AS JSON)`、`CAST(time AS JSON)`、`CAST(duration AS JSON)` | +| [聚合函数](/functions-and-operators/aggregate-group-by-functions.md) | `MIN()`、`MAX()`、`SUM()`、`COUNT()`、`AVG()`、`APPROX_COUNT_DISTINCT()`、`GROUP_CONCAT()` | +| [其他函数](/functions-and-operators/miscellaneous-functions.md) | `INET_NTOA()`、`INET_ATON()`、`INET6_NTOA()`、`INET6_ATON()` | + +## 限制 + +* 包含 Bit、Set 和 Geometry 类型的表达式不能下推到 TiFlash。 + +* `DATE_ADD()`、`DATE_SUB()`、`ADDDATE()` 和 `SUBDATE()` 函数仅支持以下间隔类型。如果使用其他间隔类型,TiFlash 会报错。 + * DAY * WEEK * MONTH @@ -53,15 +60,15 @@ TiFlash 支持部分算子的下推,支持的算子如下: * MINUTE * SECOND -如查询遇到不支持的下推计算,则需要依赖 TiDB 完成剩余计算,可能会很大程度影响 TiFlash 加速效果。对于暂不支持的算子/表达式,将会在后续版本中陆续支持。 +如果查询遇到不支持的下推计算,TiDB 需要完成剩余的计算,这可能会大大影响 TiFlash 的加速效果。当前不支持的算子和表达式可能会在未来版本中得到支持。 -类似 `MAX()` 这样的函数在聚合算子中支持下推,但是在窗口函数算子中还不支持下推。 +像 `MAX()` 这样的函数在作为聚合函数时支持下推,但作为窗口函数时不支持下推。 ## 示例 -以下通过一些例子对下推算子和表达式到 TiFlash 进行说明。 +本节提供一些将算子和表达式下推到 TiFlash 的示例。 -### 示例 1:下推算子到 TiFlash 存储 +### 示例 1:将算子下推到 TiFlash ```sql CREATE TABLE t(id INT PRIMARY KEY, a INT); @@ -81,9 +88,9 @@ EXPLAIN SELECT * FROM t LIMIT 3; 5 rows in set (0.18 sec) ``` -在该查询中,算子 Limit 被下推到 TiFlash 对数据进行过滤,减少了网络传输数据量,进而减少网络传输开销。具体可查看以上示例中 `Limit_15` 算子的 `task` 列,其值为 `mpp[tiflash]`,表示该算子被下推到 TiFlash。 +在上述示例中,`Limit` 算子被下推到 TiFlash 进行数据过滤,这有助于减少需要通过网络传输的数据量,从而减少网络开销。这可以从 `Limit_15` 算子所在行的 `task` 列值为 `mpp[tiflash]` 看出。 -### 示例 2:下推表达式到 TiFlash 存储 +### 示例 2:将表达式下推到 TiFlash ```sql CREATE TABLE t(id INT PRIMARY KEY, a INT); @@ -105,10 +112,9 @@ EXPLAIN SELECT MAX(id + a) FROM t GROUP BY a; | └─TableFullScan_21 | 6.00 | mpp[tiflash] | table:t | keep order:false, stats:pseudo | +------------------------------------+---------+--------------+---------------+---------------------------------------------------------------------------+ 8 rows in set (0.18 sec) - ``` -在该查询中,表达式 `id + a` 被下推到 TiFlash,从而能提前进行计算,减少网络传输数据量,进而减少网络传输开销,提升整体计算性能。具体可查看以上示例中 `operator` 列为 `plus(test.t.id, test.t.a)` 的行的 `task` 列,其值为 `mpp[tiflash]`,表示该表达式被下推到 TiFlash。 +在上述示例中,表达式 `id + a` 被提前下推到 TiFlash 进行计算。这有助于减少需要通过网络传输的数据量,从而减少网络传输开销并提高整体计算性能。这可以从 `operator` 列值包含 `plus(test.t.id, test.t.a)` 的行中 `task` 列值为 `mpp[tiflash]` 看出。 ### 示例 3:下推限制 @@ -131,9 +137,9 @@ EXPLAIN SELECT id FROM t WHERE TIME(now()+ a) < '12:00:00'; 5 rows in set, 3 warnings (0.20 sec) ``` -分析执行计划可以发现,该查询在执行时只在 TiFlash 中进行了 TableFullScan,其他的函数计算和过滤均在 `root` 进行,并未下推至 TiFlash。 +上述示例仅在 TiFlash 上执行 `TableFullScan`。其他函数在 `root` 上计算和过滤,未下推到 TiFlash。 -执行以下命令,可以查找不能下推的算子和表达式。 +你可以通过运行以下命令来识别无法下推到 TiFlash 的算子和表达式: ```sql SHOW WARNINGS; @@ -148,7 +154,7 @@ SHOW WARNINGS; 3 rows in set (0.18 sec) ``` -可以看出,该查询的表达式无法完全下推至 TiFlash,因为 `Time` 函数和 `Cast` 函数无法下推至 TiFlash。 +上述示例中的表达式无法完全下推到 TiFlash,因为函数 `Time` 和 `Cast` 无法下推到 TiFlash。 ### 示例 4:窗口函数 @@ -172,9 +178,10 @@ EXPLAIN SELECT id, ROW_NUMBER() OVER (PARTITION BY id > 10) FROM t; | └─TableFullScan_11 | 10000.00 | mpp[tiflash] | table:t | keep order:false, stats:pseudo | +----------------------------------+----------+--------------+---------------+---------------------------------------------------------------------------------------------------------------+ 9 rows in set (0.0073 sec) + ``` -可以看到,`Window` 操作在 `task` 列中有一个 `mpp[tiflash]` 的值,表示 `ROW_NUMBER() OVER (PARTITION BY id > 10)` 操作能够被下推至 TiFlash。 +在此输出中,你可以看到 `Window` 操作在 `task` 列中的值为 `mpp[tiflash]`,表明 `ROW_NUMBER() OVER (PARTITION BY id > 10)` 操作可以下推到 TiFlash。 ```sql CREATE TABLE t(id INT PRIMARY KEY, c1 VARCHAR(100)); @@ -196,4 +203,4 @@ EXPLAIN SELECT id, MAX(id) OVER (PARTITION BY id > 10) FROM t; 7 rows in set (0.0010 sec) ``` -可以看到,`Window` 操作在 `task` 列中有一个 `root` 的值,表示 `MAX(id) OVER (PARTITION BY id > 10)` 操作不能被下推至 TiFlash。这是因为,`MAX()` 只支持作为聚合函数下推,而不支持作为窗口函数下推。 +在此输出中,你可以看到 `Window` 操作在 `task` 列中的值为 `root`,表明 `MAX(id) OVER (PARTITION BY id > 10)` 操作无法下推到 TiFlash。这是因为 `MAX()` 仅在作为聚合函数时支持下推,而作为窗口函数时不支持下推。 diff --git a/tiflash/tune-tiflash-performance.md b/tiflash/tune-tiflash-performance.md index f9f4433c62c5..a79440e8d194 100644 --- a/tiflash/tune-tiflash-performance.md +++ b/tiflash/tune-tiflash-performance.md @@ -1,41 +1,41 @@ --- -title: TiFlash 性能调优 -summary: 介绍 TiFlash 性能调优的方法,包括机器资源规划和 TiDB 参数调优。 +title: 调优 TiFlash 性能 +summary: 了解如何通过规划机器资源和调整 TiDB 参数来调优 TiFlash 的性能。 --- -# TiFlash 性能调优 +# 调优 TiFlash 性能 -本文介绍了 TiFlash 性能调优的几种方式,包括机器资源规划和 TiDB 参数调优,通过这些方式,TiFlash 性能可以达到最优状态。 +本文介绍如何通过合理规划机器资源和调整 TiDB 参数来调优 TiFlash 的性能。通过遵循这些方法,你的 TiFlash 集群可以达到最佳性能。 -## 资源规划 +## 规划资源 -对于希望节省机器资源,并且完全没有隔离要求的场景,可以使用 TiKV 和 TiFlash 联合部署。建议为 TiKV 与 TiFlash 分别留够资源,同时避免共享磁盘。 +如果你想节省机器资源且对隔离没有要求,可以使用 TiKV 和 TiFlash 混合部署的方式。建议为 TiKV 和 TiFlash 分别预留足够的资源,并且不要共享磁盘。 -## TiDB 相关参数调优 +## 调整 TiDB 参数 -本部分介绍如何通过调整 TiDB 相关参数来提升 TiFlash 性能,具体包括如下几个方面: +本节介绍如何通过调整 TiDB 参数来提高 TiFlash 性能,包括: -- [强制开启 MPP 模式](#强制开启-mpp-模式) -- [聚合下推 `Join` 或 `Union`](#聚合下推-join-或-union) -- [开启 `Distinct` 优化](#开启-distinct-优化) -- [使用 `ALTER TABLE...COMPACT` 整理数据](#使用-alter-tablecompact-整理数据) -- [使用 Broadcast Hash Join 代替 Shuffled Hash Join](#使用-broadcast-hash-join-代替-shuffled-hash-join) +- [强制启用 MPP 模式](#强制启用-mpp-模式) +- [将聚合函数下推到 Join 或 Union 之前](#将聚合函数下推到-join-或-union-之前) +- [启用 Distinct 优化](#启用-distinct-优化) +- [使用 `ALTER TABLE ... COMPACT` 语句压缩数据](#使用-alter-table--compact-语句压缩数据) +- [用广播哈希连接替换分散哈希连接](#用广播哈希连接替换分散哈希连接) - [设置更大的执行并发度](#设置更大的执行并发度) -- [设置细粒度 Shuffle 参数](#设置细粒度-shuffle-参数) +- [配置 `tiflash_fine_grained_shuffle_stream_count`](#配置-tiflash_fine_grained_shuffle_stream_count) -### 强制开启 MPP 模式 +### 强制启用 MPP 模式 -MPP 执行计划可以充分利用分布式计算资源,从而显著提高批量数据查询的效率。当查询没有生成 MPP 执行计划的时候,你可以强制开启 MPP: +MPP 执行计划可以充分利用分布式计算资源,从而显著提高批量数据查询的效率。当优化器没有为查询生成 MPP 执行计划时,你可以强制启用 MPP 模式: -[`tidb_enforce_mpp`](/system-variables.md#tidb_enforce_mpp-从-v51-版本开始引入) 变量用于控制是否忽略优化器代价估算,强制使用 TiFlash 的 MPP 模式执行查询。要开启 MPP 模式查询,执行如下命令: +变量 [`tidb_enforce_mpp`](/system-variables.md#tidb_enforce_mpp-new-in-v51) 控制是否忽略优化器的成本估算,强制使用 TiFlash 的 MPP 模式执行查询。要强制启用 MPP 模式,运行以下命令: ```sql set @@tidb_enforce_mpp = ON; ``` -在以下示例中,`tidb_enforce_mpp` 开启前,TiDB 需要从 TiKV 读取数据,并在 TiDB 侧执行 `Join` 和 `Aggregation`。`tidb_enforce_mpp` 开启后,`Join` 和 `Aggregation` 被下推到了 TiFlash。需要注意的是,有时候优化器生成的执行计划并不稳定,可能生成 `MPP`,也可能不生成,这时候可以开启 `tidb_enforce_mpp`,强制优化器生成 `MPP` 计划。 +以下示例展示了启用 `tidb_enforce_mpp` 前后的查询结果。在启用此变量之前,TiDB 需要从 TiKV 读取数据并在 TiDB 中执行 `Join` 和 `Aggregation`。启用 `tidb_enforce_mpp` 后,`Join` 和 `Aggregation` 被下推到 TiFlash。此外,由于优化器不一定会生成 MPP 执行计划,通过启用 `tidb_enforce_mpp`,你可以强制优化器生成 MPP 执行计划。 -MPP 模式开启前: +启用 MPP 模式之前: ```sql mysql> explain analyze select o_orderpriority, count(*) as order_count from orders where o_orderdate >= '1995-01-01' and o_orderdate < date_add('1995-01-01', interval '3' month) and exists (select * from lineitem where l_orderkey = o_orderkey and l_commitdate < l_receiptdate) group by o_orderpriority; @@ -56,14 +56,15 @@ mysql> explain analyze select o_orderpriority, count(*) as order_count from orde 10 rows in set (22.82 sec) ``` -开启 MPP 模式: +启用 MPP 模式: ```sql mysql> set @@tidb_enforce_mpp = ON; + Query OK, 0 rows affected (0.00 sec) ``` -MPP 模式开启后: +启用 MPP 模式后: ```sql mysql> explain analyze select o_orderpriority, count(*) as order_count from orders where o_orderdate >= '1995-01-01' and o_orderdate < date_add('1995-01-01', interval '3' month) and exists (select * from lineitem where l_orderkey = o_orderkey and l_commitdate < l_receiptdate) group by o_orderpriority; @@ -92,19 +93,18 @@ mysql> explain analyze select o_orderpriority, count(*) as order_count from orde 18 rows in set (6.00 sec) ``` -### 聚合下推 `Join` 或 `Union` +### 将聚合函数下推到 Join 或 Union 之前 -将聚合操作下推到 `Join` 或 `Union` 之前执行,有可能能显著减少 `Join` 或 `Union` 需要处理的数据量,从而提升性能。 +通过将聚合操作下推到 `Join` 或 `Union` 操作之前的位置,可以减少 `Join` 或 `Union` 操作中需要处理的数据量,从而提高性能。 -[`tidb_opt_agg_push_down`](/system-variables.md#tidb_opt_agg_push_down) 变量用来设置优化器是否执行聚合函数下推到 Join 之前的优化操作。当查询中聚合操作执行很慢时,可以尝试设置该变量为 `ON`。 +变量 [`tidb_opt_agg_push_down`](/system-variables.md#tidb_opt_agg_push_down) 控制优化器是否执行将聚合函数下推到 `Join` 或 `Union` 之前的优化操作。当查询中的聚合操作执行较慢时,你可以将此变量设置为 `ON`。 ```sql set @@tidb_opt_agg_push_down = ON; ``` -在以下示例中,`tidb_opt_agg_push_down` 开启前,`HashAgg_58` 在 `HashJoin_41` 之后执行。`tidb_opt_agg_push_down` 开启后,新生成的 `HashAgg_21` 和 `HashAgg_32` 在 `HashJoin_76` 之前执行,显著减少了 `Join` 需要处理的数据量。 - -`tidb_opt_agg_push_down` 开启前: +以下示例展示了启用 `tidb_opt_agg_push_down` 变量前后的查询结果。在启用此变量之前,`HashAgg_58` 操作在 `HashJoin_41` 操作之后执行。启用此变量后,新生成的 `HashAgg_21` 和 `HashAgg_32` 操作在 `HashJoin_76` 操作之前执行。这显著减少了 `Join` 操作需要处理的数据量。 +启用 `tidb_opt_agg_push_down` 之前: ```sql mysql> explain analyze select count(*) from t1 join t2 where t1.a = t2.b group by t1.a; @@ -128,14 +128,14 @@ mysql> explain analyze select count(*) from t1 join t2 where t1.a = t2.b group b 13 rows in set (2.15 sec) ``` -开启 `tidb_opt_agg_push_down`: +启用 `tidb_opt_agg_push_down`: ```sql mysql> set @@tidb_opt_agg_push_down = ON; Query OK, 0 rows affected (0.00 sec) ``` -开启 `tidb_opt_agg_push_down` 后: +启用 `tidb_opt_agg_push_down` 后: ```sql mysql> explain analyze select count(*) from t1 join t2 where t1.a = t2.b group by t1.a; @@ -163,20 +163,18 @@ mysql> explain analyze select count(*) from t1 join t2 where t1.a = t2.b group b +------------------------------------------------------+--------------+-----------+--------------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------+--------+------+ 18 rows in set (0.46 sec) ``` +### 启用 Distinct 优化 -### 开启 `Distinct` 优化 +TiFlash 不支持某些带有 `Distinct` 列的聚合函数,例如 `Sum`。默认情况下,整个聚合函数在 TiDB 中计算。通过启用 `Distinct` 优化,某些操作可以下推到 TiFlash,从而提高查询性能。 -TiFlash 暂时还不支持部分可接受 `Distinct` 列的聚合函数,比如 `Sum` 。默认情况下,整个聚合函数运算都会在 TiDB 端执行。通过开启 `Distinct` 优化,部分操作可以下推到 TiFlash,从而提升查询性能: - -[`tidb_opt_distinct_agg_push_down`](/system-variables.md#tidb_opt_distinct_agg_push_down) 变量用来设置优化器是否执行带有 `Distinct` 的聚合函数(比如 `select sum(distinct a) from t`)下推到 Coprocessor 的优化操作。当查询中带有 `Distinct` 的聚合操作执行很慢时,可以尝试设置该变量为 `ON`。 +如果查询中带有 `distinct` 操作的聚合函数执行较慢,你可以通过将 [`tidb_opt_distinct_agg_push_down`](/system-variables.md#tidb_opt_distinct_agg_push_down) 变量设置为 `ON` 来启用将带有 `Distinct` 的聚合函数(如 `select sum(distinct a) from t`)下推到 Coprocessor 的优化操作。 ```sql set @@tidb_opt_distinct_agg_push_down = ON; ``` -在以下示例中,`tidb_opt_distinct_agg_push_down` 开启前,TiDB 需要从 TiFlash 读取所有数据,并在 TiDB 侧执行 `distinct`。`tidb_opt_distinct_agg_push_down` 开启后,`distinct a` 被下推到了 TiFlash,在 `HashAgg_6` 里新增里一个 `group by` 列 `test.t.a`。这边查询结果里面的两个 warnings 是警告聚合函数不能完全下推。 - -`tidb_opt_distinct_agg_push_down` 开启前: +以下示例展示了启用 `tidb_opt_distinct_agg_push_down` 变量前后的查询结果。在启用此变量之前,TiDB 需要从 TiFlash 读取所有数据并在 TiDB 中执行 `distinct`。启用此变量后,`distinct a` 被下推到 TiFlash,并在 `HashAgg_6` 中添加了一个新的 `group by` 列 `test.t.a`。查询结果中的两个警告表明聚合函数无法完全下推到 TiFlash。 +启用 `tidb_opt_distinct_agg_push_down` 之前: ```sql mysql> explain analyze select count(distinct a) from test.t; @@ -191,14 +189,14 @@ mysql> explain analyze select count(distinct a) from test.t; 4 rows in set, 2 warnings (2 min 23.21 sec) ``` -开启 `tidb_opt_distinct_agg_push_down`: +启用 `tidb_opt_distinct_agg_push_down`: ```sql mysql> set @@tidb_opt_distinct_agg_push_down = ON; Query OK, 0 rows affected (0.00 sec) ``` -`tidb_opt_distinct_agg_push_down` 开启后: +启用 `tidb_opt_distinct_agg_push_down` 后: ```sql mysql> explain analyze select count(distinct a) from test.t; @@ -214,9 +212,9 @@ mysql> explain analyze select count(distinct a) from test.t; 5 rows in set, 2 warnings (0.24 sec) ``` -### 使用 `ALTER TABLE...COMPACT` 整理数据 +### 使用 `ALTER TABLE ... COMPACT` 语句压缩数据 -[`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) 可以触发 TiFlash 节点对某个表或者某个分区进行数据整理。数据整理时,表中的物理数据会被重写,如清理已删除的数据、合并多版本数据等,从而可以获得更高的访问性能,并减少磁盘空间占用。 +执行 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) 语句可以在 TiFlash 节点上为特定表或分区启动压缩。在压缩过程中,节点上的物理数据会被重写,包括清理已删除的行和合并由更新引起的多个数据版本。这有助于提高访问性能并减少磁盘使用。以下是示例: ```sql ALTER TABLE employees COMPACT TIFLASH REPLICA; @@ -226,25 +224,24 @@ ALTER TABLE employees COMPACT TIFLASH REPLICA; ALTER TABLE employees COMPACT PARTITION pNorth, pEast TIFLASH REPLICA; ``` -### 使用 Broadcast Hash Join 代替 Shuffled Hash Join +### 用广播哈希连接替换分散哈希连接 -对于有小表的 `Join` 算子,Broadcast Hash Join 可以避免大表的网络传输,从而提升计算性能。 +对于小表的 `Join` 操作,广播哈希连接算法可以避免传输大表,从而提高计算性能。 -- [`tidb_broadcast_join_threshold_size`](/system-variables.md#tidb_broadcast_join_threshold_count-从-v50-版本开始引入),单位为 bytes。如果表大小(字节数)小于该值,则选择 Broadcast Hash Join 算法。否则选择 Shuffled Hash Join 算法。 +- [`tidb_broadcast_join_threshold_size`](/system-variables.md#tidb_broadcast_join_threshold_size-new-in-v50) 变量控制是否使用广播哈希连接算法。如果表大小(单位:字节)小于此变量的值,则使用广播哈希连接算法。否则,使用分散哈希连接算法。 ```sql set @@tidb_broadcast_join_threshold_size = 2000000; ``` -- [`tidb_broadcast_join_threshold_count`](/system-variables.md#tidb_broadcast_join_threshold_count-从-v50-版本开始引入),单位为行数。如果 join 的对象为子查询,优化器无法估计子查询结果集大小,在这种情况下通过结果集行数判断。如果子查询的行数估计值小于该变量,则选择 Broadcast Hash Join 算法。否则选择 Shuffled Hash Join 算法。 +- [`tidb_broadcast_join_threshold_count`](/system-variables.md#tidb_broadcast_join_threshold_count-new-in-v50) 变量也控制是否使用广播哈希连接算法。如果连接操作的对象属于子查询,优化器无法估计子查询结果集的大小。在这种情况下,大小由结果集中的行数决定。如果子查询的估计行数少于此变量的值,则使用广播哈希连接算法。否则,使用分散哈希连接算法。 ```sql set @@tidb_broadcast_join_threshold_count = 100000; ``` +以下示例展示了重新配置 `tidb_broadcast_join_threshold_size` 前后的查询结果。在重新配置之前,`ExchangeSender_29` 的 `ExchangeType` 是 `HashPartition`。将此变量的值更改为 `10000000` 后,`ExchangeSender_29` 的 `ExchangeType` 变为 `Broadcast`。 -在以下示例中,`tidb_broadcast_join_threshold_size` 设置前,`ExchangeSender_29` 的 `ExchangeType` 是 `HashPartition`。`tidb_broadcast_join_threshold_size` 设置后,`ExchangeSender_29` 的 `ExchangeType` 改变为 `Broadcast`。 - -`tidb_broadcast_join_threshold_size` 设置前: +重新配置 `tidb_broadcast_join_threshold_size` 之前: ```sql mysql> explain analyze select max(l_shipdate), max(l_commitdate), max(l_receiptdate) from supplier,lineitem where s_suppkey = l_suppkey; @@ -266,14 +263,14 @@ mysql> explain analyze select max(l_shipdate), max(l_commitdate), max(l_receiptd 11 rows in set (3.83 sec) ``` -设置 `tidb_broadcast_join_threshold_size`: +将 `tidb_broadcast_join_threshold_size` 设置为 `10000000`: ```sql mysql> set @@tidb_broadcast_join_threshold_size = 10000000; Query OK, 0 rows affected (0.00 sec) ``` -`tidb_broadcast_join_threshold_size` 设置后: +将 `tidb_broadcast_join_threshold_size` 设置为 `10000000` 后: ```sql mysql> explain analyze select max(l_shipdate), max(l_commitdate), max(l_receiptdate) from supplier,lineitem where s_suppkey = l_suppkey; @@ -292,20 +289,19 @@ mysql> explain analyze select max(l_shipdate), max(l_commitdate), max(l_receiptd +------------------------------------------+--------------+-----------+--------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+------+ 9 rows in set (2.76 sec) ``` - ### 设置更大的执行并发度 -设置更大的执行并发度,可以让 TiFlash 占用更多系统 CPU 资源,从而提升查询性能。 +更大的执行并发度允许 TiFlash 占用系统更多的 CPU 资源,从而提高查询性能。 -[`tidb_max_tiflash_threads`](/system-variables.md#tidb_max_tiflash_threads-从-v610-版本开始引入),单位为线程。用来设置 TiFlash 中 request 执行的最大并发度。 +[`tidb_max_tiflash_threads`](/system-variables.md#tidb_max_tiflash_threads-new-in-v610) 变量用于设置 TiFlash 执行请求的最大并发度。单位是线程。 ```sql set @@tidb_max_tiflash_threads = 20; ``` -在以下示例中,设置 `tidb_max_tiflash_threads` 前,单个 TiFlash 实例的 request 执行的并发度为 8 个线程。该集群一共有 3 个 TiFlash 实例,因此所有 TiFlash 实例上的 request 执行的线程总数是 24。当将 `tidb_max_tiflash_threads` 设置为 `20` 后,所有 TiFlash 实例上的 request 执行的线程总数是 60。 +以下示例展示了重新配置 `tidb_max_tiflash_threads` 前后的查询结果。在设置 `tidb_max_tiflash_threads` 之前,单个 TiFlash 实例的请求执行并发度为 8 个线程。由于集群总共有 3 个 TiFlash 实例,所有 TiFlash 实例上请求执行的总线程数为 24(8 × 3)。将 `tidb_max_tiflash_threads` 设置为 `20` 后,所有 TiFlash 实例上请求执行的总线程数为 60(20 × 3)。 -`tidb_max_tiflash_threads` 设置前: +重新配置 `tidb_max_tiflash_threads` 之前: ```sql mysql> explain analyze select a, count(*) from t group by a; @@ -325,14 +321,14 @@ mysql> explain analyze select a, count(*) from t group by a; 9 rows in set (0.67 sec) ``` -设置 `tidb_max_tiflash_threads`: +将 `tidb_max_tiflash_threads` 设置为 `20`: ```sql mysql> set @@tidb_max_tiflash_threads = 20; Query OK, 0 rows affected (0.00 sec) ``` -`tidb_max_tiflash_threads` 设置后: +将 `tidb_max_tiflash_threads` 设置为 `20` 后: ```sql mysql> explain analyze select a, count(*) from t group by a; @@ -352,19 +348,18 @@ mysql> explain analyze select a, count(*) from t group by a; 9 rows in set (0.37 sec) ``` -### 设置细粒度 Shuffle 参数 +### 配置 `tiflash_fine_grained_shuffle_stream_count` -细粒度 Shuffle 可以通过参数增加窗口函数执行的并发度,让函数执行占用更多系统资源,从而提升查询性能。 +你可以通过配置细粒度 Shuffle 特性的 [`tiflash_fine_grained_shuffle_stream_count`](/system-variables.md#tiflash_fine_grained_shuffle_stream_count-new-in-v620) 来增加窗口函数执行的并发度。这样,窗口函数的执行可以占用更多的系统资源,从而提高查询性能。 -[`tiflash_fine_grained_shuffle_stream_count`](/system-variables.md#tiflash_fine_grained_shuffle_stream_count-从-v620-版本开始引入),单位为线程数。当窗口函数下推到 TiFlash 执行时,可以通过该变量控制窗口函数执行的并行度。 +当窗口函数被下推到 TiFlash 执行时,你可以使用此变量来控制窗口函数执行的并发度级别。单位是线程。 ```sql set @@tiflash_fine_grained_shuffle_stream_count = 20; ``` -在以下示例中,`tiflash_fine_grained_shuffle_stream_count` 设置前,`[ExchangeSender_11, ExchangeReceiver_12, Sort_13, Window_22]` 的 `stream_count` 是 8。`tiflash_fine_grained_shuffle_stream_count` 设置后,`[ExchangeSender_11, ExchangeReceiver_12, Sort_13, Window_22]` 的 `stream_count` 是 20。 - -`tiflash_fine_grained_shuffle_stream_count` 设置前: +以下示例展示了重新配置 `tiflash_fine_grained_shuffle_stream_count` 变量前后的查询结果。在重新配置之前,`[ExchangeSender_11, ExchangeReceiver_12, Sort_13, Window_22]` 的 `stream_count` 是 8。重新配置后,`stream_count` 变为 20。 +重新配置 `tiflash_fine_grained_shuffle_stream_count` 之前: ```sql mysql> explain analyze select *, row_number() over (partition by a) from t; @@ -382,14 +377,14 @@ mysql> explain analyze select *, row_number() over (partition by a) from t; 7 rows in set (4 min 30.59 sec) ``` -设置 `tiflash_fine_grained_shuffle_stream_count`: +将 `tiflash_fine_grained_shuffle_stream_count` 设置为 `20`: ```sql mysql> set @@tiflash_fine_grained_shuffle_stream_count = 20; Query OK, 0 rows affected (0.00 sec) ``` -`tiflash_fine_grained_shuffle_stream_count` 设置后: +将 `tiflash_fine_grained_shuffle_stream_count` 设置为 `20` 后: ```sql mysql> explain analyze select *, row_number() over (partition by a) from t; diff --git a/tiflash/use-fastscan.md b/tiflash/use-fastscan.md index 0f10dfda2aba..bae31b4f7305 100644 --- a/tiflash/use-fastscan.md +++ b/tiflash/use-fastscan.md @@ -1,19 +1,21 @@ --- -title: 使用 FastScan 功能 -summary: 介绍通过使用 FastScan 来加速 OLAP 场景的查询的方法。 +title: 使用 FastScan +summary: 介绍如何使用 FastScan 在 OLAP 场景下加速查询。 --- -# 使用 FastScan 功能 +# 使用 FastScan -本文档介绍通过使用 FastScan 来加速 Online Analytical Processing (OLAP) 场景中查询的方法。 +本文档介绍如何使用 FastScan 在在线分析处理(OLAP)场景中加速查询。 -默认情况下,TiFlash 能够保证查询结果精度以及数据一致性。如果使用 FastScan,TiFlash 可以实现更高效的查询性能,但不保证查询结果精度和数据一致性。 +默认情况下,TiFlash 保证查询结果的精确性和数据一致性。通过 FastScan 功能,TiFlash 可以提供更高效的查询性能,但不保证查询结果的准确性和数据一致性。 -某些 OLAP 对查询结果精度可以容忍一定误差。如果对查询性能有更高要求,可以在 session 级别或 global 级别开启 FastScan 功能,你可以通过修改变量 `tiflash_fastscan` 的值来选择是否启用 FastScan 功能。 +某些 OLAP 场景允许查询结果有一定的容错性。在这些情况下,如果你需要更高的查询性能,可以在会话级别或全局级别启用 FastScan 功能。你可以通过配置变量 `tiflash_fastscan` 来选择是否启用 FastScan 功能。 -## 使用限制 +## 限制 -当开启 FastScan 功能时,查询结果可能会包含表中的旧数据,即相同主键的多个历史版本的数据或者已经删除的数据。如下所示: +当启用 FastScan 功能时,你的查询结果可能包含表的旧数据。这意味着你可能会获得具有相同主键的多个历史版本数据或已被删除的数据。 + +例如: ```sql CREATE TABLE t1 (a INT PRIMARY KEY, b INT); @@ -42,17 +44,15 @@ SELECT * FROM t1; +------+------+ ``` -对于这些旧数据,TiFlash 在后台会自动发起数据整理(Compaction)。当这些旧数据已经被后台整理且它们的数据版本小于 GC safe point 之后,才会被物理清理。此后在 FastScan 模式下将不再返回这些数据。旧数据被整理的时机受多种因素的自动触发,你也可以通过 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) 手动触发数据整理。 +虽然 TiFlash 可以在后台自动触发旧数据的压缩,但在数据被压缩且其数据版本早于 GC 安全点之前,旧数据不会被物理清理。在物理清理之后,被清理的旧数据将不再在 FastScan 模式下返回。数据压缩的时机由各种因素自动触发。你也可以使用 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) 语句手动触发数据压缩。 ## 启用和禁用 FastScan -默认情况下,session 和 global 级别的变量 `tiflash_fastscan=OFF`,即没有开启 FastScan 功能。你可以通过以下语句来查看对应的变量信息。 +默认情况下,变量 `tiflash_fastscan=OFF` 在会话级别和全局级别都是关闭的,即 FastScan 功能未启用。你可以使用以下语句查看变量信息。 ``` show variables like 'tiflash_fastscan'; -``` -``` +------------------+-------+ | Variable_name | Value | +------------------+-------+ @@ -62,9 +62,7 @@ show variables like 'tiflash_fastscan'; ``` show global variables like 'tiflash_fastscan'; -``` -``` +------------------+-------+ | Variable_name | Value | +------------------+-------+ @@ -72,34 +70,34 @@ show global variables like 'tiflash_fastscan'; +------------------+-------+ ``` -变量 `tiflash_fastscan` 支持 session 级别和 global 级别的修改。如果需要在当前 session 中启用 FastScan 功能,可以通过以下语句设置: +你可以在会话级别和全局级别配置变量 `tiflash_fastscan`。如果你需要在当前会话中启用 FastScan,可以使用以下语句: ``` set session tiflash_fastscan=ON; ``` -如果对 global 级别的 `tiflash_fastscan` 进行设置,设置后新建的会话中默认 session 和 global 变量 `tiflash_fastscan` 启用新值。设置方式如下: +你也可以在全局级别设置 `tiflash_fastscan`。新设置将在新会话中生效,但不会在当前和之前的会话中生效。此外,在新会话中,会话级别和全局级别的 `tiflash_fastscan` 都将采用新值。 ``` set global tiflash_fastscan=ON; ``` -可以用下面语句禁用 FastScan: +你可以使用以下语句禁用 FastScan。 -```sql +``` set session tiflash_fastscan=OFF; set global tiflash_fastscan=OFF; ``` -## 实现机制 +## FastScan 的工作机制 -TiFlash 存储层的数据主要存放在 Delta 层和 Stable 层。 +TiFlash 存储层的数据存储在两个层次:Delta 层和 Stable 层。 -在默认状态下(即未开启 FastScan 功能),TableScan 算子过程整体包括了以下步骤: +默认情况下,FastScan 未启用,TableScan 算子按以下步骤处理数据: -1. Read data:在 Delta 层和 Stable 层分别建立数据流,进行各自数据的读取。 -2. Sort Merge:将步骤 1 中建立的数据流进行合并,并且将数据按照 (主键列,时间戳列) 顺序排列返回。 -3. Range Filter:根据读取范围限制,对步骤 2 中的数据进行过滤筛选并返回。 -4. MVCC + Column Filter:对步骤 3 中的数据进行 MVCC 过滤(即依照查询需要的数据版本,根据主键列以及时间戳列筛选出正确的数据版本),同时进行 Column 过滤(即过滤掉查询请求中不需要的列)并返回。 +1. 读取数据:在 Delta 层和 Stable 层分别创建数据流来读取各自的数据。 +2. 排序合并:合并步骤 1 中创建的数据流。然后按照(主键列,时间戳列)的顺序排序后返回数据。 +3. 范围过滤:根据数据范围,过滤步骤 2 生成的数据,然后返回数据。 +4. MVCC + 列过滤:通过 MVCC(即根据主键列和时间戳列过滤数据版本)和列过滤(即过滤掉不需要的列)对步骤 3 生成的数据进行过滤,然后返回数据。 -FastScan 通过损失一定的数据一致性来获取更快的查询性能。FastScan 中的 TableScan 流程省略了上述过程中的第 2 步和第 4 步中 MVCC 的部分,从而提高查询性能。 \ No newline at end of file +FastScan 通过牺牲一些数据一致性来获得更快的查询速度。在 FastScan 中,正常扫描过程中的步骤 2 和步骤 4 中的 MVCC 部分被省略,从而提高查询性能。 diff --git a/tiflash/use-tidb-to-read-tiflash.md b/tiflash/use-tidb-to-read-tiflash.md index 65ab251169a9..0d5b0404f963 100644 --- a/tiflash/use-tidb-to-read-tiflash.md +++ b/tiflash/use-tidb-to-read-tiflash.md @@ -1,17 +1,17 @@ --- -title: 使用 TiDB 读取 TiFlash +title: 使用 TiDB 读取 TiFlash 副本 summary: 了解如何使用 TiDB 读取 TiFlash 副本。 --- -# 使用 TiDB 读取 TiFlash +# 使用 TiDB 读取 TiFlash 副本 -本文档介绍如何使用 TiDB 读取 TiFlash 副本。 +本文介绍如何使用 TiDB 读取 TiFlash 副本。 -TiDB 提供三种读取 TiFlash 副本的方式。如果添加了 TiFlash 副本,而没有做任何 engine 的配置,则默认使用 CBO 方式。 +TiDB 提供三种方式来读取 TiFlash 副本。如果你添加了 TiFlash 副本但没有任何引擎配置,默认使用 CBO(基于成本的优化)模式。 ## 智能选择 -对于创建了 TiFlash 副本的表,TiDB 优化器会自动根据代价估算选择是否使用 TiFlash 副本。具体有没有选择 TiFlash 副本,可以通过 `desc` 或 `explain analyze` 语句查看,例如: +对于有 TiFlash 副本的表,TiDB 优化器会根据成本估算自动决定是否使用 TiFlash 副本。你可以使用 `desc` 或 `explain analyze` 语句来检查是否选择了 TiFlash 副本。例如: {{< copyable "sql" >}} @@ -46,52 +46,74 @@ explain analyze select count(*) from test.t; +--------------------------+---------+---------+--------------+---------------+----------------------------------------------------------------------+--------------------------------+-----------+------+ ``` -`cop[tiflash]` 表示该任务会发送至 TiFlash 进行处理。如果没有选择 TiFlash 副本,可尝试通过 `analyze table` 语句更新统计信息后,再查看 `explain analyze` 结果。 +`cop[tiflash]` 表示该任务将被发送到 TiFlash 进行处理。如果你没有选择 TiFlash 副本,可以尝试使用 `analyze table` 语句更新统计信息,然后使用 `explain analyze` 语句检查结果。 -需要注意的是,如果表仅有单个 TiFlash 副本且相关节点无法服务,智能选择模式下的查询会不断重试,需要指定 Engine 或者手工 Hint 来读取 TiKV 副本。 +注意,如果一个表只有一个 TiFlash 副本且相关节点无法提供服务,CBO 模式下的查询将重复重试。在这种情况下,你需要指定引擎或使用手动提示来从 TiKV 副本读取数据。 -## Engine 隔离 +## 引擎隔离 -Engine 隔离是通过配置变量来指定所有的查询均使用指定 engine 的副本,可选 engine 为 "tikv"、"tidb" 和 "tiflash"(其中 "tidb" 表示 TiDB 内部的内存表区,主要用于存储一些 TiDB 系统表,用户不能主动使用),分别有 2 个配置级别: +引擎隔离是通过配置相应变量来指定所有查询使用指定引擎的副本。可选的引擎包括 "tikv"、"tidb"(表示 TiDB 的内部内存表区域,用于存储一些 TiDB 系统表,用户不能主动使用)和 "tiflash"。 -1. TiDB 实例级别,即 INSTANCE 级别。在 TiDB 的配置文件添加如下配置项: + + +你可以在以下两个配置级别指定引擎: + +* TiDB 实例级别,即 INSTANCE 级别。在 TiDB 配置文件中添加以下配置项: ``` [isolation-read] engines = ["tikv", "tidb", "tiflash"] ``` - **实例级别的默认配置为 `["tikv", "tidb", "tiflash"]`。** + **INSTANCE 级别的默认配置是 `["tikv", "tidb", "tiflash"]`。** -2. 会话级别,即 SESSION 级别。设置语句: +* SESSION 级别。使用以下语句进行配置: {{< copyable "sql" >}} ```sql - set @@session.tidb_isolation_read_engines = "逗号分隔的 engine list"; + set @@session.tidb_isolation_read_engines = "以逗号分隔的引擎列表"; ``` - 或者 + 或 {{< copyable "sql" >}} ```sql - set SESSION tidb_isolation_read_engines = "逗号分隔的 engine list"; + set SESSION tidb_isolation_read_engines = "以逗号分隔的引擎列表"; ``` - **会话级别的默认配置继承自 TiDB 实例级别的配置。** + SESSION 级别的默认配置继承自 TiDB INSTANCE 级别的配置。 -最终的 engine 配置为会话级别配置,即会话级别配置会覆盖实例级别配置。比如实例级别配置了 "tikv",而会话级别配置了 "tiflash",则会读取 TiFlash 副本。当 engine 配置为 "tikv, tiflash",即可以同时读取 TiKV 和 TiFlash 副本,优化器会自动选择。 +最终的引擎配置是会话级别的配置,即会话级别的配置会覆盖实例级别的配置。例如,如果你在 INSTANCE 级别配置了 "tikv",在 SESSION 级别配置了 "tiflash",那么将读取 TiFlash 副本。如果最终的引擎配置是 "tikv" 和 "tiflash",那么会同时读取 TiKV 和 TiFlash 副本,优化器会自动选择更好的引擎来执行。 > **注意:** > -> 由于 [TiDB Dashboard](/dashboard/dashboard-intro.md) 等组件需要读取一些存储于 TiDB 内存表区的系统表,因此建议实例级别 engine 配置中始终加入 "tidb" engine。 +> 因为 [TiDB Dashboard](/dashboard/dashboard-intro.md) 和其他组件需要读取存储在 TiDB 内存表区域的一些系统表,建议始终在实例级别的引擎配置中添加 "tidb" 引擎。 + + + + + +你可以使用以下语句指定引擎: + +```sql +set @@session.tidb_isolation_read_engines = "以逗号分隔的引擎列表"; +``` + +或 + +```sql +set SESSION tidb_isolation_read_engines = "以逗号分隔的引擎列表"; +``` + + -如果查询中的表没有对应 engine 的副本,比如配置了 engine 为 "tiflash" 而该表没有 TiFlash 副本,则查询会报该表不存在该 engine 副本的错。 +如果查询的表没有指定引擎的副本(例如,引擎配置为 "tiflash" 但表没有 TiFlash 副本),查询将返回错误。 -## 手工 Hint +## 手动提示 -手工 Hint 可以在满足 engine 隔离的前提下,强制 TiDB 对于某张或某几张表使用指定的副本,使用方法为: +手动提示可以在满足引擎隔离的前提下强制 TiDB 对特定表使用指定的副本。以下是使用手动提示的示例: {{< copyable "sql" >}} @@ -99,7 +121,7 @@ Engine 隔离是通过配置变量来指定所有的查询均使用指定 engine select /*+ read_from_storage(tiflash[table_name]) */ ... from table_name; ``` -如果在查询语句中对表设置了别名,在 Hint 语句中必须使用别名才能使 Hint 生效。比如: +如果你在查询语句中为表设置了别名,你必须在包含提示的语句中使用别名才能使提示生效。例如: {{< copyable "sql" >}} @@ -107,21 +129,21 @@ select /*+ read_from_storage(tiflash[table_name]) */ ... from table_name; select /*+ read_from_storage(tiflash[alias_a,alias_b]) */ ... from table_name_1 as alias_a, table_name_2 as alias_b where alias_a.column_1 = alias_b.column_2; ``` -其中 `tiflash[]` 是提示优化器读取 TiFlash 副本,亦可以根据需要使用 `tikv[]` 来提示优化器读取 TiKV 副本。更多关于该 Hint 语句的语法可以参考 [READ_FROM_STORAGE](/optimizer-hints.md#read_from_storagetiflasht1_name--tl_name--tikvt2_name--tl_name-)。 +在上述语句中,`tiflash[]` 提示优化器读取 TiFlash 副本。你也可以根据需要使用 `tikv[]` 提示优化器读取 TiKV 副本。有关提示语法的详细信息,请参考 [READ_FROM_STORAGE](/optimizer-hints.md#read_from_storagetiflasht1_name--tl_name--tikvt2_name--tl_name-)。 -如果 Hint 指定的表在指定的引擎上不存在副本,则 Hint 会被忽略,并产生 warning。另外 Hint 必须在满足 engine 隔离的前提下才会生效,如果 Hint 中指定的引擎不在 engine 隔离列表中,Hint 同样会被忽略,并产生 warning。 +如果提示指定的表没有指定引擎的副本,提示将被忽略并报告警告。此外,提示只在引擎隔离的前提下生效。如果提示中指定的引擎不在引擎隔离列表中,提示也会被忽略并报告警告。 > **注意:** > -> MySQL 命令行客户端在 5.7.7 版本之前默认清除了 Optimizer Hints。如果需要在这些早期版本的客户端中使用 `Hint` 语法,需要在启动客户端时加上 `--comments` 选项,例如 `mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 +> 5.7.7 或更早版本的 MySQL 客户端默认会清除优化器提示。要在这些早期版本中使用提示语法,请使用 `--comments` 选项启动客户端,例如,`mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 -## 三种方式之间关系的总结 +## 智能选择、引擎隔离和手动提示的关系 -上述三种读取 TiFlash 副本的方式中,Engine 隔离规定了总的可使用副本 engine 的范围,手工 Hint 可以在该范围内进一步实现语句级别及表级别的细粒度的 engine 指定,最终由 CBO 在指定的 engine 范围内根据代价估算最终选取某个 engine 上的副本。 +在上述三种读取 TiFlash 副本的方式中,引擎隔离指定了可用引擎副本的整体范围;在此范围内,手动提示提供了更细粒度的语句级和表级引擎选择;最后,CBO 在指定的引擎列表内基于成本估算做出决策并选择一个引擎的副本。 > **注意:** > -> - TiDB 4.0.3 版本之前,在非只读 SQL 语句中(比如 `INSERT INTO ... SELECT`、`SELECT ... FOR UPDATE`、`UPDATE ...`、`DELETE ...`)读取 TiFlash,行为是未定义的。 -> - TiDB 4.0.3 到 6.2.0 之间的版本,TiDB 内部会对非只读 SQL 语句忽略 TiFlash 副本以保证数据写入、更新、删除的正确性。对应的,如果使用了[智能选择](#智能选择)的方式,TiDB 会自动选择非 TiFlash 副本;如果使用了 [Engine 隔离](#engine-隔离)的方式指定**仅**读取 TiFlash 副本,则查询会报错;而如果使用了[手工 Hint](#手工-hint) 的方式,则 Hint 会被忽略。 -> - TiDB 6.3.0 到 7.0.0 之间的版本,如果 TiFlash 副本被允许使用,你可以通过变量 [`tidb_enable_tiflash_read_for_write_stmt`](/system-variables.md#tidb_enable_tiflash_read_for_write_stmt-从-v630-版本开始引入) 控制是否允许 TiDB 在处理非只读 SQL 语句时使用 TiFlash 副本。 -> - 从 TiDB 7.1.0 起,如果 TiFlash 副本被允许使用且当前会话的 [SQL 模式](/sql-mode.md)为非严格模式(即 `sql_mode` 值不包含 `STRICT_TRANS_TABLES` 和 `STRICT_ALL_TABLES`),TiDB 在处理非只读 SQL 语句时会根据代价估算自动选择是否使用 TiFlash 副本。 +> - 在 v4.0.3 之前,在非只读 SQL 语句中读取 TiFlash 副本的行为是未定义的(例如,`INSERT INTO ... SELECT`、`SELECT ... FOR UPDATE`、`UPDATE ...`、`DELETE ...`)。 +> - 从 v4.0.3 到 v6.2.0 版本,为了保证数据正确性,TiDB 在内部忽略非只读 SQL 语句的 TiFlash 副本。也就是说,对于[智能选择](#智能选择),TiDB 自动选择非 TiFlash 副本;对于仅指定 TiFlash 副本的[引擎隔离](#引擎隔离),TiDB 报错;对于[手动提示](#手动提示),TiDB 忽略提示。 +> - 从 v6.3.0 到 v7.0.0 版本,如果启用了 TiFlash 副本,你可以使用 [`tidb_enable_tiflash_read_for_write_stmt`](/system-variables.md#tidb_enable_tiflash_read_for_write_stmt-new-in-v630) 变量来控制 TiDB 是否在非只读 SQL 语句中使用 TiFlash 副本。 +> - 从 v7.1.0 开始,如果启用了 TiFlash 副本且当前会话的 [SQL 模式](/sql-mode.md)不是严格模式(即 `sql_mode` 值不包含 `STRICT_TRANS_TABLES` 或 `STRICT_ALL_TABLES`),TiDB 会根据成本估算自动决定是否在非只读 SQL 语句中使用 TiFlash 副本。 diff --git a/tiflash/use-tiflash-mpp-mode.md b/tiflash/use-tiflash-mpp-mode.md index 8e8f44761f0a..e41cc59de6bd 100644 --- a/tiflash/use-tiflash-mpp-mode.md +++ b/tiflash/use-tiflash-mpp-mode.md @@ -1,30 +1,40 @@ --- -title: 使用 MPP 模式 -summary: 了解如何使用 MPP 模式。 +title: 使用 TiFlash MPP 模式 +summary: 了解 TiFlash 的 MPP 模式及其使用方法。 --- -# 使用 MPP 模式 +# 使用 TiFlash MPP 模式 -本文档介绍 TiFlash 的 [Massively Parallel Processing (MPP)](/glossary.md#mpp) 模式及其使用方法。 + -TiFlash 支持 MPP 模式的查询执行,即在计算中引入跨节点的数据交换(data shuffle 过程)。TiDB 默认由优化器自动选择是否使用 MPP 模式,你可以通过修改变量 [`tidb_allow_mpp`](/system-variables.md#tidb_allow_mpp-从-v50-版本开始引入) 和 [`tidb_enforce_mpp`](/system-variables.md#tidb_enforce_mpp-从-v51-版本开始引入) 的值来更改选择策略。 +本文档介绍 TiFlash 的[大规模并行处理 (MPP)](/glossary.md#mpp) 模式及其使用方法。 -MPP 模式的工作原理见下图。 + + + + +本文档介绍 TiFlash 的[大规模并行处理 (MPP)](/tidb-cloud/tidb-cloud-glossary.md#mpp) 模式及其使用方法。 + + + +TiFlash 支持使用 MPP 模式执行查询,该模式在计算过程中引入了跨节点数据交换(数据 shuffle 过程)。TiDB 会根据优化器的成本估算自动决定是否选择 MPP 模式。你可以通过修改 [`tidb_allow_mpp`](/system-variables.md#tidb_allow_mpp-new-in-v50) 和 [`tidb_enforce_mpp`](/system-variables.md#tidb_enforce_mpp-new-in-v51) 的值来改变选择策略。 + +下图展示了 MPP 模式的工作原理。 ![mpp-mode](/media/tiflash/tiflash-mpp.png) ## 控制是否选择 MPP 模式 -变量 `tidb_allow_mpp` 控制 TiDB 能否选择 MPP 模式执行查询。变量 `tidb_enforce_mpp` 控制是否忽略优化器代价估算,强制使用 TiFlash 的 MPP 模式执行查询。 +`tidb_allow_mpp` 变量控制 TiDB 是否可以选择 MPP 模式来执行查询。`tidb_enforce_mpp` 变量控制是否忽略优化器的成本估算并强制使用 TiFlash 的 MPP 模式来执行查询。 -这两个变量所有取值对应的结果如下: +这两个变量的所有取值对应的结果如下: | | tidb_allow_mpp=off | tidb_allow_mpp=on(默认) | | ---------------------- | -------------------- | -------------------------------- | -| tidb_enforce_mpp=off(默认) | 不使用 MPP 模式。 | 优化器根据代价估算选择。(默认) | -| tidb_enforce_mpp=on | 不使用 MPP 模式。 | TiDB 无视代价估算,选择 MPP 模式。 | +| tidb_enforce_mpp=off(默认) | 不使用 MPP 模式 | 优化器根据成本估算选择是否使用 MPP 模式(默认)| +| tidb_enforce_mpp=on | 不使用 MPP 模式 | TiDB 忽略成本估算,选择使用 MPP 模式 | -例如,如果你不想使用 MPP 模式,可以通过以下语句来设置: +例如,如果你不想使用 MPP 模式,可以执行以下语句: {{< copyable "sql" >}} @@ -32,7 +42,7 @@ MPP 模式的工作原理见下图。 set @@session.tidb_allow_mpp=0; ``` -如果想要通过优化器代价估算来智能选择是否使用 MPP(默认情况),可以通过如下语句来设置: +如果你希望 TiDB 的基于成本的优化器自动决定是否使用 MPP 模式(默认),可以执行以下语句: {{< copyable "sql" >}} @@ -41,7 +51,7 @@ set @@session.tidb_allow_mpp=1; set @@session.tidb_enforce_mpp=0; ``` -如果想要 TiDB 忽略优化器的代价估算,强制使用 MPP,可以通过如下语句来设置: +如果你希望 TiDB 忽略优化器的成本估算并强制选择 MPP 模式,可以执行以下语句: {{< copyable "sql" >}} @@ -50,13 +60,17 @@ set @@session.tidb_allow_mpp=1; set @@session.tidb_enforce_mpp=1; ``` -Session 变量 `tidb_enforce_mpp` 的初始值等于这台 tidb-server 实例的 [`enforce-mpp`](/tidb-configuration-file.md#enforce-mpp) 配置项值(默认为 `false`)。在一个 TiDB 集群中,如果有若干台 tidb-server 实例只执行分析型查询,要确保它们能够选中 MPP 模式,你可以将它们的 [`enforce-mpp`](/tidb-configuration-file.md#enforce-mpp) 配置值修改为 `true`. + + +`tidb_enforce_mpp` 会话变量的初始值等于该 tidb-server 实例的 [`enforce-mpp`](/tidb-configuration-file.md#enforce-mpp) 配置值(默认为 `false`)。如果 TiDB 集群中的多个 tidb-server 实例仅执行分析查询,并且你希望确保在这些实例上使用 MPP 模式,可以将它们的 [`enforce-mpp`](/tidb-configuration-file.md#enforce-mpp) 配置值更改为 `true`。 + + > **注意:** > -> `tidb_enforce_mpp=1` 在生效时,TiDB 优化器会忽略代价估算选择 MPP 模式。但如果存在其它不支持 MPP 的因素,例如没有 TiFlash 副本、TiFlash 副本同步未完成、语句中含有 MPP 模式不支持的算子或函数等,那么 TiDB 仍然不会选择 MPP 模式。 +> 当 `tidb_enforce_mpp=1` 生效时,TiDB 优化器将忽略成本估算来选择 MPP 模式。但是,如果其他因素阻止了 MPP 模式,TiDB 将不会选择 MPP 模式。这些因素包括缺少 TiFlash 副本、TiFlash 副本复制未完成,以及语句包含 MPP 模式不支持的运算符或函数。 > -> 如果由于代价估算之外的原因导致 TiDB 优化器无法选择 MPP,在你使用 `EXPLAIN` 语句查看执行计划时,会返回警告说明原因,例如: +> 如果 TiDB 优化器由于成本估算以外的原因无法选择 MPP 模式,当你使用 `EXPLAIN` 语句查看执行计划时,会返回一个警告来解释原因。例如: > > ```sql > set @@session.tidb_enforce_mpp=1; @@ -73,14 +87,14 @@ Session 变量 `tidb_enforce_mpp` 的初始值等于这台 tidb-server 实例的 > +---------+------+-----------------------------------------------------------------------------+ > ``` -## MPP 模式的算法支持 +## MPP 模式支持的算法 -MPP 模式目前支持的物理算法有:Broadcast Hash Join、Shuffled Hash Join、 Shuffled Hash Aggregation、Union All、 TopN 和 Limit。算法的选择由优化器自动判断。通过 `EXPLAIN` 语句可以查看具体的查询执行计划。如果 `EXPLAIN` 语句的结果中出现 ExchangeSender 和 ExchangeReceiver 算子,表明 MPP 已生效。 +MPP 模式支持以下物理算法:Broadcast Hash Join、Shuffled Hash Join、Shuffled Hash Aggregation、Union All、TopN 和 Limit。优化器会自动决定在查询中使用哪种算法。要查看具体的查询执行计划,可以执行 `EXPLAIN` 语句。如果 `EXPLAIN` 语句的结果显示 ExchangeSender 和 ExchangeReceiver 算子,则表示 MPP 模式已生效。 -以 TPC-H 测试集中的表结构为例: +以下语句以 TPC-H 测试集中的表结构为例: ```sql -mysql> explain select count(*) from customer c join nation n on c.c_nationkey=n.n_nationkey; +explain select count(*) from customer c join nation n on c.c_nationkey=n.n_nationkey; +------------------------------------------+------------+--------------+---------------+----------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | +------------------------------------------+------------+--------------+---------------+----------------------------------------------------------------------------+ @@ -97,23 +111,24 @@ mysql> explain select count(*) from customer c join nation n on c.c_nationkey=n. 9 rows in set (0.00 sec) ``` -在执行计划中,出现了 `ExchangeReceiver` 和 `ExchangeSender` 算子。该执行计划表示 `nation` 表读取完毕后,经过 `ExchangeSender` 算子广播到各个节点中,与 `customer` 表先后进行 `HashJoin` 和 `HashAgg` 操作,再将结果返回至 TiDB 中。 +在示例执行计划中,包含了 `ExchangeReceiver` 和 `ExchangeSender` 算子。执行计划表明,在读取 `nation` 表后,`ExchangeSender` 算子将该表广播到每个节点,对 `nation` 表和 `customer` 表执行 `HashJoin` 和 `HashAgg` 操作,然后将结果返回给 TiDB。 -TiFlash 提供了 3 个全局/会话变量决定是否选择 Broadcast Hash Join,分别为: +TiFlash 提供以下 3 个全局/会话变量来控制是否使用 Broadcast Hash Join: -- [`tidb_broadcast_join_threshold_size`](/system-variables.md#tidb_broadcast_join_threshold_size-从-v50-版本开始引入),单位为 bytes。如果表大小(字节数)小于该值,则选择 Broadcast Hash Join 算法。否则选择 Shuffled Hash Join 算法。 -- [`tidb_broadcast_join_threshold_count`](/system-variables.md#tidb_broadcast_join_threshold_count-从-v50-版本开始引入),单位为行数。如果 join 的对象为子查询,优化器无法估计子查询结果集大小,在这种情况下通过结果集行数判断。如果子查询的行数估计值小于该变量,则选择 Broadcast Hash Join 算法。否则选择 Shuffled Hash Join 算法。 -- [`tidb_prefer_broadcast_join_by_exchange_data_size`](/system-variables.md#tidb_prefer_broadcast_join_by_exchange_data_size-从-v710-版本开始引入),控制是否使用最小网络数据交换策略。使用该策略时,TiDB 会估算 Broadcast Hash Join 和 Shuffled Hash Join 两种算法所需进行网络交换的数据量,并选择网络交换数据量较小的算法。该功能开启后,[`tidb_broadcast_join_threshold_size`](/system-variables.md#tidb_broadcast_join_threshold_size-从-v50-版本开始引入) 和 [`tidb_broadcast_join_threshold_count`](/system-variables.md#tidb_broadcast_join_threshold_count-从-v50-版本开始引入) 将不再生效。 +- [`tidb_broadcast_join_threshold_size`](/system-variables.md#tidb_broadcast_join_threshold_size-new-in-v50):值的单位为字节。如果表大小(以字节为单位)小于该变量的值,则使用 Broadcast Hash Join 算法。否则,使用 Shuffled Hash Join 算法。 +- [`tidb_broadcast_join_threshold_count`](/system-variables.md#tidb_broadcast_join_threshold_count-new-in-v50):值的单位为行数。如果连接操作的对象属于子查询,优化器无法估计子查询结果集的大小,因此由结果集中的行数来决定。如果子查询的估计行数小于该变量的值,则使用 Broadcast Hash Join 算法。否则,使用 Shuffled Hash Join 算法。 +- [`tidb_prefer_broadcast_join_by_exchange_data_size`](/system-variables.md#tidb_prefer_broadcast_join_by_exchange_data_size-new-in-v710):控制是否使用网络传输开销最小的算法。如果启用此变量,TiDB 会分别估算使用 `Broadcast Hash Join` 和 `Shuffled Hash Join` 时在网络中交换的数据大小,然后选择大小较小的那个。启用此变量后,[`tidb_broadcast_join_threshold_count`](/system-variables.md#tidb_broadcast_join_threshold_count-new-in-v50) 和 [`tidb_broadcast_join_threshold_size`](/system-variables.md#tidb_broadcast_join_threshold_size-new-in-v50) 将不会生效。 -## MPP 模式访问分区表 +## 在 MPP 模式下访问分区表 -如果希望使用 MPP 模式访问分区表,需要先开启[动态裁剪模式](/partitioned-table.md#动态裁剪模式)。 +要在 MPP 模式下访问分区表,你需要先启用[动态裁剪模式](https://docs.pingcap.com/tidb/stable/partitioned-table#dynamic-pruning-mode)。 -示例如下: +示例: ```sql mysql> DROP TABLE if exists test.employees; Query OK, 0 rows affected, 1 warning (0.00 sec) + mysql> CREATE TABLE test.employees (id int(11) NOT NULL, fname varchar(30) DEFAULT NULL, @@ -131,8 +146,10 @@ Query OK, 0 rows affected (0.10 sec) mysql> ALTER table test.employees SET tiflash replica 1; Query OK, 0 rows affected (0.09 sec) + mysql> SET tidb_partition_prune_mode=static; Query OK, 0 rows affected (0.00 sec) + mysql> explain SELECT count(*) FROM test.employees; +----------------------------------+----------+-------------------+-------------------------------+-----------------------------------+ | id | estRows | task | access object | operator info | @@ -160,6 +177,7 @@ mysql> explain SELECT count(*) FROM test.employees; mysql> SET tidb_partition_prune_mode=dynamic; Query OK, 0 rows affected (0.00 sec) + mysql> explain SELECT count(*) FROM test.employees; +------------------------------+----------+--------------+-----------------+---------------------------------------------------------+ | id | estRows | task | access object | operator info | diff --git a/tikv-overview.md b/tikv-overview.md index 403064720b1d..d21950c9ab5d 100644 --- a/tikv-overview.md +++ b/tikv-overview.md @@ -1,36 +1,36 @@ --- -title: TiKV 简介 -summary: TiKV 是一个分布式事务型的键值数据库,通过 Raft 协议保证了多副本数据一致性和高可用。整体架构采用 multi-raft-group 的副本机制,保证数据和读写负载均匀分散在各个 TiKV 上。TiKV 支持分布式事务,通过两阶段提交保证了 ACID 约束。同时,通过协处理器可以为 TiDB 分担一部分计算。 +title: TiKV 概述 +summary: TiKV 存储引擎的概述。 --- -# TiKV 简介 +# TiKV 概述 -TiKV 是一个分布式事务型的键值数据库,提供了满足 ACID 约束的分布式事务接口,并且通过 [Raft 协议](https://raft.github.io/raft.pdf)保证了多副本数据一致性以及高可用。TiKV 作为 TiDB 的存储层,为用户写入 TiDB 的数据提供了持久化以及读写服务,同时还存储了 TiDB 的统计信息数据。 +TiKV 是一个分布式事务型键值数据库,提供符合 ACID 的事务 API。通过实现 [Raft 共识算法](https://raft.github.io/raft.pdf)并将共识状态存储在 RocksDB 中,TiKV 保证了多副本之间的数据一致性和高可用性。作为 TiDB 分布式数据库的存储层,TiKV 提供读写服务,并持久化来自应用程序的写入数据。它还存储 TiDB 集群的统计数据。 -## 整体架构 +## 架构概述 -与传统的整节点备份方式不同,TiKV 参考 Spanner 设计了 multi-raft-group 的副本机制。将数据按照 key 的范围划分成大致相等的切片(下文统称为 Region),每一个切片会有多个副本(通常是 3 个),其中一个副本是 Leader,提供读写服务。TiKV 通过 PD 对这些 Region 以及副本进行调度,以保证数据和读写负载都均匀地分散在各个 TiKV 上,这样的设计保证了整个集群资源的充分利用并且可以随着机器数量的增加水平扩展。 +TiKV 基于 Google Spanner 的设计实现了多 Raft 组副本机制。Region 是键值数据移动的基本单位,指的是 Store 中的一个数据范围。每个 Region 被复制到多个节点。这些多个副本形成一个 Raft 组。Region 的一个副本称为 Peer。通常一个 Region 有 3 个 Peer。其中一个是 Leader,提供读写服务。PD 组件自动平衡所有 Region,以确保读写吞吐量在 TiKV 集群的所有节点之间保持平衡。通过 PD 和精心设计的 Raft 组,TiKV 在水平扩展性方面表现出色,可以轻松扩展到存储超过 100 TB 的数据。 ![TiKV 架构](/media/tikv-arch.png) -### Region 与 RocksDB +### Region 和 RocksDB -虽然 TiKV 将数据按照范围切割成了多个 Region,但是同一个节点的所有 Region 数据仍然是不加区分地存储于同一个 RocksDB 实例上,而用于 Raft 协议复制所需要的日志则存储于另一个 RocksDB 实例。这样设计的原因是因为随机 I/O 的性能远低于顺序 I/O,所以 TiKV 使用同一个 RocksDB 实例来存储这些数据,以便不同 Region 的写入可以合并在一次 I/O 中。 +每个 Store 内都有一个 RocksDB 数据库,它将数据存储到本地磁盘中。所有 Region 数据都存储在每个 Store 中的同一个 RocksDB 实例中。用于 Raft 共识算法的所有日志都存储在每个 Store 中的另一个 RocksDB 实例中。这是因为顺序 I/O 的性能优于随机 I/O。通过使用不同的 RocksDB 实例存储 Raft 日志和 Region 数据,TiKV 将 Raft 日志和 TiKV Region 的所有数据写入操作合并为一个 I/O 操作,以提高性能。 -### Region 与 Raft 协议 +### Region 和 Raft 共识算法 -Region 与副本之间通过 Raft 协议来维持数据一致性,任何写请求都只能在 Leader 上写入,并且需要写入多数副本后(默认配置为 3 副本,即所有请求必须至少写入两个副本成功)才会返回客户端写入成功。 +Region 副本之间的数据一致性由 Raft 共识算法保证。只有 Region 的 Leader 才能提供写入服务,并且只有当数据写入到 Region 的大多数副本时,写入操作才会成功。 -TiKV 会尽量保持每个 Region 中保存的数据在一个合适的大小,目前默认是 96 MB,这样更有利于 PD 进行调度决策。当某个 Region 的大小超过一定限制(默认是 144 MiB)后,TiKV 会将它分裂为两个或者更多个 Region。同样,当某个 Region 因为大量的删除请求而变得太小时(默认是 20 MiB),TiKV 会将比较小的两个相邻 Region 合并为一个。 +TiKV 尝试为集群中的每个 Region 保持适当的大小。Region 大小目前默认为 96 MiB。这种机制帮助 PD 组件在 TiKV 集群的节点之间平衡 Region。当 Region 的大小超过阈值(默认为 144 MiB)时,TiKV 会将其拆分为两个或多个 Region。当 Region 的大小小于阈值(默认为 20 MiB)时,TiKV 会将两个较小的相邻 Region 合并为一个 Region。 -当 PD 需要把某个 Region 的一个副本从一个 TiKV 节点调度到另一个上面时,PD 会先为这个 Raft Group 在目标节点上增加一个 Learner 副本(虽然会复制 Leader 的数据,但是不会计入写请求的多数副本中)。当这个 Learner 副本的进度大致追上 Leader 副本时,Leader 会将它变更为 Follower,之后再移除操作节点的 Follower 副本,这样就完成了 Region 副本的一次调度。 +当 PD 将副本从一个 TiKV 节点移动到另一个节点时,它首先在目标节点上添加一个 Learner 副本,当 Learner 副本中的数据与 Leader 副本中的数据几乎相同时,PD 将其更改为 Follower 副本,并移除源节点上的 Follower 副本。 -Leader 副本的调度原理也类似,不过需要在目标节点的 Learner 副本变为 Follower 副本后,再执行一次 Leader Transfer,让该 Follower 主动发起一次选举成为新 Leader,之后新 Leader 负责删除旧 Leader 这个副本。 +将 Leader 副本从一个节点移动到另一个节点的机制类似。不同之处在于,当 Learner 副本成为 Follower 副本后,会有一个"Leader 转移"操作,其中 Follower 副本主动提出选举以选举自己为 Leader。最后,新的 Leader 移除源节点中的旧 Leader 副本。 ## 分布式事务 -TiKV 支持分布式事务,用户(或者 TiDB)可以一次性写入多个 key-value 而不必关心这些 key-value 是否处于同一个数据切片 (Region) 上,TiKV 通过两阶段提交保证了这些读写请求的 ACID 约束,详见 [TiDB 乐观事务模型](/optimistic-transaction.md)。 +TiKV 支持分布式事务。用户(或 TiDB)可以写入多个键值对,而不用担心它们是否属于同一个 Region。TiKV 使用两阶段提交来实现 ACID 约束。详情请参见 [TiDB 乐观事务模型](/optimistic-transaction.md)。 -## 计算加速 +## TiKV Coprocessor -TiKV 通过协处理器 (Coprocessor) 可以为 TiDB 分担一部分计算:TiDB 会将可以由存储层分担的计算下推。能否下推取决于 TiKV 是否可以支持相关下推。计算单元仍然是以 Region 为单位,即 TiKV 的一个 Coprocessor 计算请求中不会计算超过一个 Region 的数据。 +TiDB 将一些数据计算逻辑下推到 TiKV Coprocessor。TiKV Coprocessor 处理每个 Region 的计算。发送到 TiKV Coprocessor 的每个请求只涉及一个 Region 的数据。 diff --git a/time-to-live.md b/time-to-live.md index e41f27fb3d72..3ea71cee7361 100644 --- a/time-to-live.md +++ b/time-to-live.md @@ -1,27 +1,27 @@ --- -title: 使用 TTL (Time to Live) 定期删除过期数据 -summary: Time to Live (TTL) 提供了行级别的生命周期控制策略。本篇文档介绍如何通过 TTL (Time to Live) 来管理表数据的生命周期。 +title: 使用 TTL(生存时间)定期删除数据 +summary: 生存时间(TTL)是一个允许您在行级别管理 TiDB 数据生命周期的功能。在本文档中,您可以了解如何使用 TTL 自动使数据过期并删除旧数据。 --- -# 使用 TTL (Time to Live) 定期删除过期数据 +# 使用 TTL(生存时间)定期删除过期数据 -Time to Live (TTL) 提供了行级别的生命周期控制策略。通过为表设置 TTL 属性,TiDB 可以周期性地自动检查并清理表中的过期数据。此功能在一些场景可以有效节省存储空间、提升性能。 +生存时间(TTL)是一个允许您在行级别管理 TiDB 数据生命周期的功能。对于具有 TTL 属性的表,TiDB 会自动检查数据生命周期并在行级别删除过期数据。此功能在某些场景下可以有效节省存储空间并提升性能。 -TTL 常见的使用场景: +以下是 TTL 的一些常见使用场景: -* 定期删除验证码、短网址记录 -* 定期删除不需要的历史订单 -* 自动删除计算的中间结果 +* 定期删除验证码和短链接。 +* 定期删除不必要的历史订单。 +* 自动删除计算的中间结果。 -TTL 设计的目标是在不影响在线读写负载的前提下,帮助用户周期性且及时地清理不需要的数据。TTL 会以表为单位,并发地分发不同的任务到不同的 TiDB Server 节点上,进行并行删除处理。TTL 并不保证所有过期数据立即被删除,也就是说即使数据过期了,客户端仍然有可能在这之后的一段时间内读到过期的数据,直到其真正的被后台处理任务删除。 +TTL 的设计目的是帮助用户定期及时清理不必要的数据,而不影响在线读写工作负载。TTL 以表为单位,将不同的任务并发分派到不同的 TiDB 节点上并行删除数据。TTL 不保证所有过期数据都会立即被删除,这意味着即使某些数据已过期,客户端在过期时间之后的一段时间内仍可能读取到这些数据,直到后台 TTL 任务删除这些数据。 ## 语法 -你可以通过 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 或 [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md) 语句来配置表的 TTL 功能。 +您可以使用 [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) 或 [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md) 语句配置表的 TTL 属性。 ### 创建具有 TTL 属性的表 -- 创建一个具有 TTL 属性的表: +- 创建具有 TTL 属性的表: ```sql CREATE TABLE t1 ( @@ -30,9 +30,9 @@ TTL 设计的目标是在不影响在线读写负载的前提下,帮助用户 ) TTL = `created_at` + INTERVAL 3 MONTH; ``` - 上面的例子创建了一张表 `t1`,并指定了 `created_at` 为 TTL 的时间列,表示数据的创建时间。同时,它还通过 `INTERVAL 3 MONTH` 设置了表中行的最长存活时间为 3 个月。超过了此时长的过期数据会在之后被删除。 + 上述示例创建了一个表 `t1` 并指定 `created_at` 作为 TTL 时间戳列,该列表示数据的创建时间。示例还通过 `INTERVAL 3 MONTH` 设置了一行数据在表中允许存在的最长时间为 3 个月。超过此值的数据将在之后被删除。 -- 设置 `TTL_ENABLE` 属性来开启或关闭清理过期数据的功能: +- 设置 `TTL_ENABLE` 属性以启用或禁用清理过期数据的功能: ```sql CREATE TABLE t1 ( @@ -41,9 +41,9 @@ TTL 设计的目标是在不影响在线读写负载的前提下,帮助用户 ) TTL = `created_at` + INTERVAL 3 MONTH TTL_ENABLE = 'OFF'; ``` - 如果 `TTL_ENABLE` 被设置成了 `OFF`,则即使设置了其他 TTL 选项,当前表也不会自动清理过期数据。对于一个设置了 TTL 属性的表,`TTL_ENABLE` 在缺省条件下默认为 `ON`。 + 如果 `TTL_ENABLE` 设置为 `OFF`,即使设置了其他 TTL 选项,TiDB 也不会自动清理此表中的过期数据。对于具有 TTL 属性的表,`TTL_ENABLE` 默认为 `ON`。 -- 为了与 MySQL 兼容,你也可以使用注释语法来设置 TTL: +- 为了与 MySQL 兼容,您可以使用注释设置 TTL 属性: ```sql CREATE TABLE t1 ( @@ -52,7 +52,7 @@ TTL 设计的目标是在不影响在线读写负载的前提下,帮助用户 ) /*T![ttl] TTL = `created_at` + INTERVAL 3 MONTH TTL_ENABLE = 'OFF'*/; ``` - 在 TiDB 环境中,使用表的 TTL 属性和注释语法来配置 TTL 是等价的。在 MySQL 环境中,会自动忽略注释中的内容,并创建普通的表。 + 在 TiDB 中,使用表 TTL 属性或使用注释配置 TTL 是等效的。在 MySQL 中,注释会被忽略,并创建一个普通表。 ### 修改表的 TTL 属性 @@ -62,15 +62,15 @@ TTL 设计的目标是在不影响在线读写负载的前提下,帮助用户 ALTER TABLE t1 TTL = `created_at` + INTERVAL 1 MONTH; ``` - 上面的语句既支持修改已配置 TTL 属性的表,也支持为一张非 TTL 的表添加 TTL 属性。 + 您可以使用上述语句修改已有 TTL 属性的表,或为没有 TTL 属性的表添加 TTL 属性。 -- 单独修改 TTL 表的 `TTL_ENABLE` 值: +- 修改具有 TTL 属性的表的 `TTL_ENABLE` 值: ```sql ALTER TABLE t1 TTL_ENABLE = 'OFF'; ``` -- 清除一张表的所有 TTL 属性: +- 移除表的所有 TTL 属性: ```sql ALTER TABLE t1 REMOVE TTL; @@ -78,9 +78,9 @@ TTL 设计的目标是在不影响在线读写负载的前提下,帮助用户 ### TTL 和数据类型的默认值 -TTL 可以和[数据类型的默认值](/data-type-default-values.md)一起使用。以下是两种常见的用法示例: +您可以将 TTL 与[数据类型的默认值](/data-type-default-values.md)一起使用。以下是两个常见的使用示例: -* 使用 `DEFAULT CURRENT_TIMESTAMP` 来指定某一列的默认值为该行的创建时间,并用这一列作为 TTL 的时间列,创建时间超过 3 个月的数据将被标记为过期: +* 使用 `DEFAULT CURRENT_TIMESTAMP` 将列的默认值指定为当前创建时间,并使用此列作为 TTL 时间戳列。3 个月前创建的记录将过期: ```sql CREATE TABLE t1 ( @@ -89,7 +89,7 @@ TTL 可以和[数据类型的默认值](/data-type-default-values.md)一起使 ) TTL = `created_at` + INTERVAL 3 MONTH; ``` -* 指定某一列的默认值为该行的创建时间或更新时间,并用这一列作为 TTL 的时间列,创建时间或更新时间超过 3 个月的数据将被标记为过期: +* 将列的默认值指定为创建时间或最新更新时间,并使用此列作为 TTL 时间戳列。3 个月未更新的记录将过期: ```sql CREATE TABLE t1 ( @@ -100,7 +100,7 @@ TTL 可以和[数据类型的默认值](/data-type-default-values.md)一起使 ### TTL 和生成列 -TTL 可以和[生成列](/generated-columns.md)一起使用,用来表达更加复杂的过期规则。例如: +您可以将 TTL 与[生成列](/generated-columns.md)一起使用来配置复杂的过期规则。例如: ```sql CREATE TABLE message ( @@ -114,9 +114,9 @@ CREATE TABLE message ( ) TTL = `expire_at` + INTERVAL 0 DAY; ``` -上述语句的消息以 `expire_at` 列来作为过期时间,并按照消息类型来设定。如果是图片,则 5 天后过期,不然就 30 天后过期。 +上述语句使用 `expire_at` 列作为 TTL 时间戳列,并根据消息类型设置过期时间。如果消息是图片,则 5 天后过期。否则,30 天后过期。 -TTL 还可以和 [JSON 类型](/data-type-json.md) 一起使用。例如: +您可以将 TTL 与 [JSON 类型](/data-type-json.md)一起使用。例如: ```sql CREATE TABLE orders ( @@ -128,44 +128,58 @@ CREATE TABLE orders ( ## TTL 任务 -对于每张设置了 TTL 属性的表,TiDB 内部会定期调度后台任务来清理过期的数据。你可以通过给表设置 `TTL_JOB_INTERVAL` 属性来自定义任务的执行周期,比如通过下面的语句将后台清理任务设置为每 24 小时执行一次: +对于每个具有 TTL 属性的表,TiDB 内部会调度一个后台任务来清理过期数据。您可以通过为表设置 `TTL_JOB_INTERVAL` 属性来自定义这些任务的执行周期。以下示例将表 `orders` 的后台清理任务设置为每 24 小时运行一次: ```sql ALTER TABLE orders TTL_JOB_INTERVAL = '24h'; ``` -`TTL_JOB_INTERVAL` 的默认值是 `1h`。 +`TTL_JOB_INTERVAL` 默认设置为 `1h`。 -在执行 TTL 任务时,TiDB 会基于 Region 的数量将表拆分为最多 64 个子任务。这些子任务会被分发到不同的 TiDB 节点中执行。你可以通过设置系统变量 [`tidb_ttl_running_tasks`](/system-variables.md#tidb_ttl_running_tasks-从-v700-版本开始引入) 来限制整个集群中同时执行的 TTL 子任务数量。然而,并非所有表的 TTL 任务都可以被拆分为子任务。请参考[使用限制](#使用限制)以了解哪些表的 TTL 任务不能被拆分。 +在执行 TTL 任务时,TiDB 会将表分割成最多 64 个任务,以 Region 为最小单位。这些任务将被分布式执行。您可以通过设置系统变量 [`tidb_ttl_running_tasks`](/system-variables.md#tidb_ttl_running_tasks-new-in-v700) 来限制整个集群中并发 TTL 任务的数量。但是,并非所有表的 TTL 任务都可以被分割成任务。有关哪些类型的表的 TTL 任务不能被分割成任务的更多详细信息,请参考[限制](#限制)部分。 -如果想禁止 TTL 任务的执行,除了可以设置表属性 `TTL_ENABLE='OFF'` 外,也可以通过设置全局变量 `tidb_ttl_job_enable` 关闭整个集群的 TTL 任务的执行。 +要禁用 TTL 任务的执行,除了设置表选项 `TTL_ENABLE='OFF'` 外,您还可以通过设置 [`tidb_ttl_job_enable`](/system-variables.md#tidb_ttl_job_enable-new-in-v650) 全局变量来禁用整个集群中 TTL 任务的执行: ```sql SET @@global.tidb_ttl_job_enable = OFF; ``` -在某些场景下,你可能希望只允许在每天的某个时间段内调度后台的 TTL 任务,此时可以设置全局变量 [`tidb_ttl_job_schedule_window_start_time`](/system-variables.md#tidb_ttl_job_schedule_window_start_time-从-v650-版本开始引入) 和 [`tidb_ttl_job_schedule_window_end_time`](/system-variables.md#tidb_ttl_job_schedule_window_end_time-从-v650-版本开始引入) 来指定时间窗口,比如: +在某些场景下,您可能希望只允许 TTL 任务在特定时间窗口内运行。在这种情况下,您可以设置 [`tidb_ttl_job_schedule_window_start_time`](/system-variables.md#tidb_ttl_job_schedule_window_start_time-new-in-v650) 和 [`tidb_ttl_job_schedule_window_end_time`](/system-variables.md#tidb_ttl_job_schedule_window_end_time-new-in-v650) 全局变量来指定时间窗口。例如: ```sql SET @@global.tidb_ttl_job_schedule_window_start_time = '01:00 +0000'; SET @@global.tidb_ttl_job_schedule_window_end_time = '05:00 +0000'; ``` -上述语句只允许在 UTC 时间的凌晨 1 点到 5 点调度 TTL 任务。默认情况下的时间窗口设置为 `00:00 +0000` 到 `23:59 +0000`,即允许所有时段的任务调度。 +上述语句只允许在 UTC 时间 1:00 到 5:00 之间调度 TTL 任务。默认情况下,时间窗口设置为 `00:00 +0000` 到 `23:59 +0000`,允许在任何时间调度任务。 -## TTL 的可观测性 +## 可观测性 -TiDB 会定时采集 TTL 的运行时信息,并在 Grafana 中提供了相关指标的可视化图表。你可以在 TiDB -> TTL 的面板下看到这些信息。指标详情见 [TiDB 重要监控指标详解](/grafana-tidb-dashboard.md) 中的 `TTL` 部分。 + -同时,可以通过以下三个系统表获得 TTL 任务执行的更多信息: +> **注意:** +> +> 本节仅适用于 TiDB Self-Managed。目前,TiDB Cloud 不提供 TTL 指标。 -+ `mysql.tidb_ttl_table_status` 表中包含了所有 TTL 表的上一次执行与正在执行的 TTL 任务的信息。以其中一行为例: + + +TiDB 定期收集 TTL 的运行时信息,并在 Grafana 中提供这些指标的可视化图表。您可以在 Grafana 的 TiDB -> TTL 面板中查看这些指标。 + + + +有关指标的详细信息,请参见[TiDB 监控指标](/grafana-tidb-dashboard.md)中的 TTL 部分。 + + + +此外,TiDB 提供了三个表来获取有关 TTL 任务的更多信息: + ++ `mysql.tidb_ttl_table_status` 表包含所有 TTL 表的先前执行的 TTL 任务和正在进行的 TTL 任务的信息 ```sql TABLE mysql.tidb_ttl_table_status LIMIT 1\G ``` - ```sql + ``` *************************** 1. row *************************** table_id: 85 parent_table_id: 85 @@ -187,12 +201,12 @@ TiDB 会定时采集 TTL 的运行时信息,并在 Grafana 中提供了相关 1 row in set (0.040 sec) ``` - 其中列 `table_id` 为分区表 ID,而 `parent_table_id` 为表的 ID,与 [`information_schema.tables`](/information-schema/information-schema-tables.md) 表中的 ID 对应。如果表不是分区表,则 `table_id` 与 `parent_table_id` 总是相等。 + 列 `table_id` 是分区表的 ID,`parent_table_id` 是表的 ID,与 [`information_schema.tables`](/information-schema/information-schema-tables.md) 中的 ID 对应。如果表不是分区表,这两个 ID 相同。 - 列 `{last, current}_job_{start_time, finish_time, ttl_expire}` 分别描述了过去和当前 TTL 任务的开始时间、结束时间和过期时间。`last_job_summary` 列描述了上一次 TTL 任务的执行情况,包括总行数、成功行数、失败行数。 + 列 `{last, current}_job_{start_time, finish_time, ttl_expire}` 分别描述了最后一次或当前执行的 TTL 任务的开始时间、结束时间和过期时间。`last_job_summary` 列描述了最后一次 TTL 任务的执行状态,包括总行数、成功行数和失败行数。 -+ `mysql.tidb_ttl_task` 表中包含了正在执行的 TTL 子任务。单个 TTL 任务会被拆分为多个子任务,该表中记录了正在执行的这些子任务的信息。 -+ `mysql.tidb_ttl_job_history` 表中记录了 TTL 任务的执行历史。TTL 任务的历史记录将被保存 90 天。以一行为例: ++ `mysql.tidb_ttl_task` 表包含正在进行的 TTL 子任务的信息。一个 TTL 任务被分割成许多子任务,此表记录当前正在执行的子任务。 ++ `mysql.tidb_ttl_job_history` 表包含已执行的 TTL 任务的信息。TTL 任务历史记录保留 90 天。 ```sql TABLE mysql.tidb_ttl_job_history LIMIT 1\G @@ -200,76 +214,89 @@ TiDB 会定时采集 TTL 的运行时信息,并在 Grafana 中提供了相关 ``` *************************** 1. row *************************** - job_id: f221620c-ab84-4a28-9d24-b47ca2b5a301 - table_id: 85 - parent_table_id: 85 - table_schema: test_schema - table_name: TestTable - partition_name: NULL - create_time: 2023-02-15 17:43:46 - finish_time: 2023-02-15 17:45:46 - ttl_expire: 2023-02-15 16:43:46 - summary_text: {"total_rows":9588419,"success_rows":9588419,"error_rows":0,"total_scan_task":63,"scheduled_scan_task":63,"finished_scan_task":63} - expired_rows: 9588419 - deleted_rows: 9588419 - error_delete_rows: 0 - status: finished + job_id: f221620c-ab84-4a28-9d24-b47ca2b5a301 + table_id: 85 + parent_table_id: 85 + table_schema: test_schema + table_name: TestTable + partition_name: NULL + create_time: 2023-02-15 17:43:46 + finish_time: 2023-02-15 17:45:46 + ttl_expire: 2023-02-15 16:43:46 + summary_text: {"total_rows":9588419,"success_rows":9588419,"error_rows":0,"total_scan_task":63,"scheduled_scan_task":63,"finished_scan_task":63} + expired_rows: 9588419 + deleted_rows: 9588419 + error_delete_rows: 0 + status: finished ``` - 其中列 `table_id` 为分区表 ID,而 `parent_table_id` 为表的 ID,与 `information_schema.tables` 表中的 ID 对应。`table_schema`、`table_name`、`partition_name` 分别对应表示数据库、表名、分区名。`create_time`、`finish_time`、`ttl_expire` 分别表示 TTL 任务的创建时间、结束时间和过期时间。`expired_rows` 与 `deleted_rows` 表示过期行数与成功删除的行数。 + 列 `table_id` 是分区表的 ID,`parent_table_id` 是表的 ID,与 `information_schema.tables` 中的 ID 对应。`table_schema`、`table_name` 和 `partition_name` 分别对应数据库、表名和分区名。`create_time`、`finish_time` 和 `ttl_expire` 表示 TTL 任务的创建时间、结束时间和过期时间。`expired_rows` 和 `deleted_rows` 表示过期行数和成功删除的行数。 -## TiDB 数据迁移工具兼容性 +## 与 TiDB 工具的兼容性 -TTL 功能能够与 TiDB 的迁移、备份、恢复工具一同使用。 +TTL 可以与其他 TiDB 迁移、备份和恢复工具一起使用。 -| 工具名称 | 最低兼容版本 | 说明 | +| 工具名称 | 最低支持版本 | 说明 | | --- | --- | --- | -| Backup & Restore (BR) | v6.6.0 | 恢复时会自动将表的 `TTL_ENABLE` 属性设置为 `OFF`,关闭 TTL。这样可以防止 TiDB 在备份恢复后立即删除过期的数据。此时你需要手动重新配置 `TTL_ENABLE` 属性来重新开启各个表的 TTL。 | -| TiDB Lightning | v6.6.0 | 导入后如果表中有 TTL 属性,会自动将表的 `TTL_ENABLE` 属性设置为 `OFF`,关闭 TTL。这样可以防止 TiDB 在导入后立即删除过期的数据。此时你需要手动重新配置 `TTL_ENABLE` 属性来重新开启各个表的 TTL。 | -| TiCDC | v7.0.0 | 上游的 TTL 删除将会同步至下游。因此,为了防止重复删除,下游表的 `TTL_ENABLE` 属性将被强制设置为 `OFF`。 | +| Backup & Restore (BR) | v6.6.0 | 使用 BR 恢复数据后,表的 `TTL_ENABLE` 属性将被设置为 `OFF`。这可以防止 TiDB 在备份和恢复后立即删除过期数据。您需要手动打开每个表的 `TTL_ENABLE` 属性以重新启用 TTL。 | +| TiDB Lightning | v6.6.0 | 使用 TiDB Lightning 导入数据后,导入表的 `TTL_ENABLE` 属性将被设置为 `OFF`。这可以防止 TiDB 在导入后立即删除过期数据。您需要手动打开每个表的 `TTL_ENABLE` 属性以重新启用 TTL。 | +| TiCDC | v7.0.0 | 下游的 `TTL_ENABLE` 属性将自动设置为 `OFF`。上游的 TTL 删除操作将同步到下游。因此,为了防止重复删除,下游表的 `TTL_ENABLE` 属性将被强制设置为 `OFF`。 | -## 与 TiDB 其他特性的兼容性 +## 与 SQL 的兼容性 -| 特性名称 | 说明 | +| 功能名称 | 说明 | | :-- | :---- | -| [`FLASHBACK TABLE`](/sql-statements/sql-statement-flashback-table.md) | `FLASHBACK TABLE` 语句会将每个表的 `TTL_ENABLE` 属性强制设置为 `OFF`。这样可以防止 TiDB 在 FLASHBACK 后立即删除过期的数据。此时你需要手动重新配置 `TTL_ENABLE` 属性来重新开启各个表的 TTL。 | -| [`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.md) | `FLASHBACK DATABASE` 语句会将每个表的 `TTL_ENABLE` 属性强制设置为 `OFF`。这样可以防止 TiDB 在 FLASHBACK 后立即删除过期的数据。此时你需要手动重新配置 `TTL_ENABLE` 属性来重新开启各个表的 TTL。 | -| [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) | `FLASHBACK CLUSTER` 会将 [`TIDB_TTL_JOB_ENABLE`](/system-variables.md#tidb_ttl_job_enable-从-v650-版本开始引入) 系统变量设置为 `OFF`,同时表的 `TTL_ENABLE` 属性将保持原样。 | +| [`FLASHBACK TABLE`](/sql-statements/sql-statement-flashback-table.md) | `FLASHBACK TABLE` 将把表的 `TTL_ENABLE` 属性设置为 `OFF`。这可以防止 TiDB 在闪回后立即删除过期数据。您需要手动打开每个表的 `TTL_ENABLE` 属性以重新启用 TTL。 | +| [`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.md) | `FLASHBACK DATABASE` 将把表的 `TTL_ENABLE` 属性设置为 `OFF`,且不会修改 `TTL_ENABLE` 属性。这可以防止 TiDB 在闪回后立即删除过期数据。您需要手动打开每个表的 `TTL_ENABLE` 属性以重新启用 TTL。 | +| [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) | `FLASHBACK CLUSTER` 将把系统变量 [`TIDB_TTL_JOB_ENABLE`](/system-variables.md#tidb_ttl_job_enable-new-in-v650) 设置为 `OFF`,且不会更改 `TTL_ENABLE` 属性的值。 | -## 使用限制 +## 限制 -目前,TTL 特性具有以下限制: +目前,TTL 功能有以下限制: -* 不允许在临时表上设置 TTL 属性,包括本地临时表和全局临时表。 -* 具有 TTL 属性的表不支持作为外键约束的主表被其他表引用。 -* 不保证所有过期数据立即被删除,过期数据被删除的时间取决于后台清理任务的调度周期和调度窗口。 -* 对于使用[聚簇索引](/clustered-indexes.md)的表,如果主键的类型不是整数类型或二进制字符串类型,TTL 任务将无法被拆分成多个子任务。这将导致 TTL 任务只能在一个 TiDB 节点上按顺序执行。如果表中的数据量较大,TTL 任务的执行可能会变得缓慢。 +* TTL 属性不能在临时表上设置,包括本地临时表和全局临时表。 +* 具有 TTL 属性的表不支持在外键约束中被其他表作为主表引用。 +* 不保证所有过期数据都会立即删除。过期数据被删除的时间取决于后台清理任务的调度间隔和调度窗口。 +* 对于使用[聚簇索引](/clustered-indexes.md)的表,如果主键既不是整数类型也不是二进制字符串类型,则 TTL 任务无法被分割成多个任务。这将导致 TTL 任务在单个 TiDB 节点上顺序执行。如果表包含大量数据,TTL 任务的执行可能会变慢。 ## 常见问题 -- 如何判断删除的速度是否够快,能够保持数据总量相对稳定? + - 在 [Grafana `TiDB` 面板](/grafana-tidb-dashboard.md)中,监控项 `TTL Insert Rows Per Hour` 记录了前一小时总共插入数据的数量。相应的 `TTL Delete Rows Per Hour` 记录了前一小时 TTL 任务总共删除的数据总量。如果 `TTL Insert Rows Per Hour` 长期高于 `TTL Delete Rows Per Hour`, 说明插入的速度高于删除的速度,数据总量将会上升。例如: +- 如何判断删除速度是否足够快以保持数据大小相对稳定? + + 在 [Grafana `TiDB` 面板](/grafana-tidb-dashboard.md)中,`TTL Insert Rows Per Hour` 面板记录了前一小时插入的总行数。相应的 `TTL Delete Rows Per Hour` 记录了前一小时 TTL 任务删除的总行数。如果 `TTL Insert Rows Per Hour` 长期高于 `TTL Delete Rows Per Hour`,则表示插入速率高于删除速率,总数据量将会增加。例如: ![insert fast example](/media/ttl/insert-fast.png) - 值得注意的是,由于 TTL 并不能保证数据立即被删除,且当前插入的数据将会在将来的 TTL 任务中才会被删除,哪怕短时间内 TTL 删除的速度低于插入的速度,也不能说明 TTL 的效率一定过慢。需要结合具体情况分析。 + 值得注意的是,由于 TTL 不保证过期行会立即被删除,而且当前插入的行将在未来的 TTL 任务中被删除,即使在短时间内 TTL 删除速度低于插入速度,也不一定意味着 TTL 速度太慢。您需要结合具体情况来考虑。 -- 如何判断 TTL 任务的瓶颈在扫描还是删除? +- 如何判断 TTL 任务的瓶颈是在扫描还是删除? - 观察面板中 `TTL Scan Worker Time By Phase` 与 `TTL Delete Worker Time By Phase` 监控项。如果 scan worker 处于 `dispatch` 状态的时间有很大占比,且 delete worker 很少处于 `idle` 状态,那么说明 scan worker 在等待 delete worker 完成删除工作,如果此时集群资源仍然较为宽松,可以考虑提高 `tidb_ttl_delete_worker_count` 来提高删除的 worker 数量。例如: + 查看 `TTL Scan Worker Time By Phase` 和 `TTL Delete Worker Time By Phase` 面板。如果扫描工作线程在 `dispatch` 阶段的时间占比较大,而删除工作线程很少处于 `idle` 阶段,则说明扫描工作线程在等待删除工作线程完成删除。如果此时集群资源仍然空闲,可以考虑增加 `tidb_ttl_delete_worker_count` 来增加删除工作线程的数量。例如: ![scan fast example](/media/ttl/scan-fast.png) - 与之相对,如果 scan worker 很少处于 `dispatch` 的状态,且 delete worker 长期处于 `idle` 阶段,那么说明 delete worker 闲置,且 scan worker 较为忙碌。例如: + 相反,如果扫描工作线程很少处于 `dispatch` 阶段,而删除工作线程长时间处于 `idle` 阶段,则说明扫描工作线程相对较忙。例如: ![delete fast example](/media/ttl/delete-fast.png) - TTL 任务中扫描与删除的占比与机器配置、数据分布都有关系,所以每一时刻的数据只能代表正在执行的 TTL Job 的情况。用户可以通过查询表 `mysql.tidb_ttl_job_history` 来判断某一时刻运行的 TTL Job 对应哪一张表。 + TTL 任务中扫描和删除的比例与机器配置和数据分布有关,因此每个时刻的监控数据只能代表当时正在执行的 TTL 任务。您可以通过查看 `mysql.tidb_ttl_job_history` 表来确定某个时刻正在运行的是哪个 TTL 任务以及该任务对应的表。 - 如何合理配置 `tidb_ttl_scan_worker_count` 和 `tidb_ttl_delete_worker_count`? - 1. 可以参考问题 "如何判断 TTL 任务的瓶颈在扫描还是删除?" 来考虑提升 `tidb_ttl_scan_worker_count` 还是 `tidb_ttl_delete_worker_count`。 - 2. 如果 TiKV 节点数量较多,提升 `tidb_ttl_scan_worker_count` 能够使 TTL 任务负载更加均匀。 + 1. 参考"如何判断 TTL 任务的瓶颈是在扫描还是删除?"来考虑是否需要增加 `tidb_ttl_scan_worker_count` 或 `tidb_ttl_delete_worker_count` 的值。 + 2. 如果 TiKV 节点数量较多,增加 `tidb_ttl_scan_worker_count` 的值可以使 TTL 任务的工作负载更加均衡。 + + 由于过多的 TTL 工作线程会造成较大压力,您需要结合评估 TiDB 的 CPU 水平以及 TiKV 的磁盘和 CPU 使用情况。根据不同的场景和需求(是否需要尽可能加快 TTL 速度,或者是否需要减少 TTL 对其他查询的影响),可以调整 `tidb_ttl_scan_worker_count` 和 `tidb_ttl_delete_worker_count` 的值来提高 TTL 扫描和删除的速度或减少 TTL 任务带来的性能影响。 + + + + +- 如何合理配置 `tidb_ttl_scan_worker_count` 和 `tidb_ttl_delete_worker_count`? + + 如果 TiKV 节点数量较多,增加 `tidb_ttl_scan_worker_count` 的值可以使 TTL 任务的工作负载更加均衡。 + + 但是过多的 TTL 工作线程会造成较大压力,您需要结合评估 TiDB 的 CPU 水平以及 TiKV 的磁盘和 CPU 使用情况。根据不同的场景和需求(是否需要尽可能加快 TTL 速度,或者是否需要减少 TTL 对其他查询的影响),可以调整 `tidb_ttl_scan_worker_count` 和 `tidb_ttl_delete_worker_count` 的值来提高 TTL 扫描和删除的速度或减少 TTL 任务带来的性能影响。 - 由于过高的 TTL worker 数量将会造成较大的压力,所以需要综合观察 TiDB 的 CPU 水平与 TiKV 的磁盘与 CPU 使用量。根据不同场景和需求(需要尽量加速 TTL,或是需要减少 TTL 对其他请求的影响)来调整 `tidb_ttl_scan_worker_count` 与 `tidb_ttl_delete_worker_count`,从而提升 TTL 扫描和删除数据的速度,或降低 TTL 任务对性能的影响。 + diff --git a/topn-limit-push-down.md b/topn-limit-push-down.md index 33a5002a4426..1df9b7686df2 100644 --- a/topn-limit-push-down.md +++ b/topn-limit-push-down.md @@ -1,21 +1,23 @@ --- -title: TopN 和 Limit 下推 -summary: TiDB 中的 LIMIT 子句对应 Limit 算子节点,ORDER BY 子句对应 Sort 算子节点。相邻的 Limit 和 Sort 算子组合成 TopN 算子节点,表示按排序规则提取记录的前 N 项。TopN 下推将尽可能下推到数据源附近,减少数据传输或计算的开销。可参考 [优化规则及表达式下推的黑名单](/blocklist-control-plan.md) 中的关闭方法。TopN 可下推到存储层 Coprocessor,减少计算开销。TopN 无法下推过 Join,排序规则仅依赖于外表列时可下推。TopN 也可转换成 Limit,简化排序操作。 +title: TopN 和 Limit 算子下推 +summary: 了解 TopN 和 Limit 算子下推的实现。 --- -# TopN 和 Limit 下推 +# TopN 和 Limit 算子下推 -SQL 中的 LIMIT 子句在 TiDB 查询计划树中对应 Limit 算子节点,ORDER BY 子句在查询计划树中对应 Sort 算子节点,此外,我们会将相邻的 Limit 和 Sort 算子组合成 TopN 算子节点,表示按某个排序规则提取记录的前 N 项。从另一方面来说,Limit 节点等价于一个排序规则为空的 TopN 节点。 +本文档描述了 TopN 和 Limit 算子下推的实现。 -和谓词下推类似,TopN(及 Limit,下同)下推将查询计划树中的 TopN 计算尽可能下推到距离数据源最近的地方,以尽早完成数据的过滤,进而显著地减少数据传输或计算的开销。 +在 TiDB 执行计划树中,SQL 中的 `LIMIT` 子句对应 Limit 算子节点,`ORDER BY` 子句对应 Sort 算子节点。相邻的 Limit 算子和 Sort 算子会被合并为 TopN 算子节点,表示按照某种排序规则返回前 N 条记录。也就是说,Limit 算子等价于一个没有排序规则的 TopN 算子节点。 -如果要关闭这个规则,可参照[优化规则及表达式下推的黑名单](/blocklist-control-plan.md)中的关闭方法。 +类似于谓词下推,TopN 和 Limit 在执行计划树中被下推到尽可能靠近数据源的位置,以便在早期阶段过滤所需数据。通过这种方式,下推显著减少了数据传输和计算的开销。 + +要禁用此规则,请参考[表达式下推的优化规则和黑名单](/blocklist-control-plan.md)。 ## 示例 -以下通过一些例子对 TopN 下推进行说明。 +本节通过一些示例说明 TopN 下推。 -### 示例 1:下推到存储层 Coprocessor +### 示例 1:下推到存储层的 Coprocessor {{< copyable "sql" >}} @@ -36,9 +38,9 @@ explain select * from t order by a limit 10; 4 rows in set (0.00 sec) ``` -在该查询中,将 TopN 算子节点下推到 TiKV 上对数据进行过滤,每个 Coprocessor 只向 TiDB 传输 10 条记录。在 TiDB 将数据整合后,再进行最终的过滤。 +在这个查询中,TopN 算子节点被下推到 TiKV 进行数据过滤,每个 Coprocessor 只向 TiDB 返回 10 条记录。TiDB 聚合数据后,执行最终的过滤。 -### 示例 2:TopN 下推过 Join 的情况(排序规则仅依赖于外表中的列) +### 示例 2:TopN 可以下推到 Join 中(排序规则仅依赖外表的列) {{< copyable "sql" >}} @@ -64,9 +66,9 @@ explain select * from t left join s on t.a = s.a order by t.a limit 10; 8 rows in set (0.01 sec) ``` -在该查询中,TopN 算子的排序规则仅依赖于外表 t 中的列,可以将 TopN 下推到 Join 之前进行一次计算,以减少 Join 时的计算开销。除此之外,TiDB 同样将 TopN 下推到了存储层中。 +在这个查询中,TopN 算子的排序规则仅依赖外表 `t` 的列,因此可以在下推 TopN 到 Join 之前进行计算,以减少 Join 操作的计算成本。此外,TiDB 还将 TopN 下推到存储层。 -### 示例 3:TopN 不能下推过 Join 的情况 +### 示例 3:TopN 不能下推到 Join 之前 {{< copyable "sql" >}} @@ -90,11 +92,11 @@ explain select * from t join s on t.a = s.a order by t.id limit 10; 6 rows in set (0.00 sec) ``` -TopN 无法下推过 Inner Join。以上面的查询为例,如果先 Join 得到 100 条记录,再做 TopN 可以剩余 10 条记录。而如果在 TopN 之前就过滤到剩余 10 条记录,做完 Join 之后可能就剩下 5 条了,导致了结果的差异。 +TopN 不能下推到 `Inner Join` 之前。以上面的查询为例,如果 Join 后得到 100 条记录,然后经过 TopN 后剩下 10 条记录。但如果先执行 TopN 得到 10 条记录,Join 后可能只剩下 5 条记录。在这种情况下,下推会导致不同的结果。 -同理,TopN 无法下推到 Outer Join 的内表上。在 TopN 的排序规则涉及多张表上的列时,也无法下推,如 `t.a+s.a`。只有当 TopN 的排序规则仅依赖于外表上的列时,才可以下推。 +同样,TopN 既不能下推到 Outer Join 的内表,也不能在其排序规则涉及多个表的列时下推,比如 `t.a+s.a`。只有当 TopN 的排序规则完全依赖于外表的列时,才能进行下推。 -### 示例 4:TopN 转换成 Limit 的情况 +### 示例 4:将 TopN 转换为 Limit {{< copyable "sql" >}} @@ -118,7 +120,6 @@ explain select * from t left join s on t.a = s.a order by t.id limit 10; | └─TableFullScan_34 | 10000.00 | cop[tikv] | table:s | keep order:false, stats:pseudo | +----------------------------------+----------+-----------+---------------+-------------------------------------------------+ 8 rows in set (0.00 sec) - ``` -在上面的查询中,TopN 首先推到了外表 t 上。然后因为它要对 `t.id` 进行排序,而 `t.id` 是表 t 的主键,可以直接按顺序读出 (`keep order:true`),从而省略了 TopN 中的排序,将其简化为 Limit。 +在上面的查询中,TopN 首先被下推到外表 `t`。TopN 需要按 `t.id` 排序,而这是主键并且可以直接按顺序读取(`keep order: true`),无需在 TopN 中额外排序。因此,TopN 被简化为 Limit。 diff --git a/transaction-isolation-levels.md b/transaction-isolation-levels.md index 4e6759d1d2a9..e37f1a25135f 100644 --- a/transaction-isolation-levels.md +++ b/transaction-isolation-levels.md @@ -1,36 +1,46 @@ --- title: TiDB 事务隔离级别 -summary: 了解 TiDB 事务的隔离级别。 +summary: 了解 TiDB 中的事务隔离级别。 --- # TiDB 事务隔离级别 -事务隔离级别是数据库事务处理的基础,[ACID](/glossary.md#acid) 中的 “I”,即 Isolation,指的就是事务的隔离性。 + -SQL-92 标准定义了 4 种隔离级别:读未提交 (READ UNCOMMITTED)、读已提交 (READ COMMITTED)、可重复读 (REPEATABLE READ)、串行化 (SERIALIZABLE)。详见下表: +事务隔离是数据库事务处理的基础之一。隔离是事务的四个关键特性之一(通常称为 [ACID](/glossary.md#acid))。 -| Isolation Level | Dirty Write | Dirty Read | Fuzzy Read | Phantom | -| ---------------- | ------------ | ------------ | ------------ | ------------ | -| READ UNCOMMITTED | Not Possible | Possible | Possible | Possible | -| READ COMMITTED | Not Possible | Not possible | Possible | Possible | -| REPEATABLE READ | Not Possible | Not possible | Not possible | Possible | -| SERIALIZABLE | Not Possible | Not possible | Not possible | Not possible | + -TiDB 实现了快照隔离 (Snapshot Isolation, SI) 级别的一致性。为与 MySQL 保持一致,又称其为“可重复读” (REPEATABLE READ)。该隔离级别不同于 [ANSI 可重复读隔离级别](#与-ansi-可重复读隔离级别的区别)和 [MySQL 可重复读隔离级别](#与-mysql-可重复读隔离级别的区别)。 + + +事务隔离是数据库事务处理的基础之一。隔离是事务的四个关键特性之一(通常称为 [ACID](/tidb-cloud/tidb-cloud-glossary.md#acid))。 + + + +SQL-92 标准定义了四个事务隔离级别:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。详情请参见下表: + +| 隔离级别 | 脏写 | 脏读 | 不可重复读 | 幻读 | +| :----------- | :------------ | :------------- | :----------| :-------- | +| READ UNCOMMITTED | 不可能 | 可能 | 可能 | 可能 | +| READ COMMITTED | 不可能 | 不可能 | 可能 | 可能 | +| REPEATABLE READ | 不可能 | 不可能 | 不可能 | 可能 | +| SERIALIZABLE | 不可能 | 不可能 | 不可能 | 不可能 | + +TiDB 实现了快照隔离(Snapshot Isolation,SI)一致性,为了与 MySQL 兼容,它将其标识为 `REPEATABLE-READ`。这与 [ANSI 可重复读隔离级别](#tidb-与-ansi-可重复读的区别)和 [MySQL 可重复读级别](#tidb-与-mysql-可重复读的区别)有所不同。 > **注意:** > -> 在 TiDB v3.0 中,事务的自动重试功能默认为禁用状态。不建议开启自动重试功能,因为可能导致**事务隔离级别遭到破坏**。更多关于事务自动重试的文档说明,请参考[事务重试](/optimistic-transaction.md#重试机制)。 +> 从 TiDB v3.0 开始,事务的自动重试默认关闭。不建议开启自动重试,因为这可能会**破坏事务隔离级别**。详情请参考[事务重试](/optimistic-transaction.md#自动重试)。 > -> 从 TiDB [v3.0.8](/releases/release-3.0.8.md#tidb) 版本开始,新创建的 TiDB 集群会默认使用[悲观事务模式](/pessimistic-transaction.md),悲观事务中的当前读(for update 读)为**不可重复读**,关于悲观事务使用注意事项,请参考[悲观事务模式](/pessimistic-transaction.md) +> 从 TiDB v3.0.8 开始,新创建的 TiDB 集群默认使用[悲观事务模式](/pessimistic-transaction.md)。当前读(`for update` 读)是**不可重复读**。详情请参考[悲观事务模式](/pessimistic-transaction.md)。 -## 可重复读隔离级别 (Repeatable Read) +## 可重复读隔离级别 -当事务隔离级别为可重复读时,只能读到该事务启动时已经提交的其他事务修改的数据,未提交的数据或在事务启动后其他事务提交的数据是不可见的。对于本事务而言,事务语句可以看到之前的语句做出的修改。 +可重复读隔离级别只能看到事务开始之前已经提交的数据,并且在事务执行期间不会看到未提交的数据或并发事务提交的更改。但是,事务语句可以看到其自身事务中之前执行的更新的效果,即使这些更新尚未提交。 -对于运行于不同节点的事务而言,不同事务启动和提交的顺序取决于从 PD 获取时间戳的顺序。 +对于在不同节点上运行的事务,其开始和提交顺序取决于从 PD 获取时间戳的顺序。 -处于可重复读隔离级别的事务不能并发的更新同一行,当事务提交时发现该行在该事务启动后,已经被另一个已提交的事务更新过,那么该事务会回滚。示例如下: +可重复读隔离级别的事务不能同时更新同一行。在提交时,如果事务发现该行在事务开始后已被另一个事务更新,则该事务会回滚。例如: ```sql create table t1(id int); @@ -38,52 +48,56 @@ insert into t1 values(0); start transaction; | start transaction; select * from t1; | select * from t1; -update t1 set id=id+1; | update t1 set id=id+1; -- 如果使用悲观事务,则后一个执行的 update 语句会等锁,直到持有锁的事务提交或者回滚释放行锁。 +update t1 set id=id+1; | update t1 set id=id+1; -- 在悲观事务中,后执行的 `update` 语句会等待锁,直到持有锁的事务提交或回滚并释放行锁。 commit; | - | commit; -- 事务提交失败,回滚。如果使用悲观事务,可以提交成功。 + | commit; -- 事务提交失败并回滚。悲观事务可以成功提交。 ``` -### 与 ANSI 可重复读隔离级别的区别 +### TiDB 与 ANSI 可重复读的区别 + +TiDB 中的可重复读隔离级别与 ANSI 可重复读隔离级别虽然名称相同,但实际上是不同的。根据 [A Critique of ANSI SQL Isolation Levels](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf) 论文中描述的标准,TiDB 实现的是快照隔离级别。这种隔离级别不允许严格幻读(A3),但允许宽松幻读(P3)和写偏斜。相比之下,ANSI 可重复读隔离级别允许幻读但不允许写偏斜。 -尽管名称是可重复读隔离级别,但是 TiDB 中可重复读隔离级别和 ANSI 可重复隔离级别是不同的。按照 [A Critique of ANSI SQL Isolation Levels](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf) 论文中的标准,TiDB 实现的是论文中的快照隔离级别。该隔离级别不会出现狭义上的幻读 (A3),但不会阻止广义上的幻读 (P3),同时,SI 还会出现写偏斜,而 ANSI 可重复读隔离级别不会出现写偏斜,会出现幻读。 +### TiDB 与 MySQL 可重复读的区别 -### 与 MySQL 可重复读隔离级别的区别 +TiDB 中的可重复读隔离级别与 MySQL 中的不同。MySQL 的可重复读隔离级别在更新时不检查当前版本是否可见,这意味着即使在事务开始后该行已被更新,它仍然可以继续更新。相比之下,如果在事务开始后该行已被更新,TiDB 乐观事务会回滚并重试。在 TiDB 的乐观并发控制中,事务重试可能会失败,导致事务最终失败,而在 TiDB 的悲观并发控制和 MySQL 中,更新事务可以成功。 -MySQL 可重复读隔离级别在更新时并不检验当前版本是否可见,也就是说,即使该行在事务启动后被更新过,同样可以继续更新。这种情况在 TiDB 使用乐观事务时会导致事务回滚,导致事务最终失败,而 TiDB 默认的悲观事务和 MySQL 是可以更新成功的。 +## 读已提交隔离级别 -## 读已提交隔离级别 (Read Committed) +从 TiDB v4.0.0-beta 开始,TiDB 支持读已提交隔离级别。 -从 TiDB [v4.0.0-beta](/releases/release-4.0.0-beta.md#tidb) 版本开始,TiDB 支持使用 Read Committed 隔离级别。由于历史原因,当前主流数据库的 Read Committed 隔离级别本质上都是 Oracle 定义的[一致性读隔离级别](https://docs.oracle.com/cd/B19306_01/server.102/b14220/consist.htm)。TiDB 为了适应这一历史原因,悲观事务中的 Read Committed 隔离级别的实质行为也是一致性读。 +由于历史原因,当前主流数据库的读已提交隔离级别本质上是 [Oracle 定义的一致性读隔离级别](https://docs.oracle.com/cd/B19306_01/server.102/b14220/consist.htm)。为了适应这种情况,TiDB 悲观事务中的读已提交隔离级别本质上也是一致性读行为。 > **注意:** > -> Read Committed 隔离级别仅在[悲观事务模式](/pessimistic-transaction.md)下生效。在[乐观事务模式](/optimistic-transaction.md)下设置事务隔离级别为 Read Committed 将不会生效,事务将仍旧使用可重复读隔离级别。 +> 读已提交隔离级别仅在[悲观事务模式](/pessimistic-transaction.md)下生效。在[乐观事务模式](/optimistic-transaction.md)下,设置事务隔离级别为读已提交不会生效,事务仍然使用可重复读隔离级别。 -从 v6.0.0 版本开始,TiDB 支持使用系统变量 [`tidb_rc_read_check_ts`](/system-variables.md#tidb_rc_read_check_ts-从-v600-版本开始引入) 对读写冲突较少情况下优化时间戳的获取。开启此变量后,`SELECT` 语句会尝试使用前一个有效的时间戳进行数据读取,初始值为事务的 `start_ts`。 +从 v6.0.0 开始,TiDB 支持使用 [`tidb_rc_read_check_ts`](/system-variables.md#tidb_rc_read_check_ts-new-in-v600) 系统变量来优化在读写冲突较少场景下的时间戳获取。启用该变量后,TiDB 在执行 `SELECT` 时会尝试使用之前有效的时间戳来读取数据。该变量的初始值为事务的 `start_ts`。 -- 如果整个读取过程没有遇到更新的数据版本,则返回结果给客户端且 `SELECT` 语句执行成功。 -- 如果读取过程中遇到更新的数据版本: - - 如果当前 TiDB 尚未向客户端回复数据,则尝试重新获取一个新的时间戳重试此语句。 - - 如果 TiDB 已经向客户端返回部分数据,则 TiDB 会向客户端报错。每次向客户端回复的数据量受 `tidb_init_chunk_size` 和 `tidb_max_chunk_size` 控制。 +- 如果 TiDB 在读取过程中没有遇到任何数据更新,则向客户端返回结果,`SELECT` 语句执行成功。 +- 如果 TiDB 在读取过程中遇到数据更新: + - 如果 TiDB 还未向客户端发送结果,TiDB 会尝试获取新的时间戳并重试该语句。 + - 如果 TiDB 已经向客户端发送了部分数据,TiDB 会向客户端报错。每次向客户端发送的数据量由 [`tidb_init_chunk_size`](/system-variables.md#tidb_init_chunk_size) 和 [`tidb_max_chunk_size`](/system-variables.md#tidb_max_chunk_size) 控制。 -在使用 `READ-COMMITTED` 隔离级别且单个事务中 `SELECT` 语句较多、读写冲突较少的场景,可通过开启此变量来避免获取全局 timestamp 带来的延迟和开销。 +在使用 `READ-COMMITTED` 隔离级别、`SELECT` 语句较多且读写冲突较少的场景下,启用该变量可以避免获取全局时间戳的延迟和开销。 -从 v6.3.0 版本开始,TiDB 支持通过开启系统变量 [`tidb_rc_write_check_ts`](/system-variables.md#tidb_rc_write_check_ts-从-v630-版本开始引入) 对点写冲突较少情况下优化时间戳的获取。开启此变量后,点写语句会尝试使用当前事务有效的时间戳进行数据读取和加锁操作,且在读取数据时按照开启 [`tidb_rc_read_check_ts`](/system-variables.md#tidb_rc_read_check_ts-从-v600-版本开始引入) 的方式读取数据。目前该变量适用的点写语句包括 `UPDATE`、`DELETE`、`SELECT ...... FOR UPDATE` 三种类型。点写语句是指将主键或者唯一键作为过滤条件且最终执行算子包含 `POINT-GET` 的写语句。目前这三种点写语句的共同点是会先根据 key 值做点查,如果 key 存在再加锁,如果不存在则直接返回空集。 +从 v6.3.0 开始,TiDB 支持通过启用系统变量 [`tidb_rc_write_check_ts`](/system-variables.md#tidb_rc_write_check_ts-new-in-v630) 来优化在点写冲突较少场景下的时间戳获取。启用该变量后,在执行点写语句时,TiDB 会尝试使用当前事务的有效时间戳来读取和锁定数据。TiDB 将以与启用 [`tidb_rc_read_check_ts`](/system-variables.md#tidb_rc_read_check_ts-new-in-v600) 相同的方式读取数据。 -- 如果点写语句的整个读取过程中没有遇到更新的数据版本,则继续使用当前事务的时间戳进行加锁。 - - 如果加锁过程中遇到因时间戳旧而导致写冲突,则重新获取最新的全局时间戳进行加锁。 - - 如果加锁过程中没有遇到写冲突或其他错误,则加锁成功。 -- 如果读取过程中遇到更新的数据版本,则尝试重新获取一个新的时间戳重试此语句。 +目前,适用的点写语句类型包括 `UPDATE`、`DELETE` 和 `SELECT ...... FOR UPDATE`。点写语句指使用主键或唯一键作为过滤条件且最终执行算子包含 `POINT-GET` 的写语句。目前这三种点写语句有一个共同点:它们首先根据键值进行点查询,如果键存在则锁定该键,如果键不存在则返回空集。 -在使用 `READ-COMMITTED` 隔离级别且单个事务中点写语句较多、点写冲突较少的场景,可通过开启此变量来避免获取全局时间戳带来的延迟和开销。 +- 如果点写语句的整个读取过程没有遇到更新的数据版本,TiDB 继续使用当前事务的时间戳来锁定数据。 + - 如果在获取锁的过程中由于时间戳过旧而发生写冲突,TiDB 会通过获取最新的全局时间戳来重试获取锁的过程。 + - 如果在获取锁的过程中没有发生写冲突或其他错误,则锁获取成功。 +- 如果在读取过程中遇到更新的数据版本,TiDB 会尝试获取新的时间戳并重试该语句。 -### 与 MySQL Read Committed 隔离级别的区别 +在 `READ-COMMITTED` 隔离级别下,点写语句较多但点写冲突较少的事务中,启用该变量可以避免获取全局时间戳的延迟和开销。 -MySQL 的 Read Committed 隔离级别大部分符合一致性读特性,但其中存在某些特例,如半一致性读 ([semi-consistent read](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html)),TiDB 没有兼容这个特殊行为。 +## TiDB 与 MySQL 读已提交的区别 + +MySQL 的读已提交隔离级别在大多数情况下符合一致性读特性。也有例外情况,比如[半一致性读](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html)。TiDB 不支持这种特殊行为。 ## 查看和修改事务隔离级别 -你可以通过以下方式查看和修改事务隔离级别。 +你可以按如下方式查看和修改事务隔离级别。 查看当前会话的事务隔离级别: @@ -97,15 +111,8 @@ SHOW VARIABLES LIKE 'transaction_isolation'; SET SESSION transaction_isolation = 'READ-COMMITTED'; ``` -关于事务隔离级别的配置和使用说明,请参考: +有关配置和使用事务隔离级别的更多信息,请参见以下文档: - [系统变量 `transaction_isolation`](/system-variables.md#transaction_isolation) -- [事务模式](/pessimistic-transaction.md#隔离级别) +- [隔离级别](/pessimistic-transaction.md#隔离级别) - [`SET TRANSACTION`](/sql-statements/sql-statement-set-transaction.md) - -## 更多阅读 - -- [TiDB 的乐观事务模型](https://pingcap.com/blog-cn/best-practice-optimistic-transaction/) -- [TiDB 新特性漫谈-悲观事务](https://pingcap.com/blog-cn/pessimistic-transaction-the-new-features-of-tidb/) -- [TiDB 新特性-白话悲观锁](https://pingcap.com/blog-cn/tidb-4.0-pessimistic-lock/) -- [TiKV 的 MVCC (Multi-Version Concurrency Control) 机制](https://pingcap.com/blog-cn/mvcc-in-tikv/) diff --git a/transaction-overview.md b/transaction-overview.md index 325a16aadc5f..956877faa17e 100644 --- a/transaction-overview.md +++ b/transaction-overview.md @@ -1,25 +1,25 @@ --- -title: TiDB 事务概览 +title: 事务 summary: 了解 TiDB 中的事务。 --- -# TiDB 事务概览 +# 事务 -TiDB 支持分布式事务,提供[乐观事务](/optimistic-transaction.md)与[悲观事务](/pessimistic-transaction.md)两种事务模式。TiDB 3.0.8 及以后版本,TiDB 默认采用悲观事务模式。 +TiDB 支持使用[悲观](/pessimistic-transaction.md)或[乐观](/optimistic-transaction.md)事务模式的分布式事务。从 TiDB 3.0.8 开始,TiDB 默认使用悲观事务模式。 -本文主要介绍涉及事务的常用语句、显式/隐式事务、事务的隔离级别和惰性检查,以及事务大小的限制。 +本文档介绍常用的事务相关语句、显式和隐式事务、隔离级别、约束的延迟检查以及事务大小。 -常用的变量包括 [`autocommit`](#自动提交)、[`tidb_disable_txn_auto_retry`](/system-variables.md#tidb_disable_txn_auto_retry)、[`tidb_retry_limit`](/system-variables.md#tidb_retry_limit) 以及 [`tidb_txn_mode`](/system-variables.md#tidb_txn_mode)。 +常用变量包括 [`autocommit`](#autocommit)、[`tidb_disable_txn_auto_retry`](/system-variables.md#tidb_disable_txn_auto_retry)、[`tidb_retry_limit`](/system-variables.md#tidb_retry_limit) 和 [`tidb_txn_mode`](/system-variables.md#tidb_txn_mode)。 > **注意:** > -> 变量 [`tidb_disable_txn_auto_retry`](/system-variables.md#tidb_disable_txn_auto_retry) 和 [`tidb_retry_limit`](/system-variables.md#tidb_retry_limit) 仅适用于乐观事务,不适用于悲观事务。 +> [`tidb_disable_txn_auto_retry`](/system-variables.md#tidb_disable_txn_auto_retry) 和 [`tidb_retry_limit`](/system-variables.md#tidb_retry_limit) 变量仅适用于乐观事务,不适用于悲观事务。 -## 常用事务语句 +## 常用语句 -### 开启事务 +### 开始事务 -要显式地开启一个新事务,既可以使用 [`BEGIN`](/sql-statements/sql-statement-begin.md) 语句,也可以使用 [`START TRANSACTION`](/sql-statements/sql-statement-start-transaction.md) 语句,两者效果相同。 +语句 [`BEGIN`](/sql-statements/sql-statement-begin.md) 和 [`START TRANSACTION`](/sql-statements/sql-statement-start-transaction.md) 可以互换使用,用于显式开始新事务。 语法: @@ -47,15 +47,15 @@ START TRANSACTION WITH CONSISTENT SNAPSHOT; START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; ``` -如果执行以上语句时,当前 Session 正处于一个事务的中间过程,那么系统会先自动提交当前事务,再开启一个新的事务。 +如果在执行这些语句时当前会话正在进行事务,TiDB 会在开始新事务之前自动提交当前事务。 > **注意:** > -> 与 MySQL 不同的是,TiDB 在执行完上述语句后即会获取当前数据库快照,而 MySQL 的 `BEGIN` 和 `START TRANSACTION` 是在开启事务后的第一个从 InnoDB 读数据的 `SELECT` 语句(非 `SELECT FOR UPDATE`)后获取快照,`START TRANSACTION WITH CONSISTENT SNAPSHOT` 是语句执行时获取快照。因此,TiDB 中的 `BEGIN`、`START TRANSACTION` 和 `START TRANSACTION WITH CONSISTENT SNAPSHOT` 都等效为 MySQL 中的 `START TRANSACTION WITH CONSISTENT SNAPSHOT`。 +> 与 MySQL 不同,TiDB 在执行上述语句后立即获取当前数据库的快照。MySQL 的 `BEGIN` 和 `START TRANSACTION` 在事务开始后执行第一个读取 InnoDB 数据的 `SELECT` 语句(不是 `SELECT FOR UPDATE`)时才获取快照。`START TRANSACTION WITH CONSISTENT SNAPSHOT` 在执行语句时获取快照。因此,在 MySQL 中,`BEGIN`、`START TRANSACTION` 和 `START TRANSACTION WITH CONSISTENT SNAPSHOT` 等同于 MySQL 中的 `START TRANSACTION WITH CONSISTENT SNAPSHOT`。 ### 提交事务 -[`COMMIT`](/sql-statements/sql-statement-commit.md) 语句用于提交 TiDB 在当前事务中进行的所有修改。 +语句 [`COMMIT`](/sql-statements/sql-statement-commit.md) 指示 TiDB 应用当前事务中的所有更改。 语法: @@ -65,13 +65,13 @@ START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; COMMIT; ``` -> **建议:** +> **提示:** > -> 启用[乐观事务](/optimistic-transaction.md)前,请确保应用程序可正确处理 `COMMIT` 语句可能返回的错误。如果不确定应用程序将会如何处理,建议改为使用[悲观事务](/pessimistic-transaction.md)。 +> 在启用[乐观事务](/optimistic-transaction.md)之前,请确保您的应用程序正确处理 `COMMIT` 语句可能返回错误的情况。如果您不确定应用程序如何处理这种情况,建议使用默认的[悲观事务](/pessimistic-transaction.md)。 ### 回滚事务 -[`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 语句用于回滚并撤销当前事务的所有修改。 +语句 [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) 回滚并取消当前事务中的所有更改。 语法: @@ -81,19 +81,19 @@ COMMIT; ROLLBACK; ``` -如果客户端连接中止或关闭,也会自动回滚该事务。 +如果客户端连接中断或关闭,事务也会自动回滚。 ## 自动提交 -为满足 MySQL 兼容性的要求,在默认情况下,TiDB 将在执行语句后立即进行 _autocommit_(自动提交)。 +为了保持与 MySQL 的兼容性,TiDB 默认会在语句执行后立即_自动提交_。 -举例: +例如: ```sql mysql> CREATE TABLE t1 ( - id INT NOT NULL PRIMARY KEY auto_increment, - pad1 VARCHAR(100) - ); + id INT NOT NULL PRIMARY KEY auto_increment, + pad1 VARCHAR(100) + ); Query OK, 0 rows affected (0.09 sec) mysql> SELECT @@autocommit; @@ -119,7 +119,7 @@ mysql> SELECT * FROM t1; 1 row in set (0.00 sec) ``` -以上示例中,`ROLLBACK` 语句没产生任何效果。由于 `INSERT` 语句是在自动提交的情况下执行的,等同于以下单语句事务: +在上面的例子中,`ROLLBACK` 语句没有效果。这是因为 `INSERT` 语句是在自动提交模式下执行的。也就是说,它相当于以下单语句事务: ```sql START TRANSACTION; @@ -127,13 +127,13 @@ INSERT INTO t1 VALUES (1, 'test'); COMMIT; ``` -如果已显式地启动事务,则不适用自动提交。以下示例,`ROLLBACK` 语句成功撤回了 `INSERT` 语句: +如果已经显式开始了事务,则不会应用自动提交。在下面的例子中,`ROLLBACK` 语句成功撤销了 `INSERT` 语句: ```sql mysql> CREATE TABLE t2 ( - id INT NOT NULL PRIMARY KEY auto_increment, - pad1 VARCHAR(100) - ); + id INT NOT NULL PRIMARY KEY auto_increment, + pad1 VARCHAR(100) + ); Query OK, 0 rows affected (0.10 sec) mysql> SELECT @@autocommit; @@ -157,9 +157,9 @@ mysql> SELECT * FROM t2; Empty set (0.00 sec) ``` -[`autocommit`](/system-variables.md#autocommit) 是一个系统变量,可以基于 Session 或 Global 进行[修改](/sql-statements/sql-statement-set-variable.md)。 +[`autocommit`](/system-variables.md#autocommit) 系统变量可以在全局或会话级别[进行更改](/sql-statements/sql-statement-set-variable.md)。 -举例: +例如: {{< copyable "sql" >}} @@ -173,23 +173,23 @@ SET autocommit = 0; SET GLOBAL autocommit = 0; ``` -## 显式事务和隐式事务 +## 显式和隐式事务 > **注意:** > -> 有些语句是隐式提交的。例如,执行 `[BEGIN|START TRANCATION]` 语句时,TiDB 会隐式提交上一个事务,并开启一个新的事务以满足 MySQL 兼容性的需求。详情参见 [implicit commit](https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html)。 +> 某些语句会隐式提交。例如,执行 `[BEGIN|START TRANSACTION]` 会隐式提交最后一个事务并开始新事务。这种行为是为了保持与 MySQL 的兼容性。更多详细信息,请参考[隐式提交](https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html)。 -TiDB 可以显式地使用事务(通过 `[BEGIN|START TRANSACTION]`/`COMMIT` 语句定义事务的开始和结束)或者隐式地使用事务 (`SET autocommit = 1`)。 +TiDB 支持显式事务(使用 `[BEGIN|START TRANSACTION]` 和 `COMMIT` 定义事务的开始和结束)和隐式事务(`SET autocommit = 1`)。 -在自动提交状态下,使用 `[BEGIN|START TRANSACTION]` 语句会显式地开启一个事务,同时也会禁用自动提交,使隐式事务变成显式事务。直到执行 `COMMIT` 或 `ROLLBACK` 语句时才会恢复到此前默认的自动提交状态。 +如果将 `autocommit` 的值设置为 `1` 并通过 `[BEGIN|START TRANSACTION]` 语句开始新事务,则在 `COMMIT` 或 `ROLLBACK` 之前自动提交被禁用,使事务成为显式事务。 -对于 DDL 语句,会自动提交并且不能回滚。如果运行 DDL 的时候,正在一个事务的中间过程中,会先自动提交当前事务,再执行 DDL。 +对于 DDL 语句,事务会自动提交且不支持回滚。如果在当前会话正在进行事务时运行 DDL 语句,则在当前事务提交后执行 DDL 语句。 -## 惰性检查 +## 约束的延迟检查 -执行 DML 语句时,乐观事务默认不会检查[主键约束](/constraints.md#主键约束)或[唯一约束](/constraints.md#唯一约束),而是在 `COMMIT` 事务时进行这些检查。 +默认情况下,乐观事务在执行 DML 语句时不会检查[主键](/constraints.md#primary-key)或[唯一约束](/constraints.md#unique-key)。这些检查会在事务 `COMMIT` 时执行。 -举例: +例如: {{< copyable "sql" >}} @@ -199,7 +199,7 @@ INSERT INTO t1 VALUES (1); BEGIN OPTIMISTIC; INSERT INTO t1 VALUES (1); -- MySQL 返回错误;TiDB 返回成功。 INSERT INTO t1 VALUES (2); -COMMIT; -- MySQL 提交成功;TiDB 返回错误,事务回滚。 +COMMIT; -- MySQL 成功提交;TiDB 返回错误并回滚事务。 SELECT * FROM t1; -- MySQL 返回 1 2;TiDB 返回 1。 ``` @@ -219,7 +219,7 @@ Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO t1 VALUES (2); Query OK, 1 row affected (0.00 sec) -mysql> COMMIT; -- MySQL 提交成功;TiDB 返回错误,事务回滚。 +mysql> COMMIT; -- MySQL 成功提交;TiDB 返回错误并回滚事务。 ERROR 1062 (23000): Duplicate entry '1' for key 't1.PRIMARY' mysql> SELECT * FROM t1; -- MySQL 返回 1 2;TiDB 返回 1。 +----+ @@ -230,16 +230,16 @@ mysql> SELECT * FROM t1; -- MySQL 返回 1 2;TiDB 返回 1。 1 row in set (0.01 sec) ``` -惰性检查优化通过批处理约束检查并减少网络通信来提升性能。可以通过设置 [`tidb_constraint_check_in_place = ON`](/system-variables.md#tidb_constraint_check_in_place) 禁用该行为。 +延迟检查优化通过批量约束检查和减少网络通信来提高性能。可以通过设置 [`tidb_constraint_check_in_place=ON`](/system-variables.md#tidb_constraint_check_in_place) 来禁用此行为。 > **注意:** > -> + 本优化仅适用于乐观事务。 -> + 本优化仅对普通的 `INSERT` 语句生效,对 `INSERT IGNORE` 和 `INSERT ON DUPLICATE KEY UPDATE` 不会生效。 +> + 此优化仅适用于乐观事务。 +> + 此优化不适用于 `INSERT IGNORE` 和 `INSERT ON DUPLICATE KEY UPDATE`,仅适用于普通的 `INSERT` 语句。 ## 语句回滚 -TiDB 支持语句执行失败后的原子性回滚。如果语句报错,则所做的修改将不会生效。该事务将保持打开状态,并且在发出 `COMMIT` 或 `ROLLBACK` 语句之前可以进行其他修改。 +TiDB 支持语句执行失败后的原子回滚。如果语句导致错误,其所做的更改将不会生效。事务将保持打开状态,可以在发出 `COMMIT` 或 `ROLLBACK` 语句之前进行其他更改。 {{< copyable "sql" >}} @@ -247,8 +247,8 @@ TiDB 支持语句执行失败后的原子性回滚。如果语句报错,则所 CREATE TABLE test (id INT NOT NULL PRIMARY KEY); BEGIN; INSERT INTO test VALUES (1); -INSERT INTO tset VALUES (2); -- tset 拼写错误,使该语句执行出错。 -INSERT INTO test VALUES (1),(2); -- 违反 PRIMARY KEY 约束,语句不生效。 +INSERT INTO tset VALUES (2); -- 语句不生效,因为 "test" 被错误拼写为 "tset"。 +INSERT INTO test VALUES (1),(2); -- 整个语句不生效,因为违反了主键约束 INSERT INTO test VALUES (3); COMMIT; SELECT * FROM test; @@ -264,9 +264,9 @@ Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO test VALUES (1); Query OK, 1 row affected (0.02 sec) -mysql> INSERT INTO tset VALUES (2); -- tset 拼写错误,使该语句执行出错。 +mysql> INSERT INTO tset VALUES (2); -- 语句不生效,因为 "test" 被错误拼写为 "tset"。 ERROR 1146 (42S02): Table 'test.tset' doesn't exist -mysql> INSERT INTO test VALUES (1),(2); -- 违反 PRIMARY KEY 约束,语句不生效。 +mysql> INSERT INTO test VALUES (1),(2); -- 整个语句不生效,因为违反了主键约束 ERROR 1062 (23000): Duplicate entry '1' for key 'test.PRIMARY' mysql> INSERT INTO test VALUES (3); Query OK, 1 row affected (0.00 sec) @@ -284,31 +284,31 @@ mysql> SELECT * FROM test; 2 rows in set (0.00 sec) ``` -以上例子中,`INSERT` 语句执行失败之后,事务保持打开状态。最后的 `INSERT` 语句执行成功,并且提交了修改。 +在上面的例子中,失败的 `INSERT` 语句后事务仍然保持打开状态。最后的插入语句成功执行,并且更改被提交。 -## 事务限制 +## 事务大小限制 -由于底层存储引擎的限制,TiDB 要求单行不超过 6 MB。可以将一行的所有列根据类型转换为字节数并加和来估算单行大小。 +由于底层存储引擎的限制,TiDB 要求单行不能超过 6 MB。单行的大小是根据其所有列的数据类型将其转换为字节并求和来估算的。 -TiDB 同时支持乐观事务与悲观事务,其中乐观事务是悲观事务的基础。由于乐观事务是先将修改缓存在私有内存中,因此,TiDB 对于单个事务的容量做了限制。 +TiDB 支持乐观和悲观事务,而乐观事务是悲观事务的基础。因为乐观事务首先将更改缓存在私有内存中,TiDB 限制了单个事务的大小。 -TiDB 中,单个事务的总大小默认不超过 100 MB,这个默认值可以通过配置文件中的配置项 `txn-total-size-limit` 进行修改,最大支持 1 TB。单个事务的实际大小限制还取决于服务器剩余可用内存的大小,执行事务时 TiDB 进程的内存消耗相对于事务大小会存在一定程度的放大,最大可能达到提交事务大小的 2 到 3 倍以上。 +默认情况下,TiDB 将单个事务的总大小限制为不超过 100 MB。你可以通过配置文件中的 `txn-total-size-limit` 修改此默认值。`txn-total-size-limit` 的最大值为 1 TB。单个事务的大小限制还取决于服务器中剩余可用内存的大小。这是因为在执行事务时,TiDB 进程的内存使用量会随事务大小增加而增加,最多可达到事务大小的两到三倍或更多。 -在 4.0 以前的版本,TiDB 限制了单个事务的键值对的总数量不超过 30 万条,从 4.0 版本起 TiDB 取消了这项限制。 +TiDB 之前限制单个事务的键值对总数为 300,000。这个限制在 TiDB v4.0 中被移除。 > **注意:** > -> 通常,用户会开启 TiDB Binlog 将数据向下游进行同步。某些场景下,用户会使用消息中间件来消费同步到下游的 binlog,例如 Kafka。 +> 通常,TiDB Binlog 会被启用以将数据复制到下游。在某些场景中,会使用 Kafka 等消息中间件来消费复制到下游的 binlog。 > -> 以 Kafka 为例,Kafka 的单条消息处理能力的上限是 1 GB。因此,当把 `txn-total-size-limit` 设置为 1 GB 以上时,可能出现事务在 TiDB 中执行成功,但下游 Kafka 报错的情况。为避免这种情况出现,请用户根据最终消费者的限制来决定 `txn-total-size-limit` 的实际大小。例如:下游使用了 Kafka,则 `txn-total-size-limit` 不应超过 1 GB。 +> 以 Kafka 为例,Kafka 的单条消息处理能力上限为 1 GB。因此,当 `txn-total-size-limit` 设置为超过 1 GB 时,可能会出现事务在 TiDB 中成功执行,但下游 Kafka 报错的情况。为避免这种情况,你需要根据最终消费者的限制来决定 `txn-total-size-limit` 的实际值。例如,如果下游使用 Kafka,则 `txn-total-size-limit` 不能超过 1 GB。 -## 因果一致性事务 +## 因果一致性 > **注意:** > -> 因果一致性事务只在启用 Async Commit 特性和一阶段提交特性时生效。关于这两个特性的启用情况,请参见 [`tidb_enable_async_commit` 系统变量介绍](/system-variables.md#tidb_enable_async_commit-从-v50-版本开始引入)和 [`tidb_enable_1pc` 系统变量介绍](/system-variables.md#tidb_enable_1pc-从-v50-版本开始引入)。 +> 因果一致性事务仅在启用异步提交和一阶段提交特性时生效。有关这两个特性的详细信息,请参见 [`tidb_enable_async_commit`](/system-variables.md#tidb_enable_async_commit-new-in-v50) 和 [`tidb_enable_1pc`](/system-variables.md#tidb_enable_1pc-new-in-v50)。 -TiDB 支持开启因果一致性的事务。因果一致性的事务在提交时无需向 PD 获取时间戳,所以提交延迟更低。开启因果一致性事务的语法为: +TiDB 支持为事务启用因果一致性。启用因果一致性的事务在提交时不需要从 PD 获取时间戳,具有更低的提交延迟。启用因果一致性的语法如下: {{< copyable "sql" >}} @@ -316,19 +316,17 @@ TiDB 支持开启因果一致性的事务。因果一致性的事务在提交时 START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; ``` -默认情况下,TiDB 保证线性一致性。在线性一致性的情况下,如果事务 2 在事务 1 提交完成后提交,逻辑上事务 2 就应该在事务 1 后发生。 +默认情况下,TiDB 保证线性一致性。在线性一致性的情况下,如果事务 2 在事务 1 提交后提交,从逻辑上讲,事务 2 应该发生在事务 1 之后。因果一致性比线性一致性更弱。在因果一致性的情况下,只有当事务 1 和事务 2 锁定或写入的数据有交集时,即两个事务具有数据库已知的因果关系时,才能保证两个事务的提交顺序和发生顺序一致。目前,TiDB 不支持传入外部因果关系。 -因果一致性弱于线性一致性。在因果一致性的情况下,只有事务 1 和事务 2 加锁或写入的数据有交集时(即事务 1 和事务 2 存在数据库可知的因果关系时),才能保证事务的提交顺序与事务的发生顺序保持一致。目前暂不支持传入数据库外部的因果关系。 +启用因果一致性的两个事务具有以下特征: -采用因果一致性的两个事务有以下特性: ++ [具有潜在因果关系的事务具有一致的逻辑顺序和物理提交顺序](#具有潜在因果关系的事务具有一致的逻辑顺序和物理提交顺序) ++ [没有因果关系的事务不保证一致的逻辑顺序和物理提交顺序](#没有因果关系的事务不保证一致的逻辑顺序和物理提交顺序) ++ [不带锁的读取不会创建因果关系](#不带锁的读取不会创建因果关系) -+ [有潜在因果关系的事务之间的逻辑顺序与物理提交顺序一致](#有潜在因果关系的事务之间的逻辑顺序与物理提交顺序一致) -+ [无因果关系的事务之间的逻辑顺序与物理提交顺序不保证一致](#无因果关系的事务之间的逻辑顺序与物理提交顺序不保证一致) -+ [不加锁的读取不产生因果关系](#不加锁的读取不产生因果关系) +### 具有潜在因果关系的事务具有一致的逻辑顺序和物理提交顺序 -### 有潜在因果关系的事务之间的逻辑顺序与物理提交顺序一致 - -假设事务 1 和事务 2 都采用因果一致性,并先后执行如下语句: +假设事务 1 和事务 2 都采用因果一致性,并执行以下语句: | 事务 1 | 事务 2 | |-------|-------| @@ -339,11 +337,11 @@ START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; | | UPDATE t SET v = 2 WHERE id = 1 | | | COMMIT | -上面的例子中,事务 1 对 `id = 1` 的记录加了锁,事务 2 的事务对 `id = 1` 的记录进行了修改,所以事务 1 和事务 2 有潜在的因果关系。所以即使用因果一致性开启事务,只要事务 2 在事务 1 提交成功后才提交,逻辑上事务 2 就必定比事务 1 晚发生。因此,不存在某个事务读到了事务 2 对 `id = 1` 记录的修改,但却没有读到事务 1 对 `id = 2` 记录的修改的情况。 +在上面的例子中,事务 1 锁定了 `id = 1` 记录,事务 2 修改了 `id = 1` 记录。因此,事务 1 和事务 2 具有潜在的因果关系。即使启用了因果一致性,只要事务 2 在事务 1 成功提交后提交,从逻辑上讲,事务 2 必须发生在事务 1 之后。因此,不可能出现事务读取到事务 2 对 `id = 1` 记录的修改,但没有读取到事务 1 对 `id = 2` 记录的修改的情况。 -### 无因果关系的事务之间的逻辑顺序与物理提交顺序不保证一致 +### 没有因果关系的事务不保证一致的逻辑顺序和物理提交顺序 -假设 `id = 1` 和 `id = 2` 的记录最初值都为 0,事务 1 和事务 2 都采用因果一致性,并先后执行如下语句: +假设 `id = 1` 和 `id = 2` 的初始值都是 `0`。假设事务 1 和事务 2 都采用因果一致性,并执行以下语句: | 事务 1 | 事务 2 | 事务 3 | |-------|-------|-------| @@ -355,13 +353,13 @@ START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; | | COMMIT | | | | | SELECT v FROM t WHERE id IN (1, 2) | -在本例中,事务 1 不读取 `id = 1` 的记录。此时事务 1 和事务 2 没有数据库可知的因果关系。如果使用因果一致性开启事务,即使物理时间上事务 2 在事务 1 提交完成后才开始提交,TiDB 也不保证逻辑上事务 2 比事务 1 晚发生。 +在上面的例子中,事务 1 没有读取 `id = 1` 记录,所以事务 1 和事务 2 没有数据库已知的因果关系。当事务启用因果一致性时,即使事务 2 在物理时间顺序上在事务 1 提交后提交,TiDB 也不保证事务 2 在逻辑上发生在事务 1 之后。 -此时如果有一个事务 3 在事务 1 提交前开启,并在事务 2 提交后读取 `id = 1` 和 `id = 2` 的记录,事务 3 可能读到 `id = 1` 的值为 2 但是 `id = 2` 的值为 0。 +如果事务 3 在事务 1 提交之前开始,并且在事务 2 提交后读取 `id = 1` 和 `id = 2` 记录,事务 3 可能会读取到 `id = 1` 的值为 `2` 但 `id = 2` 的值为 `0`。 -### 不加锁的读取不产生因果关系 +### 不带锁的读取不会创建因果关系 -假设事务 1 和事务 2 都采用因果一致性,并先后执行如下语句: +假设事务 1 和事务 2 都采用因果一致性,并执行以下语句: | 事务 1 | 事务 2 | |-------|-------| @@ -372,4 +370,4 @@ START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; | | COMMIT | | COMMIT | | -如本例所示,不加锁的读取不产生因果关系。事务 1 和事务 2 产生了写偏斜的异常,如果他们有业务上的因果关系,则是不合理的。所以本例中,使用因果一致性的事务 1 和事务 2 没有确定的逻辑顺序。 +在上面的例子中,不带锁的读取不会创建因果关系。事务 1 和事务 2 已经创建了写偏差。在这种情况下,如果两个事务仍然具有因果关系,那将是不合理的。因此,启用因果一致性的两个事务没有确定的逻辑顺序。 diff --git a/translated.md b/translated.md new file mode 100644 index 000000000000..f9cd8eca7553 --- /dev/null +++ b/translated.md @@ -0,0 +1,134 @@ + + + + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:String +- 默认值:`""` +- 该变量用于控制优化器的一些内部行为。 +- 优化器的行为可能会因用户场景或 SQL 语句而异。此变量提供了对优化器更细粒度的控制,有助于防止因优化器行为变化导致升级后的性能回退。 +- 更详细的介绍请参见[优化器修复控制](/optimizer-fix-controls.md)。 + + + +### tidb_opt_force_inline_cte 从 v6.3.0 版本开始引入 + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean +- 默认值:`OFF` +- 该变量用于控制整个会话中的公共表表达式(CTE)是否内联。默认值为 `OFF`,表示默认不强制内联 CTE。但是,您仍然可以通过指定 `MERGE()` hint 来内联 CTE。如果将变量设置为 `ON`,则此会话中的所有 CTE(递归 CTE 除外)都将被强制内联。 + +### tidb_opt_advanced_join_hint 从 v7.0.0 版本开始引入 + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean +- 默认值:`ON` +- 该变量用于控制连接方法 hint(如 [`HASH_JOIN()` hint](/optimizer-hints.md#hash_joint1_name--tl_name-) 和 [`MERGE_JOIN()` hint](/optimizer-hints.md#merge_joint1_name--tl_name-))是否影响连接重排优化过程,包括 [`LEADING()` hint](/optimizer-hints.md#leadingt1_name--tl_name-) 的使用。默认值为 `ON`,表示不影响。如果设置为 `OFF`,在同时使用连接方法 hint 和 `LEADING()` hint 的某些场景下可能会出现冲突。 + +> **注意:** +> +> v7.0.0 之前版本的行为与将此变量设置为 `OFF` 一致。为了保证向前兼容性,当您从早期版本升级到 v7.0.0 或更高版本的集群时,此变量会被设置为 `OFF`。为了获得更灵活的 hint 行为,强烈建议在确保不会出现性能回退的情况下将此变量切换为 `ON`。 + +### tidb_opt_insubq_to_join_and_agg + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean +- 默认值:`ON` +- 该变量用于设置是否启用将子查询转换为连接和聚合的优化规则。 +- 例如,启用此优化规则后,子查询转换如下: + + ```sql + select * from t where t.a in (select aa from t1); + ``` + + 子查询转换为连接如下: + + ```sql + select t.* from t, (select aa from t1 group by aa) tmp_t where t.a = tmp_t.aa; + ``` + + 如果 `t1` 的 `aa` 列被限制为 `unique` 且 `not null`,则可以使用以下语句,无需聚合: + + ```sql + select t.* from t, t1 where t.a=t1.aa; + ``` + +### tidb_opt_join_reorder_threshold + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer +- 默认值:`0` +- 范围:`[0, 2147483647]` +- 该变量用于控制 TiDB 连接重排算法的选择。当参与连接重排的节点数大于此阈值时,TiDB 选择贪心算法,当小于此阈值时,TiDB 选择动态规划算法。 +- 目前,对于 OLTP 查询,建议保持默认值。对于 OLAP 查询,建议将变量值设置为 10~15,以在 OLAP 场景中获得更好的连接顺序。 + +### tidb_opt_limit_push_down_threshold + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Integer +- 默认值:`100` +- 范围:`[0, 2147483647]` +- 该变量用于设置决定是否将 Limit 或 TopN 算子下推到 TiKV 的阈值。 +- 如果 Limit 或 TopN 算子的值小于或等于此阈值,这些算子将被强制下推到 TiKV。此变量解决了由于错误估算导致 Limit 或 TopN 算子无法部分下推到 TiKV 的问题。 + +### tidb_opt_memory_factor + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float +- 范围:`[0, 2147483647]` +- 默认值:`0.001` +- 表示 TiDB 存储一行数据的内存成本。此变量在[成本模型](/cost-model.md)内部使用,**不建议**修改其值。 + +### tidb_opt_mpp_outer_join_fixed_build_side 从 v5.1.0 版本开始引入 + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean +- 默认值:`OFF` +- 当变量值为 `ON` 时,左连接运算符始终使用内表作为构建侧,右连接运算符始终使用外表作为构建侧。如果将值设置为 `OFF`,外连接运算符可以使用表的任一侧作为构建侧。 + +### tidb_opt_network_factor + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float +- 范围:`[0, 2147483647]` +- 默认值:`1.0` +- 表示通过网络传输 1 字节数据的网络成本。此变量在[成本模型](/cost-model.md)内部使用,**不建议**修改其值。 + +### tidb_opt_objective 从 v7.4.0 版本开始引入 + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:枚举 +- 默认值:`moderate` +- 可选值:`moderate`,`determinate` +- 该变量控制优化器的目标。`moderate` 保持 TiDB v7.4.0 之前版本的默认行为,优化器尝试使用更多信息生成更好的执行计划。`determinate` 模式倾向于更保守,使执行计划更稳定。 +- 实时统计信息是基于 DML 语句自动更新的总行数和修改行数。当此变量设置为 `moderate`(默认)时,TiDB 基于实时统计信息生成执行计划。当此变量设置为 `determinate` 时,TiDB 不使用实时统计信息生成执行计划,这将使执行计划更稳定。 +- 对于长期稳定的 OLTP 工作负载,或者如果用户确定现有执行计划,建议使用 `determinate` 模式以减少意外执行计划变更的可能性。此外,您可以使用 [`LOCK STATS`](/sql-statements/sql-statement-lock-stats.md) 防止统计信息被修改,进一步稳定执行计划。 + +### tidb_opt_ordering_index_selectivity_ratio 从 v8.0.0 版本开始引入 + +- 作用域:SESSION | GLOBAL +- 集群持久化:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float +- 默认值:`-1` +- 范围:`[-1, 1]` diff --git a/translated_content.md b/translated_content.md new file mode 100644 index 000000000000..f52b99a7b1a5 --- /dev/null +++ b/translated_content.md @@ -0,0 +1,88 @@ +- 第五个示例同样使用 `1.0`,但在 `a` 上添加了谓词,限制了最坏情况下的扫描范围。这是因为 `WHERE a <= 9000` 匹配索引,大约有 9,000 行数据符合条件。由于 `b` 上的过滤谓词不在索引中,所有这些大约 9,000 行数据都需要被扫描,才能找到符合 `b <= 9000` 的行。 + + ```sql + > SET SESSION tidb_opt_ordering_index_selectivity_ratio = 1; + + > EXPLAIN SELECT * FROM t USE INDEX (ia) WHERE a <= 9000 AND b <= 9000 ORDER BY a LIMIT 1; + +------------------------------------+---------+-----------+-----------------------+------------------------------------+ + | id | estRows | task | access object | operator info | + +------------------------------------+---------+-----------+-----------------------+------------------------------------+ + | Limit_12 | 1.00 | root | | offset:0, count:1 | + | └─Projection_22 | 1.00 | root | | test.t.a, test.t.b, test.t.c | + | └─IndexLookUp_21 | 1.00 | root | | | + | ├─IndexRangeScan_18(Build) | 9074.99 | cop[tikv] | table:t, index:ia(a) | range:[-inf,9000], keep order:true | + | └─Selection_20(Probe) | 1.00 | cop[tikv] | | le(test.t.b, 9000) | + | └─TableRowIDScan_19 | 9074.99 | cop[tikv] | table:t | keep order:false | + +------------------------------------+---------+-----------+-----------------------+------------------------------------+ + ``` + +### tidb_opt_ordering_index_selectivity_threshold 从 v7.0.0 版本开始引入 + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Float +- 默认值:`0` +- 取值范围:`[0, 1]` +- 该变量用于控制优化器在 SQL 语句中同时存在 `ORDER BY` 和 `LIMIT` 子句以及过滤条件时如何选择索引。 +- 对于这类查询,优化器会考虑选择相应的索引来满足 `ORDER BY` 和 `LIMIT` 子句(即使该索引不满足任何过滤条件)。但是,由于数据分布的复杂性,优化器在这种情况下可能会选择次优的索引。 +- 该变量表示一个阈值。当存在可以满足过滤条件的索引,且其选择率估计值低于此阈值时,优化器将避免选择用于满足 `ORDER BY` 和 `LIMIT` 的索引,而是优先选择满足过滤条件的索引。 +- 例如,当变量设置为 `0` 时,优化器保持其默认行为;当设置为 `1` 时,优化器始终优先选择满足过滤条件的索引,避免选择同时满足 `ORDER BY` 和 `LIMIT` 子句的索引。 +- 在以下示例中,表 `t` 总共有 1,000,000 行数据。使用列 `b` 上的索引时,其估计行数约为 8,748,因此其选择率估计值约为 0.0087。默认情况下,优化器选择列 `a` 上的索引。但在将此变量设置为 0.01 后,由于列 `b` 上索引的选择率(0.0087)小于 0.01,优化器选择了列 `b` 上的索引。 + +```sql +> EXPLAIN SELECT * FROM t WHERE b <= 9000 ORDER BY a LIMIT 1; ++-----------------------------------+---------+-----------+----------------------+--------------------+ +| id | estRows | task | access object | operator info | ++-----------------------------------+---------+-----------+----------------------+--------------------+ +| Limit_12 | 1.00 | root | | offset:0, count:1 | +| └─Projection_25 | 1.00 | root | | test.t.a, test.t.b | +| └─IndexLookUp_24 | 1.00 | root | | | +| ├─IndexFullScan_21(Build) | 114.30 | cop[tikv] | table:t, index:ia(a) | keep order:true | +| └─Selection_23(Probe) | 1.00 | cop[tikv] | | le(test.t.b, 9000) | +| └─TableRowIDScan_22 | 114.30 | cop[tikv] | table:t | keep order:false | ++-----------------------------------+---------+-----------+----------------------+--------------------+ + +> SET SESSION tidb_opt_ordering_index_selectivity_threshold = 0.01; + +> EXPLAIN SELECT * FROM t WHERE b <= 9000 ORDER BY a LIMIT 1; ++----------------------------------+---------+-----------+----------------------+-------------------------------------+ +| id | estRows | task | access object | operator info | ++----------------------------------+---------+-----------+----------------------+-------------------------------------+ +| TopN_9 | 1.00 | root | | test.t.a, offset:0, count:1 | +| └─IndexLookUp_20 | 1.00 | root | | | +| ├─IndexRangeScan_17(Build) | 8748.62 | cop[tikv] | table:t, index:ib(b) | range:[-inf,9000], keep order:false | +| └─TopN_19(Probe) | 1.00 | cop[tikv] | | test.t.a, offset:0, count:1 | +| └─TableRowIDScan_18 | 8748.62 | cop[tikv] | table:t | keep order:false | ++----------------------------------+---------+-----------+----------------------+-------------------------------------+ +``` + +### tidb_opt_prefer_range_scan 从 v5.0 版本开始引入 + +- 作用域:SESSION | GLOBAL +- 持久化到集群:是 +- 适用于 hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value):是 +- 类型:Boolean +- 默认值:`OFF` +- 将此变量的值设置为 `ON` 后,优化器将始终优先选择范围扫描而不是全表扫描。 +- 在以下示例中,在启用 `tidb_opt_prefer_range_scan` 之前,TiDB 优化器执行全表扫描。启用 `tidb_opt_prefer_range_scan` 后,优化器选择索引范围扫描。 + +```sql +explain select * from t where age=5; ++-------------------------+------------+-----------+---------------+-------------------+ +| id | estRows | task | access object | operator info | ++-------------------------+------------+-----------+---------------+-------------------+ +| TableReader_7 | 1048576.00 | root | | data:Selection_6 | +| └─Selection_6 | 1048576.00 | cop[tikv] | | eq(test.t.age, 5) | +| └─TableFullScan_5 | 1048576.00 | cop[tikv] | table:t | keep order:false | ++-------------------------+------------+-----------+---------------+-------------------+ +3 rows in set (0.00 sec) + +set session tidb_opt_prefer_range_scan = 1; + +explain select * from t where age=5; ++-------------------------------+------------+-----------+-----------------------------+-------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------------+------------+-----------+-----------------------------+-------------------------------+ +| IndexLookUp_7 | 1048576.00 | root | | | +| ├─IndexRangeScan_5(Build) | 1048576.00 | cop[tikv] | table:t, index:idx_age(age) | range:[5,5], keep order:false | diff --git a/troubleshoot-data-inconsistency-errors.md b/troubleshoot-data-inconsistency-errors.md index 3b7417667342..5b5446a8f04c 100644 --- a/troubleshoot-data-inconsistency-errors.md +++ b/troubleshoot-data-inconsistency-errors.md @@ -1,91 +1,114 @@ --- -title: 数据索引一致性错误 -summary: TiDB 在执行事务或执行 ADMIN CHECK 命令时会检查数据索引的一致性。如果发现不一致,会报错并记录相关错误日志。报错处理可通过改写 SQL 或关闭错误检查来绕过。对于特定错误代码,可通过设置 @@tidb_enable_mutation_checker=0 或 @@tidb_txn_assertion_level=OFF 来跳过检查。需注意关闭开关会关闭所有 SQL 语句的对应检查。 +title: 排查数据和索引之间的不一致问题 +summary: 了解如何处理数据和索引之间一致性检查报告的错误。 --- -# 数据索引一致性报错 +# 排查数据和索引之间的不一致问题 -当执行事务或执行 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 命令时,TiDB 会对数据索引的一致性进行检查。如果检查发现 record key-value 和 index key-value 不一致,即存储行数据的键值对和存储其对应索引的键值对之间不一致(例如多索引或缺索引),TiDB 会报数据索引一致性错误,并在日志文件中打印相关错误日志。 +TiDB 在执行事务或 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 语句时会检查数据和索引之间的一致性。如果检查发现记录键值对和相应的索引键值对不一致,即存储行数据的键值对和存储其索引的键值对不一致(例如,多出索引或缺少索引),TiDB 会报告数据不一致错误,并在错误日志中打印相关错误。 -本文对数据索引一致性的报错信息进行了说明,并提供了一些绕过检查的方法。遇到报错时,你可以前往 [AskTUG 论坛](https://asktug.com/),与社区用户交流;如果是订阅用户,请联系 [PingCAP 服务与支持](https://cn.pingcap.com/support/)。 + -## 错误样例解读 +本文描述了数据不一致错误的含义,并提供了一些绕过一致性检查的方法。如果发生数据一致性错误,你可以从 PingCAP 或社区[获取支持](/support.md)。 -当数据索引不一致时,你可以通过查看 TiDB 的报错信息了解行数据和索引数据在哪一项不一致,或者查看相关错误日志进行判断。 + -### 执行事务中的报错 + -本节列出了 TiDB 在执行事务过程中可能出现的数据索引不一致性的报错,并通过举例对这些信息的含义进行了解释。 +本文描述了数据不一致错误的含义,并提供了一些绕过一致性检查的方法。如果发生数据一致性错误,你可以[联系 TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)。 -#### Error 8133 + + +## 错误说明 + +当数据和索引之间出现不一致时,你可以查看 TiDB 错误消息以了解行数据和索引数据之间哪些项目不一致,或查看相关错误日志以进行进一步调查。 + +### 事务执行期间报告的错误 + +本节列出了 TiDB 执行事务时报告的数据不一致错误,并通过示例解释这些错误的含义。 + +#### 错误 8133 `ERROR 8133 (HY000): data inconsistency in table: t, index: k2, index-count:1 != record-count:0` -上述错误表明,对于表 `t` 中的 `k2` 索引,表中索引数量为 1,行记录的数量为 0,数量不一致。 +此错误表示对于表 `t` 中的 `k2` 索引,表中的索引数量为 1,而行记录数量为 0。数量不一致。 -#### Error 8138 +#### 错误 8138 `ERROR 8138 (HY000): writing inconsistent data in table: t, expected-values:{KindString green} != record-values:{KindString GREEN}` -上述错误表明,事务试图写入的行值有误。即将写入的数据中,编码后的行数据与编码前的原始数据不符。 +此错误表示事务试图写入不正确的行值。对于要写入的数据,编码后的行数据与编码前的原始数据不匹配。 -#### Error 8139 +#### 错误 8139 `ERROR 8139 (HY000): writing inconsistent data in table: t, index: i1, index-handle:4 != record-handle:3, index: tables.mutation{key:kv.Key{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0, 0x0, 0x0, 0xfc, 0x1, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0, 0x0, 0x0, 0xfc, 0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}, flags:0x0, value:[]uint8{0x30}, indexID:1}, record: tables.mutation{key:kv.Key{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3}, flags:0xd, value:[]uint8{0x80, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, 0x0, 0xa, 0x0, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x68, 0x65, 0x6c, 0x6c, 0x6f}, indexID:0}` -上述错误表明,即将写入的数据中,handle(即行数据的 key)值不一致。对于表 `t` 中的 `i1` 索引,该事务即将写入的某行在索引键值对中的 handle 值是 4,在行记录键值对中的 handle 值是 3。这行数据将不会被写入。 +此错误表示要写入的数据的 handle(即行数据的键)不一致。对于表 `t` 中的索引 `i1`,事务要写入的行在索引键值对中的 handle 为 4,而在行记录键值对中的 handle 为 3。此行的数据将不会被写入。 -#### Error 8140 +#### 错误 8140 `ERROR 8140 (HY000): writing inconsistent data in table: t, index: i2, col: c1, indexed-value:{KindString hellp} != record-value:{KindString hello}` -上述错误表明,事务试图写入的行和索引的值不一致。对于表 `t` 中的 `i2` 索引,该事务即将写入的某行在索引键值对中的数据是 `hellp`,在行记录键值对中的数据是`hello`。这行数据将不会被写入。 +此错误表示事务要写入的行中的数据与索引中的数据不匹配。对于表 `t` 中的索引 `i2`,事务要写入的一行在索引键值对中的数据为 `hellp`,而在记录键值对中的数据为 `hello`。此行的数据将不会被写入。 -#### Error 8141 +#### 错误 8141 `ERROR 8141 (HY000): assertion failed: key: 7480000000000000405f72013300000000000000f8, assertion: NotExist, start_ts: 430590532931813377, existing start ts: 430590532931551233, existing commit ts: 430590532931551234` -上述错误表明,事务提交时断言失败。根据数据索引一致的假设,TiDB 断言 key `7480000000000000405f72013300000000000000f8` 不存在,提交事务时发现该 key 存在,是由 start ts 为 `430590532931551233` 的事务写入的。TiDB 会将该 key 的 MVCC (Multi-Version Concurrency Control) 历史输出到日志。 +此错误表示事务提交时断言失败。假设数据和索引是一致的,TiDB 断言键 `7480000000000000405f720133000000000000000000f8` 不存在。当事务提交时,TiDB 发现该键确实存在,由 `start ts` 为 `430590532931551233` 的事务写入。TiDB 会将此键的多版本并发控制(MVCC)历史记录打印到日志中。 -### Admin check 中的报错 +### admin check 中报告的错误 -本节列出了执行 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 系列语句时 TiDB 可能出现的数据索引不一致报错,并通过举例对这些信息的含义进行了解释。 +本节列出了在执行 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 语句时 TiDB 可能出现的数据不一致错误,并通过示例解释这些错误的含义。 -#### Error 8003 +#### 错误 8003 `ERROR 8003 (HY000): table count 3 != index(idx) count 2` -上述错误表明,在 [`ADMIN CHECK`](/sql-statements/sql-statement-admin-check-table-index.md) 语句所执行的表上有 3 个行键值对,但只有 2 个索引键值对。 +此错误表示执行 [`ADMIN CHECK`](/sql-statements/sql-statement-admin-check-table-index.md) 语句的表有 3 个行键值对,但只有 2 个索引键值对。 -#### Error 8134 +#### 错误 8134 `ERROR 8134 (HY000): data inconsistency in table: t, index: c2, col: c2, handle: "2", index-values:"KindInt64 13" != record-values:"KindInt64 12", compare err:` -上述错误表明,对于表 `t` 中的 `c2` 索引,handle 为 2 的行对应的索引键值对中列 c2 的值是 13,行记录键值对中列 c2 的值是 12。 +此错误表示对于表 `t` 中的索引 `c2`,列 `c2` 的值有以下不一致: + +- 在 handle 为 `2` 的行的索引键值对中,列 `c2` 的值为 `13`。 +- 在行记录键值对中,列 `c2` 的值为 `12`。 -#### Error 8223 +#### 错误 8223 `ERROR 8223 (HY000): data inconsistency in table: t2, index: i1, handle: {hello, hello}, index-values:"" != record-values:"handle: {hello, hello}, values: [KindString hello KindString hello]"` -上述错误表明,`index-values` 为空,`record-values` 不为空,说明不存在对应的索引,但存在对应的行。 +此错误表示 `index-values` 为空而 `record-values` 不为空,意味着该行没有对应的索引。 + +## 解决方案 + + + +如果遇到数据不一致错误,请立即从 PingCAP [获取支持](/support.md)进行故障排查,而不是自行处理错误。如果你的应用程序需要紧急跳过此类错误,你可以使用以下方法绕过检查。 + + + + -## 报错处理 +如果遇到数据不一致错误,请立即[联系 TiDB Cloud 支持团队](/tidb-cloud/tidb-cloud-support.md)进行故障排查,而不是自行处理错误。如果你的应用程序需要紧急跳过此类错误,你可以使用以下方法绕过检查。 -发生报错时,不要自行处理,请从 PingCAP 官方或 TiDB 社区[获取支持](/support.md)。如果业务急需跳过此类报错,可以使用以下方法绕过检查。 + -### 改写 SQL +### 重写 SQL -如果只有某一条 SQL 语句报错,可以尝试将其改写为其它等价的 SQL 形式,以使用不同的执行算子来尝试绕过。 +如果数据不一致错误仅在特定 SQL 语句中出现,你可以通过使用不同执行运算符将 SQL 语句重写为另一种等效形式来绕过此错误。 -### 关闭错误检查 +### 禁用错误检查 -对于事务执行中出现的一些报错,可以使用以下方法绕过检查: +对于事务执行中报告的以下错误,你可以绕过相应的检查: -- 对于错误代码为 8138、8139 和 8140 的错误,可以通过设置 `set @@tidb_enable_mutation_checker=0` 跳过检查。 -- 对于错误代码为 8141 的错误,可以通过设置 `set @@tidb_txn_assertion_level=OFF` 跳过检查。 +- 要绕过错误 8138、8139 和 8140 的检查,配置 `set @@tidb_enable_mutation_checker=0`。 +- 要绕过错误 8141 的检查,配置 `set @@tidb_txn_assertion_level=OFF`。 > **注意:** > -> 关闭 `tidb_enable_mutation_checker` 和 `tidb_txn_assertion_level` 开关会关闭对所有 SQL 语句的对应检查。 +> 禁用 `tidb_enable_mutation_checker` 和 `tidb_txn_assertion_level` 将绕过所有 SQL 语句的相应检查。 -对于其它错误代码,包括执行 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 系列语句或执行事务中的报错,由于数据中已经存在不一致,无法跳过对应的检查。 +对于事务执行中报告的其他错误以及在执行 [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) 语句期间报告的所有错误,你无法绕过相应的检查,因为数据已经不一致。 diff --git a/tso.md b/tso.md index 4be369fe1793..4723028cd8d1 100644 --- a/tso.md +++ b/tso.md @@ -1,13 +1,13 @@ --- -title: TiDB 中的 TimeStamp Oracle (TSO) -summary: 了解 TiDB 中的 TimeStamp Oracle (TSO)。 +title: TiDB 中的时间戳预分配器 (TSO) +summary: 了解 TiDB 中的时间戳预分配器 (TSO)。 --- -# TiDB 中的 TimeStamp Oracle (TSO) +# TiDB 中的时间戳预分配器 (TSO) -在 TiDB 中,Placement Driver (PD) 承担着 TSO 时间戳分配器的角色,负责为集群内各组件分配时间戳。这些时间戳用于为事务和数据分配时间标记。该分配机制对于在 TiDB 中启用 [Percolator](https://research.google/pubs/large-scale-incremental-processing-using-distributed-transactions-and-notifications/) 模型至关重要。Percolator 模型用于支持多版本并发控制 (Multi-Version Concurrency Control, MVCC) 和[事务管理](/transaction-overview.md)。 +在 TiDB 中,Placement Driver (PD) 在为集群内各个组件分配时间戳方面发挥着关键作用。这些时间戳对于为事务和数据分配时间标记至关重要,这种机制对于在 TiDB 中实现 [Percolator](https://research.google/pubs/large-scale-incremental-processing-using-distributed-transactions-and-notifications/) 模型非常重要。Percolator 模型用于支持[多版本并发控制 (MVCC)](https://docs.pingcap.com/tidb/stable/glossary#multi-version-concurrency-control-mvcc) 和[事务管理](/transaction-overview.md)。 -下面示例显示了如何获取 TiDB 当前的 TSO: +以下示例展示了如何在 TiDB 中获取当前的 TSO: ```sql BEGIN; SET @ts := @@tidb_current_ts; ROLLBACK; @@ -24,9 +24,9 @@ SELECT @ts; 1 row in set (0.00 sec) ``` -注意由于 TSO 时间戳是按事务分配的,所以需要从包含 `BEGIN; ...; ROLLBACK` 的事务中获取时间戳。 +注意,这是在事务中使用 `BEGIN; ...; ROLLBACK` 完成的,因为 TSO 时间戳是按事务分配的。 -从上例中得到的 TSO 时间戳是一个十进制数。你可以使用以下 SQL 函数来解析时间戳: +从上述示例中获得的 TSO 时间戳是一个十进制数。你可以使用以下 SQL 函数来解析时间戳: - [`TIDB_PARSE_TSO()`](/functions-and-operators/tidb-functions.md#tidb_parse_tso) - [`TIDB_PARSE_TSO_LOGICAL()`](/functions-and-operators/tidb-functions.md) @@ -51,20 +51,20 @@ SELECT TIDB_PARSE_TSO_LOGICAL(443852055297916932); 1 row in set (0.00 sec) ``` -下面示例展示了 TSO 时间戳的二进制细节: +以下示例展示了 TSO 时间戳在二进制中的样子: ```shell -0000011000101000111000010001011110111000110111000000000000000100 ← 该值是二进制形式的 443852055297916932 +0000011000101000111000010001011110111000110111000000000000000100 ← 这是 443852055297916932 的二进制表示 0000011000101000111000010001011110111000110111 ← 前 46 位是物理时间戳 000000000000000100 ← 后 18 位是逻辑时间戳 ``` -TSO 时间戳由两部分组成: +TSO 时间戳包含两个部分: -- 物理时间戳:自 1970 年 1 月 1 日以来的 UNIX 时间戳,单位为毫秒。 -- 逻辑时间戳:递增计数器,用于需要在一毫秒内使用多个时间戳的情况,或某些事件可能触发时钟进程逆转的情况。在这些情况下,物理时间戳会保持不变,而逻辑时间戳保持递增。该机制可以确保 TSO 时间戳的完整性,确保时间戳始终递增而不会倒退。 +- 物理时间戳:自 1970 年 1 月 1 日以来的 UNIX 时间戳(以毫秒为单位)。 +- 逻辑时间戳:一个递增计数器,用于在同一毫秒内需要多个时间戳的场景,或在某些事件可能导致时钟回退的情况下。在这些情况下,物理时间戳保持不变,而逻辑时间戳稳步前进。这种机制确保了 TSO 时间戳始终向前移动,永不回退。 -你可以通过 SQL 语句更深入地查看 TSO 时间戳,示例如下: +有了这些知识,你可以在 SQL 中更深入地检查 TSO 时间戳: ```sql SELECT @ts, UNIX_TIMESTAMP(NOW(6)), (@ts >> 18)/1000, FROM_UNIXTIME((@ts >> 18)/1000), NOW(6), @ts & 0x3FFFF\G @@ -78,11 +78,11 @@ FROM_UNIXTIME((@ts >> 18)/1000): 2023-08-27 20:33:41.6870 1 row in set (0.00 sec) ``` -`>> 18` 操作表示按位[右移](/functions-and-operators/bit-functions-and-operators.md#右移) 18 位,用于提取物理时间戳。由于物理时间戳以毫秒为单位,与更常见的以秒为单位的 UNIX 时间戳格式不同,因此需要除以 1000 将其转换为与 [`FROM_UNIXTIME()`](/functions-and-operators/date-and-time-functions.md) 兼容的格式。这个转换过程与 `TIDB_PARSE_TSO()` 的功能一致。 +`>> 18` 操作表示[右移](/functions-and-operators/bit-functions-and-operators.md#-right-shift) 18 位,用于提取物理时间戳。由于物理时间戳以毫秒为单位表示,与更常见的以秒为单位的 UNIX 时间戳格式不同,你需要将其除以 1000 以转换为与 [`FROM_UNIXTIME()`](/functions-and-operators/date-and-time-functions.md) 兼容的格式。这个过程与 `TIDB_PARSE_TSO()` 的功能一致。 -你还可以将二进制中的逻辑时间戳 `000000000000000100`(即十进制中的 `4`)提取出来。 +你还可以提取逻辑时间戳 `000000000000000100`(二进制),它等于十进制的 `4`。 -你也可以通过 CLI 工具解析时间戳,命令如下: +你也可以通过 CLI 工具解析时间戳,如下所示: ```shell $ tiup ctl:v7.1.0 pd tso 443852055297916932 @@ -93,4 +93,4 @@ system: 2023-08-27 20:33:41.687 +0200 CEST logic: 4 ``` -可以看到,物理时间戳在以 `system:` 开头的行中,逻辑时间戳在以 `logic:` 开头的行中。 +在这里,你可以看到以 `system:` 开头的行中的物理时间戳,以及以 `logic:` 开头的行中的逻辑时间戳。 diff --git a/user-defined-variables.md b/user-defined-variables.md index 3ddae1f91f23..6be79e365978 100644 --- a/user-defined-variables.md +++ b/user-defined-variables.md @@ -1,23 +1,23 @@ --- -title: 用户自定义变量 -summary: 本文介绍 TiDB 的用户自定义变量。 +title: 用户定义变量 +summary: 了解如何使用用户定义变量。 --- -# 用户自定义变量 +# 用户定义变量 + +本文档描述了 TiDB 中用户定义变量的概念以及设置和读取用户定义变量的方法。 > **警告:** > -> 当前该功能为实验特性,不建议在生产环境中使用。 - -本文介绍 TiDB 的用户自定义变量的概念,以及设置和读取用户自定义变量的方法。 +> 用户定义变量仍然是一个实验性功能。**不建议**在生产环境中使用它们。 -用户自定义变量格式为 `@var_name`。组成 `var_name` 的字符可以是任何能够组成标识符 (identifier) 的字符,包括数字 `0-9`、字母 `a-zA-Z`、下划线 `_`、美元符号 `$` 以及 UTF-8 字符。此外,还包括英文句号 `.`。用户自定义变量是大小写不敏感的。 +用户定义变量的格式是 `@var_name`。组成 `var_name` 的字符可以是任何可以组成标识符的字符,包括数字 `0-9`、字母 `a-zA-Z`、下划线 `_`、美元符号 `$` 和 UTF-8 字符。此外,还包括英文句点 `.`。用户定义变量不区分大小写。 -用户自定义变量跟 session 绑定,当前设置的用户变量只在当前连接中可见,其他客户端连接无法查看。 +用户定义变量是会话特定的,这意味着一个客户端连接定义的用户变量不能被其他客户端连接看到或使用。 -## 设置用户自定义变量 +## 设置用户定义变量 -用 [`SET` 语句](/sql-statements/sql-statement-set-variable.md)可以设置用户自定义变量,语法为 `SET @var_name = expr [, @var_name = expr] ...;`。例如: +您可以使用 [`SET` 语句](/sql-statements/sql-statement-set-variable.md)来设置用户定义变量,语法是 `SET @var_name = expr [, @var_name = expr] ...;`。例如: ```sql SET @favorite_db = 'TiDB'; @@ -27,13 +27,13 @@ SET @favorite_db = 'TiDB'; SET @a = 'a', @b = 'b', @c = 'c'; ``` -其中赋值符号还可以使用 `:=`。例如: +对于赋值运算符,您也可以使用 `:=`。例如: ```sql SET @favorite_db := 'TiDB'; ``` -赋值符号右边的内容可以是任意合法的表达式。例如: +赋值运算符右侧的内容可以是任何有效的表达式。例如: ```sql SET @c = @a + @b; @@ -43,9 +43,9 @@ SET @c = @a + @b; SET @c = b'1000001' + b'1000001'; ``` -## 读取用户自定义变量 +## 读取用户定义变量 -要读取一个用户自定义变量,可以使用 `SELECT` 语句查询: +要读取用户定义变量,您可以使用 `SELECT` 语句进行查询: ```sql SELECT @a1, @a2, @a3 @@ -59,7 +59,7 @@ SELECT @a1, @a2, @a3 +------+------+------+ ``` -还可以在 `SELECT` 语句中赋值: +您也可以在 `SELECT` 语句中赋值: ```sql SELECT @a1, @a2, @a3, @a4 := @a1+@a2+@a3; @@ -73,9 +73,9 @@ SELECT @a1, @a2, @a3, @a4 := @a1+@a2+@a3; +------+------+------+--------------------+ ``` -其中变量 `@a4` 在被修改或关闭连接之前,值始终为 `7`。 +在变量 `@a4` 被修改或连接关闭之前,其值始终为 `7`。 -如果设置用户变量时用了十六进制字面量或者二进制字面量,TiDB 会把它当成二进制字符串。如果要将其设置成数字,那么可以手动加上 `CAST` 转换,或者在表达式中使用数字的运算符: +如果在设置用户定义变量时使用了十六进制字面量或二进制字面量,TiDB 会将其视为二进制字符串。如果您想将其设置为数字,可以手动添加 `CAST` 转换,或在表达式中使用数值运算符: ```sql SET @v1 = b'1000001'; @@ -95,7 +95,7 @@ SELECT @v1, @v2, @v3; +------+------+------+ ``` -如果获取一个没有设置过的变量,会返回一个 NULL: +如果您引用一个尚未初始化的用户定义变量,它的值为 NULL,类型为字符串。 ```sql SELECT @not_exist; @@ -109,7 +109,7 @@ SELECT @not_exist; +------------+ ``` -除了 `SELECT` 读取用户自定义变量以外,常见的用法还有 `PREPARE` 语句,例如: +除了使用 `SELECT` 语句读取用户定义变量外,另一个常见用法是 `PREPARE` 语句。例如: ```sql SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; @@ -127,10 +127,10 @@ EXECUTE stmt USING @a, @b; +------------+ ``` -用户自定义变量的内容不会在 SQL 语句中被当成标识符,例如: +用户定义变量的内容在 SQL 语句中不会被识别为标识符。例如: ```sql -SELECT * FROM t; +SELECT * from t; ``` ``` @@ -156,6 +156,6 @@ SELECT @col FROM t; ## MySQL 兼容性 -除 `SELECT ... INTO ` 外,MySQL 和 TiDB 支持的语法相同。 +除了 `SELECT ... INTO ` 外,MySQL 和 TiDB 支持的语法是相同的。 -更多细节,请参考 [MySQL 文档](https://dev.mysql.com/doc/refman/8.0/en/user-variables.html)。 +更多信息,请参阅 [MySQL 中的用户定义变量](https://dev.mysql.com/doc/refman/8.0/en/user-variables.html)。 diff --git a/views.md b/views.md index bc9f9407eb31..c9896fb8799e 100644 --- a/views.md +++ b/views.md @@ -1,23 +1,26 @@ --- title: 视图 -summary: TiDB 支持视图,视图是虚拟表,结构由创建时的 SELECT 语句定义。使用视图可保证数据安全,简化复杂查询。查询视图类似查询表,TiDB 执行查询时会展开视图。可通过 SHOW CREATE TABLE 或 SHOW CREATE VIEW 查看视图创建语句及相关信息。也可查询 INFORMATION_SCHEMA.VIEWS 表或访问 HTTP API 获取视图元信息。视图有局限性,不支持物化视图,且为只读视图,不支持写入操作。已创建的视图仅支持 DROP 操作。 +summary: 了解如何在 TiDB 中使用视图。 --- # 视图 -TiDB 支持视图,视图是一张虚拟表,该虚拟表的结构由创建视图时的 `SELECT` 语句定义。使用视图一方面可以对用户只暴露安全的字段及数据,进而保证底层表的敏感字段及数据的安全。另一方面,将频繁出现的复杂查询定义为视图,可以使复杂查询更加简单便捷。 +TiDB 支持视图。视图作为一个虚拟表,其架构由创建视图的 `SELECT` 语句定义。使用视图具有以下优点: + +- 仅向用户公开安全的字段和数据,确保底层表中存储的敏感字段和数据的安全性。 +- 将经常出现的复杂查询定义为视图,使复杂查询更简单和方便。 ## 查询视图 -查询一个视图和查询一张普通表类似。但是 TiDB 在真正执行查询视图时,会将视图展开成创建视图时定义的 `SELECT` 语句,进而执行展开后的查询语句。 +查询视图与查询普通表类似。但是,当 TiDB 查询视图时,它实际上是在查询与该视图关联的 `SELECT` 语句。 -## 查看视图的相关信息 +## 显示元数据 -通过以下方式,可以查看 view 相关的信息。 +要获取视图的元数据,可以选择以下任一方法。 ### 使用 `SHOW CREATE TABLE view_name` 或 `SHOW CREATE VIEW view_name` 语句 -示例: +使用示例: {{< copyable "sql" >}} @@ -25,7 +28,7 @@ TiDB 支持视图,视图是一张虚拟表,该虚拟表的结构由创建视 show create view v; ``` -使用该语句可以查看 view 对应的创建语句,及创建 view 时对应的 `character_set_client` 及 `collation_connection` 系统变量值。 +此语句显示与此视图对应的 `CREATE VIEW` 语句,以及创建视图时 `character_set_client` 和 `collation_connection` 系统变量的值。 ```sql +------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+ @@ -38,7 +41,7 @@ show create view v; ### 查询 `INFORMATION_SCHEMA.VIEWS` 表 -示例: +使用示例: {{< copyable "sql" >}} @@ -46,7 +49,7 @@ show create view v; select * from information_schema.views; ``` -通过查询该表可以查看 view 的相关元信息,如 `TABLE_CATALOG`、`TABLE_SCHEMA`、`TABLE_NAME`、`VIEW_DEFINITION`、`CHECK_OPTION`、`IS_UPDATABLE`、`DEFINER`、`SECURITY_TYPE`、`CHARACTER_SET_CLIENT`、`COLLATION_CONNECTION` 等。 +通过查询此表,你可以查看视图的相关元信息,如 `TABLE_CATALOG`、`TABLE_SCHEMA`、`TABLE_NAME`、`VIEW_DEFINITION`、`CHECK_OPTION`、`IS_UPDATABLE`、`DEFINER`、`SECURITY_TYPE`、`CHARACTER_SET_CLIENT` 和 `COLLATION_CONNECTION`。 ```sql +---------------+--------------+------------+------------------------------------------------------------------------+--------------+--------------+----------------+---------------+----------------------+----------------------+ @@ -57,17 +60,17 @@ select * from information_schema.views; 1 row in set (0.00 sec) ``` -### 查询 HTTP API +### 使用 HTTP API -示例: +使用示例: {{< copyable "" >}} -``` +```sql curl http://127.0.0.1:10080/schema/test/v ``` -通过访问 `http://{TiDBIP}:10080/schema/{db}/{view}` 可以得到对应 view 的所有元信息。 +通过访问 `http://{TiDBIP}:10080/schema/{db}/{view}`,你可以获取视图的所有元数据。 ``` { @@ -149,7 +152,7 @@ curl http://127.0.0.1:10080/schema/test/v ## 示例 -以下例子将创建一个视图,并在该视图上进行查询,最后删除该视图。 +以下示例创建一个视图,查询此视图,并删除此视图: {{< copyable "sql" >}} @@ -230,15 +233,15 @@ drop view v; Query OK, 0 rows affected (0.02 sec) ``` -## 局限性 +## 限制 -目前 TiDB 中的视图有以下局限性: +目前,TiDB 中的视图有以下限制: -- 不支持物化视图。 -- TiDB 中视图为只读视图,不支持对视图进行 `UPDATE`、`INSERT`、`DELETE`、`TRUNCATE` 等写入操作。 -- 对已创建的视图仅支持 `DROP` 的 DDL 操作,即 `DROP [VIEW | TABLE]`。 +* 尚不支持物化视图。 +* TiDB 中的视图是只读的,不支持 `UPDATE`、`INSERT`、`DELETE` 和 `TRUNCATE` 等写操作。 +* 对于已创建的视图,唯一支持的 DDL 操作是 `DROP [VIEW | TABLE]` -## 扩展阅读 +## 另请参阅 -- [创建视图](/sql-statements/sql-statement-create-view.md) -- [删除视图](/sql-statements/sql-statement-drop-view.md) +- [CREATE VIEW](/sql-statements/sql-statement-create-view.md) +- [DROP VIEW](/sql-statements/sql-statement-drop-view.md) diff --git a/wrong-index-solution.md b/wrong-index-solution.md index e3744aa920c8..08f68b5f8892 100644 --- a/wrong-index-solution.md +++ b/wrong-index-solution.md @@ -1,67 +1,67 @@ --- -title: 错误索引的解决方案 -summary: 了解如何处理错误索引问题。 +title: 错误索引解决方案 +summary: 了解如何解决错误索引问题。 --- -# 错误索引的解决方案 +# 错误索引解决方案 -在观察到某个查询的执行速度达不到预期时,可能是它的索引使用有误。 +如果你发现某些查询的执行速度未达到预期,可能是优化器选择了错误的索引来执行查询。 -可能造成 TiDB 优化器选择非预期索引的原因包括: +优化器可能选择意外索引的原因有多个: -- **统计信息过时**:优化器依赖统计信息来估算查询成本。如果统计信息过时,可能导致优化器作出次优选择。 -- **统计信息不匹配**:即使统计信息是最新的,也可能无法准确反映数据分布情况,导致成本估算偏差。 -- **成本计算不准确**:当查询的结构复杂或数据分布不均时,优化器有可能会错误地估算使用某个索引的成本。 -- **存储引擎选择不当**:在某些场景下,优化器选择的存储引擎可能不适合当前查询。 -- **函数下推限制**:部分函数或操作无法下推到存储引擎执行,可能会影响查询性能。 +- **统计信息过期**:优化器依赖统计信息来估算查询成本。如果统计信息过期,优化器可能会做出次优选择。 +- **统计信息不匹配**:即使统计信息是最新的,它们可能无法准确反映数据分布,导致成本估算不准确。 +- **成本计算不正确**:由于查询结构复杂或数据分布的原因,优化器可能会错误计算使用索引的成本。 +- **存储引擎选择不当**:在某些情况下,优化器可能会选择对查询不是最优的存储引擎。 +- **函数下推限制**:某些函数或操作可能无法下推到存储引擎,这可能会影响查询性能。 ## 统计信息健康度 -可以先使用[表的健康度信息](/statistics.md#表的健康度信息)来查看统计信息的健康度。根据健康度可以分为以下两种情况处理。 +你可以首先查看统计信息中的[表的健康状态](/statistics.md#health-state-of-tables),然后根据不同的健康状态来解决这个问题。 -### 健康度较低 +### 低健康状态 -这意味着距离 TiDB 上次执行 `ANALYZE` 已经很久了。这时可以先使用 `ANALYZE` 命令对统计信息进行更新。更新之后如果仍在使用错误的索引,可以参考下一小节。 +低健康状态意味着 TiDB 长时间未执行 `ANALYZE` 语句。你可以通过运行 `ANALYZE` 命令来更新统计信息。更新后,如果优化器仍然使用错误的索引,请参考下一节。 -### 健康度接近 100% +### 接近 100% 的健康状态 -这时意味着刚刚结束 `ANALYZE` 命令或者结束后不久。这时可能和 TiDB 对行数的估算逻辑有关。 +接近 100% 的健康状态表明 `ANALYZE` 语句刚刚完成或在不久前完成。在这种情况下,错误索引问题可能与 TiDB 的行数估算逻辑有关。 -对于等值查询,错误索引可能是由 [Count-Min Sketch](/statistics.md#count-min-sketch) 引起的。这时可以先检查是不是这种特殊情况,然后进行对应的处理。 +对于等值查询,原因可能是 [Count-Min Sketch](/statistics.md#count-min-sketch)。你可以检查 Count-Min Sketch 是否是导致问题的原因并采取相应的解决方案。 -如果经过检查发现不是上面的可能情况,可以使用 [Optimizer Hints](/optimizer-hints.md#use_indext1_name-idx1_name--idx2_name-) 中提到的 `USE_INDEX` 或者 `use index` 来强制选择索引。同时也可以使用[执行计划管理](/sql-plan-management.md)中提到的方式来非侵入地更改查询的行为。 +如果上述原因不适用于你的问题,你可以使用 `USE_INDEX` 或 `use index` 优化器提示来强制选择索引(详见 [USE_INDEX](/optimizer-hints.md#use_indext1_name-idx1_name--idx2_name-))。此外,你还可以通过使用[SQL 计划管理](/sql-plan-management.md)以非侵入式的方式改变查询行为。 ### 其他情况 -除去上述情况外,也存在因为数据的更新导致现有所有索引都不再适合的情况。这时就需要对条件和数据分布进行分析,查看是否有新的索引可以加快查询速度,然后使用 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 命令增加新的索引。 +除了上述情况外,错误索引问题也可能是由数据更新导致所有索引不再适用。在这种情况下,你需要对条件和数据分布进行分析,看看是否可以通过新索引来加速查询。如果可以,你可以通过运行 [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) 命令来添加新索引。 ## 统计信息不匹配 -当数据分布特别不均衡时,统计信息可能无法准确反映实际数据分布。此时,可以尝试配置 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 语句的不同选项来提高统计信息的准确性,以更准确地匹配索引。 +当数据分布高度倾斜时,统计信息可能无法准确反映实际数据。在这种情况下,可以尝试配置 [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) 语句的选项。这可能有助于提高统计信息的准确性并更好地匹配索引。 -例如,假设你有一个 `orders` 表,其中 `customer_id` 列上有一个索引,但超过 50% 的订单都具有相同的 `customer_id`。对于该表,统计信息可能无法很好地反映数据分布,从而影响查询性能。 +例如,假设你有一个 `orders` 表,其中有一个 `customer_id` 列的索引,而超过 50% 的订单共享相同的 `customer_id`。在这种情况下,统计信息可能无法很好地表示数据分布,从而影响查询性能。 ## 成本信息 -如需查看执行成本的详细信息,可以在执行 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 和 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句时带上 `FORMAT=verbose` 选项。通过这些信息,可以了解不同执行路径之间的成本差异。 +要查看执行成本的详细信息,你可以使用 `FORMAT=verbose` 选项执行 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 和 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句。根据这些信息,你可以看到不同执行路径之间的成本差异。 ## 引擎选择 -默认情况下,TiDB 会基于成本估算选择使用 TiKV 或 TiFlash 访问数据表。你可以通过配置 Engine 隔离的方式,尝试使用不同的存储引擎执行同一查询。 +默认情况下,TiDB 根据成本估算选择 TiKV 或 TiFlash 进行表访问。你可以通过应用引擎隔离来尝试对同一查询使用不同的引擎。 -更多信息,请参考 [Engine 隔离](/tiflash/use-tidb-to-read-tiflash.md#engine-隔离)。 +更多信息,请参见[引擎隔离](/tiflash/use-tidb-to-read-tiflash.md#engine-isolation)。 ## 函数下推 -为了提升查询性能,TiDB 会将某些函数下推到 TiKV 或 TiFlash 存储引擎中执行。然而,部分函数不支持下推,这可能会限制可用的执行计划,进而影响查询性能。 +为了提高查询性能,TiDB 可以将某些函数下推到 TiKV 或 TiFlash 存储引擎执行。但是,某些函数不支持下推,这可能会限制可用的执行计划,并可能影响查询性能。 -关于支持下推的表达式,请参考 [TiKV 支持的下推计算](/functions-and-operators/expressions-pushed-down.md) 和 [TiFlash 支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md)。 +关于支持下推的表达式,请参见 [TiKV 支持的下推计算](/functions-and-operators/expressions-pushed-down.md)和 [TiFlash 支持的下推计算](/tiflash/tiflash-supported-pushdown-calculations.md)。 -需要注意的是,你也可以禁用特定表达式的下推。更多信息,请参考[优化规则和表达式下推的黑名单](/blocklist-control-plan.md)。 +请注意,你也可以禁用特定表达式的下推。更多信息,请参见[优化规则和表达式下推的黑名单](/blocklist-control-plan.md)。 ## 另请参阅 -- [常规统计信息](/statistics.md) +- [统计信息](/statistics.md) - [索引选择](/choose-index.md) -- [Optimizer Hints](/optimizer-hints.md) -- [执行计划管理 (SPM)](/sql-plan-management.md) \ No newline at end of file +- [优化器提示](/optimizer-hints.md) +- [SQL 计划管理](/sql-plan-management.md)