Browse Source

MDEV-31772 Innodb_rows_* missing

In commit 0dab74ff3f (MDEV-28539)
a number of counters were removed. Due to popular demand, we are
reinstating some of the counters, in a way that incurs less
performance penalty.

We reinstate the following global status variables:
innodb_rows_deleted
innodb_rows_inserted
innodb_rows_updated

The counter innodb_rows_read will not be reinstated, because doing so
would cause a large performance regression.
These counters will also cover whatever was previously covered
by innodb_system_rows_* counters, which we will not be
reinstating.

We also add the INFORMATION_SCHEMA.INNODB_METRICS counters
dml_reads, dml_inserts, dml_delete, dml_updates, but not their
dml_system_* counterparts.

trx_t::commit_in_memory(): Update the global trx_sys.row_ops[]
from the local row_ops[] at the end of each transaction.

Reviewed by: Nikita Malyavin
10.11-MDEV-31772
Marko Mäkelä 2 years ago
parent
commit
eee6f9a023
  1. 9
      mysql-test/suite/innodb/r/innodb.result
  2. 3
      mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result
  3. 3
      mysql-test/suite/innodb/r/innodb_status_variables.result
  4. 91
      mysql-test/suite/innodb/r/monitor.result
  5. 6
      mysql-test/suite/innodb/t/innodb.test
  6. 87
      mysql-test/suite/innodb/t/monitor.test
  7. 26
      mysql-test/suite/rpl/include/rpl_innodb_rows_counters.inc
  8. 102
      mysql-test/suite/rpl/r/rpl_innodb_bug68220.result
  9. 42
      mysql-test/suite/rpl/t/rpl_innodb_bug68220.test
  10. 135
      storage/innobase/handler/ha_innodb.cc
  11. 6
      storage/innobase/include/srv0mon.h
  12. 2
      storage/innobase/include/trx0sys.h
  13. 5
      storage/innobase/include/trx0trx.h
  14. 22
      storage/innobase/row/row0sel.cc
  15. 35
      storage/innobase/srv/srv0mon.cc
  16. 8
      storage/innobase/trx/trx0trx.cc
  17. 3
      storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result

9
mysql-test/suite/innodb/r/innodb.result

@ -1694,6 +1694,15 @@ OK
SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size';
variable_value
16384
SELECT variable_value - @innodb_rows_deleted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_deleted';
variable_value - @innodb_rows_deleted_orig
56
SELECT variable_value - @innodb_rows_inserted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted';
variable_value - @innodb_rows_inserted_orig
964
SELECT variable_value - @innodb_rows_updated_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated';
variable_value - @innodb_rows_updated_orig
865
SELECT variable_value - @innodb_row_lock_waits_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_row_lock_waits';
variable_value - @innodb_row_lock_waits_orig
0

3
mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result

@ -224,6 +224,9 @@ innodb_dict_lru_count_idle server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NU
innodb_dblwr_writes server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of doublewrite operations that have been performed (innodb_dblwr_writes)
innodb_dblwr_pages_written server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of pages that have been written for doublewrite operations (innodb_dblwr_pages_written)
innodb_page_size server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value InnoDB page size in bytes (innodb_page_size)
dml_inserts dml 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of rows inserted
dml_deletes dml 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of rows deleted
dml_updates dml 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of rows updated
ddl_background_drop_indexes ddl 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of indexes waiting to be dropped after failed index creation
ddl_online_create_index ddl 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of indexes being created online
ddl_pending_alter_table ddl 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of ALTER TABLE, CREATE INDEX, DROP INDEX in progress

3
mysql-test/suite/innodb/r/innodb_status_variables.result

