programing

"Mysql 행 크기가 너무 큼"에 대한 제한 변경

projobs 2022. 9. 22. 22:07
반응형

"Mysql 행 크기가 너무 큼"에 대한 제한 변경

제한을 변경하려면 어떻게 해야 합니까?

행 크기가 너무 큽니다(> 8126).일부 열을 TEXT 또는 BLOB로 변경하거나 사용ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED도움이 될 수도 있습니다. 행에서는 " " " 입니다.BLOB프리픽스 768 바이트는 인라인에 저장됩니다.

표:

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
top_a   varchar(255)    No       
top_b   varchar(255)    No       
top_c   varchar(255)    No       
top_d   varchar(255)    No       
top_e   varchar(255)    No       
top_f   varchar(255)    No       
top_g   varchar(255)    No       
top_h   varchar(255)    No       
top_i   varchar(255)    No       
top_j   varchar(255)    No       
top_title_a varchar(255)    No       
top_title_b varchar(255)    No       
top_title_c varchar(255)    No       
top_title_d varchar(255)    No       
top_title_e varchar(255)    No       
top_title_f varchar(255)    No       
top_title_g varchar(255)    No       
top_title_h varchar(255)    No       
top_title_i varchar(255)    No       
top_title_j varchar(255)    No       
top_desc_a  text    No       
top_desc_b  text    No       
top_desc_c  text    No       
top_desc_d  text    No       
top_desc_e  text    No       
top_desc_f  text    No       
top_desc_g  text    No       
top_desc_h  text    No       
top_desc_i  text    No       
top_desc_j  text    No       
status  int(11) No       
admin_id    int(11) No 

서버 장애에 대한 질문도 있었습니다.

MySQL 행 크기에 대한 많은 내용을 설명하는 이 문서를 보는 것이 좋습니다.TEXT 또는 BLOB 필드를 사용하더라도 각 필드의 첫 번째 768바이트가 페이지에 저장되므로 행 크기가 8K(InnoDB의 제한)를 초과할 수 있습니다.

이 문제를 해결하는 가장 간단한 방법은 Barracuda 파일 형식을 InnoDB와 함께 사용하는 것입니다.이는 기본적으로 처음 768바이트를 저장하는 대신 텍스트 데이터에 대한 20바이트 포인터만 저장함으로써 문제를 완전히 해결합니다.


OP에 효과가 있었던 방법은 다음과 같습니다.

  1. 음음 the the the 에 다음 항목을 합니다.my.cnf[mysqld]★★★★★★ 。

    innodb_file_per_table=1
    innodb_file_format = Barracuda
    
  2. ALTER 사용할 테이블ROW_FORMAT=COMPRESSED.

    ALTER TABLE nombre_tabla
        ENGINE=InnoDB
        ROW_FORMAT=COMPRESSED 
        KEY_BLOCK_SIZE=8;
    

위의 방법으로도 문제가 해결되지 않을 수 있습니다.InnoDB 엔진의 알려진(그리고 검증된) 버그이며, 현재 임시 수정은 MyISAM 엔진에 임시 저장소로 폴백하는 것입니다.그래서, 당신의 안에서my.cnf 삭제:

internal_tmp_disk_storage_engine=MyISAM

나는 최근에 이 문제에 부딪혀 다른 방법으로 해결했다.MySQL 버전 5.6.20 을 실행하고 있는 경우는, 시스템에 기존의 버그가 있습니다.MySQL 문서 참조

중요 버그 #69477로 인해 외부에 저장된 대규모 BLOB 필드에 대한 redo 로그 쓰기가 최신 체크포인트를 덮어쓸 수 있습니다.이 버그를 해결하기 위해 MySQL 5.6.20에 도입된 패치는 BLOB가 쓰는 redo 로그 파일의 크기를 redo 로그 파일 크기의 10%로 제한합니다.이 제한으로 인해 innodb_log_file_size는 테이블의 행에 있는 최대 BLOB 데이터 크기 및 기타 가변 길이 필드 길이(VARCHAR, VARBINAL 및 TEXT 유형 필드)의 10배를 초과하는 값으로 설정해야 합니다.

내 상황에선 문제가 되는 BLOB 테이블이 16MB 정도였어요.따라서 이 문제를 해결하려면 my.cnf에 행을 추가하여 최소 10배 이상의 양을 확보해야 합니다.그 다음 몇 가지 예를 제시하겠습니다.

innodb_log_file_size = 256M

my.cnf 파일에 다음을 설정하고 mysql 서버를 재시작합니다.

innodb_strict_mode=0

Engine을 전환하고 InnoDB 대신 MyISAM을 사용할 수 있다면 다음과 같은 이점이 있습니다.

ENGINE=MyISAM

MyISAM에는 다음 2가지 주의사항이 있습니다(상세 사항).

  1. 트랜잭션을 사용할 수 없습니다.
  2. 외부 키 제약 조건을 사용할 수 없습니다.

나도 같은 문제를 안고 있었는데, 이것으로 해결되었다.

ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;

MYSQL 문서:

DYNAMIC 행 형식은 행 전체를 인덱스노드에 저장하는 효율을 유지합니다(COMPT 형식 및 REDUAND 형식과 마찬가지로). 단, 이 새로운 형식을 사용하면 B-트리 노드에 대량의 긴 열 데이터 바이트가 채워지는 문제를 피할 수 있습니다.DYNAMIC 형식은 긴 데이터 값의 일부가 오프페이지로 저장될 경우 일반적으로 모든 값을 오프페이지로 저장하는 것이 가장 효율적이라는 생각에 기초하고 있습니다.DYNAMIC 형식을 사용하면 짧은 열은 B-트리 노드에 남아 있을 가능성이 높기 때문에 특정 행에 필요한 오버플로 페이지 수를 최소화할 수 있습니다.

멋진 대답을 하고 싶은데 도움이 될 것 같아요.Credits Bill Karwin은 여기를 참조하십시오.https://dba.stackexchange.com/questions/6598/innodb-create-table-error-row-size-too-large

InnoDB 파일 형식에 따라 다릅니다.현재 Antelope와 Barracuda라는 두 가지 형식이 있습니다.

중앙 테이블스페이스 파일(ibdata1)은 항상 Antellop 형식입니다.테이블당 파일 형식을 사용하는 경우 my.cnf에서 innodb_file_format=Filename을 설정하여 개별 파일에 Barracuda 형식을 사용하도록 설정할 수 있습니다.

기본 사항:

  1. InnoDB 데이터의 16KB 페이지에는 적어도 두 줄의 데이터가 저장되어 있어야 합니다.또한 각 페이지에는 페이지 체크섬과 로그 시퀀스 번호 등이 포함된 머리글과 바닥글이 있습니다.이 경우 한 줄당 8KB보다 약간 적은 한도를 사용할 수 있습니다.

  2. INTEGER, DATE, FLOAT, CHAR 등의 고정 크기 데이터 유형은 이 기본 데이터 페이지에 저장되며 행 크기 제한에 따라 카운트됩니다.

  3. VARCHAR, TEXT, BLOB와 같은 가변 크기의 데이터 유형은 오버플로 페이지에 저장되므로 행 크기 제한에 완전히 반영되지 않습니다.Antelope에서는 이러한 열의 최대 768바이트가 기본 데이터 페이지에 저장되며 오버플로 페이지에도 저장됩니다.Barracuda는 동적 행 형식을 지원하므로 기본 데이터 페이지에 20바이트 포인터만 저장할 수 있습니다.

  4. 가변 크기 데이터 유형에는 길이를 인코딩하기 위해 1개 이상의 바이트가 앞에 붙습니다.InnoDB 행 형식에는 필드 오프셋 배열도 있습니다.내부 구조가 위키에 거의 문서화되어 있습니다.

또한 Barracuda는 ROW_FORMAT=COMPRESSED를 지원하여 오버플로 데이터를 위한 스토리지 효율성을 더욱 높입니다.

또한 잘 디자인된 테이블이 열 크기 제한을 초과하는 것을 본 적이 없습니다.First Normal Form의 반복 그룹 조건을 위반하고 있는 것은 강한 "코드 냄새"입니다.

몇 시간 만에 해결 방법을 찾았습니다. MySQL 관리자에서 다음 SQL을 실행하여 테이블을 MyISAM으로 변환하십시오.

USE db_name;
ALTER TABLE table_name ENGINE=MYISAM;

데이터베이스 페이지 내에 로컬로 저장된 데이터에 적용되는 InnoDB 테이블의 최대 행 크기는 4KB, 8KB, 16KB 및 32KB의 페이지 절반보다 약간 작습니다.

16kb 페이지(기본값)의 경우 다음을 계산할 수 있습니다.

Slightly less than half a page 8126 / Number of bytes to threshold for overflow 767 = 10.59 fields of 767 bytes maximum

기본적으로 행의 최대값은 다음과 같습니다.

  • 11 varchar 필드 > 767 문자(latin1 = 1 문자당 1 바이트) 또는
  • 11 varchar 필드 > 255 문자(mysql의 utf-8 = 문자당 3 바이트).

필드가 767바이트보다 클 경우에만 오버플로우페이지에 도달합니다.767바이트의 필드가 너무 많으면 버스트합니다(max row_size를 초과).latin1에서는 일반적이지 않지만 개발자가 주의하지 않으면 utf-8에서는 매우 가능성이 있습니다.

이 경우 innodb_page_size를 32kb로 올릴 수 있다고 생각합니다.

my.cnf:

innodb_page_size=32K

참고 자료:

를 조금 요.my.ini

[mysqld] 아래에 추가

innodb_strict_mode=0

이 두 줄 업데이트

innodb_log_file_size=256M
innodb_log_buffer_size=256M

innodb_strict_mode시 특정 활성화 시 특정 InnoDB오류가 됩니다 경고가.

참고 자료: https://mariadb.com/kb/en/innodb-strict-mode/

innodb_log_file_size&&innodb_log_buffer_size크기가 증가할 필요가 있다.크기를 늘려야 합니다.

백업된 mysql 데이터베이스를 다른 서버에서 복원하려고 할 때 이 문제가 발생했습니다.이 문제를 해결할 수 있었던 것은 my.conf에 특정 설정을 추가하고(위 질문에서와 같이), sql 백업 파일을 추가로 변경하는 것입니다.

1단계: my.conf에서 다음 행을 추가 또는 편집합니다.

innodb_page_size=32K
innodb_file_format=Barracuda
innodb_file_per_table=1

스텝 2에서 이 에러의 원인이 되고 있는 테이블의 sql 백업 파일의 table create 문에 ROW_FORMAT=DYNAMIC을 추가합니다.

DROP TABLE IF EXISTS `problematic_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `problematic_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
  ...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 ROW_FORMAT=DYNAMIC;

위의 중요한 변경 사항은 ROW_FORMAT=DYNAMIC입니다. (오리지널 SQL 백업 파일에는 포함되지 않았습니다.)

이 문제를 해결하는 데 도움이 된 정보원:MariaDB 및 InnoDB MySQL 행 크기가 너무 큽니다.

다른 답변은 질문에 대한 답변입니다.스키마 설계 불량이라는 근본 원인을 짚어보겠습니다.

단에 걸쳐 배열 splay지 마세요.배열이 여러 열에 분산되지 않도록 하십시오.여기 3기둥의 10줄에 새 테이블에서 플러스 여기에는새 테이블에서 3열씩 10행으로 변환해야 하는 3*10열이 있습니다야 한다3*10 기둥을 가지고 있다.id등)등)

당신의 당신의.Main테이블 only테이블에는을 것이다

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
status  int(11) No       
admin_id    int(11) No 

너의 테이블(여분의 테이블(Top) 있을 것이다)는,

id  int(11) No          -- for joining to Main
seq TINYINT UNSIGNED    -- containing 1..10
img   varchar(255)    No       
title varchar(255)    No       
desc  text    No    
PRIMARY KEY(id, seq)    -- so you can easily find the 10 top_titles

또는 그 이상 것이다 10(?10개(또는 그 더 적은 이하)가 됩니다. 이상?)행?음행 입력.Top각 각각에 대해서에id.

이렇게 하면 원래 문제가 해소되고 스키마가 정리됩니다.(이것은 코멘트 중 일부에서 설명했듯이 '정규화'가 아닙니다.)

MyISAM으로 전환하지 마십시오.MyISAM은 없어집니다.
걱정하지 마세요 걱정하지 마세요ROW_FORMAT.

당신은이 작업을 할변경해야 합니다 코드를 수행하려면 코드를 바꿀 필요가 있을 것이다.JOIN을 사용하다

AWS RDS에서 MySQL 5.6을 사용하고 있으며, 파라미터 그룹에서 다음 내용을 업데이트하였습니다.

innodb_file_per_table=1
innodb_file_format = Barracuda

파라미터 그룹 변경을 적용하려면 DB 인스턴스를 재부팅해야 했습니다.

또한 ROW_FORMAT=COMPRESSED는 지원되지 않습니다.아래와 같이 DYNAMIC을 사용했는데 정상적으로 동작했습니다.

ALTER TABLE nombre_tabla ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8

Laravel Homesead(Vagrant) 박스를 파괴하고 새로 시작할 때 이 문제에 계속 부딪힙니다.

  1. 에서 박스에 SSH를 .homestead ssh

  2. file my.cnf로 합니다.sudo vi /etc/mysql/my.cnf

  3. 파일 하단에 다음 행을 추가합니다(!includedir 아래).

    [mysqld]

    innodb_log_file_size=512M

    innodb_strict_mode=0

  4. 하고 MYSQL my.cnf를합니다.sudo service mysql restart

