oracle学习笔记 锁基础原理

来源:互联网 发布:淘宝首页服务 编辑:程序博客网 时间:2024/05/17 02:02

oracle学习笔记 锁基础原理

这节课开始讲oracle的锁

oracle的锁里面有些原理性的地方我们会讲到
同时也会给大家做一些演示
同时也为大家准备了很多的sql语句
以后可以根据演示
去复制sql语句,直接去使用就可以

所以说首先来讲oracle的锁的一些的基本概念

一)oracle的并发

第一个
锁是干什么用的
oracle为什么需要锁
简单说一下

讲到这个地方的时候
就讲到oracle的一个不同与别的数据库的一个特性

我们知道oracle数据库来讲
内存里面有buffercache、sharedpool、logbuffer、pga
然后一堆的session
buffercache、sharedpool、logbuffer整个的是SGA
底下的硬盘中是dbf等文件

这时候对sga来讲
buffercache、sharedpool、logbuffer这三个空间叫SGA
也叫共享全局区
所有的进程都可以访问他们

后台进程可以访问他们
后台进程可以访问所有的空间所有的数据
serverprocession也可以同时访问这些数据

也就是对sga来讲
有非常多的进程可以同时访问它们
这叫并发

对oracle来讲
后台进程数量有限,十来个
而且它们的工作负载并不是非常重
但是oracle进程对oracle数据库来讲
最多的进程是serverprocess
就是一个会话一个连接一个session

一个session对应一个连接
一个连接对应一个serverprocess
正常情况下相对负载比较大的一个数据库
会有上百个serverprocess进程
只有十来个后台进程

这上百个加上这十来个
一百多个甚至二百多个、三百多个
然后同时来访问SGA
这就叫并发性

特别是对serverprocess来讲
serverprocess是代表用户去执行sql的
这个sql语句有可能负载很重
有可能会访问非常多的表和行

我们讲并发性的时候
主要讲的是serverprocess
主要讲的serverprocess的并发性

二)并发和锁的关系

并发的话当然好了
因为并发意味着可以同时操作

讲到这个地方的时候
可以这么来说一句话
oracle之所以能并发是因为oracle有锁
没有锁谈不上并发

同时我们又说了
因为有锁限制了并发

有点矛盾
没有锁就没有并发
当然了锁也会使得我们的并发受到一些的限制

当然了不是矛盾,这是一个对应的关系

所以说讲到锁必然会提到并发性的问题
这就是锁的作用
锁的作用就是来解决并发问题的

为什么需要并发,为什么并发就需要锁呢
举个例讲
对一块数据来讲
比如说一个serverprocess要修改这个数据
这时候它可以给这个数据加一个锁

另外一个进程就不能访问它

A进程把这个数据给锁住了
B进程想要修改它的时候
需要等待A进程修改完
A就给这个数据加了一个锁

我们看因为有锁
所以说A和B可以同时运行
因为A运行的时候可以把数据锁住
B可以去做别的,等一会过来修改数据

因为有锁所以可以并发

同时我们看
因为锁的问题
A和B不能同时修改这个数据
锁限制了并发

三)用户的感觉

有一次用户给老师讲
说数据库里面都是锁,很多锁
是不是数据库出问题了
老师说不对的
数据库里面有锁是正常的
没有锁才奇了怪了

数据库有锁是正常的
关键是什么不正常呢
是一个进程等待一个锁这是正常的
一个进程等待一个锁
关键是等待时间不要过长

举例讲
A进程访问这个数据,锁上了
B进程也要访问这个数据,它等待
等待很正常,关键不要让B等待的时间太久

如果B等待的时间太久的话
这时候用户就会感觉
数据库跟死掉一样

提到锁我们主要讲的是serverprocess的锁

A进程上来以后锁住一块数据
B进程上来以后也要访问这个数据
它需要等待A解锁
A解锁以后B才能访问这个锁

这个时候
对B这个进程所对应的用户X用户在使用B进程
数据库可能目前为止几乎没有什么负载
只有这两个进程登上来了
但是他们在同时访问一块数据

这块数据被A进程访问了
B进程就在等待
这个时候X用户就感到数据库非常的慢

也就是说
A锁住了某个资源,B等待这块资源

这个时候B用户就会感到
这个连接这个操作非常的慢
这个慢可能不是慢
是它在等待
但是我们的体会上是慢

我们举个很简单的例子

为了体验
课程中老师给大家开了几个连接
有Oracle SQL Developer的几个链接和sqlplus的几个链接

告诉大家怎么去做这个事情,怎么开连接
我们新开一个sqlplus
用sqlplus虽然说简单一些
但是它反馈一些问题

在远程控制putty软件新开一个oracle的sqlplus客户端

login as: rootroot@192.168.3.47's password:Last login: Mon Nov 13 07:46:32 2017[root@redhat4 ~]# su - oracle[oracle@redhat4 ~]$ sqlplus hr/hrSQL*Plus: Release 10.2.0.1.0 - Production on Thu Nov 16 10:25:10 2017Copyright (c) 1982, 2005, Oracle.  All rights reserved.Connected to:Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProductionWith the Partitioning, OLAP and Data Mining optionsSQL>

