diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index a556b5875df..664b0be6ba4 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -8263,7 +8263,7 @@ ha_innobase::write_row(
 
 			switch (thd_sql_command(m_user_thd)) {
 			case SQLCOM_LOAD:
-				if (!trx->duplicates) {
+				if (!m_prebuilt->allow_duplicates()) {
 					break;
 				}
 
@@ -15547,7 +15547,8 @@ ha_innobase::extra(
 		break;
 	case HA_EXTRA_RESET_STATE:
 		reset_template();
-		thd_to_trx(ha_thd())->duplicates = 0;
+		m_prebuilt->replace = 0;
+		m_prebuilt->on_duplicate_key_update = 0;
 		break;
 	case HA_EXTRA_NO_KEYREAD:
 		m_prebuilt->read_just_key = 0;
@@ -15558,24 +15559,17 @@ ha_innobase::extra(
 	case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
 		m_prebuilt->keep_other_fields_on_keyread = 1;
 		break;
-
-		/* IMPORTANT: m_prebuilt->trx can be obsolete in
-		this method, because it is not sure that MySQL
-		calls external_lock before this method with the
-		parameters below.  We must not invoke update_thd()
-		either, because the calling threads may change.
-		CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
 	case HA_EXTRA_INSERT_WITH_UPDATE:
-		thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
+		m_prebuilt->on_duplicate_key_update = 1;
 		break;
 	case HA_EXTRA_NO_IGNORE_DUP_KEY:
-		thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
+		m_prebuilt->on_duplicate_key_update = 0;
 		break;
 	case HA_EXTRA_WRITE_CAN_REPLACE:
-		thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
+		m_prebuilt->replace = 1;
 		break;
 	case HA_EXTRA_WRITE_CANNOT_REPLACE:
-		thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
+		m_prebuilt->replace = 0;
 		break;
 	case HA_EXTRA_BEGIN_ALTER_COPY:
 		m_prebuilt->table->skip_alter_undo = 1;
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 60f53221c9a..e72d4cc7c9f 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2017, 2019, MariaDB Corporation.
 
 This program is free software; you can redistribute it and/or modify it under
@@ -616,6 +616,15 @@ struct row_prebuilt_t {
 					not to be confused with InnoDB
 					externally stored columns
 					(VARCHAR can be off-page too) */
+	/** 1 if extra(HA_EXTRA_INSERT_WITH_UPDATE) was requested,
+	which happens when ON DUPLICATE KEY UPDATE clause is present,
+	0 otherwise */
+	unsigned	on_duplicate_key_update:1;
+
+	/** 1 if extra(HA_EXTRA_WRITE_CAN_REPLACE) was requested,
+	which happen when REPLACE is done instead of regular INSERT,
+	0 otherwise */
+	unsigned	replace:1;
 	mysql_row_templ_t* mysql_template;/*!< template used to transform
 					rows fast between MySQL and Innobase
 					formats; memory for this template
@@ -792,6 +801,13 @@ struct row_prebuilt_t {
 
 	/** The MySQL table object */
 	TABLE*		m_mysql_table;
+
+	/** @return whether the operation is REPLACE or
+	ON DUPLICATE KEY UPDATE instead of a regular INSERT,
+	that is, whether duplicate values should be allowed
+	(and further processed) instead of causing an error. */
+	bool allow_duplicates() const
+	{ return replace || on_duplicate_key_update; }
 };
 
 /** Callback for row_mysql_sys_index_iterate() */
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 1d71920d6c5..69f7149e05f 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2019, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2015, 2019, MariaDB Corporation.
 
 This program is free software; you can redistribute it and/or modify it under
@@ -937,7 +937,6 @@ struct trx_t {
 					the transaction; in that case we must
 					flush the log in
 					trx_commit_complete_for_mysql() */
-	ulint		duplicates;	/*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
 	trx_dict_op_t	dict_operation;	/**< @see enum trx_dict_op_t */
 
 	/* Fields protected by the srv_conc_mutex. */
@@ -1254,12 +1253,6 @@ inline bool trx_is_started(const trx_t* trx)
 						converted to LOCK IN SHARE
 						MODE reads */
 
-/* Treatment of duplicate values (trx->duplicates; for example, in inserts).
-Multiple flags can be combined with bitwise OR. */
-#define TRX_DUP_IGNORE	1U	/* duplicate rows are to be updated */
-#define TRX_DUP_REPLACE	2U	/* duplicate rows are to be replaced */
-
-
 /** Commit node states */
 enum commit_node_state {
 	COMMIT_NODE_SEND = 1,	/*!< about to send a commit signal to
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 9fdc8feee90..756235e429e 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -2587,22 +2587,11 @@ lock_rec_inherit_to_gap(
 
 	ut_ad(lock_mutex_own());
 
-	/* If srv_locks_unsafe_for_binlog is TRUE or session is using
-	READ COMMITTED isolation level, we do not want locks set
-	by an UPDATE or a DELETE to be inherited as gap type locks. But we
-	DO want S-locks/X-locks(taken for replace) set by a consistency
-	constraint to be inherited also then. */
-
 	for (lock = lock_rec_get_first(lock_sys->rec_hash, block, heap_no);
 	     lock != NULL;
 	     lock = lock_rec_get_next(heap_no, lock)) {
 
-		if (!lock_rec_get_insert_intention(lock)
-		    && !((srv_locks_unsafe_for_binlog
-			  || lock->trx->isolation_level
-			  <= TRX_ISO_READ_COMMITTED)
-			 && lock_get_mode(lock) ==
-			 (lock->trx->duplicates ? LOCK_S : LOCK_X))) {
+		if (!lock_rec_get_insert_intention(lock)) {
 			lock_rec_add_to_queue(
 				LOCK_REC | LOCK_GAP | lock_get_mode(lock),
 				heir_block, heir_heap_no, lock->index,
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 17c45503cc1..7e035f40e4d 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -2094,7 +2094,6 @@ row_ins_scan_sec_index_for_duplicate(
 	ulint		n_fields_cmp;
 	btr_pcur_t	pcur;
 	dberr_t		err		= DB_SUCCESS;
-	ulint		allow_duplicates;
 	ulint*		offsets		= NULL;
 	DBUG_ENTER("row_ins_scan_sec_index_for_duplicate");
 
@@ -2130,7 +2129,8 @@ row_ins_scan_sec_index_for_duplicate(
 		      : BTR_SEARCH_LEAF,
 		      &pcur, mtr);
 
-	allow_duplicates = thr_get_trx(thr)->duplicates;
+	const bool allow_duplicates = thr->prebuilt
+		&& thr->prebuilt->allow_duplicates();
 
 	/* Scan index records and check if there is a duplicate */
 
@@ -2351,8 +2351,8 @@ row_ins_duplicate_error_in_clust(
 			if (flags & BTR_NO_LOCKING_FLAG) {
 				/* Do nothing if no-locking is set */
 				err = DB_SUCCESS;
-			} else if (trx->duplicates) {
-
+			} else if (thr->prebuilt
+				   && thr->prebuilt->allow_duplicates()) {
 				/* If the SQL-query will update or replace
 				duplicate key we will take X-lock for
 				duplicates ( REPLACE, LOAD DATAFILE REPLACE,
@@ -2397,8 +2397,8 @@ row_ins_duplicate_error_in_clust(
 						  true,
 						  ULINT_UNDEFINED, &heap);
 
-			if (trx->duplicates) {
-
+			if (thr->prebuilt
+			    && thr->prebuilt->allow_duplicates()) {
 				/* If the SQL-query will update or replace
 				duplicate key we will take X-lock for
 				duplicates ( REPLACE, LOAD DATAFILE REPLACE,
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 6da08872a9a..d1c3af1e2f3 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -2894,8 +2894,6 @@ row_log_table_apply(
 	dict_index_t*	clust_index;
 
 	thr_get_trx(thr)->error_key_num = 0;
-	DBUG_EXECUTE_IF("innodb_trx_duplicates",
-			thr_get_trx(thr)->duplicates = TRX_DUP_REPLACE;);
 
 	stage->begin_phase_log_table();
 
@@ -2926,8 +2924,6 @@ row_log_table_apply(
 	}
 
 	rw_lock_x_unlock(dict_index_get_lock(clust_index));
-	DBUG_EXECUTE_IF("innodb_trx_duplicates",
-			thr_get_trx(thr)->duplicates = 0;);
 
 	return(error);
 }
