为什么可重复读取会出现写入倾斜?

2024-03-05

Wiki https://en.wikipedia.org/wiki/Isolation_(database_systems) says;

可重复读取:
在此隔离级别中,基于锁 并发控制 DBMS 实现保持读写锁 (在选定的数据上获取)直到交易结束。然而, 范围锁不受管理,因此可能会发生幻读。

在此隔离级别下可能会出现写偏斜,这种现象是两个 允许两个不同的人对表中的相同列进行写入 作家(之前阅读过他们正在更新的专栏), 导致该列包含两者混合的数据 交易。

我很好奇为什么write skew可能发生在Repeatable reads? 它表示它将保持读锁和写锁直到事务结束并且write skew发生在previously read the columns they are updating,那么在读锁被锁定的情况下如何才能锁定写锁呢?


可重复读隔离级别保证每个事务都会从一致的快照 https://en.wikipedia.org/wiki/Snapshot_isolation数据库的。换句话说,在同一事务中两次检索同一行始终具有相同的值。

许多数据库如Postgres、SQLServer在可重复读隔离级别下都可以检测到丢失更新 https://stackoverflow.com/questions/855105/lost-update-in-concurrency-control(写入倾斜的特殊情况)但其他人则不然。 (即:MySQL 中的 InnoDB 引擎)

我们回来写倾斜现象问题。大多数数据库引擎在可重复读隔离中无法检测到某些情况。一种情况是当2个并发交易修改2个不同的物体并制定竞争条件。

我举一个书上的例子设计数据密集型应用程序 https://rads.stackoverflow.com/amzn/click/com/1449373321。这是场景:

您正在为医生编写一个应用程序来管理他们的值班人员 在医院轮班。医院通常会尝试安排几 随时待命的医生,但绝对必须至少有 一名待命医生。医生可以放弃轮班(例如,如果他们 自己生病了),前提是至少有一名同事仍在工作 调用该轮班

下一个有趣的问题是我们如何在数据库下实现这一点。这是伪代码 SQL 代码:

BEGIN TRANSACTION;
    SELECT * FROM doctors
        WHERE on_call = true
        AND shift_id = 1234;
    if (current_on_call >= 2) {
        UPDATE doctors
        SET on_call = false WHERE name = 'Alice' AND shift_id = 1234;
    }
COMMIT;  

Here is the illustration: Flow Data

如上图所示,我们看到 Bob 和 Alice 同时运行上面的 SQL 代码。然而Bob和Alice修改了不同的数据,Bob修改了Bob的记录,Alice修改了Alice的记录。可重复读隔离级别的数据库无法知道并检查条件(总医生 >= 2)是否已被违反。出现了写入倾斜现象。

为了解决这个问题,提出了2种方法:

  1. 锁定所有手动调用的记录。所以鲍勃或爱丽丝将等待直到其他人完成交易。

这是一些伪代码使用SELECT .. FOR UPDATE query.

