Joh*_*ohn 7 mysql innodb mysql-8.0
已经连续坐了 12 个小时(现在是中午,所以当我再次醒来时我会阅读/回复)。
我犯了一个大错误,建议升级我们的生产环境的数据库以提高性能。
我们不能回去,它有将近 6 TB 的存储空间,而且 mysql 8.0 无法降级。
使用升级前快照备份也不是解决方案(工作天数)。
我想解决将服务器切换到最新版本导致的可怕性能
一些细节:
环境:Linux Stretch on AWS i3.8xlarge(32 cpu,240gb ram)
服务器:mysql/Docker 容器中的 Mysql 8.0,使用绑定安装和主机网络
存储:Amazon AWS EBS IO1 存储(6 TB),预留 20,000 IOPS .
存储在 fio 测试中提供 500mb/sec-600mb/sec。
CPU:通常 32 核使用 50-60%,但自 mysql 8.0 以来它处于空闲状态(使用 10-15%)
RAM:200GB 专用于 mysql,在 8.0 之前不久就被使用了。现在需要好几个小时,mysql 才能填满缓冲区。
核心问题:
速度比5.7下降了20倍左右
Innodb/mysql 没有有效地使用磁盘。
使用它以 15 mb/sec 读取的原始配置(简单计数需要几分钟才能运行,因为 IBD 文件未正确读取)
我已经禁用了性能模式,这有助于至少以 10% 的负载再次运行服务器。
我禁用了 bin 日志记录,也许这有帮助,但不确定。
我尝试将读/写线程增加到 64(这完全停止了服务器)
我花了 8 个小时来尝试调整 mysql 配置,我设法将 mysql 从仅使用 5mb/sec 的速度“推”到了现在的 50mb/sec。
确保:
当然,我确实从 docker 内部测试了磁盘 IO,它与外部完全相似。
主盘大部分空闲,其他盘完全空闲。
当系统应该被占用时,它有 90% 的空闲。
Innodb 状态:https :
//pastebin.com/XDgyNbk0
mysql配置:
[mysqld]
user=mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
tmpdir = /mysql_tmp
# compatibility
default_authentication_plugin=mysql_native_password
character_set_server=latin1
collation_server=latin1_swedish_ci
log-error = /var/log/mysql_error.log
bind-address = 0.0.0.0
sql_mode= "NO_ENGINE_SUBSTITUTION"
interactive_timeout = 3600
wait_timeout = 900
max_allowed_packet = 64M
thread_stack = 256K
thread_cache_size = 192
max_connections = 1600
max_user_connections = 1500
#query_cache_limit = 3M
#query_cache_size = 200M
#query_cache_type = 1
table_open_cache = 2500
key_buffer_size = 64M # index in memory for myisam
innodb_buffer_pool_size = 190G
innodb_log_file_size = 256M
tmp_table_size = 250M
max_heap_table_size = 250M
join_buffer_size = 2M
#pagecleaners - those were uncommented on 5.7
#innodb_buffer_pool_instances=8
#innodb_page_cleaners=2
innodb_io_capacity=5000
innodb_io_capacity_max=20000
# tried 64, that totally stalled the database
innodb_read_io_threads = 8
innodb_write_io_threads = 8
#in pre 5.7 times I had consistent 300mb/sec writes, now it's useless
innodb_lru_scan_depth=256
skip-name-resolve
secure_file_priv=""
#innodb_checksum_algorithm = crc32
#binlog_checksum = CRC32
# this one at least made it possible so I can go to bed, with performance_schema the database was unuseable
performance_schema=OFF
skip-log-bin
Run Code Online (Sandbox Code Playgroud)
Sysctl fs:
fs.aio-max-nr = 1048576
fs.aio-nr = 139264
fs.binfmt_misc.status = enabled
fs.dentry-state = 355223 335269 45 0 0 0
fs.dir-notify-enable = 1
fs.epoll.max_user_watches = 51660308
fs.file-max = 25224638
fs.file-nr = 19136 0 25224638
fs.inode-nr = 70145 5686
fs.inode-state = 70145 5686 0 0 0 0 0
fs.inotify.max_queued_events = 16384
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 8192
fs.lease-break-time = 45
fs.leases-enable = 1
fs.mqueue.msg_default = 10
fs.mqueue.msg_max = 10
fs.mqueue.msgsize_default = 8192
fs.mqueue.msgsize_max = 8192
fs.mqueue.queues_max = 256
fs.nr_open = 1048576
fs.overflowgid = 65534
fs.overflowuid = 65534
fs.pipe-max-size = 1048576
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
fs.quota.allocated_dquots = 0
fs.quota.cache_hits = 0
fs.quota.drops = 0
fs.quota.free_dquots = 0
fs.quota.lookups = 0
fs.quota.reads = 0
fs.quota.syncs = 62
fs.quota.warnings = 1
fs.quota.writes = 0
fs.suid_dumpable = 0
Run Code Online (Sandbox Code Playgroud)
iostat 快照:
avg-cpu: %user %nice %system %iowait %steal %idle
13.86 0.71 10.84 3.23 0.11 71.26
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvdh 1795.31 13923.89 26159.95 256609017 482112504
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它只是以 14mb/sec 的速度读取,以 26mb/sec 的速度写入……
使用 mysql 5.7,它的读取和写入速度高达200mb 。
磁盘基本空闲。它可以提供 10 倍的性能,但由于未知原因 innodb/mysql 不再这样做了。
更新:
变量和全局状态:https : //pastebin.com/pzhXV7hq
https://pastebin.com/jBTYLbY6
我被迫做出的另一个改变:
我每秒有 100 个用户通过 apache/php 连接,每个连接通常都会触发“SELECT count(*) FROM information_schema.processlist”新的 mysql 不能再这样做了,它将其中 50 个以上的选择排队,所以我做了一个异步任务,每 5 秒将进程列表插入到 innodb 表中。
这只是新 mysql 反应性能低下的另一个迹象,它甚至被进程列表阻塞。
超限
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 985342
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65536
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 985342
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Run Code Online (Sandbox Code Playgroud)
大更新
花了半天时间阅读 internas,考虑你的建议和我在 IRC 上被告知的内容。
我做了与专业相反的事情:我一次做了 10 次更改,我无法承受在渐变过程中进行这么多次重启:
1) 为系统提供大量并行写入机会而不会使其窒息
innodb_read_io_threads = 16
innodb_write_io_threads = 16
innodb_thread_concurrency=64 # cpus*2
Run Code Online (Sandbox Code Playgroud)
2)加快后台同步:
innodb_lru_scan_depth=100
Run Code Online (Sandbox Code Playgroud)
3) 禁用对性能有重大影响的最高可靠性设置
performance_schema=OFF
skip-log-bin
sync_binlog=0
innodb_flush_log_at_trx_commit=0 # not crash safe, 0 is crash safe
Run Code Online (Sandbox Code Playgroud)
4)后端内存中更多的多线程
innodb_buffer_pool_instances=12
Run Code Online (Sandbox Code Playgroud)
5)显着增加日志文件,适度增加日志文件缓冲区
innodb_log_file_size = 3G #
innodb_log_buffer_size = 64M
Run Code Online (Sandbox Code Playgroud)
发生了什么:读取性能提高了大约 10 倍,写入性能提高了 1.5 倍,我不是我想要的地方,但它比以前快了 15 倍!
IOPS 使用率从 ~5-6k 翻倍到 9k-12k,所以我处于 60% IO 使用率
CPU 使用率从 7% 增加到 50%
我的目标是数据库的 80% IO 和 CPU 使用率,我认为其他变量是瓶颈。
实时使用:我有一个巨大的插入在更改前后运行(在通常的负载旁边)。
在更改之前,速度约为每秒 3000 行,在上述更改之后,速度为每秒 8000 行。
我想我分享这一点,因为性能的变化是极端的,我只达到了应该可能的 50%。
更新
我觉得问题已经解决了一半,我在上一次成功后又做了一次更新,现在性能可以接受。
最后的更改涉及写/读线程。我已经把它们分别设置为 32 个。
写入缓冲区增加到 128M(对于我的繁重工作量,更高可能更好)
日志文件增加到 8GB
buffer_pool_instances 增加到 64(最大)以获得更好的内存碎片
page_cleaners 增加到 64(最大),以便每个缓冲区实例都有一个。
写入性能再提高约 20%,读取性能再提高约 30%。
让 mysql 的性能可以接受需要 24 小时的车程,绝对不是简单的升级。
最新状态:
Current configuration: https://pastebin.com/9vsbEQxt
show engine status innodb: https://pastebin.com/kCjnmtze
show global variables: https://pastebin.com/aMdQxWcA
global status: https://pastebin.com/VbG1yzHX
Run Code Online (Sandbox Code Playgroud)
根据美国中部时间 2019 年 1 月 22 日 15:00 目前的可用数据,考虑不停止/启动服务以立即救济的建议
SET GLOBAL innodb_io_capacity=10000 from your 5000 limit at this time
SET GLOBAL innodb_lru_scan_depth=100 from your 256 to reduce CPU cycles used for this function by 60% EVERY SECOND
Run Code Online (Sandbox Code Playgroud)
发布 SHOW GLOBAL VARIABLES 后;分析完毕还会有更多的建议。
归档时间: |
|
查看次数: |
8757 次 |
最近记录: |