数据库并发操作
来源:互联网 发布:淘宝商品品牌 编辑:程序博客网 时间:2024/06/04 19:57
在项目中,有一竞价模块,多个用户在竞价结束时,系统自动录入结果,系统操作为,先查询对应的结果,如果没有就向数据库插入数据。
出现的问题,第一次请求到时,无结果,插入;第二次请求到时,查询无结果(未查到插入的结果),再次插入了结果;第三次请求查到了结果。
解决方案:用行级排他锁。
具体实现:
//给数据加锁,防止数据重复插入String sql = "select 1 from a s where s.b = ? for update ";Db.query(sql, new Object[]{id});
数据库锁机制:
两种锁机制
共享锁(Share Lock):即S锁,是通过对数据存取的高并行性来实现的。加了共享锁的数据库对象可以被其它事务读取,但是不能被其它事务修改。
独占锁(Exclusive Lock):即X锁,又称排它锁,是用来防止同时共享相同资源的锁。加了独占锁的数据库对象不能被其它事务读取和修改。
默认情况下的select ... for update语句与DML语句相似,效果相当于启动了一个会话级别的事务,在对应的数据表(select所涉及的所有数据表)上加入一个数据表级共享锁(TM,lmode=3)。同时,在对应的数据行中加入独占锁(TX,lmode=6)。
以下来自也网络
SQL> select * from t1;
ID
1
2
3
4
SQL> alter table t1 add primary key(id);
表已更改。
SQL> select * from v$lock where type in ('TX','TM');
未选定行
SQL> insert into t1 values(5);
已创建 1 行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
141 TM 82975 0 3 0 0
141 TX 131084 1787 6 0 0
会话二:
SQL> insert into t1 values(5);
__
(阻塞)
会话一:
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
19 TX 131084 1787 0 4 0
(此处出现申请4号锁,insert本身没有阻塞,而是在等待判断主键冲突否)
19 TM 82975 0 3 0 0
141 TM 82975 0 3 0 0
19 TX 327697 1662 6 0 0
141 TX 131084 1787 6 0 1
SQL> update t1 set id=5 where id=4;
已更新 1 行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
141 TM 82975 0 3 0 0
141 TX 327706 1663 6 0 0
SQL> select sid from v$mystat where rownum=1;
SID
141
SQL> select sid,event from v$session_wait where sid in(141,19);
SID EVENT
---------- ----------------------------------------------------------------
19 SQL*Net message from client
141 SQL*Net message from client
会话二:
SQL> select sid from v$mystat where rownum=1;
SID
19
SQL> update t1 set id=5 where id=4;
__(阻塞)
会话一:
SQL> select sid,event from v$session_wait where sid in(141,19);
SID EVENT
---------- ----------------------------------------------------------------
19 enq: TX - row lock contention(等待事件出现tx锁,原因是行锁争用)
141 SQL*Net message from client
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
19 TX 327706 1663 0 6 0
(可以看到会话二在申请6号锁,而141的TX锁block为1,表示阻塞了别的会话)
19 TM 82975 0 3 0 0
141 TM 82975 0 3 0 0
141 TX 327706 1663 6 0 1
SQL> delete t1 where id=4;
已删除 1 行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
141 TM 82975 0 3 0 0
141 TX 327706 1663 6 0 0
SQL> select sid from v$mystat where rownum=1;
SID
141
SQL> select sid,event from v$session_wait where sid in(141,19);
SID EVENT
---------- ----------------------------------------------------------------
19 SQL*Net message from client
141 SQL*Net message from client
会话二:
SQL> select sid from v$mystat where rownum=1;
SID
19
SQL> delete t1 where id=4;
__(阻塞)
会话一:
SQL> select sid,event from v$session_wait where sid in(141,19);
SID EVENT
---------- ----------------------------------------------------------------
19 enq: TX - row lock contention(等待事件出现tx锁,原因是行锁争用)
141 SQL*Net message from client
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
19 TX 327706 1663 0 6 0
(可以看到会话二在申请6号锁,而141的TX锁block为1,表示阻塞了别的会话)
19 TM 82975 0 3 0 0
141 TM 82975 0 3 0 0
141 TX 327706 1663 6 0 1
KADDR
SID:锁所在的会话id
TYPE:锁的类型,类型有很多种,常用的有TX(事务锁)、TM锁(表级锁)
ID1:TM锁为对象的object_id,TX锁为v$transaction 中 XIDUSN * 2^16 + XIDSLOT
ID2:TM锁为0,TX锁为v$transaction 中 XIDSQN
LMODE:锁的模式,有2~6,越大锁的限制越高,
REQUEST:为0表示没有申请锁,其他2~6表示在申请该模式的锁
CTIME:表示锁从出现到现在的时间
BLOCK:为1表示阻塞了其他会话申请锁,为0表示没有阻塞别人。
会话一:
SQL> lock table t1 in share mode;
表已锁定。
会话二:
SQL> update t1 set id=11 where id=1;
__(等待)
直到会话一commit或roll,会话二执行。
锁模式
锁描述
含义
锁定表的SQL
0
None
1
Null
空,本模式是oracle预留模式
2
Row Share(RS)
又叫(SS)
行级共享锁,是限制最少的TM锁,可以提供最高程度的并发性。其他会话可以对锁定的表进行任何类型的DML操作,还可以与其他会话锁并存
Lock table t1 in row share mode;
3
Row Exclusive Table Lock(RX)
又叫(SX)
行级排他锁,通常已经有事务在修改行或者select…for update 修改结果集。允许其他事务对锁定的表进行select insert update delete 或 lock table 同时锁定一张表
Lock table t1 in row exclusive mode;
4
Share Table Lock(S)
共享锁,其他事务可以查询锁定的表但不能修改,只允许当前事务修改,但可以多个事务持有它
Lock table t1 in share mode;
5
Share Row Exclusive Table Lock(SRX)
又叫SSX
共享行级排他锁,同一时间只允许一个事务持有和修改锁定的表,其他事务可以查询但不能修改
Lock table t in share row exclusive mode;
6
Exclusive Table Lock (X)
排他锁,是限制最高的TM锁,禁止其他事务执行任何类型的DML语句或者锁表
一个表一般只能有一个6号锁
Lock table t1 in exclusive mode;
锁模式
锁名称
允许级别
互斥级别
2
行级共享锁
2 3 4 5 6
6
3
行级排他锁
2 3
4 5 6
4
共享锁
2 4
3 5 6
5
共享行级排他锁
2
3 4 5 6
6
排他锁
2 3 4 5 6
1、NULL,可以某些情况下,如分布式数据库的查询会产生此锁。
2、SS,表结构共享锁
3、SX,表结构共享锁+被操作的记录的排它锁
4、S, 表结构共享锁+所有记录共享锁
5、SRX 表结构共享锁+所有记录排它锁
6、X 表结构排它锁+所有记录排它锁
2 SS, 表结构共享+加上部分数据共享.虽然有人说,ORACLE里,数据没有S状态,但我还是愿意这 样理解:第1个S代表表结构共享,第2个代表表里的数据共享. 你可以想象一下,当往子表里增 加纪录时,主表的相关主键是不是得处于共享模式.
3 SX, 用于DML操作,第1个S代表表结构共享,第2个代表表里被操作的数据独占.
4 S, 代表表结构+表里的数据都是处于共享模式.当对表创建索引时,在创建期间,表处于这种模式.
5 SRX=S(4)+SX(3),
6 X, 删除表是会用上.
表已锁定。
141> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
141 TM 82975 0 2 0 0
19> select * from t1 for update; //另开会话给t1上3和6号锁
ID
----------
1
2
3
4
141> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
19 TM 82975 0 3 0 0
141 TM 82975 0 2 0 0
19 TX 393221 1754 6 0 0
可以看到236可以共存,没有互斥
19> lock table t1 in share mode; //给表再上4号锁
表已锁定。
141> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
19 TM 82975 0 5 0 0
141 TM 82975 0 2 0 0
19 TX 393221 1754 6 0 0
因为3和4不能共存,因此3+4升级为5号锁
19> lock table t1 in exclusive mode; //给表上6号锁,发生等待
__
141> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
19 TM 82975 0 5 6 1
141 TM 82975 0 2 0 1
19 TX 393221 1754 6 0 0
因为同是19号会话,上6号TM只需将原有5升级,但是已经存在2号TM,产生互斥,所以等待
表已锁定。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
141 TM 82975 0 6 0 0
SQL> update t1 set id=5 where id=4;
已更新 1 行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
141 TM 82975 0 6 0 0
141 TX 262155 1324 6 0 0
表已锁定。
141> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM') order by 1;
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
141 TM 82975 0 2 0 0
19> update t1 set id=6 where id=4;
已更新 1 行。
141> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
19 TM 82975 0 3 0 0
141 TM 82975 0 2 0 0
19 TX 458778 1387 6 0 0
会话一:
SQL> update t1 set id=11 where id=1;
已更新 1 行。
会话二:
SQL> update t2 set id=11 where id=1;
已更新 1 行。
会话一:
SQL> update t2 set id=11 where id=1;
__(等待)
会话二:
SQL> update t1 set id=11 where id=1;
__(等待)
会话一:
SQL> update t2 set id=11 where id=1;
update t2 set id=11 where id=1
*
第 1 行出现错误:
ORA-00060: 等待资源时检测到死锁
- 数据库并发操作
- 数据库并发操作
- 基本数据库并发操作
- 数据库的并发操作
- 数据库并发操作
- 数据库并发操作
- 并发操作导致数据库不一致性
- oracle数据库事务并发操作
- 【数据库】数据库并发操作(二)数据库并发控制机制
- 多线程并发操作数据库以及数据库升级
- 数据库锁 sql 数据库大并发操作 数据库原子操作
- 数据库锁 sql 数据库大并发操作 数据库原子操作
- 数据库并发操作的一致性问题
- 数据库的两种并发操作
- 数据库并发操作的一致性问题
- 数据库并发操作丢失更新解决方案
- 大并发下,数据库的操作
- 数据库并发操作与数据的不一致性
- C#之构造函数的学习
- 初步学习mysql
- QQ 引流引发的灰色地带产业
- PlayerMaker插件
- MTK点亮新模组
- 数据库并发操作
- 完美运动(链式运动)JS框架
- win10 uwp 如何打包Nuget给其他人
- h5改变
- UGUI研究院之UI的深度学习
- 电子商务javaweb b2b b2c o2o平台
- 【转】HashMap原理
- 线程服务的停止与启动
- centos7软件安装