Adaptive flushing does a dirty scan of the flush list
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Percona Server moved to https://jira.percona.com/projects/PS |
Fix Released
|
High
|
Laurynas Biveinis | ||
5.1 |
Fix Released
|
High
|
Laurynas Biveinis | ||
5.5 |
Fix Released
|
High
|
Laurynas Biveinis |
Bug Description
121124 3:56:12 [Note] /data/ssd/
Version: '5.5.28-
==3005== Thread 16:
==3005== Invalid read of size 8
==3005== at 0x8243C8: srv_master_thread (srv0srv.c:3487)
==3005== by 0x38E260677C: start_thread (pthread_
==3005== by 0x38E16D3C1C: clone (in /lib64/libc-2.5.so)
==3005== Address 0x15a488e0 is 96 bytes inside a block of size 152 free'd
==3005== at 0x4A072BA: free (vg_replace_
==3005== by 0x87446A: buf_page_get_gen (buf0buf.ic:886)
==3005== by 0x879DF3: buf_page_create (buf0buf.c:3760)
==3005== by 0x8BB89B: fsp_page_create (fsp0fsp.c:1547)
==3005== by 0x8C4411: fseg_alloc_
==3005== by 0x8C4F6E: fseg_alloc_
==3005== by 0x85B235: btr_store_
==3005== by 0x918B6C: row_ins_
==3005== by 0x91CC52: row_ins_step (row0ins.c:2294)
==3005== by 0x8088F5: row_insert_
==3005== by 0x7EFA89: ha_innobase:
==3005== by 0x69B7E1: handler:
==3005== by 0x5673D0: write_record(THD*, TABLE*, st_copy_info*) (sql_insert.
==3005== by 0x56E463: mysql_insert(THD*, TABLE_LIST*, List<Item>&, List<List<Item> >&, List<Item>&, List<Item>&, enum_duplicates, bool) (sql_insert.cc:956)
==3005== by 0x57EE0B: mysql_execute_
==3005== by 0x583112: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:5811)
==3005==
==3005== Invalid read of size 8
==3005== at 0x8243E4: srv_master_thread (srv0srv.c:3492)
==3005== by 0x38E260677C: start_thread (pthread_
==3005== by 0x38E16D3C1C: clone (in /lib64/libc-2.5.so)
==3005== Address 0x15a488c0 is 64 bytes inside a block of size 152 free'd
==3005== at 0x4A072BA: free (vg_replace_
==3005== by 0x87446A: buf_page_get_gen (buf0buf.ic:886)
==3005== by 0x879DF3: buf_page_create (buf0buf.c:3760)
==3005== by 0x8BB89B: fsp_page_create (fsp0fsp.c:1547)
==3005== by 0x8C4411: fseg_alloc_
==3005== by 0x8C4F6E: fseg_alloc_
==3005== by 0x85B235: btr_store_
==3005== by 0x918B6C: row_ins_
==3005== by 0x91CC52: row_ins_step (row0ins.c:2294)
==3005== by 0x8088F5: row_insert_
==3005== by 0x7EFA89: ha_innobase:
==3005== by 0x69B7E1: handler:
==3005== by 0x5673D0: write_record(THD*, TABLE*, st_copy_info*) (sql_insert.
==3005== by 0x56E463: mysql_insert(THD*, TABLE_LIST*, List<Item>&, List<List<Item> >&, List<Item>&, List<Item>&, enum_duplicates, bool) (sql_insert.cc:956)
==3005== by 0x57EE0B: mysql_execute_
==3005== by 0x583112: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:5811)
==3005==
[.....]
==3005==
==3005== HEAP SUMMARY:
==3005== in use at exit: 1,560 bytes in 5 blocks
==3005== total heap usage: 4,481,035 allocs, 4,481,030 frees, 40,235,084,856 bytes allocated
==3005==
==3005== LEAK SUMMARY:
==3005== definitely lost: 0 bytes in 0 blocks
==3005== indirectly lost: 0 bytes in 0 blocks
==3005== possibly lost: 0 bytes in 0 blocks
==3005== still reachable: 0 bytes in 0 blocks
==3005== suppressed: 1,560 bytes in 5 blocks
==3005==
==3005== For counts of detected and suppressed errors, rerun with: -v
==3005== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)
Preliminary Analysis thanks to Laurynas: Adaptive flushing algorithms do dirty reads from the flush list and then from the pages on that list. Because of that, nothing protects to read from a free'd or malloc'ed but uninitialized page descriptor if the same page happens to be read in by other thread.
Related branches
- Laurynas Biveinis (community): Approve
- Sergei Glushchenko (community): Needs Information (g2)
- Stewart Smith (community): Approve
-
Diff: 72 lines (+10/-8)1 file modifiedPercona-Server/storage/innodb_plugin/srv/srv0srv.c (+10/-8)
- Stewart Smith (community): Approve
- Laurynas Biveinis: Pending requested
-
Diff: 129 lines (+17/-17)2 files modifiedPercona-Server/storage/innobase/buf/buf0flu.c (+5/-7)
Percona-Server/storage/innobase/srv/srv0srv.c (+12/-10)
summary: |
- Valgrind: free in buf_page_get_gen - (srv_master_thread/buf_flush_batch/buf_flush_page_and_try_neighbors) + Valgrind: free in buf_page_get_gen (Invalid read in srv_master_thread) |
summary: |
- Adaptive flushing does a dirty scan of the flush list | Valgrind: free - in buf_page_get_gen | Debug Assert: bpage->in_flush_list + Adaptive flushing does a dirty scan of the flush list |
tags: | added: xtradb |
InnoDB master thread code in question with the dirty reads: flushing && srv_adaptive_ flushing_ method == 1) { pool_instances; j++) {
...
} else if (srv_adaptive_
...
for (j = 0; j < srv_buf_
buf_pool_t* buf_pool;
ulint n_blocks;
buf_pool = buf_pool_ from_array( j);
/* The scanning flush_list is optimistic here */
level = 0; GET_FIRST( buf_pool- >flush_ list);
n_blocks = 0;
bpage = UT_LIST_
while (bpage != NULL) { oldest_ modification; modification != 0) { >max_checkpoint _age modification) ; GET_NEXT( flush_list, bpage);
ib_uint64_t oldest_modification = bpage->
if (oldest_
level += log_sys-
- (lsn - oldest_
}
bpage = UT_LIST_
n_blocks++;
}
...