BEGIN TRANSACTION;
    SELECT * FROM doctors
        WHERE on_call = true
        AND shift_id = 1234 FOR UPDATE; // important here: locks all records that satisfied requirements.

    if (current_on_call >= 2) {
        UPDATE doctors
        SET on_call = false WHERE name = 'Alice' AND shift_id = 1234;
    }
  COMMIT;  
  1. 使用更严格的隔离级别。两个都MySQL https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html#isolevel_serializable, Postgres https://www.postgresql.org/docs/9.1/static/transaction-iso.html T-SQL https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017提供序列化隔离级别。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么可重复读取会出现写入倾斜? 的相关文章

  • Phonegap:WebSql 还是 SqLite?

    我使用phonegap的时间很短 并且我对其中的存储概念遇到了一些麻烦 因此 文档指出您可以打开这个数据库 它是一个 SQLite 实现 window openDatabase 返回一个新的数据库对象 此方法将创建一个新的 SQL Lite
  • 构建可扩展 Web 应用程序的书籍? (数据库性能/调优、网络、一般性能等)[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 从计算机科学专业毕业并作为一名从事 Web 应用程序的软件工程师进入 现实世界 后 我对如何正确扩展 W
  • 如何使用文本框在数据网格视图中搜索数据?

    这是我当前的代码 private void searchTextBox TextChanged object sender EventArgs e dataGridView1 DataSource as DataTable DefaultV
  • C# - 如何检测 SQLite DB 是否被锁定?

    我正在开发一个使用 SQLite 的多线程 C 程序 我遇到一个问题 有时运行 SQLiteCommand ExecuteNonQuery 来更新某些行会抱怨 SQLite 错误 5 数据库已锁定 我知道发生这种情况是因为数据库在插入或更新
  • Chrome 扩展 - 使用 javascript 定期运行并永久记录数据

    目前 我有一个脚本 当单击右上角托盘中的图像 仅适用于一个特定允许的网站 时 它会扫描 HTML 页面 然后输出一些值 此扫描和输出是单个 JS 文件中的函数 称为 checkData js 即使用户没有主动使用选项卡但它已打开 是否有可能
  • 如何检查 postgres 的 psql 是否自动提交

    我使用的是 postgres 9 5 如何检查自动提交是否打开或关闭 我试过SHOW AUTOCOMMIT我在哪里得到的ERROR unrecognized configuration parameter autocommit 然后我做了一
  • Codeigniter:无法使用提供的设置连接到数据库服务器

    我使用 codeigniter 作为 cms 框架 如果数据库主机名是 localhost 它可以正常工作 db default hostname localhost db default username root db default
  • MySql:将多项选择数据存储在数据库中

    我的表单中有一个复选框列表 用户可以选择其中任何一个 也可以选择全部 认为用户选择他感兴趣的运动类型 我需要最好的数据库结构来存储这个用户选择 这样 将来我就可以获得所有这些数据 我想 我无法将每个 用户 ID 运动 选择作为新行存储在数据
  • 根据代码版本测试和管理数据库版本

    当您开发应用程序时 数据库的更改不可避免地会出现 我发现的技巧是让数据库构建与代码保持同步 过去 我添加了一个针对目标数据库执行 SQL 脚本的构建步骤 但这很危险 因为您可能会无意中添加虚假数据或更糟的情况 我的问题是保持数据库与代码同步
  • 如何确定一个日期范围是否出现在另一个日期范围内的任何时间?

    我有一个事件表 指定日期范围start date and end date字段 我有另一个在代码中指定的日期范围 它将当前周定义为 week start 和 week end 我想查询本周的所有活动 这些案例似乎是 活动在一周内开始和结束
  • 私人消息数据库设计

    我正在创建一个简单的私人消息系统 但我不确定哪种数据库设计更好 第一个设计是一个消息表 以及一个消息评论表 Message id recipientId senderId title body created at MessageComme
  • Sqlite 删除速度极其慢 - 如何加快速度?

    我读到删除操作很慢 我想知道如何改进此检查 我有一个每天填充 10 15k 行的表 每次启动时我都需要清理所有超过 6 个月的记录 但是当数据库增长时 我开始遇到速度问题 当我运行此命令时 有接近 100 万条记录 即使我没有任何内容要删除
  • 非关系型数据库系统

    还有哪些其他类型的数据库系统 我最近遇到了以非关系方式处理数据的 couchDB 这让我思考其他人正在使用哪些其他模型 所以 我想知道还有哪些其他类型的数据模型 我不是在寻找任何细节 只是想看看其他人是如何处理数据存储的 我的兴趣纯粹是学术
  • 在源代码管理中管理我的数据库

    由于我正在处理一个新的数据库项目 在 VS2008 中 而且我从未从头开始开发数据库 因此我立即开始研究如何在源代码管理 在本例中为 Subversion 中管理数据库 我找到了一些关于SO的信息 包括这篇文章 保持多个环境中的开发数据库同
  • WPF 应用程序的最佳本地数据库解决方案是什么?

    目前适用于 WPF 应用程序的最佳解决方案是什么一台电脑 where 各种用户登录它们并使用它们在本地获取 保存信息 以下是我看到选项的方式 MDF似乎是最好的选择 因为我假设您可以很好地锁定它 这样即使用户可以访问 mdf 文件 他们仍然
  • Alembic 无法识别 False 默认值

    在维护 SQLAlchemy 数据模型并利用 alembic 进行版本控制时 我所做的以下代码更改导致了空修订 some column Column Boolean nullable False default False 以前是 some
  • 如何使用Python高效地将CSV文件数据插入MYSQL?

    我有一个带有 aprox 的 CSV 输入文件 400 万条记录 插入已运行超过 2 小时 但仍未完成 数据库仍然是空的 关于如何实际插入值的任何建议 使用insert into 并且更快 比如将插入物分成块 我对 python 还很陌生
  • 哪种 SQL 模式能够更快地避免插入重复行?

    我知道有两种不重复插入的方法 第一个是使用WHERE NOT EXISTS clause INSERT INTO table name col1 col2 col3 SELECT s s s WHERE NOT EXISTS SELECT
  • 如何使用 django 更新会计应用程序中的余额?

    我正在学习 Django 尝试制作一个会计应用程序来跟踪我的开支等 我使用两种模型创建数据库 一种用于帐户 一种用于操作 但我不知道如何在每次操作时更新我的 余额 我在想 也许每次我保存一个新操作时 我都会通过覆盖操作模型的保存方法来更新余
  • 单向关系和双向关系的区别

    我想知道这两个词是什么意思 我遇到他们是在教义的文档 http www doctrine project org documentation manual 2 0 en association mapping 但我不明白他们的意思 这与常见

随机推荐