死锁日志
测试索引对于多事务的影响,也是并发的影响。
1、开启两个客户端工具,操作同一张表。t_notify.表目前只有主键id,没有索引。现在需要在两个事务中分别执行以下语句
UPDATE t_notify SET unread = 0 WHERE sender_id = '5b4dd776cc68c71f577e06f0' AND record_state = 0 AND unread =1 AND notify_type IN ('remind_report_update_male', 'remind_report_update_female');
UPDATE t_notify SET unread =0 WHERE sender_id= '5b44291f40658923b71aec13' AND notify_type = 'im_patient_to_team';
如果在同一个事务下,顺序执行,则不会有问题,但是如果现在一个事务执行一个语句,还没有提交,另外一个事务也执行了,则会发生死锁。
2、使用以下语句,可以查看到最后一次死锁记录。并可以查看出死锁发生原因。如果里面的内容不明白,可以先谷歌。
show engine innodb status;
3、不加索引情况下,模拟
-- 客户端1,开启事务,但是不提交,这个执行顺序为1
START TRANSACTION;
UPDATE t_notify SET unread = 0 WHERE sender_id = '5b4dd776cc68c71f577e06f0' AND record_state = 0 AND unread =1 AND notify_type IN ('remind_report_update_male', 'remind_report_update_female');
-- 客户端2,开启事务执行完2,提交,这个执行顺序为2.这样就可以模拟出简单的并发
START TRANSACTION;
UPDATE t_notify SET unread =0 WHERE sender_id= '5b4dd776cc68c71f577e06f0' AND notify_type = 'im_patient_to_team';
commit;
4、上述第二个客户端会发生死锁,死锁日志可以通过 步骤2 查看。
5、添加索引
alter table t_notify add index senderId_notifyType(sender_id,notify_type);
6、再重复步骤4的内容,重复4的内容前,先使用 show processList; 查看一下,看是否有锁状态。如果有,可以在客户端1中执行一次 commit; 再次查看 show processList;将其中被锁的线程kill掉。
7、原因
在没有索引的情况下,执行inser update delete是对全表的加锁,在并发比较多的情况下,我们需要尽量将锁的粒度缩小,使用行级锁。如果并发量更大,事务更多,我们需要使用缓存或者部分渗透的方法。