[MDEV-18244] Server crashes in ha_innobase::update_thd / ... / ha_partition::update_next_auto_inc_val Created: 2019-01-15  Updated: 2021-04-19  Resolved: 2019-11-01

Status: Closed
Project: MariaDB Server
Component/s: Partitioning, Storage Engine - InnoDB
Affects Version/s: 10.3.5, 10.4.0
Fix Version/s: 10.3.19, 10.4.9

Type: Bug Priority: Blocker
Reporter: Elena Stepanova Assignee: Alexey Botchkov
Resolution: Fixed Votes: 0
Labels: crash, regression

Issue Links:
Duplicate
duplicates MDEV-20910 INSERTs into specific partitions cras... Closed
is duplicated by MDEV-19907 In Partiitioned table using HASH, AUT... Closed
is duplicated by MDEV-20718 Crash on insert with PARTITION clause... Closed
Problem/Incident
is caused by MDEV-11084 Select statement with partition selec... Closed
Relates
relates to MDEV-24610 Assertion `auto_increment_value' fail... Confirmed

 Description   

--source include/have_innodb.inc
--source include/have_partition.inc
 
CREATE TABLE t1 (a INT)
ENGINE=InnoDB 
PARTITION BY RANGE (a) (
  PARTITION p0 VALUES LESS THAN (6),
  PARTITION pn VALUES LESS THAN MAXVALUE
);
INSERT INTO t1 VALUES (4),(5),(6);
ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY;
UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5;
 
# Cleanup
DROP TABLE t1;

10.3 82490a97db

#3  <signal handler called>
#4  0x000055e0922036ec in ha_innobase::update_thd (this=0x7ff5100a6738, thd=0x7ff510000b00) at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:2946
#5  0x000055e0921f3e02 in ha_innobase::info_low (this=0x7ff5100a6738, flag=64, is_analyze=false) at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:13837
#6  0x000055e0921f49e4 in ha_innobase::info (this=0x7ff5100a6738, flag=64) at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:14151
#7  0x000055e092631e8c in ha_partition::info (this=0x7ff5100a8a98, flag=64) at /data/src/10.3/sql/ha_partition.cc:8157
#8  0x000055e0926367d1 in ha_partition::update_next_auto_inc_val (this=0x7ff5100a8a98) at /data/src/10.3/sql/ha_partition.cc:10322
#9  0x000055e092627c4b in ha_partition::update_row (this=0x7ff5100a8a98, old_data=0x7ff510170480 "\377\005", new_data=0x7ff510170478 "\377\003") at /data/src/10.3/sql/ha_partition.cc:4453
#10 0x000055e091ed3003 in handler::ha_update_row (this=0x7ff5100a8a98, old_data=0x7ff510170480 "\377\005", new_data=0x7ff510170478 "\377\003") at /data/src/10.3/sql/handler.cc:6269
#11 0x000055e091cc68e0 in mysql_update (thd=0x7ff510000b00, table_list=0x7ff510014e30, fields=..., values=..., conds=0x7ff510015810, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7ff565e2a6f0, updated_return=0x7ff565e2a7b0) at /data/src/10.3/sql/sql_update.cc:947
#12 0x000055e091bce24d in mysql_execute_command (thd=0x7ff510000b00) at /data/src/10.3/sql/sql_parse.cc:4581
#13 0x000055e091bd9669 in mysql_parse (thd=0x7ff510000b00, rawbuf=0x7ff510014cd8 "UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5", length=46, parser_state=0x7ff565e2b5f0, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:8092
#14 0x000055e091bc681d in dispatch_command (command=COM_QUERY, thd=0x7ff510000b00, packet=0x7ff510161011 "UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5", packet_length=46, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:1851
#15 0x000055e091bc5241 in do_command (thd=0x7ff510000b00) at /data/src/10.3/sql/sql_parse.cc:1396
#16 0x000055e091d2d256 in do_handle_one_connection (connect=0x55e094dc39d0) at /data/src/10.3/sql/sql_connect.cc:1402
#17 0x000055e091d2cfda in handle_one_connection (arg=0x55e094dc39d0) at /data/src/10.3/sql/sql_connect.cc:1308
#18 0x000055e0921c78dd in pfs_spawn_thread (arg=0x55e094dcc0c0) at /data/src/10.3/storage/perfschema/pfs.cc:1862
#19 0x00007ff5727ca494 in start_thread (arg=0x7ff565e2c700) at pthread_create.c:333
#20 0x00007ff570bb093f in clone () from /lib/x86_64-linux-gnu/libc.so.6

All of debug, non-debug and ASAN builds crash with SIGSEGV.

Not reproducible on 10.2.



 Comments   
Comment by Marko Mäkelä [ 2019-01-18 ]

The problem is that ha_partition::open_read_partitions() is not opening all partitions that the UPDATE statement is accessing. I found this out by setting a breakpoint on ha_innobase::open() and noticing that the this pointer that is passed to ha_innobase::update_thd() did not occur previously. After the ALTER TABLE, only the first partition is being accessed.

On the first look, the UPDATE should only access the first partition, but in reality it is accessing all partitions, because the auto-increment counter is being updated on all partitions.

Apparently MDEV-11084 is missing an adjustment for this special case (updating AUTO_INCREMENT value).

I verified that the crash was introduced by this change that implements MDEV-11084 . There was no crash with the parent commit.

Comment by Alice Sherepa [ 2019-07-04 ]

Test case from MDEV-19907:

--source include/have_innodb.inc
--source include/have_partition.inc
CREATE TABLE t1 (
    id1 int NOT NULL, 
    id2 int NOT NULL,
    id int(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (id1,id2), 
    KEY id (id)) 
ENGINE=innodb AUTO_INCREMENT=1 PARTITION BY HASH (id1) (PARTITION p0001, PARTITION p0002);
 
INSERT INTO t1 partition(p0002) (id1,id2) VALUES (1,1), (1,2), (1,3);
 
ANALYZE TABLE t1;
 
INSERT INTO t1 partition(p0001) ( id1, id2) VALUES (2,1), (2,2), (2,3), (2,4), (2,5) ;
 
DROP TABLE t1;

10.3 099007c3c92d140562577

==24231==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x5594d2b16256 bp 0x7f9862d4b900 sp 0x7f9862d4b850 T27)
    #0 0x5594d2b16255 in ha_innobase::update_thd(THD*)  /10.3/storage/innobase/handler/ha_innodb.cc:2958
    #1 0x5594d2af35fe in ha_innobase::info_low(unsigned int, bool)  /10.3/storage/innobase/handler/ha_innodb.cc:13923
    #2 0x5594d2af52f0 in ha_innobase::info(unsigned int)  /10.3/storage/innobase/handler/ha_innodb.cc:14237
    #3 0x5594d32baf55 in ha_partition::info(unsigned int)  /10.3/sql/ha_partition.cc:8157
    #4 0x5594d32c7f0c in ha_partition::update_next_auto_inc_val()  /10.3/sql/ha_partition.cc:10326
    #5 0x5594d329c6aa in ha_partition::write_row(unsigned char*)  /10.3/sql/ha_partition.cc:4268
    #6 0x5594d22d05f3 in handler::ha_write_row(unsigned char*)  /10.3/sql/handler.cc:6420
    #7 0x5594d1b34aea in write_record(THD*, TABLE*, st_copy_info*)  /10.3/sql/sql_insert.cc:2030
    #8 0x5594d1b2e1d5 in mysql_insert(THD*, TABLE_LIST*, List<Item>&, List<List<Item> >&, List<Item>&, List<Item>&, enum_duplicates, bool)  /10.3/sql/sql_insert.cc:1071
    #9 0x5594d1bc4a8d in mysql_execute_command(THD*)  /10.3/sql/sql_parse.cc:4735
    #10 0x5594d1bda295 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool)  /10.3/sql/sql_parse.cc:8105
    #11 0x5594d1bb4d9d in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool)  /10.3/sql/sql_parse.cc:1858
    #12 0x5594d1bb1f01 in do_command(THD*)  /10.3/sql/sql_parse.cc:1404
    #13 0x5594d1f08ec1 in do_handle_one_connection(CONNECT*)  /10.3/sql/sql_connect.cc:1402
    #14 0x5594d1f0889e in handle_one_connection  /10.3/sql/sql_connect.cc:1308
    #15 0x5594d3231cc0 in pfs_spawn_thread  /10.3/storage/perfschema/pfs.cc:1862
    #16 0x7f987a1eb6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
    #17 0x7f987968041c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)

With MYISAM it results in a wrong values in the auto_incremented column:

CREATE TABLE t1 (
    id1 int NOT NULL, 
    id2 int NOT NULL,
    id int(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (id1,id2), 
    KEY id (id)) 
ENGINE=myisam AUTO_INCREMENT=1 PARTITION BY HASH (id1) (PARTITION p0001, PARTITION p0002);
 
INSERT INTO t1 partition(p0002) (id1,id2) VALUES (1,1), (1,2), (1,3);
 
ANALYZE TABLE t1;
INSERT INTO t1 partition(p0001) ( id1, id2) VALUES (2,1), (2,2), (2,3), (2,4), (2,5) ;
SELECT id, count(*) FROM t1 GROUP BY id;

MariaDB [test]> SELECT id, count(*) FROM t1 GROUP BY id;
+----+----------+
| id | count(*) |
+----+----------+
|  1 |        2 |
|  2 |        2 |
|  3 |        2 |
|  4 |        1 |
|  5 |        1 |
+----+----------+
5 rows in set (0.000 sec)

Comment by Alice Sherepa [ 2019-10-02 ]

holyfoot, please check also test case from MDEV-20718 before closing:

create table t1 (
	id int(10) not null auto_increment,
	groupid int,
	name varchar(255),
	primary key (id, groupid)
)engine=innodb
partition by list(groupid) (partition p1 values in (1), partition p2 values in (2));
 
alter table t1 truncate partition p1;
insert into t1 partition (p1) (groupid, name) values (1, 'tamara smith');
select * from t1;

Comment by Alexey Botchkov [ 2019-10-21 ]

https://github.com/MariaDB/server/commit/7a331ec820be89f8c2d0fd968bd4b003cbbf75fc

Comment by Jacob Williams [ 2019-10-25 ]

I noticed a related bug, but it may be the same root cause.

We have some tables with old datetime columns, not yet updated to new temporal storage type. After doing a partition drop/add, the dates and times in the other partitions become corrupted. The dates look like nonsense afterward, and updating rows in the table will cause additional corruption in other columns.

My theory is that the ALTER statement for DROP/ADD causes it to "upgrade" the datetime columns to the new temporal type, or at least mark them as updated, but it doesn't actually go into the other partitions to update the data on disk. When it goes back to read or modify the data, it reads the old datetime value and tries to interpret as if it was the new type.

In my tests, upgrading to new temporal type by doing a non-partition targeted alter statement before doing partition maintenance prevented the corruption.

Comment by Elena Stepanova [ 2019-10-28 ]

Test case from MDEV-20910holyfoot, please make sure it is fixed as well before closing the bug:

--source include/have_innodb.inc
--source include/have_partition.inc
 
CREATE TABLE `t` (
`id` INT(5) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
PARTITION BY HASH (`id`)
(PARTITION `p1`, 
PARTITION `p2`);
 
INSERT INTO t PARTITION (p1) VALUES (1);

Given the number of affected users and the fact that it has already undergone at least one round of review, I'm raising it to a blocker.

Comment by Chris Calender (Inactive) [ 2019-10-30 ]

To be clear, this also affects RANGE partitions too:

Test case:

CREATE TABLE `t1` (
`id1` BIGINT(20) NOT NULL AUTO_INCREMENT,
`id2` BIGINT(20) NOT NULL,
PRIMARY KEY (`id1`,`id2`)
) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
PARTITION BY RANGE (`id2`)
(PARTITION `p1` VALUES LESS THAN (100),
PARTITION `p2` VALUES LESS THAN (200),
PARTITION `p3` VALUES LESS THAN MAXVALUE);
 
INSERT INTO t1 PARTITION (p1) VALUES (1,1);

Session Output:

mysql> CREATE TABLE `t1` (
    -> `id1` BIGINT(20) NOT NULL AUTO_INCREMENT,
    -> `id2` BIGINT(20) NOT NULL,
    -> PRIMARY KEY (`id1`,`id2`)
    -> ) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
    -> PARTITION BY RANGE (`id2`)
    -> (PARTITION `p1` VALUES LESS THAN (100),
    -> PARTITION `p2` VALUES LESS THAN (200),
    -> PARTITION `p3` VALUES LESS THAN MAXVALUE);
ERROR 1050 (42S01): Table 't1' already exists
mysql>
mysql> INSERT INTO t1 PARTITION (p1) VALUES (1,1);
ERROR 2013 (HY000): Lost connection to MySQL server during query

Comment by Jacob Williams [ 2019-11-01 ]

I realized my comment above probably does relate to this bug. Reported it separately in MDEV-20940.

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