@ -75,6 +75,9 @@ INNODB_ROW_LOCK_TIME
INNODB_ROW_LOCK_TIME_AVG
INNODB_ROW_LOCK_TIME_MAX
INNODB_ROW_LOCK_WAITS
INNODB_ROWS_DELETED
INNODB_ROWS_INSERTED
INNODB_ROWS_UPDATED
INNODB_NUM_OPEN_FILES
INNODB_TRUNCATED_STATUS_WRITES
INNODB_AVAILABLE_UNDO_LOGS

91
mysql-test/suite/innodb/r/monitor.result

@ -189,6 +189,9 @@ innodb_dict_lru_count_idle disabled
innodb_dblwr_writes enabled
innodb_dblwr_pages_written enabled
innodb_page_size enabled
dml_inserts enabled
dml_deletes enabled
dml_updates enabled
ddl_background_drop_indexes disabled
ddl_online_create_index disabled
ddl_pending_alter_table disabled
@ -383,6 +386,94 @@ where name='trx_rollbacks';
name max_count min_count count max_count_reset min_count_reset count_reset status
trx_rollbacks 1 NULL 1 1 NULL 1 enabled
set global innodb_monitor_disable = module_trx;
set global innodb_monitor_enable = module_dml;
insert into monitor_test values(9);
update monitor_test set col = 10 where col = 9;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts 1 NULL 1 1 NULL 1 enabled
dml_deletes 0 NULL 0 0 NULL 0 enabled
dml_updates 2 NULL 2 2 NULL 2 enabled
delete from monitor_test;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts 1 NULL 1 1 NULL 1 enabled
dml_deletes 2 NULL 2 2 NULL 2 enabled
dml_updates 2 NULL 2 2 NULL 2 enabled
set global innodb_monitor_reset = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts 1 NULL 1 0 NULL 0 enabled
dml_deletes 2 NULL 2 0 NULL 0 enabled
dml_updates 2 NULL 2 0 NULL 0 enabled
insert into monitor_test values(9);
insert into monitor_test values(1);
delete from monitor_test;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts 3 NULL 3 2 NULL 2 enabled
dml_deletes 4 NULL 4 2 NULL 2 enabled
dml_updates 2 NULL 2 0 NULL 0 enabled
set global innodb_monitor_reset_all = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts 3 NULL 3 2 NULL 2 enabled
dml_deletes 4 NULL 4 2 NULL 2 enabled
dml_updates 2 NULL 2 0 NULL 0 enabled
set global innodb_monitor_disable = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts 3 NULL 3 2 NULL 2 disabled
dml_deletes 4 NULL 4 2 NULL 2 disabled
dml_updates 2 NULL 2 0 NULL 0 disabled
set global innodb_monitor_reset_all = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts NULL NULL 0 NULL NULL 0 disabled
dml_deletes NULL NULL 0 NULL NULL 0 disabled
dml_updates NULL NULL 0 NULL NULL 0 disabled
set global innodb_monitor_enable = dml_inserts;
insert into monitor_test values(9);
insert into monitor_test values(1);
delete from monitor_test;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
name max_count min_count count max_count_reset min_count_reset count_reset status
dml_inserts 2 NULL 2 2 NULL 2 enabled
dml_deletes NULL NULL 0 NULL NULL 0 disabled
dml_updates NULL NULL 0 NULL NULL 0 disabled
set global innodb_monitor_disable = module_dml;
drop table monitor_test;
set global innodb_monitor_enable = file_num_open_files;
select name, max_count, min_count, count,

6
mysql-test/suite/innodb/t/innodb.test

