mysql 悲观锁和乐观锁(—悲观锁)

适合悲观锁的使用场景:

悲观锁更适合在,写操作较多、并发冲突高、业务需要强一致性等场景下使用悲观锁。

如何使用悲观锁:

悲观锁主要通过以下两个 SQL语句实现:

1、SELECT...FOR UPDATE;

这个语句会在所查询中的数据行上设置排他锁(Exclusive Lock)。在数据被锁定期间,其他事务无法修改这些被选中的行数据,也无法对他们设置新的排它锁和共享锁。

eg: 当sql语句运行至2的时候,事务已被成功开启且对指定行数据加上了排他锁,这时候,在别的进程/窗口中再对id=1的数据进行update修改命令的话,会执行失败,因为数据已经被锁定了。这时候只有当前进程/窗口可以对该数据进行编辑操作,编辑完成后。执行至语句4,提交并关闭了事务后,其他窗口对id=1的update的编辑操作才能有效果。

START TRANSACTION;  // 1、开启事务

SELECT * FROM students WHERE id=1 FOR UPDATE;//2、查询指定行数据并加排它锁

UPDATE students set name='小明' where id=1; // 3、修改数据

COMMIT;    // 4、提交并关闭事务

2、SELECT...LOCK IN SHARE MODE;

这个 语句会在所查询的数据行上设置共享锁(Shared Lock)。在被锁定期间,其他事务可以读取这些行,但不能修改这些行, 也不能在这些数据行上这设置排他锁。

eg: 当sql语句运行至2的时候,事务已被成功开启且对指定行数据加上了共享锁,这时候,在别的进程/窗口中再对id=1的数据进行查询操作是能查询到对应的数据的,但若进行update修改命令的话,则会执行失败,因为数据已经被锁定了。这时候只有当前进程/窗口可以对该数据进行编辑操作,编辑完成后。执行至语句4,提交并关闭了事务后,其他窗口对id=1的update的编辑操作才能有效果。

START TRANSACTION;

SELECT * FROM students WHERE id=1 LOCK IN SHARE MODE;

UPDATE students set name='小明' where id=1;

COMMIT;


注意事项:

悲观锁的缺点:

        1、增加性能开销:对数据的读写进行加锁和解锁操作,会增加系统的开销,特别是高并发的环境下,锁的竞争会严重影响到系统性能。所以悲观锁机制对资源的锁定操作会影响系统性能。

        2、降低并发度:悲观锁在操作数据前会加锁,这导致了同一时间,只有一个事务能操作数据,其他事务只能等待,这严重降低了系统的并发性。

        3、死锁:当遇上多个事务相互等待对方释放锁时,就可能发生死锁。虽然数据库系统通常能够检测并解决死锁,但这回导致事务回滚,增加系统的开销。

        4、锁超时:如果一个事务长时间加锁而不释放,可能导致其他等待锁的事务超时,这不仅会增大等待事务的失败概率,还可能影响到整个系统的稳定性。

MySQL 中的悲观锁乐观锁是两种处理并发访问数据一致性的机制,它们在实现方式、适用场景以及性能特点上有显著区别。 ### 悲观锁 悲观锁假设并发冲突经常发生,因此在整个数据处理过程中对数据保持锁定状态,以确保数据的完整性。悲观锁的实现通常依赖于数据库提供的锁机制,例如行锁、读锁写锁等。这种锁机制在操作开始前就对数据加锁,直到操作完成才会释放锁。悲观锁适用于写入频繁且冲突概率较高的场景,例如金融交易系统,对数据一致性要求极高,无法容忍中间状态的错误。 在实际应用中,悲观锁通过 `SELECT ... FOR UPDATE` 或 `SELECT ... LOCK IN SHARE MODE` 等语句实现,确保数据在事务处理期间不被其他事务修改 [^3]。 ### 乐观锁 乐观锁则假设并发冲突较少,因此在数据操作时不立即加锁,而是在提交更新时检查是否有冲突发生。乐观锁的实现通常依赖于版本号(Version)、时间戳(Timestamp)或比较交换(CAS)机制。如果在提交时检测到冲突,则拒绝操作并提示重试。这种锁机制适用于读取频繁且冲突概率较低的场景,例如统计数据的更新或低并发环境下的数据读取。 乐观锁的一个常见实现方式是通过版本号字段。在更新数据前,会检查当前版本号是否与数据库中的版本号一致,若一致则允许更新并增加版本号;否则,更新失败并提示冲突 [^2]。 ### 适用场景 - **悲观锁适用场景**: - **高冲突场景**:当系统中存在大量并发写入操作,冲突概率较高时,悲观锁可以有效避免数据不一致的问题。 - **数据敏感性高**:如金融系统中的交易处理,对数据一致性要求极高,不能容忍任何中间状态的错误。 - **实时性要求高**:需要立即获取数据并进行修改的场景,悲观锁可以确保数据在操作期间不会被其他事务修改 [^4]。 - **乐观锁适用场景**: - **低冲突场景**:当系统中读取操作远多于写入操作,且并发冲突概率较低时,乐观锁可以减少锁的开销,提高系统吞吐量。 - **允许重试**:在某些场景下,系统可以容忍操作失败并进行重试,此时乐观锁更为合适。 - **数据一致性要求适中**:对于某些非关键数据,如统计数据或日志信息,允许一定程度上的不一致,乐观锁可以提供更好的性能 [^2]。 ### 总结 悲观锁乐观锁各有优劣,选择合适的锁机制应根据具体的业务需求系统特点来决定。悲观锁适合高冲突、高敏感度的场景,而乐观锁则适合低冲突、高读取频率的场景。理解这两种锁机制的核心思想适用场景,有助于在实际开发中做出更合理的选择 [^4]。 ```sql -- 悲观锁示例:使用 SELECT ... FOR UPDATE 获取行锁 START TRANSACTION; SELECT * FROM accounts WHERE account_id = 1 FOR UPDATE; -- 执行更新操作 UPDATE accounts SET balance = balance - 100 WHERE account_id = 1; COMMIT; -- 乐观锁示例:使用版本号控制并发更新 UPDATE accounts SET balance = balance - 100, version = version + 1 WHERE account_id = 1 AND version = 5; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值