MySQL数据表在高并发访问下可能会出现死锁的问题,导致表锁定不能访问。死锁的产生需要同时满足四个条件:互斥、占有、不可剥夺以及循环等待。出现死锁时,可以通过以下方式处理:
- 超时机制:在访问表时设置锁定超时时间,如果在超时时间内无法获取锁,会报错。我们可以捕获错误并重试。
- 锁定顺序:按照事先规定的顺序锁定表,避免循环锁定的产生,预防死锁。
- 锁定范围:尽可能缩小锁定范围,例如锁定行而非表。行锁定的并发能力更强,死锁概率更小。
- 事务隔离级别:将隔离级别设置为READ COMMITTED,避免脏读造成的死锁。
1、查询是否锁表
show OPEN TABLES where In_use > 0;
查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
2、查询进程
show processlist ;
id #ID标识,要kill一个语句的时候很有用
use #当前连接用户
host #显示这个连接从哪个ip的哪个端口上发出
db #数据库名
command #连接状态,一般是休眠(sleep),查询(query),连接(connect)
time #连接持续时间,单位是秒
state #显示当前sql语句的状态
info #显示这个sql语句
查询到有锁死的表的id
发现进程id为xx的进程状态为Locked
直接mysql> kill id
要清空MySQL数据表数据,可以使用以下SQL语句:
- TRUNCATE TABLE:
TRUNCATE TABLE table_name;
TRUNCATE TABLE会清空表数据,但表结构、索引、约束等不变。
2. DELETE:
DELETE FROM table_name;
DELETE可以根据WHERE条件删除部分数据,不指定WHERE条件将删除所有数据。
3. DROP TABLE + CREATE TABLE:
DROP TABLE IF EXISTS table_name;
CREATE TABLE table_name();
删除表后重新创建,这会删除表数据同时重置表结构。
总结:
- 为避免死锁,可以设置锁定超时、按顺序锁定、减小锁定范围以及使用适当隔离级别。
- 死锁检测与移除可以由数据库自动完成,我们也需要在设计上做好预防措施。
- 清空表数据可以使用TRUNCATE TABLE无条件删除、DELETE条件删除或DROP TABLE重建表。
- TRUNCATE TABLE与DELETE只删除数据不影响表结构,DROP TABLE会重置表结构。
- 在高并发下,TRUNCATE TABLE具有更高性能,DELETE次之,DROP TABLE代价最大。