8

如果我在 pl/sql developer 中针对数据库表执行一个简单的选择语句,我会得到一组标准的结果,正如我所期望的那样。

最近,我从碰巧从视图中选择的存储过程中粘贴了一个查询,并注意到一个事务似乎处于打开状态。回滚和提交选项在 PL/SQL 开发人员中可用。

对其他开发人员的一项民意调查显示,这似乎会影响某些人,但不会影响其他人,这使我怀疑 PL/SQL Developer 设置。

为什么会出现这种情况?视图 itelf 有一个到另一个数据库的 DBLink,但我不希望这会产生任何影响。

有什么想法吗?

4

6 回答 6

20

与您的预期相反,看起来数据库链接打开事务的来源。在 PL/SQL Developer 中对远程表运行 SELECT 查询时,我已经注意到了这样的行为。

引用 Tom Kyte(来源):

分布式的东西“以防万一”启动事务。

编辑:'任何 SQL 语句在 Oracle 中启动事务'?不,它没有,这里有一个演示。该演示使用数据字典视图V$TRANSACTION,其中列出了活动的事务。这一切都在我的本地 Oracle XE 数据库上运行,除了我之外没有其他用户连接到它。

在此演示期间,我们将使用下表。它仅包含一列:

SQL> 描述测试;
 名称空?类型
 ----------------------------------------- -------- - --------------------------
 一个数字(38)

SQL> 从 v$transaction 中选择计数(*);

  计数(1)
----------
         0

目前没有活跃的交易。让我们对这个表运行一个 SQL 查询:

SQL> 从测试中选择 *;

         一种
----------
         2

SQL> 从 v$transaction 中选择计数(*);

  计数(1)
----------
         0

仍然没有活跃的交易。现在让我们做一些将启动事务的事情:

SQL> 插入测试值 (1);

创建了 1 行。

SQL> 从 v$transaction 中选择计数(*);

  计数(1)
----------
         1

正如预期的那样,我们现在有一个活跃的交易。

SQL>提交;

提交完成。

SQL> 从 v$transaction 中选择计数(*);

  计数(1)
----------
         0

提交事务后,它不再处于活动状态。

现在,让我们创建一个数据库链接。我正在使用 Oracle XE,以下创建了一个从我的 Oracle XE 实例返回到自身的数据库链接:

SQL> 创建数据库链接 loopback_xe 使用“XE”连接到由密码标识的用户;

已创建数据库链接。

现在让我们看看当我们通过数据库链接从表中选择时会发生什么:

SQL> 从 v$transaction 中选择计数(*);

  计数(1)
----------
         0

SQL> select * from test@loopback_xe;

         一种
----------
         2
         1

SQL> 从 v$transaction 中选择计数(*);

  计数(1)
----------
         1

如您所见,只需从远程表中选择即可打开一个事务。

我不确定这里到底有什么要提交或回滚,但我不得不承认不知道分布式事务的来龙去脉,答案可能就在其中。

于 2010-12-20T11:06:55.917 回答
3

任何SQL 语句都会在 Oracle 中启动一个事务。

从手册:

事务从第一个可执行的 SQL 语句开始。事务在提交或回滚时结束,可以使用 COMMIT 或 ROLLBACK 语句显式地结束,也可以在发出 DDL 语句时隐式地结束。[...]可执行SQL 语句是生成对实例的调用的 SQL 语句,包括 DML 和 DDL 语句

很可能那些没有看到这一点的人正在以自动提交模式运行,其中由语句启动的事务在语句完成后立即提交。

其他人声称 aSELECT不是 DML,但手册再次明确指出

数据操作语言 (DML) 语句查询或操作现有模式对象中的数据。它们使您能够:

   * 从一个或多个表或视图中检索或获取数据 (SELECT)
   * 将新的数据行添加到表或视图中 (INSERT)
[...]
于 2010-12-20T10:55:20.390 回答
1

您绝对不能使用普通查询严格打开事务。您可以通过数据库链接打开一个。发布医生链接的人故意或完全不小心遗漏了第二句话。

“Oracle 数据库中的事务在遇到第一个可执行 SQL 语句时开始。可执行 SQL 语句是生成对实例的调用的 SQL 语句,包括 DML 和 DDL 语句。”

SELECT 既不是 DML 也不是 DDL。实际测试这一点也很简单。我不想在这里像一个巨魔一样脱落,但是当人们只是在论坛上抛出答案以试图获得积分并且答案完全是垃圾时,这真的很烦人。

阅读文档的其余部分并首先进行测试。

  • 登录会话
  • 运行选择
  • v$Session通过加入(为您的会话)来查看您是否有未结交易v$transaction

如果有记录返回,您就有了交易。如果没有,你不会。

于 2012-04-04T16:02:09.260 回答
1

请注意,根据Oracle 11g 管理员指南,如果您在数据库链接上执行普通的旧 SELECT,您将启动一个需要提交(或回滚)的事务。

于 2015-01-20T19:20:49.707 回答
0

Select 只是 DML 的一部分,但不获取锁,在插入/更新/删除/选择更新时获取行锁。-罗斯是对的。

https://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_locks001.htm#SQLRF55502

                        ROW Lock    Table lock

SELECT ... FROM 表... ----- 无

INSERT INTO 表 ... 是 SX

与更新删除和选择更新相同。

于 2019-02-20T13:45:22.250 回答
0

TLDR:在从远程数据库中选择时,您还可以为远程数据库创建会话和连接。只要本地用户会话,该会话和连接就会持续存在。正如您可以猜到的那样,这可能会导致跟上会话和连接的一些问题。

所以总是做一个承诺: SELECT * FROM emp@sales; 犯罪;

我喜欢长读部分

这也让我非常烦恼,为什么从 db_links 中选择有一个事务,并决定最终从 oracle 文档中结束它:

Oracle® 数据库管理员指南 11g 第 2 版 (11.2) https://docs.oracle.com/html/E25494_01/ds_appdev002.htm

控制由数据库链接建立的连接 当在 SQL 语句或远程过程调用中引用全局对象名称时,数据库链接代表本地用户建立到远程数据库中的会话的连接。仅当先前尚未为本地用户会话建立连接时,才会创建远程连接和会话。

与远程数据库建立的连接和会话在本地用户会话期间持续存在,除非应用程序或用户明确终止它们。请注意,当您跨数据库链接发出 SELECT 语句时,会在撤消段上放置事务锁。要重新释放段,您必须发出 COMMIT 或 ROLLBACK 语句。

终止使用数据库链接建立的远程连接对于断开应用程序不再需要的高成本连接很有用。您可以使用带有 CLOSE DATABASE LINK 子句的 ALTER SESSION 语句终止远程连接和会话。例如,假设您发出以下交易:

选择 * 从 emp@sales; 犯罪; 以下语句终止销售数据库链接指向的远程数据库中的会话:

ALTER SESSION CLOSE DATABASE LINK 销售;要关闭用户会话中的数据库链接连接,您必须具有 ALTER SESSION 系统权限。

注意:在关闭数据库链接之前,首先关闭所有使用该链接的游标,如果它使用该链接,则结束当前事务。

另请参阅:Oracle 数据库 SQL 语言参考以获取有关 ALTER SESSION 语句的更多信息

于 2020-05-27T11:35:36.803 回答