Solo  当前访客:1 开始使用


数据库的锁

目的:

为了控制并发访问数据库时数据的一致性和完整性

考虑的点:

并发情况下数据的一致性和完整性、性能、防止死锁、锁的颗粒度、事务的隔离级别

类型:

行锁(共享锁、排他锁) 表锁 页锁(不管,一页有多行数据)

MyISAM 引擎:默认表锁,对表中数据进行写操作的时候,只能运行其他事务进行表的读取操作;

InnoDB引擎: 默认的是排他锁(exclusive),对表中某行数据进行写操作(update delete操作时,自动加锁)时,其他事务对该记录不可读不可写,直到当前事务释放锁。

共享锁(shared lock):给数据显式的添加共享锁 FOR SHARE,其他事务可读,但不可写

LOCK TABLE your_table IN SHARE MODE; -- 共享锁
LOCK TABLE your_table IN EXCLUSIVE MODE; -- 排他锁

SELECT * FROM your_table WHERE some_condition FOR SHARE;
SELECT * FROM your_table WHERE some_condition FOR UPDATE; //排他锁,对查询的结果集加锁。

锁升级:

是什么?

innoDB 也可以自动升级锁级别(行级锁升级为页级锁、表级锁,取决于事务隔离级别),影响并发性能,行级锁升级是为了维护事务的隔离性和一致性

发生场景:

范围锁定:当事务使用范围条件(例如范围查询、范围锁定)时,可能需要锁定范围内的多行数据,这可能导致 MySQL 将行级锁升级为更高级别的锁,如页级锁或表级锁。

并发事务处理:在高并发环境下,不同事务竞争同一批数据时,为了保证事务的隔离性,MySQL 可能会采取升级锁级别的策略,确保数据操作的正确性

加锁读操作:当一个事务对某些行进行了加锁读操作(例如 SELECT ... FOR UPDATE 或 SELECT ... LOCK IN SHARE MODE),而其他事务同时也在访问这些被锁定的行数据时,MySQL 可能会采取升级锁级别的方式来保证一致性和隔离性。

where 条件如果不存在索引字段,那么这个事务会导致表锁

当更新数据库数据时,如果没有触发索引,则会锁表

怎么做?

避免锁升级(减少数据锁定的时间):减少事务的执行时间、和数据锁定时间、按需获取数据、合理使用索引、使用乐观锁、

死锁:

Transaction A 持有资源 X,并等待获取资源 Y,而 Transaction B 持有资源 Y 并等待获取资源 X。这样就形成了一个环路等待的情况,导致 A 和 B 互相等待对方释放资源,从而造成死锁。

解决:

死锁超时检测,数据回滚

代码逻辑优化:

加锁顺序的优化

标签:
新一篇: Mybatis的占位符的数据类型 旧一篇: sql 执行计划