이 글에서는 MySQL 잠금에 대한 관련 지식을 주로 소개하며, 모두에게 도움이 되기를 바랍니다.
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> |
트랜잭션 🎜<code>트랜잭션 A
🎜에 의해 🎜id=1
🎜의 데이터가 잠겼기 때문에 B🎜가 차단됩니다. 🎜트랜잭션 B
때문입니다. >🎜다음 단계로 진행하기 전에 잠금을 해제해야 합니다. 🎜🎜🎜위 문제는 큰 문제는 아닌 것 같지만, 트랜잭션 B
뿐만 아니라 트랜잭션 C
, 트랜잭션 D
)에도 해당된다면 >, 많이 기다려서 트랜잭션 B
와 동일한 작업을 수행하면 문제가 커지고 더 많은 스레드가 차단됩니다. [추천 학습: MySQL 동영상 튜토리얼]🎜거래 A
의 id=1
문과 같이 거래가 끝날 때 차단을 일으킬 수 있는 문을 넣도록 최선을 다해야 합니다. code> 예시 두 번째 문장의 실행과는 관련이 없지만, 이 데이터 행도 트랜잭션 B
(자주 사용됨)에서도 잠겨 있어야 하기 때문에 쉽게 차단을 일으킬 수 있는 문입니다. 회사의 추심 및 결제계좌 잔고기록, 즉 **핫라인**
등 각종 거래에서)을 사용하고 있으나 거래초기에 잠금을 획득하였습니다. 🎜🎜기본적으로 잠금 획득과 잠금 해제 사이의 시간이 단축됩니다. 즉, 잠금이 유지되는 시간이 단축되어 잠금으로 인한 차단을 줄일 수 있다. 🎜🎜Deadlock🎜🎜🎜Concept🎜🎜🎜두 스레드가 서로 리소스를 해제하기를 기다리고 있습니다. 🎜🎜두 거래 A와 B에서. 🎜트랜잭션 A
가 리소스 A
의 잠금을 받았습니다. 🎜트랜잭션 B
가 리소스 B
의 잠금을 받았습니다. 🎜트랜잭션 A
는 리소스 B
의 잠금을 가져옵니다. 🎜트랜잭션 B
는 리소스 A
의 잠금을 가져옵니다. 🎜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 중국어 웹사이트의 기타 관련 기사를 참조하세요!