@ -25,6 +25,9 @@ call mtr.add_suppression("\\[ERROR\\] InnoDB: in ALTER TABLE `test`.`t1`");
call mtr.add_suppression("\\[ERROR\\] InnoDB: in RENAME TABLE table `test`.`t1`");
--disable_warnings
SET @innodb_rows_deleted_orig = (SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_deleted');
SET @innodb_rows_inserted_orig = (SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted');
SET @innodb_rows_updated_orig = (SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated');
SET @innodb_row_lock_waits_orig = (SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_row_lock_waits');
SET @innodb_row_lock_current_waits_orig = (SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_row_lock_current_waits');
SET @innodb_row_lock_time_orig = (SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_row_lock_time');
@ -1316,6 +1319,9 @@ drop table t1;
# uses previous ones(pages_created, rows_deleted, ...).
SELECT IF(variable_value BETWEEN 488 AND 512, 'OK', variable_value) FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_buffer_pool_pages_total';
SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size';
SELECT variable_value - @innodb_rows_deleted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_deleted';
SELECT variable_value - @innodb_rows_inserted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted';
SELECT variable_value - @innodb_rows_updated_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated';
# Test for row locks InnoDB status variables.
SELECT variable_value - @innodb_row_lock_waits_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_row_lock_waits';

87
mysql-test/suite/innodb/t/monitor.test

@ -256,6 +256,93 @@ where name='trx_rollbacks';
set global innodb_monitor_disable = module_trx;
# Test DML Module
set global innodb_monitor_enable = module_dml;
insert into monitor_test values(9);
update monitor_test set col = 10 where col = 9;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
delete from monitor_test;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
# test reset counter while the counter is on
set global innodb_monitor_reset = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
# insert/delete some rows after the reset
insert into monitor_test values(9);
insert into monitor_test values(1);
delete from monitor_test;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
# We do not allow reset_all while the counter is on, nothing
# should be reset here
set global innodb_monitor_reset_all = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
# Turn off the counter
set global innodb_monitor_disable = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
# Reset all counter values
set global innodb_monitor_reset_all = module_dml;
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
# Open individual counter "dml_inserts"
set global innodb_monitor_enable = dml_inserts;
insert into monitor_test values(9);
insert into monitor_test values(1);
delete from monitor_test;
# Only counter "dml_inserts" should be updated
select name, max_count, min_count, count,
max_count_reset, min_count_reset, count_reset,
if(enabled,'enabled','disabled') status
from information_schema.innodb_metrics
where name like "dml%";
set global innodb_monitor_disable = module_dml;
drop table monitor_test;
set global innodb_monitor_enable = file_num_open_files;

26
mysql-test/suite/rpl/include/rpl_innodb_rows_counters.inc

@ -0,0 +1,26 @@
#########################################
# Author: Benjamin Renard benj@fb.com
# Date: 11/15/2013
# Purpose: Showing the difference between current innodb rows stats and the ones recorded at the beginning of the test
# Requirements: Having @[master|slave]_[system_]rows_[read|inserted|deleted|updated] counters already created
#########################################
--connection master
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @master_rows_updated;
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @master_rows_deleted;
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @master_rows_inserted;
--sync_slave_with_master
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @slave_rows_updated;
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @slave_rows_deleted;
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @slave_rows_inserted;
--connection master

102
mysql-test/suite/rpl/r/rpl_innodb_bug68220.result

@ -0,0 +1,102 @@
include/master-slave.inc
[connection master]
connection master;
select variable_value into @master_rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select variable_value into @master_rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select variable_value into @master_rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
connection slave;
select variable_value into @slave_rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select variable_value into @slave_rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select variable_value into @slave_rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
connection master;
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE t1 (i int NOT NULL PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection master;
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @master_rows_updated;
@rows_updated - @master_rows_updated
0
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @master_rows_deleted;
@rows_deleted - @master_rows_deleted
0
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @master_rows_inserted;
@rows_inserted - @master_rows_inserted
1
connection slave;
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @slave_rows_updated;
@rows_updated - @slave_rows_updated
0
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @slave_rows_deleted;
@rows_deleted - @slave_rows_deleted
0
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @slave_rows_inserted;
@rows_inserted - @slave_rows_inserted
1
connection master;
UPDATE t1 SET i=2 WHERE i=1;
connection slave;
connection master;
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @master_rows_updated;
@rows_updated - @master_rows_updated
1
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @master_rows_deleted;
@rows_deleted - @master_rows_deleted
0
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @master_rows_inserted;
@rows_inserted - @master_rows_inserted
1
connection slave;
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @slave_rows_updated;
@rows_updated - @slave_rows_updated
1
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @slave_rows_deleted;
@rows_deleted - @slave_rows_deleted
0
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @slave_rows_inserted;
@rows_inserted - @slave_rows_inserted
1
connection master;
DELETE FROM t1 WHERE i=2;
connection master;
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @master_rows_updated;
@rows_updated - @master_rows_updated
1
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @master_rows_deleted;
@rows_deleted - @master_rows_deleted
1
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @master_rows_inserted;
@rows_inserted - @master_rows_inserted
1
connection slave;
select variable_value into @rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select @rows_updated - @slave_rows_updated;
@rows_updated - @slave_rows_updated
1
select variable_value into @rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select @rows_deleted - @slave_rows_deleted;
@rows_deleted - @slave_rows_deleted
1
select variable_value into @rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
select @rows_inserted - @slave_rows_inserted;
@rows_inserted - @slave_rows_inserted
1
connection master;
DROP DATABASE testdb;
connection slave;
include/rpl_end.inc

42
mysql-test/suite/rpl/t/rpl_innodb_bug68220.test

@ -0,0 +1,42 @@
--source include/have_innodb.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
#
# Bug#68220: innodb_rows_updated is misleading on slave when *info_repository=TABLE
#
# created all the base variables at the beginning at the test
--connection master
select variable_value into @master_rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select variable_value into @master_rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select variable_value into @master_rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
--connection slave
select variable_value into @slave_rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated';
select variable_value into @slave_rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted';
select variable_value into @slave_rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted';
--connection master
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE t1 (i int NOT NULL PRIMARY KEY) ENGINE=InnoDB;
# insert a row and show counters on master and slave
INSERT INTO t1 VALUES (1);
--source suite/rpl/include/rpl_innodb_rows_counters.inc
# update the row and show counters on master and slave
UPDATE t1 SET i=2 WHERE i=1;
--sync_slave_with_master
--source suite/rpl/include/rpl_innodb_rows_counters.inc
# delete the row and show counters on master and slave
DELETE FROM t1 WHERE i=2;
--source suite/rpl/include/rpl_innodb_rows_counters.inc
# clean the test
DROP DATABASE testdb;
--sync_slave_with_master
--source include/rpl_end.inc

135
storage/innobase/handler/ha_innodb.cc

@ -1008,6 +1008,9 @@ static SHOW_VAR innodb_status_variables[]= {
{"row_lock_time_avg", &export_vars.innodb_row_lock_time_avg, SHOW_ULONGLONG},
{"row_lock_time_max", &export_vars.innodb_row_lock_time_max, SHOW_ULONGLONG},
{"row_lock_waits", &export_vars.innodb_row_lock_waits, SHOW_SIZE_T},
{"rows_deleted", &trx_sys.row_ops[trx_t::ROW_DELETE], SHOW_SIZE_T},
{"rows_inserted", &trx_sys.row_ops[trx_t::ROW_INSERT], SHOW_SIZE_T},
{"rows_updated", &trx_sys.row_ops[trx_t::ROW_UPDATE], SHOW_SIZE_T},
{"num_open_files", &fil_system.n_open, SHOW_SIZE_T},
{"truncated_status_writes", &truncated_status_writes, SHOW_SIZE_T},
{"available_undo_logs", &srv_available_undo_logs, SHOW_ULONG},
@ -7787,7 +7790,6 @@ ha_innobase::write_row(
#ifdef WITH_WSREP
bool wsrep_auto_inc_inserted= false;
#endif
int error_result = 0;
bool auto_inc_used = false;
mariadb_set_stats set_stats_temporary(handler_stats);
@ -7818,9 +7820,9 @@ ha_innobase::write_row(
&& table->next_number_field->val_int() == 0;
#endif
if ((error_result = update_auto_increment())) {
if (int error_result = update_auto_increment()) {
/* MySQL errors are passed straight back. */
goto func_exit;
DBUG_RETURN(error_result);
}
auto_inc_used = true;
@ -7841,7 +7843,7 @@ ha_innobase::write_row(
ROW_INS_VERSIONED : ROW_INS_NORMAL;
/* Execute insert graph that will result in actual insert. */
error = row_insert_for_mysql((byte*) record, m_prebuilt, vers_set_fields);
error = row_insert_for_mysql(record, m_prebuilt, vers_set_fields);
DEBUG_SYNC(m_user_thd, "ib_after_row_insert");
@ -7898,11 +7900,8 @@ ha_innobase::write_row(
WSREP_DEBUG(
"retrying insert: %s",
wsrep_thd_query(m_user_thd));
error= DB_SUCCESS;
wsrep_thd_self_abort(m_user_thd);
/* jump straight to func exit over
* later wsrep hooks */
goto func_exit;
DBUG_RETURN(0);
}
break;
#endif /* WITH_WSREP */
@ -7957,18 +7956,28 @@ set_max_autoinc:
}
/* Cleanup and exit. */
if (error == DB_TABLESPACE_DELETED) {
switch (UNIV_EXPECT(error, DB_SUCCESS)) {
case DB_SUCCESS:
break;
case DB_TABLESPACE_DELETED:
ib_senderrf(
trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLESPACE_DISCARDED,
table->s->table_name.str);
DBUG_RETURN(HA_ERR_TABLESPACE_MISSING);
case DB_FTS_INVALID_DOCID:
my_error(HA_FTS_INVALID_DOCID, MYF(0));
DBUG_RETURN(HA_FTS_INVALID_DOCID);
default:
DBUG_RETURN(convert_error_code_to_mysql(error, m_prebuilt
->table->flags,
m_user_thd));
}
error_result = convert_error_code_to_mysql(
error, m_prebuilt->table->flags, m_user_thd);
trx->row_ops[trx_t::ROW_INSERT]++;
#ifdef WITH_WSREP
if (!error_result && trx->is_wsrep()
if (trx->is_wsrep()
&& !trx->is_bulk_insert()
&& wsrep_thd_is_local(m_user_thd)
&& !wsrep_thd_ignore_table(m_user_thd)
@ -7980,18 +7989,12 @@ set_max_autoinc:
record,
NULL)) {
DBUG_PRINT("wsrep", ("row key failed"));
error_result = HA_ERR_INTERNAL_ERROR;
goto func_exit;
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
}
#endif /* WITH_WSREP */
if (error_result == HA_FTS_INVALID_DOCID) {
my_error(HA_FTS_INVALID_DOCID, MYF(0));
}
func_exit:
DBUG_RETURN(error_result);
DBUG_RETURN(0);
}
/** Fill the update vector's "old_vrow" field for those non-updated,
@ -8558,9 +8561,6 @@ ha_innobase::update_row(
const uchar* old_row,
const uchar* new_row)
{
int err;
dberr_t error;
trx_t* trx = thd_to_trx(m_user_thd);
mariadb_set_stats set_stats_temporary(handler_stats);
@ -8600,12 +8600,12 @@ ha_innobase::update_row(
/* Build an update vector from the modified fields in the rows
(uses m_upd_buf of the handle) */
error = calc_row_difference(
dberr_t error = calc_row_difference(
uvect, old_row, new_row, table, m_upd_buf, m_upd_buf_size,
m_prebuilt, autoinc);
if (error != DB_SUCCESS) {
goto func_exit;
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
goto err_exit;
}
if (!uvect->n_fields) {
@ -8614,29 +8614,42 @@ ha_innobase::update_row(
should not increase the count of updated rows.
This is fix for http://bugs.mysql.com/29157 */
DBUG_RETURN(HA_ERR_RECORD_IS_THE_SAME);
} else {
if (m_prebuilt->upd_node->is_delete) {
trx->fts_next_doc_id = 0;
}
}
/* row_start was updated by vers_make_update()
in calc_row_difference() */
error = row_update_for_mysql(m_prebuilt);
if (m_prebuilt->upd_node->is_delete) {
trx->fts_next_doc_id = 0;
}
/* row_start was updated by vers_make_update()
in calc_row_difference() */
error = row_update_for_mysql(m_prebuilt);
if (error == DB_SUCCESS && m_prebuilt->versioned_write
/* Multiple UPDATE of same rows in single transaction create
historical rows only once. */
&& trx->id != table->vers_start_id()) {
/* UPDATE is not used by ALTER TABLE. Just precaution
as we don't need history generation for ALTER TABLE. */
ut_ad(thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE);
error = row_insert_for_mysql((byte*) old_row,
m_prebuilt,
ROW_INS_HISTORICAL);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
err_exit:
if (error == DB_FTS_INVALID_DOCID) {
my_error(HA_FTS_INVALID_DOCID, MYF(0));
DBUG_RETURN(HA_FTS_INVALID_DOCID);
}
DBUG_RETURN(convert_error_code_to_mysql(error,
m_prebuilt->table
->flags, m_user_thd));
}
if (error == DB_SUCCESS && autoinc) {
if (UNIV_UNLIKELY(m_prebuilt->versioned_write)
/* Multiple UPDATE of same rows in single transaction create
historical rows only once. */
&& trx->id != table->vers_start_id()) {
/* UPDATE is not used by ALTER TABLE. Just precaution
as we don't need history generation for ALTER TABLE. */
ut_ad(thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE);
error = row_insert_for_mysql(old_row, m_prebuilt,
ROW_INS_HISTORICAL);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
goto err_exit;
}
}
if (autoinc) {
/* A value for an AUTO_INCREMENT column
was specified in the UPDATE statement. */
@ -8671,20 +8684,15 @@ ha_innobase::update_row(
m_prebuilt->table),
autoinc);
}
}
}
func_exit:
if (error == DB_FTS_INVALID_DOCID) {
err = HA_FTS_INVALID_DOCID;
my_error(HA_FTS_INVALID_DOCID, MYF(0));
} else {
err = convert_error_code_to_mysql(
error, m_prebuilt->table->flags, m_user_thd);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
goto err_exit;
}
}
}
#ifdef WITH_WSREP
if (error == DB_SUCCESS && trx->is_wsrep()
if (trx->is_wsrep()
&& wsrep_thd_is_local(m_user_thd)
&& !wsrep_thd_ignore_table(m_user_thd)) {
DBUG_PRINT("wsrep", ("update row key"));
@ -8706,7 +8714,8 @@ func_exit:
}
#endif /* WITH_WSREP */
DBUG_RETURN(err);
trx->row_ops[trx_t::ROW_UPDATE]++;
DBUG_RETURN(0);
}
/**********************************************************************//**
@ -8744,8 +8753,16 @@ ha_innobase::delete_row(
error = row_update_for_mysql(m_prebuilt);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
DBUG_RETURN(convert_error_code_to_mysql(
error, m_prebuilt->table->flags,
m_user_thd));
}
trx->row_ops[trx_t::ROW_DELETE]++;
#ifdef WITH_WSREP
if (error == DB_SUCCESS && trx->is_wsrep()
if (trx->is_wsrep()
&& wsrep_thd_is_local(m_user_thd)
&& !wsrep_thd_ignore_table(m_user_thd)) {
if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE,
@ -8756,8 +8773,8 @@ ha_innobase::delete_row(
}
}
#endif /* WITH_WSREP */
DBUG_RETURN(convert_error_code_to_mysql(
error, m_prebuilt->table->flags, m_user_thd));
DBUG_RETURN(0);
}
/**********************************************************************//**
@ -9285,7 +9302,7 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
mariadb_set_stats set_stats_temporary(handler_stats);
const trx_t* trx = m_prebuilt->trx;
trx_t* trx = m_prebuilt->trx;
ut_ad(trx == thd_to_trx(m_user_thd));

6
storage/innobase/include/srv0mon.h

@ -372,6 +372,12 @@ enum monitor_id_t {
MONITOR_OVLD_SRV_DBLWR_PAGES_WRITTEN,
MONITOR_OVLD_SRV_PAGE_SIZE,
/* Data DML related counters */
MONITOR_MODULE_DML_STATS,
MONITOR_OLVD_ROW_INSERTED,
MONITOR_OLVD_ROW_DELETED,
MONITOR_OLVD_ROW_UPDATED,
/* Data DDL related counters */
MONITOR_MODULE_DDL_STATS,
MONITOR_BACKGROUND_DROP_INDEX,

2
storage/innobase/include/trx0sys.h

@ -893,6 +893,8 @@ public:
alignas(CPU_LEVEL1_DCACHE_LINESIZE) rw_trx_hash_t rw_trx_hash;
/** Total row operation counts; @see trx_t::row_ops */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) Atomic_relaxed<size_t> row_ops[3];
#ifdef WITH_WSREP
/** Latest recovered XID during startup */

5
storage/innobase/include/trx0trx.h

@ -382,6 +382,7 @@ struct trx_lock_t
only be modified by the thread that is
serving the running transaction. */
/** Pre-allocated record locks */
struct {
alignas(CPU_LEVEL1_DCACHE_LINESIZE) ib_lock_t lock;
@ -756,6 +757,10 @@ public:
Transitions to COMMITTED are protected by trx_t::mutex. */
Atomic_relaxed<trx_state_t> state;
enum row_op_names { ROW_INSERT= 0, ROW_DELETE, ROW_UPDATE };
/** Row operation counters */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) size_t row_ops[3];
/** The locks of the transaction. Protected by lock_sys.latch
(insertions also by trx_t::mutex). */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_lock_t lock;

22
storage/innobase/row/row0sel.cc

@ -4456,13 +4456,11 @@ early_not_found:
DBUG_RETURN(DB_RECORD_NOT_FOUND);
}
#if SIZEOF_SIZE_T < 8
if (UNIV_LIKELY(~prebuilt->n_rows_fetched))
#endif
prebuilt->n_rows_fetched++;
if (prebuilt->n_rows_fetched > 1000000000) {
/* Prevent wrap-over */
prebuilt->n_rows_fetched = 500000000;
}
mode = pcur->search_mode;
}
@ -4733,12 +4731,8 @@ wait_table_again:
if (UNIV_UNLIKELY(need_to_process)) {
if (UNIV_UNLIKELY(!btr_pcur_get_rec(pcur))) {
mtr.commit();
trx->op_info = "";
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return DB_CORRUPTION;
err = DB_CORRUPTION;
goto page_corrupted;
}
if (UNIV_UNLIKELY(prebuilt->row_read_type
@ -4839,8 +4833,7 @@ page_corrupted:
if (err == DB_DECRYPTION_FAILED) {
btr_decryption_failed(*index);
}
rec = NULL;
goto page_read_error;
goto page_corrupted;
}
}
@ -5007,8 +5000,7 @@ wrong_offs:
" reimport the table.";
ut_ad(0);
err = DB_CORRUPTION;
goto page_read_error;
goto page_corrupted;
} else {
/* The user may be dumping a corrupt table. Jump
over the corruption to recover as much as possible. */

35
storage/innobase/srv/srv0mon.cc

@ -1069,6 +1069,26 @@ static monitor_info_t innodb_counter_info[] =
MONITOR_EXISTING | MONITOR_DEFAULT_ON | MONITOR_DISPLAY_CURRENT),
MONITOR_DEFAULT_START, MONITOR_OVLD_SRV_PAGE_SIZE},
/* ========== Counters for DML operations ========== */
{"module_dml", "dml", "Statistics for DMLs",
MONITOR_MODULE,
MONITOR_DEFAULT_START, MONITOR_MODULE_DML_STATS},
{"dml_inserts", "dml", "Number of rows inserted",
static_cast<monitor_type_t>(
MONITOR_EXISTING | MONITOR_DEFAULT_ON),
MONITOR_DEFAULT_START, MONITOR_OLVD_ROW_INSERTED},
{"dml_deletes", "dml", "Number of rows deleted",
static_cast<monitor_type_t>(
MONITOR_EXISTING | MONITOR_DEFAULT_ON),
MONITOR_DEFAULT_START, MONITOR_OLVD_ROW_DELETED},
{"dml_updates", "dml", "Number of rows updated",
static_cast<monitor_type_t>(
MONITOR_EXISTING | MONITOR_DEFAULT_ON),
MONITOR_DEFAULT_START, MONITOR_OLVD_ROW_UPDATED},
/* ========== Counters for DDL operations ========== */
{"module_ddl", "ddl", "Statistics for DDLs",
MONITOR_MODULE,
@ -1504,6 +1524,21 @@ srv_mon_process_existing_counter(
value = srv_buf_pool_size;
break;
/* innodb_rows_inserted */
case MONITOR_OLVD_ROW_INSERTED:
value = trx_sys.row_ops[trx_t::ROW_INSERT];
break;
/* innodb_rows_deleted */
case MONITOR_OLVD_ROW_DELETED:
value = trx_sys.row_ops[trx_t::ROW_DELETE];
break;
/* innodb_rows_updated */
case MONITOR_OLVD_ROW_UPDATED:
value = trx_sys.row_ops[trx_t::ROW_UPDATE];
break;
/* innodb_row_lock_current_waits */
case MONITOR_OVLD_ROW_LOCK_CURRENT_WAIT:
// dirty read without lock_sys.wait_mutex

8
storage/innobase/trx/trx0trx.cc

@ -100,6 +100,8 @@ trx_init(
{
trx->state = TRX_STATE_NOT_STARTED;
memset(trx->row_ops, 0, sizeof trx->row_ops);
trx->is_recovered = false;
trx->op_info = "";
@ -1436,7 +1438,12 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr)
}
if (UNIV_LIKELY(!dict_operation))
{
release_locks();
// Inaccurately (on purpose) update the operation counters.
for (size_t op= 0; op < array_elements(row_ops); op++)
trx_sys.row_ops[op]= trx_sys.row_ops[op] + row_ops[op];
}
}
if (trx_undo_t *&undo= rsegs.m_noredo.undo)
@ -1516,6 +1523,7 @@ void trx_t::commit_cleanup()
check_foreigns= true;
check_unique_secondary= true;
assert_freed();
trx_init(this);
mutex.wr_unlock();

3
storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result

@ -206,6 +206,9 @@ innodb_dict_lru_count_idle server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NU
innodb_dblwr_writes server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of doublewrite operations that have been performed (innodb_dblwr_writes)
innodb_dblwr_pages_written server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of pages that have been written for doublewrite operations (innodb_dblwr_pages_written)
innodb_page_size server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value InnoDB page size in bytes (innodb_page_size)
dml_inserts dml 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of rows inserted
dml_deletes dml 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of rows deleted
dml_updates dml 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of rows updated
ddl_background_drop_indexes ddl 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of indexes waiting to be dropped after failed index creation
ddl_online_create_index ddl 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of indexes being created online
ddl_pending_alter_table ddl 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of ALTER TABLE, CREATE INDEX, DROP INDEX in progress

Loading…
Cancel
Save