내 데이터베이스에 프로필 사진을 저장하고 이러한 사진을 어딘가에 디스크로 내보내는 작은 C# 콘솔 앱을 작성했습니다. 나는 루프에서 한 번에 10 사진 선택 : 코드는 약간 더 간결하게 수정blob을 선택할 때 모든 쿼리가 시간 초과 될 때까지 MySQL 서버가 느려질 때까지
const int pageSize = 10;
using (var connection = new MySqlConnection(_options.Connectionstring))
{
connection.Open();
var pageCount = pageSize;
for (var page = 0; pageCount == pageSize; page++)
{
using (var command = new MySqlCommand($"SELECT
p.FirstName, p.LastName, p.Department, ph.Data
FROM Persons p
INNER JOIN Photos ph ON ph.PersonId = p.Id
LIMIT {pageSize} OFFSET {page * pageSize}", connection)
using (var reader = command.ExecuteReader())
{
for (pageCount = 0; reader.Read(); pageCount++)
{
var path = GetFilePath(reader, _options.Pattern);
EnsureDirectoryExists(path);
File.WriteAllBytes(path, (byte[])reader["Data"]);
}
}
}
}
을하지만 주로 어떤 검증 및 로깅을 제거했습니다.
응용 프로그램을 실행하는 동안 MySql Workbench에서 서버를 모니터링하면 약 2 분이 지나면 100 %에 도달하거나 1000 개의 이미지가 선택 될 때까지 "InnoDB 버퍼 사용"이 천천히 올라옵니다. 내가 읽은 바로는 정상이지만, 앱은 InnoDB 버퍼가 100 %에 가까워지면서 앱이 시간 초과되기 시작할 때까지 느리고 느린 이미지를 내 보냅니다.
데이터베이스 서버 정보 :제한 시간이 만료되었습니다. 작업이 완료되기 전에 시간 초과 기간이 경과되었거나 서버가 응답하지 않습니다.
- MySQL 서버 5.6
- 모든 테이블은 윈도우 서버 2012에서 실행
- innodb_buffer_pool_size = 1기가바이트
- 이노 을 사용하는 8기가바이트 RAM
사진 테이블 정의 :
CREATE TABLE `Photos` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`PersonId` int(11) NOT NULL,
`Data` longblob NOT NULL,
PRIMARY KEY (`Id`),
KEY `FK_PersonId_IDX` (`photo_person_id`),
CONSTRAINT `FK_PersonId` FOREIGN KEY (`PersonId`) REFERENCES `Persons` (`Id`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
앱 자체의 메모리 사용량이 매우 적습니다. innodb_buffer_pool_size를 늘리면 문제가 발생할 때까지 크기가 증가 할 때까지 시간 (또는 사진 수)이 증가하지만이 이미지를 내보낼 수 있도록 서버에 메모리를 추가하지 않아도됩니다. .
InnoDB 버퍼 풀을 large-is blob로 채우는 것은이 문제를 일으키는 것으로 보입니다.하지만이 모든 BLOB를 선택하려는 경우 실제로 발생하지 않도록하는 방법은 없습니다. 내가 무엇을 할 수 있을지? 아마도 타임 아웃을 늘릴 수 있다는 것을 알았지 만 그것은 분명한 이유 때문에 잘못된 해결책 일 뿐이며 Photos 테이블을 MyISAM으로 변경하여 문제를 해결할 것을 고려해 봤지만 다른 쉬운 솔루션이 있다면 그렇게하지 않을 것입니다. . 실제로이 문제를 해결할 다른 방법이 없다면 사진을 내보낼 때 완전히 다른 대안을 찾을 수 있습니다.
기타 정보가 무엇인지 알지 못하므로 다른 세부 정보는 의견에 문의하십시오.
코드는 어디에 있습니까? * 연결 *을 닫습니까? 명령 또는 판독기를 폐기해도 서버 측 자원이 해제되지 않습니다.* 페이징 *은 필요하지 않습니다. 레코드를 한 번에 하나씩로드하고 디스크에 씁니다. –
관련 코드를 추가했지만 페이징이 필요 없다는 것은 무엇을 의미합니까? 한 번에 모든 사진을 선택할 수는 없습니다 ... 또한 모든 쿼리 사이의 연결을 닫는 것이 이상한 것 같지만 시도해 볼 수 있습니다. – moggizx
첫 번째 for- 루프는 아무런 차이가 없었습니다. – moggizx