返回顶部
首页 > 资讯 > 数据库 >MySQL中I/O出现错误问题原因是什么
  • 425
分享到

MySQL中I/O出现错误问题原因是什么

2024-04-02 19:04:59 425人浏览 泡泡鱼
摘要

Mysql中I/O出现错误问题原因是什么?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!问题现象最近使用sysbench测试

Mysql中I/O出现错误问题原因是什么?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!

问题现象

最近使用sysbench测试mysql,由于测试时间较长,写了一个脚本按prepare->run->cleanup的顺序在后台跑着。跑完后察看日志发现一个问题,Mysql服务的错误日志中出现多条类似以下信息的报错:

[ERROR] InnoDB: Trying to do I/O to a tablespace which does not exist. I/O type: read, page: [page id: space=32, page number=57890], I/O length: 16384 bytes。

看起来是I/O出现了错误,但MySQL进程并未崩溃,sysbench客户端也没有报错。

发现问题过程

根据报错的时间记录以及脚本输出的各个阶段的时间点对比,确定了当时脚本正在执行的命令为:

sysbench --tables=100 --table-size=4000000 --threads=50 --mysql-db=sbtest --time=300 oltp_delete cleanup

重新手动执行一遍这个用例,却没有再出现同样的情况。但是用脚本执行却依然能够发现这个错误信息。初步怀疑是run和cleanup之间不能间隔太久才会触发这个问题。由于执行一遍100G数据量的时间较长,重现代价较大,先尝试缩减用例数据量。将—table-size=4000000修改为2000000,此时执行脚本,又不会触发这个问题了,最后将—table-size=3000000可以稳定触发又能减少部分重现时间。为了确认是否间隔太长会导致不能复现,修改脚本在run和cleanup两个阶段之间sleep 10秒,果然不会触发这个错误信息。修改为sleep 5秒则还能触发,不过报错条数已有所减少。

问题调查

察看对应版本mysql5.7.22的代码,发现这个报错只有一个位置:fil0fil.cc文件的第5578行fil_io()函数内。 直接使用gdb调试,在这个位置加上断点,并执行可复现的脚本,得到以下堆栈:

(gdb) bt
#0  fil_io (type=..., sync=sync@entry=false, page_id=..., page_size=..., byte_offset=byte_offset@entry=0, len=16384, buf=0x7f9ead544000, message=message@entry=0x7f9ea8ce9c78) at mysql-5.7.22/storage/innobase/fil/fil0fil.cc:5580
#1  0x00000000010f99fa in buf_read_page_low (err=0x7f9ddaffc72c, sync=<optimized out>, type=0, mode=<optimized out>, page_id=..., page_size=..., unzip=true) at mysql-5.7.22/storage/innobase/buf/buf0rea.cc:195
#2  0x00000000010fc5fa in buf_read_ibuf_merge_pages (sync=sync@entry=false, space_ids=space_ids@entry=0x7f9ddaffc7e0, page_nos=page_nos@entry=0x7f9ddaffc7a0, n_stored=2) at mysql-5.7.22/storage/innobase/buf/buf0rea.cc:834
#3  0x0000000000f3a86c in ibuf_merge_pages (n_pages=n_pages@entry=0x7f9ddaffce30, sync=sync@entry=false) at mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2552
#4  0x0000000000f3a94a in ibuf_merge (sync=false, sync=false, n_pages=0x7f9ddaffce30) at mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2656
#5  ibuf_merge_in_background (full=full@entry=false) at mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2721
#6  0x000000000102bcf4 in srv_master_do_active_tasks () at mysql-5.7.22/storage/innobase/srv/srv0srv.cc:2132
#7  srv_master_thread (arg=<optimized out>) at mysql-5.7.22/storage/innobase/srv/srv0srv.cc:2383
#8  0x00007fa003eeddc5 in start_thread () from /lib64/libpthread.so.0
#9  0x00007fa002aab74d in clone () from /lib64/libc.so.6

很明显这是后台线程在做insert buffer merge操作。此时发现space->stop_new_ops为true,也就是要处理的页面所属的space正在被删除。为什么会去操作正在被删除的space呢?这需要调查下insert buffer功能、insert buffer merge的流程以及删除表的流程。

insert buffer背景知识