이 문제를 해결하려면 phpmyadmin에서 innodb를 myisam으로 변경해야 합니다.이 사진 좀 봐.

여기에 이미지 설명 입력

저도 같은 문제가 발생했습니다.다음 sql을 실행하여 문제를 해결합니다.

ALTER ${table} ROW_FORMAT=COMPRESSED;

하지만 Row Storage에 대해서는 알아두셔야 할 것 같습니다.
열에는 가변 길이 열(VARCHAR, VARBINARY, BLOB 및 TEXT 유형 등)과 고정 길이 열의 두 종류가 있습니다.다른 유형의 페이지에 저장됩니다.

가변 길이 열은 이 규칙의 예외입니다.B-tree 페이지에 들어가지 않는 BLOB 및 VARCHAR과 같은 열은 오버플로 페이지라고 하는 별도로 할당된 디스크 페이지에 저장됩니다.우리는 이러한 칼럼을 페이지 밖의 칼럼이라고 부른다.이러한 열의 값은 단일 링크된 오버플로 페이지 목록에 저장되며, 이러한 각 열에는 하나 이상의 오버플로 페이지 목록이 있습니다.경우에 따라서는 스토리지 낭비를 방지하고 별도의 페이지를 읽을 필요가 없도록 긴 열 값의 전부 또는 접두사가 B-트리에 저장됩니다.

ROW_FORMAT을 설정하는 목적이

ROW_FORMAT=DYNAMIC 또는 ROW_FORMAT=COMPRESSED로 테이블을 생성하면 InnoDB는 긴 가변 길이 열 값(VARCHAR, VARBINAL 및 BLOB 및 TEXT 유형의 경우)을 완전히 오프페이지로 저장할 수 있습니다.클러스터된 인덱스 레코드에는 오버플로 페이지로의 포인터만 포함됩니다.

Dynamic형식 COMPRESSED 행 형식에 대해 자세히 알고 싶다

열이 많은 SELECT에서 이 문제가 발생할 경우 mysql이 임시 테이블을 만들고 있을 가능성이 있습니다.이 테이블이 너무 커서 메모리에 들어가지 않을 경우 기본 임시 테이블 형식인 InnoDB를 사용하여 디스크에 저장합니다.이 경우 InnoDB 크기 제한이 적용됩니다.

다음 4가지 옵션이 있습니다.

  1. innodb 행 크기 제한을 다른 게시물에서 설명한 대로 변경합니다.이 경우 서버를 다시 초기화해야 합니다.
  2. 더 적은 열을 포함하도록 쿼리를 변경하거나 임시 테이블이 생성되지 않도록 합니다(즉, 순서 기준 및 제한 구를 제거).
  3. max_disples_table_size를 크게 변경하여 결과를 메모리에 저장하여 디스크에 쓸 필요가 없습니다.
  4. 기본 임시 테이블 형식을 MYISAM으로 변경하여 이렇게 했습니다.my.cnf 변경:

    internal_tmp_disk_storage_engine=MYISAM
    

mysql을 재시작하면 쿼리가 작동합니다.

다음은 관심 있는 사용자를 위한 간단한 팁입니다.

10.3.17-MariaDB를 사용하여 Debian 9에서 Debian 10으로 업그레이드한 후 Joomla 데이터베이스에서 오류가 발생했습니다.

[경고] InnoDB: 필드를 추가할 수 없습니다.field식탁에 올라서database.table추가 후 행 크기가 8742로 인덱스 리프 페이지의 레코드의 최대 허용 크기(8126)보다 크기 때문입니다.

만약을 위해 /etc/syslog/syslogadb.conf.d/50-server.cnf에 innodb_default_row_format = DYNAMIC을 설정했습니다(기본값입니다).

그리고 Joomla 데이터베이스의 모든 테이블에 대해 "Optimize table"을 실행하기 위해 phpmyadmin을 사용했습니다.그 과정에서 phpmyadmin이 한 테이블 레크리에이션이 도움이 되었다고 생각합니다.phpmyadmin이 설치되어 있는 경우 클릭 몇 번으로 끝납니다.

Mysql 5.6의 경우:

다음 SQL 명령을 실행합니다.

Mysql > SET GLOBAL innodb_file_format=Barracuda; 
Mysql > ALTER TABLE `name_of_my_table_here` ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8; 

언급URL : https://stackoverflow.com/questions/15585602/change-limit-for-mysql-row-size-too-large

반응형