Mysql数据库锁的一个问题
- Texan默认隔离级别 可重复读, autocommit=1, 建表:
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`age` tinyint(3) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_age` (`age`) USING BTREE
) ENGINE=InnoDB ;
INSERT into test (id,age) values (1,1);
session 1:
update test set age=1 where id=1;
session 2:
update test set id=1 where age =1;
那么 session 1 和 2是否有可能产生死锁?
session 1是先锁主键,再锁二级索引. session 2是先锁二级索引再锁主键.
我在本地上各开了二十个线程来不停update,没有出现死锁. 为什么呢? - 269569205因为你cpu够快 20个线程瞬间执行完毕
- Pyrrhus普通的update是一次就commit掉的,你要把它们放在事务里
- Texan抱歉,我的意思是, 20个线程执行第一条,每个线程update 1万次. 20个线程执行第二个update, 也是每个线程1万次.
没有发现死锁. - Texanautocommit=1, 这个update本来就是事务里啊.
我只是不知道一条update语句锁了两个索引的过程,是不是一个原子性的动作. - shuihen手动commit
- Pyrrhus你还是没搞清死锁的原理,
死锁是在锁表前发现有其他事务已经将表锁住,在等待另外事务的解锁,
而你只有2个事务,前面那个事务解锁,后一个就能顺利运行,
一般要测死锁要开3个进程,这样才能骗过系统。 - txkingzjgmark下,系统偶然出现死锁,很难重现,死锁原理也懂,但是就是没法根治问题,烦人
- IAmThrilling那个回帖解释很清楚了,死锁出现原因就是进程等待,你这种情况操作很快完成,没机会等待多久 iOS fly ~
- Texan我比较好奇的就是, 这种死锁情况理论上是否会出现?
比如说UUID是有概率重复的,而且我们可以估算出来概率。 - IAmThrilling貌似你那两个语句理论上也不会锁
- Texanhttps://ruby-china.org/topics/38429发现了这篇文章, 两条简单的update语句导致死锁
文章的大意就是,
'a', 'b' 是表里两个索引
session 1:
update t set c=1where (a=1 and b =1)
session 2:
update t set c=1 where (a=2 and b =2)
这样也可能产生死锁 - Texan看12L
- lumi顺序执行,有等待但不死锁
- Hisoka-J一会我给你跑一个 iOS fly ~
- IAmThrilling你第一个session where 不会触发行锁 iOS fly ~
- xx6412223不会死锁,最多是第二个线程等待超时。
死锁的概念是两个线程对两个资源同时上锁,但是每个都只拿到其中一个资源,等待第二个资源释放。
操作系统原理对死锁一个比喻是,两个人吃面条只用一副刀叉
手动模拟的话,开两个sesaion 并且手动提交事务,第一个where a=1 for update 第二个where a =2 for update .切回第一个session再次 where a=2 for update ,就有死锁了 - swordf死锁必要条件:互斥使用资源,占有并等待资源,资源不可抢夺,循环等待资源。第二条不成立吧?
- Texan我跑过了,十个线程,每个有一个储存过程, 不停循环update, 也就是第一条语句. 另外十个线程,另外一个储存过程,第二条语句. CPU已经100%占用了. 跑了五分钟.
可以看到对聚簇索引和二级索引分别的锁的请求,但是死锁信息. 应该是源码里面用了其他机制来保证每个语句里面获取的两把锁,都是原子性一起获取的.