再另一个putty再开一个sqlplus客户端

[oracle@redhat4 ~]$ export NLS_LANG=american_america.zhs16gbk[oracle@redhat4 ~]$ sqlplus hr/hrSQL*Plus: Release 10.2.0.1.0 - Production on Thu Nov 16 10:27:46 2017Copyright (c) 1982, 2005, Oracle.  All rights reserved.Connected to:Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProductionWith the Partitioning, OLAP and Data Mining optionsSQL>

我们看在其中一个执行

SQL> select * from employees where rownum=1;EMPLOYEE_ID FIRST_NAME           LAST_NAME----------- -------------------- -------------------------EMAIL                     PHONE_NUMBER         HIRE_DATE    JOB_ID------------------------- -------------------- ------------ ----------    SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID---------- -------------- ---------- -------------        198 Donald               OConnellDOCONNEL                  650.507.9833         21-JUN-99    SH_CLERK      2600                       124            50

第一行
我们找一个EMPLOYEE_ID
这里是198

我们去找一个update的sql语句我们来作一下
我们对employees表进行更新
如:
update employees set last_name=last_name||’a’ where department_id=60;

这里有两个sqlplus会话

其中一个去更新

SQL> update employees set last_name=last_name||'a' where department_id=60;5 rows updated.

感觉速度非常的快
我们现在数据库基本上没有什么负载

在另外一个sqlplus中也更新相同的数据

SQL> update employees set last_name=last_name||'a' where department_id=60;

这个命令一回车以后
感觉执行不完一样
这个会话就感觉数据库特别的慢
等了这么长时间还没更新完

其实这时候
数据库这个慢是因为被锁住了

所以说就出一个问题
你看上去慢,用户感觉慢的时候
不一定数据库是负载很重
有可能是因为锁的问题

在以后讲优化的时候还会进一步去判断

怎么去释放锁呢

rollback和commit都可以释放锁

在第一个会话中执行回滚

SQL> rollback;Rollback complete.

这时看第二个会话

SQL> update employees set last_name=last_name||'a' where department_id=60;5 rows updated.SQL>

命令得到执行了

说明释放完了锁,第二个会话执行的命令马上就过来了

这里为了继续做实验把第二个会话也回滚了

SQL> rollback;Rollback complete.

讲到这个地方给大家讲了一个概念
产生锁的问题的时候
有锁是正常的
问题是不要因为锁而让进程等待时间过长
如果等待过长
这时候就有用户会感觉到数据库非常的慢
自然需要我们去解决

这是讲的锁的基本概念

锁的作用就是保护数据

四)数据库内存结构中的latch锁

那么oracle数据库里面又有哪种锁

总体来讲有两种锁
一种是latch锁,一种是LOCK锁

在oracle数据库里面
有哪些东西需要保护需要并发保护呢

第一种我们讲是chain链

我们讲过在内存里面
包括sharedpool里面,包括buffercache里面
有很多数据块,有很多的chunk
它们被串在各种各样的链上
比如说有个CBC(cache buffer chain)链挂着buffer
有sharedpool链挂着chunk

对这些链来讲
链底下挂着一些buffer或者一些chunk

当一个serverprocess要访问链上的chunk的时候
它需要访问这个链
在链上进行遍历
遍历以后找到这个chunk

也就是说在oracle数据库里面
一些内存结构,这些链
会被serverprocess并发访问

要并发访问这些链的话
这些链就需要保护
用latch来保护
老师只讲到这个地方
因为关于latch的问题要放到优化里面去讲

oracle数据库里面
数据库打开以后
在SGA里面有各种各样的链
这些链会被serverprocess并发访问
尽然会被并发访问,这些链就需要被保护

所以说一个serverprocess
在访问这个链的时候会获得这个链的锁
这个链的锁叫latch

获得这个链的这个锁就是获得latch
获得latch以后对这个链进行访问
访问完了自动释放latch

oracle里面有一个概念叫latch争用
这个在优化里面会详细的讲
老师会给大家讲有很多种类型的latch
和前面的体系结构是紧密的连接在一起的

发生latch争用的时候
说明有多个serverprocess同时对链进行访问
那说明出现了热块
或者比较热的一些chunk、热的sql语句、热的一些buffer、热块等等这些
我们需要一步步去排错

latch是用来保护链的
latch争用就是说明对链产生了争用

我们会在优化里面给大家解释和解决这个问题

oracle第一种锁是latch锁
它保护的是链

五)lock锁

oracle还有另外一种锁叫lock锁
这是我们这次课研究的重点

latch往往跟优化有关系和性能有关系
记住latch是保护chain也就是链

oracle还有另外一种叫lock锁
这个锁主要是用来保护buffer的
保护数据块数据行
这是我们这次讲的锁LOCK锁

锁有两种

一种叫排它锁

对一块资源来讲
A要访问它
给这个资源加了个排它锁
排它锁往往用X来表示
这时B就不能访问它
这叫排它锁

