长期支持版本

    astream使能MySQL测试步骤

    1 环境要求

    1.1 硬件

    要求服务端(server)和客户端(client)各一台。

    ServerClient
    CPUKunpeng 920-6426 * 2Kunpeng 920-6426 * 2
    核数64cores*264cores*2
    主频2600MHz2600MHz
    内存大小16 * 32G Samsung 2666 MHz16 * 32G Samsung 2666 MHz
    网络SP580 10GESP580 10GE
    系统盘1.2T HDD TOSHIBA1.12 HDD TOSHIBA
    数据盘1.6T ES3000 V5 NVMe PCIe SSD*2NA

    1.2 软件

    软件名称版本
    mysql8.0.20
    benchmarksql5.0

    1.3 组网

    2. Server端部署

    2.1 安装mysql依赖包

    yum install -y cmake doxygen bison ncurses-devel openssl-devel libtool tar rpcgen libtirpc-devel bison bc unzip git gcc-c++ libaio libaio-devel numactl
    

    2.2 编译安装mysql

    • 官网下载下载源码包。

    • 下载优化补丁:细粒度锁优化特性补丁NUMA调度补丁无锁优化特性补丁

    • 编译mysql。编译前确保已安装libaio-devel包。

      tar zxvf mysql-boost-8.0.20.tar.gz
      cd mysql-8.0.20/
      patch -p1 < ../0001-SHARDED-LOCK-SYS.patch
      patch -p1 < ../0001-SCHED-AFFINITY.patch
      patch -p1 < ../0002-LOCK-FREE-TRX-SYS.patch
      cd cmake
      make clean
      cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-8.0.20  -DWITH_BOOST=../boost -DDOWNLOAD_BOOST=1
      make -j 64
      make install
      

    2.3 配置mysql参数

    为了使磁盘压力足够大,测试过程中采用mysql双实例跑法。其中实例1对应的配置文件为/etc/my-1.cnf,实例2对应的配置文件为/etc/my-2.cnf。

    • /etc/my-1.cnf
    [mysqld_safe]
    log-error=/data/mysql-1/log/mysql.log
    pid-file=/data/mysql-1/run/mysqld.pid
    
    [client]
    socket=/data/mysql-1/run/mysql.sock
    default-character-set=utf8
    
    [mysqld]
    server-id=3306
    #log-error=/data/mysql-1/log/mysql.log
    #basedir=/usr/local/mysql
    socket=/data/mysql-1/run/mysql.sock
    tmpdir=/data/mysql-1/tmp
    datadir=/data/mysql-1/data
    default_authentication_plugin=mysql_native_password
    port=3306
    user=root
    #innodb_page_size=4k
    
    max_connections=2000
    back_log=4000
    performance_schema=OFF
    max_prepared_stmt_count=128000
    #transaction_isolation=READ-COMMITTED
    #skip-grant-tables
    
    #file
    innodb_file_per_table
    innodb_log_file_size=2048M
    innodb_log_files_in_group=32
    innodb_open_files=10000
    table_open_cache_instances=64
    
    #buffers
    innodb_buffer_pool_size=150G # 根据系统内存大小可调整
    innodb_buffer_pool_instances=16
    innodb_log_buffer_size=2048M
    #innodb_undo_log_truncate=OFF
    
    #tune
    default_time_zone=+8:00
    #innodb_numa_interleave=1
    thread_cache_size=2000
    sync_binlog=1
    innodb_flush_log_at_trx_commit=1
    innodb_use_native_aio=1
    innodb_spin_wait_delay=180
    innodb_sync_spin_loops=25
    innodb_flush_method=O_DIRECT
    innodb_io_capacity=30000
    innodb_io_capacity_max=40000
    innodb_lru_scan_depth=9000
    innodb_page_cleaners=16
    #innodb_spin_wait_pause_multiplier=25
    
    #perf special
    innodb_flush_neighbors=0
    innodb_write_io_threads=24
    innodb_read_io_threads=16
    innodb_purge_threads=32
    
    sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES
    
    #skip_log_bin
    log-bin=mysql-bin # 开启mysql-bin
    binlog_expire_logs_seconds=1800 # 根据需要生成的数据量能够维持长时间运行可调整
    ssl=0
    table_open_cache=30000
    max_connect_errors=2000
    innodb_adaptive_hash_index=0
    
    mysqlx=0
    
    • /etc/my-2.cnf
    [mysqld_safe]
    log-error=/data/mysql-2/log/mysql.log
    pid-file=/data/mysql-2/run/mysqld.pid
    
    [client]
    socket=/data/mysql-2/run/mysql.sock
    default-character-set=utf8
    
    [mysqld]
    server-id=3307
    #log-error=/data/mysql-2/log/mysql.log
    #basedir=/usr/local/mysql
    socket=/data/mysql-2/run/mysql.sock
    tmpdir=/data/mysql-2/tmp
    datadir=/data/mysql-2/data
    default_authentication_plugin=mysql_native_password
    port=3307
    user=root
    #innodb_page_size=4k
    
    max_connections=2000
    back_log=4000
    performance_schema=OFF
    max_prepared_stmt_count=128000
    #transaction_isolation=READ-COMMITTED
    #skip-grant-tables
    
    #file
    innodb_file_per_table
    innodb_log_file_size=2048M
    innodb_log_files_in_group=32
    innodb_open_files=10000
    table_open_cache_instances=64
    
    #buffers
    innodb_buffer_pool_size=150G # 根据系统内存大小可调整
    innodb_buffer_pool_instances=16
    innodb_log_buffer_size=2048M
    #innodb_undo_log_truncate=OFF
    
    #tune
    default_time_zone=+8:00
    #innodb_numa_interleave=1
    thread_cache_size=2000
    sync_binlog=1
    innodb_flush_log_at_trx_commit=1
    innodb_use_native_aio=1
    innodb_spin_wait_delay=180
    innodb_sync_spin_loops=25
    innodb_flush_method=O_DIRECT
    innodb_io_capacity=30000
    innodb_io_capacity_max=40000
    innodb_lru_scan_depth=9000
    innodb_page_cleaners=16
    #innodb_spin_wait_pause_multiplier=25
    
    #perf special
    innodb_flush_neighbors=0
    innodb_write_io_threads=24
    innodb_read_io_threads=16
    innodb_purge_threads=32
    
    sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES
    
    log-bin=mysql-bin
    #skip_log_bin # 开启mysql-bin
    binlog_expire_logs_seconds=1800 # 根据需要生成的数据量能够维持长时间运行可调整
    ssl=0
    table_open_cache=30000
    max_connect_errors=2000
    innodb_adaptive_hash_index=0
    
    mysqlx=0
    

    2.4 部署mysql

    #!/bin/bash
    systemctl stop firewalld
    systemctl disable irqbalance
    echo 3 > /proc/sys/vm/drop_caches
    mysql=mysql-8.0.20
    prepare_mysql_data()
    {
    	umount /dev/nvme0n1
    	rm -rf /data
    	mkfs.xfs /dev/nvme0n1 -f
    	groupadd mysql
    	useradd -g mysql mysql
    	mkdir /data
    	mount /dev/nvme0n1 /data
    	mkdir -p /data/{mysql-1,mysql-2}
    	mkdir -p /data/mysql-1/{data,run,share,tmp,log}
    	mkdir -p /data/mysql-2/{data,run,share,tmp,log}
    	chown -R mysql:mysql /data
    	chown -R mysql:mysql /data/mysql-1
    	chown -R mysql:mysql /data/mysql-2
    	touch /data/mysql-1/log/mysql.log
    	touch /data/mysql-2/log/mysql.log
    	chown -R mysql:mysql /data/mysql-1/log/mysql.log
    	chown -R mysql:mysql /data/mysql-2/log/mysql.log
    }
    init_mysql()
    {
    	/usr/local/$mysql/bin/mysqld --defaults-file=/etc/my.cnf --user=root --initialize
    	/usr/local/$mysql/support-files/mysql.server start
    	sed -i 's/#skip-grant-tables/skip-grant-tables/g' /etc/my.cnf
    	/usr/local/$mysql/support-files/mysql.server restart
    	/usr/local/$mysql/bin/mysql -u root -p123456 <<EOF
    	use mysql;
    	Select * from user where user='root' \G;
    	update user set password_expired='N' where user='root';
    	flush privileges;
    	alter user 'root'@'localhost' identified by '123456';
    	flush privileges;
    	update user set host='%' where user='root';
    	flush privileges;
    	create database tpcc;
    	quit
    EOF
    	sed -i 's/skip-grant-tables/#skip-grant-tables/g' /etc/my.cnf
    	/usr/local/$mysql/support-files/mysql.server restart
    }
    prepare_mysql_data
    init_mysql
    

    3. client部署benchmarksql工具

    3.1 benchmarksql安装

    下载 benchmarksql工具

    #安装benchmarksql依赖包
    yum install -y java
    
    unzip benchmarksql5.0-for-mysql.zip
    cd benchmarksql5.0-for-mysql/run
    chmod +x *.sh
    

    3.2 配置benchmarksql参数

    打开配置文件benchmarksql5.0-for-mysql/run/props.conf,配置如下:

    db=mysql
    driver=com.mysql.cj.jdbc.Driver
    conn=jdbc:mysql://192.168.1.10:3306/tpcc?useSSL=false&useServerPrepStmts=true&useConfigs=maxPerformance&rewriteBatchedStatements=true
    user=root
    password=123456
    profile=/etc/my-1.cnf
    
    warehouses=4050
    loadWorkers=100
    terminals=330
    terminalWarehouseFixed=true
    runMins=720
    
    runTxnsPerTerminal=0
    limitTxnsPerMin=1000000000
    newOrderWeight=45
    paymentWeight=43
    orderStatusWeight=4
    deliveryWeight=4
    stockLevelWeight=4
    

    当前目录下再复制一个props.conf文件,重命名为props-2.conf,作为mysql实例2对应的配置文件。

    db=mysql
    driver=com.mysql.cj.jdbc.Driver
    conn=jdbc:mysql://192.168.1.10:3307/tpcc?useSSL=false&useServerPrepStmts=true&useConfigs=maxPerformance&rewriteBatchedStatements=true
    user=root
    password=123456
    profile=/etc/my-2.cnf
    
    warehouses=4050
    loadWorkers=100
    terminals=330
    terminalWarehouseFixed=true
    runMins=720
    
    runTxnsPerTerminal=0
    limitTxnsPerMin=1000000000
    newOrderWeight=45
    paymentWeight=43
    orderStatusWeight=4
    deliveryWeight=4
    stockLevelWeight=4
    

    其中,warehouses的值根据当前 NVMe SSD 磁盘规格进行设定,然后生成一份warehouses=4050的数据作为每个mysql实例的操作数据。总的原则是:拷贝两份生成的数据分别作为两个mysql实例的操作数据,同时两份数据的总大小占磁盘空间的60%-70%,以便在经过720min的长稳运行后,磁盘空间的利用率能够达到90%以上。

    3.3 创建mysql测试数据

    #启动服务
    /usr/local/mysql-8.0.20/support-files/mysql.server start
    
    #创建测试数据(完成测试数据创建后,建议对server端/data/mysql-1/data下数据进行备份,之后测试,数据从此拷贝即可)
    ./runDatabaseBuild.sh props.conf
    
    #停止数据库
    /usr/local/mysql-8.0.20/support-files/mysql.server stop
    

    3.4 数据转储备用盘

    创建mysql数据之后,我们保存该份数据到备用盘/dev/nvme1n1,假设挂载目录为/bak。

    cp -r /data/mysql-1/data/* /bak 
    

    4 配置执行环境

    4.1 开启STEAL优化

    服务端开启STEAL优化,最大化提高mysql测试时的CPU利用率,提高CPU效率。

    /etc/grub2-efi.cfg文件中,系统启动项添加参数sched_steal_node_limit=4,reboot重启生效。

    重启后,设置开启STEAL模式即可。

    echo STEAL > /sys/kernel/debug/sched_features
    

    4.2 关闭测试影响项

    #关闭irqbalance
    systemctl stop irqbalance.service
    systemctl disable irqbalance.service
    
    #关闭防火墙
    systemctl stop iptables
    systemctl stop firewalld
    

    4.3 网卡中断绑核

    #服务端绑中断(根据环境替换网卡名称、绑核cpu核)
    ethtool -L enp4s0 combined 6
    irq1=`cat /proc/interrupts| grep -E enp4s0 | head -n5 | awk -F ':' '{print $1}'`
    cpulist=(61 62 63 64 65 66) ## 自行根据环境调整为需要固定处理网卡中断请求的核
    c=0
    for irq in $irq1
    do
    echo ${cpulist[c]} "->" $irq
    echo ${cpulist[c]} > /proc/irq/$irq/smp_affinity_list
    let "c++"
    done
    

    4.4 安装nvme-cli工具

    nvme-cli是一个用于监控和配置管理NVMe设备的命令行工具。可用于开启NVMe SSD多流功能以及通过log相关的命令获取控制器的各类日志记录等功能。

    yum install nvme-cli
    

    4.5 开启NVMe 磁盘的多流特性

    • 查询NVMe SSD磁盘当前的多流使能情况。

      nvme dir-receive /dev/nvme0n1 -n 0x1 -D 0 -O 1 -H
      

      回显结果表示,当前NVMe SSD支持Stream Directive,即支持开启多流特性,当前的状态为关闭状态。

    • 启用多流功能。

      modprobe -r nvme
      modprobe nvme-core streams=1
      modprobe nvme
      
    • 再次查询NVMe SSD磁盘当前的多流使能情况。

      回显结果表示,当前NVMe SSD已开启多流特性。

    4.6 mysql双实例数据准备

    为了统一基线测试和多流测试的流程,每次测试前格式化磁盘,统一从/bak目录下拷贝两份数据到两个mysql实例的对应数据目录下。

    prepare_mysql_data()
    {
    	umount /dev/nvme0n1
    	rm -rf /data
    	mkfs.xfs /dev/nvme0n1 -f
    	mkdir /data
    	mount /dev/nvme0n1 /data
    	mkdir -p /data/{mysql-1,mysql-2}
    	mkdir -p /data/mysql-1/{data,run,share,tmp,log}
    	mkdir -p /data/mysql-2/{data,run,share,tmp,log}
    	chown -R mysql:mysql /data
    	chown -R mysql:mysql /data/mysql-1
    	chown -R mysql:mysql /data/mysql-2
    	touch /data/mysql-1/log/mysql.log
    	touch /data/mysql-2/log/mysql.log
    	chown -R mysql:mysql /data/mysql-1/log/mysql.log
    	chown -R mysql:mysql /data/mysql-2/log/mysql.log
    }
    
    prepare_mysql_data()
    # 格式化后,创建mysql双实例对应的数据目录,即可启动astream
    astream -i /data/mysql-1/data /data/mysql-2/data -r rule1.txt rule2.txt#  ---->该步骤测试基线时请去掉
    cp -r /bak/* /data/mysql-1/data
    cp -r /bak/* /data/mysql-2/data
    

    然后,查看待测磁盘/dev/nvme0n1的空间占用率情况(df -h)是否在60%-70%左右即可。

    4.7 绑核启动mysql服务

    #启动mysql双实例
    numactl -C 0-60 -i 0-3  /usr/local/bin/mysqld --defaults-file=/etc/my-1.cnf &
    numactl -C 67-127 -i 0-3  /usr/local/bin/mysqld --defaults-file=/etc/my-2.cnf &
    

    4.8 设置定时任务

    拷贝数据或生成数据成功后,在执行mysql测试前,为了衡量磁盘的写放大水平,在12小时(720mins)的测试过程中,每隔1小时利用定时器crontab执行计算磁盘WA的脚本calculate_wa.sh

    #!/bin/bash
    
    source /etc/profile
    source ~/.bash_profile
    
    BASE_PATH=$(cd $(dirname $0);pwd)
    diskName=$1
    
    echo 0x`/usr/bin/nvme get-log /dev/${diskName}n1 -i 0xc0 -n 0xffffffff -l 800|grep "01c0:"|awk '{print $13$12$11$10$9$8$7$6}'` >> ${BASE_PATH}/host_tmp
    echo 0x`/usr/bin/nvme get-log /dev/${diskName}n1 -i 0xc0 -n 0xffffffff -l 800|grep "01d0:"|awk '{print $9$8$7$6$5$4$3$2}'` >> ${BASE_PATH}/gc_tmp
    
    # IO write counts,unit:4K #
    hostWriteHexSectorTemp=`tail -1 ${BASE_PATH}/host_tmp`
    # GC write counts,unit 4k #
    gcWriteHexSectorTemp=`tail -1 ${BASE_PATH}/gc_tmp`
    hostWriteDecSectorTemp=`printf "%llu" ${hostWriteHexSectorTemp}`
    gcWriteDecSectorTemp=`printf "%llu" ${gcWriteHexSectorTemp}`
    preHostValue=`tail -2 ${BASE_PATH}/host_tmp|head -1`
    preGcValue=`tail -2 ${BASE_PATH}/gc_tmp|head -1`
    preHostValue=`printf "%llu" ${preHostValue}`
    preGcValue=`printf "%llu" ${preGcValue}`
    
    # IO write counts for a period of time
    hostWrittenSector=$(echo ${hostWriteDecSectorTemp}-${preHostValue} | bc -l)
    # Gc write counts for a period of time
    gcWrittenSector=$(echo ${gcWriteDecSectorTemp}-${preGcValue} | bc -l)
    nandSector=$(echo ${hostWrittenSector}+${gcWrittenSector} | bc -l)
    
    # unit from kB->MB
    hostWrittenMB=$((${hostWrittenSector}/256))
    nandWrittenMB=$((${nandSector}/256))
    
    # compute the WA
    WA=$(echo "scale=5;${nandSector}/${hostWrittenSector}" | bc)
    echo $nandWrittenMB $hostWrittenMB $WA >> ${BASE_PATH}/result_WA.txt
    

    可执行crontab -e,加入每隔1小时执行脚本命令的定时任务,命令如下:

    0 */1 * * * bash  /root/calculate_wa.sh nvme0
    

    若所测的NVMe磁盘盘符名为/dev/nvme0n1,则定时任务中脚本的参数传入nvme0即可。

    4.9 启动mysql双实例测试

    执行测试前,确保已使能NVMe SSD磁盘的多流特性。

    客户端工具根目录下执行测试如下:

    cd benchmarksql5.0-for-mysql
    ./runBenchmark.sh props.conf
    ./runBenchmark.sh props-2.conf
    

    4.10 停止astream进程

    本步骤测试基线时无需操作,若测试多流结束后,执行如下命令停止astream进程:

    astream stop
    

    5 测试结果

    使用定时器脚本的结果,在脚本所在目录的result_WA.txt下输出。每次测试结束后,从中选择最近12条非0数据即可。

    当磁盘有数据写入时,result_WA.txt中每一行有三个值,其意义如下:

    • 1小时内磁盘实际写入的数据量。
    • 1小时内主机提交的写入量。
    • 当前的磁盘WA,根据附录中的公式即可算出每个小时内磁盘的WA水平。

    当前实测,在使用astream情况下,mysql长稳运行后期,NVMe SSD磁盘稳定保持12%的WA下降幅度,即性能较前提升12%

    6 附录

    写入放大(又称写放大,英语:Write amplification,简称WA)是闪存和固态硬盘(SSD)中一种不良的现象,即磁盘实际写入的数据量是写入数据量的多倍。其公式为:

    $$WA=\frac{磁盘实际写入的数据量}{主机提交的写入数据量}$$

    一般来说,随着数据的存储以及磁盘的碎片化愈演愈烈,WA的值将越来越大,如果WA的值能够延迟升高,那么将有助于延长磁盘的使用寿命。

    文档捉虫

    “有虫”文档片段

    问题描述

    提交类型 issue

    有点复杂...

    找人问问吧。

    PR

    小问题,全程线上修改...

    一键搞定!

    问题类型
    规范和低错类

    ● 错别字或拼写错误;标点符号使用错误;

    ● 链接错误、空单元格、格式错误;

    ● 英文中包含中文字符;

    ● 界面和描述不一致,但不影响操作;

    ● 表述不通顺,但不影响理解;

    ● 版本号不匹配:如软件包名称、界面版本号;

    易用性

    ● 关键步骤错误或缺失,无法指导用户完成任务;

    ● 缺少必要的前提条件、注意事项等;

    ● 图形、表格、文字等晦涩难懂;

    ● 逻辑不清晰,该分类、分项、分步骤的没有给出;

    正确性

    ● 技术原理、功能、规格等描述和软件不一致,存在错误;

    ● 原理图、架构图等存在错误;

    ● 命令、命令参数等错误;

    ● 代码片段错误;

    ● 命令无法完成对应功能;

    ● 界面错误,无法指导操作;

    风险提示

    ● 对重要数据或系统存在风险的操作,缺少安全提示;

    内容合规

    ● 违反法律法规,涉及政治、领土主权等敏感词;

    ● 内容侵权;

    您对文档的总体满意度

    非常不满意
    非常满意
    提交
    根据您的反馈,会自动生成issue模板。您只需点击按钮,创建issue即可。
    文档捉虫
    编组 3备份