MySQL 2단계 잠금 및 교착 상태에 대해 이야기해 보겠습니다.

藏色散人
풀어 주다: 2022-12-05 19:20:58
앞으로
2132명이 탐색했습니다.

이 글에서는 MySQL 잠금에 대한 관련 지식을 주로 소개하며, 모두에게 도움이 되기를 바랍니다.

2단계 잠금

Concept

에서는 InnoDB가 행 잠금 잠금 및 잠금 해제 동작을 처리하는 방법에 대해 설명합니다. InnoDB如何处理行锁的上锁,释放锁的行为。

事务使用过程中,对记录以主键为条件删改时,会立刻加上排他锁,这完成了上锁阶段。

当删改动作完成后,这个锁并不会立即释放,需要等至事务提交时,才会释放锁

引发的问题-阻塞

事务 A 事务 B
begin;
update t set k=k+1 where id=1;
update t set k=k+1 where id=2;


begin;
update t set k=k+2 where id=1;
commit;

根据两阶段锁协议,事务 B将会因为id=1的数据被事务 A上了锁,而阻塞,因为事务 B需要拿到锁后才能进行下一步操作。

上述这个问题,可能看似问题不大,但是如果不止是事务 B,还有事务 C事务 D,等等很多,做的是跟事务 B一样的事,问题就大了,被阻塞的线程就会多了起来。【推荐学习:MySQL视频教程

如何处理上述问题

我们应该尽量将可能会引起阻塞的语句,放到事务的最后面操作,例如上述事务 A例子中的id=1的语句,它和第二句的执行并没有什么关联关系,可是它是容易引起阻塞的语句,因为在事务 B中也要对这一行数据做锁操作(在各类事务中频繁使用的,如公司的收付款账号余额记录,即**热点行**),但是却在事务一开始就拿到锁了。

本质上,是缩短了拿锁时间和释放锁之间的时间。即持有锁的时间缩短,以此减少锁引起的阻塞。

死锁

概念

两个线程,互相在等待对方释放资源。

在两个事务A,B中。

  • 事务 A拿到了资源 A的锁。

  • 事务 B拿到了资源 B的锁。

  • 事务 A去拿资源 B的锁。

  • 事务 B去拿资源 A的锁。

很明显,步骤 3,4中,事务 A,B 都想去拿锁,但是又都拿不到,因为对方都还没有释放该资源的锁。这种现象就是死锁。

引发的问题-死锁

InnoDB中,有一个拿锁的等待时间配置,超过这个时间就会抛出异常,这个时间默认是50秒。通常来说,有一个接口需要50秒后才响应是不可接受的。innodb_lock_wait_timeout

那是不是把这个配置时间设置短一点就行了?比如1秒?

应该是不可以的,因为可能会影响到你的正常业务,或许你的业务导致你的事务执行时间本身就比较长,超过1秒。超出这个时间会抛出异常,你的正常业务就被影响了。

那该如何处理上述问题

InnoDB中,还有一个自动检测死锁并处理的配置。它是默认开启的,在极端情况下,虽然能处理问题,但是对CPU消耗特别大。

它原理是在事务中即将要上锁的时候,会去检测其他并发线程,有没有将此资源锁住,如果检测到某个线程A有,然后再会去检测线程A的依赖有没有被其他并发线程锁住,如此循环往复,最终判断这些锁会不会形成死锁。

可以看出,线程越多,检测成本就越大。innodb_deadlock_detect

仅代表个人当前的学习做出的对此问题的处理和总结:

1.关闭死锁检测,将拿锁时间配置缩短至预估的最高时间,通常不会超过15秒,超过15秒后,需要有重试机制。

2.开启死锁检测,在应用层控制并发连接数,使用连接池控制Mysql的连接数,在服务层限制Mysql

거래 과정

중 기본 키를 기준으로 레코드가 삭제되면 단독 잠금이 🎜즉시🎜추가되어 🎜잠금🎜 단계가 완료됩니다. 🎜🎜삭제 작업이 완료되면 잠금이 즉시 해제되지 않습니다. 트랜잭션이 커밋될 때까지 🎜잠금이 해제됩니다🎜. 🎜

문제 발생 - 차단

🎜Transaction A🎜 🎜트랜잭션 B🎜
begin;
update t set k=k+1 where id=1;
update t set k=k+1 여기서 id=2;


