firebird icon indicating copy to clipboard operation
firebird copied to clipboard

Postfix for #5385 (CORE-5101): Fix slow database restore when Classic server mode is used

Open ilya071294 opened this issue 3 years ago • 2 comments

CCH_flush has dbb->dbb_ast_flags & DBB_shutdown_single check to avoid PIO_flush call when a database is restoring. But a restore attachment didn't update dbb->dbb_ast_flags while setting a shutdown mode in a database header. This optimization worked fine for Super server mode because it has Garbage Collector and Cache Writer attachments which read the header and update flags in a shared dbb.

ilya071294 avatar Jul 14 '22 15:07 ilya071294

This commit surely helps the described situation. I still have some doubts though. DBB_shutdown_* flags are normally set via notify_shutdown() -> SHUT_blocking_ast() -> shutdown() call chain. It works when the database goes online due to delay == -1 (see SHUT_blocking_ast()). It usually works for the database shutdown because of notify_shutdown() being finally (after timeout) called with isc_dpb_shut_force flag. However, if the first call of notify_shutdown() returns true (which means we already have an exclusive access), then DBB_shutdown_* flags are not set properly. This is probably the original problem. So I'd suggest to review (and test) the alternative approach:

	// Database is being shutdown. First notification gives shutdown type and delay in seconds.

	bool exclusive = notify_shutdown(tdbb, flag, delay, guard);
	bool successful = exclusive;

	if (exclusive)
	{
		// Ensure we have the proper DBB_shutdown_* flags in place
		shutdown(tdbb, flag, false);
	}
	else
	{
		// Try to get exclusive database lock periodically up to specified delay. If we
		// haven't gotten it report shutdown error for weaker forms. For forced shutdown
		// keep notifying until successful.

		SSHORT timeout = delay ? delay - 1 : 0;

		do
		{
			if (!(dbb->dbb_ast_flags & (DBB_shut_attach | DBB_shut_tran | DBB_shut_force)))
				break;

			if ((flag & isc_dpb_shut_transaction) && !TRA_active_transactions(tdbb, dbb))
			{
				successful = true;
				break;
			}

			if (timeout && CCH_exclusive(tdbb, LCK_PW, -1, guard))
			{
				exclusive = true;
				break;
			}
		}
		while (timeout--);
	}

dyemanov avatar Oct 11 '22 18:10 dyemanov

A workaround could also be to add isc_dpb_shut_force option to gbak, but I'd rather avoid that.

dyemanov avatar Oct 11 '22 18:10 dyemanov

However, if the first call of notify_shutdown() returns true (which means we already have an exclusive access), then DBB_shutdown_* flags are not set properly. This is probably the original problem. So I'd suggest to review (and test) the alternative approach

I agree, this approach is better. I've tested it and it works fine.

ilya071294 avatar Jul 07 '23 14:07 ilya071294