运维类问题

登录不上云数据库 RDS 数据库如何排查?

  • Ping 云数据库 RDS 域名是否可通;
  • 账号、密码是否有误;
  • 白名单授权是否正确;
  • 连接数是否打满;
  • 如果返回错误提示如端口不可达(110、111、104错误码),请提交工单。

如何进行实例重启?

当云数据库 RDS 内存使用过高时或修改了mysql参数时需要进行实例重启。登录控制台进入实例的“基本信息”页面,点击右上角的“重启实例”,即可对实例执行重启操作。

如何修改 MySQL 系统参数?

登录控制台进入实例的“参数配置”页签,对需要修改的参数进行编辑修改。部分参数可以不重启立即生效,部分参数需要重启后生效,是否需要重启参见页签内的描述。

升配和降配有什么要求和影响?

  • 升配和降配支持情况:

    变配类型 预付费 后付费 内存 磁盘 实例状态
    升配 随时 随时 支持 支持 运行中
    降配 到期后支持 随时 支持 不支持 运行中
  • 执行时间:与实例数据量相关,数据量平均传输速度为100G/半小时。

  • 对服务影响:和升级过程写情况相关,会出现短暂停写,建议流量低峰期进行。

如何扩展实例?

  • 创建只读实例,扩展读。
  • 创建代理实例,实现读写分离、负载均衡和连接池。
  • 创建分布式数据库,扩展写和单机容量限制。

如何恢复数据库?

注意:数据库恢复会覆盖数据且无法恢复,且恢复期间数据库服务会中断,请用户谨慎操作。

  • 登录控制台进入实例的“备份”页签,选择要恢复的备份后面的“恢复”链接,开始恢复任务,恢复时长取决于备份文件大小。
  • 建议用户使用克隆实例功能恢复数据库,详情操作可参见克隆实例

如何迁移数据,如将自建数据库同步到云数据库 RDS 上?

百度智能云提供DTS服务帮助实现数据迁移。数据迁移的详细操作请参见数据迁移

错误信息提示“Too many connections in ...”如何处理?

该错误信息表示数据库的连接数打满,首先排查连接数打满原因是业务增长还是SQL阻塞:

  • 如果是业务增长:建议升级套餐或扩展实例。
  • 如果为SQL阻塞:找到导致阻塞的SQL,控制并发或SQL优化。

CPU达到 100% 或迅速飙升如何处理?

首先查看是否存在大量慢查询,找到数量最多的慢查询并进行SQL优化。

为什么数据库写入帐号突然变成只读了?

  • 产生原因:磁盘配额满了。为防止本地磁盘写满,去掉了部分写权限。
  • 如何处理:1.删除无用数据释放资源;2.升级磁盘配额。
  • 如何避免:添加磁盘报警监控。

数据库使用量如何计算?

数据库使用量包含Ibdata文件+数据文件,不包括binlog和全日志。

云数据库 RDS binlog 数据占用磁盘空间么,默认会保留几天?

binlog 数据占用磁盘空间,本地默认保留7天的 binlog。

为什么只读实例数据有延迟?

  • 产生原因:主库并发写入,从库串行同步;造成从库同步速度慢于主库写入速度。
  • 造成影响:读写分离后,在只读实例上查不到更新数据。
  • 如何避免:控制主库写入并发(TPS不宜超过2000),从库配置不低于主库。

云数据库 RDS 默认隔离级别如何修改?

云数据库 RDS 默认隔离级别是REPEATABLE-READ,不能修改默认事务隔离级别,也不能修改GLOBAL事务隔离级别。

使用云数据库 RDS 执行数据迁移,为什么迁移后的数据都是乱码?

请检查目标云数据库 RDS 数据库和源自建数据库的字符集信息,通常此类问题是由于不同的字符集造成迁移数据时发生强制转码导致的。解决问题的方法是,创建与源数据库相同字符集的目标数据库后再次执行数据迁移。

数据库 MySQL 表名都是大写但是导入云数据库 RDS 后表名都是小写,怎么处理?

如果在实例的“参数设置”中设置了“lower_case_table_names”即表名大小写敏感会出现这种情况。需要修改该参数取值并重新导入云数据库 RDS 。参数取值解释如下:

参数值 解释
0 使用CREATE TABLE或CREATE DATABASE语句指定的大小写字母在硬盘上保存表名和数据库名。名称对大小写敏感。在大小写不敏感的操作系统如windows或Mac OS x上我们不能将该参数设为0,如果在大小写不敏感的文件系统上将--lowercase-table-names强制设为0,并且使用不同的大小写访问MyISAM表名,可能会导致索引破坏。
1 表名在硬盘上以小写保存,名称对大小写不敏感。在存储和查找表上MySQL将所有表名转换为小写。该行为也适合数据库名和表的别名,该值为Windows的默认值。
2 表名和数据库名在硬盘上使用CREATE TABLE或CREATE DATABASE语句指定的大小写字母进行保存,但MySQL在查找表时将它们转换为小写。名称对大小写不敏感,即按照大小写来保存,按照小写来比较。注释:只在对大小写不敏感的文件系统上适用! innodb表名用小写保存。

MySQL 通过 delete 方法删除数据后空间无法释放,怎么处理?

MySQL中的数据表在使用delete操作删除数据之后,磁盘空间是无法直接释放的,delete之后会在数据表中产生数据空洞,新来的数据可以复用部分空间,如果需要立刻释放磁盘空间,需要进行表整理或重建表。

  1. 直接通过sql语句释放空间
    方法一:执行OPTIMIZE TABLE 'table_name',实现表空间的释放
    方法二:查看表的存储引擎,重建表,如InnoDB表执行ALTER TABLE 'table_name' ENGINE = InnoDB

  2. 通过页面控制台释放空间

1)选择云数据库 RDS 实例中的数据库管理工具

2)进入管理工具页面

3)点击需要释放空间的表

4)点击操作

5)点击整理表碎片或优化表

怎么确保 MySQL 字符集无乱码?

数据库相的字符集相关设置,是用户在使用数据库的过程当中需要慎重考虑的一点。

可以通过执行下面这条命令,了解到字符集相关的配置:

mysql> show variables like '%character%';

当客户端连接服务器的时候,会将自己想要的字符集发给mysql服务器,随后服务器会使用这个字符集去设置character_set_client、character_set_connection、character_set_results这三个值;此外客户端也可以通过执行set names XX,来对这三个值进行赋值。

  1. 如何保证写入正确?

    确保将要写入的数据实际字符集,character_set_client和该字段字符集三者保持一致;一些情况下,只需要保证前两者一致即可,mysql会对客户端字符集与字段字符集做转化,大部分情况下,utf8可以和gbk进行正常转化,但有无法转化而丢失字符的情况出现,因此推荐用户自行确保三个字符集保持一致。

  2. 如何保证读取正确?

    在数据被正确写入的前提下,保证客户端字符集与数据所在的字段字符集一致即可。

  3. 读到乱码应该怎么办?

    在2的前提下,仍然读到乱码,可以推测出数据的实际存储与字段的字符集出现了不一致,也就是写入时就引入了问题。这个时候需要首先确定数据的实际存储字符集是否正确;对乱码的字段使用mysql的hex()函数,可以查看到字段的实际存储;以中文为例,一个utf8字符(汉字)占用3个字节,如下:

    mysql> select hex('我们');
    +---------------+
    | hex('我们') |
    +---------------+
    | E68891E4BBAC  |
    +---------------+
    

    一个gbk汉字则占用2个字节,如下:

    mysql> select hex('我们');
    +-------------+
    | hex('我们') |
    +-------------+
    | CED2C3C7    |
    +-------------+
    1 row in set (0.00 sec)
    

    实际情况包括中英文混排等情况,较为复杂。

    确认了数据的实际存储结构之后,可以通过hex()导出数据,以unhex导入的方式,完成乱码的修复。

GTID 使用限制

GTID(Global Transaction Identifier)为全局事物ID,是Master上为每个事务分配的唯一的标识符,在一个Master/Slave的复制拓扑结构中依然具有唯一性。GTID的构成如下:

