是plsql的问题吗?,有张表就是打不开,问题如图,求大神解答。

是plsql的问题吗?,有张表就是打不开,问题如图,求大神解答。,第1张

1、查询表是否存在锁postgreSQL的SQL为:

select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname

from pg_locks a

join pg_class b on a.relation = b.oid

where upper(b.relname) = 'TABLE_NAME'

2、查询表锁及 *** 作的SQL语句的SQL为:

select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname,c.usename,c.current_query,c.query_start,c.client_addr

from pg_locks a

join pg_class b on a.relation = b.oid

join pg_stat_activity c on a.pid = c.procpid

where upper(b.relname) = 'TABLE_NAME'

不管是做应用开发,还是平时的基础数据库 *** 作的时候,锁都是得必须注意的一个事情。

下面附上PG的表级锁简单介绍:

下面的列表显示了可用的锁模式和它们被 PostgreSQL 自动使用的场合。你也可以用 LOCK 命令明确获取这些锁。请注意所有这些锁模式都是表级锁,即使它们的名字包含"row"单词(这些名称是历史遗产)。从某种角度而言,这些名字反应了每种锁模式的典型用法,但是语意却都是一样的。两种锁模式之间真正的区别是它们有着不同的冲突锁集合。两个事务在同一时刻不能在同一个表上持有相互冲突的锁。不过,一个事务决不会和自身冲突。比如,它可以在一个表上请求 ACCESS EXCLUSIVE 然后接着请求 ACCESS SHARE 。非冲突锁模式可以被许多事务同时持有。请特别注意有些锁模式是自冲突的(比如,在任意时刻 ACCESS EXCLUSIVE 模式就不能够被多个事务拥有),但其它锁模式都不是自冲突的(比如,ACCESS SHARE 可以被多个事务持有)。

表级锁模式

ACCESS SHARE

只与 ACCESS EXCLUSIVE 冲突。

SELECT 命令在被引用的表上请求一个这种锁。通常,任何只读取表而不修改它的命令都请求这种锁模式。

ROW SHARE

与 EXCLUSIVE 和 ACCESS EXCLUSIVE 冲突。

SELECT FOR UPDATE 和 SELECT FOR SHARE 命令在目标表上需要一个这样模式的锁(加上在所有被引用但没有 ACCESS SHARE 的表上的 FOR UPDATE/FOR SHARE 锁)。

ROW EXCLUSIVE

与 SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 冲突。

UPDATE, DELETE, INSERT 命令自动请求这个锁模式(加上所有其它被引用的表上的 ACCESS SHARE 锁)。通常,这种锁将被任何修改表中数据的查询请求。

SHARE UPDATE EXCLUSIVE

与 SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 冲突。这个模式保护一个表不被并发模式改变和 VACUUM 。

VACUUM(不带 FULL选项), ANALYZE, CREATE INDEX CONCURRENTLY 请求这样的锁。

SHARE

与 ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 冲突。这个模式避免表的并发数据修改。

CREATE INDEX(不带 CONCURRENTLY 选项)语句要求这样的锁模式。

SHARE ROW EXCLUSIVE

与 ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 冲突。

任何 PostgreSQL 命令都不会自动请求这个锁模式。

EXCLUSIVE

与 ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 冲突。这个模式只允许并发 ACCESS SHARE 锁,也就是说,只有对表的读动作可以和持有这个锁模式的事务并发执行。

任何 PostgreSQL 命令都不会在用户表上自动请求这个锁模式。不过,在某些 *** 作的时候,会在某些系统表上请求它。

ACCESS EXCLUSIVE

与与所有模式冲突(包括其自身)。这个模式保证其所有者(事务)是可以访问该表的唯一事务。

ALTER TABLE, DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL 命令要求这样的锁。在 LOCK TABLE 命令没有明确声明需要的锁模式时,它是缺省锁模式。

【提示】只有 ACCESS EXCLUSIVE 阻塞 SELECT(不包含 FOR UPDATE/SHARE 语句)。

一旦请求已获得某种锁,那么该锁模式将持续到事务结束。但是如果在建立保存点之后才获得锁,那么在回滚到这个保存点的时候将立即释放所有该保存点之后获得的锁。这与 ROLLBACK 取消所有保存点之后对表的影响的原则一致。同样的原则也适用于 PL/pgSQL 异常块中获得的锁:一个跳出块的错误将释放在块中获得的锁。

锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,除传统的计算资源(CPU、RAM、I/O)争用外,数据也是一种供许多用户共享的资源,如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素,从这个角度来说,锁对数据库而言是尤其重要,也更加复杂。MySQL中的锁,按照锁的粒度分为:1、全局锁,就锁定数据库中的所有表。2、表级锁,每次 *** 作锁住整张表。3、行级锁,每次 *** 作锁住对应的行数据。

全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新 *** 作的事务提交语句都将阻塞。其典型的使用场景就是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。但是对数据库加全局锁是有弊端的,如在主库上备份,那么在备份期间都不能执行更新,业务会受影响,第二如果是在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志,会导致主从延迟。

解决办法是在innodb引擎中,备份时加上--single-transaction参数来完成不加锁的一致性数据备份。

添加全局锁: flush tables with read lock解锁 unlock tables。

表级锁,每次 *** 作会锁住整张表.锁定粒度大,发送锁冲突的概率最高,并发读最低,应用在myisam、innodb、BOB等存储引擎中。表级锁分为: 表锁、元数据锁(meta data lock, MDL)和意向锁。

表锁又分为: 表共享读锁 read lock、表独占写锁write lock

语法: 1、加锁 lock tables 表名 ... read/write

2、释放锁 unlock tables 或者关闭客户端连接

注意: 读锁不会阻塞其它客户端的读,但是会阻塞其它客户端的写,写锁既会阻塞其它客户端的读,又会阻塞其它客户端的写。大家可以拿一张表来测试看看。

元数据锁,在加锁过程中是系统自动控制的,无需显示使用,在访问一张表的时候会自动加上,MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入 *** 作。为了避免DML和DDL冲突,保证读写的正确性。

在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更 *** 作时,加MDL写锁(排他).

查看元数据锁:

select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema_metadata_locks

意向锁,为了避免DML在执行时,加的行锁与表锁的冲突,在innodb中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。意向锁分为,意向共享锁is由语句select ... lock in share mode添加。意向排他锁ix,由insert,update,delete,select。。。for update 添加。

select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_lock

行级锁,每次 *** 作锁住对应的行数据,锁定粒度最小,发生锁冲突的概率最高,并发读最高,应用在innodb存储引擎中。

innodb的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁,对于行级锁,主要分为以下三类:

1、行锁或者叫record lock记录锁,锁定单个行记录的锁,防止其他事物对次行进行update和delete *** 作,在RC,RR隔离级别下都支持。

2、间隙锁Gap lock,锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事物在这个间隙进行insert *** 作,产生幻读,在RR隔离级别下都支持。

3、临键锁Next-key-lock,行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap,在RR隔离级别下支持。

innodb实现了以下两种类型的行锁

1、共享锁 S: 允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。

2、排他锁 X: 允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。

insert 语句 排他锁 自动添加的

update语句 排他锁 自动添加

delete 语句 排他锁 自动添加

select 正常查询语句 不加锁 。。。

select 。。。lock in share mode 共享锁 需要手动在select 之后加lock in share mode

select 。。。for update 排他锁 需要手动在select之后添加for update

默认情况下,innodb在repeatable read事务隔离级别运行,innodb使用next-key锁进行搜索和索引扫描,以防止幻读。

间隙锁唯一目的是防止其它事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用的间隙锁。

ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效

解决方法如下:

=========================================================

SQL>select session_id from v$locked_object

SESSION_ID

----------

56

SQL>SELECT sid, serial#, username, osuser FROM v$session where sid = 142

SIDSERIAL# USERNAME OSUSER

---------- ---------- ------------------------------ ------------------------------

56 2088 ghb fy

SQL>ALTER SYSTEM KILL SESSION '56,2088'

System altered

执行完上述命令后,提示会话断开。重新连接数据库,然后执行truncate *** 作,成功!

以下是原理部分

==============

Oracle数据库的锁类型

根据保护的对象不同,Oracle数据库锁可以分为以下几大类:DML锁(data locks,数据锁),用于保护数据的完整性;DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;内部锁和闩(internal locks and latches),保护数据库的内部结构。

DML锁的目的在于保证并发情况下的数据完整性,。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

当Oracle 执行DML语句时,系统自动在所要 *** 作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X 等多种模式,在数据库中用0-6来表示。不同的SQL *** 作产生不同类型的TM锁。

