From 6244876488f41c4aec8e55ede37625b5bc649bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 20 Apr 2021 23:09:01 +0300 Subject: [PATCH 1/8] MDEV-24807:A possibility for double free in dtor of Event_queue_element_for_exec in the case of OOM Eliminate a memory leak when init can fail by forgetting to delete the Event_queue_element_for_exec object. --- sql/event_data_objects.cc | 1 + sql/event_data_objects.h | 2 +- sql/event_queue.cc | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 4100a031c91..4e5137d3ee1 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -178,6 +178,7 @@ Event_queue_element_for_exec::init(LEX_STRING db, LEX_STRING n) if (!(name.str= my_strndup(n.str, name.length= n.length, MYF(MY_WME)))) { my_free(dbname.str); + dbname.str= NULL; return TRUE; } return FALSE; diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h index 0acf301ef5a..41626004100 100644 --- a/sql/event_data_objects.h +++ b/sql/event_data_objects.h @@ -33,7 +33,7 @@ struct TABLE; class Event_queue_element_for_exec { public: - Event_queue_element_for_exec(){}; + Event_queue_element_for_exec() : dbname{NULL, 0}, name{NULL, 0} {}; ~Event_queue_element_for_exec(); bool diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 904efe26f36..4398b650fd7 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -635,6 +635,7 @@ Event_queue::get_top_for_execution_if_time(THD *thd, if (!(*event_name= new Event_queue_element_for_exec()) || (*event_name)->init(top->dbname, top->name)) { + delete *event_name; ret= TRUE; break; } From 3635280cf7ef74ec18cfb21b21e779725aab186d Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Wed, 21 Apr 2021 01:03:32 +0300 Subject: [PATCH 2/8] MDEV-25288 Create a list of tests for distributions ... to run upon building/packaging of MariaDB server --- mysql-test/collections/smoke_test | 139 ++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100755 mysql-test/collections/smoke_test diff --git a/mysql-test/collections/smoke_test b/mysql-test/collections/smoke_test new file mode 100755 index 00000000000..191dfb520ef --- /dev/null +++ b/mysql-test/collections/smoke_test @@ -0,0 +1,139 @@ +archive.archive +archive.archive_gis +archive.partition_archive +binlog.binlog_base64_flag +binlog.binlog_database +binlog.binlog_innodb +binlog.binlog_parallel_replication_marks_stm_mix +binlog.binlog_row_mix_innodb_myisam +binlog.flashback +binlog_encryption.encrypted_slave +connect.bin +connect.bson +connect.dbf +connect.dir +connect.endian +connect.general +connect.json +connect.mysql +connect.secure_file_priv +connect.tbl +csv.csv +disks.disks +encryption.encryption_force +encryption.innodb_encryption_tables +encryption.tempfiles_encrypted +federated.federated +federated.federatedx +gcol.gcol_select_innodb +handler.interface +heap.heap +innodb.innodb +innodb.autoinc_persist +innodb.innodb_defrag_binlog +innodb.innodb_mysql +innodb.monitor +innodb.purge +innodb.table_flags +innodb.xa_recovery +innodb_fts.fulltext +innodb_gis.geometry +innodb_gis.rtree +innodb_zip.innodb-zip +innodb_zip.page_size +json.json_no_table +main-test_sql_discovery.create +main.blackhole +main.bootstrap +main.compress +main.connect +main.ctype_collate +main.ctype_utf8 +main.default +main.dyncol +main.fulltext +main.function_defaults +main.gis +main.grant +main.handlersocket +main.information_schema +main.innodb_ext_key +main.log_tables +main.lowercase_fs_off +main.myisam +main.mysql_client_test +main.mysql_protocols +main.mysql_upgrade +main.mysqladmin +main.mysqlbinlog +main.mysqlcheck +main.mysqld--defaults-file +main.mysqldump +main.mysqlhotcopy_myisam +main.mysqlshow +main.mysqlslap +main.mysqltest +main.parser +main.partition +main.perror +main.plugin +main.plugin_auth +main.pool_of_threads +main.ps +main.repair +main.shutdown +main.sp +main.ssl +main.ssl_compress +main.stat_tables +main.statistics +main.subselect +main.symlink +main.temp_table +main.timezone +main.type_timestamp_hires +main.user_var +main.userstat +main.variables +main.view +main.win +main.xa +maria.maria +mariabackup.full_backup +metadata_lock_info.table_metadata_lock +mroonga/storage.variable_version +mroonga/wrapper.count_star +multi_source.multisource +oqgraph.general-innodb +parts.rpl_partition +perfschema.selects +plugins.auth_ed25519 +plugins.cracklib_password_check +plugins.dialog +plugins.fulltext_plugin +plugins.locales +plugins.pam_cleartext +plugins.processlist +plugins.qc_info +plugins.server_audit +plugins.simple_password_check +plugins.sql_error_log +plugins.two_password_validations +plugins.unix_socket +query_response_time.basic +rocksdb.rocksdb +roles.definer +rpl.rpl_gtid_basic +rpl.rpl_relayrotate +rpl.rpl_row_blob_innodb +rpl.rpl_semi_sync_event +rpl.rpl_sp +rpl.rpl_stm_binlog_max_cache_size +rpl.rpl_switch_stm_row_mixed +sequence.simple +spider.basic_sql +spider.ha +sql_discovery.simple +sys_vars.sysvars_aria +sys_vars.sysvars_server_notembedded +wsrep.variables From df18fa4caeec597275ad1ea6667f5598ae2b23b9 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Wed, 21 Apr 2021 02:44:14 +0300 Subject: [PATCH 3/8] Smoke test collection should not be executable Since it ended up being a plain text file rather than a script (post-fix for MDEV-25288) Also removed main-test_sql_discovery.create from the list, as a workaround for MDEV-25384. The bug only affects 10.3+, but it will be simpler if 10.2 part of the tests is the same in all branches --- mysql-test/collections/smoke_test | 1 - 1 file changed, 1 deletion(-) mode change 100755 => 100644 mysql-test/collections/smoke_test diff --git a/mysql-test/collections/smoke_test b/mysql-test/collections/smoke_test old mode 100755 new mode 100644 index 191dfb520ef..83b8f4771e0 --- a/mysql-test/collections/smoke_test +++ b/mysql-test/collections/smoke_test @@ -42,7 +42,6 @@ innodb_gis.rtree innodb_zip.innodb-zip innodb_zip.page_size json.json_no_table -main-test_sql_discovery.create main.blackhole main.bootstrap main.compress From 9e6e0eaee203c0a736730a94e2f5422dfe0cd686 Mon Sep 17 00:00:00 2001 From: Lee Keun Won Date: Tue, 20 Apr 2021 12:10:24 +0900 Subject: [PATCH 4/8] fixed some korean error messages Closes #1811 --- sql/share/errmsg-utf8.txt | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 4bb1ae951af..2d4e0562d8f 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -191,7 +191,7 @@ ER_DB_DROP_DELETE hun "Adatbazis megszuntetesi hiba ('%-.192s' nem torolheto, hibakod: %M)" ita "Errore durante la cancellazione del database (impossibile cancellare '%-.192s', errno: %M)" jpn "データベース削除エラー ('%-.192s' を削除できません。エラー番号: %M)" - kor "데이타베이스 제거 에러('%-.192s'를 삭제할 수 없읍니다, 에러번호: %M)" + kor "데이타베이스 제거 에러('%-.192s'를 삭제할 수 없습니다, 에러번호: %M)" nor "Feil ved fjerning (drop) av databasen (kan ikke slette '%-.192s', feil %M)" norwegian-ny "Feil ved fjerning (drop) av databasen (kan ikkje slette '%-.192s', feil %M)" pol "Bł?d podczas usuwania bazy danych (nie można usun?ć '%-.192s', bł?d %M)" @@ -216,7 +216,7 @@ ER_DB_DROP_RMDIR hun "Adatbazis megszuntetesi hiba ('%-.192s' nem szuntetheto meg, hibakod: %M)" ita "Errore durante la cancellazione del database (impossibile rmdir '%-.192s', errno: %M)" jpn "データベース削除エラー (ディレクトリ '%-.192s' を削除できません。エラー番号: %M)" - kor "데이타베이스 제거 에러(rmdir '%-.192s'를 할 수 없읍니다, 에러번호: %M)" + kor "데이타베이스 제거 에러(rmdir '%-.192s'를 할 수 없습니다, 에러번호: %M)" nor "Feil ved sletting av database (kan ikke slette katalogen '%-.192s', feil %M)" norwegian-ny "Feil ved sletting av database (kan ikkje slette katalogen '%-.192s', feil %M)" pol "Bł?d podczas usuwania bazy danych (nie można wykonać rmdir '%-.192s', bł?d %M)" @@ -516,7 +516,7 @@ ER_DUP_KEY 23000 hun "Irasi hiba, duplikalt kulcs a '%-.192s' tablaban" ita "Scrittura impossibile: chiave duplicata nella tabella '%-.192s'" jpn "書き込めません。表 '%-.192s' に重複するキーがあります。" - kor "기록할 수 없읍니다., 테이블 '%-.192s'에서 중복 키" + kor "기록할 수 없습니다., 테이블 '%-.192s'에서 중복 키" nor "Kan ikke skrive, flere like nøkler i tabellen '%-.192s'" norwegian-ny "Kan ikkje skrive, flere like nyklar i tabellen '%-.192s'" pol "Nie można zapisać, powtórzone klucze w tabeli '%-.192s'" @@ -641,7 +641,7 @@ ER_FILE_USED hun "'%-.192s' a valtoztatas ellen zarolva" ita "'%-.192s' e` soggetto a lock contro i cambiamenti" jpn "'%-.192s' はロックされています。" - kor "'%-.192s'가 변경할 수 없도록 잠겨있읍니다." + kor "'%-.192s'가 변경할 수 없도록 잠겨있습니다." nor "'%-.192s' er låst mot oppdateringer" norwegian-ny "'%-.192s' er låst mot oppdateringar" pol "'%-.192s' jest zablokowany na wypadek zmian" @@ -691,7 +691,7 @@ ER_FORM_NOT_FOUND hun "A(z) '%-.192s' nezet nem letezik a(z) '%-.192s'-hoz" ita "La view '%-.192s' non esiste per '%-.192s'" jpn "ビュー '%-.192s' は '%-.192s' に存在しません。" - kor "뷰 '%-.192s'가 '%-.192s'에서는 존재하지 않읍니다." + kor "뷰 '%-.192s'가 '%-.192s'에서는 존재하지 않습니다." nor "View '%-.192s' eksisterer ikke for '%-.192s'" norwegian-ny "View '%-.192s' eksisterar ikkje for '%-.192s'" pol "Widok '%-.192s' nie istnieje dla '%-.192s'" @@ -739,7 +739,7 @@ ER_KEY_NOT_FOUND hun "Nem talalhato a rekord '%-.192s'-ben" ita "Impossibile trovare il record in '%-.192s'" jpn "'%-.192s' にレコードが見つかりません。" - kor "'%-.192s'에서 레코드를 찾을 수 없읍니다." + kor "'%-.192s'에서 레코드를 찾을 수 없습니다." nor "Kan ikke finne posten i '%-.192s'" norwegian-ny "Kan ikkje finne posten i '%-.192s'" pol "Nie można znaleĽć rekordu w '%-.192s'" @@ -985,7 +985,7 @@ ER_BAD_HOST_ERROR 08S01 hun "A gepnev nem allapithato meg a cimbol" ita "Impossibile risalire al nome dell'host dall'indirizzo (risoluzione inversa)" jpn "IPアドレスからホスト名を解決できません。" - kor "당신의 컴퓨터의 호스트이름을 얻을 수 없읍니다." + kor "당신의 컴퓨터의 호스트이름을 얻을 수 없습니다." nor "Kan ikke få tak i vertsnavn for din adresse" norwegian-ny "Kan ikkje få tak i vertsnavn for di adresse" pol "Nie można otrzymać nazwy hosta dla twojego adresu" @@ -1533,7 +1533,7 @@ ER_PARSE_ERROR 42000 s1009 hun "A %s a '%-.80T'-hez kozeli a %d sorban" ita "%s vicino a '%-.80T' linea %d" jpn "%s : '%-.80T' 付近 %d 行目" - kor "'%s' 에러 같읍니다. ('%-.80T' 명령어 라인 %d)" + kor "'%s' 에러 같습니다. ('%-.80T' 명령어 라인 %d)" nor "%s nær '%-.80T' på linje %d" norwegian-ny "%s attmed '%-.80T' på line %d" pol "%s obok '%-.80T' w linii %d" @@ -1658,7 +1658,7 @@ ER_TOO_MANY_KEYS 42000 S1009 hindi "बहुत सारी KEYS निर्दिष्ट हैं; अधिकतम %d KEYS की अनुमति है" ita "Troppe chiavi. Sono ammesse max %d chiavi" jpn "索引の数が多すぎます。最大 %d 個までです。" - kor "너무 많은 키가 정의되어 있읍니다.. 최대 %d의 키가 가능함" + kor "너무 많은 키가 정의되어 있습니다.. 최대 %d의 키가 가능함" nor "For mange nøkler spesifisert. Maks %d nøkler tillatt" norwegian-ny "For mange nykler spesifisert. Maks %d nyklar tillatt" pol "Okre?lono zbyt wiele kluczy. Dostępnych jest maksymalnie %d kluczy" @@ -1683,7 +1683,7 @@ ER_TOO_MANY_KEY_PARTS 42000 S1009 hun "Tul sok kulcsdarabot definialt. Maximum %d resz engedelyezett" ita "Troppe parti di chiave specificate. Sono ammesse max %d parti" jpn "索引のキー列指定が多すぎます。最大 %d 個までです。" - kor "너무 많은 키 부분(parts)들이 정의되어 있읍니다.. 최대 %d 부분이 가능함" + kor "너무 많은 키 부분(parts)들이 정의되어 있습니다.. 최대 %d 부분이 가능함" nor "For mange nøkkeldeler spesifisert. Maks %d deler tillatt" norwegian-ny "For mange nykkeldelar spesifisert. Maks %d delar tillatt" pol "Okre?lono zbyt wiele czę?ci klucza. Dostępnych jest maksymalnie %d czę?ci" @@ -2593,7 +2593,7 @@ ER_FIELD_SPECIFIED_TWICE 42000 hun "A(z) '%-.192s' mezot ketszer definialta" ita "Campo '%-.192s' specificato 2 volte" jpn "列 '%-.192s' は2回指定されています。" - kor "칼럼 '%-.192s'는 두번 정의되어 있읍니다." + kor "칼럼 '%-.192s'는 두번 정의되어 있습니다." nor "Feltet '%-.192s' er spesifisert to ganger" norwegian-ny "Feltet '%-.192s' er spesifisert to gangar" pol "Field '%-.192s' specified twice" @@ -2774,7 +2774,7 @@ ER_TOO_BIG_ROWSIZE 42000 hun "Tul nagy sormeret. A maximalis sormeret (nem szamolva a blob objektumokat) %ld. Nehany mezot meg kell valtoztatnia" ita "Riga troppo grande. La massima grandezza di una riga, non contando i BLOB, e` %ld. Devi cambiare alcuni campi in BLOB" jpn "行サイズが大きすぎます。この表の最大行サイズは BLOB を含まずに %ld です。格納時のオーバーヘッドも含まれます(マニュアルを確認してください)。列をTEXTまたはBLOBに変更する必要があります。" - kor "너무 큰 row 사이즈입니다. BLOB를 계산하지 않고 최대 row 사이즈는 %ld입니다. 얼마간의 필드들을 BLOB로 바꾸셔야 겠군요.." + kor "너무 큰 row 사이즈입니다. BLOB를 계산하지 않고 최대 row 사이즈는 %ld입니다. 일부열을 BLOB 또는 TEXT로 변경해야 합니다." por "Tamanho de linha grande demais. O máximo tamanho de linha, não contando BLOBs, é %ld. Você tem que mudar alguns campos para BLOBs" rum "Marimea liniei (row) prea mare. Marimea maxima a liniei, excluzind BLOB-urile este de %ld. Trebuie sa schimbati unele cimpuri in BLOB-uri" rus "Слишком большой размер записи. Максимальный размер строки, исключая поля BLOB, - %ld. Возможно, вам следует изменить тип некоторых полей на BLOB" @@ -3077,7 +3077,7 @@ ER_PASSWORD_NO_MATCH 28000 hun "Nincs megegyezo sor a user tablaban" ita "Impossibile trovare la riga corrispondente nella tabella user" jpn "ユーザーテーブルに該当するレコードが見つかりません。" - kor "사용자 테이블에서 일치하는 것을 찾을 수 없읍니다." + kor "사용자 테이블에서 일치하는 것을 찾을 수 없습니다." por "Não pode encontrar nenhuma linha que combine na tabela usuário (user table)" rum "Nu pot gasi nici o linie corespunzatoare in tabela utilizatorului" rus "Невозможно отыскать подходящую запись в таблице пользователей" @@ -3219,7 +3219,7 @@ ER_MIX_OF_GROUP_FUNC_AND_FIELDS 42000 hun "A GROUP mezok (MIN(),MAX(),COUNT()...) kevert hasznalata nem lehetseges GROUP BY hivatkozas nelkul" ita "Il mescolare funzioni di aggregazione (MIN(),MAX(),COUNT()...) e non e` illegale se non c'e` una clausula GROUP BY" jpn "GROUP BY句が無い場合、集計関数(MIN(),MAX(),COUNT(),...)と通常の列を同時に使用できません。" - kor "Mixing of GROUP 칼럼s (MIN(),MAX(),COUNT(),...) with no GROUP 칼럼s is illegal if there is no GROUP BY clause" + kor "GROUP BY 절 없이 혼합된 GROUP 함수 (MIN(),MAX(),COUNT(),...) 를 사용할 수 없습니다." por "Mistura de colunas agrupadas (com MIN(), MAX(), COUNT(), ...) com colunas não agrupadas é ilegal, se não existir uma cláusula de agrupamento (cláusula GROUP BY)" rum "Amestecarea de coloane GROUP (MIN(),MAX(),COUNT()...) fara coloane GROUP este ilegala daca nu exista o clauza GROUP BY" rus "Одновременное использование сгруппированных (GROUP) столбцов (MIN(),MAX(),COUNT(),...) с несгруппированными столбцами является некорректным, если в выражении есть GROUP BY" @@ -3668,6 +3668,7 @@ ER_TOO_LONG_STRING 42000 est "Tulemus on pikem kui lubatud 'max_allowed_packet' muutujaga" fre "La chaîne résultat est plus grande que 'max_allowed_packet'" ger "Ergebnis-String ist länger als 'max_allowed_packet' Bytes" + kor "결과 문자열이 설정된 max_allowed_packet 값보다 큽니다." hindi "रिजल्ट स्ट्रिंग 'max_allowed_packet' से लंबा है" hun "Ez eredmeny sztring nagyobb, mint a lehetseges maximum: 'max_allowed_packet'" ita "La stringa di risposta e` piu` lunga di 'max_allowed_packet'" @@ -3689,6 +3690,7 @@ ER_TABLE_CANT_HANDLE_BLOB 42000 ger "Der verwendete Tabellentyp (%s) unterstützt keine BLOB- und TEXT-Felder" hindi "स्टोरेज इंजन %s BLOB/TEXT कॉलम्स को सपोर्ट नहीं करता" hun "A hasznalt tabla tipus (%s) nem tamogatja a BLOB/TEXT mezoket" + kor "스토리지 엔진 (%s)는 BLOB/TEXT 컬럼을 지원하지 않습니다." ita "Il tipo di tabella usata (%s) non supporta colonne di tipo BLOB/TEXT" por "Tipo de tabela usado (%s) não permite colunas BLOB/TEXT" rum "Tipul de tabela folosit (%s) nu suporta coloane de tip BLOB/TEXT" @@ -3706,6 +3708,7 @@ ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 42000 fre "Ce type de table (%s) ne supporte pas les colonnes AUTO_INCREMENT" ger "Der verwendete Tabellentyp (%s) unterstützt keine AUTO_INCREMENT-Felder" hindi "स्टोरेज इंजन %s AUTO_INCREMENT कॉलम्स को सपोर्ट नहीं करता" + kor "스토리지 엔진 (%s)는 AUTO_INCREMENT를 지원하지 않습니다." hun "A hasznalt tabla tipus (%s) nem tamogatja az AUTO_INCREMENT tipusu mezoket" ita "Il tipo di tabella usata (%s) non supporta colonne di tipo AUTO_INCREMENT" por "Tipo de tabela usado (%s) não permite colunas AUTO_INCREMENT" From ef2749c90d7f050e7c876003c55aa20d1dee202d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Wed, 21 Apr 2021 09:21:24 +0300 Subject: [PATCH 5/8] Fixup: Event_queue_element_for_exec initializer list not supported on gcc-4.1 --- sql/event_data_objects.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h index 41626004100..8ed45d3699f 100644 --- a/sql/event_data_objects.h +++ b/sql/event_data_objects.h @@ -33,7 +33,11 @@ struct TABLE; class Event_queue_element_for_exec { public: - Event_queue_element_for_exec() : dbname{NULL, 0}, name{NULL, 0} {}; + Event_queue_element_for_exec() + { + dbname.str= NULL; dbname.length= 0; + name.str= NULL; name.length= 0; + }; ~Event_queue_element_for_exec(); bool From 2a7dd64425b6be51715f54756446398618cd1789 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Tue, 5 Jan 2021 18:08:25 +0200 Subject: [PATCH 6/8] MDEV-24526 binlog rotate via FLUSH LOGS may obsolate binlog file for recovery too eary There was race between a committing transaction and the following in binlog order FLUSH LOGS that could create a 2nd Binlog checkpoint (BCP) event in the new file *before* the first logged-in-old-binlog transaction gets committed in Innodb. That would cause the transaction loss at recovery, should the server stop right after the BCP. The race is tackled by enforcing the necessary set of mutexes to be acquired by FLUSH-LOGS handler in the correct order (of the group commit leader pattern). Note, there remain two cases where a similar race is still possible: - the above race as it is when the server is run with ("unlikely") non-default `--binlog-optimize-thread-scheduling=0` (MDEV-24530), and - at unlikely event of bin-logging of Incident event (MDEV-24531) that also triggers binlog rotation, in both cases though with lesser chances after the current fixes. --- .../r/binlog_checkpoint_flush_logs.result | 51 ++++++++++++ .../t/binlog_checkpoint_flush_logs.test | 79 +++++++++++++++++++ sql/log.cc | 19 +++++ 3 files changed, 149 insertions(+) create mode 100644 mysql-test/suite/binlog/r/binlog_checkpoint_flush_logs.result create mode 100644 mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test diff --git a/mysql-test/suite/binlog/r/binlog_checkpoint_flush_logs.result b/mysql-test/suite/binlog/r/binlog_checkpoint_flush_logs.result new file mode 100644 index 00000000000..125324e2928 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_checkpoint_flush_logs.result @@ -0,0 +1,51 @@ +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; +*** Test that FLUSH LOGS waits if a transaction ordered commit is in progress. +connect con1,localhost,root,,; +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go"; +INSERT INTO t1 VALUES (1, REPEAT("x", 1)); +connection default; +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; +SET DEBUG_SYNC= "rotate_after_rotate SIGNAL con_flush_ready WAIT_FOR default_go"; +FLUSH LOGS; +connect con2,localhost,root,,; +Trx_1 is not yet committed: +SELECT count(*) as 'ZERO' from t1; +ZERO +0 +Wait for Trx_2 has rotated binlog: +SET DEBUG_SYNC= "now WAIT_FOR con_flush_ready"; +SET DEBUG_SYNC= "now SIGNAL default_go"; +connection default; +Must be tree logs in the list: +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +master-bin.000003 # +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +master-bin.000001 # Gtid_list # # [] +master-bin.000001 # Binlog_checkpoint # # master-bin.000001 +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES (1, REPEAT("x", 1)) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Rotate # # master-bin.000002;pos=POS +Only one Binlog checkpoint must exist and point to master-bin.000001 +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +master-bin.000002 # Gtid_list # # [#-#-#] +master-bin.000002 # Binlog_checkpoint # # master-bin.000001 +SELECT count(*) as 'ONE' from t1; +ONE +1 +connection default; +DROP TABLE t1; +SET debug_sync = 'reset'; diff --git a/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test b/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test new file mode 100644 index 00000000000..e21f1eb308d --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_checkpoint_flush_logs.test @@ -0,0 +1,79 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc + +# References: +# +# MDEV-24526 binlog rotate via FLUSH LOGS may obsolate binlog file too eary +# +# The test for MDEV-24526 proves the fixes correct observed race condition +# between a commiting transaction and FLUSH-LOGS. +# The plot. +# Trx_1 (con1) transaction binlogs first +# to yield its turn acquiring LOCK_commit_ordered to Trx_2 and stand +# still waiting of a signal that will never arrive. +# Trx_2 can't acquire it in the fixed version even though +# Trx_3 makes sure Trx_2 has reached a post-rotation execution point +# to signal it to proceed. +# Then the server gets crashed and Trx_1 must recover unlike +# in the OLD buggy version. +# +SET GLOBAL innodb_flush_log_at_trx_commit= 1; +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; + +--echo *** Test that FLUSH LOGS waits if a transaction ordered commit is in progress. + +connect(con1,localhost,root,,); # Trx_1 +# hang before doing acquiring Commit Ordered mutex +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go"; + +--send INSERT INTO t1 VALUES (1, REPEAT("x", 1)) + +connection default; # Trx_2 + +SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; +SET DEBUG_SYNC= "rotate_after_rotate SIGNAL con_flush_ready WAIT_FOR default_go"; +--send FLUSH LOGS + +connect(con2,localhost,root,,); # Trx_3 +--echo Trx_1 is not yet committed: +SELECT count(*) as 'ZERO' from t1; + +--echo Wait for Trx_2 has rotated binlog: +SET DEBUG_SYNC= "now WAIT_FOR con_flush_ready"; +# Useless signal to prove Trx_2 cannot race Trx_1's commit +# even though Trx_1 never received the being waited 'con1_go'. +SET DEBUG_SYNC= "now SIGNAL default_go"; + +--let $shutdown_timeout=0 +--source include/restart_mysqld.inc + +connection default; +--enable_reconnect +--error 0,2013 +--reap + +--echo Must be tree logs in the list: +--source include/show_binary_logs.inc +--let $binlog_file= master-bin.000001 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + +--echo Only one Binlog checkpoint must exist and point to master-bin.000001 +--let $binlog_file= master-bin.000002 +--let $binlog_start= 4 +--source include/show_binlog_events.inc + + +# In the buggy server version the following select may have +# resulted with ZERO: +SELECT count(*) as 'ONE' from t1; + +# Clean up. +connection default; + +DROP TABLE t1; +SET debug_sync = 'reset'; diff --git a/sql/log.cc b/sql/log.cc index dc8df9c6fdb..1d9b4645421 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6851,6 +6851,9 @@ int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate, bool check_purge= false; mysql_mutex_lock(&LOCK_log); + + DEBUG_SYNC(current_thd, "rotate_after_acquire_LOCK_log"); + prev_binlog_id= current_binlog_id; if ((err_gtid= do_delete_gtid_domain(domain_drop_lex))) @@ -6861,11 +6864,22 @@ int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate, } else if ((error= rotate(force_rotate, &check_purge))) check_purge= false; + + DEBUG_SYNC(current_thd, "rotate_after_rotate"); + /* NOTE: Run purge_logs wo/ holding LOCK_log because it does not need the mutex. Otherwise causes various deadlocks. + Explicit binlog rotation must be synchronized with a concurrent + binlog ordered commit, in particular not let binlog + checkpoint notification request until early binlogged + concurrent commits have has been completed. */ + mysql_mutex_lock(&LOCK_after_binlog_sync); mysql_mutex_unlock(&LOCK_log); + mysql_mutex_lock(&LOCK_commit_ordered); + mysql_mutex_unlock(&LOCK_after_binlog_sync); + mysql_mutex_unlock(&LOCK_commit_ordered); if (check_purge) checkpoint_and_purge(prev_binlog_id); @@ -8014,7 +8028,12 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) } DEBUG_SYNC(leader->thd, "commit_before_get_LOCK_commit_ordered"); + mysql_mutex_lock(&LOCK_commit_ordered); + DBUG_EXECUTE_IF("crash_before_engine_commit", + { + DBUG_SUICIDE(); + }); last_commit_pos_offset= commit_offset; /* From 64eeb250eb550138c46b3ea0b3aeb2843918de90 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 20 Apr 2021 22:33:22 +0300 Subject: [PATCH 7/8] MDEV-25457 Server crashes in row_undo_mod_clust_low upon rollback of read-only transaction node->index was NULL. But it's possible to get dict_table_t* from another source. --- mysql-test/suite/innodb/r/temporary_table.result | 5 +++++ mysql-test/suite/innodb/t/temporary_table.test | 6 ++++++ storage/innobase/row/row0umod.cc | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/temporary_table.result b/mysql-test/suite/innodb/r/temporary_table.result index 490179fe6cb..0307ba88200 100644 --- a/mysql-test/suite/innodb/r/temporary_table.result +++ b/mysql-test/suite/innodb/r/temporary_table.result @@ -754,3 +754,8 @@ COUNT(*) INSERT INTO t VALUES (0); SET SESSION tx_read_only=OFF; DROP TABLE t; +CREATE TEMPORARY TABLE t (a INT) ENGINE=InnoDB; +INSERT INTO t VALUES (1); +START TRANSACTION READ ONLY; +UPDATE t SET a = NULL; +ROLLBACK; diff --git a/mysql-test/suite/innodb/t/temporary_table.test b/mysql-test/suite/innodb/t/temporary_table.test index 42bd403d0be..d7fe66e2efb 100644 --- a/mysql-test/suite/innodb/t/temporary_table.test +++ b/mysql-test/suite/innodb/t/temporary_table.test @@ -595,3 +595,9 @@ SELECT COUNT(*)FROM t; INSERT INTO t VALUES (0); SET SESSION tx_read_only=OFF; DROP TABLE t; + +CREATE TEMPORARY TABLE t (a INT) ENGINE=InnoDB; +INSERT INTO t VALUES (1); +START TRANSACTION READ ONLY; +UPDATE t SET a = NULL; +ROLLBACK; diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index d207aa5b9bc..6ccb2250c05 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -109,7 +109,8 @@ row_undo_mod_clust_low( ut_ad(success); ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur), btr_cur_get_index(btr_cur)) - == thr_get_trx(thr)->id || node->index->table->is_temporary()); + == thr_get_trx(thr)->id + || btr_cur_get_index(btr_cur)->table->is_temporary()); if (mode != BTR_MODIFY_LEAF && dict_index_is_online_ddl(btr_cur_get_index(btr_cur))) { From fb96ac0a496f0665b3feca3cf85aeeedf4bd1e23 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 21 Apr 2021 21:12:33 +0530 Subject: [PATCH 8/8] MDEV-25474 Background thread returns uninitialized statistics to mysql interpreter InnoDB returns uninitialized statistics to mysql interpreter when background thread is opening the table. So it leads to assertion failure. In that case, InnoDB avoid sending innodb statistics information to mysql interpreter. --- storage/innobase/handler/ha_innodb.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b837aec396b..c95e6646968 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6261,9 +6261,10 @@ no_such_table: innobase_copy_frm_flags_from_table_share(ib_table, table->s); + const bool bk_thread = THDVAR(thd, background_thread); /* No point to init any statistics if tablespace is still encrypted or if table is being opened by background thread */ - if (THDVAR(thd, background_thread)) { + if (bk_thread) { } else if (ib_table->is_readable()) { dict_stats_init(ib_table); } else { @@ -6515,7 +6516,10 @@ no_such_table: } } - info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); + if (!bk_thread) { + info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); + } + DBUG_RETURN(0); }