mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 02:51:44 +01:00
branches/zip: Merge 1493:1533 from trunk.
Make use of UT_BITS_IN_BYTES().
This commit is contained in:
parent
42e1de99df
commit
8a294fa351
19 changed files with 371 additions and 89 deletions
|
@ -190,7 +190,8 @@ dtype_validate(
|
|||
const dtype_t* type) /* in: type struct to validate */
|
||||
{
|
||||
ut_a(type);
|
||||
ut_a((type->mtype >= DATA_VARCHAR) && (type->mtype <= DATA_MYSQL));
|
||||
ut_a(type->mtype >= DATA_VARCHAR);
|
||||
ut_a(type->mtype <= DATA_MYSQL);
|
||||
|
||||
if (type->mtype == DATA_SYS) {
|
||||
ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS);
|
||||
|
|
|
@ -1599,9 +1599,6 @@ dict_index_copy_types(
|
|||
ifield = dict_index_get_nth_field(index, i);
|
||||
dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
|
||||
dict_col_copy_type(dict_field_get_col(ifield), dfield_type);
|
||||
if (UNIV_UNLIKELY(ifield->prefix_len)) {
|
||||
dfield_type->len = ifield->prefix_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3517,7 +3514,8 @@ dict_create_foreign_constraints(
|
|||
ulint err;
|
||||
mem_heap_t* heap;
|
||||
|
||||
ut_a(trx && trx->mysql_thd);
|
||||
ut_a(trx);
|
||||
ut_a(trx->mysql_thd);
|
||||
|
||||
str = dict_strip_comments(sql_string);
|
||||
heap = mem_heap_create(10000);
|
||||
|
@ -3559,7 +3557,8 @@ dict_foreign_parse_drop_constraints(
|
|||
FILE* ef = dict_foreign_err_file;
|
||||
struct charset_info_st* cs;
|
||||
|
||||
ut_a(trx && trx->mysql_thd);
|
||||
ut_a(trx);
|
||||
ut_a(trx->mysql_thd);
|
||||
|
||||
cs = innobase_get_charset(trx->mysql_thd);
|
||||
|
||||
|
@ -3883,7 +3882,7 @@ dict_index_calc_min_rec_len(
|
|||
}
|
||||
|
||||
/* round the NULL flags up to full bytes */
|
||||
sum += (nullable + 7) / 8;
|
||||
sum += UT_BITS_IN_BYTES(nullable);
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
|
|
@ -204,10 +204,9 @@ the extent are free and which contain old tuple version to clean. */
|
|||
space */
|
||||
#define XDES_FSEG 4 /* extent belongs to a segment */
|
||||
|
||||
/* File extent data structure size in bytes. The "+ 7 ) / 8" part in the
|
||||
definition rounds the number of bytes upward. */
|
||||
/* File extent data structure size in bytes. */
|
||||
#define XDES_SIZE \
|
||||
(XDES_BITMAP + (FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE + 7) / 8)
|
||||
(XDES_BITMAP + UT_BITS_IN_BYTES(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE))
|
||||
|
||||
/* Offset of the descriptor array on a descriptor page */
|
||||
#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
|
||||
|
@ -3845,7 +3844,11 @@ fsp_validate(
|
|||
n_full_frag_pages = FSP_EXTENT_SIZE
|
||||
* flst_get_len(header + FSP_FULL_FRAG, &mtr);
|
||||
|
||||
ut_a(free_limit <= size || (space != 0 && size < FSP_EXTENT_SIZE));
|
||||
if (UNIV_UNLIKELY(free_limit > size)) {
|
||||
|
||||
ut_a(space != 0);
|
||||
ut_a(size < FSP_EXTENT_SIZE);
|
||||
}
|
||||
|
||||
flst_validate(header + FSP_FREE, &mtr);
|
||||
flst_validate(header + FSP_FREE_FRAG, &mtr);
|
||||
|
|
|
@ -50,6 +50,7 @@ removing -DMYSQL_SERVER from ../Makefile.am as well. */
|
|||
#define thd_killed(thd) (thd)->killed
|
||||
#define thd_slave_thread(thd) (thd)->slave_thread
|
||||
#define thd_query(thd) (&(thd)->query)
|
||||
#define thd_non_transactional_update(thd) ((thd)->no_trans_update.all)
|
||||
#define mysql_bin_log_file_name() mysql_bin_log.get_log_fname()
|
||||
#define mysql_bin_log_file_pos() mysql_bin_log.get_log_file()->pos_in_file
|
||||
#define mysql_tmpfile() fileno(tmpfile())/* BUGGY: leaks memory, Bug #3998 */
|
||||
|
@ -449,7 +450,6 @@ server. Used in srv_conc_enter_innodb() to determine if the thread
|
|||
should be allowed to enter InnoDB - the replication thread is treated
|
||||
differently than other threads. Also used in
|
||||
srv_conc_force_exit_innodb(). */
|
||||
|
||||
extern "C"
|
||||
ibool
|
||||
thd_is_replication_slave_thread(
|
||||
|
@ -516,6 +516,22 @@ innobase_release_stat_resources(
|
|||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Returns true if the transaction this thread is processing has edited
|
||||
non-transactional tables. Used by the deadlock detector when deciding
|
||||
which transaction to rollback in case of a deadlock - we try to avoid
|
||||
rolling back transactions that have edited non-transactional tables. */
|
||||
extern "C"
|
||||
ibool
|
||||
thd_has_edited_nontrans_tables(
|
||||
/*===========================*/
|
||||
/* out: true if non-transactional tables have
|
||||
been edited */
|
||||
void* thd) /* in: thread handle (THD*) */
|
||||
{
|
||||
return((ibool) thd_non_transactional_update((THD*) thd));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Obtain the InnoDB transaction of a MySQL thread. */
|
||||
inline
|
||||
|
@ -1323,6 +1339,19 @@ trx_is_interrupted(
|
|||
return(trx && trx->mysql_thd && thd_killed((THD*) trx->mysql_thd));
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Resets some fields of a prebuilt struct. The template is used in fast
|
||||
retrieval of just those column values MySQL needs in its processing. */
|
||||
static
|
||||
void
|
||||
reset_template(
|
||||
/*===========*/
|
||||
row_prebuilt_t* prebuilt) /* in/out: prebuilt struct */
|
||||
{
|
||||
prebuilt->keep_other_fields_on_keyread = 0;
|
||||
prebuilt->read_just_key = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Call this when you have opened a new table handle in HANDLER, before you
|
||||
call index_read_idx() etc. Actually, we can let the cursor stay open even
|
||||
|
@ -1381,11 +1410,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
|
|||
/* We want always to fetch all columns in the whole row? Or do
|
||||
we???? */
|
||||
|
||||
prebuilt->read_just_key = FALSE;
|
||||
|
||||
prebuilt->used_in_HANDLER = TRUE;
|
||||
|
||||
prebuilt->keep_other_fields_on_keyread = FALSE;
|
||||
reset_template(prebuilt);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -3109,7 +3135,7 @@ static
|
|||
void
|
||||
build_template(
|
||||
/*===========*/
|
||||
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
|
||||
row_prebuilt_t* prebuilt, /* in/out: prebuilt struct */
|
||||
THD* thd, /* in: current user thread, used
|
||||
only if templ_type is
|
||||
ROW_MYSQL_REC_FIELDS */
|
||||
|
@ -5793,7 +5819,8 @@ ha_innobase::info(
|
|||
if (flag & HA_STATUS_ERRKEY) {
|
||||
dict_index_t* err_index;
|
||||
|
||||
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
ut_a(prebuilt->trx);
|
||||
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
|
||||
err_index = (dict_index_t*)trx_get_error_info(prebuilt->trx);
|
||||
|
||||
|
@ -5884,7 +5911,8 @@ ha_innobase::check(
|
|||
ulint ret;
|
||||
|
||||
DBUG_ASSERT(thd == ha_thd());
|
||||
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
ut_a(prebuilt->trx);
|
||||
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
ut_a(prebuilt->trx == thd_to_trx(thd));
|
||||
|
||||
if (prebuilt->mysql_template == NULL) {
|
||||
|
@ -6250,8 +6278,7 @@ ha_innobase::extra(
|
|||
}
|
||||
break;
|
||||
case HA_EXTRA_RESET_STATE:
|
||||
prebuilt->keep_other_fields_on_keyread = 0;
|
||||
prebuilt->read_just_key = 0;
|
||||
reset_template(prebuilt);
|
||||
break;
|
||||
case HA_EXTRA_NO_KEYREAD:
|
||||
prebuilt->read_just_key = 0;
|
||||
|
@ -6262,17 +6289,24 @@ ha_innobase::extra(
|
|||
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
|
||||
prebuilt->keep_other_fields_on_keyread = 1;
|
||||
break;
|
||||
|
||||
/* IMPORTANT: prebuilt->trx can be obsolete in
|
||||
this method, because it is not sure that MySQL
|
||||
calls external_lock before this method with the
|
||||
parameters below. We must not invoke update_thd()
|
||||
either, because the calling threads may change.
|
||||
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
|
||||
case HA_EXTRA_IGNORE_DUP_KEY:
|
||||
prebuilt->trx->duplicates |= TRX_DUP_IGNORE;
|
||||
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
|
||||
break;
|
||||
case HA_EXTRA_WRITE_CAN_REPLACE:
|
||||
prebuilt->trx->duplicates |= TRX_DUP_REPLACE;
|
||||
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
|
||||
break;
|
||||
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
||||
prebuilt->trx->duplicates &= ~TRX_DUP_REPLACE;
|
||||
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
||||
break;
|
||||
case HA_EXTRA_NO_IGNORE_DUP_KEY:
|
||||
prebuilt->trx->duplicates &=
|
||||
thd_to_trx(ha_thd())->duplicates &=
|
||||
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
|
||||
break;
|
||||
default:/* Do nothing */
|
||||
|
@ -6287,8 +6321,7 @@ int ha_innobase::reset()
|
|||
if (prebuilt->blob_heap) {
|
||||
row_mysql_prebuilt_free_blob_heap(prebuilt);
|
||||
}
|
||||
prebuilt->keep_other_fields_on_keyread = 0;
|
||||
prebuilt->read_just_key = 0;
|
||||
reset_template(prebuilt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6329,8 +6362,7 @@ ha_innobase::start_stmt(
|
|||
|
||||
prebuilt->sql_stat_start = TRUE;
|
||||
prebuilt->hint_need_to_fetch_extra_cols = 0;
|
||||
prebuilt->read_just_key = 0;
|
||||
prebuilt->keep_other_fields_on_keyread = FALSE;
|
||||
reset_template(prebuilt);
|
||||
|
||||
if (!prebuilt->mysql_has_locked) {
|
||||
/* This handle is for a temporary table created inside
|
||||
|
@ -6422,8 +6454,7 @@ ha_innobase::external_lock(
|
|||
prebuilt->sql_stat_start = TRUE;
|
||||
prebuilt->hint_need_to_fetch_extra_cols = 0;
|
||||
|
||||
prebuilt->read_just_key = 0;
|
||||
prebuilt->keep_other_fields_on_keyread = FALSE;
|
||||
reset_template(prebuilt);
|
||||
|
||||
if (lock_type == F_WRLCK) {
|
||||
|
||||
|
@ -6580,8 +6611,7 @@ ha_innobase::transactional_table_lock(
|
|||
prebuilt->sql_stat_start = TRUE;
|
||||
prebuilt->hint_need_to_fetch_extra_cols = 0;
|
||||
|
||||
prebuilt->read_just_key = 0;
|
||||
prebuilt->keep_other_fields_on_keyread = FALSE;
|
||||
reset_template(prebuilt);
|
||||
|
||||
if (lock_type == F_WRLCK) {
|
||||
prebuilt->select_lock_type = LOCK_X;
|
||||
|
|
|
@ -581,9 +581,10 @@ ibuf_bitmap_page_init(
|
|||
/* Write all zeros to the bitmap */
|
||||
|
||||
if (!zip_size) {
|
||||
byte_offset = (UNIV_PAGE_SIZE * IBUF_BITS_PER_PAGE + 7) / 8;
|
||||
byte_offset = UT_BITS_IN_BYTES(UNIV_PAGE_SIZE
|
||||
* IBUF_BITS_PER_PAGE);
|
||||
} else {
|
||||
byte_offset = (zip_size * IBUF_BITS_PER_PAGE + 7) / 8;
|
||||
byte_offset = UT_BITS_IN_BYTES(zip_size * IBUF_BITS_PER_PAGE);
|
||||
}
|
||||
|
||||
memset(page + IBUF_BITMAP, 0, byte_offset);
|
||||
|
|
|
@ -35,4 +35,17 @@ thd_is_replication_slave_thread(
|
|||
/* out: true if thd is the replication thread */
|
||||
void* thd); /* in: thread handle (THD*) */
|
||||
|
||||
/**********************************************************************
|
||||
Returns true if the transaction this thread is processing has edited
|
||||
non-transactional tables. Used by the deadlock detector when deciding
|
||||
which transaction to rollback in case of a deadlock - we try to avoid
|
||||
rolling back transactions that have edited non-transactional tables. */
|
||||
|
||||
ibool
|
||||
thd_has_edited_nontrans_tables(
|
||||
/*===========================*/
|
||||
/* out: true if non-transactional tables have
|
||||
been edited */
|
||||
void* thd); /* in: thread handle (THD*) */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -371,6 +371,18 @@ trx_is_interrupted(
|
|||
#define trx_is_interrupted(trx) FALSE
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/***********************************************************************
|
||||
Compares the "weight" (or size) of two transactions. The weight of one
|
||||
transaction is estimated as the number of altered rows + the number of
|
||||
locked rows. Transactions that have edited non-transactional tables are
|
||||
considered heavier than ones that have not. */
|
||||
|
||||
int
|
||||
trx_weight_cmp(
|
||||
/*===========*/
|
||||
/* out: <0, 0 or >0; similar to strcmp(3) */
|
||||
trx_t* a, /* in: the first transaction to be compared */
|
||||
trx_t* b); /* in: the second transaction to be compared */
|
||||
|
||||
/* Signal to a transaction */
|
||||
struct trx_sig_struct{
|
||||
|
|
|
@ -129,6 +129,11 @@ ut_2_power_up(
|
|||
/* out: first power of 2 which is >= n */
|
||||
ulint n) /* in: number != 0 */
|
||||
__attribute__((const));
|
||||
|
||||
/* Determine how many bytes (groups of 8 bits) are needed to
|
||||
store the given number of bits. */
|
||||
#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8)
|
||||
|
||||
/****************************************************************
|
||||
Sort function for ulint arrays. */
|
||||
|
||||
|
|
|
@ -3332,7 +3332,8 @@ lock_deadlock_occurs(
|
|||
ulint ret;
|
||||
ulint cost = 0;
|
||||
|
||||
ut_ad(trx && lock);
|
||||
ut_ad(trx);
|
||||
ut_ad(lock);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
retry:
|
||||
/* We check that adding this trx to the waits-for graph
|
||||
|
@ -3404,7 +3405,9 @@ lock_deadlock_recursive(
|
|||
trx_t* lock_trx;
|
||||
ulint ret;
|
||||
|
||||
ut_a(trx && start && wait_lock);
|
||||
ut_a(trx);
|
||||
ut_a(start);
|
||||
ut_a(wait_lock);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
if (trx->deadlock_mark == 1) {
|
||||
|
@ -3515,8 +3518,8 @@ lock_deadlock_recursive(
|
|||
return(LOCK_VICTIM_IS_START);
|
||||
}
|
||||
|
||||
if (ut_dulint_cmp(wait_lock->trx->undo_no,
|
||||
start->undo_no) >= 0) {
|
||||
if (trx_weight_cmp(wait_lock->trx,
|
||||
start) >= 0) {
|
||||
/* Our recursion starting point
|
||||
transaction is 'smaller', let us
|
||||
choose 'start' as the victim and roll
|
||||
|
|
|
@ -3003,10 +3003,22 @@ loop:
|
|||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
/* Check that there are no longer transactions. We need this wait
|
||||
even for the 'very fast' shutdown, because the InnoDB layer may have
|
||||
committed or prepared transactions and we don't want to lose
|
||||
them. */
|
||||
/* We need the monitor threads to stop before we proceed with a
|
||||
normal shutdown. In case of very fast shutdown, however, we can
|
||||
proceed without waiting for monitor threads. */
|
||||
|
||||
if (srv_fast_shutdown < 2
|
||||
&& (srv_error_monitor_active
|
||||
|| srv_lock_timeout_and_monitor_active)) {
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Check that there are no longer transactions. We need this wait even
|
||||
for the 'very fast' shutdown, because the InnoDB layer may have
|
||||
committed or prepared transactions and we don't want to lose them. */
|
||||
|
||||
if (trx_n_mysql_transactions > 0
|
||||
|| UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
|
||||
|
@ -3124,22 +3136,8 @@ loop:
|
|||
goto loop;
|
||||
}
|
||||
|
||||
/* The lock timeout thread should now have exited */
|
||||
|
||||
if (srv_lock_timeout_and_monitor_active) {
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* We now let also the InnoDB error monitor thread to exit */
|
||||
|
||||
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
|
||||
|
||||
if (srv_error_monitor_active) {
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Make some checks that the server really is quiet */
|
||||
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
|
||||
ut_a(buf_all_freed());
|
||||
|
|
51
mysql-test/innodb_trx_weight.inc
Normal file
51
mysql-test/innodb_trx_weight.inc
Normal file
|
@ -0,0 +1,51 @@
|
|||
-- connect (con1,localhost,,,)
|
||||
-- connect (con2,localhost,,,)
|
||||
|
||||
-- connection con1
|
||||
SET autocommit=0;
|
||||
SELECT * FROM t1 FOR UPDATE;
|
||||
-- if ($con1_extra_sql_present) {
|
||||
-- eval $con1_extra_sql
|
||||
-- }
|
||||
|
||||
-- connection con2
|
||||
SET autocommit=0;
|
||||
SELECT * FROM t2 FOR UPDATE;
|
||||
-- if ($con2_extra_sql_present) {
|
||||
-- eval $con2_extra_sql
|
||||
-- }
|
||||
|
||||
-- if ($con1_should_be_rolledback) {
|
||||
-- connection con1
|
||||
-- send
|
||||
INSERT INTO t2 VALUES (0);
|
||||
|
||||
-- connection con2
|
||||
INSERT INTO t1 VALUES (0);
|
||||
ROLLBACK;
|
||||
|
||||
-- connection con1
|
||||
-- error ER_LOCK_DEADLOCK
|
||||
-- reap
|
||||
-- }
|
||||
# else
|
||||
-- if (!$con1_should_be_rolledback) {
|
||||
-- connection con2
|
||||
-- send
|
||||
INSERT INTO t1 VALUES (0);
|
||||
|
||||
-- connection con1
|
||||
INSERT INTO t2 VALUES (0);
|
||||
ROLLBACK;
|
||||
|
||||
-- connection con2
|
||||
-- error ER_LOCK_DEADLOCK
|
||||
-- reap
|
||||
-- }
|
||||
|
||||
-- connection default
|
||||
|
||||
DELETE FROM t5_nontrans;
|
||||
|
||||
-- disconnect con1
|
||||
-- disconnect con2
|
1
mysql-test/innodb_trx_weight.result
Normal file
1
mysql-test/innodb_trx_weight.result
Normal file
|
@ -0,0 +1 @@
|
|||
SET storage_engine=InnoDB;
|
102
mysql-test/innodb_trx_weight.test
Normal file
102
mysql-test/innodb_trx_weight.test
Normal file
|
@ -0,0 +1,102 @@
|
|||
#
|
||||
# Ensure that the number of locks (SELECT FOR UPDATE for example) is
|
||||
# added to the number of altered rows when choosing the smallest
|
||||
# transaction to kill as a victim when a deadlock is detected.
|
||||
# Also transactions what had edited non-transactional tables should
|
||||
# be heavier than ones that had not.
|
||||
#
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
SET storage_engine=InnoDB;
|
||||
|
||||
# we do not really care about what gets output-ed, we are only
|
||||
# interested in getting the deadlock resolved according to our
|
||||
# expectations
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
-- disable_warnings
|
||||
DROP TABLE IF EXISTS t1, t2, t3, t4, t5_nontrans;
|
||||
-- enable_warnings
|
||||
|
||||
# we will create a simple deadlock with t1, t2 and two connections
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 (a INT);
|
||||
|
||||
# auxiliary table with a bulk of rows which will be locked by a
|
||||
# transaction to increase its weight
|
||||
CREATE TABLE t3 (a INT);
|
||||
|
||||
# auxiliary empty table which will be inserted by a
|
||||
# transaction to increase its weight
|
||||
CREATE TABLE t4 (a INT);
|
||||
|
||||
# auxiliary non-transactional table which will be edited by a
|
||||
# transaction to tremendously increase its weight
|
||||
CREATE TABLE t5_nontrans (a INT) ENGINE=MyISAM;
|
||||
|
||||
INSERT INTO t1 VALUES (1);
|
||||
INSERT INTO t2 VALUES (1);
|
||||
# insert a lot of rows in t3
|
||||
INSERT INTO t3 VALUES (1);
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
INSERT INTO t3 SELECT * FROM t3;
|
||||
|
||||
# test locking weight
|
||||
|
||||
-- let $con1_extra_sql =
|
||||
-- let $con1_extra_sql_present = 0
|
||||
-- let $con2_extra_sql = SELECT * FROM t3 FOR UPDATE
|
||||
-- let $con2_extra_sql_present = 1
|
||||
-- let $con1_should_be_rolledback = 1
|
||||
-- source include/innodb_trx_weight.inc
|
||||
|
||||
-- let $con1_extra_sql = INSERT INTO t4 VALUES (1), (1)
|
||||
-- let $con1_extra_sql_present = 1
|
||||
-- let $con2_extra_sql = SELECT * FROM t3 FOR UPDATE
|
||||
-- let $con2_extra_sql_present = 1
|
||||
-- let $con1_should_be_rolledback = 1
|
||||
-- source include/innodb_trx_weight.inc
|
||||
|
||||
-- let $con1_extra_sql = INSERT INTO t4 VALUES (1), (1), (1), (1), (1), (1)
|
||||
-- let $con1_extra_sql_present = 1
|
||||
-- let $con2_extra_sql = SELECT * FROM t3 FOR UPDATE
|
||||
-- let $con2_extra_sql_present = 1
|
||||
-- let $con1_should_be_rolledback = 0
|
||||
-- source include/innodb_trx_weight.inc
|
||||
|
||||
# test weight when non-transactional tables are edited
|
||||
|
||||
-- let $con1_extra_sql = INSERT INTO t4 VALUES (1), (1), (1)
|
||||
-- let $con1_extra_sql_present = 1
|
||||
-- let $con2_extra_sql =
|
||||
-- let $con2_extra_sql_present = 0
|
||||
-- let $con1_should_be_rolledback = 0
|
||||
-- source include/innodb_trx_weight.inc
|
||||
|
||||
-- let $con1_extra_sql = INSERT INTO t4 VALUES (1), (1), (1)
|
||||
-- let $con1_extra_sql_present = 1
|
||||
-- let $con2_extra_sql = INSERT INTO t5_nontrans VALUES (1)
|
||||
-- let $con2_extra_sql_present = 1
|
||||
-- let $con1_should_be_rolledback = 1
|
||||
-- source include/innodb_trx_weight.inc
|
||||
|
||||
-- let $con1_extra_sql = INSERT INTO t4 VALUES (1), (1), (1)
|
||||
-- let $con1_extra_sql = $con1_extra_sql; INSERT INTO t5_nontrans VALUES (1)
|
||||
-- let $con1_extra_sql_present = 1
|
||||
-- let $con2_extra_sql = INSERT INTO t5_nontrans VALUES (1)
|
||||
-- let $con2_extra_sql_present = 1
|
||||
-- let $con1_should_be_rolledback = 0
|
||||
-- source include/innodb_trx_weight.inc
|
||||
|
||||
DROP TABLE t1, t2, t3, t4, t5_nontrans;
|
|
@ -164,7 +164,7 @@ rec_get_n_extern_new(
|
|||
}
|
||||
|
||||
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
|
||||
lens = nulls - (index->n_nullable + 7) / 8;
|
||||
lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
|
||||
null_mask = 1;
|
||||
n_extern = 0;
|
||||
i = 0;
|
||||
|
@ -231,7 +231,8 @@ rec_init_offsets_comp_ordinary(
|
|||
ulint offs = 0;
|
||||
ulint any_ext = 0;
|
||||
const byte* nulls = rec - (extra + 1);
|
||||
const byte* lens = nulls - (index->n_nullable + 7) / 8;;
|
||||
const byte* lens = nulls
|
||||
- UT_BITS_IN_BYTES(index->n_nullable);
|
||||
dict_field_t* field;
|
||||
ulint null_mask = 1;
|
||||
|
||||
|
@ -358,7 +359,7 @@ rec_init_offsets(
|
|||
}
|
||||
|
||||
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
|
||||
lens = nulls - (index->n_nullable + 7) / 8;
|
||||
lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
|
||||
offs = 0;
|
||||
null_mask = 1;
|
||||
|
||||
|
@ -571,7 +572,7 @@ rec_get_offsets_reverse(
|
|||
rec_offs_set_n_fields(offsets, n);
|
||||
|
||||
nulls = extra;
|
||||
lens = nulls + (index->n_nullable + 7) / 8;
|
||||
lens = nulls + UT_BITS_IN_BYTES(index->n_nullable);
|
||||
i = offs = 0;
|
||||
null_mask = 1;
|
||||
any_ext = 0;
|
||||
|
@ -720,7 +721,7 @@ rec_get_converted_size_comp(
|
|||
ulint n_ext) /* in: number of elements in ext */
|
||||
{
|
||||
ulint size = REC_N_NEW_EXTRA_BYTES
|
||||
+ (index->n_nullable + 7) / 8;
|
||||
+ UT_BITS_IN_BYTES(index->n_nullable);
|
||||
ulint i;
|
||||
ulint j;
|
||||
ulint n_fields;
|
||||
|
@ -765,9 +766,9 @@ rec_get_converted_size_comp(
|
|||
}
|
||||
|
||||
ut_ad(len <= col->len || col->mtype == DATA_BLOB);
|
||||
ut_ad(!field->fixed_len || len == field->fixed_len);
|
||||
|
||||
if (field->fixed_len) {
|
||||
ut_ad(len == field->fixed_len);
|
||||
} else if (UNIV_UNLIKELY(j < n_ext) && i == ext[j]) {
|
||||
j++;
|
||||
size += 2;
|
||||
|
@ -1028,7 +1029,7 @@ rec_convert_dtuple_to_rec_comp(
|
|||
|
||||
/* Calculate the offset of the origin in the physical record.
|
||||
We must loop over all fields to do this. */
|
||||
rec += (index->n_nullable + 7) / 8;
|
||||
rec += UT_BITS_IN_BYTES(index->n_nullable);
|
||||
|
||||
for (i = j = 0; i < n_fields; i++) {
|
||||
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
|
||||
|
@ -1072,7 +1073,7 @@ init:
|
|||
ut_ad(j == n_ext);
|
||||
end = rec;
|
||||
nulls = rec - (extra + 1);
|
||||
lens = nulls - (index->n_nullable + 7) / 8;
|
||||
lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
|
||||
/* clear the SQL-null flags */
|
||||
memset(lens + 1, 0, nulls - lens);
|
||||
|
||||
|
@ -1359,7 +1360,7 @@ rec_copy_prefix_to_buf(
|
|||
}
|
||||
|
||||
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
|
||||
lens = nulls - (index->n_nullable + 7) / 8;
|
||||
lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
|
||||
UNIV_PREFETCH_R(lens);
|
||||
prefix_len = 0;
|
||||
null_mask = 1;
|
||||
|
|
|
@ -442,7 +442,11 @@ row_ins_cascade_calc_update_vec(
|
|||
ulint i;
|
||||
ulint j;
|
||||
|
||||
ut_a(node && foreign && cascade && table && index);
|
||||
ut_a(node);
|
||||
ut_a(foreign);
|
||||
ut_a(cascade);
|
||||
ut_a(table);
|
||||
ut_a(index);
|
||||
|
||||
/* Calculate the appropriate update vector which will set the fields
|
||||
in the child index record to the same value (possibly padded with
|
||||
|
@ -786,7 +790,10 @@ row_ins_foreign_check_on_constraint(
|
|||
trx_t* trx;
|
||||
mem_heap_t* tmp_heap = NULL;
|
||||
|
||||
ut_a(thr && foreign && pcur && mtr);
|
||||
ut_a(thr);
|
||||
ut_a(foreign);
|
||||
ut_a(pcur);
|
||||
ut_a(mtr);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
|
@ -1306,7 +1313,8 @@ run_again:
|
|||
goto exit_func;
|
||||
}
|
||||
|
||||
ut_a(check_table && check_index);
|
||||
ut_a(check_table);
|
||||
ut_a(check_index);
|
||||
|
||||
if (check_table != table) {
|
||||
/* We already have a LOCK_IX on table, but not necessarily
|
||||
|
|
|
@ -79,7 +79,6 @@ row_build_index_entry(
|
|||
dfield_t* dfield;
|
||||
const dfield_t* dfield2;
|
||||
ulint i;
|
||||
ulint storage_len;
|
||||
|
||||
ut_ad(row && index && heap);
|
||||
ut_ad(dtuple_check_typed(row));
|
||||
|
@ -127,19 +126,12 @@ row_build_index_entry(
|
|||
}
|
||||
|
||||
/* If a column prefix index, take only the prefix */
|
||||
if (ind_field->prefix_len) {
|
||||
if (dfield_get_len(dfield) != UNIV_SQL_NULL) {
|
||||
|
||||
storage_len = dtype_get_at_most_n_mbchars(
|
||||
col->prtype,
|
||||
col->mbminlen, col->mbmaxlen,
|
||||
ind_field->prefix_len,
|
||||
dfield->len, dfield->data);
|
||||
|
||||
dfield_set_len(dfield, storage_len);
|
||||
}
|
||||
|
||||
dfield_get_type(dfield)->len = ind_field->prefix_len;
|
||||
if (ind_field->prefix_len > 0
|
||||
&& dfield->len != UNIV_SQL_NULL) {
|
||||
dfield->len = dtype_get_at_most_n_mbchars(
|
||||
col->prtype, col->mbminlen, col->mbmaxlen,
|
||||
ind_field->prefix_len,
|
||||
dfield->len, dfield->data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,7 +474,9 @@ row_build_row_ref_in_tuple(
|
|||
ulint* offsets = offsets_;
|
||||
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
|
||||
|
||||
ut_a(ref && index && rec);
|
||||
ut_a(ref);
|
||||
ut_a(index);
|
||||
ut_a(rec);
|
||||
|
||||
if (UNIV_UNLIKELY(!index->table)) {
|
||||
fputs("InnoDB: table ", stderr);
|
||||
|
|
|
@ -1854,6 +1854,7 @@ srv_lock_timeout_and_monitor_thread(
|
|||
double time_elapsed;
|
||||
time_t current_time;
|
||||
time_t last_table_monitor_time;
|
||||
time_t last_tablespace_monitor_time;
|
||||
time_t last_monitor_time;
|
||||
ibool some_waits;
|
||||
double wait_time;
|
||||
|
@ -1866,6 +1867,7 @@ srv_lock_timeout_and_monitor_thread(
|
|||
UT_NOT_USED(arg);
|
||||
srv_last_monitor_time = time(NULL);
|
||||
last_table_monitor_time = time(NULL);
|
||||
last_tablespace_monitor_time = time(NULL);
|
||||
last_monitor_time = time(NULL);
|
||||
loop:
|
||||
srv_lock_timeout_and_monitor_active = TRUE;
|
||||
|
@ -1902,9 +1904,9 @@ loop:
|
|||
}
|
||||
|
||||
if (srv_print_innodb_tablespace_monitor
|
||||
&& difftime(current_time, last_table_monitor_time) > 60) {
|
||||
|
||||
last_table_monitor_time = time(NULL);
|
||||
&& difftime(current_time,
|
||||
last_tablespace_monitor_time) > 60) {
|
||||
last_tablespace_monitor_time = time(NULL);
|
||||
|
||||
fputs("========================"
|
||||
"========================\n",
|
||||
|
@ -2098,7 +2100,7 @@ loop:
|
|||
|
||||
os_thread_sleep(2000000);
|
||||
|
||||
if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
|
||||
if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
|
|
@ -670,7 +670,9 @@ sync_array_detect_deadlock(
|
|||
ibool ret;
|
||||
rw_lock_debug_t*debug;
|
||||
|
||||
ut_a(arr && start && cell);
|
||||
ut_a(arr);
|
||||
ut_a(start);
|
||||
ut_a(cell);
|
||||
ut_ad(cell->wait_object);
|
||||
ut_ad(os_thread_get_curr_id() == start->thread);
|
||||
ut_ad(depth < 100);
|
||||
|
|
|
@ -25,6 +25,7 @@ Created 3/26/1996 Heikki Tuuri
|
|||
#include "btr0sea.h"
|
||||
#include "os0proc.h"
|
||||
#include "trx0xa.h"
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
/* Copy of the prototype for innobase_mysql_print_thd: this
|
||||
copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */
|
||||
|
@ -1789,6 +1790,61 @@ trx_print(
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Compares the "weight" (or size) of two transactions. The weight of one
|
||||
transaction is estimated as the number of altered rows + the number of
|
||||
locked rows. Transactions that have edited non-transactional tables are
|
||||
considered heavier than ones that have not. */
|
||||
|
||||
int
|
||||
trx_weight_cmp(
|
||||
/*===========*/
|
||||
/* out: <0, 0 or >0; similar to strcmp(3) */
|
||||
trx_t* a, /* in: the first transaction to be compared */
|
||||
trx_t* b) /* in: the second transaction to be compared */
|
||||
{
|
||||
ibool a_notrans_edit;
|
||||
ibool b_notrans_edit;
|
||||
|
||||
/* If mysql_thd is NULL for a transaction we assume that it has
|
||||
not edited non-transactional tables. */
|
||||
|
||||
a_notrans_edit = a->mysql_thd != NULL
|
||||
&& thd_has_edited_nontrans_tables(a->mysql_thd);
|
||||
|
||||
b_notrans_edit = b->mysql_thd != NULL
|
||||
&& thd_has_edited_nontrans_tables(b->mysql_thd);
|
||||
|
||||
if (a_notrans_edit && !b_notrans_edit) {
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (!a_notrans_edit && b_notrans_edit) {
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Either both had edited non-transactional tables or both had
|
||||
not, we fall back to comparing the number of altered/locked
|
||||
rows. */
|
||||
|
||||
#if 0
|
||||
fprintf(stderr,
|
||||
"%s TRX_WEIGHT(a): %lld+%lu, TRX_WEIGHT(b): %lld+%lu\n",
|
||||
__func__,
|
||||
ut_conv_dulint_to_longlong(a->undo_no),
|
||||
UT_LIST_GET_LEN(a->trx_locks),
|
||||
ut_conv_dulint_to_longlong(b->undo_no),
|
||||
UT_LIST_GET_LEN(b->trx_locks));
|
||||
#endif
|
||||
|
||||
#define TRX_WEIGHT(t) \
|
||||
ut_dulint_add((t)->undo_no, UT_LIST_GET_LEN((t)->trx_locks))
|
||||
|
||||
return(ut_dulint_cmp(TRX_WEIGHT(a), TRX_WEIGHT(b)));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Prepares a transaction. */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue