Martin
by Martin Kysel

ddl + acid - 你听说过'交易',让我们谈谈'孤立'

在SQL中,您可以执行大量的DDL操作,例如创建或重命名表,创建或删除列,以及更多,这些DDL语句最常在创建或升级应用程序模式时使用。但是,还有更多的交易DDL,而不是原子地完成大型模式更新。交易DDL还提供防止失败的保护。这意味着网络可能会失败,机器可能会失败,并且仍然,NOODB将保证所有架构修改都可以应用所有应用程序或都不应用。本质上讲,这意味着Nuodb中的所有操作都渴望抵抗失效。了解我们在构建数据库时如何接近。 

在本文中,我们只关注酸的一部分交易,即隔离。我将解释它如何影响您的申请代码以及如何避免一些警告。

交易DDL是什么意思?

什么是DDL?

DDL代表 数据定义语言 and is a group of SQL statements that modifies the metadata of the database. CREATE TABLE T1(I INT); is a DDL statement and so is ALTER TABLE T1 ADD COLUMN J INT;.

什么是“交易”?

我们习惯于在DML的背景下讨论交易(数据操纵语言),但在我们谈论DDL交易时,相同的原则适用。交易必须是酸 - Atomic, Consistent, Isolated,and. D才会。在这种情况下,这意味着事务执行多个语句,其中一些语句是DDL,同时将它们视为可以回滚或提交的单个操作。 

什么是'孤立'?

本文专注于交易性的一个方面: Isolatation。如果其效果不会泄漏到其他事务,则从系统的其余部分隔离交易。您可以选择适合您需求的各种隔离级别。 NOODB支持一致的读取和读取。在本文中,我们将探讨DML与DDL和隔离级别的各种交互。

DDL必须是交​​易的吗?

没有为什么DDL陈述的根本原因 不应该 是交易的,但历史上,数据库 没有 提供了此功能。即使在今天,只有少数数据库提供真正的交易DDL,并且在大多数情况下它具有局限性。

很难说为什么90年代的供应商决定从酸度保证中排除DDL。这 ISO 9075标准 在交涉交谈时,从未在DML和DDL之间进行任何区分。 

缺乏交易性意味着许多应用程序开发人员习惯于在数据库维护窗口期间执行应用程序升级。这些窗口不再容忍 今天总是的世界.

事务性DDL意味着DDL需要孤立地发生同时发生的其他事务。这意味着修改表的元数据需要版本化。 MVCC. 是交易DDL的天然前体。在实现快照隔离的数据库中,读者不会阻止作家,编写器不会阻止读者。使用MVCC语义进行DDL意味着DDL可以在封面下发生,而读者使用元数据的旧快照继续。另一方面,作家不允许在DDL发生时继续进行。

如果维护窗口不可行,因此DDL必须与DML共存,则正确隔离变为键。如果没有它,DML可以以出乎意料的半升级状态观察数据库,因此从未测试过。这导致意外/不期望的行为可能导致应用中断和停机时间。

在不支持事务DDL的数据库中的一个流行替代方案是在DDL语句之前和之后的每一个事务提交。这可确保DDL具有最新的快照,并且由于表锁,它会删除对元数据版本控制的需求。当DDL以一致的读取隔离级别执行DDL时,它还屏蔽应用程序开发人员,我们将很快探索。

AutoCommitting DDL绝对是可行的,NuodB为那些从使用此迁移的数据库迁移的人提供兼容模式。要启用DDL的自动提交,请执行以下语句:

set system property AUTOCOMMIT_DDL=true;

如何正确地从DDL孤立的DML

在本节中,我使用这些条款 更新DML. (插入,更新,删除,选择更新)和 作家 互换。它们都指的是所有DML的子集。读取DML(SELECT)不会受到并发DDL的影响。

如果允许在DDL语句修改表时允许编写DML,则数据库必须放弃隔离保证。

We are assuming that a table T1 (create table T1(i int);) has been created prior to both conflicting transactions.

您可能会注意到我们从未指定第一次交易的隔离级别是什么。隔离级别仅影响“秒”的事务,因为它们允许应用程序开发人员违反序列化,并根据同时启动的事务结果行使,并在过去已提交。 Nuodb不支持任何低于读取的隔离级别,因此不可能观察未提交的状态。

