-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathabout-walminer.html
More file actions
executable file
·287 lines (281 loc) · 18 KB
/
about-walminer.html
File metadata and controls
executable file
·287 lines (281 loc) · 18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>了解Walminer - Walminer</title>
<meta name="description" content="Walminer - 专业的PostgreSQL WAL解析工具,支持数据恢复、审计和故障排查">
<link rel="icon" type="image/jpeg" href="image/logo.jpg">
<style>
:root {
--bg-primary: #0a0a0a;
--bg-secondary: rgba(20, 20, 20, 0.9);
--bg-card: rgba(255, 255, 255, 0.03);
--bg-card-hover: rgba(255, 255, 255, 0.05);
--bg-dropdown: rgba(15, 15, 20, 0.98);
--border-color: rgba(255, 255, 255, 0.08);
--border-light: rgba(255, 255, 255, 0.1);
--text-primary: #e4e4e7;
--text-secondary: #a1a1aa;
--text-muted: #71717a;
--text-title: #f4f4f5;
--text-gradient-start: #fafafa;
--text-gradient-end: #a1a1aa;
--accent-primary: #6366f1;
--accent-secondary: #8b5cf6;
--accent-tertiary: #ec4899;
--grid-opacity: 0.1;
--orb-opacity: 0.5;
--shadow-color: rgba(0, 0, 0, 0.3);
--nav-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
body.light-mode {
--bg-primary: #ffffff;
--bg-secondary: rgba(255, 255, 255, 0.95);
--bg-card: rgba(0, 0, 0, 0.02);
--bg-card-hover: rgba(0, 0, 0, 0.04);
--bg-dropdown: rgba(250, 250, 255, 0.98);
--border-color: rgba(0, 0, 0, 0.08);
--border-light: rgba(0, 0, 0, 0.1);
--text-primary: #18181b;
--text-secondary: #52525b;
--text-muted: #71717a;
--text-title: #27272a;
--text-gradient-start: #18181b;
--text-gradient-end: #52525b;
--grid-opacity: 0.06;
--orb-opacity: 0.3;
--shadow-color: rgba(0, 0, 0, 0.08);
--nav-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
overflow-x: hidden;
transition: background 0.3s, color 0.3s;
}
.grid-bg {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background-image:
linear-gradient(rgba(120, 119, 198, var(--grid-opacity)) 1px, transparent 1px),
linear-gradient(90deg, rgba(120, 119, 198, var(--grid-opacity)) 1px, transparent 1px);
background-size: 50px 50px;
animation: gridMove 20s linear infinite;
pointer-events: none; z-index: 0;
transition: opacity 0.3s;
}
@keyframes gridMove {
0% { background-position: 0 0; }
100% { background-position: 50px 50px; }
}
.orb { position: fixed; border-radius: 50%; filter: blur(80px); opacity: var(--orb-opacity); pointer-events: none; z-index: 1; transition: opacity 0.3s; }
.orb-1 { width: 400px; height: 400px; background: radial-gradient(circle, #6366f1 0%, transparent 70%); top: -100px; right: -100px; animation: float 8s ease-in-out infinite; }
.orb-2 { width: 300px; height: 300px; background: radial-gradient(circle, #8b5cf6 0%, transparent 70%); bottom: 10%; left: -100px; animation: float 10s ease-in-out infinite reverse; }
.orb-3 { width: 250px; height: 250px; background: radial-gradient(circle, #ec4899 0%, transparent 70%); top: 50%; right: 10%; animation: float 12s ease-in-out infinite; }
@keyframes float {
0%, 100% { transform: translate(0, 0) scale(1); }
33% { transform: translate(30px, -30px) scale(1.1); }
66% { transform: translate(-20px, 20px) scale(0.9); }
}
nav { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 100; width: 1200px; max-width: calc(100vw - 40px); padding: 15px 40px; display: flex; justify-content: space-between; align-items: center; background: var(--bg-secondary); backdrop-filter: blur(20px); border: 1px solid var(--border-light); border-radius: 50px; box-shadow: var(--nav-shadow); transition: background 0.3s, border-color 0.3s, box-shadow 0.3s; }
.logo { font-size: 1.5rem; font-weight: 700; background: linear-gradient(135deg, #6366f1, #8b5cf6, #ec4899); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; text-decoration: none; }
.nav-links { display: flex; gap: 30px; align-items: center; }
.nav-item { position: relative; }
.nav-links a { color: var(--text-secondary); text-decoration: none; font-size: 0.9rem; transition: color 0.3s; padding: 10px 0; }
.nav-links a:hover { color: var(--text-primary); }
.dropdown { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); background: var(--bg-dropdown); border: 1px solid var(--border-light); border-radius: 12px; min-width: 220px; opacity: 0; visibility: hidden; transition: all 0.3s ease; box-shadow: 0 10px 40px var(--shadow-color); backdrop-filter: blur(20px); }
.nav-item:hover .dropdown { opacity: 1; visibility: visible; top: calc(100% + 10px); }
.dropdown a { display: block; padding: 12px 20px; color: var(--text-secondary); text-decoration: none; border-bottom: 1px solid var(--border-color); transition: all 0.3s; }
.dropdown a:last-child { border-bottom: none; }
.dropdown a:hover { background: rgba(99, 102, 241, 0.1); color: var(--text-primary); padding-left: 25px; }
.dropdown-arrow { display: inline-block; margin-left: 4px; transition: transform 0.3s; font-size: 0.7rem; }
.nav-item:hover .dropdown-arrow { transform: rotate(180deg); }
.nav-cta { background: linear-gradient(135deg, #6366f1, #8b5cf6); color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-size: 0.9rem; transition: transform 0.3s, box-shadow 0.3s; }
.nav-cta:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(99, 102, 241, 0.3); }
.theme-toggle { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--border-light); background: var(--bg-card); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; transition: all 0.3s; }
.theme-toggle:hover { background: var(--bg-card-hover); transform: scale(1.05); }
.content { position: relative; z-index: 10; padding-top: 120px; }
.page-header { text-align: center; padding: 60px 20px; max-width: 900px; margin: 0 auto; }
.page-header h1 { font-size: clamp(2.5rem, 6vw, 3.5rem); font-weight: 800; margin-bottom: 20px; background: linear-gradient(135deg, var(--text-gradient-start) 0%, var(--text-gradient-end) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
.page-header h1 span { background: linear-gradient(135deg, #6366f1, #8b5cf6, #ec4899); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
.page-header p { font-size: 1.2rem; color: var(--text-secondary); }
.section { max-width: 1000px; margin: 0 auto; padding: 60px 20px; }
.section h2 { font-size: 2rem; font-weight: 700; margin-bottom: 30px; color: var(--text-title); position: relative; padding-left: 20px; }
.section h2::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 4px; height: 30px; background: linear-gradient(180deg, #6366f1, #8b5cf6); border-radius: 2px; }
.section p { color: var(--text-secondary); line-height: 1.8; margin-bottom: 20px; font-size: 1.05rem; }
.feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 25px; margin-top: 40px; }
.feature-item { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 16px; padding: 30px; transition: all 0.3s; }
.feature-item:hover { background: var(--bg-card-hover); border-color: rgba(99, 102, 241, 0.3); transform: translateY(-5px); }
.feature-icon { font-size: 2.5rem; margin-bottom: 15px; }
.feature-item h3 { font-size: 1.3rem; font-weight: 600; margin-bottom: 12px; color: var(--text-title); }
.feature-item p { color: var(--text-secondary); font-size: 0.95rem; margin: 0; }
.version-badge { display: inline-block; padding: 6px 16px; background: rgba(99, 102, 241, 0.15); border: 1px solid rgba(99, 102, 241, 0.3); border-radius: 20px; color: #a5b4fc; font-size: 0.9rem; margin-left: 10px; }
.highlight { background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(139, 92, 246, 0.1)); border-left: 4px solid #6366f1; padding: 20px; border-radius: 0 12px 12px 0; margin: 25px 0; }
.highlight p { margin: 0; }
.back-link { display: inline-flex; align-items: center; gap: 8px; color: var(--text-secondary); text-decoration: none; transition: color 0.3s; margin-bottom: 20px; }
.back-link:hover { color: var(--text-primary); }
footer { border-top: 1px solid var(--border-light); padding: 40px 20px; text-align: center; color: var(--text-muted); }
footer p { font-size: 0.9rem; }
.mobile-menu { display: none; }
@media (max-width: 768px) {
nav { padding: 15px 20px; }
.nav-links { display: none; }
.mobile-menu { display: block; color: var(--text-primary); font-size: 1.5rem; cursor: pointer; }
.page-header h1 { font-size: 2rem; }
.feature-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="grid-bg"></div>
<div class="orb orb-1"></div>
<div class="orb orb-2"></div>
<div class="orb orb-3"></div>
<nav>
<a href="index.html" class="logo">Walminer</a>
<div class="nav-links">
<a href="about-walminer.html">了解Walminer</a>
<div class="nav-item">
<a href="#">文档<span class="dropdown-arrow">▼</span></a>
<div class="dropdown">
<a href="docs/installation.html">安装部署</a>
<a href="docs/builtdic.html">创建数据字典</a>
<a href="docs/wal2sql.html">WAL反解析</a>
<a href="docs/search.html">误操作并行搜索</a>
<a href="docs/blockrecovery.html">单表快速恢复</a>
<div style="border-top: 1px solid var(--border-color); margin: 8px 0;"></div>
<div style="padding: 12px 20px; color: var(--text-muted); font-size: 0.8rem;">CDC模块</div>
<a href="docs/cdc/index.html">模块概述</a>
<a href="docs/cdc/pgto.html">端到端数据同步</a>
<a href="docs/cdc/decode.html">解码服务</a>
<a href="docs/cdc/archive.html">CDC增量归档</a>
</div>
</div>
<a href="pricing.html">授权方案</a>
<a href="faq.html">常见问题</a>
<a href="index.html#contact">联系我们</a>
<button class="theme-toggle" id="themeToggle" title="切换主题">🌙</button>
</div>
<div class="mobile-menu">☰</div>
</nav>
<div class="content">
<div class="page-header">
<h1>了解 <span>Walminer</span></h1>
<p>专业的 PostgreSQL 预写式日志(WAL)解析工具</p>
</div>
<div class="section">
<h2>什么是 Walminer?</h2>
<p>WalMiner是一个PostgreSQL的WAL解码工具,核心功能是从WAL中解码出其包含的SQL以及UNDO SQL。
WalMiner分为开源版本(WalMiner3.0)和闭源版本(WalMiner4.X),WalMiner3.0版本是PostgreSQL插件的形态,
需要在PG中安装插件使用; WalMiner4.X版本是bin工具,无需对数据库产生入侵,即可完成数据找回任务和CDC功能
</p>
<p>
如果您只需要误操作数据找回功能,且可以接受在数据库中安装插件,可以选择WalMiner3.0版本;
如果您需要更强大的功能(如全集簇级别的WAL解析、端到端CDC、生产库故障转移支持等),
或者不希望在生产库中安装插件,建议选择WalMiner4.X版本。
</p>
</div>
<div class="section">
<h2>WalMiner适用范围</h2>
<p>
WalMiner适用于所有PG10+版本的PostgreSQL数据库,包括常见的衍生版本如:</br>
<strong>PolarDB</strong>、<strong>HaloDB</strong>、<strong>IvorySQL</strong>、<strong>openGauss</strong>
、<strong>BabelFish</strong>、<strong>HighGoDB</strong>、<strong>tbase</strong>等。
</p>
<p>
有些数据库使用发布版本的WalMiner即可,有些商业数据库需要使用特定版本,如果您有其他商业数据库的WalMiner需求,
可以联系我们进行定制化兼容。
</p>
</div>
<div class="section">
<h2>核心功能</h2>
<div class="feature-grid">
<div class="feature-item">
<div class="feature-icon">🔍</div>
<h3>WAL 解析为 SQL</h3>
<p>将 WAL 日志解析为可读的 SQL 语句,包括原始 DML/DDL 语句和对应的 UNDO SQL,支持数据恢复、审计和故障排查。</p>
</div>
<div class="feature-item">
<div class="feature-icon">📡</div>
<h3>CDC 解码插件</h3>
<p>解析 REPLICA 级别的 WAL 日志,全集簇级别解码,实现端到端 CDC 功能,支持生产库故障转移自动切换。</p>
</div>
<div class="feature-item">
<div class="feature-icon">📊</div>
<h3>数据字典生成</h3>
<p>从在线数据库快速生成数据字典,支持插件数据类型解析,为 WAL 解析提供元数据支持。</p>
</div>
<div class="feature-item">
<div class="feature-icon">🔎</div>
<h3>WAL 搜索</h3>
<p>在 WAL 中快速定位指定表的所有操作位置,帮助进行故障诊断和数据追踪。</p>
</div>
<div class="feature-item">
<div class="feature-icon">💾</div>
<h3>快速表恢复</h3>
<p>支持从备份集以及备份集后的连续 WAL 中快速恢复特定表,大幅减少 RTO。</p>
</div>
<div class="feature-item">
<div class="feature-icon">🔄</div>
<h3>数据脱库</h3>
<p>数据库无法启动时,可以 dump 出所有数据,最大限度减少数据丢失。</p>
</div>
</div>
</div>
<div class="section">
<h2>应用场景</h2>
<p><strong>数据恢复:</strong>当发生误操作或数据丢失时,可以通过解析 WAL 日志生成 UNDO SQL 进行数据恢复。</p>
<p><strong>审计追踪:</strong>记录所有数据库变更操作,满足合规审计要求,追踪数据变更历史。</p>
<p><strong>故障诊断:</strong>快速定位问题发生的时间和具体操作,帮助排查数据库故障。</p>
<p><strong>CDC 数据同步:</strong>通过解码插件实现变更数据捕获,支持数据实时同步到下游系统。</p>
</div>
<div class="section">
<h2>技术特点</h2>
<p><strong>独立部署:</strong>无需修改数据库配置或安装插件,不影响生产库性能。</p>
<p><strong>全局解析:</strong>支持全集簇级别的 WAL 解析,不受单个数据库限制。</p>
<p><strong>高兼容性:</strong>支持 PostgreSQL 10+ 所有版本,以及多种数据库衍生版本。</p>
<p><strong>故障转移支持:</strong>CDC 模块支持生产库故障转移,自动切换到备库继续解码。</p>
</div>
<div class="section">
<h2>开始使用</h2>
<div class="highlight">
<p>准备好开始了吗?查看我们的 <a href="docs/installation.html" style="color: #a5b4fc;">安装文档</a>,快速上手 Walminer。</p>
</div>
</div>
</div>
<footer>
<p>Walminer - 专业 PostgreSQL WAL 解析工具</p>
<p style="margin-top: 10px; font-size: 0.85rem;">邮箱: lchch1990@sina.cn | QQ群: 811105058 | 微信: L974466845</p>
<p style="margin-top: 10px; font-size: 0.85rem;">Copyright 2024</p>
</footer>
<script>
// 主题切换功能
(function() {
const themeToggle = document.getElementById('themeToggle');
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
const currentTheme = localStorage.getItem('theme');
let isDark = currentTheme === 'dark' || (!currentTheme && prefersDarkScheme.matches);
function applyTheme(dark) {
if (dark) {
document.body.classList.remove('light-mode');
themeToggle.textContent = '🌙';
localStorage.setItem('theme', 'dark');
} else {
document.body.classList.add('light-mode');
themeToggle.textContent = '☀️';
localStorage.setItem('theme', 'light');
}
}
applyTheme(isDark);
themeToggle.addEventListener('click', function() {
isDark = !isDark;
applyTheme(isDark);
});
document.querySelector('.mobile-menu').addEventListener('click',function(){document.getElementById('mobileNav').classList.toggle('active');});
})();
</script>
</body>
</html>