td >
시작;
id=1인 경우 t set k=k+2 업데이트;
커밋; /em>
🎜🎜2단계 잠금 프로토콜에 따르면, 🎜트랜잭션 🎜<code>트랜잭션 A🎜에 의해 🎜id=1🎜의 데이터가 잠겼기 때문에 B🎜가 차단됩니다. 🎜트랜잭션 B때문입니다. >🎜다음 단계로 진행하기 전에 잠금을 해제해야 합니다. 🎜🎜🎜위 문제는 큰 문제는 아닌 것 같지만, 트랜잭션 B뿐만 아니라 트랜잭션 C, 트랜잭션 D)에도 해당된다면 >, 많이 기다려서 트랜잭션 B와 동일한 작업을 수행하면 문제가 커지고 더 많은 스레드가 차단됩니다. [추천 학습: MySQL 동영상 튜토리얼]🎜

대처 방법 위의 문제

🎜위 거래 Aid=1 문과 같이 거래가 끝날 때 차단을 일으킬 수 있는 문을 넣도록 최선을 다해야 합니다. code> 예시 두 번째 문장의 실행과는 관련이 없지만, 이 데이터 행도 트랜잭션 B(자주 사용됨)에서도 잠겨 있어야 하기 때문에 쉽게 차단을 일으킬 수 있는 문입니다. 회사의 추심 및 결제계좌 잔고기록, 즉 **핫라인** 등 각종 거래에서)을 사용하고 있으나 거래초기에 잠금을 획득하였습니다. 🎜🎜기본적으로 잠금 획득과 잠금 해제 사이의 시간이 단축됩니다. 즉, 잠금이 유지되는 시간이 단축되어 잠금으로 인한 차단을 줄일 수 있다. 🎜🎜Deadlock🎜🎜🎜Concept🎜🎜🎜두 스레드가 서로 리소스를 해제하기를 기다리고 있습니다. 🎜🎜두 거래 A와 B에서. 🎜
  • 🎜트랜잭션 A리소스 A의 잠금을 받았습니다. 🎜
  • 🎜트랜잭션 B리소스 B의 잠금을 받았습니다. 🎜
  • 🎜트랜잭션 A리소스 B의 잠금을 가져옵니다. 🎜
  • 🎜트랜잭션 B리소스 A의 잠금을 가져옵니다. 🎜
🎜분명히 3단계와 4단계에서 트랜잭션 A와 B는 모두 잠금을 원하지만 상대방이 리소스에 대한 잠금을 해제하지 않았기 때문에 어느 쪽도 잠금을 얻을 수 없습니다. 이 현상은 교착 상태입니다. 🎜🎜🎜다음으로 인한 문제 - 교착 상태🎜🎜🎜InnoDB에는 잠금 획득을 위한 대기 시간 구성이 있습니다. 이 시간을 초과하면 예외가 발생합니다. 기본 시간은 입니다. 50초. 일반적으로 응답하는 데 <code>50초가 걸리는 인터페이스는 허용되지 않습니다. innodb_lock_wait_timeout. 🎜🎜이 구성 시간을 더 짧게 설정하면 충분합니까? 예를 들어 1초? 🎜🎜귀하의 정상적인 비즈니스에 영향을 미칠 수 있기 때문에 불가능해야 합니다. 아마도 귀하의 비즈니스로 인해 거래 실행 시간이 1초를 초과하여 상대적으로 길어질 수 있습니다. 이 시간을 초과하면 예외가 발생하고 정상적인 비즈니스에 영향을 미칩니다. 🎜🎜🎜그러면 위의 문제를 어떻게 처리해야 할까요🎜🎜🎜InnoDB에는 교착 상태를 자동으로 감지하고 처리하는 구성도 있습니다. 극단적인 경우에는 문제를 해결할 수 있지만 CPU를 많이 소모합니다. 🎜🎜원칙은 트랜잭션이 잠기려고 할 때 다른 동시 스레드가 이 리소스를 잠갔는지 여부를 감지하는 것입니다. 특정 스레드 A가 잠겼는지 여부를 감지합니다. 스레드 A의 종속성은 다른 동시 스레드에 의해 잠겨 있으며, 이러한 잠금이 교착 상태를 형성할지 여부는 결국 결정됩니다. 🎜🎜스레드가 많을수록 감지 비용이 커지는 것을 볼 수 있습니다. innodb_deadlock_Detect. 🎜🎜이것은 개인의 현재 학습을 기반으로 한 이 문제의 처리 및 요약만을 나타냅니다. 🎜🎜1. 교착 상태 감지를 끄고 잠금 유지 시간 구성을 일반적으로 15초, <code>15초 후에 재시도 메커니즘이 필요합니다. 🎜🎜2. 교착 상태 감지를 켜고, 애플리케이션 계층에서 동시 연결 수를 제어하고, 연결 풀을 사용하여 Mysql 연결 수를 제어하고, Mysql 서비스 계층에서의 연결. 🎜🎜위 내용은 행 잠금이 성능에 미치는 영향을 줄이는 방법을 요약한 것입니다. 🎜

위 내용은 MySQL 2단계 잠금 및 교착 상태에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:learnku.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