【年薪百万之IT界大神成长之路二】手把手教你开数据库死锁

[catalog]

 
  1. 产生死锁的必要条件
  2. 死锁定理
  3. 遇到死锁怎么办
  4. 解决MySql死锁
  5. 解决Oracle死锁
  6. 主流数据库的区别
  7.【每日一面】乐观锁通常怎么实现?(附实例)
 
 

1.产生死锁的必要条件

  1. 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用。
  2. 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
  3. 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
  4. 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

2.死锁定理

  1. 如果资源分配图中没有环路,则系统没有死锁。
  2. 如果资源分配图中出现了环路,则系统可能有死锁。

3.遇到死锁怎么办

从上面的死锁定理中我们可以知道只要打破死锁的环路就可以解开死锁,以下是处理死锁的两种方法:

  1. 抢占资源:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。
  2. 终止(或撤销)进程:终止或撤销系统中的一个或多个死锁进程,直至打破死锁状态。

4.解决MySql死锁

  • 查看进程列表
    show processlist;
     
    在这里插入图片描述
    当state列为waiting for lock_type lock时,表示某个SQL正在query导致别的SQL等待锁,需要根据id杀进程。

各字段的含义:
1.id 该进程的标识;
2.user 显示当前用户
3.host 显示来源IP和端口
4.db 显示当前连接的数据库
5.command 显示当前连接的执行的命令,休眠 sleep ,查询 query ,连接 connect
6.time 此这个状态持续的时间,单位是秒
7.state 列显示使用当前连接的sql语句的状态,详见下面state列的含义
8.info 显示sql语句,长sql可能显示不全
state列的含义:
1.analyzing 比如进行analyze table时
2.checking table 线程正在执行表检查操作
3.cleaning up 正准备释放内存
4.closing tables 应该是一个快速的操作,如果不是这样的话,则应该检查硬盘空间是否已满或者磁盘io是否达到瓶颈
5.copy to tmp table 线程正在处理一个alter table语句
6.copying to tmp table 线程将数据写入内存中的临时表
7.copying to tmp table on disk 线程正在将数据写入磁盘中的临时表。与tmp_table_size参数有关系
8.creating sort index 线程正在使用内部临时表处理一个select操作
9.fulltext initialization 服务器正准备进行自然语言全文索引
10.sending data 线程正在读取和处理一条select语句的行,并且将数据发送至客户端,在此期间会执行大量的磁盘访问
11.sorting index 线程正在对索引页进行排序
12.updating 线程寻找更新匹配的行进行更新
13.waiting for lock_type lock 等待各个种类的表锁

  • 杀进程

1.杀单个进程

kill xxxxx;(xxxxx为死锁进程的id)

2.杀多个进程,组装kill语句

SELECT
	concat('kill ',id,';') 
FROM
	information_schema.processlist 
WHERE
	user='root' 
AND
	state='waiting for lock_type lock';

 
在这里插入图片描述
 

  • 其他有关死锁命令
     
    查看被锁的表
    show open tables where in_use > 0;
    查看当前的事务
    select * from information_schema.innodb_trx;

5.解决Oracle死锁

查看锁表进程
SELECT 
	sess.sid, 
	sess.serial#, 
	lo.oracle_username, 
	lo.os_user_name, 
	ao.object_name, 
	lo.locked_mode 
FROM
	v$locked_object lo, 
	dba_objects ao, 
	v$session sess
WHERE 
	ao.object_id = lo.object_id
	AND 
	lo.session_id = sess.sid;
查看锁表语句
SELECT 
	b.sid oracleID,
	b.username 登录Oracle用户名,
	b.serial#,
	spid 操作系统ID,
	paddr,
	sql_text 正在执行的SQL,
	b.machine 计算机名
FROM 
	v$process a, 
	v$session b, 
	v$sqlarea c
WHERE 
	a.addr = b.paddr
	AND 
	b.sql_hash_value = c.hash_value 
杀掉进程
ALTER system kill session 'sid,seial#';

6.主流数据库的区别

MySQL

MySQL(Structured Query Language)由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),使用最常用的数据库管理语言–结构化查询语言(SQL)进行数据库管理。关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。

Redis

Redis (Remote Dictionary Server)意大利的西西里岛,2010年3月15日起,Redis的开发工作由VMware主持。远程字典服务,是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。redis提供五种数据类型:字符串(String),散列/字典(hash),链表(list),集合(set)及有序集合(zset)。

Oracle

Oracle (Oracle Database)是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。

SqlServer

SqlServer (Oracle Database)是Microsoft开发和推广的关系数据库管理系统(RDBMS)具备完全Web支持的数据库产品,提供了对可扩展标记语言 (XML)的核心支持以及在Internet上和防火墙外进行查询的能力。

 
 

【每日一面】

乐观锁通常怎么实现?

乐观锁 (Optimistic Lock):相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。
何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号,则予以更新,否则说明这段期间已经有其他程序对其进行操作了,认为是过期数据

  • 乐观锁实例

在这里插入图片描述

1.查询出学生(白羊)的信息,重点记录version版本号
SELECT
	id,
	name,
	score,
	version 
FROM
	student 
WHERE
	id = 20200001

在这里插入图片描述

2.根据成绩单修改分数
UPDATE 
	student 
SET 
	score = 9,
	version = version + 1 
WHERE
	id = '20200001' 
	AND 
	version = 1

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44598507/article/details/109646345