什么情况能锁表

儿茶素2023-04-30  25

一个事务会在表上加锁,不管是查询还是修改,只是锁的类型不同,共享锁或是排他锁。

这与设定的隔离级和做的操作有关。

估计楼主关心的是非共享锁表,下面给出我所了解的几种情况

1lock table in exclusive mode

2隔离级设为RR,并执行修改操作

3如果更新行数太多,可能会由行级锁升级为表锁

给高并发情况下的mysql进行更好的优化

MySQL有三种锁的级别:页级、表级、行级,这3种锁的特性可大致归纳如下:

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作,那么这些操作是怎么实现的呢?本文我们主要就介绍一下这部分内容。

(1)锁表查询的代码有以下的形式:

select count() from v$locked_object;

select from v$locked_object;

(2)查看哪个表被锁

select bowner,bobject_name,asession_id,alocked_mode from v$locked_object a,dba_objects b where bobject_id = aobject_id;

(3)查看是哪个session引起的

select busername,bsid,bserial#,logon_time from v$locked_object a,v$session b where asession_id = bsid order by blogon_time;

(4)杀掉对应进程

执行命令:alter system kill session'1025,41';

其中1025为sid,41为serial#

加锁情况与死锁原因分析

为方便大家复现,完整表结构和数据如下:

CREATE TABLE `t3` (

`c1` int(11) NOT NULL AUTO_INCREMENT,

`c2` int(11) DEFAULT NULL,

PRIMARY KEY (`c1`),

UNIQUE KEY `c2` (`c2`)

) ENGINE=InnoDB

insert into t3 values(1,1),(15,15),(20,20);

在 session1 执行 commit 的瞬间,我们会看到 session2、session3 的其中一个报死锁。这个死锁是这样产生的:

1 session1 执行 delete  会在唯一索引 c2 的 c2 = 15 这一记录上加 X lock(也就是在MySQL 内部观测到的:X Lock but not gap);

2 session2 和 session3 在执行 insert 的时候,由于唯一约束检测发生唯一冲突,会加 S Next-Key Lock,即对 (1,15] 这个区间加锁包括间隙,并且被 seesion1 的 X Lock 阻塞,进入等待;

3 session1 在执行 commit 后,会释放 X Lock,session2 和 session3 都获得 S Next-Key Lock;

4 session2 和 session3 继续执行插入操作,这个时候 INSERT INTENTION LOCK(插入意向锁)出现了,并且由于插入意向锁会被 gap 锁阻塞,所以 session2 和 session3 互相等待,造成死锁。

死锁日志如下:

INSERT INTENTION LOCK

在之前的死锁分析第四点,如果不分析插入意向锁,也是会造成死锁的,因为插入最终还是要对记录加 X Lock 的,session2 和 session3 还是会互相阻塞互相等待。

但是插入意向锁是客观存在的,我们可以在官方手册中查到,不可忽略:

Prior to inserting the row, a type of gap lock called an insert intention gap lock is set This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap

插入意向锁其实是一种特殊的 gap lock,但是它不会阻塞其他锁。假设存在值为 4 和 7 的索引记录,尝试插入值 5 和 6 的两个事务在获取插入行上的排它锁之前使用插入意向锁锁定间隙,即在(4,7)上加 gap lock,但是这两个事务不会互相冲突等待。

当插入一条记录时,会去检查当前插入位置的下一条记录上是否存在锁对象,如果下一条记录上存在锁对象,就需要判断该锁对象是否锁住了 gap。如果 gap 被锁住了,则插入意向锁与之冲突,进入等待状态(插入意向锁之间并不互斥)。总结一下这把锁的属性:

1 它不会阻塞其他任何锁;

2 它本身仅会被 gap lock 阻塞。

在学习 MySQL 过程中,一般只有在它被阻塞的时候才能观察到,所以这也是它常常被忽略的原因吧

GAP LOCK

在此例中,另外一个重要的点就是 gap lock,通常情况下我们说到 gap lock 都只会联想到 REPEATABLE-READ 隔离级别利用其解决幻读。但实际上在 READ-COMMITTED 隔离级别,也会存在 gap lock ,只发生在:唯一约束检查到有唯一冲突的时候,会加 S Next-key Lock,即对记录以及与和上一条记录之间的间隙加共享锁。

通过下面这个例子就能验证:

