У меня есть таблица:
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
, не столкнулся с какими-либо ошибками.
@ysth Я пытался length
посчитать количество байт, получилось 16.
в перле? Я имел в виду sql, чтобы увидеть, что он на самом деле отправляет на сервер.
Лучше использовать тип 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);
Самое простое решение — просто использовать 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 user4035 Вместо этого вы можете использовать varchar(36)
@user4035 user4035 Вы также можете рассмотреть возможность обновления до последней версии LTS (11.4), поскольку версия 10.5 устарела в июле 2025 г.
BINARY(36)
будет избегать любого преобразования набора символов и всегда будет иметь фиксированную длину в качестве альтернативы для версий < 10.11. Если uuidv1 приемлем, есть также функция sql uuid . В MariaDB также было почти 3 года исправлений ошибок с версии 10.5.13.
@RawleyFowler «Вы можете использовать varchar(36)» — это то, что я сделал. Сгенерировал строку и сохранил ее в varchar(36), хотя она занимает больше места.
@RawleyFowler «Вы также можете рассмотреть возможность обновления до последней версии LTS (11.4), поскольку версия 10.5 устарела в июле 2025 года» — стабильная версия Slackware очень консервативна. Последний пакет — «mariadb-10.5.26», обновлен в пятницу, 9 августа, 21:22:03 UTC 2024. Придется подождать еще год.
Есть ли у вас идеи, почему двоичный файл (16) может привести к ошибке? Я проверил длину сгенерированных двоичных данных, она ровно 16 байт. Убрано «использовать utf-8».
@RawleyFowler Вы пытались вставить 16 байтов в свою новую MariaDB на Perl? Это работает?
@user4035 user4035 Размер переменной довольно незначителен. Например, мы используем varchar(36)
(в старом экземпляре MariaDB) в таблице, содержащей около 300 миллионов записей. Эта таблица имеет огромную пропускную способность, мы добились хорошей производительности, используя движок MyRocks
. Я также обновил ответ решением, которое работает с типом binary
.
что возвращает
select length(?), char_length(?)
с учетом $session_id? какая версия Data::UUID?