diff -Narup ./031_mariadb-10.0.15-direct_aggregate2/sql/handler.cc ./032_mariadb-10.0.15-scale_registering_xid/sql/handler.cc
--- ./031_mariadb-10.0.15-direct_aggregate2/sql/handler.cc	2014-11-29 17:03:56.230795362 +0900
+++ ./032_mariadb-10.0.15-scale_registering_xid/sql/handler.cc	2014-11-29 17:07:12.241695603 +0900
@@ -1911,8 +1911,10 @@ bool mysql_xa_recover(THD *thd)
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     DBUG_RETURN(1);
 
-  mysql_mutex_lock(&LOCK_xid_cache);
-  while ((xs= (XID_STATE*) my_hash_element(&xid_cache, i++)))
+  for (uint j= 0; j < opt_xid_cache_split_num; ++j)
+  {
+  mysql_mutex_lock(&LOCK_xid_cache[j]);
+  while ((xs= (XID_STATE*) my_hash_element(&xid_cache[j], i++)))
   {
     if (xs->xa_state==XA_PREPARED)
     {
@@ -1924,13 +1926,14 @@ bool mysql_xa_recover(THD *thd)
                       &my_charset_bin);
       if (protocol->write())
       {
-        mysql_mutex_unlock(&LOCK_xid_cache);
+        mysql_mutex_unlock(&LOCK_xid_cache[j]);
         DBUG_RETURN(1);
       }
     }
   }
 
-  mysql_mutex_unlock(&LOCK_xid_cache);
+  mysql_mutex_unlock(&LOCK_xid_cache[j]);
+  }
   my_eof(thd);
   DBUG_RETURN(0);
 }
diff -Narup ./031_mariadb-10.0.15-direct_aggregate2/sql/mysqld.cc ./032_mariadb-10.0.15-scale_registering_xid/sql/mysqld.cc
--- ./031_mariadb-10.0.15-direct_aggregate2/sql/mysqld.cc	2014-11-29 17:05:52.727462663 +0900
+++ ./032_mariadb-10.0.15-scale_registering_xid/sql/mysqld.cc	2014-11-29 17:07:12.244396099 +0900
@@ -376,6 +376,7 @@ bool opt_bin_log, opt_bin_log_used=0, op
 my_bool opt_log, opt_slow_log, debug_assert_if_crashed_table= 0, opt_help= 0;
 static my_bool opt_abort;
 uint opt_log_result_errors;
+uint opt_xid_cache_split_num;
 ulonglong log_output_options;
 my_bool opt_userstat_running;
 my_bool opt_log_queries_not_using_indexes= 0;
diff -Narup ./031_mariadb-10.0.15-direct_aggregate2/sql/mysqld.h ./032_mariadb-10.0.15-scale_registering_xid/sql/mysqld.h
--- ./031_mariadb-10.0.15-direct_aggregate2/sql/mysqld.h	2014-11-29 17:05:52.728473191 +0900
+++ ./032_mariadb-10.0.15-scale_registering_xid/sql/mysqld.h	2014-11-29 17:07:12.246794785 +0900
@@ -82,6 +82,7 @@ extern bool opt_large_files, server_id_s
 extern bool opt_update_log, opt_bin_log, opt_error_log;
 extern my_bool opt_log, opt_slow_log, opt_bootstrap;
 extern uint opt_log_result_errors;
+extern uint opt_xid_cache_split_num;
 extern my_bool opt_backup_history_log;
 extern my_bool opt_backup_progress_log;
 extern ulonglong log_output_options;
