[c#] MySqlConnection을 열 때 예외가 발생하지 않습니까?

비동기 및 작업으로 시작하고 코드 처리가 중지되었습니다. 들어오는 네트워크 패킷이 있고 패킷 처리기 내부의 데이터베이스와 통신하려고 할 때 발생합니다.

public class ClientConnectedPacket : IClientPacket
{
    private readonly EntityFactory _entityFactory;

    public ClientConnectedPacket(EntityFactory entityFactory)
    {
        _entityFactory= entityFactory;
    }

    public async Task Handle(NetworkClient client, ClientPacketReader reader)
    {
        client.Entity = await _entityFactory.CreateInstanceAsync( reader.GetValueByKey("unique_device_id"));

        // this Console.WriteLine never gets reached
        Console.WriteLine($"Client [{reader.GetValueByKey("unique_device_id")}] has connected");
    }
}

Handle 메서드는 비동기 작업에서 호출됩니다.

if (_packetRepository.TryGetPacketByName(packetName, out var packet))
{
    await packet.Handle(this, new ClientPacketReader(packetName, packetData));
}
else
{
    Console.WriteLine("Unknown packet: " + packetName);
}

문제를 일으키는 것으로 생각되는 방법은 다음과 같습니다.

public async Task<Entity> CreateInstanceAsync(string uniqueId)
{
    await using (var dbConnection = _databaseProvider.GetConnection())
    { 
        dbConnection.SetQuery("SELECT COUNT(NULL) FROM `entities` WHERE `unique_id` = @uniqueId");
        dbConnection.AddParameter("uniqueId", uniqueId);

        var row = await dbConnection.ExecuteRowAsync();

        if (row != null)
        {
            return new Entity(uniqueId, false);
        }
    }

    return new Entity(uniqueId,true);
}

DatabaseProvider의 GetConnection 메소드 :

public DatabaseConnection GetConnection()
{
    var connection = new MySqlConnection(_connectionString);
    var command = connection.CreateCommand();

    return new DatabaseConnection(_logFactory.GetLogger(), connection, command);
}

DatabaseConnection의 생성자 :

public DatabaseConnection(ILogger logger, MySqlConnection connection, MySqlCommand command)
{
    _logger = logger;

    _connection = connection;    
    _command = command;

    _connection.Open();
}

이 줄을 주석 처리하면 Console.WriteLine

_connection.Open();



답변

.NET Core 3.1 콘솔 응용 프로그램에서 MySql.Data 8.0.19 및 MySqlConnector 0.63.2로 100 개의 병렬 작업을 회전시키는 POC 프로젝트를 실행했습니다. 모든 단일 작업의 컨텍스트에 연결을 작성하고 열고 처리합니다. 두 공급자 모두 오류없이 완료됩니다.

라이브러리는 비동기 메소드 서명 (예 : ExecuteReaderAsync () 또는 ExecuteScalarAsync ())을 제공하지만 MySqlConnector는 실제로 비동기 적 으로 실행되지만 MySql.Data 쿼리는 동 기적 으로 실행 됩니다.

다음과 같은 문제가 발생할 수 있습니다.

  • mysql 공급자와 특별히 관련되지 않은 교착 상태
  • 작업 내에서 예외를 올바르게 처리하지 못합니다 (작업 관련 집계 예외를 검사하고 mysql db 로그를 모니터링 할 수도 있습니다)
  • MySql.Data가 동 기적으로 실행될 때 많은 수의 병렬 작업을 실행하는 경우 작동하지 않는다고 가정 할 때 실행이 여전히 차단됩니다 (결과를 반환하지 않음).

답변

MySQL 사용한 멀티 스레딩은 독립적 인 연결을 사용해야합니다. 멀티 스레딩은 MySQL의 질문이 아니라 클라이언트 언어 인 C #의 문제입니다.

즉, MySQL에 관계없이 스레드를 빌드 한 다음 쿼리를 수행해야하는 각 스레드에서 연결 작성하십시오. 스레드간에 데이터를 전달 해야하는 경우 어깨에있을 것입니다.

일반적으로 쿼리를 최적화하면 응용 프로그램을 다중 스레드하려는 유혹이 사라집니다.


답변