diff --git a/VC++Files/winmysqladmin/main.cpp b/VC++Files/winmysqladmin/main.cpp
index 6ca296592559664f6e70f68fb8c4e4443673f583..dfb2004a7808a0315ad39e6e9f87d180aea9bc0a 100644
--- a/VC++Files/winmysqladmin/main.cpp
+++ b/VC++Files/winmysqladmin/main.cpp
@@ -1196,7 +1196,7 @@ bool __fastcall TForm1::Shutd()
   if (IsConnect)
    {
      mysql_kill(MySQL,mysql_thread_id(MySQL));
-     mysql_shutdown(MySQL);
+     mysql_shutdown(MySQL, SHUTDOWN_DEFAULT);
      StatusLine->SimpleText = "";
 
    }
diff --git a/VC++Files/winmysqladmin/mysql.h b/VC++Files/winmysqladmin/mysql.h
index e83babb8fa8b3d8ea290ad142618c9dbe1ca1a5c..f01b55f5d3f0f6f591d76d4fd15e58011342ffe7 100644
--- a/VC++Files/winmysqladmin/mysql.h
+++ b/VC++Files/winmysqladmin/mysql.h
@@ -229,7 +229,9 @@ int		STDCALL mysql_real_query(MYSQL *mysql, const char *q,
 					unsigned int length);
 int		STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
 int		STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
-int		STDCALL mysql_shutdown(MYSQL *mysql);
+int		STDCALL mysql_shutdown(MYSQL *mysql,
+                                       enum enum_shutdown_level
+                                       shutdown_level);
 int		STDCALL mysql_dump_debug_info(MYSQL *mysql);
 int		STDCALL mysql_refresh(MYSQL *mysql,
 				     unsigned int refresh_options);
diff --git a/VC++Files/winmysqladmin/mysql_com.h b/VC++Files/winmysqladmin/mysql_com.h
index 2a1471f735da9b4782c72c0b0e03ef34705f8f5f..7d7d77898c321cda37a21762442b97afd1c665e1 100644
--- a/VC++Files/winmysqladmin/mysql_com.h
+++ b/VC++Files/winmysqladmin/mysql_com.h
@@ -155,6 +155,27 @@ enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
 #define FIELD_TYPE_CHAR FIELD_TYPE_TINY		/* For compability */
 #define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM	/* For compability */
 
+enum enum_shutdown_level {
+  /*
+    We want levels to be in growing order of gracefulness. So we leave room
+    for future intermediate levels. For now, escalating one level is += 10;
+    later if we insert new levels in between we will need a function
+    next_shutdown_level(level). Note that DEFAULT does not respect the
+    growing property.
+  */
+  SHUTDOWN_DEFAULT= 0, /* mapped to WAIT_ALL_BUFFERS for now */
+  /*
+    Here is the list in growing order (the next does the previous plus
+    something). WAIT_ALL_BUFFERS is what we have now. Others are "this MySQL
+    server does not support this shutdown level yet".
+  */
+  SHUTDOWN_WAIT_CRITICAL_BUFFERS= 10, /* flush MyISAM buffs (no corruption) */
+  SHUTDOWN_WAIT_ALL_BUFFERS= 20, /* flush InnoDB buffers */
+  SHUTDOWN_WAIT_STATEMENTS= 30, /* wait for existing updating stmts to finish */
+  SHUTDOWN_WAIT_TRANSACTIONS= 40, /* wait for existing trans to finish */
+  SHUTDOWN_WAIT_CONNECTIONS= 50 /* wait for existing connections to finish */
+};
+
 extern unsigned long max_allowed_packet;
 extern unsigned long net_buffer_length;
 
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index fcbcc0d71512d771b8492fe24d306b42c0cd87d3..aaed101a83ed9686b49da0a0e42126938b920208 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -509,7 +509,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
 	  !stat(pidfile, &pidfile_status))
 	last_modified= pidfile_status.st_mtime;
 
-      if (mysql_shutdown(mysql))
+      if (mysql_shutdown(mysql, SHUTDOWN_DEFAULT))
       {
 	my_printf_error(0,"shutdown failed; error: '%s'",MYF(ME_BELL),
 			mysql_error(mysql));
diff --git a/include/mysql.h b/include/mysql.h
index 39b9b7da0004e61f0dcebac4287a685b6ff6888c..931995fb1ac32ce267d1720cd5e56382bff4ce90 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -453,7 +453,9 @@ int             STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
 					const char* user,
 					const char* passwd);
 
-int		STDCALL mysql_shutdown(MYSQL *mysql);
+int		STDCALL mysql_shutdown(MYSQL *mysql,
+                                       enum enum_shutdown_level
+                                       shutdown_level);
 int		STDCALL mysql_dump_debug_info(MYSQL *mysql);
 int		STDCALL mysql_refresh(MYSQL *mysql,
 				     unsigned int refresh_options);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index d354a979cd100207500e1a6942d5ef73d162326d..90859b467c6b3e85c43c4e409da268fa27c6db0f 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -223,6 +223,27 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
 #define FIELD_TYPE_INTERVAL    MYSQL_TYPE_ENUM
 #define FIELD_TYPE_GEOMETRY    MYSQL_TYPE_GEOMETRY
 
