これに12時間まっすぐ座っていた(今は正午なので、また目が覚めたら読みます/返信します)。
パフォーマンスを向上させるために、私たちの生産的な環境のデータベースのアップグレードを推奨するという大きな誤りを犯しました。
戻ることはできません。6テラバイト近くのストレージであり、mysql 8.0ではダウングレードできません。
また、アップグレード前のスナップショットバックアップを使用することは、解決策ではありません(作業日数)。
サーバーを最新バージョンに切り替えたことによる恐ろしいパフォーマンスを解決したい
いくつかの詳細:
環境:AWS i3.8xlarge上のLinux Stretch(32 CPU、240GB RAM)
Server:バインドマウントとホストネットワークを使用したmysql/Dockerコンテナー内のMysql 8.0
ストレージ:20,000 IOPSが予約されたAmazon AWS EBS IO1ストレージ(6 TB)。
ストレージは、fioテストで500mb /秒〜600mb /秒を提供します。
CPU:通常、32コアは50-60%使用されますが、mysql 8.0以降はアイドル状態です(10-15%使用)
[〜#〜] ram [〜#〜]:200GBはmysql専用で、8.0より前はそれほど長くはかかりませんでした中古。現在、mysqlがバッファを満たすことができるまでには何時間もかかります。
コアの問題:速度は5.7と比較して約20倍低下しました
Innodb/mysqlはディスクを効率的に使用していません。
元の構成を使用して15 mb /秒で読み取っていました(IBDファイルが正しく読み取られなかったため、単純なカウントの実行には数分かかりました)
それ以降、パフォーマンススキーマを無効にしました。これにより、少なくともサーバーを10%の負荷で再び動作させることができました。
ビンのログを無効にしました。多分、それはもう少し助けになりました、確かではありません。
読み取り/書き込みスレッドを64に増やしました(サーバーが完全に停止しました)。
私はmysqlの設定を調整するために8時間を費やしましたが、mysqlを5mb/secだけから現在は50mb/secまで「プッシュ」することができました。
確認するには:
もちろん、ディスクをテストしましたIO Dockerの内側から、それは外側とまったく同じです。
メインディスクはほとんどアイドル状態で、他のディスクは完全にアイドル状態です。
システムは、占有される必要があるときに90%アイドル状態です。
Innodbステータス:
https://Pastebin.com/XDgyNbk
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
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
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
ご覧のとおり、14mb /秒で読み取り、26mb /秒で書き込みを行っています。
mysql 5.7では、最大200MBの読み取りと書き込みを実行していました。
ディスクは基本的にアイドルです。 10倍のパフォーマンスを提供できますが、不明な理由により、innodb/mysqlはもう実行していません。
更新:変数とグローバルステータス: https://Pastebin.com/pzhXV7hq
https://Pastebin.com/jBTYLbY6
私が強制された別の変更:
Apache/phpを介して1秒あたり100人のユーザーが接続しているため、すべての接続で通常「SELECT count(*)FROM information_schema.processlist」がトリガーされました。これらの選択の代わりに、代わりに、5秒ごとにプロセスリストをinnodbテーブルに挿入する非同期タスクを作成しました。
これは、新しいmysqlの反応がいかに低いかを示すもう1つの兆候であり、プロセスリストによってさえ詰まっています。
ulimit
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
大きなアップデート
あなたの提案を考慮し、IRCで私に言われたことを考慮して、半日かけて内部を読みました。
私は専門家の反対をしました:私は一度に10の変更を行いました、私は段階的な変更プロセスでそれほど多くの再起動をする余裕がありません:
1)チョークせずにシステムに多くの並列書き込みの機会を与える
innodb_read_io_threads = 16
innodb_write_io_threads = 16
innodb_thread_concurrency=64 # cpus*2
2)バックグラウンド同期の高速化:
innodb_lru_scan_depth=100
3)パフォーマンスに大きな影響を与える最高の信頼性設定を無効にする
performance_schema=OFF
skip-log-bin
sync_binlog=0
innodb_flush_log_at_trx_commit=0 # not crash safe, 0 is crash safe
4)バックエンドメモリのマルチスレッド化
innodb_buffer_pool_instances=12
5)ログファイルを大幅に増やし、ログファイルバッファを適度に増やします
innodb_log_file_size = 3G #
innodb_log_buffer_size = 64M
何が起こったのか:読み取りパフォーマンスが約10倍、書き込みパフォーマンスが1.5倍になりました。私が望んでいるところではありませんが、以前より15倍高速です。 !
IOPSの使用量が〜5-6kから9k-12kに倍増したため、60%に達しましたIO usage
CPU使用率が7%から50%に増加
私の目標は80%ですIOおよびデータベースによるCPU使用率、他の変数がボトルネックになっていると思います。
リアルタイムでの使用:変更の前後に(通常のロードの横に)巨大な挿入を実行しています。
変更前の速度は約3000行/秒でしたが、上記の変更後は8000行/秒です。
これは、パフォーマンスの変化が極端であり、可能なことの50%にしか達していないためです。
更新
問題は半分解決されたと見なすことができると思います。前回成功したものの後に別の更新を行い、パフォーマンスは現在許容範囲です。
最後の変更には、書き込み/読み取りスレッドが含まれていました。私はそれらをそれぞれ32個に入れました。
書き込みバッファが128Mに増加しました(私の重いワークロードの場合、高い方が良い場合があります)
ログファイルが8GBに増加
メモリの断片化を改善するために、buffer_pool_instancesを64(最大)に増加
page_cleanersは64(最大)に増加し、各バッファーインスタンスに1つを持ちます。
書き込みパフォーマンスがさらに約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
GLOBAL STATUS
およびVARIABLES
のレビュー
観察:
より重要な問題:
table_open_cache
は高いですが、さらに上げるとよいでしょう。 table_open_cache_instances
を32に上げることも役立つ場合があります。
innodb_buffer_pool_instances = 16
; innodb_page_cleaners
の同上。
innodb_log_file_size
を8Gに増やします。これを達成する方法の詳細については、8.0マニュアルを参照してください(変更されました)。
なぜあなたはinnodb_flush_method = fsync
を持っているのですか? O_DIRECT
は多くの状況で推奨されます。
縮小long_quer_time
;スローログを確認してください。調査する必要があるいたずらなクエリがいくつかあります。
CREATE TABLE
5秒ごと?何が起こっている? dayごとに数回以上行うのは珍しいことです。
REPLACE
のほとんどはIODKUに取って代わられました。あなたのユースケースは何ですか?
さまざまなSHOW
コマンドを頻繁に使用しています。それらの実装は8.0で大幅に変更されており、8.0ではより高速になると予想しますが、これがスローダウンの原因の1つになる可能性があります。
1分あたり10 TRUNCATE TABLE
?調子はどう?テーブルの内容を置き換える場合は、通常新しいテーブルを作成してデータを入力し、RENAME TABLE
を使用してアトミックにそれを所定の位置に入れ替えます。
詳細およびその他の観察:
( Innodb_buffer_pool_pages_flushed ) = 96,254,291 / 38829 = 2478 /sec
-書き込み(フラッシュ)
( Opened_tables ) = 104,524 / 38829 = 2.7 /sec
-テーブルを開く頻度-table_open_cacheを増やす
( table_open_cache ) = 19,000
-キャッシュするテーブル記述子の数-通常は数百が適切です。
( Table_open_cache_misses ) = 104,520 / 38829 = 2.7 /sec
-table_open_cacheを増やす必要があるかもしれません
( innodb_buffer_pool_size / innodb_buffer_pool_instances ) = 181248M / 8 = 22656MB
-各buffer_poolインスタンスのサイズ。 -インスタンスは少なくとも1GBである必要があります。非常に大きなRAMには、16個のインスタンスがあります。
( innodb_page_cleaners / innodb_buffer_pool_instances ) = 4 / 8 = 0.5
-page_cleaners-innodb_page_cleanersをinnodb_buffer_pool_instancesに設定することをお勧めします
( (Innodb_buffer_pool_reads + Innodb_buffer_pool_pages_flushed) ) = ((23804167 + 96254291) ) / 38829 = 3091 /sec
-InnoDB I/O
( Innodb_os_log_written ) = 249,997,739,520 / 38829 = 6438428 /sec
-これは、InnoDBのビジー状態の指標です。
( Innodb_log_writes ) = 411,565,494 / 38829 = 10599 /sec
( Innodb_os_log_written / (Uptime / 3600) / innodb_log_files_in_group / innodb_log_file_size ) = 249,997,739,520 / (38829 / 3600) / 2 / 256M = 43.2
-比率-(分を参照)
( Uptime / 60 * innodb_log_file_size / Innodb_os_log_written ) = 38,829 / 60 * 256M / 249997739520 = 0.695
-InnoDBログローテーション間の分5.6.8以降、これは動的に変更できます。 my.cnfも必ず変更してください。 -(ローテーション間の60分の推奨はやや恣意的です。)innodb_log_file_sizeを調整します。 (AWSでは変更できません。)
( innodb_flush_method ) = innodb_flush_method = fsync
-InnoDBがOSにブロックの書き込みを要求する方法。ダブルバッファリングを回避するには、O_DIRECTまたはO_ALL_DIRECT(Percona)を推奨します。 (少なくともUnixの場合。)O_ALL_DIRECTに関する警告については、chrischandlerを参照してください。
( Innodb_row_lock_waits ) = 41,325 / 38829 = 1.1 /sec
-行ロックの取得に遅延が発生する頻度。 -最適化できる複雑なクエリが原因である可能性があります。
( Innodb_dblwr_writes ) = 1,177,834 / 38829 = 30 /sec
-「ダブルライトバッファ」はディスクに書き込みます。 「ダブルライト」は信頼性の高い機能です。新しいバージョン/構成の中には、それらを必要としないものがあります。 -(その他の問題の症状)
( Innodb_row_lock_current_waits ) = 54
-InnoDBテーブルに対する操作によって現在待機されている行ロックの数。ゼロはかなり正常です。 -何か大きなことが起こっていますか?
( innodb_print_all_deadlocks ) = innodb_print_all_deadlocks = OFF
-すべてのデッドロックをログに記録するかどうか。 -デッドロックに悩まされている場合は、これをオンにします。注意:デッドロックが多数ある場合、ディスクに大量に書き込まれる可能性があります。
( Queries ) = 146,600,019 / 38829 = 3775 /sec
-クエリ(SP内を含む)
( Created_tmp_tables ) = 43,466,450 / 38829 = 1119 /sec
-複雑なSELECTの一部として「temp」テーブルを作成する頻度。
( Created_tmp_disk_tables ) = 69,721 / 38829 = 1.8 /sec
-複雑なSELECTの一部としてdisk "temp"テーブルを作成する頻度-tmp_table_sizeとmax_heap_table_sizeを増やします。 MyISAMの代わりにMEMORYを使用する場合の一時テーブルのルールを確認してください。おそらく、マイナーなスキーマまたはクエリの変更により、MyISAMを回避できます。インデックスの改善とクエリの再構成が役立つ可能性が高くなります。
( Select_full_join ) = 341,473 / 38829 = 8.8 /sec
-インデックスなしの結合-JOINで使用されるテーブルに適切なインデックスを追加します。
( Select_scan ) = 20,070,358 / 38829 = 516 /sec
-テーブル全体のスキャン-インデックスを追加する/クエリを最適化する(小さなテーブルでない限り)
( Select_scan / Com_select ) = 20,070,358 / 46219009 = 43.4%
-全表スキャンを実行する選択の%。 (ストアドルーチンにだまされる可能性があります。)-インデックスを追加する/クエリを最適化する
( Com_insert + Com_delete + Com_delete_multi + Com_replace + Com_update + Com_update_multi ) = (1395278 + 512340 + 0 + 1843851 + 14825066 + 9554) / 38829 = 478 /sec
-書き込み/秒-50書き込み/秒+ログのフラッシュにより、通常のドライブのI/O書き込み容量が最大になります
( Com_replace ) = 1,843,851 / 38829 = 47 /sec
-INSERT ... ON DUPLICATE KEY UPDATEに変更することを検討してください。
( expire_logs_days ) = 0
-binlogを自動的にパージするまでの時間(この日数が経過した後)-大きすぎる(またはゼロ)=ディスク領域を消費します。小さすぎる=ネットワーク/マシンのクラッシュに迅速に対応する必要がある(log_bin = OFFの場合は関係ありません)
( slave_pending_jobs_size_max / max_allowed_packet ) = 128M / 64M = 2
-並列スレーブスレッドの場合-slave_pending_jobs_size_maxはmax_allowed_packet未満であってはなりません
( long_query_time ) = 10
-「遅い」クエリを定義するためのカットオフ(秒)。 -提案2
( back_log / max_connections ) = 1,600 / 1600 = 100.0%
( Connections ) = 1,054,868 / 38829 = 27 /sec
-接続-wait_timeoutを増やします。プーリングを使用しますか?
( thread_cache_size ) = 192
-保持する余分なプロセスの数(スレッドプーリングを使用する場合は関係ありません)(5.6.8以降で自動サイズ設定、max_connectionsに基づく)
異常に大きい:
Bytes_received = 1583925 /sec
Com_begin = 11 /sec
Com_create_db = 0.093 /HR
Com_create_function = 4.1 /HR
Com_create_procedure = 0.37 /HR
Com_create_table = 0.21 /sec
Com_delete = 13 /sec
Com_drop_procedure = 0.37 /HR
Com_insert_select = 29 /sec
Com_insert_select + Com_replace_select = 75 /sec
Com_kill = 0.74 /HR
Com_replace_select = 47 /sec
Com_show_create_db = 2.2 /HR
Com_show_create_trigger = 0.28 /HR
Com_show_events = 0.74 /HR
Com_show_storage_engines = 0.93 /HR
Com_show_warnings = 16 /HR
Com_stmt_close = 919 /sec
Com_stmt_execute = 919 /sec
Com_stmt_prepare = 919 /sec
Com_truncate = 0.16 /sec
Com_update = 381 /sec
Com_update_multi = 0.25 /sec
Handler_commit = 1638 /sec
Handler_delete = 60 /sec
Handler_external_lock = 5083 /sec
Handler_read_key = 58652 /sec
Handler_read_next = 607861 /sec
Handler_update = 40571 /sec
Innodb_buffer_pool_bytes_dirty = 1,309.3MB
Innodb_buffer_pool_pages_data = 1.18e+7
Innodb_buffer_pool_pages_dirty = 83,894
Innodb_buffer_pool_pages_flushed / max(Questions, Queries) = 0.657
Innodb_buffer_pool_pages_misc = 664,249
Innodb_buffer_pool_pages_total = 1.25e+7
Innodb_data_fsyncs = 232 /sec
Innodb_data_pending_fsyncs = 0.46 /HR
Innodb_data_read = 12400226 /sec
Innodb_data_reads = 770 /sec
Innodb_data_writes = 13131 /sec
Innodb_data_written = 88604121 /sec
Innodb_dblwr_pages_written = 2476 /sec
Innodb_dblwr_pages_written / Innodb_dblwr_writes = 81.6
Innodb_log_write_requests = 10906 /sec
Innodb_os_log_fsyncs = 87 /sec
Innodb_os_log_written / (Uptime / 3600) / innodb_log_files_in_group = 11,052.3MB
Innodb_pages_created = 57 /sec
Innodb_pages_written = 2478 /sec
Innodb_rows_deleted = 60 /sec
Innodb_rows_deleted + Innodb_rows_inserted = 658 /sec
Innodb_rows_inserted = 598 /sec
Innodb_rows_updated = 520 /sec
Max_execution_time_set = 0.0MB
Max_used_connections = 768
Select_range = 1250 /sec
Select_range / Com_select = 105.0%
Sort_range = 274 /sec
Sort_scan = 509 /sec
Table_open_cache_hits = 3826 /sec
Threads_cached = 142
Threads_connected = 366
back_log = 1,600
innodb_io_capacity_max = 20,000
innodb_max_dirty_pages_pct_lwm = 1000.0%
innodb_undo_tablespaces = 2
max_error_count = 1,024
max_length_for_sort_data = 4,096
max_user_connections = 1,500
optimizer_trace_max_mem_size = 1.05e+6
slave_pending_jobs_size_max = 128MB
異常な文字列:
bind_address = 0.0.0.0
event_scheduler = ON
explicit_defaults_for_timestamp = ON
have_query_cache = NO
have_ssl = YES
have_symlink = DISABLED
innodb_buffer_pool_dump_at_shutdown = ON
innodb_buffer_pool_load_at_startup = ON
innodb_fast_shutdown = 1
innodb_undo_directory = ./
innodb_undo_log_truncate = ON
master_info_repository = TABLE
optimizer_trace = enabled=off,one_line=off
optimizer_trace_features = greedy_search=on, range_optimizer=on, dynamic_range=on, repeated_subselect=on
relay_log_info_repository = TABLE
slave_rows_search_algorithms = INDEX_SCAN,HASH_SCAN
ssl_ca = ca.pem
ssl_cert = server-cert.pem
ssl_key = server-key.pem
transaction_write_set_extraction = XXHASH64
UPDATE task_s_b SET result_delivered=1, result_data='DISABLED',
result_gathered=1
WHERE result_data is NULL
AND (assigned_counter >= 4
OR c_counter > 2
)
そのテーブルの値の分布に応じて、このクエリmayは問題を引き起こしています。
2つのクエリとして書き直すことを検討してください。
UPDATE task_s_b SET result_delivered=1, result_data='DISABLED',
result_gathered=1
WHERE result_data is NULL
AND assigned_counter >= 4;
UPDATE task_s_b SET result_delivered=1, result_data='DISABLED',
result_gathered=1
WHERE result_data is NULL
AND c_counter > 2;
そして、これらの2つの複合インデックスを指定された順序で列に追加します。
INDEX(result_data, assigned_counter)
INDEX(result_data, c_counter)
詳細については、SHOW CREATE TABLE
およびSHOW TABLE STATUS
そのテーブル。
これはmayデッドロックを減らし、サーバーを高速化します。
現時点で利用可能なデータに基づく即時救済のためのサービスの停止/開始なしで検討すべき提案1月22日19日15:00 CT USA
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
SHOW GLOBAL VARIABLESの投稿後;分析が完了すると、さらに提案が表示されます。