共享锁是
A访问这个资源加了个锁,加了共享锁
B也可以访问它,也可以加共享锁
也就是两个共享锁是兼容的
这个资源它有两个锁
两个共享锁

简单先记住
锁有两种
有共享锁有排它锁

latch是用来保护链的
lock是用来保护数据块数据行的
当然这个保护是保护并发访问

六)行级锁

我们在前面讲过oracle有行级锁
这是oracle的特性之一

我们知道一个事务开始的时候

事务表里面有一行它指向回滚块

然后数据块里面有事务槽
然后修改数据块里面的一行的时候
行的头部要加上一个锁标记

其实锁标记的数字
指向数据块里面的事务槽的槽的编号

数据块中一个事务槽又指向undo段头块中的事务表中的一行
undo段头块的事务表中的一条记录又指向回滚块
数据块中的事务槽中的一条记录也指向回滚块

这个是对应关系是我们前几节课讲的

oracle在访问这个行的时候加上了一个行级锁

对这个数据块来讲
A事务要修改数据块中的这个行
B事务要修改这个块里面的另一行的时候
它可以也获取到这个数据块中的一个事务槽
然后修改这个另一行
B事务修改的这个行指向事务槽中分配给B的那行事务槽

也就是说oracle
通过在一个数据行前面加上一个锁标记
实现了行级锁

也就是oracle对数据lock锁最小的粒度单位是行
我要访问那个行
就给这个行加上一个锁
当然这个访问叫DML,是修改,增删改
这就是一个粒度的概念

对于微软的sqlserver这个数据库
它的粒度是一个配置叫页
也就是我们讲的block

sqlserver要访问某个行的时候
它至少把这个行所在的整个块这个页给锁住
锁住的话里面的别的行即使没被修改也锁住了
sqlserver并发性在这方面就表现的很差

这是关于一个粒度的问题
oracle锁的粒度是行
这是第一个特点

其实还有一个很重要的概念
当一个事务修改一个数据行的时候
不影响另外一个select对这个行进行访问
也就是说我修改这个数据的时候
加了个X锁排它锁
不影响对这个数据块和这个数据行的读
因为我们可以构造cr块
这也是oracle的一个特性特点
一个非常有特色的地方

就是我对数据行的修改
不影响另外一个事务或另外一个访问
对这个数据行的一个读
这就是oracle的第二个特点

所以说oracle在锁上实现了行级锁
同时通过构造cr块这个行级锁又不影响对这个行的访问
这就是oracle并发性非常好的最主要的原因

这比sqlserver它们要好的多
这是我们讲了行级锁

行级锁主要是DML语句产生的

七)事务锁

有一个叫事务锁的概念

首先我们看看什么叫事务锁

我们知道一个事务开始
首先来讲一个事务它会产生一个事务锁

当然这个事务可能会修改很多的行
每行要叫行级锁
但是只有一个事务锁,因为它只有一个事务

我们可以查
举个例讲

这有三条sql语句:

update employees set last_name=last_name||'a' where department_id=60;update departments set department_name='unknow' where department_id=10;update locations set city='unknown' where location_id=1100;

组成一个事务

它修改了非常多的行
但是查以后发现
比如说这三个sql语句修改了十行
这时候它只有一个事务锁

讲到这个地方的时候再给大家来讲什么叫事务锁

首先事务锁是因为一个事务
一个事务有一个事务锁

事务锁是因为行级锁产生的
但是一个事务只有一个事务锁
它是因为行级锁产生的

先记住一个事务只能产生一个事务锁
这个事务是因为行级锁产生的

事务锁的加锁和解锁
很简单commit和rollback就解锁了
加锁就是DML语句
有了行级锁就会产生TX锁
一个事务有了行级锁就有了事务锁

有的时候我们把行级锁和事务锁给混了
其实它不一会事

行级锁是每个行上加一个锁
事务锁是一个事务一个锁
但是事务锁是因为行级锁产生的

我们查一下目前有没有事务
在sqldeveloper中执行
select xidusn,xidslot,xidsqn,status from v$transaction;
老师做的实验环境速度非常的慢,最后没等到结果

这个实验我自己做的结果

一开始执行update前没有事务

SQL> select xidusn,xidslot,xidsqn,status from v$transaction;no rows selected

HR用户执行了一条update语句

SQL> update employees set last_name=last_name||'a' where department_id=60;5 rows updated.

产生了事务

SQL> select xidusn,xidslot,xidsqn,status from v$transaction;    XIDUSN    XIDSLOT     XIDSQN STATUS---------- ---------- ---------- ----------------         7         35        223 ACTIVE

hr用户再接着执行另外两个update
就是同一会话中同时对三个表执行三个不同的update

SQL> update employees set last_name=last_name||'a' where department_id=60;5 rows updated.SQL> update departments set department_name='unknow' where department_id=10;1 row updated.SQL> update locations set city='unknown' where location_id=1100;1 row updated.

这时v$transaction中仍是只有一个事务

SQL> select xidusn,xidslot,xidsqn,status from v$transaction;    XIDUSN    XIDSLOT     XIDSQN STATUS---------- ---------- ---------- ----------------         7         35        223 ACTIVE