insert buffer是一种特殊的数据结构(B+ tree),当辅助索引页面不在缓冲池中时,它会将更改缓存起来,稍后在页面被其他读取操作加载到缓冲池中时合并。MySQL最初引进这个功能的时候只能缓存insert操作,所以叫做insert buffer,现在这些操作可以是 INSERT, UPDATE, or DELETE(DML),所以改叫做change buffer了(本文依然以insert buffer描述),但源码中依然以ibuf作为标识。这个功能把若干对同一页面的更新缓存起来,合并为一次性更新操作,减少了IO,并转化随机IO为顺序IO,这样可以避免随机IO带来性能损耗,提高数据库的写性能。

相关insert buffer merge逻辑

当buffer page读入buffer pool时,就会进行insert buffer merge。主要有几个场景会出现merge过程:

  1. 当页面被读入缓冲池时,读取完成后先进行ibuf的merge,然后页面才可用;

  2. merge操作作为后台任务执行。 innodb_io_capacity参数可设置InnoDB后台任务每次merge过程的页面数上限;

  3. 在崩溃恢复期间,当索引页被读入缓冲池时,将执行对应页的insert buffer merge;

  4. insert buffer具有持久性,系统崩溃不会导致它失效。重启后,insert buffer merge操作将恢复正常;

  5. 服务器关闭时可使用—innodb-fast-shutdown = 0强制进行ibuf的完全合并。

我们这次的问题很明显属于第二种情况。innodb主线程(svr_master_thread)会每隔一秒主动进行一次insert buffer的merge操作。先判断过去1s之内服务器是否发生过活动(插入元组到页面、undo表上的行操作等),如果发生过,则merge的最大页面数为innodb_io_capacity设定的5%。如果没有则merge的最大页面数为innodb_io_capacity设定的值。

innodb主线程(svr_master_thread)merge的主流程如下:

  1. 主线程从ibuf树的叶子节点读取页号和space号,并记录到一个二元数组中(未加);

  2. 主线程对二元组中space进行检测是否在表空间缓存中,如不在,说明已经被删除了,删除对应ibuf的记录;

  3. 主线程判断是否对一个正在删除的space进行异步读取操作,如果是,报错,并删除对应ibuf的记录,转到过程2继续下一个数组元素的判断;

  4. 如果一切判断正常,主线程发出async io请求,async读取需要被merge的索引页面;

  5. I/O handler 线程,在接受到完成的async I/O之后,进行merge操作;

  6. 进行merge的时候调用fil_space_acquire对space->n_pending_ops进行自增。避免删除操作并发

  7. 执行完毕后调用fil_space_release对space->n_pending_ops进行自减。

相关删除表的逻辑

  1. 对fil_system->mutex加锁,设置sp->stop_new_ops = true,标记space正在删除,不允许对它进行新操作,然后对fil_system->mutex解锁;

  2. 对fil_system->mutex加锁,检测space->n_pending_ops,对fil_system->mutex解锁。如果检测到大于0,意味着还有依赖的操作未完成,睡眠20ms后重试;

  3. 对fil_system->mutex加锁,检测space->n_pending_flushes和(*node)->n_pending ,对fil_system->mutex解锁。如果检测到大于0,意味着还有依赖的I/O未完成,睡眠20ms后重试;

  4. 此时认为已经没有冲突的操作了,刷出所有脏页面或删除所有给定的表空间的页面;

  5. 从表空间缓存删除指定space的记录;

  6. 删除对应数据文件。

问题结论

情况很明确了,主线程获取ibuf的(space,page)的过程与删除操作执行的过程并没有锁保证互斥,只有async I/O完成之后的merge操作与删除操作才有互斥。如果后台线程开始ibuf merge并已经执行过了第2步的检测,但还没有执行到第3步检测,此时用户线程开始做删除表的操作,并设置好stop_new_ops标记但还没有执行到第5步删除表空间缓存,就会出现这个错误信息。两线程的交互如下图所示:

MySQL中I/O出现错误问题原因是什么

不出意外的话,在打中断点时必然有线程在执行对应表的删除操作。果然我们可以发现如下堆栈:

Thread 118 (Thread 0x7f9de0111700 (LWP 5234)):
#0  0x00007fa003ef1e8e in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x0000000000f82f41 in broadcast (this=0xd452ef8) at mysql-5.7.22/storage/innobase/os/os0event.cc:184
#2  set (this=0xd452ef8) at mysql-5.7.22/storage/innobase/os/os0event.cc:75
#3  os_event_set (event=0xd452ef8) at mysql-5.7.22/storage/innobase/os/os0event.cc:483
#4  0x00000000010ec8a4 in signal (this=<optimized out>) at mysql-5.7.22/storage/innobase/include/ut0mutex.ic:105
#5  exit (this=<optimized out>) at mysql-5.7.22/storage/innobase/include/ib0mutex.h:690
#6  exit (this=<optimized out>) at mysql-5.7.22/storage/innobase/include/ib0mutex.h:961
#7  buf_flush_yield (bpage=<optimized out>, buf_pool=<optimized out>) at mysql-5.7.22/storage/innobase/buf/buf0lru.cc:405
#8  buf_flush_try_yield (processed=<optimized out>, bpage=<optimized out>, buf_pool=<optimized out>) at mysql-5.7.22/storage/innobase/buf/buf0lru.cc:449
#9  buf_flush_or_remove_pages (trx=<optimized out>, flush=<optimized out>, observer=<optimized out>, id=<optimized out>, buf_pool=<optimized out>) at mysql-5.7.22/storage/innobase/buf/buf0lru.cc:632
#10 buf_flush_dirty_pages (buf_pool=<optimized out>, id=<optimized out>, observer=<optimized out>, flush=<optimized out>, trx=<optimized out>) at mysql-5.7.22/storage/innobase/buf/buf0lru.cc:693
#11 0x00000000010f6de7 in buf_LRU_remove_pages (trx=0x0, buf_remove=BUF_REMOVE_FLUSH_NO_WRITE, id=55, buf_pool=0x31e55e8) at mysql-5.7.22/storage/innobase/buf/buf0lru.cc:893
#12 buf_LRU_flush_or_remove_pages (id=id@entry=55, buf_remove=buf_remove@entry=BUF_REMOVE_FLUSH_NO_WRITE, trx=trx@entry=0x0) at mysql-5.7.22/storage/innobase/buf/buf0lru.cc:951
#13 0x000000000114e488 in fil_delete_tablespace (id=id@entry=55, buf_remove=buf_remove@entry=BUF_REMOVE_FLUSH_NO_WRITE) at mysql-5.7.22/storage/innobase/fil/fil0fil.cc:2800
#14 0x0000000000fe77bd in row_drop_single_table_tablespace (trx=0x0, is_encrypted=false, is_temp=false, filepath=0x7f9d7c209f38 "./sbtest/sbtest25.ibd", tablename=0x7f9d7c209dc8 "sbtest/sbtest25", space_id=55) at mysql-5.7.22/storage/innobase/row/row0mysql.cc:4189
#15 row_drop_table_for_mysql (name=name@entry=0x7f9de010e020 "sbtest/sbtest25", trx=trx@entry=0x7f9ff9515750, drop_db=<optimized out>, nonatomic=<optimized out>, nonatomic@entry=true, handler=handler@entry=0x0) at mysql-5.7.22/storage/innobase/row/row0mysql.cc:4741
#16 0x0000000000f092f3 in ha_innobase::delete_table (this=<optimized out>, name=0x7f9de010f5e0 "./sbtest/sbtest25") at mysql-5.7.22/storage/innobase/handler/ha_innodb.cc:12539
#17 0x0000000000801a30 in ha_delete_table (thd=thd@entry=0x7f9d7c1f6910, table_type=table_type@entry=0x2ebd100, path=path@entry=0x7f9de010f5e0 "./sbtest/sbtest25", db=db@entry=0x7f9d7c00e560 "sbtest", alias=0x7f9d7c00df98 "sbtest25", generate_warning=generate_warning@entry=true) at mysql-5.7.22/sql/handler.cc:2586
#18 0x0000000000d0a6af in mysql_rm_table_no_locks (thd=thd@entry=0x7f9d7c1f6910, tables=tables@entry=0x7f9d7c00dfe0, if_exists=true, drop_temporary=false, drop_view=drop_view@entry=false, dont_log_query=dont_log_query@entry=false) at mysql-5.7.22/sql/sql_table.cc:2546
#19 0x0000000000d0ba58 in mysql_rm_table (thd=thd@entry=0x7f9d7c1f6910, tables=tables@entry=0x7f9d7c00dfe0, if_exists=<optimized out>, drop_temporary=<optimized out>) at mysql-5.7.22/sql/sql_table.cc:2196
#20 0x0000000000c9d90b in mysql_execute_command (thd=thd@entry=0x7f9d7c1f6910, first_level=first_level@entry=true) at mysql-5.7.22/sql/sql_parse.cc:3589
#21 0x0000000000ca1edd in mysql_parse (thd=thd@entry=0x7f9d7c1f6910, parser_state=parser_state@entry=0x7f9de01107a0) at mysql-5.7.22/sql/sql_parse.cc:5582
#22 0x0000000000ca2a20 in dispatch_command (thd=thd@entry=0x7f9d7c1f6910, com_data=com_data@entry=0x7f9de0110e00, command=COM_QUERY) at mysql-5.7.22/sql/sql_parse.cc:1458
#23 0x0000000000ca4377 in do_command (thd=thd@entry=0x7f9d7c1f6910) at mysql-5.7.22/sql/sql_parse.cc:999
#24 0x0000000000d5ed00 in handle_connection (arg=arg@entry=0x10b8e910) at mysql-5.7.22/sql/conn_handler/connection_handler_per_thread.cc:300
#25 0x0000000001223D74 in pfs_spawn_thread (arg=0x10c48f40) at mysql-5.7.22/storage/perfschema/pfs.cc:2190
#26 0x00007fa003eeddc5 in start_thread () from /lib64/libpthread.so.0
#27 0x00007fa002aab74d in clone () from /lib64/libc.so.6

