[tarantool-patches] [PATCH 2/4] sql: remove mutexes around the code

Kirill Yukhin kyukhin at tarantool.org
Mon Mar 26 18:56:56 MSK 2018


This is first part, which will be likely squashed with
following. Tests pass.
---
 src/box/sql/CMakeLists.txt |   4 -
 src/box/sql/date.c         |   7 --
 src/box/sql/func.c         |   2 -
 src/box/sql/global.c       |   6 --
 src/box/sql/legacy.c       |   2 -
 src/box/sql/main.c         | 200 ++-------------------------------------------
 src/box/sql/malloc.c       |  53 ++----------
 src/box/sql/os.c           |  21 -----
 src/box/sql/os_unix.c      | 143 ++------------------------------
 src/box/sql/prepare.c      |   8 --
 src/box/sql/printf.c       |   6 --
 src/box/sql/random.c       |  11 ---
 src/box/sql/sqliteInt.h    |  71 +---------------
 src/box/sql/status.c       |   9 +-
 src/box/sql/tokenize.c     |   2 -
 src/box/sql/vdbe.c         |   5 +-
 src/box/sql/vdbeapi.c      |  54 ------------
 src/box/sql/vdbeaux.c      |   2 -
 src/box/sql/vdbemem.c      |  17 ----
 src/box/sql/vdbesort.c     |   6 +-
 20 files changed, 27 insertions(+), 602 deletions(-)

diff --git a/src/box/sql/CMakeLists.txt b/src/box/sql/CMakeLists.txt
index 238e185..8494e15 100644
--- a/src/box/sql/CMakeLists.txt
+++ b/src/box/sql/CMakeLists.txt
@@ -14,7 +14,6 @@ set(SRCDIR ${CMAKE_CURRENT_SOURCE_DIR})
 include_directories(${SRCDIR})
 
 add_definitions(-DSQLITE_MAX_WORKER_THREADS=0)
-add_definitions(-DTHREADSAFE=0)
 add_definitions(-DSQLITE_DEFAULT_FOREIGN_KEYS=1)
 add_definitions(-DSQLITE_OMIT_AUTOMATIC_INDEX)
 