老师的sqldeveloper实验中
会话长了它会自动的断开
所以说每次访问的时候它会自动的去连
所以说速度会慢一些
又开了三个sqldeveloper所以说速度很慢

我们知道行级锁并不影响我们去构造cr块
并不影响读

八)表级锁

除了行级锁、事务锁以外还有种锁叫表级锁
在表的级别上加一个锁
有时候我们还是需要表级锁的

我们知道oracle主要的锁是行级锁
修改那个行就加那个锁
同时因为事务会产生事务锁

我们来看还有一个表级锁叫TM

表级锁:TM行级排他锁(Row exclusive)RX锁    当我们进行DML时,会自动在被更新的表上添加RX锁,可以执行LOCK命令显式的在表上添加RX锁    允许其他事务通过DML语句修改相同表里的其他数据行    允许使用lock命令对表添加RX锁定    不允许其他事务对表添加X锁行级共享锁(Row Shared,简称RS锁)    select … from for update共享锁(Share,简称S锁)    通过lock table in share mode命令添加该S锁排他锁(Exclusive,简称X锁)    通过lock table in exclusive mode命令添加X锁共享行级排他锁(Share Row Exclusive,简称SRX锁)    通过lock table in share row exclusive mode命令添加SRX锁lock table  in [row share][row exclusive][share][share row exclusive][exclusive] mode;

表级锁里面又分5种

一种行级排它锁
它是一种表级锁RX锁
这个锁最多

一个表里面假设有十万行
A事务上来以后修改了表里面其中的一行
也就是给这个行加了X锁是行级锁
同时这个A产生了一个事务锁TX

A事务假设它修改了很多的行
每一行前面都加了一个行级锁
但是这个A事务只产生一个TX锁

这个时候B会话上来以后
它要把整个表删掉
oracle至少需要保证
这个表上所有的事务都提交了

这个时候B就需要

一种方法
B把所有的行统统读一遍
读一遍以后确认所有的行都提交了
然后再删除这个表

这时候有个问题

这里面我们看有十万行
有可能有非常多的事务在访问

这时候对B来讲
要把这十万行都访问一遍
然后确认这里面有没有人、有那个事务
有没有事务在其中修改某一行
做起来很困难

十万行它要一行行去查
要是一百万行
这时候对B来讲
他可能检查后面十万行的时候
前面十万行又被修改了

所以说对B来讲
要实现这个操作很麻烦

为了解决这个问题
oracle就做了这么个事情

A事务
要修改这个表里面的某一行或多行数据的时候
这个行加行级锁
同时这个A又产生了一个事务锁
同时另外一个地方
A这个事务
还在表的级别上加了一个TM锁
加了个表级锁
这个表级锁的名字叫RX

A事务刚才做了一件事情以后
产生了三个锁

一个锁是在这个行上加了个行级锁
同时A事务自己产生了一个TX锁事务锁
同时A这个事务还在这个表的级别上加了个TM
TM就是表级锁
这个锁的名字叫RX
RX锁是个表级锁

它是因为对这个表里面的某一行或多行进行的修改
而产生的RX锁

有一个C事务也要修改这个表里面的一行或多行
它也会做一件什么事情
第一它要对修改的行加上行级锁
同时也产生TX锁
还会给这个表加RX锁

A事务已经对这个表加了RX锁了
B事务也可以对这个表加RX锁
这就是锁和锁之间的兼容性的问题

在一个表上在一个资源上加了共享锁
还可以再加第二个共享锁
这里面的RX一样

加共享锁后再可以加共享锁
因为共享锁和共享锁是兼容的
所以说锁有兼容性的问题

我在一个资源上加了一个锁
另外一个会话上来以后
在这个资源上还可以加锁的时候
说明这两个锁是兼容的

A事务加了RX锁,在这个表加了RX锁
B事务和C事务上来以后在表上还可以加RX锁
也就是RX锁和RX锁是兼容的
虽然带了X但它是兼容的
这是表级锁

既然表级别上加了RX了
这个时候对B这个会话它要删除表的时候
它不需要关心表里面的行有没有加锁
因为这个表上已经加了表级锁了

B这个会话只要查一下这个表上有没有表级锁
使用表级锁就可以了
它一看有RX锁有表级锁
这时候它不能把这个表删除

因为B要删除这个表的话
需要对这个表加一个X锁
加个完全排它锁
因为这个表上已经有RX了
RX和X是互斥的,有RX就不能有X
所以说这时候B用户B会话不能删除这个表

不能删除表是因为表级别上有RX锁
这是这个概念

现在理解了吧
记住很有意思

九)表级锁的模式

1)RX锁、行级排它锁

一般的情况我们对表进行DML的时候
这时候oracle自动的对这个表加一个锁名字叫RX

记住RX是因为DML产生引起的
但是它是个表级锁

同时我们还可以用lock命令对表加RX锁

1、行级排他锁(Row exclusive)RX锁