解决办法

为buf_read_ibuf_merge_pages、buf_read_page_low、fil_io新增一个参数ignore_missing_space。表示忽略正在删除的space,默认为false,当ibuf_merge_pages调用的时候置为true。在fil_io报错处额外判断该参数是否为true,是则不报错,继续其他流程。

或者直接在buf_read_ibuf_merge_pages调用buf_read_page_low时传入IORequest::IGNORE_MISSING参数。

具体代码参考MariaDB commit:8edbb1117a9e1fd81fbd08b8f1d06c72efe38f44

影响版本

察看相关信息,这个问题是修改Bug#19710564时删除表空间版本引入的。

  • MySQL CommUnity Server 5.7.6引入,版本5.7.22尚未修复,版本8.0.0已修复。

  • MariaDB Server 10.2受影响。MariaDB Server 10.2.9, 10.3.2已修复

优化建议

优化一下性能:在buf_read_ibuf_merge_pages中记录下出错的space id,循环的时候判断下一个page的space id,如果space id是相同的,直接删除对应ibuf的记录(当前分配的最大space id记录在系统表空间,space id占4个字节,低于0xFFFFFFF0UL,分配时读取系统表空间保存的值,然后加一,具有唯一性)。

end:对于知识点我就介绍到这里了,写的有点快,可能有不足之处,还望多多交流指正,希望能帮到大家。

感谢各位的阅读!看完上述内容,你们对MySQL中I/O出现错误问题原因是什么大概了解了吗?希望文章内容对大家有所帮助。如果想了解更多相关文章内容,欢迎关注编程网数据库频道。

您可能感兴趣的文档:

--结束END--

本文标题: MySQL中I/O出现错误问题原因是什么

