数据库的锁
目的:
为了控制并发访问数据库时数据的一致性和完整性
考虑的点:
并发情况下数据的一致性和完整性、性能、防止死锁、锁的颗粒度、事务的隔离级别
类型:
行锁(共享锁、排他锁) 表锁 页锁(不管,一页有多行数据)
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 互相等待对方释放资源,从而造成死锁。
解决:
死锁超时检测,数据回滚
代码逻辑优化:
加锁顺序的优化
废话短说