当我们进行DML时,会自动在被更新的表上添加RX锁,可以执行LOCK命令显式的在表上添加RX锁

比如说
lock table 表的名字 in row exclusive mode;

就是在表上加RX锁
RX和RX可以兼容

2、允许其他事务通过DML语句修改相同表里的其他数据行
两个事务可以同时给某个表加RX

3、允许使用lock命令对表添加RX锁定
刚才讲了

4、不允许其他事务对表添加X锁
我们对表加X锁是因为要删除这个表
也就是说RX和X是互斥的

2)RS锁

对表TM除了有RX锁以外
还有行级RS锁行级共享锁

有一个语句
select … from for update
这个语句在实际生产里面很多人使用

select正常的不加锁
select for update是加锁的

我们看select for update的一个过程

首先来讲select for update 会产生一个事务
会产生事务就会在事务表里面产生一行
然后有回滚块
然后数据块
数据块里面的事务槽
和数据块里面修改的这一行

select for update是访问这行
但是行上加了锁
所以说select for update
和普通的DML语句一样
都会产生这一系列的东西
只不过select for update实际没有修改
但它锁住了这个行了

select for update 它读的是这行
但是是以DML的形式去读的这一行,也加锁了
它和普通DML不一样的是
它在表的级别上它加了RS锁,它没有加RX
就是这个区别

如果我对这行进行for update的时候
另外一个不能对这个行for update
因为for update和for update在行上是互斥的

举个例子

我们直接去做一个
select * from employees where rownum=1 for update;

在第一个sqlplus中的执行结果

SQL> select * from employees where rownum=1 for update;EMPLOYEE_ID FIRST_NAME           LAST_NAME----------- -------------------- -------------------------EMAIL                     PHONE_NUMBER         HIRE_DATE    JOB_ID------------------------- -------------------- ------------ ----------    SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID---------- -------------- ---------- -------------        198 Donald               OConnellDOCONNEL                  650.507.9833         21-JUN-99    SH_CLERK      2600                       124            50

访问了employees中的其中第一行
然后加了个for update

我们在第二个地方第二个sqlplus中执行

SQL> select * from employees where rownum=1 for update;

指令暂时得不到结果
出现问题了,锁住了

如果第一个sqlplus中rollback

SQL> rollback;Rollback complete.

这时第二个sqlplus中刚才等待的命令得到了执行

SQL> select * from employees where rownum=1 for update;EMPLOYEE_ID FIRST_NAME           LAST_NAME----------- -------------------- -------------------------EMAIL                     PHONE_NUMBER         HIRE_DATE    JOB_ID------------------------- -------------------- ------------ ----------    SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID---------- -------------- ---------- -------------        198 Donald               OConnellDOCONNEL                  650.507.9833         21-JUN-99    SH_CLERK      2600                       124            50

返回了结果
第二个访问了

第二个也给rollback

SQL> rollback;Rollback complete.

这就是select for update

就是刚才select for update一行的时候
也是在行上加锁、产生事务等等这些都一样
只不过select for update在表级别上加了个RS锁没有加RX
就这一个区别,别的都一样

这是表级共享锁

表的
行级共享锁(Row Shared,简称RS锁)
select … from for update

是因为select for update 产生的

3)其它几种表级锁

表上还可以加共享锁

共享锁(Share,简称S锁)
通过lock table in share mode命令添加该S锁

还可以加排它锁

排他锁(Exclusive,简称X锁)
通过lock table in exclusive mode命令添加X锁

记住排它锁的最经典的一个标志是
对表的结构进行改变或者把这个表删除
这时候就需要对这个表加排它锁
这个时候任何人任何用户
都不能对这个表有任何的修改
这是排它锁

我们可以用lock加

还有共享行级排它锁

共享行级排他锁(Share Row Exclusive,简称SRX锁)
通过lock table in share row exclusive mode命令添加SRX锁

这时候后面几个锁
真的有时候不太理解
排它锁还可以理解
有什么共享锁、共享行级排它锁
我们有时候不太理解

记住研究锁的时候从几个点上研究

第一个锁和锁之间的兼容性问题
第二锁是怎么产生的

oracle搞这么多的锁出来
其实就是为了锁数据的时候用
比如锁越多,分的越细
我锁某个资源的时候
可以选择的锁就越多
可以最小限度的减少锁的粒度

比如举例讲
咱们没有这些没有别的锁
比如说oracle数据库里面
什么锁都没有
只有一个表级别的一个排它锁
连DML这事务锁都没有
只有一个锁

那意味着
我要对这个表进行任何访问的时候
都需要加X锁
这个时候并发性会很差

所以说oracle就研究出来这么多的锁
目的是
研究出来的锁越来越多
每种锁有每种锁的兼容性
对某个表加锁的时候就可以非常灵活
最大限度的来减少锁对数据的影响

研究这么多的锁
特别是后面几种锁
共享锁、共享行级排他锁 这后面这几种锁
有的人不太理解搞了加上这么多锁什么时候用
你总会用到

我们用什么锁关键是
我要锁什么资源
我锁的粒度是什么然后去选择相应的锁