+enum enum_shutdown_level {
+  /*
+    We want levels to be in growing order of gracefulness. So we leave room
+    for future intermediate levels. For now, escalating one level is += 10;
+    later if we insert new levels in between we will need a function
+    next_shutdown_level(level). Note that DEFAULT does not respect the
+    growing property.
+  */
+  SHUTDOWN_DEFAULT= 0, /* mapped to WAIT_ALL_BUFFERS for now */
+  /*
+    Here is the list in growing order (the next does the previous plus
+    something). WAIT_ALL_BUFFERS is what we have now. Others are "this MySQL
+    server does not support this shutdown level yet".
+  */
+  SHUTDOWN_WAIT_CRITICAL_BUFFERS= 10, /* flush MyISAM buffs (no corruption) */
+  SHUTDOWN_WAIT_ALL_BUFFERS= 20, /* flush InnoDB buffers */
+  SHUTDOWN_WAIT_STATEMENTS= 30, /* wait for existing updating stmts to finish */
+  SHUTDOWN_WAIT_TRANSACTIONS= 40, /* wait for existing trans to finish */
+  SHUTDOWN_WAIT_CONNECTIONS= 50 /* wait for existing connections to finish */
+};
+
 /* options for mysql_set_option */
 enum enum_mysql_set_option
 {
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index ebbcbc5037d4149ea6b6dd41036daedd05738689..6ad4e020464b61baa0b8cb535ec6e47ae17d375b 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1284,10 +1284,12 @@ mysql_drop_db(MYSQL *mysql, const char *db)
 
 
 int STDCALL
-mysql_shutdown(MYSQL *mysql)
+mysql_shutdown(MYSQL *mysql, enum enum_shutdown_level shutdown_level)
 {
+  uchar level[1];
+  level[0]= (uchar) shutdown_level;
   DBUG_ENTER("mysql_shutdown");
-  DBUG_RETURN(simple_command(mysql,COM_SHUTDOWN,0,0,0));
+  DBUG_RETURN(simple_command(mysql, COM_SHUTDOWN, (char *)level, 1, 0));
 }
 
 
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 10d780bca48f67c34431eadea7a9a2eb675b7d81..cfa6d6bb0796584bc75fc796411aaeb5fe17fd92 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1308,6 +1308,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
   if (command != COM_STATISTICS && command != COM_PING)
     query_id++;
   thread_running++;
+  /* TODO: set thd->lex->sql_command to SQLCOM_END here */
   VOID(pthread_mutex_unlock(&LOCK_thread_count));
 
   thd->server_status&=
@@ -1478,6 +1479,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
       thd->query_length= length;
       thd->query= packet;
       thd->query_id= query_id++;
+      /* TODO: set thd->lex->sql_command to SQLCOM_END here */
       VOID(pthread_mutex_unlock(&LOCK_thread_count));
 #ifndef EMBEDDED_LIBRARY
       mysql_parse(thd, packet, length);
@@ -1631,10 +1633,28 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
     }
 #ifndef EMBEDDED_LIBRARY
   case COM_SHUTDOWN:
+  {
     statistic_increment(com_other,&LOCK_status);
     if (check_global_access(thd,SHUTDOWN_ACL))
       break; /* purecov: inspected */
-    DBUG_PRINT("quit",("Got shutdown command"));
+    /*
+      If the client is < 4.1.3, it is going to send us no argument; then
+      packet_length is 1, packet[0] is the end 0 of the packet. Note that
+      SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in
+      packet[0].
+    */
+    enum enum_shutdown_level level=
+      (enum enum_shutdown_level) (uchar) packet[0];
+    DBUG_PRINT("quit",("Got shutdown command for level %u", level));
+    if (level == SHUTDOWN_DEFAULT)
+      level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable
+    else if (level != SHUTDOWN_WAIT_ALL_BUFFERS)
+    {
+      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level");
+      send_error(thd);
+      break;
+    }
+    DBUG_PRINT("quit",("Got shutdown command for level %u", level));
     mysql_log.write(thd,command,NullS);
     send_eof(thd);
 #ifdef __WIN__
@@ -1650,6 +1670,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
     kill_mysql();
     error=TRUE;
     break;
+  }
 #endif
   case COM_STATISTICS:
   {
diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c
index 45865e97ab73b630ffd8d4154a60e557e7a0ffbd..bb0a76d6c49e6e0e5cb8d2816bb6ea870dad9a30 100644
--- a/tools/mysqlmanager.c
+++ b/tools/mysqlmanager.c
@@ -687,7 +687,7 @@ HANDLE_DECL(handle_stop_exec)
     error="Process not running";
     goto err;
   }
-  if (mysql_shutdown(&e->mysql))
+  if (mysql_shutdown(&e->mysql, SHUTDOWN_DEFAULT))
   {
     /* e->th=0; */	/* th may be a struct */
     pthread_mutex_unlock(&e->lock);