diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result
index 44b930e0705804cabb12cceb8b9d7d6e94b8fe07..a7f0594588dc51b5b55fee1f81d82f2372dba8c1 100644
--- a/mysql-test/r/events_bugs.result
+++ b/mysql-test/r/events_bugs.result
@@ -325,4 +325,57 @@ drop event e22830_3;
 drop event e22830_4;
 drop table t1;
 drop table t2;
+DROP USER mysqltest_u1@localhost;
+CREATE USER mysqltest_u1@localhost;
+GRANT EVENT ON events_test.* TO mysqltest_u1@localhost;
+CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	root@localhost
+DROP EVENT e1;
+CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	root@localhost
+ALTER DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	mysqltest_u1@localhost
+DROP EVENT e1;
+CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	root@localhost
+DROP EVENT e1;
+CREATE DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO
+SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	mysqltest_u1@localhost
+DROP EVENT e1;
+CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	mysqltest_u1@localhost
+DROP EVENT e1;
+CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	mysqltest_u1@localhost
+ALTER DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	mysqltest_u1@localhost
+DROP EVENT e1;
+CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS;
+event_name	definer
+e1	mysqltest_u1@localhost
+DROP EVENT e1;
+CREATE DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+DROP EVENT e1;
+ERROR HY000: Unknown event 'e1'
+DROP USER mysqltest_u1@localhost;
 drop database events_test;
diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test
index 26abf663ce15cd4461f87806e35ecaf7e97f60d2..0790999d7207d7a14c0cea0bbc7d8eead8d0efda 100644
--- a/mysql-test/t/events_bugs.test
+++ b/mysql-test/t/events_bugs.test
@@ -364,6 +364,63 @@ drop event e22830_4;
 drop table t1;
 drop table t2;
 
+
+#
+# BUG#16425: Events: no DEFINER clause
+#
+--error 0,ER_CANNOT_USER
+DROP USER mysqltest_u1@localhost;
+
+CREATE USER mysqltest_u1@localhost;
+GRANT EVENT ON events_test.* TO mysqltest_u1@localhost;
+
+CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+DROP EVENT e1;
+
+CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+ALTER DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+DROP EVENT e1;
+
+CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+DROP EVENT e1;
+
+CREATE DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO
+  SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+DROP EVENT e1;
+
+connect (conn1, localhost, mysqltest_u1, , events_test);
+
+CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+DROP EVENT e1;
+
+CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+ALTER DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+DROP EVENT e1;
+
+CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; 
+DROP EVENT e1;
+
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+CREATE DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
+--error ER_EVENT_DOES_NOT_EXIST
+DROP EVENT e1;
+
+disconnect conn1;
+connection default;
+
+DROP USER mysqltest_u1@localhost;
+
+
 #
 # End of tests
 #
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index b1724a28820d64623721932c63c6ccc45e89b2b7..42f8d2959b03ebd4e4e006bf564a31aa4e353969 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -611,16 +611,18 @@ Event_parse_data::check_parse_data(THD *thd)
 void
 Event_parse_data::init_definer(THD *thd)
 {
-  int definer_user_len;
-  int definer_host_len;
   DBUG_ENTER("Event_parse_data::init_definer");
 
-  DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx  "
-                     "thd->sec_ctx->priv_user: 0x%lx", (long) thd->mem_root,
-                     (long) thd->security_ctx->priv_user));
+  DBUG_ASSERT(thd->lex->definer);
+
+  const char *definer_user= thd->lex->definer->user.str;
+  const char *definer_host= thd->lex->definer->host.str;
+  int definer_user_len= thd->lex->definer->user.length;
+  int definer_host_len= thd->lex->definer->host.length;
 
-  definer_user_len= strlen(thd->security_ctx->priv_user);
-  definer_host_len= strlen(thd->security_ctx->priv_host);
+  DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx  "
+                     "definer_user: 0x%lx", (long) thd->mem_root,
+                     (long) definer_user));
 
   /* + 1 for @ */
   DBUG_PRINT("info",("init definer as whole"));