diff -Narup ./031_mariadb-10.0.15-direct_aggregate2/sql/sql_class.cc ./032_mariadb-10.0.15-scale_registering_xid/sql/sql_class.cc
--- ./031_mariadb-10.0.15-direct_aggregate2/sql/sql_class.cc	2014-11-22 06:02:53.000000000 +0900
+++ ./032_mariadb-10.0.15-scale_registering_xid/sql/sql_class.cc	2014-11-29 17:07:12.249795358 +0900
@@ -4947,8 +4947,8 @@ void mark_transaction_to_rollback(THD *t
   Handling of XA id cacheing
 ***************************************************************************/
 
-mysql_mutex_t LOCK_xid_cache;
-HASH xid_cache;
+mysql_mutex_t *LOCK_xid_cache;
+HASH *xid_cache;
 
 extern "C" uchar *xid_get_hash_key(const uchar *, size_t *, my_bool);
 extern "C" void xid_free_hash(void *);
@@ -4993,26 +4993,50 @@ bool xid_cache_init()
   init_xid_psi_keys();
 #endif
 
-  mysql_mutex_init(key_LOCK_xid_cache, &LOCK_xid_cache, MY_MUTEX_INIT_FAST);
-  return my_hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
-                      xid_get_hash_key, xid_free_hash, 0) != 0;
+  if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
+                       &LOCK_xid_cache,
+                       sizeof(mysql_mutex_t) * opt_xid_cache_split_num,
+                       &xid_cache,
+                       sizeof(HASH) * opt_xid_cache_split_num,
+                       NullS))
+    return TRUE;
+
+  for (uint j= 0; j < opt_xid_cache_split_num; ++j)
+  {
+  mysql_mutex_init(key_LOCK_xid_cache, &LOCK_xid_cache[j], MY_MUTEX_INIT_FAST);
+  if (my_hash_init(&xid_cache[j], &my_charset_bin, 100, 0, 0,
+                   xid_get_hash_key, xid_free_hash, 0))
+    return TRUE;
+  }
+  return FALSE;
 }
 
 void xid_cache_free()
 {
-  if (my_hash_inited(&xid_cache))
+  if (LOCK_xid_cache)
   {
-    my_hash_free(&xid_cache);
-    mysql_mutex_destroy(&LOCK_xid_cache);
+    for (uint j= 0; j < opt_xid_cache_split_num; ++j)
+    {
+  if (my_hash_inited(&xid_cache[j]))
+  {
+    my_hash_free(&xid_cache[j]);
+    mysql_mutex_destroy(&LOCK_xid_cache[j]);
+  }
+    }
+    my_free(LOCK_xid_cache);
+    LOCK_xid_cache= NULL;
   }
 }
 
 XID_STATE *xid_cache_search(XID *xid)
 {
-  mysql_mutex_lock(&LOCK_xid_cache);
-  XID_STATE *res=(XID_STATE *)my_hash_search(&xid_cache, xid->key(),
-                                             xid->key_length());
-  mysql_mutex_unlock(&LOCK_xid_cache);
+  my_hash_value_type hash_value = my_calc_hash(&xid_cache[0],
+    (uchar*) xid->key(), xid->key_length());
+  uint idx= hash_value % opt_xid_cache_split_num;
+  mysql_mutex_lock(&LOCK_xid_cache[idx]);
+  XID_STATE *res=(XID_STATE *)my_hash_search_using_hash_value(&xid_cache[idx],
+    hash_value, xid->key(), xid->key_length());
+  mysql_mutex_unlock(&LOCK_xid_cache[idx]);
   return res;
 }
 