@@ -54,9 +53,6 @@ add_library(sql STATIC
     mem2.c
     mem3.c
     mem5.c
-    mutex.c
-    mutex_noop.c
-    mutex_unix.c
     os.c
     os_unix.c
     pragma.c
diff --git a/src/box/sql/date.c b/src/box/sql/date.c
index 21df6df..9566cc3 100644
--- a/src/box/sql/date.c
+++ b/src/box/sql/date.c
@@ -545,10 +545,6 @@ osLocaltime(time_t * t, struct tm *pTm)
 	int rc;
 #if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
 	struct tm *pX;
-#if SQLITE_THREADSAFE>0
-	sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
-	sqlite3_mutex_enter(mutex);
 	pX = localtime(t);
 #ifndef SQLITE_UNTESTABLE
 	if (sqlite3GlobalConfig.bLocaltimeFault)
@@ -556,7 +552,6 @@ osLocaltime(time_t * t, struct tm *pTm)
 #endif
 	if (pX)
 		*pTm = *pX;
-	sqlite3_mutex_leave(mutex);
 	rc = pX == 0;
 #else
 #ifndef SQLITE_UNTESTABLE
@@ -1290,11 +1285,9 @@ currentTimeFunc(sqlite3_context * context, int argc, sqlite3_value ** argv)
 #if HAVE_GMTIME_R
 	pTm = gmtime_r(&t, &sNow);
 #else
-	sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
 	pTm = gmtime(&t);
 	if (pTm)
 		memcpy(&sNow, pTm, sizeof(sNow));
-	sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
 #endif
 	if (pTm) {
 		strftime(zBuf, 20, zFormat, &sNow);
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index d8d39a2..47b45de 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1712,12 +1712,10 @@ sqlite3_overload_function(sqlite3 * db, const char *zName, int nArg)
 		return SQLITE_MISUSE_BKPT;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	if (sqlite3FindFunction(db, zName, nArg, 0) == 0) {
 		rc = sqlite3CreateFunc(db, zName, nArg, 0, 0, sqlite3InvalidFunction, 0, 0, 0);
 	}
 	rc = sqlite3ApiExit(db, rc);
-	sqlite3_mutex_leave(db->mutex);
 	return rc;
 }
 
diff --git a/src/box/sql/global.c b/src/box/sql/global.c
index 97bdbe6..6a78550 100644
--- a/src/box/sql/global.c
+++ b/src/box/sql/global.c
@@ -195,8 +195,6 @@ const unsigned char sqlite3CtypeMap[256] = {
  */
 SQLITE_WSD struct Sqlite3Config sqlite3Config = {
 	SQLITE_DEFAULT_MEMSTATUS,	/* bMemstat */
-	1,			/* bCoreMutex */
-	SQLITE_THREADSAFE == 1,	/* bFullMutex */
 	SQLITE_USE_URI,		/* bOpenUri */
 	SQLITE_ALLOW_COVERING_INDEX_SCAN,	/* bUseCis */
 	0x7ffffffe,		/* mxStrlen */
@@ -205,7 +203,6 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
 	125,			/* nLookaside */
 	0,			/* nStmtSpill */
 	{0, 0, 0, 0, 0, 0, 0, 0},	/* m */
-	{0, 0, 0, 0, 0, 0, 0, 0, 0},	/* mutex */
 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/* pcache2 */
 	(void *)0,		/* pHeap */
 	0,			/* nHeap */
@@ -224,10 +221,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
 	/* All the rest should always be initialized to zero */
 	0,			/* isInit */
 	0,			/* inProgress */
-	0,			/* isMutexInit */
 	0,			/* isMallocInit */
-	0,			/* nRefInitMutex */
-	0,			/* pInitMutex */
 	0,			/* xLog */
 	0,			/* pLogArg */
 #ifdef SQLITE_ENABLE_SQLLOG
diff --git a/src/box/sql/legacy.c b/src/box/sql/legacy.c
index e757095..978cf01 100644
--- a/src/box/sql/legacy.c
+++ b/src/box/sql/legacy.c
@@ -69,7 +69,6 @@ sqlite3_exec(sqlite3 * db,	/* The database on which the SQL executes */
 	if (zSql == 0)
 		zSql = "";
 
-	sqlite3_mutex_enter(db->mutex);
 	sqlite3Error(db, SQLITE_OK);
 	while (rc == SQLITE_OK && zSql[0]) {
 		int nCol;
@@ -184,6 +183,5 @@ sqlite3_exec(sqlite3 * db,	/* The database on which the SQL executes */
 	}
 
 	assert((rc & db->errMask) == rc);
-	sqlite3_mutex_leave(db->mutex);
 	return rc;
 }
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index f0333fa..1f8c026 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -90,16 +90,6 @@ sqlite3_libversion_number(void)
 	return SQLITE_VERSION_NUMBER;
 }
 
-/* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns
- * zero if and only if SQLite was compiled with mutexing code omitted due to
- * the SQLITE_THREADSAFE compile-time option being set to 0.
- */
-int
-sqlite3_threadsafe(void)
-{
-	return SQLITE_THREADSAFE;
-}
-
 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
 /*
  * If the following function pointer is not NULL and if
@@ -132,7 +122,7 @@ char *sqlite3_data_directory = 0;
  * Initialize SQLite.
  *
  * This routine must be called to initialize the memory allocation,
- * VFS, and mutex subsystems prior to doing any serious work with
+ * and VFS subsystems prior to doing any serious work with
  * SQLite.  But as long as you do not compile with SQLITE_OMIT_AUTOINIT
  * this routine will be called automatically by key routines such as
  * sqlite3_open().
@@ -162,9 +152,7 @@ char *sqlite3_data_directory = 0;
 int
 sqlite3_initialize(void)
 {
-	MUTEX_LOGIC(sqlite3_mutex * pMaster;
-	    )			/* The main static mutex */
-	int rc;			/* Result code */
+	int rc = SQLITE_OK;
 #ifdef SQLITE_EXTRA_INIT
 	int bRunExtraInit = 0;	/* Extra initialization needed */
 #endif
@@ -190,56 +178,18 @@ sqlite3_initialize(void)
 	if (sqlite3GlobalConfig.isInit)
 		return SQLITE_OK;
 
-	/* Make sure the mutex subsystem is initialized.  If unable to
-	 * initialize the mutex subsystem, return early with the error.
-	 * If the system is so sick that we are unable to allocate a mutex,
-	 * there is not much SQLite is going to be able to do.
-	 *
-	 * The mutex subsystem must take care of serializing its own
-	 * initialization.
-	 */
-	rc = sqlite3MutexInit();
-	if (rc)
-		return rc;
-
-	/* Initialize the malloc() system and the recursive pInitMutex mutex.
-	 * This operation is protected by the STATIC_MASTER mutex.  Note that
-	 * MutexAlloc() is called for a static mutex prior to initializing the
-	 * malloc subsystem - this implies that the allocation of a static
-	 * mutex must not require support from the malloc subsystem.
-	 */
-	MUTEX_LOGIC(pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-	    )
-	    sqlite3_mutex_enter(pMaster);
-	sqlite3GlobalConfig.isMutexInit = 1;
-	if (!sqlite3GlobalConfig.isMallocInit) {
+	if (!sqlite3GlobalConfig.isMallocInit)
 		rc = sqlite3MallocInit();
-	}
-	if (rc == SQLITE_OK) {
+	if (rc == SQLITE_OK)
 		sqlite3GlobalConfig.isMallocInit = 1;
-		if (!sqlite3GlobalConfig.pInitMutex) {
-			sqlite3GlobalConfig.pInitMutex =
-			    sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
-			if (sqlite3GlobalConfig.bCoreMutex
-			    && !sqlite3GlobalConfig.pInitMutex) {
-				rc = SQLITE_NOMEM_BKPT;
-			}
-		}
-	}
-	if (rc == SQLITE_OK) {
-		sqlite3GlobalConfig.nRefInitMutex++;
-	}
-	sqlite3_mutex_leave(pMaster);
 
-	/* If rc is not SQLITE_OK at this point, then either the malloc
-	 * subsystem could not be initialized or the system failed to allocate
-	 * the pInitMutex mutex. Return an error in either case.
+	/* If rc is not SQLITE_OK at this point, then the malloc
+	 * subsystem could not be initialized.
 	 */
-	if (rc != SQLITE_OK) {
+	if (rc != SQLITE_OK)
 		return rc;
-	}
 
-	/* Do the rest of the initialization under the recursive mutex so
+	/* Do the rest of the initialization
 	 * that we will be able to handle recursive calls into
 	 * sqlite3_initialize().  The recursive calls normally come through
 	 * sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
@@ -248,11 +198,9 @@ sqlite3_initialize(void)
 	 * IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls
 	 * to the xInit method, so the xInit method need not be threadsafe.
 	 *
-	 * The following mutex is what serializes access to the appdef pcache xInit
-	 * methods.  The sqlite3_pcache_methods.xInit() all is embedded in the
+         * The sqlite3_pcache_methods.xInit() all is embedded in the
 	 * call to sqlite3PcacheInitialize().
 	 */
-	sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
 	if (sqlite3GlobalConfig.isInit == 0
 	    && sqlite3GlobalConfig.inProgress == 0) {
 		sqlite3GlobalConfig.inProgress = 1;
@@ -276,19 +224,6 @@ sqlite3_initialize(void)
 		}
 		sqlite3GlobalConfig.inProgress = 0;
 	}
-	sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
-
-	/* Go back under the static mutex and clean up the recursive
-	 * mutex to prevent a resource leak.
-	 */
-	sqlite3_mutex_enter(pMaster);
-	sqlite3GlobalConfig.nRefInitMutex--;
-	if (sqlite3GlobalConfig.nRefInitMutex <= 0) {
-		assert(sqlite3GlobalConfig.nRefInitMutex == 0);
-		sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
-		sqlite3GlobalConfig.pInitMutex = 0;
-	}
-	sqlite3_mutex_leave(pMaster);
 
 	/* The following is just a sanity check to make sure SQLite has
 	 * been compiled correctly.  It is important to run this code, but
@@ -364,10 +299,6 @@ sqlite3_shutdown(void)
 		sqlite3_temp_directory = 0;
 #endif
 	}
-	if (sqlite3GlobalConfig.isMutexInit) {
-		sqlite3MutexEnd();
-		sqlite3GlobalConfig.isMutexInit = 0;
-	}
 
 	return SQLITE_OK;
 }
@@ -395,57 +326,6 @@ sqlite3_config(int op, ...)
 
 	va_start(ap, op);
 	switch (op) {
-
-		/* Mutex configuration options are only available in a threadsafe
-		 * compile.
-		 */
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0	/* IMP: R-54466-46756 */
-	case SQLITE_CONFIG_SINGLETHREAD:{
-			/* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to
-			 * Single-thread.
-			 */
-			sqlite3GlobalConfig.bCoreMutex = 0;	/* Disable mutex on core */
-			sqlite3GlobalConfig.bFullMutex = 0;	/* Disable mutex on connections */
-			break;
-		}
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0	/* IMP: R-20520-54086 */
-	case SQLITE_CONFIG_MULTITHREAD:{
-			/* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to
-			 * Multi-thread.
-			 */
-			sqlite3GlobalConfig.bCoreMutex = 1;	/* Enable mutex on core */
-			sqlite3GlobalConfig.bFullMutex = 0;	/* Disable mutex on connections */
-			break;
-		}
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0	/* IMP: R-59593-21810 */
-	case SQLITE_CONFIG_SERIALIZED:{
-			/* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to
-			 * Serialized.
-			 */
-			sqlite3GlobalConfig.bCoreMutex = 1;	/* Enable mutex on core */
-			sqlite3GlobalConfig.bFullMutex = 1;	/* Enable mutex on connections */
-			break;
-		}
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0	/* IMP: R-63666-48755 */
-	case SQLITE_CONFIG_MUTEX:{
-			/* Specify an alternative mutex implementation */
-			sqlite3GlobalConfig.mutex =
-			    *va_arg(ap, sqlite3_mutex_methods *);
-			break;
-		}
-#endif
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0	/* IMP: R-14450-37597 */
-	case SQLITE_CONFIG_GETMUTEX:{
-			/* Retrieve the current mutex implementation */
-			*va_arg(ap, sqlite3_mutex_methods *) =
-			    sqlite3GlobalConfig.mutex;
-			break;
-		}
-#endif
-
 	case SQLITE_CONFIG_MALLOC:{
 			/* EVIDENCE-OF: R-55594-21030 The SQLITE_CONFIG_MALLOC option takes a
 			 * single argument which is a pointer to an instance of the
@@ -709,21 +589,6 @@ setupLookaside(sqlite3 * db, void *pBuf, int sz, int cnt)
 }
 
 /*
- * Return the mutex associated with a database connection.
- */
-sqlite3_mutex *
-sqlite3_db_mutex(sqlite3 * db)
-{
-#ifdef SQLITE_ENABLE_API_ARMOR
-	if (!sqlite3SafetyCheckOk(db)) {
-		(void)SQLITE_MISUSE_BKPT;
-		return 0;
-	}
-#endif
-	return db->mutex;
-}
-
-/*
  * Free up as much memory as we can from the given database
  * connection.
  */
@@ -889,7 +754,6 @@ functionDestroy(sqlite3 * db, FuncDef * p)
 static int
 connectionIsBusy(sqlite3 * db)
 {
-	assert(sqlite3_mutex_held(db->mutex));
 	if (db->pVdbe)
 		return 1;
 	return 0;
@@ -910,7 +774,6 @@ sqlite3Close(sqlite3 * db, int forceZombie)
 	if (!sqlite3SafetyCheckSickOrOk(db)) {
 		return SQLITE_MISUSE_BKPT;
 	}
-	sqlite3_mutex_enter(db->mutex);
 	if (db->mTrace & SQLITE_TRACE_CLOSE) {
 		db->xTrace(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
 	}
@@ -922,7 +785,6 @@ sqlite3Close(sqlite3 * db, int forceZombie)
 		sqlite3ErrorWithMsg(db, SQLITE_BUSY,
 				    "unable to close due to unfinalized "
 				    "statements");
-		sqlite3_mutex_leave(db->mutex);
 		return SQLITE_BUSY;
 	}
 #ifdef SQLITE_ENABLE_SQLLOG
@@ -975,7 +837,6 @@ sqlite3RollbackAll(Vdbe * pVdbe, int tripCode)
 	int inTrans = 0;
 	(void)tripCode;
 	struct session *user_session = current_session();
-	assert(sqlite3_mutex_held(db->mutex));
 
 	/* DDL is impossible inside a transaction.  */
 	assert((user_session->sql_flags & SQLITE_InternChanges) == 0
@@ -1364,12 +1225,10 @@ sqlite3_busy_handler(sqlite3 * db, int (*xBusy) (void *, int), void *pArg)
 	if (!sqlite3SafetyCheckOk(db))
 		return SQLITE_MISUSE_BKPT;
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	db->busyHandler.xFunc = xBusy;
 	db->busyHandler.pArg = pArg;
 	db->busyHandler.nBusy = 0;
 	db->busyTimeout = 0;
-	sqlite3_mutex_leave(db->mutex);
 	return SQLITE_OK;
 }
 
@@ -1389,7 +1248,6 @@ sqlite3_progress_handler(sqlite3 * db,
 		return;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	if (nOps > 0) {
 		db->xProgress = xProgress;
 		db->nProgressOps = (unsigned)nOps;
@@ -1399,7 +1257,6 @@ sqlite3_progress_handler(sqlite3 * db,
 		db->nProgressOps = 0;
 		db->pProgressArg = 0;
 	}
-	sqlite3_mutex_leave(db->mutex);
 }
 #endif
 
@@ -1459,7 +1316,6 @@ sqlite3CreateFunc(sqlite3 * db,
 	FuncDef *p;
 	int extraFlags;
 
-	assert(sqlite3_mutex_held(db->mutex));
 	if (zFunctionName == 0 ||
 	    (xSFunc && (xFinal || xStep)) ||
 	    (!xSFunc && (xFinal && !xStep)) ||
@@ -1554,7 +1410,6 @@ sqlite3_create_function_v2(sqlite3 * db,
 		return SQLITE_MISUSE_BKPT;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	if (xDestroy) {
 		pArg =
 		    (FuncDestructor *) sqlite3DbMallocZero(db,
@@ -1577,7 +1432,6 @@ sqlite3_create_function_v2(sqlite3 * db,
 
  out:
 	rc = sqlite3ApiExit(db, rc);
-	sqlite3_mutex_leave(db->mutex);
 	return rc;
 }
 
@@ -1595,7 +1449,6 @@ sqlite3_trace_v2(sqlite3 * db,		/* Trace this connection */
 		return SQLITE_MISUSE_BKPT;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	if (mTrace == 0)
 		xTrace = 0;
 	if (xTrace == 0)
@@ -1603,7 +1456,6 @@ sqlite3_trace_v2(sqlite3 * db,		/* Trace this connection */
 	db->mTrace = mTrace;
 	db->xTrace = xTrace;
 	db->pTraceArg = pArg;
-	sqlite3_mutex_leave(db->mutex);
 	return SQLITE_OK;
 }
 
@@ -1627,11 +1479,9 @@ sqlite3_commit_hook(sqlite3 * db,	/* Attach the hook to this database */
 		return 0;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	pOld = db->pCommitArg;
 	db->xCommitCallback = xCallback;
 	db->pCommitArg = pArg;
-	sqlite3_mutex_leave(db->mutex);
 	return pOld;
 }
 
@@ -1653,11 +1503,9 @@ sqlite3_update_hook(sqlite3 * db,	/* Attach the hook to this database */
 		return 0;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	pRet = db->pUpdateArg;
 	db->xUpdateCallback = xCallback;
 	db->pUpdateArg = pArg;
-	sqlite3_mutex_leave(db->mutex);
 	return pRet;
 }
 
@@ -1678,11 +1526,9 @@ sqlite3_rollback_hook(sqlite3 * db,	/* Attach the hook to this database */
 		return 0;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	pRet = db->pRollbackArg;
 	db->xRollbackCallback = xCallback;
 	db->pRollbackArg = pArg;
-	sqlite3_mutex_leave(db->mutex);
 	return pRet;
 }
 
@@ -1699,11 +1545,9 @@ sqlite3_preupdate_hook(sqlite3 * db,		/* Attach the hook to this database */
 		       void *pArg)		/* First callback argument */
 {
 	void *pRet;
-	sqlite3_mutex_enter(db->mutex);
 	pRet = db->pPreUpdateArg;
 	db->xPreUpdateCallback = xCallback;
 	db->pPreUpdateArg = pArg;
-	sqlite3_mutex_leave(db->mutex);
 	return pRet;
 }
 #endif				/* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -1779,7 +1623,6 @@ sqlite3_errmsg(sqlite3 * db)
 	if (!sqlite3SafetyCheckSickOrOk(db)) {
 		return sqlite3ErrStr(SQLITE_MISUSE_BKPT);
 	}
-	sqlite3_mutex_enter(db->mutex);
 	if (db->mallocFailed) {
 		z = sqlite3ErrStr(SQLITE_NOMEM_BKPT);
 	} else {
@@ -1790,7 +1633,6 @@ sqlite3_errmsg(sqlite3 * db)
 			z = sqlite3ErrStr(db->errCode);
 		}
 	}
-	sqlite3_mutex_leave(db->mutex);
 	return z;
 }
 
@@ -2256,7 +2098,6 @@ sql_init_db(sqlite3 **out_db)
 {
 	sqlite3 *db;
 	int rc;			/* Return code */
-	int isThreadsafe;	/* True for threadsafe connections */
 
 #ifdef SQLITE_ENABLE_API_ARMOR
 	if (ppDb == 0)
@@ -2268,24 +2109,10 @@ sql_init_db(sqlite3 **out_db)
 		return rc;
 #endif
 
-	if (sqlite3GlobalConfig.bCoreMutex == 0) {
-		isThreadsafe = 0;
-	} else {
-		isThreadsafe = sqlite3GlobalConfig.bFullMutex;
-	}
 	/* Allocate the sqlite data structure */
 	db = sqlite3MallocZero(sizeof(sqlite3));
 	if (db == 0)
 		goto opendb_out;
-	if (isThreadsafe) {
-		db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
-		if (db->mutex == 0) {
-			sqlite3_free(db);
-			db = 0;
-			goto opendb_out;
-		}
-	}
-	sqlite3_mutex_enter(db->mutex);
 	db->errMask = 0xff;
 	db->magic = SQLITE_MAGIC_BUSY;
 
@@ -2382,11 +2209,6 @@ sql_init_db(sqlite3 **out_db)
 			sqlite3CommitInternalChanges();
 	}
 opendb_out:
-	if (db) {
-		assert(db->mutex != 0 || isThreadsafe == 0
-		       || sqlite3GlobalConfig.bFullMutex == 0);
-		sqlite3_mutex_leave(db->mutex);
-	}
 	rc = sqlite3_errcode(db);
 	assert(db != 0 || rc == SQLITE_NOMEM);
 	if (rc == SQLITE_NOMEM) {
@@ -2492,9 +2314,7 @@ sqlite3_extended_result_codes(sqlite3 * db, int onoff)
 	if (!sqlite3SafetyCheckOk(db))
 		return SQLITE_MISUSE_BKPT;
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	db->errMask = onoff ? 0xffffffff : 0xff;
-	sqlite3_mutex_leave(db->mutex);
 	return SQLITE_OK;
 }
 
@@ -2805,14 +2625,12 @@ sqlite3_test_control(int op, ...)
 		 */
 	case SQLITE_TESTCTRL_IMPOSTER:{
 			sqlite3 *db = va_arg(ap, sqlite3 *);
-			sqlite3_mutex_enter(db->mutex);
 			db->init.busy = db->init.imposterTable =
 			    va_arg(ap, int);
 			db->init.newTnum = va_arg(ap, int);
 			if (db->init.busy == 0 && db->init.newTnum > 0) {
 				sqlite3ResetAllSchemasOfConnection(db);
 			}
-			sqlite3_mutex_leave(db->mutex);
 			break;
 		}
 	}
diff --git a/src/box/sql/malloc.c b/src/box/sql/malloc.c
index 325faf5..0a8107a 100644
--- a/src/box/sql/malloc.c
+++ b/src/box/sql/malloc.c
@@ -68,7 +68,6 @@ typedef struct ScratchFreeslot {
  * State information local to the memory allocation subsystem.
  */
 static SQLITE_WSD struct Mem0Global {
-	sqlite3_mutex *mutex;	/* Mutex to serialize access */
 	sqlite3_int64 alarmThreshold;	/* The soft heap limit */
 
 	/*
@@ -87,18 +86,10 @@ static SQLITE_WSD struct Mem0Global {
 	 */
 	int nearlyFull;
 } mem0 = {
-0, 0, 0, 0, 0, 0};
+0, 0, 0, 0, 0};
 
 #define mem0 GLOBAL(struct Mem0Global, mem0)
 
-/*
- * Return the memory allocator mutex. sqlite3_status() needs it.
- */
-sqlite3_mutex *
-sqlite3MallocMutex(void)
-{
-	return mem0.mutex;
-}
 
 /*
  * Set the soft heap-size limit for the library. Passing a zero or
@@ -115,16 +106,13 @@ sqlite3_soft_heap_limit64(sqlite3_int64 n)
 	if (rc)
 		return -1;
 #endif
-	sqlite3_mutex_enter(mem0.mutex);
 	priorLimit = mem0.alarmThreshold;
 	if (n < 0) {
-		sqlite3_mutex_leave(mem0.mutex);
 		return priorLimit;
 	}
 	mem0.alarmThreshold = n;
 	nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
 	mem0.nearlyFull = (n > 0 && n <= nUsed);
-	sqlite3_mutex_leave(mem0.mutex);
 	excess = sqlite3_memory_used() - n;
 	if (excess > 0)
 		sqlite3_release_memory((int)(excess & 0x7fffffff));
@@ -150,7 +138,6 @@ sqlite3MallocInit(void)
 		sqlite3MemSetDefault();
 	}
 	memset(&mem0, 0, sizeof(mem0));
-	mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
 	if (sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch >= 100
 	    && sqlite3GlobalConfig.nScratch > 0) {
 		int i, n, sz;
@@ -239,9 +226,7 @@ sqlite3MallocAlarm(int nByte)
 {
 	if (mem0.alarmThreshold <= 0)
 		return;
-	sqlite3_mutex_leave(mem0.mutex);
 	sqlite3_release_memory(nByte);
-	sqlite3_mutex_enter(mem0.mutex);
 }
 
 /*
@@ -253,7 +238,6 @@ mallocWithAlarm(int n, void **pp)
 {
 	int nFull;
 	void *p;
-	assert(sqlite3_mutex_held(mem0.mutex));
 	nFull = sqlite3GlobalConfig.m.xRoundup(n);
 	sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
 	if (mem0.alarmThreshold > 0) {
@@ -299,9 +283,7 @@ sqlite3Malloc(u64 n)
 		 */
 		p = 0;
 	} else if (sqlite3GlobalConfig.bMemstat) {
-		sqlite3_mutex_enter(mem0.mutex);
 		mallocWithAlarm((int)n, &p);
-		sqlite3_mutex_leave(mem0.mutex);
 	} else {
 		p = sqlite3GlobalConfig.m.xMalloc((int)n);
 	}
@@ -340,7 +322,7 @@ sqlite3_malloc64(sqlite3_uint64 n)
  * case by setting scratchAllocOut to 1 when an allocation
  * is outstanding clearing it when the allocation is freed.
  */
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+#if !defined(NDEBUG)
 static int scratchAllocOut = 0;
 #endif
 
@@ -358,28 +340,22 @@ sqlite3ScratchMalloc(int n)
 	void *p;
 	assert(n > 0);
 
-	sqlite3_mutex_enter(mem0.mutex);
 	sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
 	if (mem0.nScratchFree && sqlite3GlobalConfig.szScratch >= n) {
 		p = mem0.pScratchFree;
 		mem0.pScratchFree = mem0.pScratchFree->pNext;
 		mem0.nScratchFree--;
 		sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
-		sqlite3_mutex_leave(mem0.mutex);
 	} else {
-		sqlite3_mutex_leave(mem0.mutex);
 		p = sqlite3Malloc(n);
 		if (sqlite3GlobalConfig.bMemstat && p) {
-			sqlite3_mutex_enter(mem0.mutex);
 			sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW,
 					sqlite3MallocSize(p));
-			sqlite3_mutex_leave(mem0.mutex);
 		}
 		sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
 	}
-	assert(sqlite3_mutex_notheld(mem0.mutex));
 
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+#if !defined(NDEBUG)
 	/* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch
 	 * buffers per thread.
 	 *
@@ -398,7 +374,7 @@ sqlite3ScratchFree(void *p)
 {
 	if (p) {
 
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+#if !defined(NDEBUG)
 		/* Verify that no more than two scratch allocation per thread
 		 * is outstanding at one time.  (This is only checked in the
 		 * single-threaded case since checking in the multi-threaded case
@@ -413,14 +389,12 @@ sqlite3ScratchFree(void *p)
 			/* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
 			ScratchFreeslot *pSlot;
 			pSlot = (ScratchFreeslot *) p;
-			sqlite3_mutex_enter(mem0.mutex);
 			pSlot->pNext = mem0.pScratchFree;
 			mem0.pScratchFree = pSlot;
 			mem0.nScratchFree++;
 			assert(mem0.nScratchFree <=
 			       (u32) sqlite3GlobalConfig.nScratch);
 			sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
-			sqlite3_mutex_leave(mem0.mutex);
 		} else {
 			/* Release memory back to the heap */
 			assert(sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH));
@@ -429,7 +403,6 @@ sqlite3ScratchFree(void *p)
 			sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
 			if (sqlite3GlobalConfig.bMemstat) {
 				int iSize = sqlite3MallocSize(p);
-				sqlite3_mutex_enter(mem0.mutex);
 				sqlite3StatusDown
 				    (SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
 				sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED,
@@ -437,7 +410,6 @@ sqlite3ScratchFree(void *p)
 				sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT,
 						  1);
 				sqlite3GlobalConfig.m.xFree(p);
-				sqlite3_mutex_leave(mem0.mutex);
 			} else {
 				sqlite3GlobalConfig.m.xFree(p);
 			}
@@ -486,10 +458,8 @@ sqlite3DbMallocSize(sqlite3 * db, void *p)
 		}
 #endif
 		return sqlite3GlobalConfig.m.xSize(p);
-	} else {
-		assert(sqlite3_mutex_held(db->mutex));
+	} else
 		return db->lookaside.sz;
-	}
 }
 
 sqlite3_uint64
@@ -511,12 +481,10 @@ sqlite3_free(void *p)
 	assert(sqlite3MemdebugHasType(p, MEMTYPE_HEAP));
 	assert(sqlite3MemdebugNoType(p, (u8) ~ MEMTYPE_HEAP));
 	if (sqlite3GlobalConfig.bMemstat) {
-		sqlite3_mutex_enter(mem0.mutex);
 		sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED,
 				  sqlite3MallocSize(p));
 		sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
 		sqlite3GlobalConfig.m.xFree(p);
-		sqlite3_mutex_leave(mem0.mutex);
 	} else {
 		sqlite3GlobalConfig.m.xFree(p);
 	}