GTID = source_id:transaction_id
source_id一般为server_id,transaction_id是一个由1递增的序列号。
GTID最显著的优势为,在基于GTID的Master/Slave复制场景下,CHANGE MASTER TO无需指定同步点(MASTER_LOG_FILE/MASTER_LOG_POS)即可进行“自动”复制。
但要注意,基于GTID的复制模式不支持以下场景:

  • 事务中包含对非事务型引擎表的更新

    当在一个事务中混合对事务型引擎表的更新和非事务型引擎表的更新,会导致赋予这个事务多个GTID。

  • CREATE TABLE … SELECT语句

    对于基于语句的复制(statement-based replication),CREATE TABLE … SELECT是不安全的。
    对于基于行的复制(row-based replication),这个语句被记录为两个事件(event),一个是创建表,另一个是从源表中导入数据到刚刚创建的表。当在事务中执行这个语句时,存在某些场景使得这两个事件有一样的事务标识符,导致在Slave中“导入数据”过程被跳过。

  • 临时表

    CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE 不支持在基于GTID的复制模式下使用。只可以临时表的操作放在事务外,并且使得参数autocommit=1。

错误信息提示“The table 'XXXX' is full”如何处理?

在使用云数据库 RDS 的过程中,有时会碰到这样的出错信息:
The table 'XXXX' is full

  1. 出现这种错误的原因

    MySQL在进行聚合类操作(group by,count(distinct)等)、排序类操作(order by,distinct等)、union、group_concat、子查询或者多表关联时,可能会使用内部临时表。首先使用内存临时表,如果需要的内存超过了tmp_table_size、max_heap_table_size设定的内存,它就会把内存临时表转化为磁盘临时表,存储在tmpdir变量标示的目录下(当查询涉及到Blob或Text类型字段,MySQL会跳过内存临时表的步骤,而直接使用磁盘临时表)。
    受限于物理磁盘的可用空间,当空间不足时,磁盘临时表对应的物理文件无法继续扩展,就会报告这类错误。
    对应这种错误,查看“监控”中的“磁盘使用率”监控项,可能会看到磁盘瞬间打满的情况(打满情况和监控采样数据的频率有关,监控项可能无法采样到瞬间打满的情况)。

  2. 对于这种错误的跟进,处理方法

    • 在查询中,尽量避免使用Blob和Text类型字段。
    • 优化查询逻辑,避免过大的中间结果集操作。比如说通过合理的使用索引优化该类查询,避免使用临时表等。
  3. 如何确认查询使用了内部临时表

    使用explain查看执行计划,如果执行计划的Extra部分出现了Using temporary,可以说明查询使用了内部临时表。

MySQL 的事务执行时间较长,怎么处理?

概念

MySQL大事务指MySQL的事务执行时间较长,例如如下事务执行1000秒:

BEGIN;
SELECT sleep(1000);
COMMIT;

影响

  • 大事务对MySQL的影响:大事务期间,MySQL性能下降,可能引起MySQL的连接数上涨、慢查询增多、锁等待增加、CPU及内存使用率过高等问题。
  • 大事务对用户影响:读写访问变慢、访问超时报错、甚至不可用的风险。

起因

  • 开启了事务,但由于程序问题一直未提交事务,使得这个事务耗时较久;也会因为这个事务产生的锁表,导致其他事务发生锁等待而变成大事务;
  • DDL语句:大表的DDL语句会使得DDL SQL执行耗时较长,例如100G的表做加字段操作,会产生至少100分钟的大事务;
  • 低效率的SQL语句:读写语句影响行数较多、联表查询、未按照索引的大量数据查询,都是低效率的SQL,都容易产生大事务。

处理

用户应尽量避免大事务,比如开启了事务及时提交、上线之前在线下测试是否存在低效率的SQL、DDL语句、尽量在业务低峰期操作。

如果大事务产生了,该如何处理,以下为处理方案:

  • 终止会话,即kill掉大事务
    通过show process list查找对应事务,得到进程id号(第一列),例如id=202020;执行kill 202020

  • 开启事务自动提交
    开启自动提交:执行set autocommit = 1
    若需关闭自动提交:执行set autocommit = 0

  • 设置最大事务时间
    若设置事务最长执行100秒,则执行如下命令:

    set global wait_timeout=100;
    set global interactive_timeout=100;
    

MySQL CPU 负载较高的原因和处理方法

MySQL CPU高可能是SQL不合理或者没有合适索引,导致rows_read过高;也可能是QPS非常高,或者热点数据读写导致锁争用等。

CPU使用率过高现象:

原因:

  1. 应用负载高
    有的表数据量不大,但是读写频率繁过高,并发量也很大(比如,热点数据),容易导致PCU使用率高。

  2. 查询执行成本高
    数据集当前运行的QPS不高,但存在查询执行效率低、执行需要扫描大量表中的数据,即,存在慢查询SQL。

