[MDEV-9963] information_schema.innodb_sys_tablestats MODIFIED_COUNTER weirdness Created: 2016-04-21  Updated: 2021-04-26  Resolved: 2021-04-26

Status: Closed
Project: MariaDB Server
Component/s: Storage Engine - InnoDB
Affects Version/s: 10.1.11, 10.1, 10.2, 10.3, 10.4, 10.5
Fix Version/s: N/A

Type: Bug Priority: Minor
Reporter: Erik Cederstrand Assignee: Marko Mäkelä
Resolution: Not a Bug Votes: 0
Labels: None


 Description   

Issue MDEV-8297 was closed, but there are still unexpected (for me, at least) things going on with MODIFIED_COUNTER, with both indexed and non-indexed columns.

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 1785
Server version: 10.1.11-MariaDB Homebrew
 
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [test]> drop table t1;
Query OK, 0 rows affected (0.04 sec)
 
MariaDB [test]> create table t1 (i int primary key, j int);
Query OK, 0 rows affected (0.03 sec)
 
MariaDB [test]> select * from information_schema.innodb_sys_tablestats where name = 'test/t1';
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
| TABLE_ID | NAME    | STATS_INITIALIZED | NUM_ROWS | CLUST_INDEX_SIZE | OTHER_INDEX_SIZE | MODIFIED_COUNTER | AUTOINC | REF_COUNT |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
|    14999 | test/t1 | Uninitialized     |        0 |                0 |                0 |                0 |       0 |         0 |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
1 row in set (0.03 sec)
 
MariaDB [test]> insert into t1 values (1, 2);
Query OK, 1 row affected (0.00 sec)
 
MariaDB [test]> select * from information_schema.innodb_sys_tablestats where name = 'test/t1';
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
| TABLE_ID | NAME    | STATS_INITIALIZED | NUM_ROWS | CLUST_INDEX_SIZE | OTHER_INDEX_SIZE | MODIFIED_COUNTER | AUTOINC | REF_COUNT |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
|    14999 | test/t1 | Initialized       |        1 |                1 |                0 |                1 |       0 |         1 |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
1 row in set (0.00 sec)

Looks good. num_rows is 1 and modified_counter is 1.

MariaDB [test]> update t1 set i=2;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
MariaDB [test]> select * from information_schema.innodb_sys_tablestats where name = 'test/t1';
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
| TABLE_ID | NAME    | STATS_INITIALIZED | NUM_ROWS | CLUST_INDEX_SIZE | OTHER_INDEX_SIZE | MODIFIED_COUNTER | AUTOINC | REF_COUNT |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
|    14999 | test/t1 | Initialized       |        1 |                1 |                0 |                0 |       0 |         1 |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
1 row in set (0.00 sec)

What? modified_counter counts backwards on UPDATE?

MariaDB [test]> update t1 set i=3;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
MariaDB [test]> select * from information_schema.innodb_sys_tablestats where name = 'test/t1';
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
| TABLE_ID | NAME    | STATS_INITIALIZED | NUM_ROWS | CLUST_INDEX_SIZE | OTHER_INDEX_SIZE | MODIFIED_COUNTER | AUTOINC | REF_COUNT |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
|    14999 | test/t1 | Initialized       |        1 |                1 |                0 |                1 |       0 |         1 |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
1 row in set (0.00 sec)

What? num_rows and modified_counter are now the same with table contents [(1, 2)] and [(3, 2)], even though I did two updates in a row.

MariaDB [test]> update t1 set i=3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0
 
MariaDB [test]> select * from information_schema.innodb_sys_tablestats where name = 'test/t1';
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
| TABLE_ID | NAME    | STATS_INITIALIZED | NUM_ROWS | CLUST_INDEX_SIZE | OTHER_INDEX_SIZE | MODIFIED_COUNTER | AUTOINC | REF_COUNT |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
|    14999 | test/t1 | Initialized       |        1 |                1 |                0 |                1 |       0 |         1 |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
1 row in set (0.00 sec)

No-op UPDATE doesn't change values. Looks good.

MariaDB [test]> update t1 set j=3;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
MariaDB [test]> select * from information_schema.innodb_sys_tablestats where name = 'test/t1';
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
| TABLE_ID | NAME    | STATS_INITIALIZED | NUM_ROWS | CLUST_INDEX_SIZE | OTHER_INDEX_SIZE | MODIFIED_COUNTER | AUTOINC | REF_COUNT |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
|    14999 | test/t1 | Initialized       |        1 |                1 |                0 |                2 |       0 |         1 |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
1 row in set (0.00 sec)

Looks good, modified_counter got incremented.

MariaDB [test]> update t1 set j=3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0
 
MariaDB [test]> select * from information_schema.innodb_sys_tablestats where name = 'test/t1';
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
| TABLE_ID | NAME    | STATS_INITIALIZED | NUM_ROWS | CLUST_INDEX_SIZE | OTHER_INDEX_SIZE | MODIFIED_COUNTER | AUTOINC | REF_COUNT |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
|    14999 | test/t1 | Initialized       |        1 |                1 |                0 |                3 |       0 |         1 |
+----------+---------+-------------------+----------+------------------+------------------+------------------+---------+-----------+
1 row in set (0.00 sec)

What? No-op UPDATE increments modified_counter even though MariaDB reports "Changed: 0".

But maybe this is intentional, and I'm just misunderstanding the way num_rows and modified_counter is supposed to work?



 Comments   
Comment by Elena Stepanova [ 2020-10-20 ]

This report fell very deeply through the cracks, sorry about that.

There are three "what?"s in here.

1) upon 1st UPDATE (update t1 set i=2) MODIFIED_COUNTER is reset to 0. It is still reproducible on 10.1-10.5 and is indeed strange.
2) upon 2nd UPDATE (update t1 set i=3) MODIFIED_COUNTER is set to 1 and NUM_ROWS is still 1. It seems reasonable (considering that MODIFIED_COUNTER was already 0 before), since the number of rows is indeed still 1, and one row was modified.
3) upon 5th UPDATE (no-op update t1 set j=3) MODIFIED_COUNTER is incremented. It is still reproducible on 10.1, but not on 10.2+, so I suppose it's not much of a concern.

marko, I'm leaving it to you to decide what to do about all of this, if anything.

Comment by Marko Mäkelä [ 2021-04-26 ]

The column is reflecting dict_table_t::stat_modified_counter. I have no idea what its purpose is. I see that it is being updated in a few code paths, including some (but not all) cases of ROLLBACK. I also see that concurrent access to that field is not being protected by any means.

The purpose of the data field is unclear to me. I see that it was renamed from stat_modif_counter in 2001. The field was present already in the very first public release of InnoDB.

Because the field is apparently not being used for anything useful, and because implementing correct concurrency protection of it could degrade performance, I would remove the field.

Comment by Marko Mäkelä [ 2021-04-26 ]

It turns out that after all, dict_table_t::stat_modified_counter is being exactly in one place. dict_stats_update_if_needed() uses it to determine whether statistics should be recalculated.

The fact that the counter will be reset whenever statistics are recalculated appear to be so by design.

Even less useful than the MODIFIED_COUNTER column could be the column information_schema.innodb_sys_tablestats.REF_COUNT.

Generated at Thu Feb 08 07:38:38 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.