====== MySQL User Lock ====== * MySQL에서 ''GET_LOCK''과 ''RELEASE_LOCK'' 으로 분산 락(distributed lock)을 구현할 수 있다. * 원래는 [[nosql:redis:distributed_lock|Redis Distributed Lock]]를 사용하려다가 서버 구성하고 관리하는게 힘들어서 어차피 사용하는 MySQL에 적용했는데, 너무 잘 작동해서 Redis Distributed Lock 을 사용할 필요가 없어졌다. * [[https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html|MySQL Lock Functions]] * [[http://gywn.net/2013/12/mysql-user-level-lock/|MySQL의 User Level Lock를 활용한다면?]] user level lock의 활용에 대해 잘 설명한 글 * 동일 커넥션에서 GET_LOCK을 여러번하면 여러번 락이 잡힌다. 따라서 RELEASE_LOCK을 그 횟수만큼 동일 커넥션에서 반복해서 해주지 않으면 lock이 풀리지 않게 된다. * 위 문제에 따라 **Java에서 Connection Pool 사용시 항상 동일 Lock 문자열에 대한 GET_LOCK과 RELEASE_LOCK 이 동일 커넥션에서 동일 횟수만큼 이뤄짐을 보장해줘야 한다.** * 이 문제를 해결하려면 [[:springframework|Spring Framework]]의 트랜잭션에 의존하지 말고, **별도의 DataSource를 생성하여 직접 Lock 용 커넥션과 트랜잭션을 컨트롤**하는 것이 좋다. * Lock 은 트랜잭션 commit/rollback 여부와 상관없이 작동한다. rollback 한다고해서 lock 이 풀리지는 않는다. * Performance schema의 [[https://dev.mysql.com/doc/refman/5.7/en/metadata-locks-table.html|metadata_locks]] 테이블에 관련 정보가 저장된다. * Lock 이름은 **64**글자 제한(from MySQL 5.7) -- lock 잡기. 숫자 1은 lock 을 잡기 위해 대기할 수 있는 최대시간. -- 이 시간안에 락을 잡지 못하면 0 반환. select get_lock('session key', 1); -- 배타적으로 할 일. -- 락 풀기 select release_lock('session key'); * MySQL 5.6은 ''GET_LOCK''을 동일 세션에서 연속 호출하면 앞선 Lock을 해지하고 다시 잡는다. * MySQL 5.7은 두번 이상 호출해도 앞선 락을 해지하지 않는다. * [[http://mysqlserverteam.com/making-get_lock-behavior-more-predictable-cross-version-with-query-rewrite/|Making GET_LOCK behavior more predictable cross version with query rewrite]] * 5.7 부터 하나의 세션에서 연속으로 동일 Lock 이름으로 Lock을 잡으면 그 횟수만큼 중복으로 Lock이 잡힌다. select get_lock('a', 1); select is_free_lock('a'); -> false select get_lock('a', 1); select is_free_lock('a'); -> false -- release 시작 select release_lock('a'); -> 1 select is_free_lock('a'); -> false select release_lock('a'); -> 1 select is_free_lock('a'); -> true -- 이미 모든 Lock 해지 상태 select release_lock('a'); -> NULL ===== 참조 ===== * [[http://blog.saltfactory.net/introduce-mysql-lock/|MySQL에서 사용하는 Lock 이해]] * [[https://techblog.woowahan.com/2631/|MySQL을 이용한 분산락으로 여러 서버에 걸친 동시성 관리 | 우아한형제들 기술블로그]] * [[https://github.com/woowabros/mysql_user_level_lock_demo|woowabros/mysql_user_level_lock_demo]] -> https://github.com/kwon37xi/mysql_user_level_lock_demo fork 하고 수정해둠.