如何复制托管数据库?

How to copy managed database?

据我所知没有 REST API providing this functionality directly. So, I am using restore for this (there are other ways but those don’t guarantee transactional consistency and are more complicated) via Create request

由于无法关闭短时间备份(至少保留1天)所以应该是可靠的。我在请求中将当前时间用于“properties.restorePointInTime”属性。这适用于大多数数据库。但是一个 db returns 我这个错误(来自异步操作请求):

"error": {
    "code": "BackupSetNotFound",
    "message": "No backups were found to restore the database to the point in time 6/14/2021 8:20:00 PM (UTC). Please contact support to restore the database."
}

我知道我没有超出范围,因为如果恢复时间早于“earliestRestorePoint”(这可以在托管数据库的 GET 请求中找到)或者将来我会收到“PitrPointInTimeInvalid”错误。尽管如此,我发现一些信息表明我不应该使用当前时间,而应该使用当前时间——最多 6 分钟。如果通过 Azure 门户完成(顺便说一句,它失败并出现同样的错误)也是如此,它不允许输入比当前更新的时间 - 6 分钟。几次尝试后,我发现当前时间 - 大约 40 分钟开始正常工作。但是 40 分钟很多,在我尝试等待异步操作的结果之前,我没有找到任何方法来确定什么时间有效。

我的问题是:有没有办法找到最晚的恢复时间?

或者是否有更好的方法来“复制”托管数据库以保证事务的一致性并且相当快?

编辑:
我描述的问题已报告给 MS。发生时间:

  1. 有自定义时区格式,例如UTC + 1 小时。
  2. 在所需时间点跳过源数据库的备份,因为数据库处于非活动状态(没有活动事务)。

这应该从现在(2021 年 8 月 25 日)开始修复,我无法用当前时间重现它 - 10 分钟。我还被告知应该有新的 API 允许在不使用 PITR 的情况下进行复制(不早于 1Q/22)。

回答您的第一个问题“有没有办法找到最晚的恢复时间?”

是的。通过 SQL。找出这一点的唯一方法是使用扩展事件 (XEvent) 会话来监视备份 activity.

开始记录 backup_restore_progress_trace 扩展事件并报告的过程在此处描述 https://docs.microsoft.com/en-us/azure/azure-sql/managed-instance/backup-activity-monitor

在这里包括 SQL 以防 link 过时。

这是为了存储在环形缓冲区中(最多最后 1000 条记录):

CREATE EVENT SESSION [Verbose backup trace] ON SERVER 
ADD EVENT sqlserver.backup_restore_progress_trace(
    WHERE (
              [operation_type]=(0) AND (
              [trace_message] like '%100 percent%' OR 
              [trace_message] like '%BACKUP DATABASE%' OR [trace_message] like '%BACKUP LOG%'))
       )
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
       MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,
       TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)

ALTER EVENT SESSION [Verbose backup trace] ON SERVER
STATE = start;

然后查看所有备份事件的输出:

WITH
a AS (SELECT xed = CAST(xet.target_data AS xml)
FROM sys.dm_xe_session_targets AS xet
JOIN sys.dm_xe_sessions AS xe
ON (xe.address = xet.event_session_address)
WHERE xe.name = 'Verbose backup trace'),
b AS(SELECT
d.n.value('(@timestamp)[1]', 'datetime2') AS [timestamp],
ISNULL(db.name, d.n.value('(data[@name="database_name"]/value)[1]', 'varchar(200)')) AS database_name,
d.n.value('(data[@name="trace_message"]/value)[1]', 'varchar(4000)') AS trace_message
FROM a
CROSS APPLY  xed.nodes('/RingBufferTarget/event') d(n)
LEFT JOIN master.sys.databases db
ON db.physical_database_name = d.n.value('(data[@name="database_name"]/value)[1]', 'varchar(200)'))
SELECT * FROM b

注意:当我遇到同样的时间点恢复问题时,我通过 Microsoft 支持获得了这个提示,这似乎是随机的。他们不为日志备份提供任何 SLA。我发现在一个繁忙的数据库上,日志备份似乎每 5-10 分钟发生一次,但在一个安静的数据库上每小时发生一次。以这种方式恢复数据库可能会很慢,具体取决于事务日志的数量和要重播的 activity 数量等。(https://docs.microsoft.com/en-us/azure/azure-sql/database/recovery-using-backups)

回答你的第二个问题:“或者是否有更好的方法来‘复制’托管数据库,以保证事务的一致性并且相当快?”

我必须同意 Thomas 的观点 - 如果您追求保证事务的一致性和速度,则需要考虑创建故障转移组 https://docs.microsoft.com/en-us/azure/azure-sql/database/auto-failover-group-overview?tabs=azure-powershell#best-practices-for-sql-managed-instance and https://docs.microsoft.com/en-us/azure/azure-sql/managed-instance/failover-group-add-instance-tutorial?tabs=azure-portal

托管实例的故障转移组将有一个主服务器和故障转移服务器,每个服务器上的相同用户数据库保持同步。

但是,是的,这是否符合您的需要取决于 Thomas 提出的副本目的是什么的问题。