在实际工作中总会用到

所以说用锁的时候
考虑我要锁什么资源
我锁的粒度是什么
锁多少
这时候自然就会找相关的锁

所以说这些锁
只要记住
锁越多,分的越细
那么将来我要锁资源的时候
可以选的就越多
那么它产生的一种并发的一种影响就越小
记住这个就行了

我们平时用的最多的是
行级锁、事务锁
这是我们平时涉及到最多的

再就是还有
表级别的RX锁还有RS锁
还有排它锁

这是我们平时接触最多的

共享锁、共享行级排它锁
用的相对比较少一些

十)锁的兼容性和加锁语句

对着兼容性就可以以后加锁的时候要注意一些

就可以知道
哪些锁可以兼容哪些锁不能兼容

所谓的兼容是两个锁可以同时在一个资源上加上

- S X RS RX SRX N/A S √ × √ × × √ X × × × × × √ RS √ × √ √ √ √ RX × × √ √ × √ SRX × × √ × × √ N/A √ √ √ √ √ √

表级锁之间的兼容性,有了这个锁,能不能有另外一个锁。

对RX来讲
RX锁和RX锁是兼容的
也就是
表上我加了RX锁还可以继续加RX

如果在表上加了RS了
在这个表上我可以同时加RS和RX
我对这个表 select for update
还可以继续对这个表select for update
同时我还可以对这个表进行DML
因为它都是兼容的

我们看表级别的X锁
它和表所有的锁都是排它的
也就是说
只要这个表上有任何一个锁都不能加X
当然了你加了X以后
任何锁都不能再加了

这就是表锁的兼容性

如果对表加了X的话对并发影响最大

这是这些锁
锁的兼容性的问题

还有加锁语句
各种锁是如何产生的

SQL语句 表锁定模式 允许的表锁定模式 Select * from (table_name)…… 无 RS、RX、S、SRX、X Insert into (table_name)…… RX RS、RX Update (table_name)…… RX RS、RX Delete from (table_name)…… RX RS、RX Select * from (table_name) for update RS RS、RX、S、SRX lock table (table_name) in row share mode RS RS、RX、S、SRX lock table (table_name) in row exclusive mode RX RS、RX lock table (table_name) in share mode S RS、S lock table (table_name) in share row exclusive mode SRX RS lock table (table_name) in exclusive mode X 无

可以通过DML进行自动的加锁,也可以使用LOCK手工加锁。

比如说我要select from某个表的时候
没有任何锁
对某个表进行增删改的时候
会在表上产生RX锁
这个我们可以理解
在这个表上有了RX以后
我们可以继续在表上加RS和RX

对某个表for update的时候
都会产生RS
有了RS以后
我们还可以在表上加RS、RX、S、SRX都可以加

也就是说RS的兼容性更好一些

还有底下这些SQL
直接对某个表lock
lock某个表,表的名字 然后 in RS

lock table in row share mode

Select * from for update
对这个表的锁都产生RS锁

下面这些lock table是手工加锁
而前面这些 select for update和DML都是自动产生的锁
底下的lock可以手工加锁

这两个表还是有参考意义的
大家事后保存一下

锁的释放非常简单就是
rollback和commit

关于锁的基础知识先讲到这个地方
我们底下研究锁相关的视图以及锁的相关的操作

十一)oracle锁总结

1)latch和lock

oracle的内存中有锁,数据库对象中也有锁

oracle数据库内存结构里面
有一个重要的特征就是使用了大量的链chain
如:共享池shared pool中librarycache中chunk的链,数据缓冲池buffercache中buffer的链

为了解决内存中链的争用使用闩叫latch来保护链
属于System Locks
是Oracle为保护内存结构而发明的一种资源
是Oracle提供的轻量级锁资源
是对内存数据结构提供互斥访问的一种机制

latch是一种低级排队(串行)机制
没有一个入队机制,一旦前面进程释放锁定,后面的进程就蜂拥而上,没有先来后到的概念
是一种快速的被获取和释放的内存锁

latch只作用于内存中;是瞬间的占用,释放;是非入队的;不存在死锁

内存中资源的锁叫latch
数据库对象(表,索引等)的锁叫Lock
Lock的释放需要等到事务正确的结束,他占用的时间长短由事务大小决定
并且Lock是入队的和Lock中存在死锁现象

在我们的使用中
实际操作需要考虑的是lock
latch是实例自动完成的

在数据库使用中
为了保护数据库元数据
在表和数据行使用锁lock
为了保证一个事务的完整性和尽量使多个事务可以并发

下面详细的叙述一下lock的类型

2)行级锁、事务锁和表级锁

lock锁都是由事务对数据行或表的占有产生的
在数据行上加的锁是行级锁
在表级别加的锁叫表级锁
行级锁标明位置在数据行上
表级锁标明的位置在表上
表级锁是对整个表的使用的说明
而行级锁是单个行的占有说明

