随着Sybase被完全整合到SAP下,Sybase原来的支持网站被SAP Support Portal取代。
只有购买了SAP服务的用户才能使用账号登录SAP Support Portal进行介质下载、补丁升级、报Incident等。
目前,原Sybase所有产品(包括:Adaptive Server Enterprise、Sybase IQ、Replication Server、PowerDesigner等)的官方手册仍然可以从https://infocenter.sybase.com/help/index.jsp进行浏览或下载。暂不清楚该网站https://infocenter.sybase.com/help/index.jsp何时会被完全迁移到SAP Support上!
Sybase官方手册英文版有html和pdf两种格式,而中文版手册只有pdf一种格式。为了国内Sybase用户更方便、快捷地搜索Sybase常见产品的官方手册内容,特将中文版Sybase官方手册转为html格式!
Sybase产品官方手册中文版的html格式所有内容的版权归SAP公司所有!本博客站长是Sybase数据库的铁杆粉丝!
如有Sybase数据库技术问题需要咨询,请联系我!
以下官方手册为ASE 15.7 ESD#2中文版:
- 新增功能公告 适用于 Windows、Linux 和 UNIX 的 Open Server 15.7 和 SDK 15.7
- 新增功能摘要
- 新增功能指南
- ASE 15.7 发行公告
- 配置指南(windows)
- 安装指南(windows)
- 参考手册:构件块
- 参考手册:命令
- 参考手册:过程
- 参考手册:表
- Transact-SQL® 用户指南
- 系统管理指南,卷 1
- 系统管理指南,卷 2
- 性能和调优系列:基础知识
- 性能和调优系列:锁定和并发控制
- 性能和调优系列:监控表
- 性能和调优系列:物理数据库调优
- 性能和调优系列:查询处理和抽象计划
- 性能和调优系列:使用 sp_sysmon 监控 Adaptive Server
- 性能和调优系列:利用统计分析改进性能
- 程序员参考 jConnect for JDBC 7.0.7
- Adaptive Server Enterprise 中的 Java
- 组件集成服务用户指南
- Ribo 用户指南
- 内存数据库用户指南
- Sybase Control Center for Adaptive Server® Enterprise
- 安全性管理指南
- 实用程序指南
查询处理期间的锁类型和持有时间
查询处理期间获取的锁的类型和持有时间取决于命令的类型、表的锁定 方案以及命令运行时所用的隔离级别。
锁的持有时间取决于隔离级别和查询类型。锁持有时间可以是:
• 扫描持有时间 — 对于行锁或页锁,锁在扫描移出行或页时释放; 对于表锁,锁在表扫描完成时释放。
• 语句持有时间 — 锁在语句执行完成后释放。
• 事务持有时间 — 锁在事务完成时释放。
表 1-12 为不使用游标的查询的每个锁定方案列出了不同隔离级别的查
询所获取的锁的类型。 表 1-13 显示了基于游标的查询的信息。
表 1-12:无游标情况下的锁类型和持有时间
|
隔离级别 |
锁定方案 |
表锁 |
数据 页锁 |
索引 页锁 |
数据 行锁 |
持有时间 |
select |
0 |
所有页 |
- |
- |
- |
- |
不获取任何锁。 |
readtext |
数据页 |
- |
- |
- |
- |
||
任何类型的 |
数据行 |
- |
- |
- |
- |
||
扫描 |
1 |
所有页 |
IS |
S |
S |
- |
* 取决于 read committed with |
2,使用 |
数据页 |
IS |
* |
- |
- |
lock 的设置。请参见 |
|
noholdlock |
数据行 |
IS |
- |
- |
* |
||
3,使用 |
|||||||
noholdlock |
|||||||
2 |
所有页 |
IS |
S |
S |
- |
锁在事务结束时释放。请参 |
|
数据页 |
IS |
S |
- |
- |
|||
数据行 |
IS |
- |
- |
S |
和所有页锁定表”。 |
||
select 通过 |
3 |
所有页 |
IS |
S |
S |
- |
锁在事务结束时释放。 |
索引扫描 |
1,使用 |
数据页 |
IS |
S |
- |
- |
|
holdlock |
数据行 |
IS |
- |
- |
S |
||
2,使用 |
|||||||
holdlock |
|||||||
select |
3 |
所有页 |
IS |
S |
- |
- |
锁在事务结束时释放。 |
通过表扫描 |
1,使用 |
数据页 |
S |
- |
- |
- |
|
holdlock |
数据行 |
S |
- |
- |
- |
||
2,使用 |
|||||||
holdlock |
|||||||
insert |
0, 1, 2, 3 |
所有页 |
IX |
X |
X |
- |
锁在事务结束时释放。 |
数据页 |
IX |
X |
- |
- |
|||
数据行 |
IX |
- |
- |
X |
提示:IS 共享意图, IX 排它意图, S 共享, U 更新, X 排它
语句 |
隔离级别 |
锁定方案 |
表锁 |
数据 页锁 |
索引 页锁 |
数据 行锁 |
持有时间 |
writetext |
0, 1, 2, 3 |
所有页 |
IX |
X |
- |
- |
在第一个文本页或行上持有 |
数据页 |
IX |
X |
- |
- |
锁;锁在事务结束时释放。 |
||
数据行 |
IX |
- |
- |
X |
|||
delete |
0, 1, 2 |
所有页 |
IX |
U、 X |
U、 X |
- |
“U”锁在语句完成后释放。 |
update |
数据页 |
IX |
U、 X |
- |
- |
“IX”和 “X”锁在事务结 |
|
任何类型的 |
数据行 |
IX |
- |
- |
U、 X |
束时释放。 |
|
扫描 |
|||||||
delete |
3 |
所有页 |
IX |
U、 X |
U、 X |
- |
“U”锁在语句完成后释放。 |
update |
数据页 |
IX |
U、 X |
- |
- |
“IX”和 “X”锁在事务结 |
|
通过索引 |
数据行 |
IX |
- |
- |
U、 X |
束时释放。 |
|
扫描 |
|||||||
delete |
3 |
所有页 |
IX |
U、 X |
- |
- |
锁在事务结束时释放。 |
update |
数据页 |
X |
- |
- |
- |
||
通过表扫描 |
数据行 |
X |
- |
- |
- |
提示:IS 共享意图, IX 排它意图, S 共享, U 更新, X 排它
select 0 (无 for 子句) select... for 1 read only 2 ,使用 noholdlock 3 ,使用 noholdlock 2, 3 1,使用 holdlock 2,使用 holdlock select...for 1 update |
数据 |
索引 |
数据 |
||||
锁定方案 |
表锁 |
页锁 |
页锁 |
行锁 |
持有时间 |
||
所有页 |
- |
- |
- |
- |
不获取任何锁。 |
||
数据页 |
- |
- |
- |
- |
|||
数据行 |
- |
- |
- |
- |
|||
所有页 |
IS |
S |
S |
- |
* 取决于 read committed with |
||
数据页 |
IS |
* |
- |
- |
|||
数据行 |
IS |
- |
- |
* |
|||
查询的锁定”。 |
|||||||
所有页 |
IS |
S |
S |
- |
游标移出页 / 行之外后锁变为 |
||
数据页 |
IS |
S |
- |
- |
事务型锁。锁在事务结束时 |
||
数据行 |
IS |
- |
- |
S |
释放。 |
||
所有页 |
IX |
U、 X |
X |
- |
“U”锁在游标移出页 / 行之 |
||
数据页 |
IX |
U、 X |
- |
- |
外后释放。“IX”和 “X” |
||
数据行 |
IX |
- |
- |
U、 X |
锁在事务结束时释放。 |
||
select...for |
1 |
所有页 |
IX |
S、 X |
X |
- |
“S”锁在游标移出页 / 行之 |
update with |
数据页 |
IX |
S、 X |
- |
- |
外后释放。“IX”和 “X” |
|
shared |
数据行 |
IX |
- |
- |
S、 X |
锁在事务结束时释放。 |
|
select...for |
2, 3, 1 holdlock |
所有页 |
IX |
U、 X |
X |
- |
游标移出页 / 行之外后锁变 |
update |
2, holdlock |
数据页 数据行 |
IX IX |
U、 X - |
- - |
- U、 X |
为事务型锁。锁在事务结束 时释放。 |
提示:IS 共享意图, IX 排它意图, S 共享, U 更新, X 排它
数据 |
索引 |
数据 |
|||||
语句 |
隔离级别 |
锁定方案 |
表锁 |
页锁 |
页锁 |
行锁 |
持有时间 |
select...for |
2, 3 |
所有页 |
IX |
S、 X |
X |
- |
游标移出页 / 行之外后锁变 |
update with |
1,使用 holdlock 数据页 |
IX |
S、 X |
- |
- |
为事务型锁。锁在事务结束 |
shared
2,使用 holdlock
数据行
IX -
- S、 X
时释放。
提示:IS 共享意图, IX 排它意图, S 共享, U 更新, X 排它
create index 命令期间的锁类型
表 1-14 描述了 Adaptive Server 对 create index 语句应用的锁类型:
表 1-14:create index 语句期间的锁的总结
语句 |
表锁 |
数据页锁 |
create clustered index |
X |
- |
create nonclustered index |
S |
- |
键:S = 共享, X = 排它 |
用于隔离级别 1 的 select 查询的锁定
当所有页锁定表上的 select 查询以隔离级别 1 执行表扫描时,查询首先 在表上获取共享意图锁,然后在第一个数据页上获取共享锁。接着,查 询锁定下一个数据页,并删除第一页上的锁,以便锁 “穿过”结果集。 查询完成后,立即释放最后一个数据页上的锁,然后释放表级锁。同样, 在对所有页锁定表执行索引扫描期间,在扫描从索引根页向下进行到数 据页时,将持有重叠锁。当扫描连接的内部表中匹配的行时,也会在连 接的外部表上持有锁。
DOL 锁定表上的 select 查询首先获取共享意图表锁。可以发出参数 read committed with lock 来配置数据页和数据行上的锁定行为,如下所示:
• 如果 read committed with lock 设置为 0 (缺省值),那么 select 查询使 用瞬间页锁或瞬间行锁读取列值。在所需的列值或行的指针读入内 存后,将释放这些瞬间锁。访问内部表的行时,在连接的外部表上 并不持有锁。这样减少了死锁并提高了并发性。
如果 select 查询需要读取由不兼容锁锁定的行,查询会在这一行上 阻塞,直到不兼容锁被释放。将 read committed with lock 设置为 0 并 不影响隔离级别,只有提交的行才会返回给用户。
• 如果将 read committed with lock 设置为 1,select 查询在数据页锁定表 上获取共享页锁,在数据行锁定表上获取共享行锁。先在第一页或 第一行上持有锁,然后在第二页或第二行上获取锁并删除第一页或 第一行上的锁。
必须将游标声明为只读,以避免当 read committed with lock 设置为 0 时在 扫描期间持有锁。 DOL 锁定表上的任何隐式或显式可更新游标都在当 前页或行上持有锁,直到游标移出该行或页。当 read committed with lock 设置为 1 时,只读游标在游标所在行上持有共享页锁或共享行锁。
read committed with lock 不影响所有页锁定表上的锁定行为。有关这些配 置参数的信息,请参见 《系统管理指南:第一卷》中的第 5 章 “设置 配置参数”。
表扫描与隔离级别 2 和 3
本节描述关于以隔离级别 2 和 3 执行的表扫描期间的锁定需特别考虑的 问题。
隔离级别 3 的表扫描和表锁
当查询以隔离级别 3 在 DOL 锁定表上执行表扫描时,共享或排它表锁 可提供幻像保护并减少维护大量行锁或页锁所需的锁定开销。在所有页 锁定表上,隔离级别 3 的扫描首先获取共享或排它意图表锁,然后获取 并持有页级锁,直到事务完成或直到达到锁升级阈值并可以授予表锁。
隔离级别 2 和所有页锁定表
在所有页锁定表上, Adaptive Server 支持隔离级别 2 (可重复读取), 另外也会强制使用隔离级别 3 (可串行化读取)。如果在会话中设置了 事务级别 2,而且查询中包括所有页锁定表,则也将在此所有页锁定表 上应用隔离级别 3。事务级别 2 将用在会话中的所有 DOL 锁定表上。
当不需要更新锁时
所有页锁定表上的所有 update 和 delete 命令都首先在数据页上获取更新 锁,然后,如果行符合查询中的条件,则更改为排它锁。
在查询为以下情况时,DOL 锁定表上的 update 和 delete 命令并不先获取 更新锁:
• 包含对应于选定索引中的每个键的搜索参数,从而使索引明确地限 定了相应的行,以及
• 不包含 or 子句。
符合这些要求的更新和删除立即在数据页或数据行上获取一个排它锁。 这减少了锁开销。
在某些情况下,使用 or 子句的查询作为多个查询的联合进行处理。尽管 某些行可能与多个 or 条件匹配,但每行必须只返回一次。对每个 or 子 句,可使用不同的索引。如果任一子句缺少有用的索引,则使用表扫描 来执行查询。
表锁定方案和隔离级别可影响 or 处理的执行方式以及查询期间锁的持有 时间。
如果 or 查询使用 “or”策略 (不同的 or 子句可能匹配相同的行),查 询处理会从索引中检索行 ID 和匹配的键值并将它们存储到工作表中, 同时在包含这些行的索引页上持有共享锁。检索完所有的行 ID 后,会 对工作表进行排序以删除重复的值。然后,扫描工作表,用行 ID 检索 数据行,同时在数据页上获取共享锁。索引页和数据页锁在语句结束时 释放 (对于隔离级别 1)或在事务结束时释放 (对于隔离级别 2 和 3)。
如果 or 查询不可能返回重复的行,就不需要进行工作表排序。在隔离级 别 1,数据页上的锁在扫描移出页后立即释放。
在 DOL 锁定表上,使用 “or”策略 (当可能有多个子句匹配相同的行 时)的 or 查询获取的锁类型和持有时间取决于隔离级别。
从索引中检索行 ID 并复制到工作表中时,在 DOL 锁定表的索引页或行 上不获取任何锁。对工作表排序以删除重复值后,当用行 ID 从表中读 取数据时,数据行将重新进行限定。如果删除了任何行,则不会返回这 些行。如果更新了任何行,则会通过应用全部查询子句来重新限定这些 行。对于隔离级别 1,锁在行限定完成后释放,对于隔离级别 2,锁在 事务完成后释放。
处理隔离级别 3 的 or 查询
隔离级别 3 要求可串行化读取。在此隔离级别上, or 查询在 or 处理的 第一阶段 (也就是填充工作表时)在数据页或数据行上获得锁。这些 锁一直持有到事务完成,不需要重新限定行。
在 select 期间跳过未提交的插入
在以下情况下, DOL 锁定表上的 select 查询不阻塞未提交的插入:
• 表使用数据行锁定,以及
• 隔离级别为 1 或 2。 在这些情况下,扫描将跳过这样的行。
此规则的唯一例外是,执行未提交 insert 的事务正在覆盖由同一事务以 前对同一行执行的未提交 delete 的情况。在这种情况下,扫描将在未提 交的插入行上阻塞。
在 delete、 update 和 insert 期间跳过未提交的插入
对于未提交的插入, delete 和 update 查询与扫描的行为相同。当 delete 或 update 命令遇到未提交的具有相关键值的插入行时,将跳过此行而不 阻塞。
此规则的唯一例外是,执行未提交 insert 的事务正在覆盖由同一事务以前 对同一行执行的未提交 delete 的情况。在这种情况下, update 和 delete 将在未提交的插入行上阻塞。
当遇到未提交的具有相同键值的插入行时, insert 查询将由于索引不唯 一而引发重复键错误。
DML 期间在具有跨数据库参照完整性约束的表上锁定
当事务在具有外键约束的表中插入一行时,它会在隔离级别 2 对具有主 键约束的表 (被具有外键约束的表引用)执行扫描。 Adaptive Server 执 行此扫描,以使用行在事务提交之前不被更新或删除。被扫描的表上的 任何更新和删除都会在被插入但还未提交的行的引用键上阻塞。
同样,当事务尝试从具有主键约束的表中删除一行时,它会在隔离级别 3 对具有外键约束的表 (引用此表)执行扫描。 Adaptive Server 不允许对 这些表进行行插入,直到发生删除行提交的事务为止。
使用替代谓词跳过非限定行
当 select 查询包括多个由 and 链接的 where 子句时,Adaptive Server 可以 对任何未受未提交的行更新影响的列应用限定条件。如果由于未修改的 列上的一个子句而使行无法限定,则不需要返回相应的行,因此查询不 会阻塞。
如果行在检查过未修改列上的条件时进行了限定,而且 第 30 页的 “限 定未提交的更新的旧值和新值”中所描述的条件不允许查询继续进行, 则查询会阻塞,直到锁被释放。
例如, 表 1-15 中的事务 T15 更新 balance,而同时事务 T16 在结果集和 搜索子句中包含 balance。但是,T15 并不更新 branch 列,所以 T16 可以 应用该搜索参数。 表 1-15 讲述使用伪列的事务,伪列是索引表中的列, 它定义搜索的参数并提供对结果数据的访问。
因为受 T15 影响的行的 branch 值不是 77,所以该行不被限定并被跳过, 如下所示。如果 T15 更新了 branch 等于 77 的行,select 查询会阻塞,直 到 T15 提交或回退。
表 1-15:使用多个谓词的伪列级锁定
T15 |
事件序列 |
T16 |
begin transaction
update accounts set balance = 80
where acct_number = 20 and branch = 23
commit transaction
T15 和 T16 开始。
T15 更新帐户并持有 排它行锁。
T16 查询帐户,但并 不阻塞,因为可以应 用 branch 限定。
begin transaction
select acct_number, balance from accounts
where balance < 50 and branch = 77 commit tran
为了使 select 查询在引用要更新的列以外的列时避免阻塞,必须满足以 下所有条件:
• 表必须使用数据行或数据页锁定。
• select 查询的搜索子句中,必须至少有一个子句位于表的头 32 列中 的某一列。
• select 查询必须在隔离级别 1 或 2 运行。
• 配置参数 read committed with lock 必须设置为缺省值 0。
Sybase SQL Anywhere数据库恢复工具ReadASADB:
之前就已经研发成功了能够从Sybase SQL Anywhere的DB文件中恢复数据的工具: ReadASADB。此工具支持ASA v5.0, v6.0, v7.0, v8.0, v9.0, v10.0, v11.0, v12.0, v16.0, v17.0等版本。
能够从损坏的SQL Anywhere数据文件(.db)和UltraLite数据文件(.udb)上提取数据的非常规恢复工具。
恢复Sybase SQL Anywhere的工具在国内处于领先水平。
Sybase SQL Anywhere数据库恢复工具ReadASADB功能
能够从损坏的SQL Anywhere数据文件(.db)和UltraLite数据文件(.udb)上提取数据的非常规恢复工具
- 适用于所有的SQL Anywhere版本 包括:5.x,6.x,7.x,8.x,9.x,10.x,11.x,12.x,16.x,17.x
- 适用于所有的UltraLite版本
- 能够恢复出来表结构和数据
- 能够恢复自定义数据类型
- 能够恢复存储过程等对象的语法
- 能够导出到目标数据库
- 能够导出到SQL文件并生成导入脚本
- 支持多种字符集,包括:cp850、cp936、gb18030、utf8等
- 能够恢复未加密或者简单加密类型的数据
- 简单易用
- 限制:不支持AES加密的数据文件
SQL Anywhere数据库非常规恢复工具ReadASADB使用介绍
Sybase SQL Anywhere数据库恢复工具ReadASADB适用场景
各种误操作:
- 误截断表(truncate table)
- 误删除表(drop table)
- 错误的where条件误删数据
- 误删除db或log文件
- 误删除表中的字段
Sybase SQL Anywhere数据库恢复工具ReadASADB的应用场景:
1.因为物理磁盘故障、操作系统、系统软件方面或者掉电等等原因导致的Sybase SQL Anywhere数据库无法打开的情况;
2.误操作,包括truncate table,drop table,不正确的where条件导致的误删除等;
Sybase SQL Anywhere无法打开时,比较常见的错误是:Assertion failed。
如:
1、Internal database error *** ERROR *** Assertion failed:201819 (8.0.1.2600) Checkpoint log: invalid bitmap page -- transaction rolled back
2、Internal database error *** ERROR *** Assertion failed:201819 (8.0.1.2600) Page number on page does not match page requested -- transaction rolled back
3、Internal database error *** ERROR *** Assertion failed:200502 (9.0.2.2451) Checksum failure on page 23 -- transaction rolled back
4、File is shorter than expected
5、Internal database error *** ERROR *** Assertion failed: 201116 Invalid free list index page found while processing checkpoint log -- transaction rolled back
6、*** ERROR *** Assertion failed: 51901 Page for requested record not a table page or record not present on page
7、*** ERROR *** Assertion failed: 201417 (7.0.4.3541) Invalid count or free space offset detected on a table page
8、Internal database error *** ERROR *** Assertion failed: 201425 (8.0.3.5594) Invalid count or free space offset detected on a free list page -- transaction rolled back.
9、Internal database error *** ERROR *** Assertion failed: 100702 (8.0.1.2600) Unable to modify indexes for a row referenced in rollback log -- transaction rolled back
Sybase ASE数据库恢复工具READSYBDEVICE:
一个不依赖数据库管理系统、直接从Sybase数据库设备文件上提取数据的业内领先的恢复工具!能够从损坏的Sybase ASE设备文件(.dat)上提取数据的非常规恢复工具。
Sybase ASE数据库恢复工具READSYBDEVICE的主要功能:
- 被勒索病毒加密数据文件及备份文件情况下的恢复;
- 系统崩溃只剩下数据文件的情况下的恢复,甚至数据库文件不存在而只有损坏的备份文件情况下的恢复;
- 因断电、硬盘坏道等造成数据库文件损坏情况下的恢复;
- delete数据恢复、误update数据恢复、误删除表(drop)恢复、误truncate表恢复 等;
- 各种Sybase内部系统表损坏、索引错误的修复;
- master数据库损坏而无法正常运行情况下的恢复;
- Sybase数据库被标记为可疑,不可用等情况的恢复;
- Sybase数据库中数据文件内部出现坏块情况下的恢复;
- Sybase数据库无数据文件但有日志文件的情况下的恢复;
- Sybase数据库只有数据文件无任何日志文件的情况下的恢复;
- Sybase数据文件被误删除情况下的碎片提取恢复;
- 磁盘阵列上的Sybase数据库被误格式化情况下的数据库恢复;
- 数据库sysobjects等系统表损坏无法正常应用情况下的恢复;
- Sybase数据库还原数据库出现失败情况下的恢复;
- Sybase数据库只剩下损坏的备份文件情况下的恢复。
Sybase ASE数据库恢复工具READSYBDEVICE支持的版本:
Sybase ASE 11.0.x,11.5.x,11.9.x,12.0.x,12.5.x,15.0.x,15.5.x,15.7.x,16.0.xSQL Server数据库恢复工具SQLRescue:
一个不依赖数据库管理系统、直接从SQL Server数据库文件上提取数据的业内领先的恢复工具!能够从损坏的SQL Server数据库文件(.mdf)上提取数据的非常规恢复工具。
SQL Server数据库恢复工具SQLRescue的主要功能:
- 系统崩溃只剩下数据文件的情况下的恢复,即无日志文件或者日志文件损坏情况下的恢复;
- 断电导致数据库文件损坏情况下的恢复;
- 硬盘坏道造成数据库损坏情况下的恢复;
- 数据文件内部存在坏页情况下的恢复;
- 企业管理器误删除数据表记录,管理软件误删除数据表记录的恢复;
- 并闩锁错误、格式化、误删除后导致软件不能使用的情况;
- 无法读取并闩锁页sysindexes失败情况下的修复;
- 数据文件被误删除情况下的碎片提取恢复;
- 系统表损坏、索引错误、误删除数据库表、删除记录的数据找回;
- master数据库损坏而无法正常运行情况下的恢复;
- 数据文件无法附加情况下的数据恢复;
- 数据库被标记为可疑,质疑,不可用等情况的恢复;
- 数据库sysobjects等系统表损坏情况下的恢复;
- 数据被误(drop、delete、truncate)删除表数据的恢复,误update后的数据恢复等;
- 还原时报一致性错误,错误823等情况下的数据恢复,各种错误提示的数据库文件修复;
- 数据库被误格式化等情况下的数据库恢复;
- 日志收缩造成数据库损坏情况下的恢复;
- 仅剩损坏的备份文件情况下的恢复。
SQL Server数据库恢复工具SQLRescue技术特点:
只要SQL Server数据库的数据文件存在,我们就有办法帮您从数据文件中找回重要数据。- 从数据文件中直接恢复数据
- 不能附加时直接恢复数据并生成新的数据库
- 系统表损坏的数据库修复
- 快速修复SQL 823错误、连接中断错误
SQL Server数据库恢复工具SQLRescue支持的版本:
Microsoft SQL Server 7.0, 2000, 2005, 2008, 2008R2, 2012, 2014, 2016, 2017,2019。+-------------------------------------华丽的分割线-------------------------------------------------------------------------