|
| 1 | +# Copyright Materialize, Inc. and contributors. All rights reserved. |
| 2 | +# |
| 3 | +# Use of this software is governed by the Business Source License |
| 4 | +# included in the LICENSE file at the root of this repository. |
| 5 | +# |
| 6 | +# As of the Change Date specified in that file, in accordance with |
| 7 | +# the Business Source License, use of this software will be governed |
| 8 | +# by the Apache License, Version 2.0. |
| 9 | + |
| 10 | +# |
| 11 | +# Regression test: a freshly created source must report a near-zero ingestion |
| 12 | +# lag, even while its upstream database is idle. |
| 13 | +# |
| 14 | +# The two offset statistics must be initialized from a common validated |
| 15 | +# upstream point. Leaving `offset_committed` at 0 after `offset_known` advances |
| 16 | +# produces an enormous lag. Publishing the full resumption LSN before the known |
| 17 | +# frontier catches up reverses the ordering and makes the same lag calculation |
| 18 | +# (`offset_known - offset_committed`) underflow. |
| 19 | +# |
| 20 | +# A newly enabled capture instance can start ahead of the database-wide CDC |
| 21 | +# maximum. Purification must use that higher start LSN as the source's resumption |
| 22 | +# point. The progress probe still observes the lower database maximum. We stop |
| 23 | +# this database's capture job before enabling the target table so the two LSNs |
| 24 | +# cannot converge and mask the invalid statistics. |
| 25 | + |
| 26 | +$ sql-server-connect name=sql-server |
| 27 | +server=tcp:sql-server,1433;IntegratedSecurity=true;TrustServerCertificate=true;User ID=${arg.default-sql-server-user};Password=${arg.default-sql-server-password} |
| 28 | + |
| 29 | +$ sql-server-execute name=sql-server split-lines=false |
| 30 | +IF EXISTS (SELECT name FROM sys.databases WHERE name = N'lag_test') |
| 31 | +BEGIN |
| 32 | + ALTER DATABASE lag_test SET SINGLE_USER WITH ROLLBACK IMMEDIATE; |
| 33 | + DROP DATABASE lag_test; |
| 34 | +END; |
| 35 | + |
| 36 | +$ sql-server-execute name=sql-server |
| 37 | +CREATE DATABASE lag_test COLLATE Latin1_General_100_CI_AI_SC_UTF8; |
| 38 | +USE lag_test; |
| 39 | +EXEC sys.sp_cdc_enable_db; |
| 40 | +ALTER DATABASE lag_test SET ALLOW_SNAPSHOT_ISOLATION ON; |
| 41 | + |
| 42 | +$ sql-server-execute name=sql-server |
| 43 | +USE lag_test; |
| 44 | +CREATE TABLE lag_seed (f1 VARCHAR(20)); |
| 45 | +EXEC sys.sp_cdc_enable_table @source_schema = 'dbo', @source_name = 'lag_seed', @role_name = 'SA', @supports_net_changes = 0; |
| 46 | +INSERT INTO lag_seed VALUES ('seed'); |
| 47 | + |
| 48 | +# Establish a nonzero database maximum, then freeze it. Enabling `lag_t` after |
| 49 | +# this point gives its capture instance a later start LSN. |
| 50 | +$ sql-server-execute name=sql-server split-lines=false |
| 51 | +WAITFOR DELAY '00:00:20'; |
| 52 | + |
| 53 | +$ sql-server-execute name=sql-server |
| 54 | +USE lag_test; |
| 55 | +EXEC sys.sp_cdc_stop_job @job_type = 'capture'; |
| 56 | +CREATE TABLE lag_t (f1 VARCHAR(20)); |
| 57 | +EXEC sys.sp_cdc_enable_table @source_schema = 'dbo', @source_name = 'lag_t', @role_name = 'SA', @supports_net_changes = 0; |
| 58 | +INSERT INTO lag_t VALUES ('one'), ('two'), ('three'); |
| 59 | + |
| 60 | +# This is the upstream state the test depends on. If SQL Server changes its CDC |
| 61 | +# behavior, fail here rather than attributing a later result to Materialize. |
| 62 | +$ sql-server-execute name=sql-server split-lines=false |
| 63 | +IF NOT EXISTS ( |
| 64 | + SELECT 1 |
| 65 | + FROM lag_test.cdc.change_tables |
| 66 | + WHERE capture_instance = 'dbo_lag_t' |
| 67 | + AND start_lsn > lag_test.sys.fn_cdc_get_max_lsn() |
| 68 | +) |
| 69 | + THROW 50000, 'expected capture start LSN above database maximum', 1; |
| 70 | + |
| 71 | +$ postgres-execute connection=postgres://mz_system:materialize@${testdrive.materialize-internal-sql-addr} |
| 72 | +ALTER SYSTEM SET storage_statistics_collection_interval = 1000; |
| 73 | +ALTER SYSTEM SET storage_statistics_interval = 2000; |
| 74 | + |
| 75 | +> CREATE SECRET IF NOT EXISTS mspass AS '${arg.default-sql-server-password}' |
| 76 | + |
| 77 | +> CREATE CONNECTION msconn TO SQL SERVER ( |
| 78 | + HOST 'sql-server', |
| 79 | + PORT 1433, |
| 80 | + DATABASE lag_test, |
| 81 | + USER '${arg.default-sql-server-user}', |
| 82 | + PASSWORD = SECRET mspass |
| 83 | + ); |
| 84 | + |
| 85 | +> CREATE CLUSTER lag_cluster SIZE '${arg.default-replica-size}' |
| 86 | +> CREATE SOURCE lag_source IN CLUSTER lag_cluster FROM SQL SERVER CONNECTION msconn; |
| 87 | +> CREATE TABLE lag_t FROM SOURCE lag_source (REFERENCE dbo.lag_t); |
| 88 | + |
| 89 | +# We intentionally do not wait for the snapshot to become queryable. On an idle |
| 90 | +# database the source frontier only advances once SQL Server advances its max |
| 91 | +# LSN, which can take minutes. That frontier advance is also what would fix a |
| 92 | +# buggy `offset_committed`, so waiting for it would mask the bug. Instead we |
| 93 | +# assert on the statistics, which are populated within seconds regardless of the |
| 94 | +# frontier. |
| 95 | + |
| 96 | +# Ensure statistics for the source's replica exist before pinning the replica |
| 97 | +# id below, which does not retry on a missing row. |
| 98 | +> SELECT COUNT(*) > 0 |
| 99 | + FROM |
| 100 | + mz_cluster_replicas cr, |
| 101 | + mz_internal.mz_source_statistics u, |
| 102 | + mz_sources s |
| 103 | + WHERE |
| 104 | + cr.id = u.replica_id AND s.name = 'lag_source' AND u.id = s.id |
| 105 | +true |
| 106 | + |
| 107 | +$ set-from-sql var=replica_id |
| 108 | +SELECT cr.id |
| 109 | + FROM |
| 110 | + mz_clusters c, |
| 111 | + mz_cluster_replicas cr, |
| 112 | + mz_internal.mz_source_statistics u, |
| 113 | + mz_sources s |
| 114 | + WHERE |
| 115 | + c.name = 'lag_cluster' AND c.id = cr.cluster_id AND cr.id = u.replica_id |
| 116 | + AND s.name = 'lag_source' AND u.id = s.id |
| 117 | + ORDER BY cr.id |
| 118 | + LIMIT 1 |
| 119 | + |
| 120 | +# The reported committed offset must not exceed the first known upstream offset, |
| 121 | +# even though the actual resumption LSN does. The second expression is the |
| 122 | +# ingestion-lag calculation used by customers. Since both columns are `uint8`, |
| 123 | +# invalid ordering makes the subtraction itself fail instead of reporting lag. |
| 124 | +$ set-sql-timeout duration=60s |
| 125 | + |
| 126 | +> SELECT |
| 127 | + u.offset_committed > 0, |
| 128 | + u.offset_known >= u.offset_committed, |
| 129 | + u.offset_known - u.offset_committed < 1000000 |
| 130 | + FROM mz_sources s |
| 131 | + JOIN mz_internal.mz_source_statistics u ON s.id = u.id |
| 132 | + WHERE s.name = 'lag_source' AND u.replica_id = '${replica_id}' |
| 133 | +true true true |
0 commit comments