Mysql为什么会产生死锁?
事务A、B分别拿到1,4的独占行锁,然后再去拿4,1的行锁,都会由于另一个事务不释放锁等待,造成了循环等待的局面。
-
(1)同一时刻只能有一个事务持有这把锁;
-
(2)其他的事务需要在这个事务释放锁之后才能获取锁,而不可以强行剥夺;
-
(3)当多个事务形成等待环路的时候,即发生死锁。
如何去检测死锁?
show status命令查看行锁相关参数
show status like 'innodb_row_lock_%';
lnnodb_row_lock_current_waits:当前正在等待锁定的数量;
lnnodb_row_lock_time :从系统启动到现在锁定的总时间长度,单位ms;
Innodb_row_lock_time_avg :每次等待所花平均时间;
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间;
lnnodb_row_lock_waits :从系统启动到现在总共等待的次数。
show status只是来看一下大概的情况,具体情况还需要用到Innodb提供的三张表
具体的处理:
通过这三条命令看锁和事务的关系
select * from information_schema.INNODB_TRX; --当前运行的所有事务﹐还有具体的语句
select* from information_schema.INNODB_LOCKS; --当前出现的锁
select * from information_schema.INNODB_LOCK_WAITS; --锁等待的对应关系
kill掉事务的线程id INNODB_TRX表中的trx_mysql_thread_id
但是kill需要手动,我们不可能每次都自己去kill掉死锁问题,还是应该从代码层出发,尽量不让死锁发生。
-
1、在程序中,操作多张表时,尽量以相同的顺序来访问(避免形成等待环路)
-
2、批量操作单张表数据的时候,先对数据进行排序(避免形成等待环路);
-
3、申请足够级别的锁,如果要操作数据,就申请排它锁;
-
4、尽量使用索引访问数据,避免没有where条件的操作,避免锁表;
-
5、如果可以,大事务化成小事务;
-
6、使用等值查询而不是范围查询查询数据,命中记录,避免间隙锁对并发的影响。
Mysql索引的数据结构:
Hash:
myisam和innodb都不支持hash索引。
hash索引是基于hash表来实现,那么就是两次查询,第一次根据hash值找到hash表对应的位置,然后根据位置上的值找到数据。
只有查询条件在精确匹配hash表的所有值得时候,才用到hash索引。 hash索引包括一个hash码,键值和指针。
既然是hash表的形式,那么hash的缺点也就很明显:
1.二次查找的性能消耗。
2.hash值碰撞问题,如果冲突,那么找到新位置的性能消耗很大。
3.hash索引没有办法外排序,因为他存的不是实际的数据值,而是hash码
4.最重要的一点!hash不支持范围索引,只有在等值索引才能派上用场。
B+树和B树:
B树:
B+树:
不难看出B树键和值放在每个节点。 B+树的内部节点只存储键,在叶子节点存键值并且用链表串起来。
B+树和Hash的优缺点:
Hash由于通过hash函数去hash表获取相应键值,然后再回表查询对应的值得特性。
1.由于hash索引建立的无序,所以不能范围查找,只能等值查找。
2.必须要回表,B+树在覆盖索引和聚簇索引可以不回表。
3.虽然hash等值查找快,但是由于hash碰撞会带来不确定性,不推荐用hash
B+树和B树:
B树由于内部存放键和值,如果把热点数据放在接近根节点的位置,查询效率更高。所以B+树在特定数据重复多次查询场景更高效。
B+树由于叶子节点存值,内部节点只存键。因此内存页可以存更多的键,对于数据量高的情况下,B+树更有优势。
1.B树不支持顺序索引,B+树支持
2.相同IO次数,B+树空间利用率高,读写的代价更低
3.B树的查询效率不稳定,由于不确定关键字在树的哪个位置,相当于不断做二分查找,最快一次,最慢就不知道了。
B+树的查询效率很稳定,因为每个数据的查询至少都要走到叶子节点。
4.B树没有解决遍历的问题,B+树通过把叶子节点链表存储解决。
5.增删效率方面,B+树由于可以顺序查找,效率一定是更高的。
聚簇索引和非聚簇索引:
聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
非聚簇索引:
Full-text:
标签:事务,hash,查询,索引,死锁,mysql,乔亚,节点 From: https://www.cnblogs.com/dwj-ngu/p/17144543.html