解决方法:

  1. 使用show processlist语句,查找负荷较重的SQL语句,对该语句进行优化,如建立适合的索引。
  2. 打开慢查询配置,找到对性能有影响的SQL语句,然后使用EXPLAIN,找出相应的优化方案。
  3. 在高并发情况下,是否可以添加缓存,如memcache/redis之类的,以缓解db的压力。
  4. 修改数据集架构,适当添加从库,改善对热点数据的频繁读操作。
  5. 查看tmp_table_size、max_heap_table_size的大小是否偏小,如果允许,适当增大表;
    MySQL的配置文件中,tmp_table_size的默认大小是32M,如果一张临时表超出该大小,MySQL将会产生一个The table tbl_name is full形式的错误;如果业务需要做很多高级group by查询,可以增加 tmp_table_size值。
  6. 对WHERE、JOIN、MAX()、MIN()、ORDER BY等子句条件判断中用到的字段,应该根据其建立索引INDEX。
    索引被用来快速找出在一列上用特定值的行。没有索引,MySQL不得不首先以第一条记录开始并读完整个表直到找出相关的行。表越大,花费时间越多。如果表对于查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要遍历所有数据。如果一个表有1000行,这比顺序读取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。
  7. 定时优化文件及索引,就MYSQL官方建议,一周或一月左右优化一次。

避免出现cpu使用高的准备:

  1. 提前使用压测工具,对新上线功能、模块进行压测;
  2. 应用设计与开发过程中,尽量遵守云数据库 RDS for MySQL 优化的原则,降低查询的逻辑IO,提高扩展性。

云数据库 RDS for MySQL Metadata lock 的产生和处理方法

1、 Metadata lock的含义和作用

在5.5版本,MySQL 引入了 Metadata lock 用于在并发环境中维护表结构的一致性,自 5.5 版本后一直沿用至今。

Metadata lock 是表结构的互斥锁。当事务对表结构进行修改(alter table)、删除(drop table)等操作前,需要获得Metadata lock才能执行。如果当前表上有未提交的事务,则该事务将持有 Metadata lock,对表结构进行修改和删除的事务需要等待未提交事务提交后才能获得Metadata lock。

Metadata lock 解决了两个问题:

  • 事务隔离问题。当云数据库 RDS for MySQL 处于 Repeatable read 隔离级别时,事务A对同一个表进行两次查询,事务B要修改表结构,Metadata lock 保证了A的两次查询结果一致。
  • 主从同步问题。未引入 Metadata lock 之前,事务A向表中插入数据,事务B要删除表,若事务B先提交,则 binary log 会先记录删除操作,后记录插入操作。当从库执行 relay log 中的操作时会出错。

2、 Metadata lock 相关的常见操作

需要获得 Metadata lock 才能执行的操作如下

  • 修改表结构(alter table)
  • 删除表(drop table)
  • 增加/删除索引(alter table add/drop index,create/drop index)
  • 维护表操作(optimize/repair table)
  • 获得表级写锁(lock table tblname write)

如下图,通过 show processlist; 命令可以看到等待Metadata lock的会话。

当某一事务持有Metadata lock时,该表将被阻塞读写,后续对该表的读写操作将被迫等待锁。因而如果使用不当,可能会对RDS用户造成巨大损失。

下面介绍了使用云数据库 RDS 遇到 Waiting for table Metadata lock 的常见问题及解决办法。

3、 云数据库 RDS 上事务处于 Waiting for table Metadata lock 的常见问题

  • 表上存在长时间查询;
  • 表上存在未提交或回滚的事务;
  • 表上有失败的查询事务,且该事务未提交或回滚。

4、 解决方案

1) 使用show processlist; 命令查看长时间查询;

然后使用kill命令终止该查询会话

2) 使用如下语句从 MySQL 中查询持有该表metadata lock的未提交/回滚的事务。

select i.trx_mysql_thread_id metadata_lock_thread_id from information_schema.innodb_trx i, (select id, time from information_schema.processlist where time = (select max(time) from information_schema.processlist where state = 'Waiting for table metadata lock' and substring(info, 1, 5) in ('alter' , 'optim', 'repai', 'lock ', 'drop ', 'creat'))) p where timestampdiff(second, i.trx_started, now()) > p.time and i.trx_mysql_thread_id  not in (connection_id(),p.id);