本文链接: https://lsjlt.com/news/52292.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • MySQL中I/O出现错误问题原因是什么
    MySQL中I/O出现错误问题原因是什么?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!问题现象最近使用sysbench测试...
    99+
    2024-04-02
  • MySQL删除表时I/O错误的原因分析与解决
    问题现象 最近使用sysbench测试MySQL,由于测试时间较长,写了一个脚本按prepare->run->cleanup的顺序在后台跑着。跑完后察看日志发现一个问题,MySQL服务的错误日...
    99+
    2024-04-02
  • MySQL出现“Lock wait timeout exceeded”错误的原因是什么?
    1. 概述 在本教程中,我们将讨论MySQL中的“Lock wait timeout exceeded(锁等待超时)”错误。我们将讨论导致这个错误的原因以及MySQL锁的一些细微差别。 为了简单起见,...
    99+
    2023-09-02
    mysql 数据库
  • php出现500错误的原因是什么
    本文小编为大家详细介绍“php出现500错误的原因是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“php出现500错误的原因是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。php出现500错误的原因:1...
    99+
    2023-06-29
  • Linux中直接I/O原理是什么
    这篇文章主要为大家展示了“Linux中直接I/O原理是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux中直接I/O原理是什么”这篇文章吧。什么是缓存 I/O (Buffered I/...
    99+
    2023-06-16
  • DISCUZ 7.0文件上传过程中出现I/O错误!
    关键字描述:出现 错误 过程 上传 文件 目录 图片   问题 头像 如果你的论坛已经打上补丁,但上传头像是仍然出现出现I/O错误解决办法:在网站根目录新建一个 .htaccess 文件 内容:<If...
    99+
    2022-06-12
    出现 错误 过程 上传 文件 目录 图片 头像 问题 已经
  • 出现MySQL server has gone away这个错误的原因是什么
    本篇内容主要讲解“出现MySQL server has gone away这个错误的原因是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“出现MySQL se...
    99+
    2024-04-02
  • php出现403错误是什么原因?怎么解决?
    PHP 403是指在使用PHP程序开发网站时,访问某个页面或目录时出现了“禁止访问”的错误。通常情况下,这种错误可能是由于服务器或网站配置不当所导致的,而在进行网站开发的时候,更是显示频繁的错误。既然出现了PHP 403错误,那我们就需要了...
    99+
    2023-05-14
    403错误 php
  • linux中出现make:arm-linux- conmand not found错误的原因是什么
    这篇文章主要为大家展示了“linux中出现make:arm-linux- conmand not found错误的原因是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“linux中出现make...
    99+
    2023-06-13
  • MySQL出现"Lock wait timeout exceeded"错误的原因是什么详解
    目录1. 概述2. 在mysql中的锁3. 隔离级别4. 监控4.1. InnoDB 状态4.2. 进程列表4.3. Select语句5. 测试设置6. 测试场景6.1. 行锁6.2. 检查数据锁表中的行锁6....
    99+
    2023-05-23
    lock wait timeout exceeded mysql lock wait
  • jsp出现500错误的原因及解决方法是什么
    JSP(Java Server Pages)出现500错误通常是由以下原因引起的:1. 语法错误:JSP页面中存在语法错误,比如拼写...
    99+
    2023-08-19
    jsp
  • php出现403错误的原因是什么及如何解决
    这篇文章主要介绍“php出现403错误的原因是什么及如何解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“php出现403错误的原因是什么及如何解决”文章能帮助大家解决问题。PHP 403是指在使用...
    99+
    2023-07-05
  • c++中EnterCriticalSection出错的原因是什么
    在C++中,EnterCriticalSection函数用于进入一个临界区,并锁定该临界区,防止其他线程进入临界区。如果EnterC...
    99+
    2023-08-08
    c++
  • mysql出现ERROR 1130错误问题怎么办
    这篇文章给大家分享的是有关mysql出现ERROR 1130错误问题怎么办的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 一直使用本机的mysql, 将迁移到服务器上,报错:...
    99+
    2024-04-02
  • mysql中出现索引失效的原因是什么
    这篇文章将为大家详细讲解有关mysql中出现索引失效的原因是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。最佳左前缀原则——如果索引了多列,要遵守最左前缀原则。指的是查询要从索引的最左前...
    99+
    2023-06-08
  • 解决mysql出现1290错误的问题
    解决mysql出现1290错误的问题?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!mysql 出现1290错误的解决办法:...
    99+
    2024-04-02
  • 记一次 MySQL出现“Lock wait timeout”错误的原因
    先说原因: 手动开启事务,由于处理业务时间过长,既不提交也未报错回滚,长时间占用事务就会出现这种情况,错误 关键字:trx_state为 running 故障场景:在测试环境中,在修改订单中偶现Lock wait timeout,且一直重复...
    99+
    2023-08-20
    mysql 数据库 java
  • 如何解决mysql出现10055错误问题
    这篇文章主要介绍如何解决mysql出现10055错误问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!mysql出现10055错误的解决办法:首先查一下netstat有多少连接和等待...
    99+
    2024-04-02
  • MySQL连接出现挂死的原因是什么
    MySQL连接出现挂死的原因是什么?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。架构首先,本系统以 MySQL 作为主要的数据存储部件。整一个是典型的微服务架构...
    99+
    2023-06-15
  • 服务器出错的原因是什么
    服务器出错的原因可能有很多种,包括但不限于: 软件错误:服务器软件或应用程序出现bug或错误导致服务器崩溃或无法正常工作。 硬件故...
    99+
    2024-04-24
    服务器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作