数据库修复系列Part3:repair_allow_data_loss

本文介绍了一种针对SQL Server数据库出现严重损坏时的修复流程,包括如何将数据库设置为紧急模式、单用户模式,使用repair_allow_data_loss选项进行修复,并检查修复后的数据库状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

运行DBCC CHECKDB withNO_INFOMSGS发现下面的错误:

Table error: ObjectID 7, index ID 2, partition ID 562949953880064, alloc unit ID 562949953880064(type In-row data), page (1:54). Test ((m_type >= DATA_PAGE &&m_type <= UNDOFILE_HEADER_PAGE) || (m_type == UNKNOWN_PAGE && level== BASIC_HEADER)) failed. Values are 0 and 0.

Msg 8939, Level 16,State 5, Line 4

Table error: ObjectID 7, index ID 2, partition ID 562949953880064, alloc unit ID 562949953880064(type In-row data), page (1:54). Test (m_headerVersion == HEADER_7_0) failed.Values are 0 and 1.

Msg 8939, Level 16,State 6, Line 4

Table error: ObjectID 7, index ID 2, partition ID 562949953880064, alloc unit ID 562949953880064(type In-row data), page (1:54). Test ((m_type >= DATA_PAGE &&m_type <= UNDOFILE_HEADER_PAGE) || (m_type == UNKNOWN_PAGE && level== BASIC_HEADER)) failed. Values are 0 and 0.

repair_allow_data_loss is the minimum repairlevel for the errors found by DBCC CHECKDB (Corrupt2008DemoFatalCorruption).

最小的修复级别是repair_allow_data_loss

