diff --git a/h2/src/main/org/h2/command/Parser.java b/h2/src/main/org/h2/command/Parser.java
index 925877f..f04b31a 100644
--- a/h2/src/main/org/h2/command/Parser.java
+++ b/h2/src/main/org/h2/command/Parser.java
@@ -1614,6 +1614,9 @@
             } else if (readIf("IGNORE")) {
                 command.setDropAction(ConstraintActionType.SET_DEFAULT);
             }
+            if (readIf("TRANSACTIONAL")) {
+                command.setTransactional(true);
+            }
             return command;
         } else if (readIf("INDEX")) {
             boolean ifExists = readIfExists(false);
@@ -1626,6 +1629,9 @@
             if (readIf("ON")) {
                 readIdentifierWithSchema();
             }
+            if (readIf("TRANSACTIONAL")) {
+                command.setTransactional(true);
+            }
             return command;
         } else if (readIf("USER")) {
             boolean ifExists = readIfExists(false);
@@ -4683,6 +4689,9 @@
                 }
 
             }
+            if (readIf("TRANSACTIONAL")) {
+                command.setTransactional(true);
+            }
             command.setHash(hash);
             command.setSpatial(spatial);
             return command;
@@ -6459,6 +6468,9 @@
             }
             read("REFERENCES");
             parseReferences(command, schema, tableName);
+            if (readIf("TRANSACTIONAL")) {
+               command.setTransactional(true);
+           }
         } else {
             if (constraintName != null) {
                 throw getSyntaxError();
diff --git a/h2/src/main/org/h2/command/ddl/DropIndex.java b/h2/src/main/org/h2/command/ddl/DropIndex.java
index 9344a13..a13200c 100644
--- a/h2/src/main/org/h2/command/ddl/DropIndex.java
+++ b/h2/src/main/org/h2/command/ddl/DropIndex.java
@@ -41,7 +41,9 @@
 
     @Override
     public int update() {
-        session.commit(true);
+        if (!transactional) {
+            session.commit(true);
+        }
         Database db = session.getDatabase();
         Index index = getSchema().findIndex(session, indexName);
         if (index == null) {
diff --git a/h2/src/main/org/h2/command/ddl/DropTable.java b/h2/src/main/org/h2/command/ddl/DropTable.java
index a3e6f3e..e7bbdcf 100644
--- a/h2/src/main/org/h2/command/ddl/DropTable.java
+++ b/h2/src/main/org/h2/command/ddl/DropTable.java
@@ -125,7 +125,9 @@
 
     @Override
     public int update() {
-        session.commit(true);
+        if (!transactional) {
+            session.commit(true);
+        }
         prepareDrop();
         executeDrop();
         return 0;
diff --git a/h2/src/main/org/h2/table/RegularTable.java b/h2/src/main/org/h2/table/RegularTable.java
index f607396..ffec091 100644
--- a/h2/src/main/org/h2/table/RegularTable.java
+++ b/h2/src/main/org/h2/table/RegularTable.java
@@ -534,39 +534,41 @@
     }
 
     private boolean doLock2(Session session, int lockMode, boolean exclusive) {
-        if (exclusive) {
-            if (lockExclusiveSession == null) {
-                if (lockSharedSessions.isEmpty()) {
-                    traceLock(session, exclusive, "added for");
-                    session.addLock(this);
-                    lockExclusiveSession = session;
-                    return true;
-                } else if (lockSharedSessions.size() == 1 &&
-                        lockSharedSessions.contains(session)) {
-                    traceLock(session, exclusive, "add (upgraded) for ");
-                    lockExclusiveSession = session;
-                    return true;
-                }
-            }
-        } else {
-            if (lockExclusiveSession == null) {
-                if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
-                    if (!database.isMultiThreaded() && !database.isMultiVersion()) {
-                        // READ_COMMITTED: a read lock is acquired,
-                        // but released immediately after the operation
-                        // is complete.
-                        // When allowing only one thread, no lock is
-                        // required.
-                        // Row level locks work like read committed.
+        synchronized (this) {
+            if (exclusive) {
+                if (lockExclusiveSession == null) {
+                    if (lockSharedSessions.isEmpty()) {
+                        traceLock(session, exclusive, "added for");
+                        session.addLock(this);
+                        lockExclusiveSession = session;
+                        return true;
+                    } else if (lockSharedSessions.size() == 1 &&
+                            lockSharedSessions.contains(session)) {
+                        traceLock(session, exclusive, "add (upgraded) for ");
+                        lockExclusiveSession = session;
                         return true;
                     }
                 }
-                if (!lockSharedSessions.contains(session)) {
-                    traceLock(session, exclusive, "ok");
-                    session.addLock(this);
-                    lockSharedSessions.add(session);
+            } else {
+                if (lockExclusiveSession == null) {
+                    if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
+                        if (!database.isMultiThreaded() && !database.isMultiVersion()) {
+                            // READ_COMMITTED: a read lock is acquired,
+                            // but released immediately after the operation
+                            // is complete.
+                            // When allowing only one thread, no lock is
+                            // required.
+                            // Row level locks work like read committed.
+                            return true;
+                        }
+                    }
+                    if (!lockSharedSessions.contains(session)) {
+                        traceLock(session, exclusive, "ok");
+                        session.addLock(this);
+                        lockSharedSessions.add(session);
+                    }
+                    return true;
                 }
-                return true;
             }
         }
         return false;
@@ -639,12 +641,15 @@
                     }
                 }
             }
-            if (error == null && lockExclusiveSession != null) {
-                Table t = lockExclusiveSession.getWaitForLock();
-                if (t != null) {
-                    error = t.checkDeadlock(lockExclusiveSession, clash, visited);
-                    if (error != null) {
-                        error.add(session);
+            synchronized (this)
+            {
+                if (error == null && lockExclusiveSession != null) {
+                    Table t = lockExclusiveSession.getWaitForLock();
+                    if (t != null) {
+                        error = t.checkDeadlock(lockExclusiveSession, clash, visited);
+                        if (error != null) {
+                            error.add(session);
+                        }
                     }
                 }
             }
@@ -667,14 +672,16 @@
     @Override
     public void unlock(Session s) {
         if (database != null) {
-            traceLock(s, lockExclusiveSession == s, "unlock");
-            if (lockExclusiveSession == s) {
-                lockExclusiveSession = null;
-            }
-            synchronized (database) {
+            synchronized (this) {
+                traceLock(s, lockExclusiveSession == s, "unlock");
+                if (lockExclusiveSession == s) {
+                    lockExclusiveSession = null;
+                }
                 if (!lockSharedSessions.isEmpty()) {
                     lockSharedSessions.remove(s);
                 }
+            }
+            synchronized (database) {
                 if (!waitingSessions.isEmpty()) {
                     database.notifyAll();
                 }
@@ -720,7 +727,10 @@
         scanIndex.remove(session);
         database.removeMeta(session, getId());
         scanIndex = null;
-        lockExclusiveSession = null;
+        synchronized (this)
+        {
+            lockExclusiveSession = null;
+        }
         lockSharedSessions = null;
         invalidate();
     }
