视觉做的比较好的国外网站网站设计有限公司

当前位置: 首页 > news >正文

视觉做的比较好的国外网站,网站设计有限公司,一个网站百度百科怎么做,seo外链优化培训背景描述 现在有两个事务#xff0c;事务A和事务B#xff0c;他们都需要修改同一行数据#xff0c;这行数据原始值为100#xff0c;事务A的操作是数据增加100#xff0c;事务B的操作也是增加100#xff0c;预期的最终结果是300#xff0c;现在如何保证最终的数据是300的…背景描述 现在有两个事务事务A和事务B他们都需要修改同一行数据这行数据原始值为100事务A的操作是数据增加100事务B的操作也是增加100预期的最终结果是300现在如何保证最终的数据是300的什么时候会出现200的情况 执行结果 最终数据是300的情况可重复读 : 在可重复读REPEATABLE READ隔离级别下这种情况较为容易实现。此隔离级别是MySQL默认级别它可以有效避免脏读、不可重复读和幻读问题。 执行流程: 事务A开始执行查询操作SELECT获取值100。事务A给这行数据加上读锁共享锁或排他锁根据是否使用SELECT … FOR UPDATE或SELECT … LOCK IN SHARE MODE。事务A在查询结果的基础上增加100更新这行数据然后提交事务释放任何持有的锁。接着事务B开始执行查询操作获取到更新后的值200因为事务A已经提交。事务B给这行数据加上读锁或排他锁。事务B在查询结果的基础上增加100更新这行数据然后提交事务释放任何持有的锁。 使用的锁: 根据是否声明FOR UPDATE或LOCK IN SHARE MODE可能会使用记录锁行锁或next-key锁next-key锁是行锁和gap锁的组合防止幻读。如果没有使用上述子句那么InnoDB存储引擎默认会在更新操作时自动给涉及的行加上排他锁X锁 。
最终数据是300的情况读未提交 : 在读未提交READ UNCOMMITTED隔离级别下事务可以读取到其他事务未提交的更改也就是这个隔离级别允许发生“脏读”Dirty Reads 执行流程 事务A在读未提交的隔离级别下启动。事务A执行 SELECT 查询操作读取数据值为100。然后事务A增加这个值100执行 UPDATE 操作更新该数据行为200。此时事务A还没有提交所以更改是未提交的。在读未提交隔离级别下事务B也启动。事务B执行 SELECT 操作在这个隔离级别下它可以读取到事务A未提交的更改也就是它可能会读取到数据值为200。事务A提交事务后事务A对数据行的更改变成持久的这时候数据是200。基于事务B读到的200的数据值事务B决定将这个数据增加100更新操作将这个值更改为300。然后事务B提交这时数据行的更新已经持久化为300。
出现200的情况低级别的隔离级别 : 在较低级别的隔离级别如读未提交READ UNCOMMITTED或读提交READ COMMITTED可能会出现最终结果是200的情况。 执行流程: 事务A开始执行查询操作获取值100。事务B几乎同时间开始并执行查询操作也读取到值100尤其在READ UNCOMMITTED级别或事务B在READ COMMITTED级别下且在事务A提交之前读取数据。事务A增加100更新数据库行为200然后提交。事务B没有得到事务A的更新因为它已经读取了数据它也增加100在其本地的值基础上100并更新数据库行为200然后提交。 使用的锁: 在READ UNCOMMITTED级别下不使用行级锁定事务可以读取未提交的数据。在READ COMMITTED级别下每次查询都会读取最新的已提交数据但如果事务B在事务A提交之前读取数据它不会再次查询数据库。在REPEATABLE READ级别下第一次读取后事务内的读操作会在提交前看到同样的数据即事务B第一次查询后再次查询依然会是100直到事务提交才会读到新的值。
出现200的情况并发导致更新丢失 : 执行流程 事务A在可重复读的隔离级别下启动。事务B也在可重复读的隔离级别下启动。事务A执行SELECT查询并且读取到这行数据的初始值100。事务A在查询结果的基础上增加100并执行UPDATE操作将该行的值变为200。在UPDATE操作过程中事务A为这行数据加上排他锁。事务A提交事务行数据变为200并释放排他锁。因为事务B也在可重复读隔离级别下所以即便事务A已经提交更新事务B的SELECT操作依然会看到事务B自己快照里的数据即历史值100。这意味着事务B在这个阶段读取到的是100而非事务A更新后的200。此时事务B尝试基于它自己读取到的那个100的值增加100并且执行UPDATE。由于事务A已经提交并释放了排他锁事务B现在确实能对这行数据进行更新操作但是基于自己快照里的原始值100它更新行数为200而非基于事务A的更新结果。事务B提交事务数据的最新状态是200。
更新丢失问题 当两个或多个事务读取同一数据并基于此数据进行更新时其中一个事务的更新可能会由于另一个事务的更新而被覆盖导致第一个事务的更改丢失。什么场景下会出现这种问题呢 假设一个场景在事务中涉及到先查询后更新的操作那么使用排他锁时是在事务开始时加锁还是说在更新数据时加锁 这有两种常见的策略各有不同的问题 1、 查询时不加锁更新时加锁 在这种策略中事务在查询数据时不会对数据行加锁。只有当事务执行更新操作时才会对相关数据行加上排他锁。这样做的好处是可以减少锁的持有时间从而提高并发性能。但是这种策略可能会导致“丢失更新”Lost Update问题即两个事务可能同时读取相同的数据然后几乎同时更新导致一个事务的更新覆盖另一个事务的更新。 2、查询时就加锁保持到事务结束 在这种策略中事务在查询数据时就会对数据行加上排他锁并且保持锁直到事务结束提交或回滚。这样可以确保在事务执行期间其他事务无法修改被锁定的数据行从而避免了“丢失更新”问题。然而这种策略会增加锁的持有时间可能会降低系统的并发性能。 在MySQL的InnoDB存储引擎中默认的隔离级别是可重复读REPEATABLE READ。在这个隔离级别下InnoDB会使用以下策略查询时不加锁更新时加锁 当执行普通的SELECT查询时InnoDB不会加排他锁。当进行写操作如UPDATE、DELETE、INSERT时会对涉及的数据行加上排他锁。 这里是两种不同SELECT语句的例子 普通查询不加锁 : SELECT * FROM your_table WHERE id 1;查询并锁定加排他锁 :
如果你希望在读取数据时立即加锁以确保数据不会被其他事务修改你可以使用SELECT … FOR UPDATE语句。这会对选中的行加上排他锁直到当前事务结束。 SELECT * FROM your_table WHERE id 1 FOR UPDATE;那么MySQL是不是存在“更新丢失”问题呢它是怎么解决的呢 如何解决“更新丢失”问题呢 我们先来看看解决“更新丢失”有哪些办法 使用合适的隔离级别可重复读或串行化SERIALIZABLE隔离级别可以防止这种问题。悲观锁定通过在读取数据时立即加上SELECT … FOR UPDATE以获取对相关数据行的排他锁防止其他事务并发修改。乐观锁定通过版本号或时间戳来检查在读取数据后和更新数据前是否有其他事务对数据作了修改如果检测到了变化可以拒绝更新或重新读取最新数据再尝试更新。乐观锁定一般需要在数据表中使用一个额外的字段来控制版本version或者保存时间戳timestamp。 下面是如何在MySQL中使用乐观锁定的方法和步骤 修改表结构: 在你的数据表中增加一个版本号字段或时间戳字段。例如 ALTER TABLE your_table ADD COLUMN version INT DEFAULT 0;读取数据: 在进行数据操作时你需要读取数据和它当前的版本号。例如 SELECT value, version FROM your_table WHERE id 1;更新数据: 更新数据时除了更改数据之外还需要增加版本号并检查更新时的版本号是否跟读取时的一致。如果不一致说明数据在读取之后有过其他更新当前更新应该被拒绝。 UPDATE your_table SET value value 100, version version 1 WHERE id 1 AND version read_version;操作结果处理: 执行更新后需要检查操作是否成功。你可以根据更新影响行数来判断如果影响行数为0则说明在读取数据和尝试更新之间数据已经被其他地方更新过此时可以选择重新读取再尝试更新或返回错误提示。 int affectedRows preparedStatement.executeUpdate(); if (affectedRows 0) {// Handle the optimistic lock failure (e.g., throw an exception or retry) }在Java代码中可以通过检查数据库操作返回的受影响行数来实现乐观锁定逻辑。如果受影响行数为0则说明更新并没有成功很可能是因为版本号不一致导致的更新冲突。应用程序可以根据业务场景选择是重新尝试、放弃操作还是抛出异常来通知用户。 乐观锁定在并发不是特别高冲突概率较低的系统中是非常有用的并且相对于悲观锁它提供了更好的性能和用户体验。但在高冲突环境下乐观锁可能会导致大量的冲突和重试从而可能影响系统的整体性能。 MySQL怎么解决“更新丢失”问题 在MySQL默认的事务隔离级别REPEATABLE READ下解决并发事务中的“更新丢失”的关键流程主要包括 Next-Key锁: 当事务对数据进行修改时InnoDB会使用Next-Key锁锁定这些数据并且锁定它们的索引记录以及索引记录之间的间隙防止并发事务插入新的记录。检查当前版本: 在更新数据前事务会检查此行数据的当前版本确保没有其他事务已经修改过这个数据。如果数据已经被修改事务会等待或得到更新冲突的通知。行锁定: 当执行UPDATE或DELETE操作时, InnoDB会对涉及的每行数据加上排它锁X锁这使得其他事务不能同时对这些行进行写操作。使用Undo日志保持一致性读: 即便有事务正在对数据行进行修改其他事务因为Undo日志的存在仍然可以读取到修改前的数据快照保证了在更新过程中可以进行一致性非锁定读取。版本控制: InnoDB通过为每个事务维护一个版本链来实现MVCC。事务在开始时记录下系统版本号只查询版本早于当前事务版本的数据记录避免了读取到其他事务修改后的数据从而防止了更新丢失。COMMIT前确认: 在事务提交前系统会检查所有修改是否与其他事务有冲突。如果发现冲突当前事务需要重新执行或等待其他事务完成。REDO日志: 为了保证即便数据库发生故障已经提交的修改也不会丢失所有的更改操作都会记录在REDO日志中。隔离和序列化操作: 当需要修改数据时InnoDB通过锁定机制对相关的数据行进行隔离确保操作的序列化防止更新丢失。 排他锁 排他锁Exclusive Lock通常简称为X锁是数据库中用于控制并发访问的一种锁机制。当一个事务对数据行加上排他锁时它可以确保在这个事务完成并释放锁之前其他事务不能对该数据行进行任何读取或修改操作。 排他锁的主要特点如下 写操作保护排他锁主要用于写操作确保在事务执行更新、删除等操作时数据不会被其他并发事务干扰。互斥性当一个事务持有排他锁时其他事务必须等待直到锁被释放。这种互斥性保证了数据的一致性和完整性。防止死锁通过合理的锁策略排他锁可以帮助防止死锁的发生。例如事务可以按照一致的顺序获取锁避免循环等待。锁的释放一旦事务完成了对数据的修改并提交排他锁就会被释放其他事务可以开始对数据行进行操作。 在MySQL中当执行INSERT、UPDATE或DELETE操作时InnoDB存储引擎会自动为涉及的数据行加上排他锁。这些锁在事务提交或回滚后自动释放。排他锁是实现事务隔离的关键机制之一它有助于维护事务的原子性和一致性。 需要注意的是排他锁可能会导致性能问题特别是在高并发的场景下。如果事务长时间持有锁可能会导致其他事务等待从而降低系统的并发性能。因此在设计数据库操作时应该尽量减少锁的持有时间合理地使用锁以及考虑使用其他并发控制机制如乐观锁等来平衡性能和数据一致性的需求。