

# 使用 SQL Server Agent for Amazon RDS
<a name="Appendix.SQLServer.CommonDBATasks.Agent"></a>

借助 Amazon RDS，您可以在运行 Microsoft SQL Server 企业版、标准版或 Web 版的数据库实例上使用 SQL Server Agent。SQL Server Agent 是一项 Microsoft Windows 服务，可运行计划的管理任务，即所谓的作业。您可以使用 SQL Server Agent 运行 T - SQL 作业，以在 SQL Server 数据库实例中重新生成索引、运行损坏检查和聚合数据。

创建 SQL Server 数据库实例时，主用户以 `SQLAgentUserRole` 角色登记。

SQL Server Agent 可以按照时间表运行作业，对特定事件或需求做出响应。有关详细信息，请参阅 Microsoft 文档中的 [SQL Server Agent](http://msdn.microsoft.com/en-us/library/ms189237)。

**注意**  
避免在数据库实例维护和备份 Windows 期间计划运行作业。由 AWS 启动的维护和备份过程可能会中断作业或导致作业取消。  
在多可用区部署中，启用作业复制功能时，SQL Server Agent 作业将从主要主机复制到辅助主机。有关更多信息，请参阅 [启用 SQL Server Agent 作业复制](#SQLServerAgent.Replicate)。  
多可用区部署具有 10000 个 SQL Server 代理任务的限制。如果您需要更高的限制，则可联系 支持 请求增加限制。打开 [AWS 支持 Center (Amazon Web Services Support 中心)](https://console.aws.amazon.com/support/home#/) 页面，登录（如有必要），然后选择 **Create case (创建案例)**。选择 **Service Limit increase (提高服务限制)**。填写并提交表格。

要查看 SQL Server Management Studio (SSMS) 中单个 SQL Server Agent 作业的历史记录，需打开 Object Explorer，右键单击此作业，然后选择 **View History**。

SQL Server Agent 正在数据库实例中的托管主机上运行，因此不支持某些操作：
+ 不支持使用 ActiveX、Windows Command Shell或 Windows PowerShell 运行复制作业和命令行脚本。
+ 无法手动启动、停止或重新启动 SQL Server Agent。
+ 无法从数据库实例获取通过 SQL Server Agent 发出的电子邮件通知。
+ 不支持 SQL Server Agent 提示和运算符。
+ 不支持使用 SQL Server Agent 创建备份。用 Amazon RDS 备份数据库实例。
+ 目前，RDS for SQL Server 不支持使用 SQL Server Agent 令牌。

## 启用 SQL Server Agent 作业复制
<a name="SQLServerAgent.Replicate"></a>

您可以使用以下存储的过程启用 SQL Server Agent 作业复制：

```
EXECUTE msdb.dbo.rds_set_system_database_sync_objects @object_types = 'SQLAgentJob';
```

您可以在 Amazon RDS for SQL Server 支持的所有 SQL Server 版本上运行存储的过程。将复制以下类别中的作业：
+ [未分类（本地）]
+ [未分类（多服务器）]
+ [未分类]
+ 数据收集器
+ 数据库引擎优化顾问
+ 数据库维护
+ 全文

仅复制使用 T-SQL 作业步骤的作业。不复制步骤类型为 SQL Server Integration Services（SSIS）、SQL Server Reporting Services（SSRS）、复制和 PowerShell 等的作业。不复制使用数据库邮件和服务器级别对象的作业。

**重要**  
主要主机是复制的信任源。在开启作业复制之前，请确保您的 SQL Server Agent 任务位于主要主机上。否则，如果在辅助主机上使用较新的任务时开启该功能，则可能会导致删除 SQL Server Agent 任务。

您可以使用以下函数来确认复制是否已开启。

```
SELECT * from msdb.dbo.rds_fn_get_system_database_sync_objects();
```

 如果正在复制 SQL Server Agent 作业，T-SQL 查询将返回以下内容。如果未复制这些作业，将不会返回任何 `object_class` 内容。

![\[正在复制 SQL Server Agent 作业\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/SQLAgentJob.png)


您可以使用以下函数来查找上次同步对象的时间，以 UTC 时间表示。

```
SELECT * from msdb.dbo.rds_fn_server_object_last_sync_time();
```

例如，假设您在 01:00 修改 SQL Server Agent 作业。您预计最近的同步时间将在 01:00 之后，这表示同步已经进行。

同步后，为辅助节点上的 `date_created` 和 `date_modified` 返回的值预计将匹配。

![\[上次同步服务器对象的时间为 01:21:23\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/SQLAgentJob_last_sync_time.png)


如果您也在使用 `tempdb` 复制，则可以通过在 `@object_type` 参数中提供 SQL 代理任务和 `tempdb` 配置来为它们启用复制：

```
EXECUTE msdb.dbo.rds_set_system_database_sync_objects @object_types = 'SQLAgentJob,TempDbFile';
```

有关 `tempdb` 复制的更多信息，请参阅[多可用区部署的 TempDB 配置](SQLServer.TempDB.MAZ.md)。

# SQL Server Agent 角色
<a name="SQLServerAgent.AgentRoles"></a>

RDS for SQL Server 支持以下 SQL Server Agent 角色，这些角色具有不同的权限级别来管理作业：
+ **SQLAgentUserRole**

  权限
  + 创建和管理自己的作业、计划和操作员
  + 查看自己的作业和计划的属性
  + 无法查看或管理由其他用户创建的作业

  此角色适用于需要创建和管理自己的作业，但不需要访问由其他用户创建的作业的用户。
+ **SQLAgentReaderRole**

  权限
  + SQLAgentUserRole 的所有权限
  + 查看所有作业和计划（包括其他用户创建的作业和计划）的列表
  + 查看所有作业的属性
  + 查看作业历史记录

  此角色适用于需要监控所有作业的状态但不需要管理这些作业的用户。
+ **SQLAgentOperatorRole**

  权限
  + SQLAgentUserRole 和 SQLAgentReaderRole 的所有权限
  + 执行、停止或启动作业
  + 管理作业历史记录
  + 启用/禁用作业和计划
  + 查看操作员和代理

  此角色提供最全面的权限，适合需要完全控制所有作业的用户。

使用以下命令将角色分配给您的 SQL Server 登录名：

```
USE msdb;
EXEC sp_addrolemember 'SQLAgentOperatorRole', 'username';
```

## 在 RDS for SQL Server 中管理 SQLAgentOperatorRole
<a name="SQLServerAgent.AgentRoles.ManageSQLAgentOperatorRole"></a>

要查看当前作业，必须将 SQLAgentOperatorRole 添加到 SQL Server 登录名，并在断开与数据库的连接之前将其移除。

要在 SQL Server Management Studio 中可视化 SQL Server Agent 树，请按照以下说明操作：

**在 SQL Server Management Studio（SSMS）上查看 SQL Server Agent**

1. 使用 RDS 主凭证，登录 RDS SQL Server 实例并向所需用户授予 SQLAgentUserRole。

   ```
   USE msdb
   GO
   IF NOT EXISTS(SELECT name FROM sys.database_principals WHERE name = 'UserName')
   BEGIN
   CREATE USER UserName FROM LOGIN UserName
   END
   GO
   ALTER ROLE SQLAgentUserRole ADD MEMBER UserName
   GO
   GRANT ALTER ON ROLE::[SQLAgentOperatorRole] to UserName
   GO
   ```

   如果该用户不存在，则这些命令会在 `msdb` 数据库上创建该用户。它还会在 SQLAgentUserRole 上添加用户，因此可以看到 SSMS 上的 SQL Server Agent 树。最后，它向用户授予对 SQLAgentOperatorRole 的更改权限。这可让用户在该角色中添加/移除自身。

1. 要将自己添加到上述角色中，请使用需要查看作业的用户连接到 RDS SQL Server 实例，然后运行以下脚本。

   ```
   use msdb
   go
   ALTER ROLE SQLAgentOperatorRole ADD MEMBER UserName
   GO
   ```

   之后，右键单击**作业**文件夹，然后选择**刷新**。

1. 执行此操作时，**作业**选项卡会显示一个 **\$1**（加号）按钮。单击可展开 SQL Server Agent 作业列表。

1. 
**重要**  
在断开与 RDS SQL Server 实例的连接之前，您需要将自己从 SQLAgentOperatorRole 中移除。

   要从 SQLAgentOperatorRole 中移除登录名，请在断开或关闭 Management Studio 之前运行以下查询：

   ```
   USE msdb
   GO
   ALTER ROLE SQLAgentOperatorRole DROP MEMBER UserName
   GO
   ```

有关更多信息，请参阅 [Leveraging SQLAgentOperatorRole in RDS SQL Server](https://aws.amazon.com/blogs/database/leveraging-sqlagentoperatorrole-in-rds-sql-server/)。

# 将用户添加到 SQLagentUser 角色
<a name="SQLServerAgent.AddUser"></a>

要允许其他登录名或用户使用 SQL Server Agent，请以主用户身份登录并执行以下操作：

1. 使用 `CREATE LOGIN` 命令创建另一个服务器级别的登录名。

1. 使用 `msdb` 命令在 `CREATE USER` 内创建一个用户，然后将此用户链接到上一步骤中创建的登录名。

1. 使用 `SQLAgentUserRole` 系统存储过程将用户添加到 `sp_addrolemember`。

例如，假设您的主用户名为 **admin**，并且您要授予一个用户对 SQL Server Agent 的访问权限，此用户的用户名为 **theirname**，密码为 **theirpassword**。在这种情况下，您可以使用以下过程。

**要将用户添加到 SQLagentUser 角色**

1. 以主用户身份登录。

1. 运行以下命令：

   ```
   --Initially set context to master database
   USE [master];
   GO
   --Create a server-level login named theirname with password theirpassword
   CREATE LOGIN [theirname] WITH PASSWORD = 'theirpassword';
   GO
   --Set context to msdb database
   USE [msdb];
   GO
   --Create a database user named theirname and link it to server-level login theirname
   CREATE USER [theirname] FOR LOGIN [theirname];
   GO
   --Added database user theirname in msdb to SQLAgentUserRole in msdb
   EXEC sp_addrolemember [SQLAgentUserRole], [theirname];
   ```

# 删除 SQL Server Agent 作业
<a name="SQLServerAgent.DeleteJob"></a>

您可以使用 `sp_delete_job` 存储过程删除 Amazon RDS for Microsoft SQL Server 上的 SQL Server Agent 作业。

不能使用 SSMS 删除 SQL Server Agent 作业。如果您尝试这样做，就会收到类似于以下内容的错误消息：

```
The EXECUTE permission was denied on the object 'xp_regread', database 'mssqlsystemresource', schema 'sys'.
```

作为托管服务，RDS 在运行访问 Windows 注册表的过程时受到了限制。使用 SSMS 时，其会尝试运行没有 RDS 授权的进程 (`xp_regread`)。

**注意**  
在 RDS for SQL Server 上，只允许 sysadmin 角色的成员更新或删除由其他登录账户拥有的任务。有关更多信息，请参阅 [Leveraging SQLAgentOperatorRole in RDS SQL Server](https://aws.amazon.com/blogs/database/leveraging-sqlagentoperatorrole-in-rds-sql-server/)。

**要删除 SQL Server Agent 作业**
+ 运行以下 T-SQL 语句：

  ```
  EXEC msdb..sp_delete_job @job_name = 'job_name';
  ```