这是this question的后续行动。
Oracle在执行eventcreate
的{{1}} Windows命令时遇到麻烦。
作为一种解决方法,我创建了一个基本的C#应用程序来执行相同的DBMS_SCHEDULER
函数。它可以在基本水平上运行,但我面临一些障碍。
这是程序。 (我没有在这个问题中标记C#,因为这个问题不是关于C#的。我只是将其作为信息提供。)
eventcreate
我将using System;
using System.Diagnostics;
class myEventCreateClass
{
public static void Main(String[] args)
{
using(EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "MySource";
eventLog.WriteEntry(args[0], EventLogEntryType.Warning, 218);
}
}
}
作业修改为此:
DBMS_SCHEDULER
当我在BEGIN
sys.dbms_scheduler.create_job(
job_name => 'SYS.TESTJOB',
job_type => 'EXECUTABLE',
job_action => 'C:\myEventCreate.exe',
job_class => 'DEFAULT_JOB_CLASS',
number_of_arguments => 1,
auto_drop => FALSE,
enabled => FALSE);
sys.dbms_scheduler.set_job_argument_value('SYS.TESTJOB', 1, 'testing123');
sys.dbms_scheduler.enable('SYS.TESTJOB');
END;
模式下手动运行此作业时,它成功地将一个事件放入Windows事件日志中,内容为:
SYS
这就是我成功的终点...
如果我在不同的架构下创建同一作业(例如,将testing123
的所有实例更改为SYS.TESTJOB
),它将在该架构下创建作业,但是当我决定运行该作业时(从任何模式),我得到以下一长串错误:
MYSCHEMA.TESTJOB
当我尝试从ORA-27370: job slave failed to launch a job of type EXECUTABLE
ORA-27300: OS system dependent operation:accessing job scheduler service failed with status: 2
ORA-27301: OS failure message: The system cannot find the file specified.
ORA-27302: failure occurred at: sjsec 6a
ORA-27303: additional information: The system cannot find the file specified.
ORA-06512: at "SYS.DBMS_ISCHED", line 185
ORA-06512: at "SYS.DBMS_SCHEDULER", line 486
ORA-06512: at line 1
运行SYS.TESTJOB
时,它告诉我该作业不存在:
MYSCHEMA
如何通过ORA-27476: "SYS.TESTJOB" does not exist
ORA-06512: at "SYS.DBMS_ISCHED", line 185
ORA-06512: at "SYS.DBMS_SCHEDULER", line 486
ORA-06512: at line 1
以外的其他模式来完成这项工作?
另一个问题(可能是更大的问题):我正在尝试从触发器内部运行此作业。
根据this question,更改SYS
作业的设置(在我的情况下,每次运行作业前我都试图更改作业参数)会导致隐式{{1 }},在触发器中是不允许的。
对我来说,Oracle甚至将它们标记为“参数”似乎是一种误导,因为参数的值在作业内部是固定的,而更改参数意味着更改作业本身。
无论如何,此问题中被接受的答案是说使用DBMS_SCHEDULER
,因为它不会隐式COMMIT
,但是我找不到使用DBMS_JOB
来运行外部{ {1}}文件。
因此,有可能以某种方式修改此作业以允许动态作业参数吗?
我也对其他解决方案持开放态度,但据我所读,COMMIT
似乎是实现此目的的最佳方法。
根据要求,以下是我要完成的工作的上下文:
在我公司,我们对其进行了设置,如果将某个条目放置在Windows事件日志中的某个特定来源下(例如,在这种情况下,如提供的C#应用程序中所示的DBMS_JOB
),则文本包含用户日志消息内容的消息会自动发送给我本人和其他一些管理员的手机。
这非常有用,因为它可以立即通知我们发生了一些重要事件,并且我们可以准确地控制我们要包括的事件以及想要通知这些事件的具体信息。
以下是我们当前通过短信收到通知的一些示例:
我想将此功能扩展到Oracle数据库中的某些事件(这就是为什么我试图基于Oracle中的触发器将事件放入事件日志中的原因。)
到目前为止,我想着一些要通过短信通知的事情,所有这些都可以在触发器内确定:
当不在某个“批准的”用户列表中的任何人(这将是我们的管理员以及与Oracle连接的自定义应用程序)连接到我们的Oracle数据库。这可以通过登录触发器来完成。 (实际上,由于登录触发器由.exe
模式调用,因此我已经可以使用该模式了,因此我对其他模式无法运行该任务没有任何疑问。但是...因为我仍然可以请勿更改任何参数,我目前能做的最好只是说DBMS_SCHEDULER
。如果我可以将用户名传递给Windows事件日志,这会很有用。)
当除自定义应用程序以外的任何其他内容更改Oracle数据库中的数据时。 (我们的自定义应用程序可以处理所有插入/更新/删除等操作。只有在极少数情况下,我们才需要手动修改某些内容。我们希望在 任何人 时收到通知[包括我自己或其他管理员在内的人]都会修改数据库的任何内容。)这可以通过对每个表进行更新/插入/删除触发器来实现。
答案 0 :(得分:1)
它在 SYS 下工作的原因是它是特殊特权帐户。您需要创建一个新凭据并将其映射到作业
解决方案是使用DBMS_SCHEDULER.CREATE_CREDENTIAL和具有足够特权的OS帐户创建凭据,然后将此新凭据分配给您的工作。
说实话,触发事件还不知道。
更新OP并回复评论后:
基于工作流程,我认为最好使用内部Oracle通知进行响应审核。我认为尝试通过外部应用程序将自己入侵Windows事件日志会带来另一种不必要的复杂性。
我将在数据库中创建一个表,在该表中存储所有事件,并在该表的顶部创建一个带有通知(SMS,邮件等)的作业,如果对日志表进行任何更改,该通知将运行。
为了在发生错误时使用触发器,您应该在主范围内使用PRAGMA autonomous_transaction
(允许您进行子交易)。这将使您可以提交可能拥有的任何Process: com.example.final_pah, PID: 18707
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at com.example.final_pah.MoviesActivity.onCreateView(MoviesActivity.java:138)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6923)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
,但对其余部分进行回滚。
答案 1 :(得分:1)
在另一个答案中,权限问题已经解决。对于“在触发器内部提交”问题,有PRAGMA AUTONOMOUS_TRANSACTION
。有关示例,请参见此链接的底部:https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/13_elems002.htm。它正是您想要的。