@@ -5021,8 +5045,12 @@ bool xid_cache_insert(XID *xid, enum xa_
 {
   XID_STATE *xs;
   my_bool res;
-  mysql_mutex_lock(&LOCK_xid_cache);
-  if (my_hash_search(&xid_cache, xid->key(), xid->key_length()))
+  my_hash_value_type hash_value = my_calc_hash(&xid_cache[0],
+    (uchar*) xid->key(), xid->key_length());
+  uint idx= hash_value % opt_xid_cache_split_num;
+  mysql_mutex_lock(&LOCK_xid_cache[idx]);
+  if (my_hash_search_using_hash_value(&xid_cache[idx],
+    hash_value, xid->key(), xid->key_length()))
     res=0;
   else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
     res=1;
@@ -5032,34 +5060,41 @@ bool xid_cache_insert(XID *xid, enum xa_
     xs->xid.set(xid);
     xs->in_thd=0;
     xs->rm_error=0;
-    res=my_hash_insert(&xid_cache, (uchar*)xs);
+    res=my_hash_insert(&xid_cache[idx], (uchar*)xs);
   }
-  mysql_mutex_unlock(&LOCK_xid_cache);
+  mysql_mutex_unlock(&LOCK_xid_cache[idx]);
   return res;
 }
 
 
 bool xid_cache_insert(XID_STATE *xid_state)
 {
-  mysql_mutex_lock(&LOCK_xid_cache);
-  if (my_hash_search(&xid_cache, xid_state->xid.key(),
-      xid_state->xid.key_length()))
+  my_hash_value_type hash_value = my_calc_hash(&xid_cache[0],
+    (uchar*) xid_state->xid.key(), xid_state->xid.key_length());
+  uint idx= hash_value % opt_xid_cache_split_num;
+  mysql_mutex_lock(&LOCK_xid_cache[idx]);
+  if (my_hash_search_using_hash_value(&xid_cache[idx], hash_value,
+    xid_state->xid.key(), xid_state->xid.key_length()))
   {
-    mysql_mutex_unlock(&LOCK_xid_cache);
+    mysql_mutex_unlock(&LOCK_xid_cache[idx]);
     my_error(ER_XAER_DUPID, MYF(0));
     return true;
   }
-  bool res= my_hash_insert(&xid_cache, (uchar*)xid_state);
-  mysql_mutex_unlock(&LOCK_xid_cache);
+  bool res= my_hash_insert(&xid_cache[idx], (uchar*)xid_state);
+  mysql_mutex_unlock(&LOCK_xid_cache[idx]);
   return res;
 }
 
 
 void xid_cache_delete(XID_STATE *xid_state)
 {
-  mysql_mutex_lock(&LOCK_xid_cache);
-  my_hash_delete(&xid_cache, (uchar *)xid_state);
-  mysql_mutex_unlock(&LOCK_xid_cache);
+  my_hash_value_type hash_value = my_calc_hash(&xid_cache[0],
+    (uchar*) xid_state->xid.key(), xid_state->xid.key_length());
+  uint idx= hash_value % opt_xid_cache_split_num;
+  mysql_mutex_lock(&LOCK_xid_cache[idx]);
+  my_hash_delete_with_hash_value(&xid_cache[idx], hash_value,
+    (uchar *)xid_state);
+  mysql_mutex_unlock(&LOCK_xid_cache[idx]);
 }
 
 
diff -Narup ./031_mariadb-10.0.15-direct_aggregate2/sql/sql_class.h ./032_mariadb-10.0.15-scale_registering_xid/sql/sql_class.h
--- ./031_mariadb-10.0.15-direct_aggregate2/sql/sql_class.h	2014-11-22 06:02:53.000000000 +0900
+++ ./032_mariadb-10.0.15-scale_registering_xid/sql/sql_class.h	2014-11-29 17:07:12.251794859 +0900
@@ -43,6 +43,8 @@
 #include <mysql/psi/mysql_table.h>
 #include <mysql_com_server.h>
 
+#define XID_CACHE_IS_SPLITTED
+
 extern "C"
 void set_thd_stage_info(void *thd,
                         const PSI_stage_info *new_stage,
@@ -1096,8 +1098,8 @@ typedef struct st_xid_state {
   uint rm_error;
 } XID_STATE;
 
-extern mysql_mutex_t LOCK_xid_cache;
-extern HASH xid_cache;
+extern mysql_mutex_t *LOCK_xid_cache;
+extern HASH *xid_cache;
 bool xid_cache_init(void);
 void xid_cache_free(void);
 XID_STATE *xid_cache_search(XID *xid);
diff -Narup ./031_mariadb-10.0.15-direct_aggregate2/sql/sys_vars.cc ./032_mariadb-10.0.15-scale_registering_xid/sql/sys_vars.cc
--- ./031_mariadb-10.0.15-direct_aggregate2/sql/sys_vars.cc	2014-11-29 17:05:54.730380566 +0900
+++ ./032_mariadb-10.0.15-scale_registering_xid/sql/sys_vars.cc	2014-11-29 17:07:12.255795704 +0900
@@ -4005,6 +4005,12 @@ static Sys_var_uint Sys_log_result_error
        GLOBAL_VAR(opt_log_result_errors), CMD_LINE(REQUIRED_ARG),
        VALID_RANGE(0, 4), DEFAULT(0), BLOCK_SIZE(1));
 
+static Sys_var_uint Sys_xid_cache_split_num(
+       "xid_cache_split_num",
+       "The number of splitting xid cache for scaling",
+       READ_ONLY GLOBAL_VAR(opt_xid_cache_split_num), CMD_LINE(REQUIRED_ARG),
+       VALID_RANGE(1, UINT_MAX), DEFAULT(20), BLOCK_SIZE(1));
+
 static bool check_not_empty_set(sys_var *self, THD *thd, set_var *var)
 {
   return var->save_result.ulonglong_value == 0;
