我的问题是oracle在发出COMMIT之前如何处理INSERT事务。
当我正在进行INSERT事务时,oracle是否会等到我在该过程中插入所有记录,然后当我发出COMMIT语句时,是否会将记录保存在此事务的序列中?
在下面的代码中,第一个插入是行数(元数据),然后光标循环并开始插入实际数据。
有可能,在我调用此过程的一个事务中,首先插入我的元数据记录,然后插入一些其他数据(与此事务无关),然后插入其余的数据。因此,循环中的第一条记录和其余记录不会插入序列中。
-- This code belongs to proecdure when ever a user clicks on insert
-- button from the front end form
DECLARE
rowcnt NUMBER;
CURSOR c_get_employ IS
SELECT EMP.EMPLOYER_ID, EMP.EMPLOYER_NAME, EMP.EMPLOYER_LOCATION
FROM EMP
WHERE EMP.EMPLOYER_COUNTRY = 'USA'
ORDER BY EMP.EMPLOYER_ID;
BEGIN
Select count(*)
INTO rowcnt
FROM EMP
WHERE EMP.EMPLOYER_COUNTRY = 'USA'
ORDER BY EMP.EMPLOYER_ID;
-- I want to insert the 'number of employee records' that will be inserted (metadata)
INSERT INTO EMP_OUTPUT
(EMPID, EMPNAME, EMPLOC, ECOUNT)
VALUES
(,,,rowcnt);
-- Then loop through the cursor and start inserting the data
FOR c_post_employ IN c_get_employ LOOP
INSERT INTO EMP_OUTPUT
(EMPID, EMPNAME, EMPLOC)
VALUES
(c_post_employ.EMPLOYER_ID,c_post_employ.EMPLOYER_NAME,c_post_employ.EMPLOYER_LOCATION);
END LOOP;
COMMIT;
END;
答案 0 :(得分:4)
另一项交易可以同时对您的交易执行插入,但您的交易无法看到它们:
这是否会产生正确的行为,由你决定。
请注意SELECT COUNT(*) ...
- 它可能无法返回您的期望。请考虑以下情形:
SELECT COUNT(*) FROM EMP
并获得1(因为它看到了自己新插入的行,但由于B尚未提交,因此没有看到B'新插入的行)。SELECT COUNT(*) FROM EMP
并且也获得1(出于同样的原因但反之)。因此,尽管表实际上有2行,但仍插入1!
不幸的是,即使是Oracle的SERIALIZABLE隔离也不会让你免于这种异常现象。几乎是保证"正确"的唯一方法。结果if lock the entire table,因此不会发生并发插入(或删除)。
答案 1 :(得分:2)
如果可能,请使用单个SQL语句。它将具有语句级读取一致性,并且会更快。
insert into emp_output(empid, empname, emploc, ecount)
with employees as
(
select employer_id, employee_name, employer_location
from emp
where employer_country = 'USA'
order by employer_id
)
select null, null, null, count(*) from employees
union all
select employer_id, employee_name, employer_location, null from employees;
答案 2 :(得分:1)
您想谷歌的术语是“读取一致性”:
http://docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm
底线:
如您所知,如果您回滚,就好像插件“从未发生过”
然而,其他东西可能(并且可能确实)在此期间“发生”。
答案 3 :(得分:1)
您需要在Serializable Isolation Level中运行:
http://docs.oracle.com/cd/E11882_01/server.112/e16508/consist.htm#BABCJIDI
“可序列化事务只查看事务开始时提交的那些更改,以及事务本身通过INSERT,UPDATE和DELETE语句所做的更改。可序列化事务不会遇到不可重复的读取或幻像。”