mysql 連接線程被阻塞怎么解決
創(chuàng)新互聯長期為上1000家客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態(tài)環(huán)境。為聞喜企業(yè)提供專業(yè)的成都網站建設、成都網站制作,聞喜網站改版等技術服務。擁有十載豐富建站經驗和眾多成功案例,為您定制開發(fā)。
1. 通過調用mysql_library_init(),初始化MySQL庫。庫可以是mysqlclient C客戶端庫,或mysqld嵌入式服務器庫,具體情況取決于應用程序是否與“-libmysqlclient”或“-libmysqld”標志鏈接。 2. 通過調用mysql_init()初始化連接處理程序,并通過調用mysql_real_connect()連接到服務器。 3. 發(fā)出SQL語句并處理其結果。(在下面的討論中,詳細介紹了使用它的方法)。 4. 通過調用mysql_close(),關閉與MySQL服務器的連接。 5. 通過調用mysql_library_end(),結束MySQL庫的使用。
通過下面的查詢,?來查詢當前數據庫,?有哪些事務,都鎖定哪些資源。
SELECT
trx_id?AS??`事務ID`,
trx_state?AS?`事務狀態(tài)`,
trx_requested_lock_id??AS??`事務需要等待的資源`,
trx_wait_started AS??`事務開始等待時間`,
trx_tables_in_use?AS?`事務使用表`,
trx_tables_locked?AS?`事務擁有鎖`,
trx_rows_locked??AS?`事務鎖定行`,
trx_rows_modified??AS?`事務更改行`
FROM
information_schema.innodb_trx?;
SELECT
lock_id AS `鎖ID`,
lock_trx_id? AS `擁有鎖的事務ID`,
lock_mode? AS `鎖模式 `,
lock_type? AS `鎖類型`,
lock_table? AS `被鎖的表`,
lock_index? AS `被鎖的索引`,
lock_space? AS `被鎖的表空間號`,
lock_page? AS `被鎖的頁號`,
lock_rec? AS `被鎖的記錄號`,
lock_data? AS `被鎖的數據`
FROM
information_schema.innodb_locks;
SELECT
requesting_trx_id???AS??`請求鎖的事務ID`,
requested_lock_id???AS??`請求鎖的鎖ID`,
blocking_trx_id?????AS??`當前擁有鎖的事務ID`,
blocking_lock_id????AS??`當前擁有鎖的鎖ID`
FROM
innodb_lock_waits;
查詢死鎖進程
采用如下存儲過程來查詢數據中當前造成死鎖的進程。
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 '引起數據庫死鎖的是: '+ CAST(@spid AS VARCHAR(10)) + '進程號,其執(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))+ '進程號,其執(zhí)行的SQL語法如下'
else
select '進程號SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '進程號SPID:'+ CAST(@blk AS VARCHAR(10)) +'阻塞,其當前進程執(zhí)行的SQL語法如下'
dbcc inputbuffer(@spid)
dbcc inputbuffer(@blk)
set @index=@index+1
end
end
drop table #temp_who_lock
return 0
end
GO
--執(zhí)行該存儲過程
exec sp_who_lock
補充:
一、產生死鎖的原因
在SQL Server中,阻塞更多的是產生于實現并發(fā)之間的隔離性。為了使得并發(fā)連接所做的操作之間的影響到達某一期望值而對資源人為的進行加鎖(鎖本質其實可以看作是一個標志位)。當一個連接對特定的資源進行操作時,另一個連接同時對同樣的資源進行操作就會被阻塞,阻塞是死鎖產生的必要條件。
二、如何避免死鎖
1.使用事務時,盡量縮短事務的邏輯處理過程,及早提交或回滾事務;
2.設置死鎖超時參數為合理范圍,如:3分鐘-10分種;超過時間,自動放棄本次操作,避免進程懸掛;
3.優(yōu)化程序,檢查并避免死鎖現象出現;
4.對所有的腳本和SP都要仔細測試,在正是版本之前;
5.所有的SP都要有錯誤處理(通過@error);
6.一般不要修改SQL SERVER事務的默認級別。不推薦強行加鎖。
三、處理死鎖
1、最簡單的處理死鎖的方法就是重啟服務。
2、根據指定的死鎖進程ID進行處理
根據第二步查詢到的死鎖進行,大致分析造成死鎖的原因,并通過如下語句釋放該死鎖進程
kill pid --pid為查詢出來的死鎖進程號
3、通過存儲過程殺掉某個庫下面的所有死鎖進程和鎖
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) --要關閉進程的數據庫名
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”為處理的數據庫名稱
exec sp_killspid 'db_name'
直接用MYSQL庫,肯定是阻塞方式的,就是說,你的SQL語句,網絡傳到服務器,服務器執(zhí)行完,再把結果通過網絡發(fā)回來,你調用的接口才會返回;所以,崩潰的話,肯定是自己代碼有BUG的了,不會是異步導致的;
Mysql數據庫的一個表任何操作都阻塞,
看會不會有一些語句卡住了,鎖表,新語句執(zhí)行不了 show full processlist,看看是否有運行太久的語句
線程A等待線程B的數據,線程B等待線程A的數據,互相等待,就會陷入阻塞,這也是一種線程阻塞。阻塞狀態(tài)是正在運行的線程遇到某個特殊情況。例如,延遲、掛起、等待I/O操作完成等。進入阻塞狀態(tài)的線程讓出CPU,并暫時停止自己的執(zhí)行。線程進入阻塞狀態(tài)后,就一直等待,直到引起阻塞的原因被消除,線程又轉入就緒狀態(tài),重新進入就緒隊列排隊。