GreatSQL性能优化
硬件、操作系统优化
1. 服务器配置及优化
如果是在物理机上运行GreatSQL数据库,建议至少采用如下配置等级:
配置 | 要求 |
---|---|
CPU | 8 cores+ |
内存 | 8 GB+ |
磁盘 | 100 GB+ |
网络 | 千兆网络 |
如果想要支撑更高数据库服务能力,应当进一步提升服务器配置,包括且不仅限以下几点:
1.配置更高性能的CPU,不仅是核数越多越好,处理主频也是越高越好。
2.配置更大物理内存。
3.配置更高物理IOPS性能的设备,例如用NVMe SSD。使用更好的物理I/O设备,相比提升物理内存综合成本通常更低。
4.如果是X86架构的CPU,通常建议关闭NUMA;如果是ARM架构,则可以开启NUMA。MySQL/GreatSQL数据库是单进程多线程模式,如果是是运行单实例的场景下,没必要开启NUMA;如果是运行多实例,则可以开启NUMA以提升性能。
5.调整CPU设置,修改为最大性能模式。
6.如果计划构建MGR集群,则通常要使用不低于千兆网络的条件,如果有条件甚至可以使用万兆网络,或者InfiniBand网络。
2. 操作系统层优化
1.采用XFS文件系统,以保证在高I/O负载情况下IOPS的性能及稳定性。
2.修改数据库分区的I/O Scheduler,设置为 noop / deadline。
3.关闭SWAP。运行数据库服务建议配置足够的物理内存。如果内存不足,不建议使用SWAP作为缓冲,因为这会降低性能。建议永久关闭系统SWAP。
4.关闭透明大页(Transparent Huge Pages / THP)。OLTP型数据库内存访问模式通常是稀疏的而非连续的。当高阶内存碎片化比较严重时,分配 THP 页面会出现较高的延迟,反而影响性能。
5.调整mysql用户使用资源上限,避免报告文件数不够等限制错误。
6.其他内核参数优化。
GreatSQL数据库层的优化
通常情况下,运行GreatSQL数据库时,采用 这份my.cnf 参考就足够了。
#
# my.cnf example for GreatSQL
# last update, 2021/8/20
#
# 下面参数选项设置仅作为参考,且假设服务器可用内存为256G
#
[client]
socket = /data/GreatSQL/mysql.sock
[mysql]
loose-skip-binary-as-hex
prompt="(\\D)[\\u@GreatSQL][\\d]>"
no-auto-rehash
[mysqld]
user = mysql
port = 3306
server_id = 3306
basedir = /usr/
datadir = /data/GreatSQL
socket = /data/GreatSQL/mysql.sock
pid-file = mysql.pid
character-set-server = UTF8MB4
skip_name_resolve = 1
#若你的MySQL数据库主要运行在境外,请务必根据实际情况调整本参数
default_time_zone = "+8:00"
#performance setttings
lock_wait_timeout = 3600
open_files_limit = 65535
back_log = 1024
max_connections = 1024
max_connect_errors = 1000000
table_open_cache = 2048
table_definition_cache = 2048
thread_stack = 512K
sort_buffer_size = 4M
join_buffer_size = 4M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
thread_cache_size = 768
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 96M
max_heap_table_size = 96M
#log settings
log_timestamps = SYSTEM
log_error = /data/GreatSQL/error.log
log_error_verbosity = 3
slow_query_log = 1
log_slow_extra = 1
slow_query_log_file = /data/GreatSQL/slow.log
long_query_time = 0.01
log_queries_not_using_indexes = 1
log_throttle_queries_not_using_indexes = 60
min_examined_row_limit = 100
log_slow_admin_statements = 1
log_slow_slave_statements = 1
log_slow_verbosity = FULL
log_bin = /data/GreatSQL/binlog
binlog_format = ROW
sync_binlog = 1
binlog_cache_size = 4M
max_binlog_cache_size = 6G
max_binlog_size = 1G
binlog_rows_query_log_events = 1
binlog_expire_logs_seconds = 604800
binlog_checksum = CRC32
gtid_mode = ON
enforce_gtid_consistency = TRUE
#myisam settings
key_buffer_size = 32M
myisam_sort_buffer_size = 128M
#replication settings
relay_log_recovery = 1
slave_parallel_type = LOGICAL_CLOCK
#并行复制线程数可以设置为逻辑CPU数量的2倍
slave_parallel_workers = 64
binlog_transaction_dependency_tracking = WRITESET
slave_preserve_commit_order = 1
slave_checkpoint_period = 2
#启用InnoDB并行查询优化功能
loose-force_parallel_execute = OFF
#设置每个SQL语句的并行查询最大并发度
loose-parallel_default_dop = 8
#设置系统中总的并行查询线程数,可以和最大逻辑CPU数量一样
loose-parallel_max_threads = 64
#并行执行时leader线程和worker线程使用的总内存大小上限,可以设置物理内存的5-10%左右
loose-parallel_memory_limit = 12G
#mgr settings
loose-plugin_load_add = 'mysql_clone.so'
loose-plugin_load_add = 'group_replication.so'
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1"
#MGR本地节点IP:PORT,请自行替换
loose-group_replication_local_address = "172.16.16.10:33061"
#MGR集群所有节点IP:PORT,请自行替换
loose-group_replication_group_seeds = '172.16.16.10:33061,72.16.16.12:33061,72.16.16.12:33061'
loose-group_replication_start_on_boot = ON
loose-group_replication_bootstrap_group = OFF
loose-group_replication_exit_state_action = READ_ONLY
loose-group_replication_flow_control_mode = "DISABLED"
loose-group_replication_single_primary_mode = ON
loose-group_replication_majority_after_mode = ON
loose-group_replication_communication_max_message_size = 10M
loose-group_replication_arbitrator = 0
loose-group_replication_single_primary_fast_mode = 1
loose-group_replication_request_time_threshold = 100
loose-group_replication_primary_election_mode = GTID_FIRST
loose-group_replication_unreachable_majority_timeout = 30
loose-group_replication_member_expel_timeout = 5
loose-group_replication_autorejoin_tries = 288
report_host = "172.16.16.10"
#innodb settings
innodb_buffer_pool_size = 16G
innodb_buffer_pool_instances = 8
innodb_data_file_path = ibdata1:12M:autoextend
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 32M
innodb_log_file_size = 2G
innodb_log_files_in_group = 3
innodb_doublewrite_files = 2
innodb_max_undo_log_size = 4G
# 根据您的服务器IOPS能力适当调整
# 一般配普通SSD盘的话,可以调整到 10000 - 20000
# 配置高端PCIe SSD卡的话,则可以调整的更高,比如 50000 - 80000
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_open_files = 65534
innodb_flush_method = O_DIRECT
innodb_lru_scan_depth = 4000
innodb_lock_wait_timeout = 10
innodb_rollback_on_timeout = 1
innodb_print_all_deadlocks = 1
innodb_online_alter_log_max_size = 4G
innodb_print_ddl_logs = 1
innodb_status_file = 1
innodb_status_output = 0
innodb_status_output_locks = 1
innodb_sort_buffer_size = 64M
#innodb monitor settings
innodb_monitor_enable = "module_innodb"
innodb_monitor_enable = "module_server"
innodb_monitor_enable = "module_dml"
innodb_monitor_enable = "module_ddl"
innodb_monitor_enable = "module_trx"
innodb_monitor_enable = "module_os"
innodb_monitor_enable = "module_purge"
innodb_monitor_enable = "module_log"
innodb_monitor_enable = "module_lock"
innodb_monitor_enable = "module_buffer"
innodb_monitor_enable = "module_index"
innodb_monitor_enable = "module_ibuf_system"
innodb_monitor_enable = "module_buffer_page"
innodb_monitor_enable = "module_adaptive_hash"
#pfs settings
performance_schema = 1
#performance_schema_instrument = '%memory%=on'
performance_schema_instrument = '%lock%=on'
下面针对其中的几个关键参数选项稍作解读:
- no-auto-rehash mysql客户端登入时,不读取全部metadata,避免影响性能以及产生MDL等待。
- skip_name_resolve = 1 不进行DNS反解析,提高用户端连接性能。
- default_time_zone = "+8:00" 显示指定时区,避免频繁调用时区转换函数,提升性能。请务必根据实际情况调整本参数。
- lock_wait_timeout = 3600 限制表级锁、MDL锁、备份锁等最大等待时长。
- log_error_verbosity = 3 设置为3可以记录更多日志信息,便于问题分析排查。
- slave_parallel_type = LOGICAL_CLOCK
- slave_parallel_workers = 64 采用LOGICAL_CLOCK模式,并行复制线程数最高可以设置为逻辑CPU数量的2倍,提高SQL线程应用事务的并行效率。
- binlog_transaction_dependency_tracking = WRITESET 采用WRITESET模式提高从节点事务并行回放度。
- slave_preserve_commit_order = 1 从节点回放事务时,要保证事务顺序,避免和主节点数据不一致。
- loose-force_parallel_execute = OFF 启用InnoDB并行查询优化功能。
- loose-parallel_default_dop = 8 设置每个SQL语句的并行查询最大并发度。
- loose-parallel_max_threads = 64 设置系统中总的并行查询线程数,可以和最大逻辑CPU数量一样。
- loose-parallel_memory_limit = 12G 并行执行时leader线程和worker线程使用的总内存大小上限,可以设置物理内存的5-10%左右
- loose-group_replication_flow_control_mode = "DISABLED" 关闭MySQL原生的MGR流控模式,因为其作用不大。
- loose-group_replication_majority_after_mode = ON 在AFTER模式下,当发生个别节点异常时,只要多数派达成一致即可,不会导致整个MGR都被hang住。
- loose-group_replication_communication_max_message_size = 10M 设置MGR通信消息分片,避免一次性发送消息太大,导致网络拥塞,影响MGR性能。
- loose-group_replication_single_primary_fast_mode = 1 启用快速单主模式。
- loose-group_replication_request_time_threshold = 100 记录因MGR通信超过阈值的事件,便于后续检查确认MGR通信性能是否存在瓶颈。
- loose-group_replication_primary_election_mode = GTID_FIRST 设置MGR选主模式为GTID_FIRST,在发生主节点切换时,会优先选择事务应用效率最高的那个节点。
- innodb_io_capacity = 4000
- innodb_io_capacity_max = 8000 配置高端PCIe SSD卡的话,则可以调整的更高,比如 50000 - 80000
- innodb_thread_concurrency = 0 不限制InnoDB并行线程数,使其发挥最大性能。但如果业务端发起的业务请求并行度总是超过服务器逻辑CPU数,则可能导致CPU调度频繁等待,此时可以考虑将本选项设置为逻辑CPU的数量。
对GreatSQL进行性能测试
1. 压测工具
优先推荐使用 sysbench工具(https://github.com/akopytov/sysbench) 进行性能测试。
如果想要测试GreatSQL的InnoDB并行查询特性,则可以使用 tpch工具(https://www.tpc.org/tpch/)。
本文以侧重OLTP场景下的性能测试为例,因此推荐使用sysbench工具。
2. 压测模式
sysbench默认支持以下几种OLTP测试方案:
- oltp_delete
- oltp_insert
- oltp_point_select
- oltp_read_only
- oltp_read_write
- oltp_update_index
- oltp_update_non_index
- oltp_write_only
如果有条件,可以把这几种方案全部跑一遍。
3. 压测参数及建议
压测的目的通常是想找到数据库运行时的性能瓶颈,以及在不断摸索调整参数选项,采用何种设置模式下其性能表现最好。
只有个别时候的压测是为了找到服务器硬件或者数据库的运行极限值,看看在什么情况下能把硬件或数据库"压死"。
不同服务器配置等级,对应不同的压力测试值。
对于压测参数,有几个建议:
1.并发线程数,可以分别是逻辑CPU数的1/8、1/4、1/2以及跑满。
2.数据库的innodb_buffer_pool_size通常设置不超过物理内存的50%。
3.测试表个数通常不低于逻辑CPU数的1/2。
4.测试数据库物理大小通常不低于innodb_buffer_pool_size,因为生产环境中的业务数据量基本上都是大于物理内存的。
5.如果本意就是想测试数据库在非物理I/O为瓶颈场景下的性能表现,则可以减少测试数据量,让数据尽可能加载到buffer pool中。
6.运行sysbench压测客户机和数据库服务器分开,不要在同一个物理环境内,避免因为sysbench本身也产生性能损耗而影响数据库的性能表现。
7.单轮测试时长通常不低于10分钟。
8.每轮测试结束后,预留足够间隔时长,让数据库将所有脏数据、日志都有充分时间刷到磁盘,服务器趋于空负载后再次下一轮压测。
9.每轮测试开始前,最好能先进行数据预热,即先运行一小段时间压测,让热点数据都加载到buffer pool中之后再正式开始压测。
10.每轮测试结束后,最好清空所有数据,在下一轮新的测试开始前,重新初始化填充数据。
下面是我常用的sysbench压测参数供参考:
sysbench /usr/local/share/sysbench/oltp_read_write.lua \
...
--tables=64 \
--table_size= 10000000 \
--threads=128 \
--rand-type=uniform \
--report-interval=1 \
--db-ps-mode=disable \
--mysql-ignore-errors=all \
--time=900 run
sysbench默认支持以下几种OLTP测试方案:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2022-05-10 K8s 上的分布式存储集群搭建(Rook/ceph)
2021-05-10 frpc穿透报错 日志显示 http: proxy error: no such domain 解决办法
2021-05-10 win7通过netsh命令禁用、启用本地连接 定时关闭开启网络连接