在数据行上只有X锁(排他锁)。在 Oracle数据库中,当一个事务首次发起一个DML语句时就获得一个TX锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后,TX锁被释放,其他会话才可以加锁。

当Oracle数据库发生TX锁等待时,如果不及时处理常常会引起Oracle数据库挂起,或导致死锁的发生,产生ORA-60的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。

悲观封锁和乐观封锁

一、悲观封锁

锁在用户修改之前就发挥作用:

Select ..for update(nowait)

Select * from tab1 for update

用户发出这条命令之后,oracle将会对返回集中的数据建立行级封锁,以防止其他用户的修改。

如果此时其他用户对上面返回结果集的数据进行dml或ddl *** 作都会返回一个错误信息或发生阻塞。

1:对返回结果集进行update或delete *** 作会发生阻塞。

2:对该表进行ddl *** 作将会报:Ora-00054:resource busy and acquire with nowait specified.

原因分析

此时Oracle已经对返回的结果集上加了排它的行级锁,所有其他对这些数据进行的修改或删除 *** 作都必须等待这个锁的释放,产生的外在现象就是其他的 *** 作将发生阻塞,这个这个 *** 作commit或rollback.

同样这个查询的事务将会对该表加表级锁,不允许对该表的任何ddl *** 作,否则将会报出ora-00054错误::resource busy and acquire with nowait specified.

二、乐观封锁

乐观的认为数据在select出来到update进取并提交的这段时间数据不会被更改。这里面有一种潜在的危险就是由于被选出的结果集并没有被锁定,是存在一种可能被其他用户更改的可能。因此Oracle仍然建议是用悲观封锁,因为这样会更安全。

阻塞

定义:

当一个会话保持另一个会话正在请求的资源上的锁定时,就会发生阻塞。被阻塞的会话将一直挂起,直到持有锁的会话放弃锁定的资源为止。4个常见的dml语句会产生阻塞

INSERT

UPDATE

DELETE

SELECT…FOR UPDATE

INSERT

Insert发生阻塞的唯一情况就是用户拥有一个建有主键约束的表。当2个的会话同时试图向表中插入相同的数据时,其中的一个会话将被阻塞,直到另外一个会话提交或会滚。一个会话提交时,另一个会话将收到主键重复的错误。回滚时,被阻塞的会话将继续执行。

UPDATE 和DELETE当执行Update和delete *** 作的数据行已经被另外的会话锁定时,将会发生阻塞,直到另一个会话提交或会滚。

Select …for update

当一个用户发出select..for update的错作准备对返回的结果集进行修改时,如果结果集已经被另一个会话锁定,就是发生阻塞。需要等另一个会话结束之后才可继续执行。可以通过发出 select… for update nowait的语句来避免发生阻塞,如果资源已经被另一个会话锁定,则会返回以下错误:Ora-00054:resource busy and acquire with nowait specified.

死锁-deadlock

定义:当两个用户希望持有对方的资源时就会发生死锁.

即两个用户互相等待对方释放资源时,oracle认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续执行,牺牲的用户的事务将回滚.

例子:

1:用户1对A表进行Update,没有提交。

2:用户2对B表进行Update,没有提交。

此时双反不存在资源共享的问题。

3:如果用户2此时对A表作update,则会发生阻塞,需要等到用户一的事物结束。

4:如果此时用户1又对B表作update,则产生死锁。此时Oracle会选择其中一个用户进行会滚,使另一个用户继续执行 *** 作。

起因:

Oracle的死锁问题实际上很少见,如果发生,基本上都是不正确的程序设计造成的,经过调整后,基本上都会避免死锁的发生。

DML锁分类表

表1 Oracle的TM锁类型

锁模式 锁描述 解释 SQL *** 作

0 none

1 NULL 空 Select

2 SS(Row-S) 行级共享锁,其他对象只能查询这些数据行 Select for update、Lock for update、Lock row share

3 SX(Row-X) 行级排它锁,在提交前不允许做DML *** 作 Insert、Update、Delete、Lock row share

4 S(Share) 共享锁 Create index、Lock share

5 SSX(S/Row-X) 共享行级排它锁 Lock share row exclusive

6 X(Exclusive) 排它锁 Alter table、Drop able、Drop index、Truncate table 、Lock exclusive

1.关于V$lock表和相关视图的说明

Column Datatype Description

ADDR RAW(4 | 8) Address of lock state object

