MySQL 常用配置变量-max_length_for_sort_data

本文深入解析MySQL中的排序算法,包括单路排序和双路排序的工作原理及应用场景。探讨max_length_for_sort_data和max_sort_length变量如何影响排序过程,以及如何通过调整这些参数优化查询性能。

控制 MySQL 排序的最大字段定义的列总字节长度

  • mysql 有两种文件排序算法(双路排序和单路排序),如果需要排序的列的总大小加上 order by 列的大小超过了max_length_for_sort_data 定义的字节,mysql 就会使用双路排序,当任何需要的列(包含结果集列和 order by 的列)包含text、blob 列时,也会使用双路排序,(可以使用 subsstring()把这些列转化为可以单路排序的列)。
  • 可以通过改变 max_length_for_sort_data 变量的值来影响mysql 选择的算法。因为单路排序要将排序的每一行创建固定的缓冲区,varchar 列的最大长度是 max_length_for_sort_data规定的值,而不是排序数据的实际大小(5.7.x 版本中对排序做了优化,分配排序缓冲时针对变长列可以根据数据实际占用的大小来分配内存)。
  • 当 MySQl 不得不对 text、blob 列进行排序时,它只会使用前缀并忽略剩余的值,这是因为不得不分配固定大小的结构来容纳数据并且从外部存储中将前缀拷贝回结构中,可以使用max_sort_length 定义前缀应该是多大。
  • mysql 并不能查看某个查询执行时内部使用的是哪种算法,如果增大了 max_length_for_sort_data 的值,并且磁盘使用率上升,cpu 使用率下降,Sort_merge_passes 的值比以前增加的更快,也许该强制排序使用单路排序算法。* 双路排序:读取行指针和 order by 列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出。双路排序的开销可能会非常巨大,因为他会读取表两次,第二次读取会引发大量的随机 I/O,对于 MyISAM 涞说,这个代价尤其昂贵,MyISAM 表利用系统调用去提取每行的数据。

    * 单路排序:读取查询需要的所有列,按照 order by 列对他们进行排序,然后扫描排序后的列表进行输出,它的效率更快一些,避免了第二次读取数据。并且把随机 I/O 变成了顺序 I/O,但是它会使用更多的内存空间,因为它把排序需要的所有列都一次性度的去出来保存在内存中了。

  • 全局,会话,动态变量,整型值,单位为字节,取值范围4~8388608 字节,默认值为 1024 字节。
