mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge remote-tracking branch 'origin/10.0' into 10.0
This commit is contained in:
commit
6c09a72af5
14 changed files with 245 additions and 23 deletions
|
@ -235,7 +235,7 @@ typedef struct _global { /* Global structure */
|
|||
void *Xchk; /* indexes in create/alter */
|
||||
short Alchecked; /* Checked for ALTER */
|
||||
short Mrr; /* True when doing mrr */
|
||||
short Trace;
|
||||
int N; /* Utility */
|
||||
int jump_level;
|
||||
jmp_buf jumper[MAX_JUMP + 2];
|
||||
} GLOBAL;
|
||||
|
|
|
@ -165,9 +165,10 @@
|
|||
/***********************************************************************/
|
||||
/* Initialize the ha_connect static members. */
|
||||
/***********************************************************************/
|
||||
#define SZCONV 8192
|
||||
#define SZWORK 67108864 // Default work area size 64M
|
||||
#define SZWMIN 4194304 // Minimum work area size 4M
|
||||
#define SZCONV 8192
|
||||
#define SZWORK 67108864 // Default work area size 64M
|
||||
#define SZWMIN 4194304 // Minimum work area size 4M
|
||||
#define JSONMAX 10 // JSON Default max grp size
|
||||
|
||||
extern "C" {
|
||||
char version[]= "Version 1.03.0006 February 06, 2015";
|
||||
|
@ -217,6 +218,7 @@ bool ExactInfo(void);
|
|||
USETEMP UseTemp(void);
|
||||
int GetConvSize(void);
|
||||
TYPCONV GetTypeConv(void);
|
||||
uint GetJsonGrpSize(void);
|
||||
uint GetWorkSize(void);
|
||||
void SetWorkSize(uint);
|
||||
extern "C" const char *msglang(void);
|
||||
|
@ -323,6 +325,12 @@ static MYSQL_THDVAR_ENUM(
|
|||
0, // def (no)
|
||||
&xconv_typelib); // typelib
|
||||
|
||||
// Estimate max number of rows for JSON aggregate functions
|
||||
static MYSQL_THDVAR_UINT(json_grp_size,
|
||||
PLUGIN_VAR_RQCMDARG, // opt
|
||||
"max number of rows for JSON aggregate functions.",
|
||||
NULL, NULL, JSONMAX, 1, INT_MAX, 1);
|
||||
|
||||
#if defined(XMSG) || defined(NEWMSG)
|
||||
const char *language_names[]=
|
||||
{
|
||||
|
@ -353,6 +361,7 @@ bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
|
|||
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
|
||||
int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
|
||||
TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
|
||||
uint GetJsonGrpSize(void) {return THDVAR(current_thd, json_grp_size);}
|
||||
uint GetWorkSize(void) {return THDVAR(current_thd, work_size);}
|
||||
void SetWorkSize(uint n)
|
||||
{
|
||||
|
@ -6516,6 +6525,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
|
|||
#if defined(XMSG)
|
||||
MYSQL_SYSVAR(errmsg_dir_path),
|
||||
#endif // XMSG
|
||||
MYSQL_SYSVAR(json_grp_size),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
|
|||
goto err;
|
||||
} else if (!(jsp = ParseObject(g, ++i, src)))
|
||||
goto err;
|
||||
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
|
@ -90,6 +91,11 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
|
|||
|
||||
sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
|
||||
goto err;
|
||||
case '"':
|
||||
if (!(jsp = ParseValue(g, i, src)))
|
||||
goto err;
|
||||
|
||||
break;
|
||||
case '(':
|
||||
b = true;
|
||||
break;
|
||||
|
|
|
@ -8,12 +8,18 @@
|
|||
/* Include relevant sections of the MariaDB header file. */
|
||||
/***********************************************************************/
|
||||
#include <my_global.h>
|
||||
#include <mysqld.h>
|
||||
#include <mysql.h>
|
||||
#include <sql_error.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "json.h"
|
||||
|
||||
#define MEMFIX 512
|
||||
|
||||
uint GetJsonGrpSize(void);
|
||||
|
||||
extern "C" {
|
||||
DllExport my_bool Json_Value_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||
DllExport char *Json_Value(UDF_INIT*, UDF_ARGS*, char*,
|
||||
|
@ -23,6 +29,10 @@ DllExport my_bool Json_Array_init(UDF_INIT*, UDF_ARGS*, char*);
|
|||
DllExport char *Json_Array(UDF_INIT*, UDF_ARGS*, char*,
|
||||
unsigned long*, char *, char *);
|
||||
DllExport void Json_Array_deinit(UDF_INIT*);
|
||||
DllExport my_bool Json_Array_Add_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||
DllExport char *Json_Array_Add(UDF_INIT*, UDF_ARGS*, char*,
|
||||
unsigned long*, char *, char *);
|
||||
DllExport void Json_Array_Add_deinit(UDF_INIT*);
|
||||
DllExport my_bool Json_Object_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||
DllExport char *Json_Object(UDF_INIT*, UDF_ARGS*, char*,
|
||||
unsigned long*, char *, char *);
|
||||
|
@ -44,8 +54,8 @@ DllExport void Json_Object_Grp_deinit(UDF_INIT*);
|
|||
/***********************************************************************/
|
||||
/* Allocate and initialise the memory area. */
|
||||
/***********************************************************************/
|
||||
static my_bool JsonInit(UDF_INIT *initid, char *message, unsigned long reslen,
|
||||
unsigned long memlen)
|
||||
static my_bool JsonInit(UDF_INIT *initid, char *message,
|
||||
unsigned long reslen, unsigned long memlen)
|
||||
{
|
||||
PGLOBAL g = PlugInit(NULL, memlen);
|
||||
|
||||
|
@ -119,7 +129,7 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
|
|||
} // endfor i
|
||||
|
||||
// Calculate the amount of memory needed
|
||||
memlen = 1024 + sizeof(JOUTSTR) + reslen;
|
||||
memlen = MEMFIX + sizeof(JOUTSTR) + reslen;
|
||||
|
||||
for (i = 0; i < args->arg_count; i++) {
|
||||
memlen += (args->lengths[i] + sizeof(JVALUE));
|
||||
|
@ -219,14 +229,23 @@ static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
|
|||
static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, int i)
|
||||
{
|
||||
char *sap = args->args[i];
|
||||
PJSON jsp;
|
||||
PJVAL jvp = new(g) JVALUE;
|
||||
|
||||
if (sap) switch (args->arg_type[i]) {
|
||||
case STRING_RESULT:
|
||||
if (args->lengths[i]) {
|
||||
if (IsJson(args, i))
|
||||
jvp->SetValue(ParseJson(g, sap, args->lengths[i], 0));
|
||||
else
|
||||
if (IsJson(args, i)) {
|
||||
if (!(jsp = ParseJson(g, sap, args->lengths[i], 0)))
|
||||
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
|
||||
g->Message);
|
||||
|
||||
if (jsp && jsp->GetType() == TYPE_JVAL)
|
||||
jvp = (PJVAL)jsp;
|
||||
else
|
||||
jvp->SetValue(jsp);
|
||||
|
||||
} else
|
||||
jvp->SetString(g, MakePSZ(g, args, i));
|
||||
|
||||
} // endif str
|
||||
|
@ -328,6 +347,59 @@ void Json_Array_deinit(UDF_INIT* initid)
|
|||
PlugExit((PGLOBAL)initid->ptr);
|
||||
} // end of Json_Array_deinit
|
||||
|
||||
/***********************************************************************/
|
||||
/* Add values to a Json array. */
|
||||
/***********************************************************************/
|
||||
my_bool Json_Array_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||
{
|
||||
unsigned long reslen, memlen;
|
||||
|
||||
if (args->arg_count < 2) {
|
||||
strcpy(message, "Json_Value_Add must have at least 2 arguments");
|
||||
return true;
|
||||
} else if (!IsJson(args, 0)) {
|
||||
strcpy(message, "Json_Value_Add first argument must be a json array");
|
||||
return true;
|
||||
} else
|
||||
CalcLen(args, false, reslen, memlen);
|
||||
|
||||
return JsonInit(initid, message, reslen, memlen);
|
||||
} // end of Json_Array_Add_init
|
||||
|
||||
char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||
unsigned long *res_length, char *is_null, char *error)
|
||||
{
|
||||
char *str;
|
||||
PJVAL jvp;
|
||||
PJAR arp;
|
||||
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||
|
||||
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||
jvp = MakeValue(g, args, 0);
|
||||
|
||||
if (jvp->GetValType() != TYPE_JAR) {
|
||||
arp = new(g) JARRAY;
|
||||
arp->AddValue(g, jvp);
|
||||
} else
|
||||
arp = jvp->GetArray();
|
||||
|
||||
for (uint i = 1; i < args->arg_count; i++)
|
||||
arp->AddValue(g, MakeValue(g, args, i));
|
||||
|
||||
arp->InitArray(g);
|
||||
|
||||
if (!(str = Serialize(g, arp, NULL, 0)))
|
||||
str = strcpy(result, g->Message);
|
||||
|
||||
*res_length = strlen(str);
|
||||
return str;
|
||||
} // end of Json_Array_Add
|
||||
|
||||
void Json_Array_Add_deinit(UDF_INIT* initid)
|
||||
{
|
||||
PlugExit((PGLOBAL)initid->ptr);
|
||||
} // end of Json_Array_Add_deinit
|
||||
|
||||
/***********************************************************************/
|
||||
/* Make a Json Oject containing all the parameters. */
|
||||
/***********************************************************************/
|
||||
|
@ -370,7 +442,7 @@ void Json_Object_deinit(UDF_INIT* initid)
|
|||
/***********************************************************************/
|
||||
my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||
{
|
||||
unsigned long reslen, memlen, n = 10;
|
||||
unsigned long reslen, memlen, n = GetJsonGrpSize();
|
||||
|
||||
if (args->arg_count != 1) {
|
||||
strcpy(message, "Json_Array_Grp can only accept 1 argument");
|
||||
|
@ -379,7 +451,7 @@ my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
|||
CalcLen(args, false, reslen, memlen);
|
||||
|
||||
reslen *= n;
|
||||
memlen *= n;
|
||||
memlen += ((memlen - MEMFIX) * (n - 1));
|
||||
|
||||
if (JsonInit(initid, message, reslen, memlen))
|
||||
return true;
|
||||
|
@ -388,6 +460,7 @@ my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
|||
|
||||
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||
g->Activityp = (PACTIVITY)new(g) JARRAY;
|
||||
g->N = (int)n;
|
||||
return false;
|
||||
} // end of Json_Array_Grp_init
|
||||
|
||||
|
@ -397,7 +470,9 @@ void Json_Array_Grp_add(UDF_INIT *initid, UDF_ARGS *args,
|
|||
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||
PJAR arp = (PJAR)g->Activityp;
|
||||
|
||||
arp->AddValue(g, MakeValue(g, args, 0));
|
||||
if (g->N-- > 0)
|
||||
arp->AddValue(g, MakeValue(g, args, 0));
|
||||
|
||||
} // end of Json_Array_Grp_add
|
||||
|
||||
char *Json_Array_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||
|
@ -407,6 +482,10 @@ char *Json_Array_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
|||
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||
PJAR arp = (PJAR)g->Activityp;
|
||||
|
||||
if (g->N < 0)
|
||||
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
|
||||
"Result truncated to json_grp_size values");
|
||||
|
||||
arp->InitArray(g);
|
||||
|
||||
if (!(str = Serialize(g, arp, NULL, 0)))
|
||||
|
@ -422,6 +501,7 @@ void Json_Array_Grp_clear(UDF_INIT *initid, char *is_null, char *error)
|
|||
|
||||
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||
g->Activityp = (PACTIVITY)new(g) JARRAY;
|
||||
g->N = GetJsonGrpSize();
|
||||
} // end of Json_Array_Grp_clear
|
||||
|
||||
void Json_Array_Grp_deinit(UDF_INIT* initid)
|
||||
|
@ -434,7 +514,7 @@ void Json_Array_Grp_deinit(UDF_INIT* initid)
|
|||
/***********************************************************************/
|
||||
my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||
{
|
||||
unsigned long reslen, memlen, n = 10;
|
||||
unsigned long reslen, memlen, n = GetJsonGrpSize();
|
||||
|
||||
if (args->arg_count != 2) {
|
||||
strcpy(message, "Json_Array_Grp can only accept 2 argument");
|
||||
|
@ -443,7 +523,7 @@ my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
|||
CalcLen(args, true, reslen, memlen);
|
||||
|
||||
reslen *= n;
|
||||
memlen *= n;
|
||||
memlen += ((memlen - MEMFIX) * (n - 1));
|
||||
|
||||
if (JsonInit(initid, message, reslen, memlen))
|
||||
return true;
|
||||
|
@ -452,6 +532,7 @@ my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
|||
|
||||
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||
g->Activityp = (PACTIVITY)new(g) JOBJECT;
|
||||
g->N = (int)n;
|
||||
return false;
|
||||
} // end of Json_Object_Grp_init
|
||||
|
||||
|
@ -461,7 +542,9 @@ void Json_Object_Grp_add(UDF_INIT *initid, UDF_ARGS *args,
|
|||
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||
PJOB objp = (PJOB)g->Activityp;
|
||||
|
||||
objp->SetValue(g, MakeValue(g, args, 0), MakePSZ(g, args, 1));
|
||||
if (g->N-- > 0)
|
||||
objp->SetValue(g, MakeValue(g, args, 0), MakePSZ(g, args, 1));
|
||||
|
||||
} // end of Json_Object_Grp_add
|
||||
|
||||
char *Json_Object_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||
|
@ -471,6 +554,10 @@ char *Json_Object_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
|||
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||
PJOB objp = (PJOB)g->Activityp;
|
||||
|
||||
if (g->N < 0)
|
||||
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
|
||||
"Result truncated to json_grp_size values");
|
||||
|
||||
if (!(str = Serialize(g, objp, NULL, 0)))
|
||||
str = strcpy(result, g->Message);
|
||||
|
||||
|
@ -484,6 +571,7 @@ void Json_Object_Grp_clear(UDF_INIT *initid, char *is_null, char *error)
|
|||
|
||||
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||
g->Activityp = (PACTIVITY)new(g) JOBJECT;
|
||||
g->N = GetJsonGrpSize();
|
||||
} // end of Json_Object_Grp_clear
|
||||
|
||||
void Json_Object_Grp_deinit(UDF_INIT* initid)
|
||||
|
|
|
@ -311,7 +311,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
|
|||
else
|
||||
crp->Kdata = NULL;
|
||||
|
||||
if (g->Trace)
|
||||
if (trace)
|
||||
htrc("Column(%d) %s type=%d len=%d value=%p\n",
|
||||
crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
|
||||
|
||||
|
|
|
@ -144,12 +144,12 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
|
|||
return NULL;
|
||||
} else {
|
||||
g->Sarea_Size = worksize;
|
||||
g->Trace = 0;
|
||||
g->Createas = 0;
|
||||
g->Alchecked = 0;
|
||||
g->Mrr = 0;
|
||||
g->Activityp = g->ActivityStart = NULL;
|
||||
g->Xchk = NULL;
|
||||
g->N = 0;
|
||||
strcpy(g->Message, "");
|
||||
|
||||
/*******************************************************************/
|
||||
|
|
|
@ -931,7 +931,11 @@ void JSONCOL::WriteColumn(PGLOBAL g)
|
|||
case TYPE_STRING:
|
||||
if (Nodes[Nod-1].Op == OP_XX) {
|
||||
s = Value->GetCharValue();
|
||||
jsp = ParseJson(g, s, (int)strlen(s), 0);
|
||||
|
||||
if (!(jsp = ParseJson(g, s, (int)strlen(s), 0))) {
|
||||
strcpy(g->Message, s);
|
||||
longjmp(g->jumper[g->jump_level], 666);
|
||||
} // endif jsp
|
||||
|
||||
if (arp) {
|
||||
if (Nod > 1 && Nodes[Nod-2].Rank)
|
||||
|
|
|
@ -787,7 +787,7 @@ bool TDBODBC::OpenDB(PGLOBAL g)
|
|||
{
|
||||
bool rc = true;
|
||||
|
||||
if (g->Trace)
|
||||
if (trace)
|
||||
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
||||
this, Tdb_No, Use, Mode);
|
||||
|
||||
|
@ -1185,12 +1185,12 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
|
|||
|
||||
} // endif Buf_Type
|
||||
|
||||
if (g->Trace) {
|
||||
if (trace) {
|
||||
char buf[64];
|
||||
|
||||
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
|
||||
Name, tdbp->Rows, Bufp, Buf_Type, Value->GetCharString(buf));
|
||||
} // endif Trace
|
||||
} // endif trace
|
||||
|
||||
put:
|
||||
if (tdbp->Memory != 2)
|
||||
|
@ -1424,7 +1424,7 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
|
|||
{
|
||||
bool rc = false;
|
||||
|
||||
if (g->Trace)
|
||||
if (trace)
|
||||
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
||||
this, Tdb_No, Use, Mode);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -72,6 +73,12 @@ struct lock_t {
|
|||
hash_node_t hash; /*!< hash chain node for a record
|
||||
lock */
|
||||
dict_index_t* index; /*!< index for a record lock */
|
||||
|
||||
/* Statistics for how long lock has been held and time
|
||||
how long this lock had to be waited before it was granted */
|
||||
time_t requested_time; /*!< Lock request time */
|
||||
ulint wait_time; /*!< Time waited this lock or 0 */
|
||||
|
||||
union {
|
||||
lock_table_t tab_lock;/*!< table lock */
|
||||
lock_rec_t rec_lock;/*!< record lock */
|
||||
|
|
|
@ -1009,6 +1009,19 @@ struct trx_t{
|
|||
/*------------------------------*/
|
||||
char detailed_error[256]; /*!< detailed error message for last
|
||||
error, or empty. */
|
||||
/* Lock wait statistics */
|
||||
ulint n_rec_lock_waits;
|
||||
/*!< Number of record lock waits,
|
||||
might not be exactly correct. */
|
||||
ulint n_table_lock_waits;
|
||||
/*!< Number of table lock waits,
|
||||
might not be exactly correct. */
|
||||
ulint total_rec_lock_wait_time;
|
||||
/*!< Total rec lock wait time up
|
||||
to this moment. */
|
||||
ulint total_table_lock_wait_time;
|
||||
/*!< Total table lock wait time
|
||||
up to this moment. */
|
||||
};
|
||||
|
||||
/* Transaction isolation levels (trx->isolation_level) */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2014, 2015, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1886,6 +1887,9 @@ lock_rec_create(
|
|||
/* Set the bit corresponding to rec */
|
||||
lock_rec_set_nth_bit(lock, heap_no);
|
||||
|
||||
lock->requested_time = ut_time();
|
||||
lock->wait_time = 0;
|
||||
|
||||
index->table->n_rec_locks++;
|
||||
|
||||
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
|
||||
|
@ -2034,6 +2038,8 @@ lock_rec_enqueue_waiting(
|
|||
|
||||
MONITOR_INC(MONITOR_LOCKREC_WAIT);
|
||||
|
||||
trx->n_rec_lock_waits++;
|
||||
|
||||
return(DB_LOCK_WAIT);
|
||||
}
|
||||
|
||||
|
@ -2454,6 +2460,17 @@ lock_grant(
|
|||
}
|
||||
}
|
||||
|
||||
/* Cumulate total lock wait time for statistics */
|
||||
if (lock_get_type_low(lock) & LOCK_TABLE) {
|
||||
lock->trx->total_table_lock_wait_time +=
|
||||
(ulint)difftime(ut_time(), lock->trx->lock.wait_started);
|
||||
} else {
|
||||
lock->trx->total_rec_lock_wait_time +=
|
||||
(ulint)difftime(ut_time(), lock->trx->lock.wait_started);
|
||||
}
|
||||
|
||||
lock->wait_time = (ulint)difftime(ut_time(), lock->requested_time);
|
||||
|
||||
trx_mutex_exit(lock->trx);
|
||||
}
|
||||
|
||||
|
@ -4215,6 +4232,8 @@ lock_table_create(
|
|||
|
||||
lock->type_mode = type_mode | LOCK_TABLE;
|
||||
lock->trx = trx;
|
||||
lock->requested_time = ut_time();
|
||||
lock->wait_time = 0;
|
||||
|
||||
lock->un_member.tab_lock.table = table;
|
||||
|
||||
|
@ -4458,6 +4477,7 @@ lock_table_enqueue_waiting(
|
|||
|
||||
trx->lock.wait_started = ut_time();
|
||||
trx->lock.was_chosen_as_deadlock_victim = FALSE;
|
||||
trx->n_table_lock_waits++;
|
||||
|
||||
ut_a(que_thr_stop(thr));
|
||||
|
||||
|
@ -5133,6 +5153,10 @@ lock_table_print(
|
|||
fputs(" waiting", file);
|
||||
}
|
||||
|
||||
fprintf(file, " lock hold time %lu wait time before grant %lu ",
|
||||
(ulint)difftime(ut_time(), lock->requested_time),
|
||||
lock->wait_time);
|
||||
|
||||
putc('\n', file);
|
||||
}
|
||||
|
||||
|
@ -5200,6 +5224,10 @@ lock_rec_print(
|
|||
|
||||
mtr_start(&mtr);
|
||||
|
||||
fprintf(file, " lock hold time %lu wait time before grant %lu ",
|
||||
(ulint)difftime(ut_time(), lock->requested_time),
|
||||
lock->wait_time);
|
||||
|
||||
putc('\n', file);
|
||||
|
||||
block = buf_page_try_get(space, page_no, &mtr);
|
||||
|
@ -5458,6 +5486,14 @@ loop:
|
|||
trx->read_view->up_limit_id);
|
||||
}
|
||||
|
||||
/* Total trx lock waits and times */
|
||||
fprintf(file, "Trx #rec lock waits %lu #table lock waits %lu\n",
|
||||
trx->n_rec_lock_waits, trx->n_table_lock_waits);
|
||||
fprintf(file, "Trx total rec lock wait time %lu SEC\n",
|
||||
trx->total_rec_lock_wait_time);
|
||||
fprintf(file, "Trx total table lock wait time %lu SEC\n",
|
||||
trx->total_table_lock_wait_time);
|
||||
|
||||
if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
|
||||
|
||||
fprintf(file,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -72,6 +73,12 @@ struct lock_t {
|
|||
hash_node_t hash; /*!< hash chain node for a record
|
||||
lock */
|
||||
dict_index_t* index; /*!< index for a record lock */
|
||||
|
||||
/* Statistics for how long lock has been held and time
|
||||
how long this lock had to be waited before it was granted */
|
||||
time_t requested_time; /*!< Lock request time */
|
||||
ulint wait_time; /*!< Time waited this lock or 0 */
|
||||
|
||||
union {
|
||||
lock_table_t tab_lock;/*!< table lock */
|
||||
lock_rec_t rec_lock;/*!< record lock */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1058,6 +1059,20 @@ struct trx_t{
|
|||
#define DPAH_SIZE 8192
|
||||
byte* distinct_page_access_hash;
|
||||
ibool take_stats;
|
||||
|
||||
/* Lock wait statistics */
|
||||
ulint n_rec_lock_waits;
|
||||
/*!< Number of record lock waits,
|
||||
might not be exactly correct. */
|
||||
ulint n_table_lock_waits;
|
||||
/*!< Number of table lock waits,
|
||||
might not be exactly correct. */
|
||||
ulint total_rec_lock_wait_time;
|
||||
/*!< Total rec lock wait time up
|
||||
to this moment. */
|
||||
ulint total_table_lock_wait_time;
|
||||
/*!< Total table lock wait time
|
||||
up to this moment. */
|
||||
};
|
||||
|
||||
/* Transaction isolation levels (trx->isolation_level) */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2014, 2015, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1897,6 +1898,9 @@ lock_rec_create(
|
|||
/* Set the bit corresponding to rec */
|
||||
lock_rec_set_nth_bit(lock, heap_no);
|
||||
|
||||
lock->requested_time = ut_time();
|
||||
lock->wait_time = 0;
|
||||
|
||||
index->table->n_rec_locks++;
|
||||
|
||||
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
|
||||
|
@ -2055,6 +2059,8 @@ lock_rec_enqueue_waiting(
|
|||
|
||||
MONITOR_INC(MONITOR_LOCKREC_WAIT);
|
||||
|
||||
trx->n_rec_lock_waits++;
|
||||
|
||||
return(DB_LOCK_WAIT);
|
||||
}
|
||||
|
||||
|
@ -2474,6 +2480,17 @@ lock_grant(
|
|||
}
|
||||
}
|
||||
|
||||
/* Cumulate total lock wait time for statistics */
|
||||
if (lock_get_type_low(lock) & LOCK_TABLE) {
|
||||
lock->trx->total_table_lock_wait_time +=
|
||||
(ulint)difftime(ut_time(), lock->trx->lock.wait_started);
|
||||
} else {
|
||||
lock->trx->total_rec_lock_wait_time +=
|
||||
(ulint)difftime(ut_time(), lock->trx->lock.wait_started);
|
||||
}
|
||||
|
||||
lock->wait_time = (ulint)difftime(ut_time(), lock->requested_time);
|
||||
|
||||
trx_mutex_exit(lock->trx);
|
||||
}
|
||||
|
||||
|
@ -4239,6 +4256,8 @@ lock_table_create(
|
|||
|
||||
lock->type_mode = type_mode | LOCK_TABLE;
|
||||
lock->trx = trx;
|
||||
lock->requested_time = ut_time();
|
||||
lock->wait_time = 0;
|
||||
|
||||
lock->un_member.tab_lock.table = table;
|
||||
|
||||
|
@ -4484,6 +4503,7 @@ lock_table_enqueue_waiting(
|
|||
|
||||
trx->lock.wait_started = ut_time();
|
||||
trx->lock.was_chosen_as_deadlock_victim = FALSE;
|
||||
trx->n_table_lock_waits++;
|
||||
|
||||
if (UNIV_UNLIKELY(trx->take_stats)) {
|
||||
ut_usectime(&sec, &ms);
|
||||
|
@ -5168,6 +5188,10 @@ lock_table_print(
|
|||
fputs(" waiting", file);
|
||||
}
|
||||
|
||||
fprintf(file, " lock hold time %lu wait time before grant %lu ",
|
||||
(ulint)difftime(ut_time(), lock->requested_time),
|
||||
lock->wait_time);
|
||||
|
||||
putc('\n', file);
|
||||
}
|
||||
|
||||
|
@ -5235,6 +5259,10 @@ lock_rec_print(
|
|||
|
||||
mtr_start(&mtr);
|
||||
|
||||
fprintf(file, " lock hold time %lu wait time before grant %lu ",
|
||||
(ulint)difftime(ut_time(), lock->requested_time),
|
||||
lock->wait_time);
|
||||
|
||||
putc('\n', file);
|
||||
|
||||
if ( srv_show_verbose_locks ) {
|
||||
|
@ -5495,6 +5523,14 @@ loop:
|
|||
trx->read_view->up_limit_id);
|
||||
}
|
||||
|
||||
/* Total trx lock waits and times */
|
||||
fprintf(file, "Trx #rec lock waits %lu #table lock waits %lu\n",
|
||||
trx->n_rec_lock_waits, trx->n_table_lock_waits);
|
||||
fprintf(file, "Trx total rec lock wait time %lu SEC\n",
|
||||
trx->total_rec_lock_wait_time);
|
||||
fprintf(file, "Trx total table lock wait time %lu SEC\n",
|
||||
trx->total_table_lock_wait_time);
|
||||
|
||||
if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
|
||||
|
||||
fprintf(file,
|
||||
|
|
Loading…
Reference in a new issue