KADDR RAW(4 | 8) Address of lock

SID NUMBER Identifier for session holding or acquiring the lock

TYPE VARCHAR2(2) Type of user or system lock

The locks on the user types are obtained by user applications. Any process that is blocking others is likely to be holding one of these locks. The user type locks are:

TM - DML enqueue

TX - Transaction enqueue

UL - User supplied

--我们主要关注TX和TM两种类型的锁

--UL锁用户自己定义的,一般很少会定义,基本不用关注

--其它均为系统锁,会很快自动释放,不用关注

ID1 NUMBER Lock identifier #1 (depends on type)

ID2 NUMBER Lock identifier #2 (depends on type)

---当lock type 为TM时,id1为DML-locked object的object_id

---当lock type 为TX时,id1为usn+slot,而id2为seq。

--当lock type为其它时,不用关注

LMODE NUMBER Lock mode in which the session holds the lock:

0 - none

1 - null (NULL)

2 - row-S (SS)

3 - row-X (SX)

4 - share (S)

5 - S/Row-X (SSX)

6 - exclusive (X)

--大于0时表示当前会话以某种模式占有该锁,等于0时表示当前会话正在等待该锁资源,即表示该会话被阻塞。

--往往在发生TX锁时,伴随着TM锁,比如一个sid=9会话拥有一个TM锁,一般会拥有一个或几个TX锁,但他们的id1和id2是不同的,请注意

REQUEST NUMBER Lock mode in which the process requests the lock:

0 - none

1 - null (NULL)

2 - row-S (SS)

3 - row-X (SX)

4 - share (S)

5 - S/Row-X (SSX)

6 - exclusive (X)

--大于0时,表示当前会话被阻塞,其它会话占有改锁的模式

CTIME NUMBER Time since current mode was granted

BLOCK NUMBER The lock is blocking another lock

0, 'Not Blocking',

1, 'Blocking',

2, 'Global',

--该锁是否阻塞了另外一个锁

2.其它相关视图说明

视图名 描述 主要字段说明

v$session 查询会话的信息和锁的信息。 sid,serial#:表示会话信息。

program:表示会话的应用程序信息。

row_wait_obj#:表示等待的对象,和dba_objects中的object_id相对应。

lockwait :该会话等待的锁的地址,与v$lock的kaddr对应.

v$session_wait 查询等待的会话信息。 sid:表示持有锁的会话信息。

Seconds_in_wait:表示等待持续的时间信息

Event:表示会话等待的事件,锁等于enqueue

dba_locks 对v$lock的格式化视图。 Session_id:和v$lock中的Sid对应。

Lock_type:和v$lock中的type对应。

Lock_ID1: 和v$lock中的ID1对应。

Mode_held,mode_requested:和v$lock中

的lmode,request相对应。

v$locked_object 只包含DML的锁信息,包括回滚段和会话信息。 Xidusn,xidslot,xidsqn:表示回滚段信息。和

v$transaction相关联。

Object_id:表示被锁对象标识。

Session_id:表示持有锁的会话信息。

Locked_mode:表示会话等待的锁模式的信

息,和v$lock中的lmode一致。

以下是命令行部分

================

1.查询数据库中的锁

select * from v$lock

select * from v$lock where block=1

2.查询被锁的对象

select * from v$locked_object

3.查询阻塞

查被阻塞的会话

select * from v$lock where lmode=0 and type in ('TM','TX')

查阻塞别的会话锁

select * from v$lock where lmode>0 and type in ('TM','TX')

4.查询数据库正在等待锁的进程

select * from v$session where lockwait is not null

5.查询会话之间锁等待的关系

select a.sid holdsid,b.sid waitsid,a.type,a.id1,a.id2,a.ctime from v$lock a,v$lock b

where a.id1=b.id1 and a.id2=b.id2 and a.block=1 and b.block=0

6.查询锁等待事件

select * from v$session_wait where event='enqueue'

解决方案:

select session_id from v$locked_object--首先得到被锁对象的session_id

SELECT sid, serial#, username, osuser FROM v$session where sid = session_id--通过上面得到的session_id去取得v$session的sid和serial#,然后对该进程进行终止。

ALTER SYSTEM KILL SESSION 'sid,serial'

example:

ALTER SYSTEM KILL SESSION '13, 8'


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8121104.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-13
下一篇 2023-04-13

发表评论

登录后才能评论

评论列表(0条)

保存