#MySql中的锁及解决的问题
#解决事务并发问题
- 方案一:读取操作用MVCC,写操作进行加锁
- 方案二:读、写操作都采用加锁的方式
#锁定读(LockingReads):读取当前版本,读取数据 加锁,阻止其他事务同时的修改(相同记录),避免安全问题。
###共享锁和独占锁
- 共享锁: Shared Locks,简称S锁
事务1->读取一条记录,S锁
事务2->加S锁
事务1和事务2持有同一把锁
- 独占锁: Exclusive Locks,简称X锁
事务1->读取一条记录,X锁
事务1->读取一条记录,X锁 阻塞
- X排他锁 X-X不兼容 X-S不兼容
- 共享锁 S-S兼容
###锁定度的SELECT语句
###写操作的锁
- insert update delete写操作
- delete:B+tree 读这条记录 取一下这条记录的 X锁 delete记录
- 定位删除的记录 B+树的过程,获取X锁定读
- insert:新增不要加锁
- update:比较复杂
三种情况:
1、要去该的记录A,(1024),所在的存储空间,修改前后没有发生变化,获取X锁
2、修改前后发生变化(1024->100),B+tree定位到这条数据位置,获取X锁,该条记录彻底删除,插入一条心记录(100),100位置获取X锁
3、修改,先delete再insert
#锁定的力度
#锁的粒度
- 行锁
- 表锁:lock tables table_name read;(read:共享锁;write:排他锁)特殊情况:崩溃恢复过程中。
#表锁与行锁的比较
- 锁定粒度:表锁>行锁
- 加锁效率:表锁>行锁
- 冲突概率:表锁>行锁
- 并发性能:表锁<行锁
#意向锁 效率问题
- 事务:某条记录 加 共享锁的时候,先在表的级别 一个IS锁
- 意向独占锁 IX
表级别各种锁的兼容性:
兼容性 | X | IX | S | IS |
X | 不兼容 | 不兼容 | 不兼容 | 不兼容 |
IX | 不兼容 | 不兼容 | ||
S | 不兼容 | 不兼容 | ||
IS | 不兼容 |
锁的组合性:(意向做没有行锁)
组合性 | X | IX | S | IS |
表锁 | 有 | 有 | 有 | 有 |
行锁 | 有 | 有 |
#Mysql中的 行锁 表锁
- 存储引擎有关 非InnoDB 都是表锁
- 加载一个表级别 表 同时一时刻 允许一个回话 对表进行操作
- InnoDB 区分表锁和行锁
#各种存储引擎中的锁
- 其他存储引擎中的锁: 只有表锁
- InnoDB存储引擎中的锁:表级别的S锁、X锁、元数据锁、IS锁、IX锁、AUTO-INC锁
IS锁、IX锁:意义 判断(防止遍历)没办法手动添加。
插入数据的时候(自增)
表级别锁:不去定具体要插入多少数据
2个事务 同时插入 的安全问题 事务A id=13 事务B id= 13
插入语句 执行之前 确定具体要插入多少记录。 100(初始ID=0)
事务A:100条
事务B:id 101 开始就行
轻量级锁:
参数来控制: | innodb_autoinc_lock_mode | 1 |
0 表级别
2 轻量级 (主从复制场景 不安全)
1 混合(根据事务能不能确定 插入数据的数量)
行锁 --> 记录加锁:
注意! 索引上加锁才是行锁,不是索引上加就是表锁 索引加锁
select * from table_name where id 用到索引
执行计划当中:确定真正使用索引 加行锁;
MySql 不同SQL, 执行计划,判断(数据2条,不会使用索引) 表锁。
间隙锁 -> 幻读问题
幻读 --> 记录不存在 MVCC 日志、版本链
彻底解决怎么办
间隙锁 概念 Gap locks
索引的前后 上间隙锁
事务1
begin;
upgate teacher set domain = '并发编程' where number = 6; 行锁 间隙锁
2-6 6-10 记录上锁
无法插入id为5的数据
事务2
begin;
insert into teacher values(7,'周老师','Netty');无法正常插入
insert into teacher values(20,'周老师','Netty');可以正常插入
#死锁
两个或两个以上进程(事务) 竞争资源 阻塞现象
没有外力,无法推进
A和B -> 会所
同时享受 语文课、数学课
李老师(语文课)
赵老师(数学课)
A -> T1 李老师,T3想抢到赵老师,都会阻塞
B -> T2 赵老师,T4(形成了:MySql事务重启)想抢到李老师,都会阻塞
#查看死锁参数
show variables like 'innodb_status_output_locks';
#设置参数
set global innodb_status_out_locks = ON;(OFF:关闭)
#查看死锁相关信息
show engine innodb status\G
查看 -> LATEST DELECTED DEADLOCK