千家信息网

常见而严重的MySQL问题有哪些

发表于:2024-11-20 作者:千家信息网编辑
千家信息网最后更新 2024年11月20日,本篇内容介绍了"常见而严重的MySQL问题有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 问
千家信息网最后更新 2024年11月20日常见而严重的MySQL问题有哪些

本篇内容介绍了"常见而严重的MySQL问题有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1 问题回顾和思考

1.1 SQLException: Lock wait timeout exceeded; try restarting transaction,please rollback!

再发生这样的错误时,别很自豪的说数据库出问题了,呼叫DBA ...(uat多次出现)

第一个问题目前发生的原因有:

  1. 磁盘空间满,事务无法提交成功。(磁盘满是一个很危险的操作,会引起binlog写坏,备库无法同步进而需要恢复备库)

  2. 更新事务未正常提交而产生排他锁,造成其他更新事务一直获取不到该锁而事务超时。

1.2 条件查询卡住了,怎么重跑都通不过,怎么办,急死人了(迁移后比对实际出现)。

Truncate table过程中CTRL +C 终止了。 有分片上存在truncate 事务一直存在,进而对该表的所有操作均会超时。

1.3 查询卡住,更新卡住...殊不知,你前面的Alter table都没成功......

DBProxy的问题不在此文讨论,查询事务没有正常提交而占据共享锁时,同样会造成alter table获取不到MDL锁,而造成一直等待。 提示为:Waiting fortable metadata lock (show processlist中可查)。

2 原理详细分析

2.1 什么是MDL锁?

为了在并发环境下维护表元数据的数据一致性,在表上有活动事务(显式或隐式)的时候,不可以对元数据进行写入操作。因此从MySQL5.5版本开始引入了MDL锁(metadata lock),来保护表的元数据信息,用于解决或者保证DDL操作与DML操作之间的一致性。

对于引入MDL,其主要解决了2个问题,一个是事务隔离问题,比如在可重复读隔离级别下,会话A在2次查询期间,会话B对表结构做了修改,两次查询结果就会不一致,无法满足可重复读的要求;另外一个是数据复制的问题,比如会话A执行了多条更新语句期间,另外一个会话B做了表结构变更并且先提交,就会导致slave在重做时,先重做alter,再重做update时就会出现复制错误的现象。

所以在对表进行上述操作时,如果表上有活动事务(未提交或回滚),请求写入的会话会等待在Metadata lock wait 。例如下面的这种情形:

若没有MDL锁的保护,则事务2可以直接执行DDL操作,并且导致事务1出错,5.1版本即是如此。5.5版本加入MDL锁就在于保护这种情况的发生,由于事务1开启了查询,那么获得了MDL锁,锁的模式为SHARED_READ,事务2要执行DDL,则需获得EXCLUSIVE锁,两者互斥,所以事务2需要等待。

注:支持事务的InnoDB引擎表和不支持事务的MyISAM引擎表,都会出现Metadata Lock Wait等待现象。一旦出现Metadata Lock Wait等待现象,后续所有对该表的访问都会阻塞在该等待上,导致连接堆积,业务受影响。

MySQL的设计:在设置的autocommit=0;read_commited的时候,无论session的第一条语句是select还是dml,都开始一个事务,然后直到commit,所持有的MDL锁也一直维持到commit结束。

Oracle的设计:在session的第一条更新语句发起时,才创建transaction,在读多的系统上,减少了阻塞的发生可能性。特别是在开发人员发起select语句时,认为没有更新,就不再commit。但在MySQL上,发起select语句,而忘记commit,是非常危险的。

2.2 常见MDL锁场景和详细解释

1)当前有执行DML操作时执行ALTRE操作

2)当前有对表的长时间查询或使用mysqldump/mysqlpump时,使用alter会被堵住

3)显示或者隐式开启事务后未提交或回滚,比如查询完成后未提交或者回滚,使用alter会被堵住

4)表上有失败的查询事务,比如查询不存在的列,语句失败返回,但是事务没有提交,此时alter仍然会被堵住

