diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c
index d468d1cd8497903b545e60c2dac45fb3268e4295..924f8bbc42bec63b7227699b25fcbb36d4ea3439 100644
--- a/src/box/memtx_engine.c
+++ b/src/box/memtx_engine.c
@@ -384,15 +384,7 @@ static int
 memtx_engine_begin(struct engine *engine, struct txn *txn)
 {
 	(void)engine;
-	/*
-	 * Register a trigger to rollback transaction on yield.
-	 * This must be done in begin(), since it's
-	 * the first thing txn invokes after txn->n_stmts++,
-	 * to match with trigger_clear() in rollbackStatement().
-	 */
-	if (txn->is_autocommit == false) {
-		memtx_init_txn(txn);
-	}
+	(void)txn;
 	return 0;
 }
 
@@ -404,15 +396,9 @@ memtx_engine_begin_statement(struct engine *engine, struct txn *txn)
 	if (txn->engine_tx == NULL) {
 		struct space *space = txn_last_stmt(txn)->space;
 
-		if (space->def->id > BOX_SYSTEM_ID_MAX &&
-		    ! rlist_empty(&space->on_replace)) {
-			/**
-			 * A space on_replace trigger may initiate
-			 * a yield.
-			 */
-			assert(txn->is_autocommit);
+		if (space->def->id > BOX_SYSTEM_ID_MAX)
+			/* Setup triggers for non-ddl transactions. */
 			memtx_init_txn(txn);
-		}
 	}
 	return 0;
 }
diff --git a/src/box/txn.c b/src/box/txn.c
index deb4fac478de5ff3908e2a1e47cf8c0406794f0b..618711ce54afb144083da0a8a64df37d9698c0e6 100644
--- a/src/box/txn.c
+++ b/src/box/txn.c
@@ -191,7 +191,6 @@ txn_begin_stmt(struct space *space)
 		diag_set(ClientError, ER_SUB_STMT_MAX);
 		return NULL;
 	}