这里 session1 插入数据遇到唯一冲突,虽然报错,但是对 (15,20] 加的 S Next-Key Lock 并不会马上释放,所以 session2 被阻塞。另外一种情况就是本文开始的例子,当 session2 插入遇到唯一冲突但是因为被 X Lock 阻塞,并不会立刻报错 “Duplicate key”,但是依然要等待获取 S Next-Key Lock 。

有个困惑很久的疑问:出现唯一冲突需要加 S Next-Key Lock 是事实,但是加锁的意义是什么?还是说是通过 S Next-Key Lock 来实现的唯一约束检查,但是这样意味着在插入没有遇到唯一冲突的时候,这个锁会立刻释放,这不符合二阶段锁原则。这点希望能与大家一起讨论得到好的解释。

如果是在 REPEATABLE-READ,除以上所说的唯一约束冲突外,gap lock 的存在是这样的:

普通索引(非唯一索引)的S/X Lock,都带 gap 属性,会锁住记录以及前1条记录到后1条记录的左闭右开区间,比如有[4,6,8]记录,delete 6,则会锁住[4,8)整个区间。

对于 gap lock,相信 DBA 们的心情是一样一样的,所以我的建议是:

1 在绝大部分的业务场景下,都可以把 MySQL 的隔离界别设置为 READ-COMMITTED;

2 在业务方便控制字段值唯一的情况下,尽量减少表中唯一索引的数量。

锁冲突矩阵

前面我们说的 GAP LOCK 其实是锁的属性,另外我们知道 InnoDB 常规锁模式有:S 和 X,即共享锁和排他锁。锁模式和锁属性是可以随意组合的,组合之后的冲突矩阵如下,这对我们分析死锁很有帮助:

在进行数据表检查或修补时,可以先将数据表锁定,可确保数据表的安全:

mysql>LOCK TABLE tbl_name READ;

mysql>FLUSH TABLES;

将数据表锁定后再进行检查或修补的工作。完成后再解除锁定:

mys(>

查看被锁表:

select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName

from sysdm_tran_locks where resource_type='OBJECT'

--spid 锁表进程

--tableName 被锁表名

解锁:

declare @spid int

Set @spid = 57 --锁表进程

declare @sql varchar(1000)

set @sql='kill '+cast(@spid as varchar)

exec(@sql)

--查询出死锁的SPID

select blocked

from (select from sysprocesses where blocked>0 ) a

where not exists(select from (select from sysprocesses where blocked>0 ) b

where ablocked=spid)

--输出引起死锁的操作

DBCC INPUTBUFFER (@spid)

--查询当前进程数

select count(-1) from sysprocesses

where dbid in (select dbid from sysdatabases where name like '%telcount%');

燃气表锁表是一种高精度的锁表设备,它具有安全、可靠、防止盗用等特点,可以用来统计、监控和管理燃气的使用情况。燃气表锁表的主要结构由锁表机械部分、电子部分和外壳三部分组成,其中锁表机械部分包括锁表机构、把手和三个轴承,电子部分主要由变频器、显示器、控制器和电池等组成,而外壳则有不锈钢外壳和铝合金外壳两种材料可供选择。

可直接在mysql命令行执行:show engine innodb status\G;

查看造成死锁的sql语句,分析索引情况,然后优化sql然后show processlist;

show status like ‘%lock%’

show OPEN TABLES where In_use > 0; 这个语句记录当前锁表状态

另外可以打开慢查询日志,linux下打开需在mycnf的[mysqld]里面加上以下内容:

slow_query_log=TRUE(有些mysql版本是ON)

slow_query_log_file=/usr/local/mysql/slow_query_logtxt

long_query_time=3

select from v$locked_object:可以获得被锁的对象的object_id及产生锁的会话sid。通过查询结果中的object_id,可以查询到具体被锁的对象。

扩展资料:

注意事项

也可以直接把这几个视图和表关联起来,在查询结果中直接得到“alter system kill session 'sid, serial#'”这样的方便的kill sessoin命令。

如果执行kill session命令后,锁并没有除掉,session依然存在。这种情况,通过select spid from v$process where addr in(select paddr from v$session where sid = &sid)查询到oracle会话在服务器上的pid,然后登陆到服务器上,执行kill -9 pid这样就能杀掉进程解锁了。

以上就是关于什么情况能锁表全部的内容,包括:什么情况能锁表、MYSQL为什么要锁表 有什么好处、查看oracle是否锁表等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

转载请注明原文地址:https://juke.outofmemory.cn/read/3734989.html

最新回复(0)