详细测试解释说明:

1)当前有执行DML操作时执行ALTRE操作

# SESSION Amysql> insert into yetest2 select * from yetest1;# SESSION Bmysql> alter table yetest2 add yeColumn int;   //等待SESSION A执行完;# SESSION Cmysql> show processlist;+-----+------+-------+------+--------------+--------+-----------------------------------------+------------| Id  | User | Host| db  | Command | Time | State                       | Info                              |+-----+------+------+----- +--------------+--------+------------------------------------------+------------| 267 | root | localhost | sbtest | Query   |    7 | Sending data                    | insert into yetest2 select * from yetest1 || 271 | root | localhost | sbtest | Query   |    3 | Waiting for table metadata lock | alter table  yetest2 add yeColumn int         || 272 | root | localhost | NULL   | Query   |    0 | starting                        | show processlist                          |+-----+------+-----------+--------+---------+------+---------------------------------+-------------------------------------------+3 rows in set (0.00 sec) # SESSION Dmysql> select * from yetest2 limit 10;    //等待元数据锁;# SESSION Emysql> show processlist;+-----+------+-------+------+--------------+--------+-----------------------------------------+------------| Id  | User | Host| db  | Command | Time | State                       | Info                              |+-----+------+------+----- +--------------+--------+------------------------------------------+------------| 267 | root | localhost | sbtest | Query   |   20 | Sending data                    | insert into sbtest2 select * from sbtest1 || 271 | root | localhost | sbtest | Query   |   13 | Waiting for table metadata lock | alter table yetest2 add  yeColumn int         || 272 | root | localhost | NULL   | Query   |    0 | starting                        | show processlist                          || 308 | root | localhost | sbtest | Query   |    3 | Waiting for table metadata lock | select * from yetest2 limit 10            |+-----+------+-----------+--------+---------+------+---------------------------------+-------------------------------------------+4 rows in set (0.00 sec)

由于事务1开启了查询,那么获得了MDL锁,锁的模式为SHARED_READ,事务2要执行DDL,则需获得EXCLUSIVE锁,两者互斥,所以事务2需要等待。 查询都能卡住,是不是很郁闷?我们上次迁移就是这种场景,truncate table属于DDL,会lock table metadata,甚至可以可以由锁表升级到锁库。

3)显示或者隐式开启事务后未提交或回滚,比如查询完成后未提交或者回滚,使用alter会被堵住

# SESSION Amysql> begin;mysql> select * from test2;# SESSION Bmysql> alter table test2 add test3 int;   //等待SESSION A执行完;# SESSION Cmysql> show processlist;+-----+------+-------+------+--------------+--------+-----------------------------------------+------------| Id  | User | Host| db  | Command | Time | State                       | Info                              |+-----+------+------+----- +--------------+--------+------------------------------------------+------------| 267 | root | localhost | sbtest | Sleep   |   36 |                                 | NULL                              || 271 | root | localhost | sbtest | Query   |   30 | Waiting for table metadata lock | alter table test2 add test3 int || 272 | root | localhost | NULL   | Query   |    0 | starting                        | show processlist                  |+-----+------+-----------+--------+---------+------+---------------------------------+-----------------------------------+3 rows in set (0.00 sec)

4 ) 表上有失败的查询事务,比如查询不存在的列,语句失败返回,但是事务没有提交,此时alter仍然会被堵住

# SESSION Amysql> begin;mysql> select error from  test2; ERROR 1054 (42S22): Unknown column 'error' in 'field list'# SESSION Bmysql> alter table test2 add test3 int;    //等待SESSION A提交或回滚;# SESSION Cmysql> show processlist;+-----+------+-------+------+--------------+--------+-----------------------------------------+------------| Id  | User | Host| db  | Command | Time | State                       | Info                              |+-----+------+------+----- +--------------+--------+------------------------------------------+------------| 267 | root | local | test |  Sleep   |    7 |                             |NULL              | 271 | root | local | test |  Query   |    3 | Waiting for table metadata lock | alter table test2 add test3 int || 272 | root | local | NULL| Query   |    0 | starting                      | show processlist             | 311 | root | local | NULL | Sleep   |  413 |                            | NULL           +-----+------+-----------+--------+---------+------+-------------------------------------------+--------------4 rows in set (0.00 sec)# SESSION Dmysql> select * from information_schema.innodb_trx;Empty set (0.00 sec)