如果我们没有数据库备份,无法使用页面还原,那么我们就需要用repair_allow_data_loss来修复(会有数据损失,而且不一定所有的都是可以恢复的 参考:http://blog.youkuaiyun.com/smithliu328/article/details/7827147

下面我们就使用DBCC CHECKDH repair_allow_data_loss来修复损坏的数据库。

---将数据库状态改为紧急模式

ALTER DATABASECorrupt2008DemoFatalCorruptionSETEMERGENCY

GO

--将数据库改为单用户访问

ALTER DATABASE Corrupt2008DemoFatalCorruptionSETSINGLE_USER

GO

--运行repair_allow_data_loss修复

DBCC CHECKDB(Corrupt2008DemoFatalCorruption,repair_allow_data_loss)

Go

---修复完成后运行DBCC CHECKDB确定没有问题

DBCC CHECKDB withNO_INFOMSGS

Go

--将数据库更改为多用户访问

ALTER DATABASE Corrupt2008DemoFatalCorruptionSETMULTI_USER

如果建议的修复级别为REPAIR_REBUILD,您可以放心执行,不会有数据损失 这包括快速修复(如修复非聚集索引中缺少的行)以及更耗时的修复(如重新生成索引)。

注意事项:

仅将 REPAIR 选项作为最后手段使用。 若要修复错误,建议您通过备份进行还原。 修复操作不会考虑表本身或表之间可能存在的任何约束。如果指定的表与一个或多个约束有关,建议您在修复操作后运行 DBCC CHECKCONSTRAINTS。如果必须使用 REPAIR,则运行不带有修复选项的 DBCC CHECKDB 来查找要使用的修复级别。如果使用 REPAIR_ALLOW_DATA_LOSS 级别,则建议您在运行带有此选项的 DBCC CHECKDB 之前备份数据库。

两个步骤用来对比数据丢失:

1.Create a copy of the corrupt database before running repair so you can compare the prerepair and postrepair data and see what is missing. This may be tricky to do if the
database is badly corrupt—you may need to use the WITH CONTINUE_AFTER_ERROR options of BACKUP and RESTORE to do this.
2.Start an explicit transaction before running repair. It is not very well known that you can run repair inside a transaction. After repair completes, you can examine the database to see what repair did, and if you want to undo the repairs, you can simply roll back the explicit transaction.

<think>我们正在解决两个问题:1.datetime.strptime的ValueError2.KeyError&#39;start_park&#39;首先,关于ValueError:unconverteddataremains:22:00:00.000000原因:在使用strptime解析字符串时,格式字符串没有匹配整个字符串,导致有剩余部分未被解析。示例代码:collect_start_time=&#39;2025-03-1922:00:00.000000&#39;part_start=datetime.datetime.strptime(collect_start_time,&#39;%Y-%m-%d&#39;).strftime(&#39;%Y%m&#39;)这里,格式字符串&#39;%Y-%m-%d&#39;只能解析日期部分(到"2025-03-19"),后面的时间部分"22:00:00.000000"成了剩余部分,因此报错。解决方案:1.如果只需要年月,可以只截取前10个字符(即日期部分),然后再解析。2.修改格式字符串以匹配整个字符串,然后提取需要的部分。方法一:截取前10个字符(因为"2025-03-19"正好10个字符)collect_start_time=&#39;2025-03-1922:00:00.000000&#39;date_part=collect_start_time[:10]#得到&#39;2025-03-19&#39;thenconverttodatetimeobjectandformatasneeded.方法二:使用完整的格式字符串解析整个字符串,然后转换为年月格式字符串需要匹配到秒或微秒。由于字符串中有微秒,我们可以使用格式:&#39;%Y-%m-%d%H:%M:%S.%f&#39;但是注意:原字符串中日期和时间之间有一个空格,然后后面是时间部分。因此,我们可以这样做:dt=datetime.datetime.strptime(collect_start_time,&#39;%Y-%m-%d%H:%M:%S.%f&#39;)part_start=dt.strftime(&#39;%Y%m&#39;)#得到&#39;202503&#39;但是注意,如果原始字符串中时间部分不一定有微秒,那么可能有时有有时没有,我们可以尝试两种格式。第二个问题:KeyError&#39;start_park&#39;这通常发生在字典中不存在这个键。我们需要检查字典是否有这个键,可以使用以下方法:1.使用dict.get(key)方法,如果不存在则返回None或默认值。2.在访问前检查key是否在字典中。3.使用try-except捕获KeyError。假设我们的代码是:value=my_dict[&#39;start_park&#39;]如果my_dict中没有&#39;start_park&#39;,就会引发KeyError。解决方案:1.使用get方法:value=my_dict.get(&#39;start_park&#39;)#不存在返回None或者value=my_dict.get(&#39;start_park&#39;,default_value)#提供默认值2.检查存在:if&#39;start_park&#39;inmy_dict:value=my_dict[&#39;start_park&#39;]else:...处理...3.try-except:try:value=my_dict[&#39;start_park&#39;]exceptKeyError:value=None#或者处理错误根据实际需求选择方法。结合两个问题的解决方案:对于时间解析,我们采用第二种方法(完整解析):collect_start_time=&#39;2025-03-1922:00:00.000000&#39;try:#尝试解析带微秒的格式dt=datetime.datetime.strptime(collect_start_time,&#39;%Y-%m-%d%H:%M:%S.%f&#39;)exceptValueError:try:#如果不带微秒,尝试不带微秒的格式dt=datetime.datetime.strptime(collect_start_time,&#39;%Y-%m-%d%H:%M:%S&#39;)exceptValueError:#如果还不带秒,只取日期部分dt=datetime.datetime.strptime(collect_start_time,&#39;%Y-%m-%d&#39;)part_start=dt.strftime(&#39;%Y%m&#39;)但是注意,原问题中只需要年月,因此我们也可以只提取前7个字符(年-月)然后替换掉横杠?但这样不如解析后格式化安全。另一种更简单的处理:如果字符串格式固定为年-月-日,后面跟时间,我们也可以只分割字符串:date_str=collect_start_time.split()[0]#按空格分割,取第一部分#然后解析日期部分dt=datetime.datetime.strptime(date_str,&#39;%Y-%m-%d&#39;)part_start=dt.strftime(&#39;%Y%m&#39;)这样更简单,也避免了处理时间部分。所以我们推荐:collect_start_time=&#39;2025-03-1922:00:00.000000&#39;#按空格分割,取第一个部分date_str=collect_start_time.split()[0]dt=datetime.datetime.strptime(date_str,&#39;%Y-%m-%d&#39;)part_start=dt.strftime(&#39;%Y%m&#39;)这样就不会有剩余字符的问题。现在,针对用户给出的具体错误信息,我们提供完整的解决方案。同时,我们不知道KeyError出现的具体位置,可能是另一个变量(例如,我们有一个字典包含了开始时间,但键名不对?)假设原始代码中从某个字典获取collect_start_time时使用了键&#39;start_park&#39;,而该字典没有这个键。例如:collect_start_time=some_dict[&#39;start_park&#39;]#可能这里出现了KeyError解决方法:根据实际情况,确保字典中存在&#39;start_park&#39;键,或者用get方法并提供默认值。如果用户代码结构是:data={&#39;some_key&#39;:&#39;2025-03-1922:00:00.000000&#39;}collect_start_time=data[&#39;start_park&#39;]#KeyError因为键是&#39;some_key&#39;那么我们需要确认键名,或者用get方法。因此,综合两个问题,我们可以这样写:#获取数据,使用get方法避免KeyErrorcollect_start_time=data.get(&#39;start_park&#39;)#或者根据实际情况使用正确的键名ifcollect_start_timeisNone:#处理缺失值,例如给一个默认值或报错#假设我们给一个默认值,比如当前时间的年月part_start=datetime.datetime.now().strftime(&#39;%Y%m&#39;)else:#使用分割的方式取日期部分date_str=collect_start_time.split()[0]try:dt=datetime.datetime.strptime(date_str,&#39;%Y-%m-%d&#39;)part_start=dt.strftime(&#39;%Y%m&#39;)exceptExceptionase:#如果解析出错,也使用默认值part_start=datetime.datetime.now().strftime(&#39;%Y%m&#39;)注意:如果原始数据中日期部分格式不是年-月-日,则需要调整解析格式。如果问题中两个错误是独立出现的,那么需要分别处理。下面,我们给出针对两个错误的独立解决方案。</think> ### Python中`datetime.strptime`的`ValueError`与`KeyError`解决方案 #### 🔧问题1:`ValueError: unconverted data remains: 22:00:00.000000` **原因分析** - 输入字符串`2025-03-19 22:00:00.000000`包含完整时间信息 - 格式字符串`%Y-%m-%d`仅匹配日期部分(10字符),导致时间部分成为未解析的"剩余数据" **解决方法** ```python from datetime import datetime collect_start_time = &#39;2025-03-19 22:00:00.000000&#39; # 方案1:精确匹配完整格式(推荐) dt = datetime.strptime(collect_start_time, &#39;%Y-%m-%d %H:%M:%S.%f&#39;) part_start = dt.strftime(&#39;%Y%m&#39;) # → 202503 # 方案2:分割日期部分(更安全) date_part = collect_start_time.split()[0] # 提取"2025-03-19" dt = datetime.strptime(date_part, &#39;%Y-%m-%d&#39;) part_start = dt.strftime(&#39;%Y%m&#39;) # → 202503 ``` #### 🔑问题2:`KeyError: &#39;start_park&#39;` **原因分析** - 字典中不存在`start_park`键 - 可能原因:键名拼写错误/大小写不一致/数据源未包含该字段 **解决方法** ```python data = {&#39;collect_start_time&#39;: &#39;2025-03-19 22:00:00.000000&#39;} # 方案1:使用get()提供默认值 start_park = data.get(&#39;start_park&#39;, None) # 键不存在返回None # 方案2:先检查键是否存在 if &#39;start_park&#39; in data: value = data[&#39;start_park&#39;] else: # 处理缺失逻辑 print("Key not found") # 方案3:异常捕获 try: value = data[&#39;start_park&#39;] except KeyError: # 错误处理逻辑 value = datetime.now().strftime(&#39;%Y%m&#39;) ``` #### 🎯综合解决方案 ```python from datetime import datetime def process_time(data_dict, key=&#39;collect_start_time&#39;): try: # 1. 安全获取字典值 time_str = data_dict.get(key) or "" # 避免NoneType错误 if not time_str: return datetime.now().strftime(&#39;%Y%m&#39;) # 默认值 # 2. 分割日期部分 date_part = time_str.split()[0] # 提取日期 # 3. 安全解析日期 return datetime.strptime(date_part, &#39;%Y-%m-%d&#39;).strftime(&#39;%Y%m&#39;) except Exception as e: print(f"处理错误: {e}") return datetime.now().strftime(&#39;%Y%m&#39;) # 降级方案 # 使用示例 data = {&#39;collect_start_time&#39;: &#39;2025-03-19 22:00:00.000000&#39;} part_start = process_time(data) # → "202503" ``` #### 📌关键要点 1. **时间解析原则**: - 格式字符串必须匹配整个输入字符串 - 使用`split()[0]`可隔离日期部分 - 微秒需用`%f`解析(精确到6位数)[^1] 2. **字典安全访问**: - `dict.get(key, default)`避免`KeyError` - `key in dict`显式检查存在性 - 异常捕获作为最后防线[^2] 3. **防御式编程**: ```mermaid graph LR A[获取原始数据] --> B{键是否存在?} B -->|是| C[解析时间] B -->|否| D[使用默认值] C --> E{解析成功?} E -->|是| F[返回结果] E -->|否| D ``` #### 📚相关问题 1. 如何解析带时区的时间字符串(如`2025-03-19T22:00:00+08:00`)? 2. 使用`pandas`处理时间序列数据时如何避免类似错误? 3. Python中`arrow`或`dateutil`库如何简化日期解析? 4. 如何处理来自不同地区(美式/欧式)的日期格式? [^1]: Python官方文档 [`strftime()`和`strptime()`格式代码](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) [^2]:《Python Cookbook》字典章节异常处理最佳实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值