• insert 阻塞概念
  • 1、无主键插入同样的数据
  • 2、 有主键时插入同样的数据


insert 阻塞概念

insert 阻塞情况不多见,最常见的情况是,你有一个带主键的表,或者有唯一性约束,但有两个会话视图用
同样的值插入一行,但是如果这样,其中一个会话会被阻塞,知道另一个会话,提交或者回滚为止;
如果另外一个会话提交,那么阻塞的会话会收到一个错误,指出存在一个重复值;倘若另一会话回滚,在这种情况下
阻塞的会话则会成功。还有一种情况,可能存在多个表通过引用完整性约束相互连接。对子表的插入可能会阻塞,如果它依赖父表中的行正在创建或删除。发生insert 阻塞 通常因为应用允许最终用户自己生成主键/唯一列值。为避免这种情况,最容易的做法是使用一个序列或sys_guid()内置函数来生成主键/唯一列值。序列/sys_guid()是被设计在用于多用户
环境中,以高并发生成唯一键值。如果这两个都没法用,并且必须运行用户生成可能重复的键,那应该使用手工锁
来避免这个问题,这里的手工锁是通过dbms_lock 包来实现

1、无主键插入同样的数据

来看员工emp_a表 此时没有主键 数据如下。

oracle insert 阻塞实例_主键


此时有两个用户向员工表中插入 信息7935,‘Jones’,‘SALESMAN’,而第一个用户还未提交,第二个用户就

进行插入。

第一个用户插入数据

INSERT INTO emp_a VALUES (7935, 'Jones', 'SALESMAN');

oracle insert 阻塞实例_oracle insert 阻塞实例演示_02


第二个用户插入数据,此时第一个用户并未提交,此时第二个用户能插入数据吗?

oracle insert 阻塞实例_oracle insert 阻塞实例演示_03


看到结果也能插入 我们两个用户都进行提交。

oracle insert 阻塞实例_oracle insert 阻塞实例演示_04


查看数据,很明显 该数据插入了2条

oracle insert 阻塞实例_插入数据_05


当然这不是我们想看到的,所以 我们给员工表在编号上加上了主键

继续看如下实例

2、 有主键时插入同样的数据

---删除数据
DELETE FROM emp_a t WHERE t.empno = 7935 ;
--增加主键
alter table  emp_a add constraint pk_emp_a primary key (empno);

然后我们再次重复先前的插入操作。

oracle insert 阻塞实例_数据_06


看到用户1在插入数据后,还未及时提交,而用户2进行插入时发生了阻塞,

此时会有两种情况发生

1、用户1觉得插入数据没有问题,进行了提交,提交后用户2就会提示错误 违反主键约束

oracle insert 阻塞实例_oralce避免插入重复数据_07


2、用户1觉得插入数据好像有问题,进行了回滚 ,那用户2就会成功插入数据

oracle insert 阻塞实例_数据_08

所以解决避免重复数据插入的方法之一就是主键最好由系统控制,而不是由用户控制。