锁
select * from t_user where name = ‘xx‘ lock in share mode 获取目标集共享锁后,执行查询
select * from t_user where name = ‘xx‘ for update
获取目标集排他锁后,执行查询
1 #准备数据 2 create table t_deadlock( 3 id int not null auto-increment, 4 name varchar(20), 5 type int, 6 key (type), 7 primary key (id) 8 ); 9 10 insert into t_deadlock (name,type) VALUES (‘zs‘,1); 11 insert into t_deadlock (name,type) VALUES (‘ls‘,2); 12 insert into t_deadlock (name,type) VALUES (‘ww‘,3);
1 # 需求: 对zs的type做加1操作, 为防?资源抢夺(更新丢失), 设置锁 2 --事务1------------- 3 begin; 4 select type from t_deadlock where name=‘zs‘ lock in share mode; # 共享锁 5 --事务2------------- 6 begin; 7 select type from t_deadlock where name=‘zs‘ lock in sharemode; # 共享锁 8 --事务1------------- 9 update t_deadlock set type=2 where name=‘zs‘; # 等待事务2释放共享锁 10 -事务2------------- 11 update t_deadlock set type=2 where name=‘zs‘; # 等待事务1释放共享锁 12 # 相互等待, 产生死锁
1 #更新丢失的解决方法: 2 1.使用update子查询更新(乐观锁) 3 update t_deadlock set type=type+1 where name=‘zs‘; 4 2.查询时直接使用排它锁(悲观锁) 5 select type from t_deadlock where name=‘zs‘ for update;
1 # 需求: 记录的数量=3,才插入一条数据 2 --事务1------------- 3 begin; 4 select count(*) from t_deadlock; # 获取记录数量为3 5 --事务2------------- 6 begin; 7 select count(*) from t_deadlock; # 获取记录数量为3 8 --事务1------------- 9 insert into t_deadlock (name, type) values (‘zl‘, 1); 10 commit; # 插入成功 11 --事务2------------- 12 insert into t_deadlock (name, type) values (‘fq‘, 1); 13 commit; # 插入成功, 结果插入了两条数据
1 # 并发插?的解决办法: insert后边不能直接连接where, 并且insert只锁对应的行, 2 不锁表, 不会影响并发的插入操作(无法使用乐观锁完成需求), 只能在查询时就手动设置 3 排它锁(悲观锁) 4 --事务1------------- 5 begin; 6 select count(*) from t_deadlock for update; # 获取记录数量为3 7 --事务2------------- 8 begin; 9 select count(*) from t_deadlock for update; # 等待获取排它锁 10 --事务1------------- 11 insert into t_deadlock (name, type) values (‘zl‘, 1) 12 commit; # 插入成功 13 --事务2------------- 14 select count(*) from t_deadlock for update; # 事务1完成, 获取到记录数量为4, 不再执行插入操作
1 #gap锁场景1:使用范围条件 2 3 begin; #事务1 4 select * from t_user where age<30 for update; 5 #如果此时事务2插入记录(age<30),则会阻塞 (age不是索引触发表锁,age是索引触发的是间隙锁) 6 7 #gap锁场景2:锁定索引的前后区间 [prev,next) 8 update t_user set name=‘lisi‘ where age=30; 9 #如果age为索引,且数据中最接近age=30的值为20和40,则age=[20,40)的范围也会被锁定
1 #查看隔离级别 2 select @@global.tx_isolation, @@session.tx_isolation; 3 4 #设置隔离级别(重启后会重置) 5 SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ 6 UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE] 7 8 #修改配置文件设置隔离级别(重启不重置) 9 [mysqld] 10 transaction-isolation = READ-COMMITTED
原文:https://www.cnblogs.com/Infernal/p/11147831.html