MariaDB, Data::UUID GUID: данные слишком длинные для двоичного столбца (16)

У меня есть таблица:

CREATE TABLE `sessions` (
  id BINARY(16) NOT NULL,
  PRIMARY KEY(id)
) ENGINE=InnoDB;

Я создал значение для вставки в поле id:

$sql = 'INSERT INTO sessions (id) VALUES(?)';
my $generator = Data::UUID->new;
my $session_id = $generator->create();
$result = $dbh->do($sql, undef, $session_id);

Согласно документации к модулю Data::UUID:

# creates binary (16 byte long binary value) UUID.
$ug->create();

https://metacpan.org/pod/Data::UUID

Но когда я пытаюсь ВСТАВИТЬ данные, я получаю сообщение об ошибке от MariaDB:

Данные слишком длинные для столбца "id"

Почему оно слишком длинное, если длина поля составляет 16 байт и, согласно документации, размер $session_id также составляет 16 байт?

Я подозреваю, что проблема связана с драйвером: я подключаюсь с помощью "dbi:MariaDB:$dbinst:$dbhost", в то время как другой пользователь, который пробовал драйвер mysql, не столкнулся с какими-либо ошибками.

что возвращает select length(?), char_length(?) с учетом $session_id? какая версия Data::UUID?

ysth 30.08.2024 02:46

@ysth Я пытался length посчитать количество байт, получилось 16.

user4035 30.08.2024 16:15

в перле? Я имел в виду sql, чтобы увидеть, что он на самом деле отправляет на сервер.

ysth 30.08.2024 16:42
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
4
3
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

МарияДБ >= 10,7

Лучше использовать тип UUID в MariaDB и Data::UUID::create_str. Это будет выглядеть примерно так:

CREATE TABLE `sessions` (
  id UUID NOT NULL,
  PRIMARY KEY(id)
) ENGINE=InnoDB;
$sql = 'INSERT INTO sessions (id) VALUES(?)';
my $generator = Data::UUID->new;
my $session_id = $generator->create_str();
$result = $dbh->do($sql, undef, $session_id);

МарияДБ < 10,7

Самое простое решение — просто использовать varchar(16), желательно с движком MyRocks, если он доступен (MyRocksзначительно улучшит производительность и сжатие varchar-ключей):

CREATE TABLE `sessions` (
  id VARCHAR(16) NOT NULL,
  PRIMARY KEY(id)
) ENGINE=MyRocks;
$sql = 'INSERT INTO sessions (id) VALUES(?)';
my $generator = Data::UUID->new;
my $session_id = $generator->create_bin();
$result = $dbh->do($sql, undef, $session_id);

Объяснение

По какой-то причине Data::UUID возвращает значение с length(?), варьирующимся от 23 до 27 байт, но char_length(?) из 16. Вероятно, это ошибка либо Data::UUID, либо DBD::MariaDB/DBD::mysql.

Моя MariaDB — 10.5.13: слишком стара для этого типа данных.

user4035 29.08.2024 16:34

@user4035 user4035 Вместо этого вы можете использовать varchar(36)

Rawley Fowler 29.08.2024 19:35

@user4035 user4035 Вы также можете рассмотреть возможность обновления до последней версии LTS (11.4), поскольку версия 10.5 устарела в июле 2025 г.

Rawley Fowler 29.08.2024 19:53
BINARY(36) будет избегать любого преобразования набора символов и всегда будет иметь фиксированную длину в качестве альтернативы для версий < 10.11. Если uuidv1 приемлем, есть также функция sql uuid . В MariaDB также было почти 3 года исправлений ошибок с версии 10.5.13.
danblack 30.08.2024 01:27

@RawleyFowler «Вы можете использовать varchar(36)» — это то, что я сделал. Сгенерировал строку и сохранил ее в varchar(36), хотя она занимает больше места.

user4035 30.08.2024 09:41

@RawleyFowler «Вы также можете рассмотреть возможность обновления до последней версии LTS (11.4), поскольку версия 10.5 устарела в июле 2025 года» — стабильная версия Slackware очень консервативна. Последний пакет — «mariadb-10.5.26», обновлен в пятницу, 9 августа, 21:22:03 UTC 2024. Придется подождать еще год.

user4035 30.08.2024 09:46

Есть ли у вас идеи, почему двоичный файл (16) может привести к ошибке? Я проверил длину сгенерированных двоичных данных, она ровно 16 байт. Убрано «использовать utf-8».

user4035 30.08.2024 09:48

@RawleyFowler Вы пытались вставить 16 байтов в свою новую MariaDB на Perl? Это работает?

user4035 30.08.2024 10:55

@user4035 user4035 Размер переменной довольно незначителен. Например, мы используем varchar(36) (в старом экземпляре MariaDB) в таблице, содержащей около 300 миллионов записей. Эта таблица имеет огромную пропускную способность, мы добились хорошей производительности, используя движок MyRocks. Я также обновил ответ решением, которое работает с типом binary.

Rawley Fowler 30.08.2024 16:56

Другие вопросы по теме