Let me explain using a concrete conflict between update DML insert into T1(i) values(5) and DDL alter table T1 add column j int not null. Thanks to table locks, these two operations can never happen concurrently and order is enforced. Additionally, NuoDB supports two Isolation levels: Read Committed and Consistent Read, which further complicates the interaction.

DDL是第一个;插入已读取已提交

If the insert is in Read Committed, it has to operate on a consistent snapshot of the database that is recalculated for every statement. This means that once the table lock is released by the DDL, the insert is allowed to reload the metadata and proceed. In this case, the snapshot of the insert will contain the new column and hence the insert will fail with Error 58000: illegal null in field J in table T1. This result might be surprising to application developers who did not anticipate a concurrent metadata modification.

DDL是第一个;插入是一致的读取

If the insert is in Consistent Read, it has to operate on a consistent snapshot of the database. NuoDB includes the metadata at the start of the transaction in the snapshot. This means that reads always return the same columns, even if concurrent metadata modifications are happening. For writes, enforcing a consistent snapshot leads to potential Consistency violations. If the insert happens after the DDL, it might insert NULL into a column that has been defined as NOT NULL. Clearly, this is a violation of the table constraints, hence the write needs to be aborted with Error 58000: Table USER.T1 has been changed.

插入是第一个;读取的读取已提交

插入完成后,表包含列中的值5 i。没有列 J。如果尝试添加列 J,所有行都将隐式扩展到值 无效的。由于J被定义为 没有空 in our scenario, the DDL will fail with Error 42000: field J doesn't allow NULL values, but a default value for the existing rows hasn't been specified. The application developer now has to rewrite the insert DML to include data for column J.

插入是第一个; DDL是一致的阅读

这种情况可能是最令人困惑的情景。类似于DML的DDL包含数据库的快照。快照包含在事务开始时可见的所有记录。新插入的行对一致的读取DDL事务不可见,因为它发生在事务启动后发生。如果允许DDL在行上运行,则将违反隔离级别。另一方面,如果允许DDL继续,它必须忽略该行并且不会用空展开它。这将是违反NOUL NULL限制和违反的行为 C持有情况。为防止这种情况发生,DDL事务需要失败。如果您有一个如下所示,则这可能会令人困惑:

SQL > start transaction isolation level consistent read;
SQL > select * From T1;
SQL > alter table T1 add column j int not null;
Error 42000: field J doesn't allow NULL values, but a default value for the existing rows hasn't been specified
SQL > select * from T1;
SQL > rollback;

如您所见,读取DML的快照不包含新插入的记录,但防止DDL。我相信这就是为什么一些传统数据库决定只允许在阅读承诺的事务中允许交易DDL。

为什么交易DDL相关?

到目前为止,我们从数据库供应商的角度讨论了交易DDL。但是,使用情况来自数据库管理员的角度。当我们将酸度应用于DDL交易时,我们意识到这一点 A统治非常有用。定义表明: 

“每个交易被视为单个”单位“,它完全成功或完全失败。”

事务性DDL为数据库管理员提供了在单个操作中执行多个修改(例如,多个alter表语句)的功能。

对于开发人员来说,交易DDL的强烈隔离保证使得应用更容易开发应用。应用程序只能在状态a(升级之前)或状态b(升级后)中观察数据库,并且永远不会看到部分结果。这减少了所需的测试矩阵,并增加了滚动升级程序的置信度。

保持调整为未来的文章,探索滚动大型模式修改的能力。

概括

在数据库中实施交易DDL需要非琐碎的工作量,而不是所有数据库供应商都决定投入努力。 Nuodb支持交易DDL,我们认为它是我们的基础 永远关注的承诺。我们将探讨竞争景观,并在下一篇文章中概述了2019年的交易DDL支持。

鉴于不断变化的业务需求,应用程序在定期更改。在编写始终开启应用程序时,您应该期望不同的演员并发/在线元数据修改。在阅读本文中阅读我们的示例后,我们建议您查看您的应用程序代码并询问自己的问题:“如果元数据同时更改,此查询会如何进行?” 

想试试我们的诺贝布吗? 今天下载我们的社区版。 

额外阅读