一个事务有了行级锁后也就有了事务锁
事务锁是因为行级锁产生的
一个事务可以修改很多的行
这样每行都会加一个行级锁
但这个事务的所有行级锁都指向这个事务的事务锁
即使一个事务在多个表中都有行级锁
这些所有的行级锁同样使用的是一个事务锁
整个库的锁信息视图中也只有一个这个事务的事务锁信息
所以一个事务可以有很多的行级锁
也可以在不同表上有不同的表级锁
但一个事务只有一个事务锁

事务锁表明哪个事务正在修改数据行
一个事务修改了一个表中的某一行,要在表上的行上加上锁,这个行锁标明是哪个事务在操作
在数据块的事务槽和回滚段的事务表中会有这个事务的信息这就是事务锁
事务锁只有一种标明哪个事务正在修改数据
而行级锁它只指向那个操作这行的事务锁

行级锁只有一种X锁就是排它锁
在行上加了一个锁以后不再允许任何事务再在这个行上加锁
其它事务就不能再修改这个行了
这个行就属于这个事务了
其它的事务如果可以再修改表中的行
也只能修改其它行,不能修改已被占有的行
非要修改必须等待这个行的当前锁释放

表级锁TM是在表上加一个锁
表级锁是因为对表的操作或操作要求而产生的
表级锁用来说明本身事务正在对表做什么和其它事务还可以对表做什么操作

3)表级锁类型

表级锁有以下几种模式:
0:none
1:null 空
2:Row-S 行共享(RS / S锁):共享表锁
3:Row-X 行专用(RX / X锁):用于行的修改
4:Share 共享锁(S):阻止其他DML操作
5:S/Row-X 共享行专用(SRX):阻止其他事务操作
6:exclusive 专用(X):独立访问使用

数字越大锁级别越高,影响的操作越多。

一个事务拥有一种表锁以后和其它事务表锁的关系

- RS RX S SRX X N/A 锁编号 N/A √ √ √ √ √ √ 0或1 RS √ √ √ √ _ √ 2 RX √ √ _ _ _ √ 3 S √ _ √ _ _ √ 4 SRX √ _ _ _ _ √ 5 X _ _ _ _ _ √

可以看出
级别越高它占有的资源也越多
同时允许其它事务使用的资源也越少

如:
一个事务拥有了RX锁以后
其它事务只能在这个表上再加RS锁或RX锁
就是只能再进行产生RS锁和RX锁而所做的操作

一个事务拥有了S锁后
其它事务只能在这个表上再加RS锁或S锁

下面列出产生这些表级锁的语句:

表锁定模式        SQL语句                                                       允许的其它事务表锁定模式无                Select * from <table_name>……                                RS、RX、S、SRX、X RS                Select * from <table_name> for update                         RS、RX、S、SRX                          lock table <table_name> in row share mode RX                Insert into <table_name>……                                  RS、RX                  Update <table_name>……                                                Delete from <table_name>……                                      lock table <table_name> in row exclusive modeS                 lock table <table_name> in share mode                         RS、SSRX               lock table <table_name> in share row exclusive mode           RSX                 lock table <table_name> in exclusive mode                     无

4)S共享和X排它的区别

在锁类型名字中有X排它和S共享的区别

共享类型的锁有RS和S
排它类型的锁有RX和X
而SRX锁是RX和S锁的复合

一般的解释是:
当数据对象被加上排它锁时,其他的事务不能对它读取和修改
加了共享锁的数据对象可以被其他事务读取,但不能修改

但在oracle中事实是
不管加上什么类型的锁
其它事务都可以继续对对象读取
因为即使表加了最高级别的x锁,也是可以被其它事务读取访问的
而在锁作用数据级别上即使加的是共享锁
其它事务也不能在这个级别对它进行修改操作

同时在实际中可以看到
在作用数据级别上
没有实际的数据修改就会加共享锁
有实际的数据修改就会加排它锁
共享锁没有对数据做实际的修改所以可以和另一个没有修改数据的锁共存
排它锁对数据做实际的修改所以不能和其它锁共存

所以这里的共享和排它并不是对数据来说的
而是对锁本身来讲的
可以理解为共存的意思
锁能否共存要看锁影响的数据有没有冲突

所有的这些表级锁名字中的S和X即共享和排它都是在表级别上锁的排它和共享
在行级别只有排它锁
共享锁可以和其它共享锁共存
排它锁不能和其它的锁包括排它锁和共享锁共存

从所有锁的角度看
本事务要操作的数据可以加什么锁由其它事务已经做得操作来决定

5)锁的作用位置

这里还要说明这些锁的作用位置
RX锁和RS锁作用的最低位置也就是作用的基础是行
S锁和X锁作用的基础是表,不是表中的单个或部分行
RX锁和RS锁都在行上加的是排它锁
于此同时RX锁又在行所在表上加了表级别的排它锁
这里叫RX就是表上的行级排它锁
这两种锁为一体同时存在但作用于两个位置
RS锁在行加了排它锁后又在表级加了共享锁
所以RS锁和RX锁都有两部分
作用单位是行同时表上也加了锁
加的时候同时加但使用时要分开看

在表上加锁并不会开始一个事务
只有在行上加了锁后才会产生事务锁才会开始一个事务