@@ -539,7 +507,6 @@ measureAllocationSize(sqlite3 * db, void *p)
 void
 sqlite3DbFree(sqlite3 * db, void *p)
 {
-	assert(db == 0 || sqlite3_mutex_held(db->mutex));
 	if (p == 0)
 		return;
 	if (db) {
@@ -597,7 +564,6 @@ sqlite3Realloc(void *pOld, u64 nBytes)
 	if (nOld == nNew) {
 		pNew = pOld;
 	} else if (sqlite3GlobalConfig.bMemstat) {
-		sqlite3_mutex_enter(mem0.mutex);
 		sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
 		nDiff = nNew - nOld;
 		if (nDiff > 0
@@ -614,7 +580,6 @@ sqlite3Realloc(void *pOld, u64 nBytes)
 			nNew = sqlite3MallocSize(pNew);
 			sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew - nOld);
 		}
-		sqlite3_mutex_leave(mem0.mutex);
 	} else {
 		pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
 	}
@@ -732,7 +697,6 @@ sqlite3DbMallocRawNN(sqlite3 * db, u64 n)
 #ifndef SQLITE_OMIT_LOOKASIDE
 	LookasideSlot *pBuf;
 	assert(db != 0);
-	assert(sqlite3_mutex_held(db->mutex));
 	assert(db->pnBytesFreed == 0);
 	if (db->lookaside.bDisable == 0) {
 		assert(db->mallocFailed == 0);
@@ -754,7 +718,6 @@ sqlite3DbMallocRawNN(sqlite3 * db, u64 n)
 	}
 #else
 	assert(db != 0);
-	assert(sqlite3_mutex_held(db->mutex));
 	assert(db->pnBytesFreed == 0);
 	if (db->mallocFailed) {
 		return 0;
@@ -776,7 +739,6 @@ sqlite3DbRealloc(sqlite3 * db, void *p, u64 n)
 	assert(db != 0);
 	if (p == 0)
 		return sqlite3DbMallocRawNN(db, n);
-	assert(sqlite3_mutex_held(db->mutex));
 	if (isLookaside(db, p) && n <= db->lookaside.sz)
 		return p;
 	return dbReallocFinish(db, p, n);
@@ -941,12 +903,7 @@ apiOomError(sqlite3 * db)
 int
 sqlite3ApiExit(sqlite3 * db, int rc)
 {
-	/* If the db handle must hold the connection handle mutex here.
-	 * Otherwise the read (and possible write) of db->mallocFailed
-	 * is unsafe, as is the call to sqlite3Error().
-	 */
 	assert(db != 0);
-	assert(sqlite3_mutex_held(db->mutex));
 	if (db->mallocFailed || rc == SQLITE_IOERR_NOMEM) {
 		return apiOomError(db);
 	}
diff --git a/src/box/sql/os.c b/src/box/sql/os.c
index ecb437f..ae98831 100644
--- a/src/box/sql/os.c
+++ b/src/box/sql/os.c
@@ -439,25 +439,17 @@ sqlite3_vfs *
 sqlite3_vfs_find(const char *zVfs)
 {
 	sqlite3_vfs *pVfs = 0;
-#if SQLITE_THREADSAFE
-	sqlite3_mutex *mutex;
-#endif
 #ifndef SQLITE_OMIT_AUTOINIT
 	int rc = sqlite3_initialize();
 	if (rc)
 		return 0;
 #endif
-#if SQLITE_THREADSAFE
-	mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
-	sqlite3_mutex_enter(mutex);
 	for (pVfs = vfsList; pVfs; pVfs = pVfs->pNext) {
 		if (zVfs == 0)
 			break;
 		if (strcmp(zVfs, pVfs->zName) == 0)
 			break;
 	}
-	sqlite3_mutex_leave(mutex);
 	return pVfs;
 }
 
@@ -467,8 +459,6 @@ sqlite3_vfs_find(const char *zVfs)
 static void
 vfsUnlink(sqlite3_vfs * pVfs)
 {
-	assert(sqlite3_mutex_held
-	       (sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)));
 	if (pVfs == 0) {
 		/* No-op */
 	} else if (vfsList == pVfs) {
@@ -492,8 +482,6 @@ vfsUnlink(sqlite3_vfs * pVfs)
 int
 sqlite3_vfs_register(sqlite3_vfs * pVfs, int makeDflt)
 {
-	MUTEX_LOGIC(sqlite3_mutex * mutex;
-	    )
 #ifndef SQLITE_OMIT_AUTOINIT
 	int rc = sqlite3_initialize();
 	if (rc)
@@ -504,9 +492,6 @@ sqlite3_vfs_register(sqlite3_vfs * pVfs, int makeDflt)
 		return SQLITE_MISUSE_BKPT;
 #endif
 
-	MUTEX_LOGIC(mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-	    )
-	    sqlite3_mutex_enter(mutex);
 	vfsUnlink(pVfs);
 	if (makeDflt || vfsList == 0) {
 		pVfs->pNext = vfsList;
@@ -516,7 +501,6 @@ sqlite3_vfs_register(sqlite3_vfs * pVfs, int makeDflt)
 		vfsList->pNext = pVfs;
 	}
 	assert(vfsList);
-	sqlite3_mutex_leave(mutex);
 	return SQLITE_OK;
 }
 
@@ -526,11 +510,6 @@ sqlite3_vfs_register(sqlite3_vfs * pVfs, int makeDflt)
 int
 sqlite3_vfs_unregister(sqlite3_vfs * pVfs)
 {
-#if SQLITE_THREADSAFE
-	sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-#endif
-	sqlite3_mutex_enter(mutex);
 	vfsUnlink(pVfs);
-	sqlite3_mutex_leave(mutex);
 	return SQLITE_OK;
 }
diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c
index 56c1c7e..4285d9f 100644
--- a/src/box/sql/os_unix.c
+++ b/src/box/sql/os_unix.c
@@ -134,15 +134,6 @@
 #define SQLITE_FSFLAGS_IS_MSDOS     0x1
 
 /*
- * If we are to be thread-safe, include the pthreads header and define
- * the SQLITE_UNIX_THREADS macro.
- */
-#if SQLITE_THREADSAFE
-#include <pthread.h>
-#define SQLITE_UNIX_THREADS 1
-#endif
-
-/*
  * Default permissions when creating a new file
  */
 #ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
@@ -287,16 +278,6 @@ static pid_t randomnessPid = 0;
 #endif
 
 /*
- * The threadid macro resolves to the thread-id or to 0.  Used for
- * testing and debugging only.
- */
-#if SQLITE_THREADSAFE
-#define threadid pthread_self()
-#else
-#define threadid 0
-#endif
-
-/*
  * HAVE_MREMAP defaults to true on Linux and false everywhere else.
  */
 #if !defined(HAVE_MREMAP)
@@ -648,39 +629,6 @@ robust_open(const char *z, int f, mode_t m)
 	return fd;
 }
 
-/*
- * Helper functions to obtain and relinquish the global mutex. The
- * global mutex is used to protect the unixInodeInfo object
- * used by this file, all of which may be shared by multiple threads.
- *
- * Function unixMutexHeld() is used to assert() that the global mutex
- * is held when required. This function is only used as part of assert()
- * statements. e.g.
- *
- *   unixEnterMutex()
- *     assert( unixMutexHeld() );
- *   unixEnterLeave()
- */
-static void
-unixEnterMutex(void)
-{
-	sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
-}
-
-static void
-unixLeaveMutex(void)
-{
-	sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
-}
-
-#ifdef SQLITE_DEBUG
-static int
-unixMutexHeld(void)
-{
-	return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
-}
-#endif
-
 #ifdef SQLITE_LOCK_TRACE
 /*
  * Print out information about all locking operations.
@@ -717,8 +665,8 @@ lockTrace(int fd, int op, struct flock *p)
 	assert(p->l_whence == SEEK_SET);
 	s = osFcntl(fd, op, p);
 	savedErrno = errno;
-	sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
-			   threadid, fd, zOpName, zType, (int)p->l_start,
+	sqlite3DebugPrintf("fcntl %d %s %s %d %d %d %d\n",
+			   fd, zOpName, zType, (int)p->l_start,
 			   (int)p->l_len, (int)p->l_pid, s);
 	if (s == (-1) && op == F_SETLK
 	    && (p->l_type == F_RDLCK || p->l_type == F_WRLCK)) {
@@ -951,39 +899,7 @@ unixLogErrorAtLine(int errcode,	/* SQLite error code */
 	char *zErr;		/* Message from strerror() or equivalent */
 	int iErrno = errno;	/* Saved syscall error number */
 
-	/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
-	 * the strerror() function to obtain the human-readable error message
-	 * equivalent to errno. Otherwise, use strerror_r().
-	 */
-#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
-	char aErr[80];
-	memset(aErr, 0, sizeof(aErr));
-	zErr = aErr;
-
-	/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
-	 * assume that the system provides the GNU version of strerror_r() that
-	 * returns a pointer to a buffer containing the error message. That pointer
-	 * may point to aErr[], or it may point to some static storage somewhere.
-	 * Otherwise, assume that the system provides the POSIX version of
-	 * strerror_r(), which always writes an error message into aErr[].
-	 *
-	 * If the code incorrectly assumes that it is the POSIX version that is
-	 * available, the error message will often be an empty string. Not a
-	 * huge problem. Incorrectly concluding that the GNU version is available
-	 * could lead to a segfault though.
-	 */
-#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
-	zErr =
-#endif
-	    strerror_r(iErrno, aErr, sizeof(aErr) - 1);
-
-#elif SQLITE_THREADSAFE
-	/* This is a threadsafe build, but strerror_r() is not available. */
-	zErr = "";
-#else
-	/* Non-threadsafe build, use strerror(). */
 	zErr = strerror(iErrno);
-#endif
 
 	if (zPath == 0)
 		zPath = "";
@@ -1045,15 +961,11 @@ closePendingFds(unixFile * pFile)
 
 /*
  * Release a unixInodeInfo structure previously allocated by findInodeInfo().
- *
- * The mutex entered using the unixEnterMutex() function must be held
- * when this function is called.
  */
 static void
 releaseInodeInfo(unixFile * pFile)
 {
 	unixInodeInfo *pInode = pFile->pInode;
-	assert(unixMutexHeld());
 	if (ALWAYS(pInode)) {
 		pInode->nRef--;
 		if (pInode->nRef == 0) {
@@ -1080,9 +992,6 @@ releaseInodeInfo(unixFile * pFile)
  * describes that file descriptor.  Create a new one if necessary.  The
  * return value might be uninitialized if an error occurs.
  *
- * The mutex entered using the unixEnterMutex() function must be held
- * when this function is called.
- *
  * Return an appropriate error code.
  */
 static int
@@ -1096,8 +1005,6 @@ findInodeInfo(unixFile * pFile,	/* Unix file with file desc used in the key */
 	struct stat statbuf;	/* Low-level file information */
 	unixInodeInfo *pInode = 0;	/* Candidate unixInodeInfo object */
 
-	assert(unixMutexHeld());
-
 	/* Get low-level information about the file that we can used to
 	 * create a unique name for the file.
 	 */
@@ -1238,15 +1145,12 @@ unixCheckReservedLock(sqlite3_file * id, int *pResOut)
 
 	assert(pFile);
 	assert(pFile->eFileLock <= SHARED_LOCK);
-	unixEnterMutex();	/* Because pFile->pInode is shared across threads */
 
 	/* Check if a thread in this process holds such a lock */
 	if (pFile->pInode->eFileLock > SHARED_LOCK) {
 		reserved = 1;
 	}
 
-	unixLeaveMutex();
-
 	*pResOut = reserved;
 	return rc;
 }
@@ -1275,7 +1179,6 @@ unixFileLock(unixFile * pFile, struct flock *pLock)
 {
 	int rc;
 	unixInodeInfo *pInode = pFile->pInode;
-	assert(unixMutexHeld());
 	assert(pInode != 0);
 	if ((pFile->ctrlFlags & (UNIXFILE_EXCL | UNIXFILE_RDONLY)) ==
 	    UNIXFILE_EXCL) {
@@ -1367,12 +1270,10 @@ unixLock(sqlite3_file * id, int eFileLock)
 	assert(pFile);
 
 	/* If there is already a lock of this type or more restrictive on the
-	 * unixFile, do nothing. Don't use the end_lock: exit path, as
-	 * unixEnterMutex() hasn't been called yet.
+	 * unixFile, do nothing.
 	 */
-	if (pFile->eFileLock >= eFileLock) {
+	if (pFile->eFileLock >= eFileLock)
 		return SQLITE_OK;
-	}
 
 	/* Make sure the locking sequence is correct.
 	 *  (1) We never move from unlocked to anything higher than shared lock.
@@ -1383,9 +1284,6 @@ unixLock(sqlite3_file * id, int eFileLock)
 	assert(eFileLock != PENDING_LOCK);
 	assert(eFileLock != RESERVED_LOCK || pFile->eFileLock == SHARED_LOCK);
 
-	/* This mutex is needed because pFile->pInode is shared across threads
-	 */
-	unixEnterMutex();
 	pInode = pFile->pInode;
 
 	/* If some thread using this PID has a lock via a different unixFile*
@@ -1529,7 +1427,6 @@ unixLock(sqlite3_file * id, int eFileLock)
 	}
 
  end_lock:
-	unixLeaveMutex();
 	return rc;
 }
 
@@ -1575,7 +1472,6 @@ posixUnlock(sqlite3_file * id, int eFileLock, int handleNFSUnlock)
 	if (pFile->eFileLock <= eFileLock) {
 		return SQLITE_OK;
 	}
-	unixEnterMutex();
 	pInode = pFile->pInode;
 	assert(pInode->nShared != 0);
 	if (pFile->eFileLock > SHARED_LOCK) {
@@ -1711,7 +1607,6 @@ posixUnlock(sqlite3_file * id, int eFileLock, int handleNFSUnlock)
 	}
 
  end_unlock:
-	unixLeaveMutex();
 	if (rc == SQLITE_OK)
 		pFile->eFileLock = eFileLock;
 	return rc;
@@ -1778,7 +1673,6 @@ unixClose(sqlite3_file * id)
 	unixFile *pFile = (unixFile *) id;
 	verifyDbFile(pFile);
 	unixUnlock(id, NO_LOCK);
-	unixEnterMutex();
 
 	/* unixFile.pInode is always valid here. Otherwise, a different close
 	 * routine (e.g. nolockClose()) would be called instead.
@@ -1794,7 +1688,6 @@ unixClose(sqlite3_file * id)
 	}
 	releaseInodeInfo(pFile);
 	rc = closeUnixFile(id);
-	unixLeaveMutex();
 	return rc;
 }
 
@@ -2355,7 +2248,6 @@ afpCheckReservedLock(sqlite3_file * id, int *pResOut)
 		*pResOut = 1;
 		return SQLITE_OK;
 	}
-	unixEnterMutex();	/* Because pFile->pInode is shared across threads */
 
 	/* Check if a thread in this process holds such a lock */
 	if (pFile->pInode->eFileLock > SHARED_LOCK) {
@@ -2384,8 +2276,6 @@ afpCheckReservedLock(sqlite3_file * id, int *pResOut)
 		}
 	}
 
-	unixLeaveMutex();
-
 	*pResOut = reserved;
 	return rc;
 }
@@ -2426,8 +2316,7 @@ afpLock(sqlite3_file * id, int eFileLock)
 	assert(pFile);
 
 	/* If there is already a lock of this type or more restrictive on the
-	 * unixFile, do nothing. Don't use the afp_end_lock: exit path, as
-	 * unixEnterMutex() hasn't been called yet.
+	 * unixFile, do nothing.
 	 */
 	if (pFile->eFileLock >= eFileLock) {
 		return SQLITE_OK;
@@ -2442,9 +2331,6 @@ afpLock(sqlite3_file * id, int eFileLock)
 	assert(eFileLock != PENDING_LOCK);
 	assert(eFileLock != RESERVED_LOCK || pFile->eFileLock == SHARED_LOCK);
 
-	/* This mutex is needed because pFile->pInode is shared across threads
-	 */
-	unixEnterMutex();
 	pInode = pFile->pInode;
 
 	/* If some thread using this PID has a lock via a different unixFile*
@@ -2594,7 +2480,6 @@ afpLock(sqlite3_file * id, int eFileLock)
 	}
 
  afp_end_lock:
-	unixLeaveMutex();
 	return rc;
 }
 
@@ -2624,7 +2509,6 @@ afpUnlock(sqlite3_file * id, int eFileLock)
 	if (pFile->eFileLock <= eFileLock) {
 		return SQLITE_OK;
 	}
-	unixEnterMutex();
 	pInode = pFile->pInode;
 	assert(pInode->nShared != 0);
 	if (pFile->eFileLock > SHARED_LOCK) {
@@ -2710,7 +2594,6 @@ afpUnlock(sqlite3_file * id, int eFileLock)
 		}
 	}
 
-	unixLeaveMutex();
 	if (rc == SQLITE_OK)
 		pFile->eFileLock = eFileLock;
 	return rc;
@@ -2726,7 +2609,6 @@ afpClose(sqlite3_file * id)
 	unixFile *pFile = (unixFile *) id;
 	assert(id != 0);
 	afpUnlock(id, NO_LOCK);
-	unixEnterMutex();
 	if (pFile->pInode && pFile->pInode->nLock) {
 		/* If there are outstanding locks, do not actually close the file just
 		 * yet because that would clear those locks.  Instead, add the file
@@ -2738,7 +2620,6 @@ afpClose(sqlite3_file * id)
 	releaseInodeInfo(pFile);
 	sqlite3_free(pFile->lockingContext);
 	rc = closeUnixFile(id);
-	unixLeaveMutex();
 	return rc;
 }
 
@@ -4110,11 +3991,10 @@ fillInUnixFile(sqlite3_vfs * pVfs,	/* Pointer to vfs object */
 	    || pLockingStyle == &nfsIoMethods
 #endif
 	    ) {
-		unixEnterMutex();
 		rc = findInodeInfo(pNew, &pNew->pInode);
 		if (rc != SQLITE_OK) {
 			/* If an error occurred in findInodeInfo(), close the file descriptor
-			 * immediately, before releasing the mutex. findInodeInfo() may fail
+			 * immediately. findInodeInfo() may fail
 			 * in two scenarios:
 			 *
 			 *   (a) A call to fstat() failed.
@@ -4134,7 +4014,6 @@ fillInUnixFile(sqlite3_vfs * pVfs,	/* Pointer to vfs object */
 			robust_close(pNew, h, __LINE__);
 			h = -1;
 		}
-		unixLeaveMutex();
 	}
 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
 	else if (pLockingStyle == &afpIoMethods) {
@@ -4153,14 +4032,12 @@ fillInUnixFile(sqlite3_vfs * pVfs,	/* Pointer to vfs object */
 			pCtx->dbPath = zFilename;
 			pCtx->reserved = 0;
 			srandomdev();
-			unixEnterMutex();
 			rc = findInodeInfo(pNew, &pNew->pInode);
 			if (rc != SQLITE_OK) {
 				sqlite3_free(pNew->lockingContext);
 				robust_close(pNew, h, __LINE__);
 				h = -1;
 			}
-			unixLeaveMutex();
 		}
 	}
 #endif
@@ -4308,7 +4185,6 @@ findReusableFd(const char *zPath, int flags)
 	if (0 == osStat(zPath, &sStat)) {
 		unixInodeInfo *pInode;
 
-		unixEnterMutex();
 		pInode = inodeList;
 		while (pInode && (pInode->fileId.dev != sStat.st_dev
 				  || pInode->fileId.ino !=
@@ -4325,7 +4201,6 @@ findReusableFd(const char *zPath, int flags)
 				*pp = pUnused->pNext;
 			}
 		}
-		unixLeaveMutex();
 	}
 	return pUnused;
 }
@@ -4897,12 +4772,10 @@ unixDlError(sqlite3_vfs * NotUsed, int nBuf, char *zBufOut)
 {
 	const char *zErr;
 	UNUSED_PARAMETER(NotUsed);
-	unixEnterMutex();
 	zErr = dlerror();
 	if (zErr) {
 		sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
 	}
-	unixLeaveMutex();
 }
 
 static
@@ -6379,8 +6252,8 @@ proxyClose(sqlite3_file * id)
  * files.
  *
  * This routine is called once during SQLite initialization and by a
- * single thread.  The memory allocation and mutex subsystems have not
- * necessarily been initialized when this routine is called, and so they
+ * single thread.  The memory allocation subsystem have not
+ * necessarily been initialized when this routine \is called, and so they
  * should not be used.
  */
 int
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 9b80282..0ea181d 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -86,7 +86,6 @@ sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed)
 	sqlite3 *db = pData->db;
 	assert(argc == 3);
 	UNUSED_PARAMETER2(NotUsed, argc);
-	assert(sqlite3_mutex_held(db->mutex));
 	if (db->mallocFailed) {
 		corruptSchema(pData, argv[0], 0);
 		return 1;
@@ -165,7 +164,6 @@ sqlite3InitDatabase(sqlite3 * db)
 	InitData initData;
 
 	assert(db->pSchema != NULL);
-	assert(sqlite3_mutex_held(db->mutex));
 
 	memset(&initData, 0, sizeof(InitData));
 	initData.db = db;
@@ -227,7 +225,6 @@ sqlite3SchemaToIndex(sqlite3 * db, Schema * pSchema)
 	 * more likely to cause a segfault than -1 (of course there are assert()
 	 * statements too, but it never hurts to play the odds).
 	 */
-	assert(sqlite3_mutex_held(db->mutex));
 	if (pSchema) {
 		if (db->pSchema == pSchema) {
 			i = 0;
@@ -279,7 +276,6 @@ sqlite3Prepare(sqlite3 * db,	/* Database handle. */
 	sParse.pReprepare = pReprepare;
 	assert(ppStmt && *ppStmt == 0);
 	/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
-	assert(sqlite3_mutex_held(db->mutex));
 
 	/* Check to verify that it is possible to get a read lock on all
 	 * database schemas.  The inability to get a read lock indicates that
@@ -410,7 +406,6 @@ sqlite3LockAndPrepare(sqlite3 * db,		/* Database handle. */
 	if (!sqlite3SafetyCheckOk(db) || zSql == 0) {
 		return SQLITE_MISUSE_BKPT;
 	}
-	sqlite3_mutex_enter(db->mutex);
 	rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt,
 			    pzTail);
 	if (rc == SQLITE_SCHEMA) {
@@ -418,7 +413,6 @@ sqlite3LockAndPrepare(sqlite3 * db,		/* Database handle. */
 		rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt,
 				    pzTail);
 	}
-	sqlite3_mutex_leave(db->mutex);
 	assert(rc == SQLITE_OK || *ppStmt == 0);
 	return rc;
 }
@@ -439,11 +433,9 @@ sqlite3Reprepare(Vdbe * p)
 	const char *zSql;
 	sqlite3 *db;
 
-	assert(sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex));
 	zSql = sqlite3_sql((sqlite3_stmt *) p);
 	assert(zSql != 0);	/* Reprepare only called for prepare_v2() statements */
 	db = sqlite3VdbeDb(p);
-	assert(sqlite3_mutex_held(db->mutex));
 	rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
 	if (rc) {
 		if (rc == SQLITE_NOMEM) {
diff --git a/src/box/sql/printf.c b/src/box/sql/printf.c
index 7884487..4be7bb8 100644
--- a/src/box/sql/printf.c
+++ b/src/box/sql/printf.c
@@ -1167,14 +1167,8 @@ sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...)
  * We house it in a separate routine from sqlite3_log() to avoid using
  * stack space on small-stack systems when logging is disabled.
  *
- * sqlite3_log() must render into a static buffer.  It cannot dynamically
- * allocate memory because it might be called while the memory allocator
- * mutex is held.
- *
  * sqlite3VXPrintf() might ask for *temporary* memory allocations for
  * certain format characters (%q) or for very large precisions or widths.
- * Care must be taken that any sqlite3_log() calls that occur while the
- * memory mutex is held do not use these mechanisms.
  */
 static void
 renderLogMsg(int iErrCode, const char *zFormat, va_list ap)
diff --git a/src/box/sql/random.c b/src/box/sql/random.c
index 4006ef0..4d6e642 100644
--- a/src/box/sql/random.c
+++ b/src/box/sql/random.c
@@ -70,23 +70,13 @@ sqlite3_randomness(int N, void *pBuf)
 #define wsdPrng sqlite3Prng
 #endif
 
-#if SQLITE_THREADSAFE
-	sqlite3_mutex *mutex;
-#endif
-
 #ifndef SQLITE_OMIT_AUTOINIT
 	if (sqlite3_initialize())
 		return;
 #endif
 
-#if SQLITE_THREADSAFE
-	mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
-#endif
-
-	sqlite3_mutex_enter(mutex);
 	if (N <= 0 || pBuf == 0) {
 		wsdPrng.isInit = 0;
-		sqlite3_mutex_leave(mutex);
 		return;
 	}
 
@@ -127,7 +117,6 @@ sqlite3_randomness(int N, void *pBuf)
 		t += wsdPrng.s[wsdPrng.i];
 		*(zBuf++) = wsdPrng.s[t];
 	} while (--N);
-	sqlite3_mutex_leave(mutex);
 }
 
 #ifndef SQLITE_UNTESTABLE
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 50dadf4..f2a74ce 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -180,26 +180,6 @@
 #define SQLITE_NOINLINE
 #endif
 
-
-/*
- * The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
- * 0 means mutexes are permanently disable and the library is never
- * threadsafe.  1 means the library is serialized which is the highest
- * level of threadsafety.  2 means the library is multithreaded - multiple
- * threads can use SQLite as long as no two threads try to use the same
- * database connection at the same time.
- *
- * Older versions of SQLite used an optional THREADSAFE macro.
- * We support that for legacy.
- */
-#if !defined(SQLITE_THREADSAFE)
-#if defined(THREADSAFE)
-#define SQLITE_THREADSAFE THREADSAFE
-#else
-#define SQLITE_THREADSAFE 1	/* IMP: R-07272-22309 */
-#endif
-#endif
-
 /*
  * Powersafe overwrite is on by default.  But can be turned off using
  * the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
@@ -251,16 +231,6 @@
 #endif
 
 /*
- * We need to define _XOPEN_SOURCE as follows in order to enable
- * recursive mutexes on most Unix systems and fchmod() on OpenBSD.
- * But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
- * it.
- */
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
-#define _XOPEN_SOURCE 600
-#endif
-
-/*
  * Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on.
  */
 #if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG)
@@ -450,20 +420,6 @@ struct sqlite3_vfs {
 	*/
 };
 
-typedef struct sqlite3_mutex sqlite3_mutex;
-typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
-struct sqlite3_mutex_methods {
-	int (*xMutexInit) (void);
-	int (*xMutexEnd) (void);
-	sqlite3_mutex *(*xMutexAlloc) (int);
-	void (*xMutexFree) (sqlite3_mutex *);
-	void (*xMutexEnter) (sqlite3_mutex *);
-	int (*xMutexTry) (sqlite3_mutex *);
-	void (*xMutexLeave) (sqlite3_mutex *);
-	int (*xMutexHeld) (sqlite3_mutex *);
-	int (*xMutexNotheld) (sqlite3_mutex *);
-};
-
 #define SQLITE_LIMIT_LENGTH                    0
 #define SQLITE_LIMIT_SQL_LENGTH                1
 #define SQLITE_LIMIT_COLUMN                    2
@@ -1215,7 +1171,7 @@ sqlite3_bind_parameter_lindex(sqlite3_stmt * pStmt, const char *zName,
  * SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it
  * to zero.
  */
-#if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0
+#if SQLITE_TEMP_STORE==3
 #undef SQLITE_MAX_WORKER_THREADS
 #define SQLITE_MAX_WORKER_THREADS 0
 #endif
@@ -1657,7 +1613,6 @@ typedef int VList;
 #include "cursor.h"
 #include "vdbe.h"
 #include "os.h"
-#include "mutex.h"
 
 /*
  * An instance of the following structure stores a database schema.
@@ -1729,7 +1684,6 @@ struct sqlite3 {
 	sqlite3_vfs *pVfs;	/* OS Interface */
 	struct Vdbe *pVdbe;	/* List of active virtual machines */
 	struct coll *pDfltColl;	/* The default collating sequence (BINARY) */
-	sqlite3_mutex *mutex;	/* Connection mutex */
 	struct Schema *pSchema; /* Schema of the database */
 	i64 szMmap;		/* Default mmap_size setting */
 	int errCode;		/* Most recent error code (SQLITE_*) */
@@ -3365,8 +3319,6 @@ typedef struct {
  */
 struct Sqlite3Config {
 	int bMemstat;		/* True to enable memory status */
-	int bCoreMutex;		/* True to enable core mutexing */
-	int bFullMutex;		/* True to enable full mutexing */
 	int bOpenUri;		/* True to interpret filenames as URIs */
 	int bUseCis;		/* Use covering indices for full-scans */
 	int mxStrlen;		/* Maximum string length */
@@ -3375,7 +3327,6 @@ struct Sqlite3Config {
 	int nLookaside;		/* Default lookaside buffer count */
 	int nStmtSpill;		/* Stmt-journal spill-to-disk threshold */
 	sqlite3_mem_methods m;	/* Low-level memory allocation interface */
-	sqlite3_mutex_methods mutex;	/* Low-level mutex interface */
 	sqlite3_pcache_methods2 pcache2;	/* Low-level page-cache interface */
 	void *pHeap;		/* Heap storage space */
 	int nHeap;		/* Size of pHeap[] */
@@ -3396,10 +3347,7 @@ struct Sqlite3Config {
 	 */
 	int isInit;		/* True after initialization has finished */
 	int inProgress;		/* True while initialization in progress */
-	int isMutexInit;	/* True after mutexes are initialized */
 	int isMallocInit;	/* True after malloc is initialized */
-	int nRefInitMutex;	/* Number of users of pInitMutex */
-	sqlite3_mutex *pInitMutex;	/* Mutex used by sqlite3_initialize() */
 	void (*xLog) (void *, int, const char *);	/* Function for logging */
 	void *pLogArg;		/* First argument to xLog() */
 #ifdef SQLITE_ENABLE_SQLLOG
@@ -3640,28 +3588,11 @@ const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
 const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
 #endif
 
-#ifndef SQLITE_MUTEX_OMIT
-sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
-sqlite3_mutex_methods const *sqlite3NoopMutex(void);
-sqlite3_mutex *sqlite3MutexAlloc(int);
-int sqlite3MutexInit(void);
-int sqlite3MutexEnd(void);
-#endif
-#if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP)
-void sqlite3MemoryBarrier(void);
-#else
-#define sqlite3MemoryBarrier()
-#endif
-
 sqlite3_int64 sqlite3StatusValue(int);
 void sqlite3StatusUp(int, int);
 void sqlite3StatusDown(int, int);
 void sqlite3StatusHighwater(int, int);
 
-/* Access to mutexes used by sqlite3_status() */
-sqlite3_mutex *sqlite3Pcache1Mutex(void);
-sqlite3_mutex *sqlite3MallocMutex(void);
-
 #ifndef SQLITE_OMIT_FLOATING_POINT
 int sqlite3IsNaN(double);
 #else
diff --git a/src/box/sql/status.c b/src/box/sql/status.c
index 8b476f8..963d3d8 100644
--- a/src/box/sql/status.c
+++ b/src/box/sql/status.c
@@ -68,8 +68,7 @@ static SQLITE_WSD struct sqlite3StatType {
 #endif
 
 /*
- * Return the current value of a status parameter.  The caller must
- * be holding the appropriate mutex.
+ * Return the current value of a status parameter.
  */
 sqlite3_int64
 sqlite3StatusValue(int op)
@@ -81,8 +80,7 @@ sqlite3StatusValue(int op)
 }
 
 /*
- * Add N to the value of a status record.  The caller must hold the
- * appropriate mutex.  (Locking is checked by assert()).
+ * Add N to the value of a status record.
  *
  * The StatusUp() routine can accept positive or negative values for N.
  * The value of N is added to the current status value and the high-water
@@ -115,7 +113,6 @@ sqlite3StatusDown(int op, int N)
 
 /*
  * Adjust the highwater mark if necessary.
- * The caller must hold the appropriate mutex.
  */
 void
 sqlite3StatusHighwater(int op, int X)
@@ -193,7 +190,6 @@ sqlite3_db_status(sqlite3 * db,	/* The database connection whose status is desir
 		return SQLITE_MISUSE_BKPT;
 	}
 #endif
-	sqlite3_mutex_enter(db->mutex);
 	switch (op) {
 	case SQLITE_DBSTATUS_LOOKASIDE_USED:{
 			*pCurrent = db->lookaside.nOut;
@@ -347,6 +343,5 @@ sqlite3_db_status(sqlite3 * db,	/* The database connection whose status is desir
 			rc = SQLITE_ERROR;
 		}
 	}
-	sqlite3_mutex_leave(db->mutex);
 	return rc;
 }
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index 056924e..f810db4 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -609,11 +609,9 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
 	assert(nErr == 0);
 	pParse->zTail = &zSql[i];
 #ifdef YYTRACKMAXSTACKDEPTH
-	sqlite3_mutex_enter(sqlite3MallocMutex());
 	sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
 			       sqlite3ParserStackPeak(pEngine)
 	    );
-	sqlite3_mutex_leave(sqlite3MallocMutex());
 #endif				/* YYDEBUG */
 	sqlite3ParserFree(pEngine, sqlite3_free);
 	if (db->mallocFailed) {
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 96609b5..6877cab 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -5527,10 +5527,7 @@ abort_due_to_error:
 		sqlite3SchemaClear(db);
 	}
 
-	/* This is the only way out of this procedure.  We have to
-	 * release the mutexes on btrees that were acquired at the
-	 * top.
-	 */
+	/* This is the only way out of this procedure. */
 vdbe_return:
 	testcase( nVmStep>0);
 	p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 9c86c4c..dff1e16 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -125,7 +125,6 @@ sqlite3_finalize(sqlite3_stmt * pStmt)
 		sqlite3 *db = v->db;
 		if (vdbeSafety(v))
 			return SQLITE_MISUSE_BKPT;
-		sqlite3_mutex_enter(db->mutex);
 		checkProfileCallback(db, v);
 		rc = sqlite3VdbeFinalize(v);
 		rc = sqlite3ApiExit(db, rc);
@@ -150,13 +149,11 @@ sqlite3_reset(sqlite3_stmt * pStmt)
 	} else {
 		Vdbe *v = (Vdbe *) pStmt;
 		sqlite3 *db = v->db;
-		sqlite3_mutex_enter(db->mutex);
 		checkProfileCallback(db, v);
 		rc = sqlite3VdbeReset(v);
 		sqlite3VdbeRewind(v);
 		assert((rc & (db->errMask)) == rc);
 		rc = sqlite3ApiExit(db, rc);
-		sqlite3_mutex_leave(db->mutex);
 	}
 	return rc;
 }
@@ -170,10 +167,6 @@ sqlite3_clear_bindings(sqlite3_stmt * pStmt)
 	int i;
 	int rc = SQLITE_OK;
 	Vdbe *p = (Vdbe *) pStmt;
-#if SQLITE_THREADSAFE
-	sqlite3_mutex *mutex = ((Vdbe *) pStmt)->db->mutex;
-#endif
-	sqlite3_mutex_enter(mutex);
 	for (i = 0; i < p->nVar; i++) {
 		sqlite3VdbeMemRelease(&p->aVar[i]);
 		p->aVar[i].flags = MEM_Null;
@@ -181,7 +174,6 @@ sqlite3_clear_bindings(sqlite3_stmt * pStmt)
 	if (p->isPrepareV2 && p->expmask) {
 		p->expired = 1;
 	}
-	sqlite3_mutex_leave(mutex);
 	return rc;
 }
 
@@ -369,7 +361,6 @@ sqlite3_result_blob(sqlite3_context * pCtx,
     )
 {
 	assert(n >= 0);
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	if (sqlite3VdbeMemSetStr(pCtx->pOut, z, n,0, xDel) == SQLITE_TOOBIG) {
 		sqlite3_result_error_toobig(pCtx);
 	}
@@ -380,7 +371,6 @@ sqlite3_result_blob64(sqlite3_context * pCtx,
 		      const void *z, sqlite3_uint64 n, void (*xDel) (void *)
     )
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	assert(xDel != SQLITE_DYNAMIC);
 	if (n > 0x7fffffff) {
 		(void)invokeValueDestructor(z, xDel, pCtx);
@@ -392,14 +382,12 @@ sqlite3_result_blob64(sqlite3_context * pCtx,
 void
 sqlite3_result_double(sqlite3_context * pCtx, double rVal)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	sqlite3VdbeMemSetDouble(pCtx->pOut, rVal);
 }
 
 void
 sqlite3_result_error(sqlite3_context * pCtx, const char *z, int n)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	pCtx->isError = SQLITE_ERROR;
 	pCtx->fErrorOrAux = 1;
 	sqlite3VdbeMemSetStr(pCtx->pOut, z, n, 1, SQLITE_TRANSIENT);
@@ -408,21 +396,18 @@ sqlite3_result_error(sqlite3_context * pCtx, const char *z, int n)
 void
 sqlite3_result_int(sqlite3_context * pCtx, int iVal)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	sqlite3VdbeMemSetInt64(pCtx->pOut, (i64) iVal);
 }
 
 void
 sqlite3_result_int64(sqlite3_context * pCtx, i64 iVal)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	sqlite3VdbeMemSetInt64(pCtx->pOut, iVal);
 }
 
 void
 sqlite3_result_null(sqlite3_context * pCtx)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	sqlite3VdbeMemSetNull(pCtx->pOut);
 }
 
@@ -430,7 +415,6 @@ void
 sqlite3_result_subtype(sqlite3_context * pCtx, unsigned int eSubtype)
 {
 	Mem *pOut = pCtx->pOut;
-	assert(sqlite3_mutex_held(pOut->db->mutex));
 	pOut->eSubtype = eSubtype & 0xff;
 	pOut->flags |= MEM_Subtype;
 }
@@ -440,7 +424,6 @@ sqlite3_result_text(sqlite3_context * pCtx,
 		    const char *z, int n, void (*xDel) (void *)
     )
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	setResultStrOrError(pCtx, z, n, xDel);
 }
 
@@ -450,7 +433,6 @@ sqlite3_result_text64(sqlite3_context * pCtx,
 		      sqlite3_uint64 n,
 		      void (*xDel) (void *))
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	assert(xDel != SQLITE_DYNAMIC);
 	if (n > 0x7fffffff) {
 		(void)invokeValueDestructor(z, xDel, pCtx);
@@ -462,14 +444,12 @@ sqlite3_result_text64(sqlite3_context * pCtx,
 void
 sqlite3_result_value(sqlite3_context * pCtx, sqlite3_value * pValue)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	sqlite3VdbeMemCopy(pCtx->pOut, pValue);
 }
 
 void
 sqlite3_result_zeroblob(sqlite3_context * pCtx, int n)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n);
 }
 
@@ -477,7 +457,6 @@ int
 sqlite3_result_zeroblob64(sqlite3_context * pCtx, u64 n)
 {
 	Mem *pOut = pCtx->pOut;
-	assert(sqlite3_mutex_held(pOut->db->mutex));
 	if (n > (u64) pOut->db->aLimit[SQLITE_LIMIT_LENGTH]) {
 		return SQLITE_TOOBIG;
 	}
@@ -504,7 +483,6 @@ sqlite3_result_error_code(sqlite3_context * pCtx, int errCode)
 void
 sqlite3_result_error_toobig(sqlite3_context * pCtx)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	pCtx->isError = SQLITE_TOOBIG;
 	pCtx->fErrorOrAux = 1;
 	sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, 1,
@@ -515,7 +493,6 @@ sqlite3_result_error_toobig(sqlite3_context * pCtx)
 void
 sqlite3_result_error_nomem(sqlite3_context * pCtx)
 {
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	sqlite3VdbeMemSetNull(pCtx->pOut);
 	pCtx->isError = SQLITE_NOMEM_BKPT;
 	pCtx->fErrorOrAux = 1;
@@ -667,7 +644,6 @@ sqlite3_step(sqlite3_stmt * pStmt)
 		return SQLITE_MISUSE_BKPT;
 	}
 	db = v->db;
-	sqlite3_mutex_enter(db->mutex);
 	v->doingRerun = 0;
 	while ((rc = sqlite3Step(v)) == SQLITE_SCHEMA
 	       && cnt++ < SQLITE_MAX_SCHEMA_RETRY) {
@@ -700,7 +676,6 @@ sqlite3_step(sqlite3_stmt * pStmt)
 		}
 	}
 	rc = sqlite3ApiExit(db, rc);
-	sqlite3_mutex_leave(db->mutex);
 	return rc;
 }
 
@@ -814,7 +789,6 @@ void *
 sqlite3_aggregate_context(sqlite3_context * p, int nByte)
 {
 	assert(p && p->pFunc && p->pFunc->xFinalize);
-	assert(sqlite3_mutex_held(p->pOut->db->mutex));
 	testcase(nByte < 0);
 	if ((p->pMem->flags & MEM_Agg) == 0) {
 		return createAggContext(p, nByte);
@@ -832,7 +806,6 @@ sqlite3_get_auxdata(sqlite3_context * pCtx, int iArg)
 {
 	AuxData *pAuxData;
 
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	if (pCtx->pVdbe == 0)
 		return 0;
 
@@ -858,7 +831,6 @@ sqlite3_set_auxdata(sqlite3_context * pCtx,
 	AuxData *pAuxData;
 	Vdbe *pVdbe = pCtx->pVdbe;
 
-	assert(sqlite3_mutex_held(pCtx->pOut->db->mutex));
 	if (iArg < 0)
 		goto failed;
 	if (pVdbe == 0)
@@ -973,7 +945,6 @@ columnMem(sqlite3_stmt * pStmt, int i)
 	if (pVm == 0)
 		return (Mem *) columnNullValue();
 	assert(pVm->db);
-	sqlite3_mutex_enter(pVm->db->mutex);
 	if (pVm->pResultSet != 0 && i < pVm->nResColumn && i >= 0) {
 		pOut = &pVm->pResultSet[i];
 	} else {
@@ -1011,9 +982,7 @@ columnMallocFailure(sqlite3_stmt * pStmt)
 	Vdbe *p = (Vdbe *) pStmt;
 	if (p) {
 		assert(p->db != 0);
-		assert(sqlite3_mutex_held(p->db->mutex));
 		p->rc = sqlite3ApiExit(p->db, p->rc);
-		sqlite3_mutex_leave(p->db->mutex);
 	}
 }
 
@@ -1131,7 +1100,6 @@ columnName(sqlite3_stmt * pStmt,
 	n = sqlite3_column_count(pStmt);
 	if (N < n && N >= 0) {
 		N += useType * n;
-		sqlite3_mutex_enter(db->mutex);
 		assert(db->mallocFailed == 0);
 		ret = xFunc(&p->aColName[N]);
 		/* A malloc may have failed inside of the xFunc() call. If this
@@ -1141,7 +1109,6 @@ columnName(sqlite3_stmt * pStmt,
 			sqlite3OomClear(db);
 			ret = 0;
 		}
-		sqlite3_mutex_leave(db->mutex);
 	}
 	return ret;
 }
@@ -1226,9 +1193,6 @@ sqlite3_column_origin_name(sqlite3_stmt * pStmt, int N)
  * the same as binding a NULL value to the column. If the "i" parameter is
  * out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
  *
- * A successful evaluation of this routine acquires the mutex on p.
- * the mutex is released if any kind of error occurs.
- *
  * The error code stored in database p->db is overwritten with the return
  * value in any case.
  */
@@ -1239,17 +1203,14 @@ vdbeUnbind(Vdbe * p, int i)
 	if (vdbeSafetyNotNull(p)) {
 		return SQLITE_MISUSE_BKPT;
 	}
-	sqlite3_mutex_enter(p->db->mutex);
 	if (p->magic != VDBE_MAGIC_RUN || p->pc >= 0) {
 		sqlite3Error(p->db, SQLITE_MISUSE);
-		sqlite3_mutex_leave(p->db->mutex);
 		sqlite3_log(SQLITE_MISUSE,
 			    "bind on a busy prepared statement: [%s]", p->zSql);
 		return SQLITE_MISUSE_BKPT;
 	}
 	if (i < 1 || i > p->nVar) {
 		sqlite3Error(p->db, SQLITE_RANGE);
-		sqlite3_mutex_leave(p->db->mutex);
 		return SQLITE_RANGE;
 	}
 	i--;
@@ -1299,7 +1260,6 @@ bindText(sqlite3_stmt * pStmt,	/* The statement to bind against */
 			sqlite3Error(p->db, rc);
 			rc = sqlite3ApiExit(p->db, rc);
 		}
-		sqlite3_mutex_leave(p->db->mutex);
 	} else if (xDel != SQLITE_STATIC && xDel != SQLITE_TRANSIENT) {
 		xDel((void *)zData);
 	}
@@ -1344,7 +1304,6 @@ sqlite3_bind_double(sqlite3_stmt * pStmt, int i, double rValue)
 	rc = vdbeUnbind(p, i);
 	if (rc == SQLITE_OK) {
 		sqlite3VdbeMemSetDouble(&p->aVar[i - 1], rValue);
-		sqlite3_mutex_leave(p->db->mutex);
 	}
 	return rc;
 }
@@ -1363,7 +1322,6 @@ sqlite3_bind_int64(sqlite3_stmt * pStmt, int i, sqlite_int64 iValue)
 	rc = vdbeUnbind(p, i);
 	if (rc == SQLITE_OK) {
 		sqlite3VdbeMemSetInt64(&p->aVar[i - 1], iValue);
-		sqlite3_mutex_leave(p->db->mutex);
 	}
 	return rc;
 }
@@ -1374,9 +1332,6 @@ sqlite3_bind_null(sqlite3_stmt * pStmt, int i)
 	int rc;
 	Vdbe *p = (Vdbe *) pStmt;
 	rc = vdbeUnbind(p, i);
-	if (rc == SQLITE_OK) {
-		sqlite3_mutex_leave(p->db->mutex);
-	}
 	return rc;
 }
 
@@ -1448,7 +1403,6 @@ sqlite3_bind_zeroblob(sqlite3_stmt * pStmt, int i, int n)
 	rc = vdbeUnbind(p, i);
 	if (rc == SQLITE_OK) {
 		sqlite3VdbeMemSetZeroBlob(&p->aVar[i - 1], n);
-		sqlite3_mutex_leave(p->db->mutex);
 	}
 	return rc;
 }
@@ -1458,7 +1412,6 @@ sqlite3_bind_zeroblob64(sqlite3_stmt * pStmt, int i, sqlite3_uint64 n)
 {
 	int rc;
 	Vdbe *p = (Vdbe *) pStmt;
-	sqlite3_mutex_enter(p->db->mutex);
 	if (n > (u64) p->db->aLimit[SQLITE_LIMIT_LENGTH]) {
 		rc = SQLITE_TOOBIG;
 	} else {
@@ -1466,7 +1419,6 @@ sqlite3_bind_zeroblob64(sqlite3_stmt * pStmt, int i, sqlite3_uint64 n)
 		rc = sqlite3_bind_zeroblob(pStmt, i, n);
 	}
 	rc = sqlite3ApiExit(p->db, rc);
-	sqlite3_mutex_leave(p->db->mutex);
 	return rc;
 }
 
@@ -1534,11 +1486,9 @@ sqlite3TransferBindings(sqlite3_stmt * pFromStmt, sqlite3_stmt * pToStmt)
 	int i;
 	assert(pTo->db == pFrom->db);
 	assert(pTo->nVar == pFrom->nVar);
-	sqlite3_mutex_enter(pTo->db->mutex);
 	for (i = 0; i < pFrom->nVar; i++) {
 		sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
 	}
-	sqlite3_mutex_leave(pTo->db->mutex);
 	return SQLITE_OK;
 }
 
@@ -1580,13 +1530,11 @@ sqlite3_next_stmt(sqlite3 * pDb, sqlite3_stmt * pStmt)
 		return 0;
 	}
 #endif
-	sqlite3_mutex_enter(pDb->mutex);
 	if (pStmt == 0) {
 		pNext = (sqlite3_stmt *) pDb->pVdbe;
 	} else {
 		pNext = (sqlite3_stmt *) ((Vdbe *) pStmt)->pNext;
 	}
-	sqlite3_mutex_leave(pDb->mutex);
 	return pNext;
 }
 
@@ -1639,9 +1587,7 @@ sqlite3_expanded_sql(sqlite3_stmt * pStmt)
 	const char *zSql = sqlite3_sql(pStmt);
 	if (zSql) {
 		Vdbe *p = (Vdbe *) pStmt;
-		sqlite3_mutex_enter(p->db->mutex);
 		z = sqlite3VdbeExpandSql(p, zSql);
-		sqlite3_mutex_leave(p->db->mutex);
 	}
 	return z;
 #endif
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 92bf994..2b8d858 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -3000,7 +3000,6 @@ sqlite3VdbeDelete(Vdbe * p)
 	if (NEVER(p == 0))
 		return;
 	db = p->db;
-	assert(sqlite3_mutex_held(db->mutex));
 	sqlite3VdbeClearObject(db, p);
 	if (p->pPrev) {
 		p->pPrev->pNext = p->pNext;
@@ -4165,7 +4164,6 @@ sqlite3VdbeIdxKeyCompare(sqlite3 * db,			/* Database connection */
 void
 sqlite3VdbeSetChanges(sqlite3 * db, int nChange)
 {
-	assert(sqlite3_mutex_held(db->mutex));
 	db->nChange = nChange;
 	db->nTotalChange += nChange;
 }
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 5dd85b8..9dd254f 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -183,7 +183,6 @@ sqlite3VdbeMemClearAndResize(Mem * pMem, int szNew)
 int
 sqlite3VdbeMemMakeWriteable(Mem * pMem)
 {
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	if ((pMem->flags & (MEM_Str | MEM_Blob)) != 0) {
 		if (ExpandBlob(pMem))
 			return SQLITE_NOMEM;
@@ -215,7 +214,6 @@ sqlite3VdbeMemExpandBlob(Mem * pMem)
 	int nByte;
 	assert(pMem->flags & MEM_Zero);
 	assert(pMem->flags & MEM_Blob);
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 
 	/* Set nByte to the number of bytes required to store the expanded blob. */
 	nByte = pMem->n + pMem->u.nZero;
@@ -255,7 +253,6 @@ vdbeMemAddTerminator(Mem * pMem)
 int
 sqlite3VdbeMemNulTerminate(Mem * pMem)
 {
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	testcase((pMem->flags & (MEM_Term | MEM_Str)) == (MEM_Term | MEM_Str));
 	testcase((pMem->flags & (MEM_Term | MEM_Str)) == 0);
 	if ((pMem->flags & (MEM_Term | MEM_Str)) != MEM_Str) {
@@ -285,7 +282,6 @@ sqlite3VdbeMemStringify(Mem * pMem, u8 bForce)
 	int fg = pMem->flags;
 	const int nByte = 32;
 
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	assert(!(fg & MEM_Zero));
 	assert(!(fg & (MEM_Str | MEM_Blob)));
 	assert(fg & (MEM_Int | MEM_Real));
@@ -323,7 +319,6 @@ sqlite3VdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
 		sqlite3_context ctx;
 		Mem t;
 		assert((pMem->flags & MEM_Null) != 0 || pFunc == pMem->u.pDef);
-		assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 		memset(&ctx, 0, sizeof(ctx));
 		memset(&t, 0, sizeof(t));
 		t.flags = MEM_Null;
@@ -353,7 +348,6 @@ sqlite3VdbeMemFinalize(Mem * pMem, FuncDef * pFunc)
 static SQLITE_NOINLINE void
 vdbeMemClearExternAndSetNull(Mem * p)
 {
-	assert(p->db == 0 || sqlite3_mutex_held(p->db->mutex));
 	assert(VdbeMemDynamic(p));
 	if (p->flags & MEM_Agg) {
 		sqlite3VdbeMemFinalize(p, p->u.pDef);
@@ -458,7 +452,6 @@ i64
 sqlite3VdbeIntValue(Mem * pMem)
 {
 	int flags;
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 	flags = pMem->flags;
 	if (flags & MEM_Int) {
@@ -484,7 +477,6 @@ sqlite3VdbeIntValue(Mem * pMem)
 double
 sqlite3VdbeRealValue(Mem * pMem)
 {
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 	if (pMem->flags & MEM_Real) {
 		return pMem->u.r;
@@ -510,7 +502,6 @@ sqlite3VdbeIntegerAffinity(Mem * pMem)
 {
 	i64 ix;
 	assert(pMem->flags & MEM_Real);
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 
 	ix = doubleToInt64(pMem->u.r);
@@ -537,7 +528,6 @@ sqlite3VdbeIntegerAffinity(Mem * pMem)
 int
 sqlite3VdbeMemIntegerify(Mem * pMem)
 {
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 
 	pMem->u.i = sqlite3VdbeIntValue(pMem);
@@ -552,7 +542,6 @@ sqlite3VdbeMemIntegerify(Mem * pMem)
 int
 sqlite3VdbeMemRealify(Mem * pMem)
 {
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 
 	pMem->u.r = sqlite3VdbeRealValue(pMem);
@@ -573,7 +562,6 @@ sqlite3VdbeMemNumerify(Mem * pMem)
 {
 	if ((pMem->flags & (MEM_Int | MEM_Real | MEM_Null)) == 0) {
 		assert((pMem->flags & (MEM_Blob | MEM_Str)) != 0);
-		assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 		if (0 == sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n)) {
 			MemSetTypeFlag(pMem, MEM_Int);
 		} else {
@@ -843,8 +831,6 @@ sqlite3VdbeMemCopy(Mem * pTo, const Mem * pFrom)
 void
 sqlite3VdbeMemMove(Mem * pTo, Mem * pFrom)
 {
-	assert(pFrom->db == 0 || sqlite3_mutex_held(pFrom->db->mutex));
-	assert(pTo->db == 0 || sqlite3_mutex_held(pTo->db->mutex));
 	assert(pFrom->db == 0 || pTo->db == 0 || pFrom->db == pTo->db);
 
 	sqlite3VdbeMemRelease(pTo);
@@ -879,7 +865,6 @@ sqlite3VdbeMemSetStr(Mem * pMem,	/* Memory cell to set to string value */
 	int nByte = n;		/* New value for pMem->n */
 	int iLimit;		/* Maximum allowed string or blob size */
 	u16 flags = 0;		/* New value for pMem->flags */
-	assert(pMem->db == 0 || sqlite3_mutex_held(pMem->db->mutex));
 
 	/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
 	if (!z) {
@@ -1019,7 +1004,6 @@ static SQLITE_NOINLINE const void *
 valueToText(sqlite3_value * pVal)
 {
 	assert(pVal != 0);
-	assert(pVal->db == 0 || sqlite3_mutex_held(pVal->db->mutex));
 	assert((pVal->flags & (MEM_Null)) == 0);
 	if (pVal->flags & (MEM_Blob | MEM_Str)) {
 		if (ExpandBlob(pVal))
@@ -1048,7 +1032,6 @@ sqlite3ValueText(sqlite3_value * pVal)
 {
 	if (!pVal)
 		return 0;
-	assert(pVal->db == 0 || sqlite3_mutex_held(pVal->db->mutex));
 	if ((pVal->flags & (MEM_Str | MEM_Term)) == (MEM_Str | MEM_Term)) {
 		return pVal->z;
 	}
diff --git a/src/box/sql/vdbesort.c b/src/box/sql/vdbesort.c
index 68dbf50..fc10ef6 100644
--- a/src/box/sql/vdbesort.c
+++ b/src/box/sql/vdbesort.c
@@ -863,11 +863,7 @@ sqlite3VdbeSorterInit(sqlite3 * db,	/* Database connection (for malloc()) */
 
 	/* Initialize the upper limit on the number of worker threads */
 #if SQLITE_MAX_WORKER_THREADS>0
-	if (sqlite3TempInMemory(db) || sqlite3GlobalConfig.bCoreMutex == 0) {
-		nWorker = 0;
-	} else {
-		nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS];
-	}
+	nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS];
 #endif
 
 	/* Do not allow the total number of threads (main thread + all workers)
-- 
2.11.0





More information about the Tarantool-patches mailing list