🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
>### 悲观锁 - `悲观锁(Pessimistic Lock)`,顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等,都是在做操作之前先上锁。 - 假设最坏的情况, 每次读取数据的时候都认为别人会修改,所以每次读取数据都上锁 - 读写(共享锁) : select * from key_table lock in share mode - 写锁(排它锁) : select * from key_table for update ### 锁的详细分类和操作 | 锁类型 | 事务操作行为 | 其他事务行为(读取、写入) | | --- | --- | --- | | **读锁** | 可以读取数据 | 可以读取数据,但不能写入数据 | | **写锁** | 可以读取和修改数据 | 不能读取数据,也不能写入数据 | ### 读锁与写锁的详细比较 | 特性 | 读锁(Shared Lock) | 写锁(Exclusive Lock) | | --- | --- | --- | | **锁定粒度** | 行级锁(可以是表级锁) | 行级锁(通常是表级锁) | | **操作类型** | 只允许读取,不允许写入 | 允许读取和写入 | | **并发控制** | 多个事务可以同时获得读锁 | 只能有一个事务获得写锁 | | **对其他事务的影响** | 允许其他事务获得读锁,但不允许获得写锁 | 不允许其他事务获得读锁或写锁 | | **例子** | SELECT ... LOCK IN SHARE MODE | SELECT ... FOR UPDATE | | **使用场景** | 适用于读取数据而不修改的场景 | 适用于需要修改数据的场景 | > ### 失效的场景 1. **使用的存储引擎**:`SELECT ... FOR UPDATE` 只适用于使用 InnoDB 存储引擎的表。如果表使用的是 MyISAM 或其他不支持行级锁定的引擎,该语句不会起到锁定作用。 2. **事务隔离级别**:事务隔离级别可能影响锁定行为。如果事务的隔离级别是 `READ UNCOMMITTED` 或 `READ COMMITTED`,可能会导致预期外的行为。 > # 例子 - 表结构 ``` CREATE TABLE `symbol` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `code` varchar(10) DEFAULT NULL, `price` decimal(10,3) DEFAULT NULL COMMENT '价格', `overflow` decimal(10,3) DEFAULT NULL COMMENT '溢价率', `date` datetime DEFAULT NULL COMMENT '申购日期', `scale` decimal(10,3) DEFAULT NULL COMMENT '市值', `max_scale` decimal(10,3) DEFAULT NULL, `market` varchar(255) DEFAULT NULL, `zg_name` varchar(255) DEFAULT NULL, `zg_code` varchar(255) DEFAULT NULL, `zg_syl_d` decimal(10,3) DEFAULT NULL COMMENT '动态市盈率', `zg_syl_j` decimal(10,3) DEFAULT NULL COMMENT '静态市盈率', `zg_syl_t` decimal(10,3) DEFAULT NULL COMMENT 'ttm市盈率', `zg_plate` varchar(255) DEFAULT NULL, `is_num` tinyint(11) DEFAULT NULL, `t_amount` decimal(10,3) DEFAULT NULL, `t_num` int(11) DEFAULT NULL, `t_hight` decimal(10,3) DEFAULT NULL, `t_low` decimal(10,3) DEFAULT NULL, `t_data` json DEFAULT NULL, `is_price` decimal(10,3) DEFAULT NULL, `is_buy` varchar(255) DEFAULT NULL, `create_at` datetime DEFAULT NULL, `update_at` datetime DEFAULT NULL, `delete_at` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `code` (`code`) ) ENGINE=MyISAM AUTO_INCREMENT=780 DEFAULT CHARSET=utf8mb4; ``` - 会话一 ``` START TRANSACTION; select *,SLEEP(60) from symbol WHERE id = 527 for UPDATE; update symbol set price = 120 where id =527; COMMIT; ``` - 会话二 去修改 id = 527 时会阻塞