一键安装mysql脚本#!/bin/bash# # 要用root用户 ## #获取本机的ip地址,然后将这个ip地址设置为环境变量ipaddr的值 export ipaddr=`ip a | grep -w inet | grep -v 127| awk '{ print $2 }' |awk -F '/' '{print $1}'` #将本机的ip地址的第三第四位合在一起,然后赋予给环境变量serverid,加入本机ip为10.192.168.178,那么serverid=168178 export serverid=`echo $ipaddr | awk -F '.' '{print $3$4}'` #以下这一段是为了求得机器的内存是多少。dmidecode -t 17是获取系统内存相关信息,并把这个值赋予给MEM_SIZE这个环境变量 export UNIT=`dmidecode -t 17|grep -i size |grep -i GB|wc -l` if [[ $UNIT -eq 0 ]]; then export MEM_SIZE=`dmidecode -t 17|grep -i size |grep -v 'No'|awk '{sum+=$2;}END{print sum;}'` else export SIZE=`dmidecode -t 17|grep -i size |grep -v 'No'|awk '{sum+=$2;}END{print sum;}'` export MEM_SIZE=$(($SIZE*1024)) fi # 物理内存等于虚拟内存除以2,并把这个值赋予给buffer这个环境变量 export buffer=$(($MEM_SIZE/2)) # 密码需要修改 export pwd=yourpassword export rplpwd=yourpassword #统计一下 系统中装有mariadb-libs的数量 mariadbcheck=`rpm -qa|grep mariadb-libs|wc -l` #如果统计值后发现mariadb-libs的数量等于1,说明系统里装了mariadb-libs,那么我就要用yum remove删除他 if [[ $mariadbcheck -eq 1 ]]; then yum remove -y mariadb-libs fi #解压/opt 目录下的 mysql-8.0.13-linux-glibc2.12-x86_64.tar.xz 文件,并将解压过程中的输出信息重定向到 /dev/null ,这意味着不会在终端显示解压的详细过程和输出。 #tar 是用于打包和解包文件的命令。-J 表示使用 xz 格式进行解压缩。-x 表示解包。-v 表示显示详细信息。-f 后跟要操作的文件。 tar -Jxvf /opt/mysql-8.0.13-linux-glibc2.12-x86_64.tar.xz >/dev/null mv /opt/mysql-8.0.13-linux-glibc2.12-x86_64/* /usr/local/mysql/ chown -R mysql:mysql /usr/local/mysql/ cp /usr/local/mysql/bin/* /usr/bin/ #检查是否存在/etc/my.cnf个文件,如果存在那么就以当天日期重命名这个文件然后备份为bak,例如my.cnf.20240905140424.bak if [ -s /etc/my.cnf ]; then mv /etc/my.cnf /etc/my.cnf.`date +%Y%m%d%H%M%S`.bak fi #创建一个新的/etc/my.cnf文件,然后将以下内容写进去,直至遇到EOF这个标识符,EOF之后的内容就别写进去了 cat >/etc/my.cnf <<EOF [mysqld] read_only = 0 show_compatibility_56 = 1 port = 3306 server_id = $serverid user = mysql basedir = /usr/local/mysql datadir = /vdb/mysql/data socket = /vdb/mysql/tmp/mysql.sock tmpdir = /vdb/mysql/tmp character_set_server = utf8mb4 transaction_isolation = READ-COMMITTED event_scheduler = 1 default-time-zone = "+8:00" log_timestamps = SYSTEM explicit_defaults_for_timestamp = 1 secure_file_priv = "" skip_slave_start = 1 skip_name_resolve = 1 skip_external_locking = 1 lower_case_table_names = 1 default_storage_engine = InnoDB disabled_storage_engines = ARCHIVE,BLACKHOLE,EXAMPLE,FEDERATED,MEMORY,MERGE,NDB # connection # lock_wait_timeout = 1800 max_connections = 3000 max_connect_errors = 1000000 interactive_timeout = 1800 wait_timeout = 1800 # session memory setting # read_buffer_size = 8M read_rnd_buffer_size = 8M sort_buffer_size = 2M tmp_table_size = 64M join_buffer_size = 64M max_heap_table_size = 64M max_allowed_packet = 64M # cache config # key_buffer_size = 16M table_definition_cache = 2000 table_open_cache = 2000 table_open_cache_instances = 8 query_cache_type = 0 query_cache_size = 0 thread_cache_size = 200 open_files_limit = 65536 binlog_cache_size = 1M max_binlog_cache_size = 512M # log config # log_bin = /vdb/mysql/binlog/mysql-bin binlog_format = row sync_binlog = 1 binlog_error_action = ABORT_SERVER max_binlog_size = 250M binlog_rows_query_log_events = 1 expire_logs_days = 7 log_bin_trust_function_creators = 1 log_slave_updates = 1 relay_log = /vdb/mysql/binlog/mysql-relay relay_log_recovery = 1 master_info_repository = TABLE relay_log_info_repository = TABLE log_error = /vdb/mysql/logs/error.log slow_query_log = 1 slow_query_log_file = /vdb/mysql/logs/slow.log long_query_time = 5 log_queries_not_using_indexes = 1 log_slow_admin_statements = 1 log_slow_slave_statements = 1 log_throttle_queries_not_using_indexes = 10 min_examined_row_limit = 100 # innodb settings # innodb_data_home_dir = /vdb/mysql/data innodb_log_group_home_dir = /vdb/mysql/data innodb_file_per_table = 1 innodb_data_file_path = ibdata1:1G:autoextend innodb_flush_log_at_trx_commit = 1 innodb_buffer_pool_size = ${buffer}M innodb_buffer_pool_instances = 8 innodb_buffer_pool_load_at_startup = 1 innodb_buffer_pool_dump_at_shutdown = 1 innodb_buffer_pool_dump_pct = 25 innodb_lock_wait_timeout = 10 innodb_io_capacity = 10000 innodb_io_capacity_max = 20000 innodb_max_dirty_pages_pct = 60 innodb_flush_method = O_DIRECT innodb_log_file_size = 2G innodb_log_files_in_group = 2 innodb_log_buffer_size = 64M innodb_purge_threads = 2 innodb_write_io_threads = 16 innodb_read_io_threads = 16 innodb_large_prefix = 1 innodb_thread_concurrency = 64 innodb_print_all_deadlocks = 1 innodb_strict_mode = 1 innodb_sort_buffer_size = 32M innodb_stats_persistent_sample_pages = 64 innodb_autoinc_lock_mode = 2 innodb_online_alter_log_max_size = 1G innodb_open_files = 4096 innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:20G # undo config # innodb_rollback_segments = 128 innodb_undo_log_truncate = 1 innodb_max_undo_log_size = 4G # GTID # gtid_mode = ON enforce_gtid_consistency = 1 binlog_gtid_simple_recovery = 1 # MTS # slave_parallel_type = LOGICAL_CLOCK slave_parallel_workers = 16 slave_preserve_commit_order = ON slave_rows_search_algorithms = 'INDEX_SCAN,HASH_SCAN' # SEMISYNC # plugin-load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so" rpl_semi_sync_master_enabled = 1 rpl_semi_sync_slave_enabled = 1 rpl_semi_sync_master_timeout = 60000 #1min rpl_semi_sync_master_wait_for_slave_count = 1 rpl_semi_sync_master_wait_no_slave = 0 # Performance Schema Config # performance-schema-instrument = 'wait/lock/metadata/sql/mdl=ON' performance-schema-instrument = 'memory/%=COUNTED' # Other # innodb_numa_interleave = 1 [mysqldump] quick max_allowed_packet = 2G log-error = /vdb/mysql/logs/dump.log net_buffer_length = 8K [mysqladmin] default-character-set = utf8mb4 socket = /vdb/mysql/tmp/mysql.sock [client] port = 3306 socket = /vdb/mysql/tmp/mysql.sock [mysql] prompt = [\\u@\\h][\\d]:\\_ default-character-set = utf8mb4 no-auto-rehash EOF #这里用的是>>,是追加新内容到/root/.bash_profile,并不是全覆盖。 #然后将以下内容写进去,直至遇到EOF这个标识符,EOF之后的内容就别写进去了 cat >>/root/.bash_profile <<EOF export PATH=/usr/local/mysql/bin:\$PATH EOF 刷新/root/.bash_profile这个文件并使之生效 source /root/.bash_profile #这段命令用于启动 MySQL 服务器,并指定了一些重要的参数: #/usr/local/mysql/bin/mysqld这个是mysql的启动项,相当于windows桌面上的启动图标双击一下就运行该软件了 # --defaults-file=/etc/my.cnf:指定了配置文件的路径。 #--user=mysql:指定以 mysql 用户身份运行服务器。 #--datadir=/vdb/mysql/data:指定数据存储的目录。 #--basedir=/usr/local/mysql:指定 MySQL 的安装目录。 #--initialize-insecure:执行不安全的初始化,这可能意味着设置一些默认的、不太严格的安全选项来快速初始化数据库。 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql --datadir=/vdb/mysql/data --basedir=/usr/local/mysql --initialize-insecure #把/usr/local/mysql/support-files/mysql.server复制到/etc/init.d/这个文件夹里面去,取名为mysqld #/etc/init.d/ 文件夹通常用于存放系统服务和守护进程的启动、停止、重启等操作的脚本。 #也就是说我们这样手动安装的软件mysql,以后也可以用systemctl start mysql这样的命令来启动mysql了比较方便。 # /usr/local/mysql/support-files/mysql.server这个文件其实就是一个程序脚本,你看路径名里都有一个support-files #就是为了方便后续用户可以添加到linux系统里面的快捷启动方式里面(systemctl)。 #但是上面那个/usr/local/mysql/bin/mysqld是mysql的启动文件,这个不是一个脚本,用vim是打不开的,看不到里有啥内容 cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld #赋予/etc/init.d/mysqld具有可执行的权限 chmod 755 /etc/init.d/mysqld #将名为 mysqld 的服务添加到系统的服务管理配置中,方便可以用systemctl来控制启动、停止等状态 chkconfig --add mysqld #设置 MySQL 服务(mysqld)在运行级别 2、3、4、5 中为开机自启动(on)状态。 #运行级别是系统在不同模式下的运行状态,例如,2 通常是多用户模式但没有网络,3 是多用户模式带网络,4 通常未被使用,5 是带有图形界面的多用户模式。 chkconfig --level 2345 mysqld on #将”/usr/local/mysql/lib“写入到/etc/ld.so.conf.d/mysql-x86_64.conf里面去 cat >> /etc/ld.so.conf.d/mysql-x86_64.conf<<EOF /usr/local/mysql/lib EOF #刷新系统的共享库缓存,以便程序能够正确找到和加载所需的共享库 ldconfig #用于检查/proc/vz是否为一个目录,条件为真,就会执行then后面的语句 #ulimit -s unlimited 这条命令用于设置栈大小(stack size)为无限制(unlimited)。 #在某些情况下,如果程序需要较大的栈空间来处理复杂的操作或递归调用,可能会使用这条命令来避免栈空间不足导致的错误。 if [ -d "/proc/vz" ]; then ulimit -s unlimited fi #使用systemctl来启动mysql systemctl start mysqld.service # 创建监控用户,只读用户,复制用户 /usr/local/mysql/bin/mysqladmin -u root password $pwd > /dev/dull #把这两句SQL语句写入到/tmp/mysql_sec_scripts里面去 #这段 SQL 语句的作用是授予用户 'repl_user'@'%' 复制从服务器的权限。 #*.* 表示在所有数据库和所有表上授予权限。 #identified by '$rplpwd' 表示设置该用户的密码为 $rplpwd 变量所代表的值。 #flush privileges是刷新授权表; cat > /tmp/mysql_sec_scripts<<EOF grant replication slave on *.* to 'repl_user'@'%' identified by '$rplpwd'; flush privileges; EOF # 使用 /usr/local/mysql/bin/mysql 这个 MySQL 客户端程序, #以 root 用户身份,密码由 $pwd 变量指定,连接到本地主机(localhost)上的 MySQL 服务器 #并执行 /tmp/mysql_sec_scripts 文件中的 SQL 语句 # /usr/local/mysql/bin/mysql和刚才上面提到的/usr/local/mysql/bin/mysqld是不太一样的 # mysql是客户端程序,mysqld是主程序,主程序是运行在背后,但是我们人类想看mysql数据库里面的各种数据库具体表格 #就需要用到mysql客户端了,用mysql客户端连接背后的数据库用SQL语句进行相关的增删改查交互操作 /usr/local/mysql/bin/mysql -u root -p$pwd -h localhost </tmp/mysql_sec_scripts #删除/tmp/mysql_sec_scripts rm -f /tmp/mysql_sec_scripts #检查MySQL主程序有没有运行,在运行就赋值mcheck为1,否则为0 mcheck=`systemctl status mysqld.service|grep 'active (running)'|wc -l` #如果/usr/local/mysql/bin/mysql存在,并且/usr/local/mysql/bin/mysqld_safe也存在, #并且/etc/my.cnf也存在,并且MySQL主程序在运行中 #那么输出MySQL 5.7 install completed,以及MySQL网络连接状态信息,不然就输出安装失败Failed #ss -anutlp | grep 3306就是使用 ss 命令查看所有的网络连接状态信息; #(包括套接字的类型、状态、本地地址和端口、远程地址和端口等),然后通过 grep 3306 筛选出与端口 3306 相关的连接信息。 if [ -s /usr/local/mysql/bin/mysql ] && [ -s /usr/local/mysql/bin/mysqld_safe ] && [ -s /etc/my.cnf ] && [ $mcheck -eq 1 ]; then echo "" echo "MySQL 5.7 install completed" ss -anutlp | grep 3306 else echo "Error: MySQL Install Failed!!" fi
最新发布
08-06
### 一键安装 MySQL 脚本解析与优化建议 #### 一键安装 MySQL 脚本解析 一键安装脚本通常包含以下几个关键步骤: 1. **切换目录**:脚本通常会将工作目录切换到 `/opt`,以便集中管理安装文件。 2. **获取安装包**:通过变量获取上传的 MySQL 安装包名,例如 `mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz`。 3. **解压安装包**:使用 `tar` 命令解压安装包,并将其移动到指定的安装目录,例如 `/usr/local/mysql`。 4. **配置环境变量**:通过变量 `MYSQL_HOME` 设置 MySQL 的安装路径,并将其添加到 `PATH` 环境变量中,以便全局使用 MySQL 命令。 5. **配置 MySQL 服务**:创建 MySQL 用户和组,设置数据目录权限,并生成系统数据库。 6. **设置开机自启**:将 MySQL 服务添加到系统服务管理器中,确保每次系统启动时自动启动 MySQL。 7. **验证安装**:检查 MySQL 是否成功安装,通常通过 `mysql --version` 或启动 MySQL 服务后检查其运行状态。 #### 优化建议 1. **自动化检测依赖**:在安装脚本中添加对系统依赖的检查,例如 `libaio`、`numactl` 等库,若未安装则自动通过 `yum` 或 `dnf` 安装[^4]。 ```bash if ! rpm -q libaio &>/dev/null; then dnf install -y libaio fi ``` 2. **自定义安装路径**:允许用户通过参数指定安装路径,提升脚本的灵活性。 ```bash MYSQL_INSTALL_DIR="/usr/local/mysql" ``` 3. **配置文件优化**:在安装完成后,自动修改 `my.cnf` 文件,优化配置参数,例如调整 `innodb_buffer_pool_size`、`max_connections` 等关键参数。 ```bash echo "innodb_buffer_pool_size = 1G" >> /etc/my.cnf echo "max_connections = 500" >> /etc/my.cnf ``` 4. **日志与错误处理**:在脚本中添加日志记录功能,便于排查安装过程中可能出现的问题。 ```bash exec > >(tee -i install.log) exec 2>&1 ``` 5. **权限管理**:确保 MySQL 数据目录的权限正确设置,避免因权限问题导致数据库无法启动。 ```bash chown -R mysql:mysql /usr/local/mysql chmod -R 755 /usr/local/mysql ``` 6. **服务注册优化**:使用 `systemd` 管理 MySQL 服务,确保服务的稳定性与可控性。 ```bash cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld chkconfig --add mysqld systemctl daemon-reload systemctl enable mysqld ``` 7. **安全配置**:在安装完成后,自动执行 `mysql_secure_installation` 脚本,提高数据库安全性,包括设置 root 密码、删除匿名用户等。 #### 脚本示例 以下是一个简化版的 MySQL 一键安装脚本示例: ```bash #!/bin/bash # 变量定义 MYSQL_VERSION="mysql-8.0.33-linux-glibc2.12-x86_64" INSTALL_DIR="/usr/local/mysql" DATA_DIR="/var/lib/mysql" MYSQL_USER="mysql" # 创建 MySQL 用户 if ! id "$MYSQL_USER" &>/dev/null; then useradd -r -s /bin/false $MYSQL_USER fi # 解压安装包 tar -xvf /opt/$MYSQL_VERSION.tar.xz -C /usr/local/ mv /usr/local/$MYSQL_VERSION $INSTALL_DIR # 创建数据目录 mkdir -p $DATA_DIR chown -R $MYSQL_USER:$MYSQL_USER $DATA_DIR # 初始化数据库 $INSTALL_DIR/bin/mysqld --initialize --user=$MYSQL_USER --basedir=$INSTALL_DIR --datadir=$DATA_DIR # 配置环境变量 echo "export PATH=$INSTALL_DIR/bin:\$PATH" >> /etc/profile.d/mysql.sh source /etc/profile.d/mysql.sh # 配置 systemd 服务 cat <<EOF > /etc/systemd/system/mysqld.service [Unit] Description=MySQL Server After=network.target [Service] User=mysql Group=mysql ExecStart=$INSTALL_DIR/bin/mysqld --basedir=$INSTALL_DIR --datadir=$DATA_DIR --pid-file=/var/run/mysqld/mysqld.pid Restart=on-failure [Install] WantedBy=multi-user.target EOF # 启动并启用服务 systemctl daemon-reload systemctl enable mysqld systemctl start mysqld ``` --- ####
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值