因为直接使用lock命令加锁v$transaction中不会产生事务相关的记录

只有在DML语句执行后
行级锁加上后,v$transaction中才会出现一个相关的记录

各种锁的共享和排它在共同作用的基础数据上决定

RX和RS是否同时加
因为它们的最低基础都是行
它们之间在表上加锁时都是相容的
在表上加了一个RX或RS锁后可以随时加另外一个RS或RX锁

但它们在行上加的锁仍然是排它的

在一个表上加了RS锁后
另一个事务要加的RS锁如果锁定的行和前面一个锁相同
在表上加了RS锁后
在冲突行加事务锁会发生等待

但这另一个事务可以立即在其它未锁定行加上锁

RS锁和RX锁的作用基本单位是行
所以多个RS锁和RX锁可以在一个表上同时存在

S锁和X锁作用最低基础是表
这两种锁的相互作用是
在加这两种锁时由表上是否加了S或X锁决定
一个共享锁S锁可以和其它的S锁共存
一个排它锁X锁不能和任何其它的S锁或X锁共存

而(RX或RS)和(S或X)是否可以同时加
因为S和X锁最低基础是表,
RX锁和RS锁在表上有锁,虽然他们的最低作用基础是数据行
但这四种锁它们共同的最低作用基础是表
所以这里由表上的锁决定

RX在表上加的是排它锁,所以加了RX锁后S锁或X锁都不能再加了
RS在表上加的是共享锁,所以加了RS锁后可以继续加S锁不能继续加X锁
在表上加了S锁后,RS在表也是加的共享锁,所以可以继续加RS锁
在表上加了S锁后,RX在表上加的是排它锁,所以不能再加RX锁了
在表上先加了X锁后它排斥所有的其它锁,所以RS锁和RX锁在表上就不能添加了
当然RS锁或RX锁整体的两部分中在表上部分不能添加,整个锁包括在行上的锁也就不能添加了

下面有一个实验的结果:

       SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK---------- -- ---------- ---------- ------------------- ------------------- ----------       147 TM      51857          0 None                Row Exclusive                0       150 TM      51857          0 Share               None                         1

这是一个150会话对表employees加了S锁后
另一个147会话要对表employees加RX锁的例子
S锁加上后,再加RX锁
RX处于请求状态,S锁把RX锁阻塞住了
就是加了S锁后另一事务不能同时再加RX锁

所有的锁能否共存
是在它们共同作用的最低基础数据单位水平来相互衡量的
原则是不会影响到其它事务已经加在数据上的锁和已经锁住的内容

SRX锁是RX锁和S锁的复合
表上加了S锁后还允许RS和S锁
RX锁加了后还允许加RS和RX
S锁和RX锁共同允许的只有RS锁
所以SRX锁加了后就只允许RS锁

6)同一事务中锁的叠加

当一个事务给表加了一个锁后
它允许表的锁定模式是指其它事务还能在这个表上加什么类型的锁
当碰到不能共存的锁时
后一个加锁的事务这时会得不到执行会等待前一个事务的锁释放

而在同一个事务中
在它给一个表加了锁后,如果没有其它事务已经对这个表加的锁,
它仍然可以对这个表进行任何操作
也就是可以继续做任何类型的锁操作

当一个事务继续进行加锁的操作
它在这个表的TM表级锁任然只有一个
它使用事务中已经使用的级别最高的锁类型

如:
加了RS锁后又加了RX锁
这时这个事务在这个表上是RX锁

加了x锁后又加了RX锁
或者加了RX锁后又加了X锁
这时的锁类型是X锁

如果同时加了X锁和SRX锁不管时间先后
最后的TM锁类型是X锁

RS锁和S锁相比S锁的级别高
同时加了S锁和RS锁后得到的表级锁是S锁

当一个事务
对一个表加了RX锁后又加了S锁
或加了S锁后又加了RX锁
这时这两种锁会复合为更高级别的SRX锁
这个事务对这个表的表级锁就是SRX类型

也就是同一个事务在没有其它事务影响下
可以给同一个表同时进行任何类型的操作
但最后结果它对这个表加的锁的类型是使用过的级别最高的锁的类型

一个锁对其它锁的限制只是指一个事务的锁对其它事务加锁的限制

7)一个版本造成的歧义

在实践的操作中
本人想使用select for update看看得到的RS锁
但是得到的却都是RX锁

开始以为是自己操作的问题

但上网查询其它使用者也有同样的情况

并且有以下的陈述:
select for update
10G产生的是RX锁
而oracle 8和9产生的是RS锁

在10G实践中有些语句是可以产生RS锁的,如delete时在其它表会产生
说明10G并没有取消RS锁
这里单独执行select for update产生的却不是RS锁

最终只能归结为这是又一个版本升级造成的不愉快的地方

oracle版本升级,改变了很多的内容
可能一时看不出来,但稍微深入使用,往往都会无奈的发现
到底如何对待往往也是两难的选择
重新学习或使用原来的内容 ,是两个使用者面临的选择!

2017年12月12日
文字:韵筝

原创粉丝点击