increase the max character limit for the index keys in mariaDB - mariadb

On Nextcloud/social we have this problem:
Primary index name on "oc_social_a2_cache_documts" is too long.
see: https://github.com/nextcloud/social/issues/850
Is there a way to increase the limit for the character length of the index?
Update:
The table structure is
REATE TABLE `oc_social_a2_cache_documts` (
`id_prim` varchar(128) COLLATE utf8_bin NOT NULL,
`id` varchar(1000) COLLATE utf8_bin DEFAULT NULL
PRIMARY KEY (`id_prim`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
It works, If I rename the table to a shorter name with one character less: just oc_social_a2_cache_docums
But that is not a solution here, since it seems to have worked before in older versions I am not sure, how the problem could only occur now with the latest update???

Related

10.4.24-MariaDB - Foreign key constraint is incorrectly formed

In person_addresses table i am getting error Foreign key constraint is incorrectly formed. My Version is 10.4.24-MariaDB
CREATE TABLE persons (
person_id int(11) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
email varchar(50) DEFAULT NULL,
phone int(11) DEFAULT NULL,
bio text DEFAULT NULL,
dob date DEFAULT NULL,
gender enum('Male','Female','Other') NOT NULL,
status tinyint(4) NOT NULL,
created_at timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (person_id),
UNIQUE KEY email (email),
UNIQUE KEY phone (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE person_addresses (
person_id int(11) NOT NULL ,
address text NOT NULL,
created_at timestamp NOT NULL DEFAULT current_timestamp(),
UNIQUE KEY uc_person_address (person_id,address),
CONSTRAINT fk_person FOREIGN KEY (person_id) REFERENCES persons(person_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
More Detailed Error
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2023-01-11 12:41:52 0x421c Error in foreign key constraint of table `test`.`person_addresses`:
There is no index in table ```test``.``person_addresses``` where the columns appear
as the first columns. Constraint:
FOREIGN KEY (person_id) REFERENCES persons (person_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
Please refer to https://mariadb.com/kb/en/library/foreign-keys/ for correct foreign key definition.Create table `test`.`person_addresses` with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' FOREIGN KEY (person_id) REFERENCES persons (person_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4'.
I think I found a matching bug report in MariaDB: https://jira.mariadb.org/browse/MDEV-29717
The issue is that if the index required for the foreign key is very large, the index is created automatically. But this fails if that index is larger than the index size limit for the storage engine (this should be 3072 bytes in the version of MariaDB you are using, because it defaults to DYNAMIC row format with innodb_large_prefix=on). The text type in your index is too large to be indexed without defining an index prefix. But foreign keys can't use indexes defined with index prefixes.
Unfortunately, because foreign keys are implemented deep in the storage engine, there is little opportunity for a more informative error message to be revealed. This is a problem with the implementation of pluggable storage engines.
The solution in your case should be to change the address column type. It cannot be text, it can only be a varchar that is not too long for the index prefix length limit.
For example, I tested with MariaDB 10.4. https://dbfiddle.uk/5jTX8iFt It fails if address is text, and it works fine if address is varchar(255). I did not test other lengths, I'll leave that to you.
I doubt you need text for an address anyway. Does anyone have an address that requires 64KB?

Why is my MariaDb not adding a column to a large table using the INSTANT algorithm

I have a huge table in a MariaDb (10.4.10-MariaDB-1:10.4.10+maria~bionic) and I am adding a new column using
alter table Appointment add column responsible_organization varchar(256);
The existing table is this:
CREATE TABLE `Appointment` (
`id` VARCHAR(256) NOT NULL,
`version` VARCHAR(24) NOT NULL,
`repetition_ref` VARCHAR(256) NULL DEFAULT NULL,
`type` VARCHAR(256) NULL DEFAULT NULL,
`comment` VARCHAR(2048) NULL DEFAULT NULL,
`description` VARCHAR(2048) NULL DEFAULT NULL,
`end` DATETIME NULL DEFAULT NULL,
`start` DATETIME NULL DEFAULT NULL,
`status` VARCHAR(256) NULL DEFAULT NULL,
`statuschangedate` DATETIME NULL DEFAULT NULL,
`deliverystatus` VARCHAR(256) NULL DEFAULT NULL,
`reasoncancelled` VARCHAR(256) NULL DEFAULT NULL,
`visit_type` VARCHAR(256) NULL DEFAULT NULL,
`modified_db_time` TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(3) ON UPDATE current_timestamp(3),
`markedasdeleted` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`id`, `version`),
INDEX `FKc4f6e4y3ftaya162pwf7v4uj4` (`deliverystatus`),
INDEX `FKeuhxsh83rlweegn404penommb` (`reasoncancelled`),
INDEX `FK5xmurewn61wf4n3of5yx2nsmg` (`visit_type`),
INDEX `modified_db_time` (`modified_db_time`),
CONSTRAINT `FK5xmurewn61wf4n3of5yx2nsmg` FOREIGN KEY (`visittype`) REFERENCES `Coding` (`id`),
CONSTRAINT `FKc4f6e4y3ftaya162pwf7v4uj4` FOREIGN KEY (`deliverystatus`) REFERENCES `CodeableConcept` (`id`),
CONSTRAINT `FKeuhxsh83rlweegn404penommb` FOREIGN KEY (`reasoncancelled`) REFERENCES `CodingDt` (`id`)
)
;
As far as I read the MariaDb documentation it should choose the most efficient algorithm if I don't specify any. I would expect it to use INPLACE at the minimum. But when I run it i can see in the process list that it is running with the state "Copy to tmp table". So this is the COPY algorithm right?
I then tried to force it to use INSTANT as sugested by #o-jones. That gave me this output:
MariaDB [mydb]> alter table Appointment add column responsibleorganisation varchar(256), ALGORITHM=INSTANT;
ERROR 1846 (0A000): ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY
Weird, since I am adding a column.
I am wondering if it has something to do with the table being created on an older version of MariaDb and not having been rebuilt recently. I have found references to this being an issue for tables with old style temporal columns.
The variables old_alter_table and alter_algorithm both have the value DEFAULT
My table has 110+ million rows, so I would have liked to find a way to optimize this.
Any ideas?
MariaDB Server 10.4.10 was released over 2 years ago, in November 2019. Is this repeatable with a more recent version? There have been some fixes to ALTER TABLE since then.
If the problem is repeatable with the latest version in the 10.4 series, I would suggest that you file a bug report at https://jira.mariadb.org with a minimal reproducible test case (CREATE TABLE and ALTER TABLE statements).
With a more recent version, the answer could have been that MDEV-20590 introduced a way to disable instant operations that involve changing the data file format. SET GLOBAL innodb_instant_alter_column_allowed=never; would make ADD COLUMN always rebuild the table, like it did before MariaDB Server 10.3.
I have seen this in cases where a database was created in an earlier version of MariaDB. Sometimes the storage format for some columns has changed, but the upgrade did not rewrite all of the data. Instead it waits until certain schema changes are made and then it modifies that underlying data format. In my cases it was because some of the columns were date/datetime and the temporal storage format had changed in 10.3, but many of my tables were still in the old format. Any schema change I made in 10.4 wanted to update the format for all of those columns, which was a pain for tables with many millions of rows.
If you rebuild the table first using "ALTER TABLE tab_name ENGINE = InnoDB;" then the column add would be able to be added "instantly". Although the alter will take as long as the non-instant column add would. However, there are circumstances where doing the processes separately might be advantageous.
In my case I had to do a manual table rebuild because I could not allow the live table to be locked for as long as the rebuild would take. So I wrote a stored procedure to take the table and create a copy of it gradually, and keep the copy up-to-date. The copy process was throttled to avoid putting to much strain on the db and then once the copy was ready I was able to swap the old and new tables quickly with renames so that the down time was measured in seconds instead of hours. Once the new table was in place I was able to do instant ddl operations on it like normal.

MariaDB won't let me make column unique

I recently duplicated an existing MariaDB table (for use on Amazon RDS). The two tables are basically identical, data included, but I noticed the new version was missing all the unique constraints (kept the primary keys just fine). When I tried to add back the uniques, I got an error:
BLOB/TEXT column 'url' used in key specification without a key length
Others have had this problem, and people have claimed that MySQL/MariaDB simply doesn't let you make text columns unique. But my original MariaDB database (on my local machine) has plenty of text columns with unique keys, so that can't be it. I tried their solution anyway (switching to varchar) but MariaDB wouldn't let me do that either because my data has too many characters. Any ideas? Many thanks.
MariaDB 10.4 supports a UNIQUE KEY on a TEXT column because it automatically converts the index to a HASH index:
mysql> create table t (id serial primary key, t text, unique key(t));
Query OK, 0 rows affected (0.01 sec)
mysql> show create table t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`t` text DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `t` (`t`) USING HASH
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Unfortunately, Amazon RDS for MariaDB does not support MariaDB 10.4 yet (as of 2020-03-19), according to https://aws.amazon.com/rds/mariadb/:
Amazon RDS supports MariaDB Server versions 10.0, 10.1, 10.2, and 10.3 which means that the code, applications, and tools you already use today can be used with Amazon RDS.
The HASH index feature is not supported in MariaDB 10.3 or earlier:
mysql> create table t (id serial primary key, t text, unique key(t));
ERROR 1170 (42000): BLOB/TEXT column 't' used in key specification without a key length
You can create a unique key on a prefix of the text column:
mysql> create table t (id serial primary key, t text, unique key(t(1000)));
Query OK, 0 rows affected (0.01 sec)
mysql> show create table t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`t` text DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `t` (`t`(1000))
) ENGINE=InnoDB DEFAULT CHARSET=latin1
This means the unique key will enforce uniqueness in the first 1000 characters. You won't be allowed to store two rows with string that have the same first 1000 characters, but differ in the 1001st character or later.

why is there error 1064 in my script when i executed it

MySQL
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') ENGINE = InnoDB' at line 7
CREATE TABLE IF NOT EXISTS `game_review`.`users` (
`user_id` INT NOT NULL AUTO_INCREMENT,
`email_address` VARCHAR(45) NOT NULL,
`password` VARCHAR(6) NOT NULL,
`username` VARCHAR(20) NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE INDEX `user_id_UNIQUE` (`user_id` ASC) VISIBLE)
ENGINE = InnoDB;
I expected this to execute properly since I forward engineered it with my ER diagram that I created, but it gives me the error message above.
MariaDB does not support invisible indices, so the VISIBLE and INVISIBLE keywords are not used. Indices are already visible to the optimizer by default, so you could just use:
UNIQUE INDEX user_id_UNIQUE (user_id)
But, a primary key column should already be unique, so you can probably just not even include the unique index.
Side note: MySQL 8+ does support invisible indices, see here, but your MariaDB version seems to not support them.

MariaDB: ALTER TABLE syntax to add a FOREIGN KEY?

what'S wrong with the following statement?
ALTER TABLE submittedForecast
ADD CONSTRAINT FOREIGN KEY (data) REFERENCES blobs (id);
The error message I am getting is
Can't create table `fcdemo`.`#sql-664_b` (errno: 150 "Foreign key constraint is incorrectly formed")
This works for me on MariaDB 10.1.8:
CREATE TABLE `submittedforecast` (
`id` INT(11) NOT NULL,
`data` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `data` (`data`)
) ENGINE=InnoDB;
CREATE TABLE `blobs` (
`id` INT(11) NOT NULL,
`content` BLOB NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
ALTER TABLE submittedForecast
ADD CONSTRAINT FOREIGN KEY (data) REFERENCES blobs (id);
Can you give your MariaDB version number and a complete example including the CREATE TABLE statements for submittedForecast and blobs?
No idea if you already solved this but make sure both engines and collations match between tables (e.g: latin1 to latin1 and InnoDB to InnoDB).
I was having the same issue and by switching these I managed to get it working.
I was getting the same issue and after looking at my table structure, found out that my child table's foreign key clause was not referencing the primary key of parent table. Once i changed it to reference to primary key of parent table, the error was gone.
I had the same error and is actually pretty easy to solve, you have name the constraint, something like this should do:
ALTER TABLE submittedForecast ADD CONSTRAINT `fk_submittedForecast`
FOREIGN KEY (data) REFERENCES blobs (id)
If you would like more cohesion also add at the end of the query
ON DELETE CASCADE ON UPDATE RESTRICT
This could also be a different fields error so check if the table key and the foreign key are of the same type and have the same atributes.
I had the same problem, too. When checking the definition of the fields, I noticed that one field was defined as INT and the other as BIGINT. After changing the BIGINT type to INT, I was able to create my foreign key.

Resources