多语言展示
当前在线:932今日阅读:126今日分享:42

mysql死锁解决方法

使用mysql数据库,在并发加锁的时候不注意,如锁A和锁B,出现锁A等待锁B,锁B又等待锁A的情况,这个时候会引发死锁。一个成熟的数据库,一般都有死锁检测机制,会自动识别死锁的情况。但有时候为了减少死锁检查的性能开销,会选择关闭死锁检测,这个时候如果出现死锁会等待超时才会释放锁的
工具/原料
1

navicat

2

mysql

方法/步骤
1

使用navicat客户端工具连接上测试的mysql数据库,新建一个测试表CREATE TABLE `t_user` (  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',  `login_name` varchar(50) NOT NULL COMMENT '用户名',  `pwd` varchar(50) NOT NULL COMMENT '密码',  `nick_name` varchar(90) DEFAULT NULL COMMENT '用户昵称',  `usable` int(11) NOT NULL DEFAULT '1' COMMENT '是否可用 0:不可用;1:可用',  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `last_login_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后登录时间',  PRIMARY KEY (`id`),  UNIQUE KEY `login_name` (`login_name`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='用户表';数据如图所示

2

打开一个新的会话窗口,执行以下语句set autocommit=0; --关闭自动提交SELECT * from t_user t where t.id='1' FOR UPDATE; 给id为1的数据行添加行锁

3

打开另一个新的会话窗口,执行以下语句set autocommit=0; --关闭自动提交SELECT * from t_user t where t.id='2' FOR UPDATE; 给id为2的数据行添加行锁

4

这个时候,2和3步骤各持了一把锁。下面开始在会话一执行SELECT * from t_user t where t.id='2' FOR UPDATE; 会出现锁等待的情况

5

在会话二里执行SELECT * from t_user t where t.id='1' FOR UPDATE; 则出现了死锁提示:ERROR 1213 : Deadlock found when trying to get lock; try restarting transactionmysql自动检测到了两个会话互相等待锁的情况,则把最后一个会话做了回滚操作

6

可以通过以下三个语句来查询被打开的表,正在执行的任务列表和开启的事务show OPEN TABLES where In_use > 0;show processlist; -- kill杀死进程id(id列)SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;-- kill杀死进程id(trx_mysql_thread_id列)

注意事项

对于高并发的系统,如果锁控制不好,很容易就会出现死锁,数据库出现死锁会导致应用系统功能无响应,甚至服务崩溃。

推荐信息