@@ -628,12 +630,11 @@ Event_parse_data::init_definer(THD *thd)
   definer.str= thd->alloc(definer.length + 1);
 
   DBUG_PRINT("info",("copy the user"));
-  memcpy(definer.str, thd->security_ctx->priv_user, definer_user_len);
+  memcpy(definer.str, definer_user, definer_user_len);
   definer.str[definer_user_len]= '@';
 
   DBUG_PRINT("info",("copy the host"));
-  memcpy(definer.str + definer_user_len + 1, thd->security_ctx->priv_host,
-         definer_host_len);
+  memcpy(definer.str + definer_user_len + 1, definer_host, definer_host_len);
   definer.str[definer.length]= '\0';
   DBUG_PRINT("info",("definer [%s] initted", definer.str));
 
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 9307836731a794f28f1bfc541b0fdb2daf59ca76..580be4d5c1f3fab421981b84ec399d9d8666e84e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2492,6 +2492,91 @@ static void reset_one_shot_variables(THD *thd)
 }
 
 
+static
+bool sp_process_definer(THD *thd)
+{
+  DBUG_ENTER("sp_process_definer");
+
+  LEX *lex= thd->lex;
+
+  /*
+    If the definer is not specified, this means that CREATE-statement missed
+    DEFINER-clause. DEFINER-clause can be missed in two cases:
+
+      - The user submitted a statement w/o the clause. This is a normal
+        case, we should assign CURRENT_USER as definer.
+
+      - Our slave received an updated from the master, that does not
+        replicate definer for stored rountines. We should also assign
+        CURRENT_USER as definer here, but also we should mark this routine
+        as NON-SUID. This is essential for the sake of backward
+        compatibility.
+
+        The problem is the slave thread is running under "special" user (@),
+        that actually does not exist. In the older versions we do not fail
+        execution of a stored routine if its definer does not exist and
+        continue the execution under the authorization of the invoker
+        (BUG#13198). And now if we try to switch to slave-current-user (@),
+        we will fail.
+
+        Actually, this leads to the inconsistent state of master and
+        slave (different definers, different SUID behaviour), but it seems,
+        this is the best we can do.
+  */
+
+  if (!lex->definer)
+  {
+    Query_arena original_arena;
+    Query_arena *ps_arena= thd->activate_stmt_arena_if_needed(&original_arena);
+
+    lex->definer= create_default_definer(thd);
+
+    if (ps_arena)
+      thd->restore_active_arena(ps_arena, &original_arena);
+
+    /* Error has been already reported. */
+    if (lex->definer == NULL)
+      DBUG_RETURN(TRUE);
+
+    if (thd->slave_thread)
+      lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
+  }
+  else
+  {
+    /*
+      If the specified definer differs from the current user, we
+      should check that the current user has SUPER privilege (in order
+      to create a stored routine under another user one must have
+      SUPER privilege).
+    */
+    if ((strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
+         my_strcasecmp(system_charset_info, lex->definer->host.str,
+                       thd->security_ctx->priv_host)) &&
+        check_global_access(thd, SUPER_ACL))
+    {
+      my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
+      DBUG_RETURN(TRUE);
+    }
+  }
+
+  /* Check that the specified definer exists. Emit a warning if not. */
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  if (!is_acl_user(lex->definer->host.str, lex->definer->user.str))
+  {
+    push_warning_printf(thd,
+                        MYSQL_ERROR::WARN_LEVEL_NOTE,
+                        ER_NO_SUCH_USER,
+                        ER(ER_NO_SUCH_USER),
+                        lex->definer->user.str,
+                        lex->definer->host.str);
+  }
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
+
+  DBUG_RETURN(FALSE);
+}
+
+
 /*
   Execute command saved in thd and lex->sql_command
 
@@ -3992,6 +4077,11 @@ mysql_execute_command(THD *thd)
                "function calls as part of this statement");
       break;
     }
+
+    res= sp_process_definer(thd);
+    if (res)
+      break;
+
     switch (lex->sql_command) {
     case SQLCOM_CREATE_EVENT:
       res= Events::get_instance()->
@@ -4487,83 +4577,8 @@ mysql_execute_command(THD *thd)
     }
 #endif
 
-    /*
-      If the definer is not specified, this means that CREATE-statement missed
-      DEFINER-clause. DEFINER-clause can be missed in two cases:
-
-        - The user submitted a statement w/o the clause. This is a normal
-          case, we should assign CURRENT_USER as definer.
-
-        - Our slave received an updated from the master, that does not
-          replicate definer for stored rountines. We should also assign
-          CURRENT_USER as definer here, but also we should mark this routine
-          as NON-SUID. This is essential for the sake of backward
-          compatibility.
-
-          The problem is the slave thread is running under "special" user (@),
-          that actually does not exist. In the older versions we do not fail
-          execution of a stored routine if its definer does not exist and
-          continue the execution under the authorization of the invoker
-          (BUG#13198). And now if we try to switch to slave-current-user (@),
-          we will fail.
-
-          Actually, this leads to the inconsistent state of master and
-          slave (different definers, different SUID behaviour), but it seems,
-          this is the best we can do.
-    */
-
-    if (!lex->definer)
-    {
-      bool res= FALSE;
-      Query_arena original_arena;
-      Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
-
-      if (!(lex->definer= create_default_definer(thd)))
-        res= TRUE;
-
-      if (ps_arena)
-        thd->restore_active_arena(ps_arena, &original_arena);
-
-      /* Error has been already reported. */
-      if (res)
-        goto create_sp_error;
-
-      if (thd->slave_thread)
-        lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
-    }
-
-    /*
-      If the specified definer differs from the current user, we should check
-      that the current user has SUPER privilege (in order to create a stored
-      routine under another user one must have SUPER privilege).
-    */
-
-    else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
-        my_strcasecmp(system_charset_info,
-                      lex->definer->host.str,
-                      thd->security_ctx->priv_host))
-    {
-      if (check_global_access(thd, SUPER_ACL))
-      {
-        my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
-        goto create_sp_error;
-      }
-    }
-
-    /* Check that the specified definer exists. Emit a warning if not. */
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-    if (!is_acl_user(lex->definer->host.str,
-                     lex->definer->user.str))
-    {
-      push_warning_printf(thd,
-                          MYSQL_ERROR::WARN_LEVEL_NOTE,
-                          ER_NO_SUCH_USER,
-                          ER(ER_NO_SUCH_USER),
-                          lex->definer->user.str,
-                          lex->definer->host.str);
-    }
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
+    if (sp_process_definer(thd))
+      goto create_sp_error;
 
     res= (result= lex->sphead->create(thd));
     switch (result) {
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index cd11bb543efab634d0a3c0958d2237a3078b3436..89f30f8b4527d068eea3d49fafdfd432be18986b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -5104,7 +5104,7 @@ alter:
 	  }
 	  view_list_opt AS view_select view_check_option
 	  {}
-	| ALTER EVENT_SYM sp_name
+	| ALTER definer EVENT_SYM sp_name
           /*
             BE CAREFUL when you add a new rule to update the block where
             YYTHD->client_capabilities is set back to original value
@@ -5120,7 +5120,7 @@ alter:
 
             if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
               YYABORT;
-            Lex->event_parse_data->identifier= $3;
+            Lex->event_parse_data->identifier= $4;
 
             /*
               We have to turn off CLIENT_MULTI_QUERIES while parsing a
@@ -5140,13 +5140,14 @@ alter:
           {
             /*
               $1 - ALTER
-              $2 - EVENT_SYM
-              $3 - sp_name
-              $4 - the block above
+              $2 - definer
+              $3 - EVENT_SYM
+              $4 - sp_name
+              $5 - the block above
             */
-            YYTHD->client_capabilities |= $<ulong_num>4;
+            YYTHD->client_capabilities |= $<ulong_num>5;
 
-            if (!($5 || $6 || $7 || $8 || $9))
+            if (!($6 || $7 || $8 || $9 || $10))
             {
 	      yyerror(ER(ER_SYNTAX_ERROR));
               YYABORT;