直接将上述SQL语句粘贴运行,可得如下结果:

执行kill 语句即可关闭该会话

3) 第三种情况可视为第一种情况的特例,但由于失败查询在执行前就返回,因而不会有查询正在执行,因而前述的show processlist;和 information_schema.innodb_trx 表中都无法找到相关信息。

此时,可使用下面的 SQL 语句查询持有metadata lock的会话ID。

select p1.id metadata_lock_thread_id from information_schema.processlist p1, (select id, time from information_schema.processlist where time = (select max(time) from information_schema.processlist where state = 'Waiting for table metadata lock' and substring(info, 1, 5) in ('alter' , 'optim', 'repai', 'lock ', 'drop ', 'creat', 'trunc'))) p2 where p1.time >= p2.time and p1.command in ('Sleep' , 'Query') and p1.id not in (connection_id() , p2.id);

执行结果如下图:

执行kill语句关闭该会话

5、 避免Metadata lock影响业务的注意事项

1) 在业务低峰期执行第2节的操作,比如修改/删除表、创建/删除索引。

2) 显式打开会话自动提交。在到云数据库 RDS 的数据库连接建立后,执行 set autocommit=1; 或 set autocommit=on;

3) 设置SQL语句的锁等待超时参数,避免长时间等待元数据锁影响表上其他业务查询。比如 set lock_wait_timeout=30; 命令可以设置 metadata lock wait 的最长时间为 30 秒。

4) 使用事件来终止长时间运行的事务,比如下面的SQL语句会终止执行时间超过30分钟的事务。

create event my_long_running_trx_monitor
    on schedule every 30 minute
    starts '2016-01-01 00:00:00'
    on completion preserve enable do
    begin
      declare v_sql varchar(500);
      declare no_more_long_running_trx integer default 0;
      declare c_tid cursor for
        select concat ('kill ',trx_mysql_thread_id,';')
        from information_schema.innodb_trx
        where timestampdiff(minute,trx_started,now()) >= 60;
      declare continue handler for not found
        set no_more_long_running_trx=1;
      open c_tid;
      repeat
        fetch c_tid into v_sql;
    set @v_sql=v_sql;
    prepare stmt from @v_sql;
    execute stmt;
    deallocate prepare stmt;
      until no_more_long_running_trx end repeat;
      close c_tid;
    end;

云数据库 RDS MySQL InnoDB锁分析

背景

关系型数据库中事务的隔离性是通过锁(Lock)来实现的。通常来说,锁可以分为读锁(也称为共享锁)和写锁(也称为互斥锁)两种类型。读锁可以与读锁兼容,而写锁不能与任何类型的锁兼容,也就是说当一个事务获取一个数据库对象的读锁之后,另一个事务也可以获取对该对象加读锁,但是不能加写锁。在出现锁冲突时,通常来说,后发起锁请求的事务会进入锁等待状态;一旦等待达到设置的超时时间,则该事务会由于等待超时而被回滚。

MySQL InnoDB引擎中的锁在遵循上述规则的同时,出于性能优化和提升并发度的考虑,对锁处理进行了优化,一方面通过实现行及锁,使事务的并发度最大化;另一方面通过使用MVCC(Multiple Version Concurrent Control,多版本并发控制)技术,使得读锁和写锁能够兼容,从而减少事务之间的锁等待。

InnoDB 中的锁超时配置

InnoDB中事务锁等待的超时时间通过系统配置参数innodb_lock_wait_timeout来指定,要查看和该参数的值,可以通过云数据库 RDS 的控制管理页面的“参数配置”页面来设置,也可以通过MySQL客户端执行如下命令:

mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50    |
+--------------------------+-------+
1 row in set (0.00 sec)

mysql> set global innodb_lock_wait_timeout = 100;
Query OK, 0 rows affected (0.00 sec)

mysql> set session innodb_lock_wait_timeout = 100;
Query OK, 0 rows affected (0.00 sec)

