在 Oracle 中发出 COMMIT 之前 INSERT 是如何工作的
我的问题是 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;
My question is how oracle treats an INSERT transaction before issuing a COMMIT.
While I am doing an INSERT transaction, will oracle wait until I have inserted all my records within that procedure and then when I issue a COMMIT statement will the records be saved in a sequence for this transaction?
In the following code, the first insert that is made is the number of rows (metadata) and then the cursor loops and starts inserting the actual data.
Is there a possibility, in one transaction when I call this procedure, first my metadata record is inserted and then some other data (not related to this transaction) be inserted and then rest of my data. So that, the first record and the rest of the records from the loop are not inserted in a Sequence.
-- 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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
另一个事务可以与您的事务同时执行插入,但您的事务不会看到它们:
这是否会产生正确的行为,由您决定。
请注意
SELECT COUNT(*) ...
- 它可能不会返回您期望的结果。考虑以下场景:SELECT COUNT(*) FROM EMP
并且也得到1(出于相同的原因但相反)。因此,尽管表实际上有 2 行,但还是插入了 1 行!
不幸的是,即使是 Oracle 的 SERIALIZABLE 隔离也无法避免这种异常情况。如果锁定,几乎是保证“正确”结果的唯一方法整个表,因此不会发生并发插入(或删除)。
Another transaction can perform inserts concurrently to your transaction, but your transaction won't see them:
Whether this will yield a correct behavior, is for you to decide.
Just be careful about
SELECT COUNT(*) ...
- it may not return what you expect. Consider the following scenario:SELECT COUNT(*) FROM EMP
and gets 1 (because it sees its own newly inserted row, but does not see B's newly inserted row since B did not commit yet).SELECT COUNT(*) FROM EMP
and also gets 1 (for the same reason but in reverse).So, 1 is inserted despite table actually having 2 rows!
Unfortunately not even Oracle's SERIALIZABLE isolation will save you from this kind of anomaly. Pretty much the only way to guarantee the "correct" result if to lock the entire table, so no concurrent inserts (or deletes) can occur.
如果可能,请使用单个 SQL 语句。它将具有语句级读取一致性,并且速度会快得多。
Use a single SQL statement if possible. It will have statement-level read consistency, and will be much faster.
您要在 Google 上搜索的术语是“读取一致性”:
http: //docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm
底线:
As你知道,如果你回滚,就好像插入“从未发生过”
但是,其他东西可以(并且可能确实发生过)同时“发生”。
The term you want to google for is "read consistency":
http://docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm
Bottom line:
As you know, if you rollback, it's as though the inserts "never happened"
However, other stuff can (and probably did) "happen" in the meantime.
您需要在可序列化隔离级别中运行:
http://docs.oracle.com/cd/E11882_01/server.112/e16508/consist.htm#BABCJIDI
“可序列化事务仅看到事务时提交的那些更改开始,加上事务本身通过 INSERT、UPDATE 和 DELETE 语句进行的更改不会经历不可重复的读取或操作。幻影。”
You need to run in the Serializable Isolation Level:
http://docs.oracle.com/cd/E11882_01/server.112/e16508/consist.htm#BABCJIDI
"Serializable transactions see only those changes that were committed at the time the transaction began, plus those changes made by the transaction itself through INSERT, UPDATE, and DELETE statements. Serializable transactions do not experience nonrepeatable reads or phantoms."