作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
第一个 和 第二个 本系列的部分文章讨论了甲骨文数据库和Microsoft SQL Server在事务实现方面的差异, 以及由此产生的转换陷阱, 以及一些常用的语法元素.
最后一部分将介绍的概念 甲骨文 阅读一致性以及如何将基于此概念的体系结构转换为 Microsoft SQL Server 版本. 本文还将讨论同义词的使用(以及不使用同义词的方法)以及变更控制过程在管理数据库环境中的作用.
甲骨文读一致性 是否保证单个SQL语句返回的所有数据都来自同一时间点.
也就是说,如果你发行了 SELECT
12:01:02的声明.在返回结果集之前,它运行了5分钟, 截至12:01:02时在数据库中提交的所有数据(且仅是数据).345英镑会进入你的回程. 在数据库处理您的语句所花费的5分钟内,您的返回集不会添加任何新数据, 也没有任何更新, 并且不会看到任何删除.
甲骨文体系结构通过在内部对每次数据更改进行时间戳,并从两个来源构建结果集来实现读一致性:永久数据文件和撤销段(或回滚段),” 直到10g版本才知道).
为了支持它,撤销信息 应该保存. 如果它被覆盖,就会产生臭名昭著的 ORA-01555:快照太旧
错误.
不考虑撤消段管理,以及如何导航 ORA-01555:快照太旧
让我们看看读一致性在甲骨文中任何实际实现中的含义. 也, 它应该如何镜像在SQL Server, 这与其他RDBMS实现的情况一样, postgresql不支持它?
关键是甲骨文的读和写不会互相阻塞. 这还意味着长时间运行的查询返回集可能没有最新的数据.
非阻塞读写是甲骨文的一个优势 影响事务范围.
但是读一致性也意味着您没有数据的最新状态. 在某些情况下,它非常好(比如生成特定时间的报告), 这可能会给其他国家带来重大问题.
没有最新的——甚至“脏”,或未提交的数据可能很关键:典型的场景是酒店房间预订系统.
考虑以下用例:您有两个同时接受房间预订订单的客户服务代理. 你如何确保房间不会被超额预订?
在SQL Server中,您可以启动显式事务和 SELECT
可用房间列表(可以是表或视图)中的一条记录. 只要这笔交易不是由 提交
or 回滚
),没有人可以得到您选择的相同房间记录. 这可以防止重复预订,但也会使其他所有代理等待对方一次完成一个预订请求, 按顺序.
在甲骨文中,您可以通过发出 SELECT ... 更新
对符合您搜索条件的记录的声明.
注意:存在更好的解决方案, 比如设置一个临时标志,标记一个房间“正在考虑中”,而不是盲目地锁定进入它的通道. 但这些都是架构解决方案,而不是语言选项.
结论甲骨文读一致性不是“全好”或“全坏”,而是平台的一个重要属性,需要很好地理解,对跨平台代码迁移至关重要.
“公共同义词是邪恶的.“这是 这不完全是我个人的发现直到我的每一天、每一周、每一年都被公开的同义词拯救了.
在许多数据库环境中——我要说的是我有机会使用过的所有甲骨文环境, 但都不是我设计的 创建公共同义词
对于每个对象 是例行公事是因为“我们一直都是这么做的?.”
在这些环境中, 公共同义词只有一个功能:允许引用对象而不指定其所有者. 这是一个 考虑不周的理由 使公共同义词.
然而, 甲骨文公共同义词非常有用,并且给团队带来的生产力好处大大超过了它们所有的缺点, 如果执行和管理正确,并且有理由的话. 是的,我说的是“团队生产力”.“可是怎么回事?”? 为此,我们需要了解甲骨文中的名称解析是如何工作的.
当甲骨文解析器查找名称(非保留关键字)时, 它尝试按照以下顺序将其与现有数据库对象匹配:
注意:引发的错误将是 ORA-00942:表或视图不存在
对于DML语句,或 pl -00201:标识符'my_object'必须声明
用于存储过程或函数调用.
按此名称解析顺序, 当开发人员在他们自己的模式中工作时,很容易看到这一点, 任何与公共同义词同名的本地对象都将 隐藏 这个公共同义词. (注意:甲骨文 18c实现了“仅登录”模式类型,这里的讨论不适用于它.)
现在让我们假设一个由100名开发人员组成的团队在同一个数据库上工作(这是我经历过的). 进一步, 让我们假设他们都在他们的个人工作站上本地工作,并且独立地进行非数据库构建, 所有链接到相同的数据库开发环境. 解决非数据库代码(无论是c#)的代码合并问题, Java, C++, Python, 或其他任何事情)将在变更控制签入时完成,并将在下一个代码构建中生效. 但是数据库表, code, 在持续的开发过程中,数据需要来回更改多次. 每个开发人员都独立地执行此操作,并且立即生效.
为此,所有数据库对象都是在一个通用的应用程序模式中创建的. 这是 的 应用程序引用的模式. 每个开发人员:
当开发者需要制作 任何 对数据库的更改—创建或修改表, 更改程序代码, 或者甚至修改一组数据来支持某些测试场景——他们在他们的个人模式中创建对象的副本. 方法获取DDL代码 描述
命令并在本地运行.
从这一刻起, 该开发人员的代码将看到对象和数据的本地版本, 这不会被其他人看到(也不会对他们产生影响). 开发完成后, 修改后的数据库代码签入到源代码控制中, 冲突得到解决. 然后,在公共模式中实现最终的代码(和数据,如果需要的话).
在此之后,整个开发团队可以再次看到相同的数据库. 刚刚交付代码的开发人员从他/她的个人模式中删除了所有对象,并准备好接受新的任务.
这种促进多个开发人员独立并行工作的能力是公共同义词的主要好处——其重要性怎么强调都不为过. 然而, 在实践中, 我继续看到团队在甲骨文实现中创建公共同义词,“只是因为我们总是这样做。.相比之下, 使用SQL Server的团队, 我不认为创建公共同义词是一种常见的做法. 该功能存在,但不经常使用.
在SQL Server中, 用户的当前默认模式是在用户配置中定义的,如果您具有“alter user”权限,则可以随时更改该模式. 可以实现与上面描述的甲骨文完全相同的方法. 但是,如果不使用此方法,则不应复制公共同义词.
由于Microsoft SQL Server默认情况下不会将新用户帐户与自己的模式关联(而甲骨文则会)。, 该关联应该是标准“创建用户”脚本的一部分.
下面是创建专用用户模式并将其分配给用户的脚本示例.
首先,为新用户创建模式,这些用户需要登录到命名的数据库 DevelopmentDatabase
(每个模式必须在自己的批处理中创建):
使用DevelopmentDatabase;
GO
创建模式Dev1
GO
创建模式Dev2
GO
其次,用分配的默认模式创建第一个用户:
创建账号DevLogin123, PASSWORD = 'first_pass123';
用DEFAULT_SCHEMA = Dev1创建用户Dev1
GO
此时,默认模式为user Dev1
将 Dev1
.
接下来,创建另一个没有默认模式的用户:
创建用户DevLogin321和PASSWORD = 'second_pass321';
创建用户Dev2
GO
用户的默认模式 Dev2
is dbo
.
现在修改用户 Dev2
将其默认模式更改为 Dev2
:
改变用户 Dev2 WITH DEFAULT_SCHEMA
GO
现在是用户的默认模式 Dev2
is Dev2
.
这个脚本演示了在Microsoft SQL Server数据库中为用户分配和更改默认模式的两种方法. 由于SQL Server支持多种用户身份验证方法(最常见的是Windows身份验证),因此用户登录可能由系统管理员而不是dba来处理, 的 改变用户
分配/更改默认模式的方法将更有用.
注意:我使模式的名称与用户的名称相同. 在SQL Server中不需要这样, 但这是我的首选,因为(1)它与甲骨文中的方式相匹配,(2)它简化了用户管理(解决了DBA首先要做正确的事情的最大反对意见)—您知道用户的名称, 并且您会自动知道用户的默认模式.
结论公共同义词是构建稳定且受到良好保护的多用户开发环境的重要工具. 不幸的是, 根据我对这个行业的观察, 它更经常被用于错误的原因——让团队遭受公共同义词的困惑和其他缺点,而没有意识到它们的好处. 更改此实践以从公共同义词中获得真正的好处可以为团队的开发工作流带来真正的好处.
正如我们刚刚谈到的大型团队对并行开发的支持, 有一个单独的、经常被误解的话题是值得讨论的:变更控制过程.
变更管理经常变成一种由团队领导和dba控制的繁文缛节, 被叛逆的开发者鄙视,他们想要交付所有东西,如果不是“昨天”,那就是“现在”.”
作为一名DBA,我总是在进入“我的”数据库的路上设置保护性屏障. 我有一个很好的理由:数据库是一种共享资源.
在源代码控制上下文中, 变更管理通常被接受,因为它允许团队从新的但损坏的代码恢复到旧的但工作的代码. 但是在数据库上下文中, 变更管理看起来像是dba设置的一组不合理的障碍和限制:这是纯粹的疯狂,它不必要地减缓了开发!
让我们把这个开发人员的咆哮放在一边:我是一个DBA,我不会向自己扔石头! 作为一名DBA,我总是在进入“我的”数据库的路上设置保护性屏障. 我有一个很好的理由:数据库是一种共享资源.
每个开发团队——以及他们的每个开发人员——都有一个非常明确定义的目标和非常具体的可交付成果. DBA每天的唯一目标是确保数据库作为共享资源的稳定性. DBA在组织中具有独特的角色,监督所有团队的所有开发工作,并控制所有开发人员访问的数据库. DBA要确保所有项目和所有流程都在互不干扰的情况下运行,并确保每个项目和流程都拥有运行所需的资源.
问题在于开发团队和DBA团队都被困在各自的象牙塔里.
开发者不知道, 没有权限, 甚至不关心数据库上发生了什么,只要它能正常运行就行. (这不是他们的可交付成果,也不会影响他们的绩效评估.)
DBA团队将数据库保密, 保护它不受“一无所知”的开发人员的影响, 因为他们的团队目标是数据库稳定性. 确保稳定性的最佳方法是防止破坏性的更改,这通常会导致尽可能保护数据库不受任何更改的影响.
这些 对数据库的矛盾态度 可以, 正如我所见, 会导致开发团队和DBA团队之间的敌意,并导致不可用的环境. 但是dba和开发团队必须一起工作以实现一个共同的目标:交付业务解决方案, 是什么让他们走到一起的.
我经历过开发人员和dba这两个阵营, 我知道,当dba更好地理解开发团队的共同任务和目标时,这个问题很容易解决. 站在他们这边, 开发人员不应将数据库视为抽象概念,而应将其视为共享资源, DBA应该扮演教育者的角色.
非开发人员dba最常犯的错误是限制开发人员访问数据字典和代码优化工具. 访问甲骨文 DBA_
目录视图,动态的 V$
视图和 SYS
对于许多DBA来说,表似乎是“DBA特权”,而实际上,这些是关键的开发工具.
这同样适用于SQL Server, 但有一个复杂之处:不能直接授予对某些系统视图的访问权限, 然而,这只是……的一部分 系统管理员
数据库角色,这个角色永远不应该被授予DBA团队之外的人. 这可以通过创建视图和存储过程来解决(并且应该在项目从甲骨文迁移到SQL Server的情况下解决) 系统管理员
权限,但非dba用户可以访问. 这是 开发DBA的 作为一个新的SQL Server开发环境配置的工作.
数据保护是DBA的主要职责之一. 尽管如此, 开发团队通常可以完全访问未经过滤的生产数据,以便进行与数据相关的票据故障排除. 这些开发人员对数据结构的访问权限有限——数据结构是由他们创建的,或者首先是为他们创建的.
当开发团队和DBA团队之间建立了适当的工作关系时, 创建一个好的变更控制过程变得很直观. 数据库端变更管理的特点和挑战是数据库的刚性和流动性——结构是刚性的, 数据是流动的.
变更管理经常发生在结构修改上.e., 论数据定义语言, 或ddl是完善的,而数据更改在更改管理方面几乎没有. 理由很简单——数据一直在变化.
但如果我们更仔细地看, 我们在任何系统中都能看到, 所有数据都可以分为两类:应用程序数据和用户数据.
应用程序数据 数据字典是否定义了应用程序的行为,并且与任何应用程序代码一样对其进程至关重要. 对这些数据的更改应在严格的更改控制流程下进行, 就像任何其他应用程序更改一样. 为了在应用程序数据更改的变更控制过程中创建透明度, 应用程序数据和用户数据应该明确地分开.
在甲骨文中,应该通过将应用程序和用户数据分别放在自己的模式中来完成. 在Microsoft SQL Server中, 应该通过将它们放入单独的模式中来完成,或者更好的方法是将它们放入单独的数据库中. 做出这些选择应该是迁移计划的一部分:甲骨文有两级名称解析(模式/所有者-对象名称),而SQL Server有三级名称解析(数据库-模式/所有者-对象名称).
令人惊讶的是,甲骨文和SQL Server世界之间的一个常见混淆来源是术语 数据库 和 服务器:
SQL Server术语 | 甲骨文术语 | 定义 |
---|---|---|
服务器 | 数据库 可与…互换使用 服务器 用一般的说法, 除非特别提到服务器硬件, OS, or network elements; 的re 可以 be one or more 数据库s on a physical/virtual 服务器) | 可以通过网络端口与其他实例“对话”的运行实例 |
数据库 (服务器的一部分,包含多个模式/所有者) | 模式/所有者 | 最顶层的分组 |
在跨平台迁移项目中,应该清楚地理解这种术语混淆,因为术语误解可能导致不正确的配置决策,难以追溯.
正确分离应用程序和用户数据可以让DBA团队解决第二个最重要的问题:用户数据安全性. 由于用户数据是单独存在的,因此实现 破玻璃的过程 根据需要访问用户数据.
结论变更控制过程在任何项目中都是至关重要的. 在软件工程中, 数据库端的变更管理常常被忽视,因为数据被认为“太不稳定”.但正是因为数据是“流动的”和“持久的”,所以设计良好的变更控制过程应该是适当的数据库环境体系结构的基石.
标准的第一方工具, 甲骨文迁移工作台 和 SQL Server迁移助手,可以在代码迁移中有所帮助. 但需要考虑的是 80/20法则:何时代码迁移的正确性为80%, 解决剩下的20%将占用迁移工作的80%.
使用迁移工具的最大风险是“银弹”观念. 人们可能会想, “它会起作用的, 我只需要做一点清理和整理.“我观察过一个由于转换团队及其技术领导的这种态度而失败的项目.
另一方面, 使用notepad++的批量替换功能作为主要编辑工具,我花了四个工作日完成了一个中型Microsoft SQL Server 2008系统(大约200个对象)的基本转换.
到目前为止,我所讨论的关键迁移元素都不能由迁移工具解决.
当然,一定要使用迁移辅助工具,但请记住,这些工具只提供编辑辅助. 需要检查产生的输出文本, 修改, 在某些情况下,还需要重写代码以使其具有生产价值.
人工智能工具的发展可能会在未来解决这些迁移工具的不足, 但我预计,在那之前,数据库之间的差异将变得模糊,任何迁移过程本身都将变得不必要. So, 只要这些类型的项目是需要的, 我们需要用老方法来做, 利用传统的人类智慧.
结论使用迁移辅助工具是有帮助的,但它不是“银弹”,,任何转换项目仍然需要对上述几点进行详细的审查.
甲骨文和Microsoft SQL Server是企业环境中最流行的两个RDBMS平台. 两者都基本符合ANSI SQL标准, 小段的代码可以在很少修改的情况下移动, 甚至是现在.
这种相似性造成了一种错觉,即跨两个平台的迁移很简单, 任务很简单,而且同一个应用程序可以很容易地从一个RDBMS后端移植到另一个RDBMS后端.
在实践中, 这样的平台迁移远非微不足道,必须考虑到每个平台内部工作的精细元素, 最重要的是, 它们实现对数据管理中最关键元素:事务的支持的方式.
虽然我介绍了两个RDBMS平台,它们是我专业知识的核心, 同样的警告——“看起来相似并不意味着工作方式相似”——应该应用于在任何其他sql兼容的数据库管理系统之间移动代码. 在所有情况下, 首先要注意的是源平台和目标平台之间事务管理的实现有何不同.
在甲骨文中, 数据一致性基于多版本控制:引用单个时间点的任何版本的数据都应该处于不违反活动数据库约束的状态.
甲骨文读一致性是一种SQL语句级别的保证,保证所有数据都以一致的状态返回,就像提交语句执行时的状态一样. 为了支持这一点,甲骨文管理多个时间点对应的多个版本的数据.
数据库一致性检查是一个验证数据库处于一致状态并且没有丢失或损坏数据块的过程. 应该在备份和硬件故障后正在恢复其功能的数据库上执行此操作.
在sql兼容的数据库中, 数据一致性指的是数据不违反任何活动数据库约束的状态. 这是在任何交易结束时必须满足的基本要求.
甲骨文私有同义词是在特定的模式中创建的,可以像其他模式对象一样通过模式引用访问. 另一方面, 公共同义词是在public组中创建的,可以在没有任何模式引用的情况下访问.
在甲骨文中,要更改同义词引用的对象,需要删除并重新创建同义词.
甲骨文实例是甲骨文数据库作为存储和操作数据的应用程序的后台进程和已分配内存的全部集合.
Leonid有20多年的多平台开发和DBA经验, 在甲骨文和SQL Server跨平台迁移方面具有特殊的专业知识.
世界级的文章,每周发一次.
世界级的文章,每周发一次.