I have simplified the test case a little bit more: DROP TABLE IF EXISTS `t`; CREATE TABLE `t` ( `f1` int(10) unsigned NOT NULL, PRIMARY KEY (`f1`) ) ENGINE=InnoDB; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `f1` int(10) unsigned NOT NULL, PRIMARY KEY (`f1`) ) ENGINE=InnoDB; DROP TRIGGER IF EXISTS t_insert_trig; DELIMITER ;; CREATE TRIGGER t_insert_trig AFTER INSERT ON t FOR EACH ROW BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK TO savepoint_1; INSERT INTO t1 VALUES(NEW.f1); //<------- Crash Line END; SAVEPOINT savepoint_1; //<---------SAVEPOINT Line INSERT INTO dummy VALUES (1); END ;; DELIMITER ; INSERT INTO `t` VALUES (2); INSERT INTO `t` VALUES (3); //<-------SECOND INSERT Line "Crash Line" is the line which absence cause the crash. If this line is commented out we have crash. Why trans->ha_list does not contain binlog handlerton item to initialize it's per-engine savepoint data. So there are two cases. The one is without crash (Case_Good) when "Crash Line" presents, the other one is with crash (Case_Crash) when "Crash Line" absents. The question is why thd->transaction.stmt.ha_list does not contain item which corresponds to binlog_handlerton for Case_Crash? 1) Consider Case_Good. The question can be restated as: "Why thd->transaction.stmt.ha_list contains item which corresponds to binlog_handlerton for the Case_Good?" Consider events after executing first ha_savepoint() and ha_rollback_to_savepoint() calls. a) binlog handlerton is set in write_locked_table_maps() if thd->binlog_table_maps is 0. b) thd->binlog_table_maps is set to 0 only if binlog_cache_data::m_pending is not 0 #0 THD::clear_binlog_table_maps (this=0x20adb10) at ./sql/sql_class.h:2646 #1 0x0000000000a47b30 in binlog_cache_data::flush_pending_event (this=0x7fffa000e660, thd=0x20adb10) at ./sql/binlog.cc:499 #2 0x0000000000a3280f in binlog_cache_data::finalize (this=0x7fffa000e660, thd=0x20adb10, end_event=0x7fffdc0d16d0) at ./sql/binlog.cc:1207 #3 0x0000000000a406e3 in MYSQL_BIN_LOG::commit (this=0x1859dc0 , thd=0x20adb10, all=false) at ./sql/binlog.cc:6675 #4 0x0000000000637b29 in ha_commit_trans (thd=0x20adb10, all=false, ignore_global_read_lock=false) at ./sql/handler.cc:1513 #5 0x00000000008aa3d2 in trans_commit_stmt (thd=0x20adb10) at ./sql/transaction.cc:436 #6 0x00000000007dcace in mysql_execute_command (thd=0x20adb10) at ./sql/sql_parse.cc:5573 #7 0x00000000007dfe00 in mysql_parse (thd=0x20adb10, rawbuf=0x7fffa0004ff0 "INSERT INTO `t` VALUES (2)", length=26, parser_state=0x7fffdc0d41d0) at ./sql/sql_parse.cc:6955 #8 0x00000000007d1da0 in dispatch_command (command=COM_QUERY, thd=0x20adb10, packet=0x2193b61 "INSERT INTO `t` VALUES (2)", packet_length=26) at ./sql/sql_parse.cc:1442 #9 0x00000000007d0c55 in do_command (thd=0x20adb10) at ./sql/sql_parse.cc:1054 #10 0x000000000079a5d8 in do_handle_one_connection (thd_arg=0x20adb10) at ./sql/sql_connect.cc:1532 #11 0x000000000079a0ef in handle_one_connection (arg=0x20adb10) at ./sql/sql_connect.cc:1443 #12 0x0000000000da1942 in pfs_spawn_thread (arg=0x214f5c0) at ./storage/perfschema/pfs.cc:1860 #13 0x00007ffff737d182 in start_thread (arg=0x7fffdc0d5700) at pthread_create.c:312 #14 0x00007ffff688a47d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111 c) binlog_cache_data::m_pending is set from here: #0 binlog_cache_data::set_pending (this=0x7fffa000e660, pending=0x7fffa0069560) at ./sql/binlog.cc:368 #1 0x0000000000a3cd3e in MYSQL_BIN_LOG::flush_and_set_pending_rows_event (this=0x1859dc0 , thd=0x20adb10, event=0x7fffa0069560, is_transactional=true) at ./sql/binlog.cc:5412 #2 0x0000000000a489ad in THD::binlog_prepare_pending_rows_event (this=0x20adb10, table=0x7fffa0066840, serv_id=1, needed=5, is_transactional=true, hint=0x0, extra_row_info=0x0) at ./sql/binlog.cc:8716 #3 0x0000000000a44969 in THD::binlog_write_row (this=0x20adb10, table=0x7fffa0066840, is_trans=true, record=0x7fffa0067620 "\377\002", extra_row_info=0x0) at ./sql/binlog.cc:8874 #4 0x0000000000648fd2 in Write_rows_log_event::binlog_row_logging_function (thd=0x20adb10, table=0x7fffa0066840, is_transactional=true, before_record=0x0, after_record=0x7fffa0067620 "\377\002") at ./sql/log_event.h:4533 #5 0x000000000064496f in binlog_log_row (table=0x7fffa0066840, before_record=0x0, after_record=0x7fffa0067620 "\377\002", log_func=0x648f97 ) at ./sql/handler.cc:7551 #6 0x0000000000644f16 in handler::ha_write_row (this=0x7fffa0067130, buf=0x7fffa0067620 "\377\002") at ./sql/handler.cc:7688 #7 0x00000000007b8346 in write_record (thd=0x20adb10, table=0x7fffa0066840, info=0x7fffdc0d07e0, update=0x7fffdc0d0860) at ./sql/sql_insert.cc:1947 #8 0x00000000007b605e in mysql_insert (thd=0x20adb10, table_list=0x7fffa0058880, fields=..., values_list=..., update_fields=..., update_values=..., duplic=DUP_ERROR, ignore=false) at ./sql/sql_insert.cc:1085 #9 0x00000000007d7b17 in mysql_execute_command (thd=0x20adb10) at ./sql/sql_parse.cc:3897 #10 0x000000000098eea0 in sp_instr_stmt::exec_core (this=0x7fffa0058fa0, thd=0x20adb10, nextp=0x7fffdc0d2090) at ./sql/sp_instr.cc:937 #11 0x000000000098dc47 in sp_lex_instr::reset_lex_and_exec_core (this=0x7fffa0058fa0, thd=0x20adb10, nextp=0x7fffdc0d2090, open_tables=false) at ./sql/sp_instr.cc:391 #12 0x000000000098e5f8 in sp_lex_instr::validate_lex_and_execute_core (this=0x7fffa0058fa0, thd=0x20adb10, nextp=0x7fffdc0d2090, open_tables=false) at ./sql/sp_instr.cc:642 #13 0x000000000098eb36 in sp_instr_stmt::execute (this=0x7fffa0058fa0, thd=0x20adb10, nextp=0x7fffdc0d2090) at ./sql/sp_instr.cc:825 #14 0x000000000072d099 in sp_head::execute (this=0x7fffa00577d0, thd=0x20adb10, merge_da_on_success=false) at ./sql/sp_head.cc:648 #15 0x000000000072db03 in sp_head::execute_trigger (this=0x7fffa00577d0, thd=0x20adb10, db_name=0x7fffa0056010, table_name=0x7fffa0056020, grant_info=0x7fffa0056fc8) at ./sql/sp_head.cc:895 #16 0x0000000000865ce3 in Table_triggers_list::process_triggers (this=0x7fffa0056f00, thd=0x20adb10, event=TRG_EVENT_INSERT, time_type=TRG_ACTION_AFTER, old_row_is_record1=true) at ./sql/sql_trigger.cc:2184 #17 0x00000000007b847a in write_record (thd=0x20adb10, table=0x7fffa0049550, info=0x7fffdc0d28d0, update=0x7fffdc0d2950) at ./sql/sql_insert.cc:1962 #18 0x00000000007b605e in mysql_insert (thd=0x20adb10, table_list=0x7fffa00050d8, fields=..., values_list=..., update_fields=..., update_values=..., duplic=DUP_ERROR, ignore=false) at ./sql/sql_insert.cc:1085 #19 0x00000000007d7b17 in mysql_execute_command (thd=0x20adb10) at ./sql/sql_parse.cc:3897 #20 0x00000000007dfe00 in mysql_parse (thd=0x20adb10, rawbuf=0x7fffa0004ff0 "INSERT INTO `t` VALUES (2)", length=26, parser_state=0x7fffdc0d41d0) at ./sql/sql_parse.cc:6955 #21 0x00000000007d1da0 in dispatch_command (command=COM_QUERY, thd=0x20adb10, packet=0x2193b61 "INSERT INTO `t` VALUES (2)", packet_length=26) at ./sql/sql_parse.cc:1442 #22 0x00000000007d0c55 in do_command (thd=0x20adb10) at ./sql/sql_parse.cc:1054 #23 0x000000000079a5d8 in do_handle_one_connection (thd_arg=0x20adb10) at ./sql/sql_connect.cc:1532 #24 0x000000000079a0ef in handle_one_connection (arg=0x20adb10) at ./sql/sql_connect.cc:1443 #25 0x0000000000da1942 in pfs_spawn_thread (arg=0x214f5c0) The sequence is the following: binlog_cache_data::set_pending() - is set from "Crash Line", i.e. "INSERT" just after "ROLLBACK" in trigger; binlog_cache_data::flush_pending_event()-(as binlog_cache_data::m_pending is not 0)-> THD::clear_binlog_table_maps() ; write_locked_table_maps()-(as thd->binlog_table_maps is 0)->binlog_start_trans_and_stmt()->THD::binlog_write_table_map->register_binlog_handler() 2) Consider Case_Crash. Why thd->transaction.stmt.ha_list does not contain item which corresponds to binlog_handlerton for the Case_Crash? Consider events after executing first ha_savepoint() and ha_rollback_to_savepoint() calls as for (1). The sequence is the following: binlog_cache_data::flush_pending_event() - does not invoke THD::clear_binlog_table_maps() as binlog_cache_data::m_pending is 0; write_locked_table_maps() - does not invoke register_binlog_handler() as thd->binlog_table_maps is not 0 3) Where binlog_cache_data::m_pending is set to 0? #0 binlog_cache_data::set_pending (this=0x7fffa0021e80, pending=0x0) at ./sql/binlog.cc:367 #1 0x0000000000a3cd3e in MYSQL_BIN_LOG::flush_and_set_pending_rows_event (this=0x1859dc0 , thd=0x20adb10, event=0x0, is_transactional=true) at ./sql/binlog.cc:5412 #2 0x0000000000a45465 in THD::binlog_flush_pending_rows_event (this=0x20adb10, stmt_end=false, is_transactional=true) at ./sql/binlog.cc:9088 #3 0x0000000000a3ce8a in MYSQL_BIN_LOG::write_event (this=0x1859dc0 , event_info=0x7fffdc0cfaf0) at ./sql/binlog.cc:5447 #4 0x0000000000a3403d in binlog_savepoint_set (hton=0x188ca40, thd=0x20adb10, sv=0x7fffa0007040) at ./sql/binlog.cc:1868 #5 0x000000000063961e in ha_savepoint (thd=0x20adb10, sv=0x7fffa0007010) at ./sql/handler.cc:2239 #6 0x00000000008aa961 in trans_savepoint (thd=0x20adb10, name=...) at ./sql/transaction.cc:568 #7 0x00000000007dabd0 in mysql_execute_command (thd=0x20adb10) at ./sql/sql_parse.cc:4848 #8 0x000000000098eea0 in sp_instr_stmt::exec_core (this=0x7fffa0067e50, thd=0x20adb10, nextp=0x7fffdc0d2090) at ./sql/sp_instr.cc:937 #9 0x000000000098dc47 in sp_lex_instr::reset_lex_and_exec_core (this=0x7fffa0067e50, thd=0x20adb10, nextp=0x7fffdc0d2090, open_tables=false) at ./sql/sp_instr.cc:391 #10 0x000000000098e5f8 in sp_lex_instr::validate_lex_and_execute_core (this=0x7fffa0067e50, thd=0x20adb10, nextp=0x7fffdc0d2090, open_tables=false) at ./sql/sp_instr.cc:642 #11 0x000000000098eb36 in sp_instr_stmt::execute (this=0x7fffa0067e50, thd=0x20adb10, nextp=0x7fffdc0d2090) at ./sql/sp_instr.cc:825 #12 0x000000000072d099 in sp_head::execute (this=0x7fffa00664c0, thd=0x20adb10, merge_da_on_success=false) at ./sql/sp_head.cc:648 #13 0x000000000072db03 in sp_head::execute_trigger (this=0x7fffa00664c0, thd=0x20adb10, db_name=0x7fffa0056010, table_name=0x7fffa0056020, grant_info=0x7fffa004dcb8) at ./sql/sp_head.cc:895 #14 0x0000000000865ce3 in Table_triggers_list::process_triggers (this=0x7fffa004dbf0, thd=0x20adb10, event=TRG_EVENT_INSERT, time_type=TRG_ACTION_AFTER, old_row_is_record1=true) at ./sql/sql_trigger.cc:2184 #15 0x00000000007b847a in write_record (thd=0x20adb10, table=0x7fffa0064a10, info=0x7fffdc0d28d0, update=0x7fffdc0d2950) at ./sql/sql_insert.cc:1962 #16 0x00000000007b605e in mysql_insert (thd=0x20adb10, table_list=0x7fffa00050d8, fields=..., values_list=..., update_fields=..., update_values=..., duplic=DUP_ERROR, ignore=false) at ./sql/sql_insert.cc:1085 #17 0x00000000007d7b17 in mysql_execute_command (thd=0x20adb10) at ./sql/sql_parse.cc:3897 #18 0x00000000007dfe00 in mysql_parse (thd=0x20adb10, rawbuf=0x7fffa0004ff0 "INSERT INTO `t` VALUES (2)", length=26, parser_state=0x7fffdc0d41d0) at ./sql/sql_parse.cc:6955 #19 0x00000000007d1da0 in dispatch_command (command=COM_QUERY, thd=0x20adb10, packet=0x2193b61 "INSERT INTO `t` VALUES (2)", packet_length=26) at ./sql/sql_parse.cc:1442 #20 0x00000000007d0c55 in do_command (thd=0x20adb10) at ./sql/sql_parse.cc:1054 #21 0x000000000079a5d8 in do_handle_one_connection (thd_arg=0x20adb10) at ./sql/sql_connect.cc:1532 #22 0x000000000079a0ef in handle_one_connection (arg=0x20adb10) at ./sql/sql_connect.cc:1443 #23 0x0000000000da1942 in pfs_spawn_thread (arg=0x214f5c0) at ./storage/perfschema/pfs.cc:1860 #24 0x00007ffff737d182 in start_thread (arg=0x7fffdc0d5700) at pthread_create.c:312 #25 0x00007ffff688a47d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111 Summary: Part 1. binlog_cache_data::m_pending is set to 0 when binlog_savepoint_set() is first time invoked from ha_savepoint() when "SAVEPOINT Line" is first time executed(see (3)). After this binlog_cache_data::flush_pending_event() is invoked (see (1b)) and as binlog_cache_data::m_pending is 0 THD::clear_binlog_table_maps() is not invoked and THD::binlog_table_maps is not zeroed. The next write_locked_table_maps() invocation for "SECOND INSERT Line" does not invoke register_binlog_handler() as THD::binlog_table_maps is not zeroed. Part 2. As register_binlog_handler() was not invoked thd->transactions.stmt.ha_list does not contain the item for binlog_handler and on the next ha_savepoint() execution for "SECOND INSERT Line" will not invoke binlog_savepoint_set(). Recall there is some extra memory allocated just after SAVEPOINT instance which contains some per-engine information(see analysis #1-(4)). binlog_savepoint_set() initializes corresponding memory allocated for binary log goals. As this function was not invoked this memory is uninitialized. The value which is stored in this memory is savepoint position in binary log file. It is used when "ROLLBACK TO SAVEPOINT" is executed (see analysis #1-(2)). binlog_cache_data::cache_log.pos_in_file is initialized with this value when ha_rollback_to_savepoint() is executed (see analysis #1-(2)). binlog_cache_data::cache_log.pos_in_file contains undefined value binlog_cache_data::is_binlog_empty() can return false and we will see the assertion in debug version. In the case if the version is not debug more likely wrong value in binlog_cache_data::cache_log.pos_in_file can lead to binary log file damaging.