而该参数的默认值是50,单位是秒,也就是说,在默认情况下事务在等待写锁的时候,最多等50秒,如果在50秒之后还未能获取该锁,那么该事务会被回滚,应用程序将得到如下的错误消息:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
一般来说,应用程序对于该错误的处理应该是重试事务。正常情况下,该默认锁超时时间不易达到,因此不应出现大量锁超时和重试。如果应用程序中确有执行时间超过该超时时间且带有写入操作的事务,则建议对应用程序进行优化,尽量缩短事务执行的时间,避免长时间持有写锁。

锁超时的处理

如果系统中持续发生了大量的等待和超时,则需要定位长时间持有写锁的事务,并考虑将其结束执行。要列出当前InnoDB中的锁等待的情况,可以执行如下SQL语句:

select l.* from
    (select 'Blocker' role, p.id, p.user,
            left(p.host, locate(':', p.host) - 1) host,
            tx.trx_id, tx.trx_state, tx.trx_started,
            timestampdiff(second, tx.trx_started, now()) duration,
            lo.lock_mode, lo.lock_type, lo.lock_table, lo.lock_index,
            tx.trx_query, lw.requested_lock_id Blockee_id,
            lw.requesting_trx_id Blockee_trx
      from information_schema.innodb_trx tx,
           information_schema.innodb_lock_waits lw,
           information_schema.innodb_locks lo,
           information_schema.processlist p
      where lw.blocking_trx_id = tx.trx_id
        and p.id = tx.trx_mysql_thread_id
        and lo.lock_id = lw.blocking_lock_id
      union
      select 'Blockee' role, p.id, p.user,
          left(p.host, locate(':', p.host) - 1) host,
          tx.trx_id, tx.trx_state, tx.trx_started,
          timestampdiff(second, tx.trx_started,
          now()) duration, lo.lock_mode, lo.lock_type,
          lo.lock_table, lo.lock_index, tx.trx_query,
          null, null
      from information_schema.innodb_trx tx,
           information_schema.innodb_lock_waits lw,
           information_schema.innodb_locks lo,
           information_schema.processlist p
      where lw.requesting_trx_id = tx.trx_id
        and p.id = tx.trx_mysql_thread_id
        and lo.lock_id = lw.requested_lock_id)
l order by role desc, trx_state desc;

该SQL的执行结果参考输出如下:

通过该输出,可以结束role为Blocker的事务,使其占用的互斥锁得到释放,其他role为Blockee的事务获取所需的互斥锁。要结束指定的事务,可以在MySQL客户端中使用kill connection命令:

mysql> kill connection 2;
Query OK, 0 rows affected (0.00 sec)

如果在结束长时间占有互斥锁的事务后,仍有大量事务出现锁等待超时,则考虑优化应用程序中的处理逻辑,减少事务持有互斥锁时间;同时对数据库进行优化,提高SQL执行速度。如果还无法解决该问题,请联系在线技术支持。

MySQL MyISAM 引擎锁分析

背景

MyISAM是MySQL中最古老的存储引擎之一,由于该引擎出现的早,因此有很多的先天缺陷和不足,其中最明显区别于InnoDB存储引擎的缺点是:

  • 不支持事务
  • 只支持行级锁

目前版本的MySQL中,如无特殊理由,则表都应该使用InnoDB,而不是用MyISAM表。然而考虑到向前兼容,目前仍有部分用户表的存储引擎是MyISAM。

由于MyISAM存储引擎只支持表级锁,对表中数据进行的任何操作都会对整张表加锁;同时由于MyISAM存储引擎没有类似于InnoDB中的MVCC技术,使得MyISAM表上的读锁和写锁不兼容。

MyIsam 中的锁超时设置

与InnoDB不同,MyISAM引擎中没有相应的lock_wait_timeout配置参数。也就是说,当一个事务在等待一张MyISAM表上的锁时,会无限等待。相应的,这时候应用程序会表现为挂起。因此,在使用MyISAM表类型的应用程序中,应该设有等待超时机制,防止程序被无限挂起。

MyISAM 中锁等待的处理

当使用MyISAM类型表的应用程序出现被挂起等待数据返回的情况,可能是由于数据库访问正处于锁等待状态。要检查事务的执行是否正处于锁等待状态,可以通过MySQL客户端运行show processlist命令,相应的输出如下:

由于MyISAM引擎并不支持事务,在SQL语句执行完毕后表级锁会立即释放,因此通常情况下很难出现表级锁被长时间占用。此处,通过一个特定的带有SLEEP的语句来模拟长时间占有MyIS