1.查看表被鎖狀態(tài)
創(chuàng)新互聯(lián)專注于嵐縣企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城網(wǎng)站定制開發(fā)。嵐縣網(wǎng)站建設(shè)公司,為嵐縣等地區(qū)提供建站服務(wù)。全流程定制開發(fā),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
2.查看造成死鎖的sql語句
3.查詢進(jìn)程
4.解鎖(刪除進(jìn)程)
5.查看正在鎖的事物? (8.0以下版本)
6.查看等待鎖的事物?(8.0以下版本)
1、查詢是否鎖表
show OPEN TABLES where In_use 0;
查詢到相對應(yīng)的進(jìn)程 === 然后 kill id
2、查詢進(jìn)程
show processlist
補(bǔ)充:
查看正在鎖的事務(wù)
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
查看等待鎖的事務(wù)
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
查詢死鎖進(jìn)程
采用如下存儲(chǔ)過程來查詢數(shù)據(jù)中當(dāng)前造成死鎖的進(jìn)程。
drop procedure sp_who_lock
go
CREATE procedure sp_who_lock
as
begin
declare @spid int
declare @blk int
declare @count int
declare @index int
declare @lock tinyint
set @lock=0
create table #temp_who_lock
(
id int identity(1,1),
spid int,
blk int
)
if @@error0 return @@error
insert into #temp_who_lock(spid,blk)
select 0 ,blocked
from (select * from master..sysprocesses where blocked0)a
where not exists(select * from master..sysprocesses where a.blocked =spid and blocked0)
union select spid,blocked from master..sysprocesses where blocked0
if @@error0 return @@error
select @count=count(*),@index=1 from #temp_who_lock
if @@error0 return @@error
if @count=0
begin
select '沒有阻塞和死鎖信息'
return 0
end
while @indexA href="mailto:=@count"=@count
begin
if exists(select 1 from #temp_who_lock a where id@index and exists(select 1 from #temp_who_lock where idA href="mailto:=@index"=@index and a.blk=spid))
begin
set @lock=1
select @spid=spid,@blk=blk from #temp_who_lock where id=@index
select '引起數(shù)據(jù)庫死鎖的是: '+ CAST(@spid AS VARCHAR(10)) + '進(jìn)程號(hào),其執(zhí)行的SQL語法如下'
select @spid, @blk
dbcc inputbuffer(@spid)
dbcc inputbuffer(@blk)
end
set @index=@index+1
end
if @lock=0
begin
set @index=1
while @indexA href="mailto:=@count"=@count
begin
select @spid=spid,@blk=blk from #temp_who_lock where id=@index
if @spid=0
select '引起阻塞的是:'+cast(@blk as varchar(10))+ '進(jìn)程號(hào),其執(zhí)行的SQL語法如下'
else
select '進(jìn)程號(hào)SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '進(jìn)程號(hào)SPID:'+ CAST(@blk AS VARCHAR(10)) +'阻塞,其當(dāng)前進(jìn)程執(zhí)行的SQL語法如下'
dbcc inputbuffer(@spid)
dbcc inputbuffer(@blk)
set @index=@index+1
end
end
drop table #temp_who_lock
return 0
end
GO
--執(zhí)行該存儲(chǔ)過程
exec sp_who_lock
補(bǔ)充:
一、產(chǎn)生死鎖的原因
在SQL Server中,阻塞更多的是產(chǎn)生于實(shí)現(xiàn)并發(fā)之間的隔離性。為了使得并發(fā)連接所做的操作之間的影響到達(dá)某一期望值而對資源人為的進(jìn)行加鎖(鎖本質(zhì)其實(shí)可以看作是一個(gè)標(biāo)志位)。當(dāng)一個(gè)連接對特定的資源進(jìn)行操作時(shí),另一個(gè)連接同時(shí)對同樣的資源進(jìn)行操作就會(huì)被阻塞,阻塞是死鎖產(chǎn)生的必要條件。
二、如何避免死鎖
1.使用事務(wù)時(shí),盡量縮短事務(wù)的邏輯處理過程,及早提交或回滾事務(wù);
2.設(shè)置死鎖超時(shí)參數(shù)為合理范圍,如:3分鐘-10分種;超過時(shí)間,自動(dòng)放棄本次操作,避免進(jìn)程懸掛;
3.優(yōu)化程序,檢查并避免死鎖現(xiàn)象出現(xiàn);
4.對所有的腳本和SP都要仔細(xì)測試,在正是版本之前;
5.所有的SP都要有錯(cuò)誤處理(通過@error);
6.一般不要修改SQL SERVER事務(wù)的默認(rèn)級(jí)別。不推薦強(qiáng)行加鎖。
三、處理死鎖
1、最簡單的處理死鎖的方法就是重啟服務(wù)。
2、根據(jù)指定的死鎖進(jìn)程ID進(jìn)行處理
根據(jù)第二步查詢到的死鎖進(jìn)行,大致分析造成死鎖的原因,并通過如下語句釋放該死鎖進(jìn)程
kill pid --pid為查詢出來的死鎖進(jìn)程號(hào)
3、通過存儲(chǔ)過程殺掉某個(gè)庫下面的所有死鎖進(jìn)程和鎖
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_killspid]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[sp_killspid]
GO
create proc sp_killspid
@dbname varchar(200) --要關(guān)閉進(jìn)程的數(shù)據(jù)庫名
as
declare @sql nvarchar(500)
declare @spid nvarchar(20)
declare #tb cursor for
select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname)
open #tb
fetch next from #tb into @spid
while @@fetch_status=0
begin
exec('kill '+@spid)
fetch next from #tb into @spid
end
close #tb
deallocate #tb
go
--使用方法,“db_name”為處理的數(shù)據(jù)庫名稱
exec sp_killspid 'db_name'
1,查看數(shù)據(jù)庫的隔離級(jí)別:
mysql select @@tx_isolation;
2,去查看先當(dāng)前庫的線程情況:
mysql show processlist;
沒有看到正在執(zhí)行的慢SQL記錄線程,再去查看innodb的事務(wù)表INNODB_TRX,看下里面是否有正在鎖定的事務(wù)線程,看看ID是否在show full processlist里面的sleep線程中,如果是,就證明這個(gè)sleep的線程事務(wù)一直沒有commit或者rollback而是卡住了,我們需要手動(dòng)kill掉。
mysql SELECT * FROM information_schema.INNODB_TRX;
如果有記錄,則找到trx_mysql_thread_id這個(gè)字段對應(yīng)的id, 將其kill掉。假如id=100
mysql-kill 100
SELECT CONCAT_WS('','kill',' ',t.trx_mysql_thread_id,';')a FROM information_schema.INNODB_TRX t;
4,總結(jié)分析
表數(shù)據(jù)量也不大,按照普通的情況來說,簡單的update應(yīng)該不會(huì)造成阻塞的,mysql都是autocommit,不會(huì)出現(xiàn)update卡住的情況,去查看下autocommit的值。
mysql select @@autocommit;
1表示自動(dòng)提交。0表示不自動(dòng)提交。
如果你發(fā)現(xiàn)自己的數(shù)據(jù)庫autocommit=0,將它改正吧。
解除死鎖的兩種方法:
(1)終止(或撤銷)進(jìn)程。終止(或撤銷)系統(tǒng)中的一個(gè)或多個(gè)死鎖進(jìn)程,直至打破循環(huán)環(huán)路,使系統(tǒng)從死鎖狀態(tài)中解除出來。
(2)搶占資源。從一個(gè)或多個(gè)進(jìn)程中搶占足夠數(shù)量的資源,分配給死鎖進(jìn)程,以打破死鎖狀態(tài)。
一、show ENGINE INNODB status
查看死鎖位置,分析。
二、
首先解決死鎖可以從死鎖發(fā)生的條件入手,最容易解決的就是更改獲取資源的順序;
其次是避免長事務(wù),讓事務(wù)執(zhí)行的時(shí)間盡可能少,讓事務(wù)的覆蓋范圍盡可能小,長事務(wù)會(huì)導(dǎo)致并發(fā)度降低,且會(huì)有更多的SQL查 詢延遲;
給整個(gè)方法加事務(wù)是否是必須的?可以不加事務(wù)的盡量不加。
1 使用終端或命令提示符登錄到MySQL,輸入命令: mysql -h xxxx.xxx.xxx -P 3306 -u username -p password 2 在MySQL客戶端下輸入命令: show engine innodb status \G; 3 在打印出來的信息中找到“LATEST DETECTED DEADLOCK”一節(jié)內(nèi)容 4 分析其中的內(nèi)容,我們就可以知道最近導(dǎo)致死鎖的事務(wù)有哪些