-
 	struct txn_stmt *stmt = txn_stmt_new(txn);
 	if (stmt == NULL) {
 		if (txn->is_autocommit && txn->in_sub_stmt == 0)
@@ -430,7 +429,7 @@ txn_abort(struct txn *txn)
 int
 txn_check_singlestatement(struct txn *txn, const char *where)
 {
-	if (!txn->is_autocommit || !txn_is_first_statement(txn)) {
+	if (!txn_is_first_statement(txn)) {
 		diag_set(ClientError, ER_UNSUPPORTED,
 			 where, "multi-statement transactions");
 		return -1;
diff --git a/src/box/txn.h b/src/box/txn.h
index c9829da9ec09340fe2e3b148d2794eb08c44722c..27bef7e2f033b401ce4f759358c2bf5f860c85c0 100644
--- a/src/box/txn.h
+++ b/src/box/txn.h
@@ -309,9 +309,8 @@ void
 txn_rollback_stmt();
 
 /**
- * Raise an error if this is a multi-statement
- * transaction: DDL can not be part of a multi-statement
- * transaction and must be run in autocommit mode.
+ * Raise an error if this is a multi-statement transaction: DDL
+ * can not be part of a multi-statement transaction.
  */
 int
 txn_check_singlestatement(struct txn *txn, const char *where);
diff --git a/test/box/ddl.result b/test/box/ddl.result
index 3d6d07f437a67d5533342f7b1efc463c0c38d0b4..e48284ffdf1bedf11d30019b99ea57348a224535 100644
--- a/test/box/ddl.result
+++ b/test/box/ddl.result
@@ -299,11 +299,7 @@ box.space._collation:replace(c)
 ---
 - error: collation does not support alter
 ...
-box.begin() box.internal.collation.create('test2', 'ICU', 'ru_RU')
----
-- error: Space _collation does not support multi-statement transactions
-...
-box.rollback()
+box.begin() box.internal.collation.create('test2', 'ICU', 'ru_RU') box.rollback()
 ---
 ...
 box.internal.collation.create('test', 'ICU', 'ru_RU')
@@ -645,11 +641,11 @@ _ = fiber.create(function()
 end);
 ---
 ...
+-- Should be Ok for now
 box.begin()
     test_latch:create_index("sec2", {unique = true, parts = {2, 'unsigned'}})
 box.commit();
 ---
-- error: DDL does not support multi-statement transactions
 ...
 test_run:cmd("setopt delimiter ''");
 ---
diff --git a/test/box/ddl.test.lua b/test/box/ddl.test.lua
index 5c147cdfbf8a3ca063202c4927802e8b6d79c665..101bc6f9b6ad285ce1165dc2891eae9bb9c4ea9b 100644
--- a/test/box/ddl.test.lua
+++ b/test/box/ddl.test.lua
@@ -131,8 +131,7 @@ c = box.space._collation:get{1}:totable()
 c[2] = 'unicode_test'
 box.space._collation:replace(c)
 
-box.begin() box.internal.collation.create('test2', 'ICU', 'ru_RU')
-box.rollback()
+box.begin() box.internal.collation.create('test2', 'ICU', 'ru_RU') box.rollback()
 
 box.internal.collation.create('test', 'ICU', 'ru_RU')
 box.internal.collation.exists('test')
@@ -260,6 +259,7 @@ _ = fiber.create(function()
     c:put(true)
 end);
 
+-- Should be Ok for now
 box.begin()
     test_latch:create_index("sec2", {unique = true, parts = {2, 'unsigned'}})
 box.commit();
diff --git a/test/box/transaction.result b/test/box/transaction.result
index 8a4d11d3b24b02503b24ce855f76e0ac3700a597..807cd5c7ca2dd6a2f30c7898caacf047fb4fb346 100644
--- a/test/box/transaction.result
+++ b/test/box/transaction.result
@@ -84,77 +84,50 @@ while f:status() ~= 'dead' do fiber.sleep(0) end;
 ---
 ...
 -- transactions and system spaces
+-- some operation involves more than one ddl spaces, so they should fail
 box.begin() box.schema.space.create('test');
 ---
-- error: Space _schema does not support multi-statement transactions
-...
-box.rollback();
----
-...
-box.begin() box.schema.func.create('test');
----
-- error: Space _func does not support multi-statement transactions
+- error: DDL does not support multi-statement transactions
 ...
 box.rollback();
 ---
 ...
 box.begin() box.schema.user.create('test');
 ---
-- error: Space _user does not support multi-statement transactions
-...
-box.rollback();
----
-...
-box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv');
----
 - error: Space _priv does not support multi-statement transactions
 ...
 box.rollback();
 ---
 ...
-box.begin() box.space._user:delete{box.schema.GUEST_ID};
+-- but this is Ok now
+box.begin() box.schema.func.create('test') box.rollback();
 ---
-- error: Space _user does not support multi-statement transactions
 ...
-box.rollback();
+box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv') box.rollback();
 ---
 ...
-box.begin() box.space._space:delete{box.schema.CLUSTER_ID};
+space = box.schema.space.create('test');
 ---
-- error: DDL does not support multi-statement transactions
 ...
-box.rollback();
----
-...
-box.begin() box.space._sequence:insert{1, 1, 'test', 1, 1, 2, 1, 0, false};
----
-- error: Space _sequence does not support multi-statement transactions
-...
-box.rollback();
+box.begin() box.space._space:delete{space.id} box.rollback();
 ---
 ...
-box.begin() box.space._schema:insert{'test'};
+box.begin() box.space._space:delete{space.id} box.commit();
 ---
-- error: Space _schema does not support multi-statement transactions
 ...
-box.rollback();
+box.begin() box.space._sequence:insert{1, 1, 'test', 1, 1, 2, 1, 0, false} box.rollback();
 ---
 ...
-box.begin() box.space._cluster:insert{123456789, 'abc'};
+box.begin() box.space._schema:insert{'test'} box.rollback();
 ---
-- error: Space _cluster does not support multi-statement transactions
 ...
-box.rollback();
+box.begin() box.space._cluster:insert{30, '00000000-0000-0000-0000-000000000001'} box.rollback();
 ---
 ...
 s = box.schema.space.create('test');
 ---
 ...
-box.begin() index = s:create_index('primary');
----
-- error: DDL does not support multi-statement transactions
-...
-box.rollback();
+box.begin() index = s:create_index('primary') box.rollback();
 ---
 ...
 index = s:create_index('primary');
diff --git a/test/box/transaction.test.lua b/test/box/transaction.test.lua
index 8f7dfedec8b6f11ac7d3030ead22661be9ec7b16..0d212ca297b24a440d8dc895612efd4d4fccefd3 100644
--- a/test/box/transaction.test.lua
+++ b/test/box/transaction.test.lua
@@ -41,27 +41,22 @@ f = fiber.create(sloppy);
 -- ensure it's rolled back automatically
 while f:status() ~= 'dead' do fiber.sleep(0) end;
 -- transactions and system spaces
+-- some operation involves more than one ddl spaces, so they should fail
 box.begin() box.schema.space.create('test');
 box.rollback();
-box.begin() box.schema.func.create('test');
-box.rollback();
 box.begin() box.schema.user.create('test');
 box.rollback();
-box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv');
-box.rollback();
-box.begin() box.space._user:delete{box.schema.GUEST_ID};
-box.rollback();
-box.begin() box.space._space:delete{box.schema.CLUSTER_ID};
-box.rollback();
-box.begin() box.space._sequence:insert{1, 1, 'test', 1, 1, 2, 1, 0, false};
-box.rollback();
-box.begin() box.space._schema:insert{'test'};
-box.rollback();
-box.begin() box.space._cluster:insert{123456789, 'abc'};
-box.rollback();
+-- but this is Ok now
+box.begin() box.schema.func.create('test') box.rollback();
+box.begin() box.schema.user.grant('guest', 'read', 'space', '_priv') box.rollback();
+space = box.schema.space.create('test');
+box.begin() box.space._space:delete{space.id} box.rollback();
+box.begin() box.space._space:delete{space.id} box.commit();
+box.begin() box.space._sequence:insert{1, 1, 'test', 1, 1, 2, 1, 0, false} box.rollback();
+box.begin() box.space._schema:insert{'test'} box.rollback();
+box.begin() box.space._cluster:insert{30, '00000000-0000-0000-0000-000000000001'} box.rollback();
 s = box.schema.space.create('test');
-box.begin() index = s:create_index('primary');
-box.rollback();
+box.begin() index = s:create_index('primary') box.rollback();
 index = s:create_index('primary');
 t = nil
 function multi()
diff --git a/test/engine/ddl.result b/test/engine/ddl.result
index 8d34d5ef447d0d4c37e5d196dd282839144c3b3f..c493bd4ac59c89d12fba58efb6daad6620fa3479 100644
--- a/test/engine/ddl.result
+++ b/test/engine/ddl.result
@@ -2075,6 +2075,15 @@ i3:select()
 ...
 -- Check that recovery works.
 inspector:cmd("restart server default")
+test_run = require('test_run')
+---
+...
+inspector = test_run.new()
+---
+...
+engine = inspector:get_cfg('engine')
+---
+...
 s = box.space.test
 ---
 ...
@@ -2130,3 +2139,86 @@ box.snapshot()
 s:drop()
 ---
 ...
+-- test ddl operation within begin/commit/rollback
+-- acquire free space id
+space = box.schema.space.create('ddl_test', {engine = engine})
+---
+...
+id = space.id
+---
+...
+space:drop()
+---
+...
+inspector:cmd("setopt delimiter ';'")
+---
+- true
+...
+box.begin()
+s = box.schema.space.create('ddl_test', {engine = engine, id = id})
+box.rollback();
+---
+...
+box.begin()
+s = box.schema.space.create('ddl_test', {engine = engine, id = id})
+box.commit();
+---
+...
+box.begin()
+s:create_index('pk')
+box.rollback();
+---
+...
+box.begin()
+s:create_index('pk')
+box.commit();
+---
+...
+s:replace({1});
+---
+- [1]
+...
+s:replace({2});
+---
+- [2]
+...
+s:replace({3});
+---
+- [3]
+...
+box.begin()
+s:truncate()
+box.commit();
+---
+...
+s:select();
+---
+- []
+...
+box.begin()
+box.schema.user.grant('guest', 'write', 'space', 'ddl_test')
+box.rollback();
+---
+...
+box.begin()
+box.schema.user.grant('guest', 'write', 'space', 'ddl_test')
+box.commit();
+---
+...
+box.begin()
+box.schema.user.revoke('guest', 'write', 'space', 'ddl_test')
+box.rollback();
+---
+...
+box.begin()
+box.schema.user.revoke('guest', 'write', 'space', 'ddl_test')
+box.commit();
+---
+...
+-- index and space drop are not currently supported (because of truncate)
+s.index.pk:drop();
+---
+...
+s:drop();
+---
+...
diff --git a/test/engine/ddl.test.lua b/test/engine/ddl.test.lua
index cdaf7a5bf40b0871948b9b696fea6ba9ec103a8e..636f6c3b951bb47044655fc498899fdb8e5d7130 100644
--- a/test/engine/ddl.test.lua
+++ b/test/engine/ddl.test.lua
@@ -759,6 +759,9 @@ i3:select()
 
 -- Check that recovery works.
 inspector:cmd("restart server default")
+test_run = require('test_run')
+inspector = test_run.new()
+engine = inspector:get_cfg('engine')
 
 s = box.space.test
 s.index.i1:select()
@@ -775,3 +778,55 @@ s.index.i1:select()
 box.snapshot()
 
 s:drop()
+
+-- test ddl operation within begin/commit/rollback
+-- acquire free space id
+space = box.schema.space.create('ddl_test', {engine = engine})
+id = space.id
+space:drop()
+
+inspector:cmd("setopt delimiter ';'")
+box.begin()
+s = box.schema.space.create('ddl_test', {engine = engine, id = id})
+box.rollback();
+
+box.begin()
+s = box.schema.space.create('ddl_test', {engine = engine, id = id})
+box.commit();
+
+box.begin()
+s:create_index('pk')
+box.rollback();
+
+box.begin()
+s:create_index('pk')
+box.commit();
+
+s:replace({1});
+s:replace({2});
+s:replace({3});
+
+box.begin()
+s:truncate()
+box.commit();
+s:select();
+
+box.begin()
+box.schema.user.grant('guest', 'write', 'space', 'ddl_test')
+box.rollback();
+
+box.begin()
+box.schema.user.grant('guest', 'write', 'space', 'ddl_test')
+box.commit();
+
+box.begin()
+box.schema.user.revoke('guest', 'write', 'space', 'ddl_test')
+box.rollback();
+
+box.begin()
+box.schema.user.revoke('guest', 'write', 'space', 'ddl_test')
+box.commit();
+
+-- index and space drop are not currently supported (because of truncate)
+s.index.pk:drop();
+s:drop();
diff --git a/test/engine/truncate.result b/test/engine/truncate.result
index b4de787fb8c8ba0881277a982bfa2d5c7c8c0dc6..277e7bda6c095204df30a7e03fa9658c8a2ad6cb 100644
--- a/test/engine/truncate.result
+++ b/test/engine/truncate.result
@@ -24,14 +24,13 @@ box.begin()
 ...
 s:truncate()
 ---
-- error: DDL does not support multi-statement transactions
 ...
 box.commit()
 ---
 ...
 s:select()
 ---
-- - [123]
+- []
 ...
 s:drop()
 ---
diff --git a/test/sql-tap/trigger1.test.lua b/test/sql-tap/trigger1.test.lua
index 2984d4c213299555d5856a9eb09c5941db6a5292..924e57b5833f73c76c24ba0eae71b209a2ce6d6b 100755
--- a/test/sql-tap/trigger1.test.lua
+++ b/test/sql-tap/trigger1.test.lua
@@ -849,28 +849,24 @@ test:do_catchsql_test(
         -- </trigger1-16.7>
     })
 
-test:do_catchsql_test(
+test:do_execsql_test(
     "trigger1-16.8",
     [[
         START TRANSACTION;
           CREATE TRIGGER tr168 INSERT ON tA BEGIN
             INSERT INTO t16 values(1);
           END;
+        ROLLBACK;
    ]], {
-        1, [[Space _trigger does not support multi-statement transactions]]
 })
 
-test:execsql [[
-    ROLLBACK;
-]]
-
-test:do_catchsql_test(
+test:do_execsql_test(
     "trigger1-16.9",
     [[
         START TRANSACTION;
           DROP TRIGGER t16err3;
+        ROLLBACK;
    ]], {
-        1, [[Space _trigger does not support multi-statement transactions]]
 })
 -- MUST_WORK_TEST
 -- #-------------------------------------------------------------------------
diff --git a/test/sql/delete.result b/test/sql/delete.result
index 29459cc567f7544ec3c6bd4cdca46dcfec03c349..40da0a633fa7a0c638b0a028befb5810fddad2df 100644
--- a/test/sql/delete.result
+++ b/test/sql/delete.result
@@ -76,17 +76,21 @@ box.sql.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
 box.sql.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
 ---
 ...
--- Can't truncate in transaction.
+-- Truncate rollback
 box.sql.execute("START TRANSACTION")
 ---
 ...
 box.sql.execute("TRUNCATE TABLE t1;")
 ---
-- error: DDL does not support multi-statement transactions
 ...
 box.sql.execute("ROLLBACK")
 ---
 ...
+box.sql.execute("SELECT * FROM t1")
+---
+- - [1, 1, 'one']
+  - [2, 2, 'two']
+...
 -- Can't truncate view.
 box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
 ---
diff --git a/test/sql/delete.test.lua b/test/sql/delete.test.lua
index 5a0813071fac83a8ac9febaddf97572fd2d221ca..b61a993a8bf30d8571ccddc5686f423a176c702b 100644
--- a/test/sql/delete.test.lua
+++ b/test/sql/delete.test.lua
@@ -50,10 +50,11 @@ box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT, b TEXT);")
 box.sql.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
 box.sql.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
 
--- Can't truncate in transaction.
+-- Truncate rollback
 box.sql.execute("START TRANSACTION")
 box.sql.execute("TRUNCATE TABLE t1;")
 box.sql.execute("ROLLBACK")
+box.sql.execute("SELECT * FROM t1")
 
 -- Can't truncate view.
 box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")