programing

관련이 없는 SELECT 문으로 다른 결과를 반환하는 동시 MYSQL 프로시저 호출

javajsp 2023. 10. 11. 20:29

관련이 없는 SELECT 문으로 다른 결과를 반환하는 동시 MYSQL 프로시저 호출

제 MYSQL 응용 프로그램에서 매우 이상한 거래 행위를 경험하고 있습니다.

문제를 작은 분리된 테스트 케이스로 축소할 수 있었습니다. 아래에 포함된 코드는 다음과 같습니다.

-- Setup a new environment
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
DROP DATABASE IF EXISTS `testDB`;
CREATE DATABASE `testDB`;
USE `testDB`;

-- Create a table I want two procedure calls to interact with
CREATE TABLE `tbl_test` (
    `id` INT(10) UNSIGNED NOT NULL
    , PRIMARY KEY (`id`)
);

-- A second table purely to demonstrate the issue
CREATE TABLE `tbl_test2` (
    `id` INT(10) UNSIGNED NOT NULL
);


DELIMITER $$

DROP PROCEDURE IF EXISTS `sp_test` $$
CREATE PROCEDURE `sp_test` ()
BEGIN

    START TRANSACTION;

        -- CRAZY LINE
        SELECT * FROM `tbl_test2`;

        -- Insert ignore so both calls don’t try to insert the same row
        INSERT IGNORE INTO `tbl_test` (`id`) VALUES (1);

        -- Sleep added to make it possible to run concurrently manually
        SELECT SLEEP(1) INTO @rubbish; 

        -- The result I am interested in
        SELECT COUNT(*) FROM `tbl_test`;

    COMMIT;

END $$

DELIMITER ;

재생하는 단계:

  1. 위 스크립트에서 실행하여 테스트 데이터베이스, 두 개의 테이블 및 저장 프로시저를 만듭니다.
  2. 가능한 한 동시에 가까운 두 개의 개별 연결에서 저장된 프로시저를 실행합니다(확장할 수 있음).SLEEP시간이 더 필요한 경우):

    USE `testDB`;
    CALL sp_test ();
    

더 프로블럼

두 개의 개별 연결을 동시에 실행할 경우SELECT COUNT(*) FROM `tbl_test`;statement는 두 호출에 대해 서로 다른 값을 반환합니다.

위의 단계를 따를 때, 나는 뒤로 돌아옵니다.1두 번의 절차 중 첫 번째 전화로부터 그리고02차 때부터

거래 행위와 테이블 잠금에 대한 나의 이해는 첫번째 호출이 도착했을 때INSERT잠금을 생성할 것임을 명시합니다.두 번째 프로시저 호출은 동일한 회선에 도달하지만 첫 번째 호출의 트랜잭션이 커밋될 때까지 기다려야 합니다.수면 시간을 늘리면 두 번째 통화를 완료하는 데 두 배의 시간이 소요되기 때문에 이러한 생각이 강화됩니다.그러나 이 경우 두 번째 프로시저 호출은 첫 번째 호출에서 삽입을 선택해야 하며 두 결과 모두 다음과 같아야 합니다.1.

TL;DR 둘 다 동일할 것으로 예상합니다.1

사용 중인 참고 사항READ_COMMITTED내 거래 격리 수준으로서 말입니다.

이것을 사용해서 테스트해봤습니다.MYSQL server그리고.MariaDB

더 이상함

그래서 이 시점에서 저는 제 이해가 잘못되었다고 생각했습니다.하지만 그 다음에 그 줄을 제거함으로써 그 사실을 알게 되었습니다.SELECT * FROM `tbl_test2`;결과는 갑자기 예상치를 만들어냈습니다!

대본을 가지고 여러 실험을 해보았지만 본질적으로는,SELECT데이터베이스 내의 테이블에 대한 문장(state)을 입력합니다.INSERT선은 예상치 못한 결과를 초래합니다.나는 왜 이런지 전혀 모르겠어요.

문의사항

  1. 예상 거래 행위에 대한 제 이해가 맞습니까?
  2. 도대체 왜 그런거죠?SELECT관련 없는 테이블에 대한 문이 트랜잭션 잠금을 실패하게 합니까?

누군가 이것에 대해 설명해 줄 수 있다면 정말 감사하겠습니다!

언급URL : https://stackoverflow.com/questions/39513667/concurrent-mysql-procedure-calls-returning-different-results-with-an-unrelated-s