其实SESSION A中的事务并未开启,但是由于select获取表元数据的语句,语法上是有效的,虽然执行失败了,但是任然不会释放元数据锁,故而导致SESSION B的alter动作被阻塞。

通过SESSION D查看当前打开事务时,你会发现没有,从而找不到原因。所以当出现这种场景时,如何判断是哪个进程导致的呢,我们可以尝试查看表performance_schema. events_statements_current,分析进程状态来进行判断。

mysql> select * from performance_schema. events_statements_current\G*************************** 1. row ***************************              THREAD_ID: 293   EVENT_ID: 32   END_EVENT_ID: 32 EVENT_NAME: statement/sql/select SOURCE: socket_connection.cc:211TIMER_START: 212721717099954000  TIMER_END: 212721717213807000 TIMER_WAIT: 113853000  LOCK_TIME: 0   SQL_TEXT: select error from test2                 DIGEST: 0bbb2d5d1be45e77debea68111264885            DIGEST_TEXT: SELECT ERROR FROM `test2`          CURRENT_SCHEMA: test            OBJECT_TYPE: NULL  OBJECT_SCHEMA: NULLOBJECT_NAME: NULL  OBJECT_INSTANCE_BEGIN: NULLMYSQL_ERRNO: 1054  RETURNED_SQLSTATE: 42S22           MESSAGE_TEXT: Unknown column 'error' in 'field list' ERRORS: 1

然后找到其sid, kill掉该session,也可以kill掉DDL所在的session解决可以解决此问题。

另外,测试时SESSION A要显式开启一个事务,否则查询会隐式回滚结束,无法重现上面的场景。SESSION B执行alter后,没有立即阻塞住,而是立马开始copy to tmp table,这个过程结束后,才进行了MDL锁等待。执行alter操作主要分为创建临时新表->插入老表的数据->临时新表rename to老表三个步骤,在这种情况下,到最后一步才需要MDL锁,所以copy过程中不会阻塞。由于没有查询在进行,而且查询也没有进入innodb层 (失败返回),所以show processlist和information_schema.innodb_trx没有可以参考的信息。

出现以上几种情况时,这个时候如果进行如下操作就会引起MDL:

1.创建、删除索引。

2.修改表结构。

3.表维护操作(optimize table、repair table等)。

4.删除表。

5.获取表上表级写锁 (lock table tab_name write)。

"常见而严重的MySQL问题有哪些"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

事务 查询 问题 数据 语句 更新 阻塞 场景 情况 过程 常见 一致 时候 版本 现象 结构 保护 危险 成功 一致性 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 软件网络安全协议模板 数据库管理员是什么级别 企业服务器的选用 网络技术与管理专业前景 计算机软件开发合同二审在北京吗 徐汇区自动化软件开发推荐咨询 网络安全技术加密实验报告 做软件开发最好选择哪些城市 常熟市网络安全技术支撑 腾讯云服务器环境搭建 甘肃诚信积分管理软件开发公司 Q版的网络安全手抄报 软件开发商 英文翻译 扬州银联软件开发创新服务 金融科技数字互联网 西安嘉宁壹捌网络技术有限公司 网络安全法成立办公室 wp换服务器系统教程 网络安全密码怎么去掉 软件开发价格1 太仓运营网络技术费用是多少 哇嘎的最新服务器 浙江定制软件开发有哪些 汕尾无线软件开发销售厂 第七届网络安全宣传周小结 服务器设计行业 贵广网络技术视频 信用信息数据库模板 虚拟机服务器内存已满怎么办 绿书签行动的网络安全指什么
0