Why does insert error 1062 occur, although it should not be? - mysql

Server version: 10.3.22-MariaDB-0+deb10u1 - Debian 10
Table
CREATE TABLE `background` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`data` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '[]',
`priority` tinyint(4) NOT NULL DEFAULT 0,
`time` int(11) NOT NULL DEFAULT 0,
`attempt` int(11) NOT NULL DEFAULT 0,
`status` tinyint(4) NOT NULL DEFAULT 0,
`add` int(11) NOT NULL DEFAULT 0,
`update` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `status` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=2002280000000127419 DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE (`id`)
(PARTITION `d200226` VALUES LESS THAN (2002270000000000000) ENGINE = InnoDB,
PARTITION `d200227` VALUES LESS THAN (2002280000000000000) ENGINE = InnoDB,
PARTITION `d200228` VALUES LESS THAN (2002290000000000000) ENGINE = InnoDB)
Periodically, an error 1062 occurs during insertion
INSERT INTO `background` (`name`, `data`, `priority`, `time`, `status`, `add`) VALUES ('move', '{\"id\":2002280000000000448,\"frame\":18}', 1, 1582840572, 0, 1582840572)
I looked on the Internet, advised innodb_autoinc_lock_mode to change from 1 to 2, but this did not help, errors still occur.
Question: what to do?
Thanks for answers.

MySQL 1062 error is "Duplicate entry for key".
The only unique constrain in your table is PRIMARY KEY (`id`).
I see 2 possible reasons in shown environ:
1) Manual update of id field value (or insert new record with specifying id value). When autoincrement generator gives the value which is already present in the table the error occured.
2) There exists some trigger which fires while inserting, it inserts data into or updates data in some another table, and the values inserted/updated causes some unique constraint violation.
For to select what reason occures in your particular case you must show full text of the error message.

Related

Deadlocks happened when massive inserting executed simultaneously in mysql 5.0

I am using mysql 5.0 and I met some mysql deadlock problems when there were lots of inserts from different session at the same time (We estimated there would be a maximum about 900 insert statements executed in one second).
Here is the error I got:
1213, Deadlock found when trying to get lock; try restarting transaction
Here is one of my failure insert statement:
INSERT `cj_202203qmoh_prize_log` (`user_id`, `lottery_id`, `create_ip`, `flags`, `created_at`, `create_mac`)VALUES('388','58','???.???.???.???','0','2022-04-01 20:00:33','444937f4bc5d5aa8f4af3d96d31dbf61');
My table definition:
CREATE TABLE `cj_202203qmoh_prize_log` (
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL,
`lottery_id` int(10) unsigned default NULL,
`code` int(11) default NULL,
`flags` int(10) unsigned default '0',
`create_ip` varchar(64) NOT NULL,
`create_mac` varchar(255) character set ascii NOT NULL,
`created_at` timestamp NOT NULL default '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY USING BTREE (`id`),
KEY `user_id` USING BTREE (`user_id`,`created_at`),
KEY `user_id_2` USING BTREE (`user_id`,`lottery_id`),
KEY `create_ip` USING BTREE (`create_ip`),
KEY `create_mac` USING BTREE (`create_mac`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
I didn't use transactions at all in my business. Except for the insert statement, the only possible (in fact it's extremely improbable to be executed simultaneously) sql that requires a x-lock executes at the same time is:
UPDATE `cj_202203qmoh_prize_log` SET `code` = ? WHERE `id` = ?;
There are several select statements using index 'user_id' or 'user_id_2' could be executed simultaneously, but they don't need a s-lock.
And same user_id could only be inserted in the same session.
According to my company's policy, I have no privileges to run SHOW ENGINE INNODB STATUS, so I am afraid I could not provide further information.
After I set the transaction level to READ COMMITTED, execute the statement in a transaction and drop both create_ip and create_mac indexes, it seemed this problem have not happened again. But I still couldn't figure out what caused the deadlock.

Foreign key constraint fails but referenced row exists

I'm running MySQL 5.7.21 on Amazon RDS.
I know this question has been asked a thousand times, but I'm getting the issue on a scenario I wouldn't expect, so please read through before downvoting or marking as duplicate.
I'm not restoring the database, just running single INSERT queries, so is not a matter of ordering.
The referenced row does exist on the table; me and my colleagues had it triple checked.
As one might expect, disabling the FK checks with SET foreign_key_checks = 0 does make the query work.
I've seen this happening because of different table charsets, but in this case, both use utf8mb4. Also both have collation set to utf8mb4_general_ci.
This is happening in a production environment, so dropping the tables and recreating them is something I would like to avoid.
Some additional information:
The FK constraint was created AFTER the original tables were already populated.
Here is the relevant portion of the current DDL:
CREATE TABLE `VehicleTickets` (
`id` varchar(50) NOT NULL,
`vehiclePlate` char(7) NOT NULL,
`organizationId` varchar(50) NOT NULL,
`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` timestamp NULL DEFAULT NULL,
`status` varchar(15) NOT NULL DEFAULT 'OPEN',
`description` text NULL DEFAULT NULL,
`ticketInfo` json DEFAULT NULL,
`externalId` varchar(100) GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.externalId'))) VIRTUAL,
`value` decimal(10,2) GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.value'))) VIRTUAL,
`issuedAt` timestamp GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.issuedAt'))) VIRTUAL NOT NULL,
`expiresAt` timestamp GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.expiresAt'))) VIRTUAL NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `VehicleTickets_externalId_unq_idx` (`externalId`,`organizationId`),
KEY `VehicleTickets_vehiclePlate_idx` (`vehiclePlate`),
KEY `VehicleTickets_organizationId_idx` (`organizationId`),
KEY `VehicleTickets_issuedAt_idx` (`createdAt`),
KEY `VehicleTickets_expiresAt_idx` (`expiresAt`),
CONSTRAINT `VehicleTickets_Organizations_fk`
FOREIGN KEY (`organizationId`) REFERENCES `Organizations` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `Organizations` (
`id` varchar(50) NOT NULL,
`name` varchar(100) NOT NULL,
`taxPayerId` varchar(50) DEFAULT NULL,
`businessName` varchar(100) DEFAULT NULL,
`status` varchar(15) NOT NULL DEFAULT 'TESTING',
`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`activatedAt` timestamp NULL DEFAULT NULL,
`assetConfiguration` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
When I run:
select * from VehicleTickets where organizationId not in (
select id from Organizations
);
I get an empty result set.
However, if I run a query like this:
insert into `VehicleTickets` (
`id`,
`createdAt`,
`organizationId`,
`ticketInfo`,
`vehiclePlate`
)
values (
'... application generated id',
'... current date ',
'cjlchoksi01r8nfks3f51kht8', -- DOES EXIST on Organizations
'{ ... some JSON payload }',
'... vehicle plate'
)
This produces the following error:
Cannot add or update a child row: a foreign key constraint fails
(VehicleTickets, CONSTRAINT VehicleTickets_Organizations_fk
FOREIGN KEY (organizationId) REFERENCES Organizations (id))
Additionally, it gives me:
"errno": 1452,
"sqlState": "23000",
I've read through several threads regarding this issue, but couldn't find a similar case.

How can I insert or update if a value is different?

I'm trying to write an SQL query that will set a value to 1 when it updates another column.
Specifically, I want to set my is_patch_file to 1 if the corresponding hash column is changed. If the hash column is NOT changed, it should keep whatever the currently stored is_patch_file value is.
Is this possible?
Table Structure
DROP TABLE IF EXISTS `program_files`;
CREATE TABLE `program_files` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`folder_id` int(10) unsigned NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`path` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`hash` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`enabled` tinyint(1) NOT NULL DEFAULT '1',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`is_patch_file` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `unique_file` (`folder_id`,`name`,`path`,`hash`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SQL Queries
INSERT INTO program_files (folder_id, name, path, hash, is_patch_file, enabled, created_at, updated_at) VALUES (3, 'TestName', 'TestPath', 'TestHash', 0, 1, NOW(), NOW()) ON DUPLICATE KEY UPDATE
is_patch_file=1, #Is Patch file should ONLY be 1 if the hash is different from the original hash...otherwise keep our current value how do I do this?
hash=VALUES(hash),
updated_at=VALUES(updated_at);
INSERT INTO program_files (folder_id, name, path, hash, is_patch_file, enabled, created_at, updated_at) VALUES (3, 'TestName', 'TestPath', 'TestHash2', 0, 1, NOW(), NOW()) ON DUPLICATE KEY UPDATE
is_patch_file=1, #Is Patch file should ONLY be 1 if the hash is different from the original hash...otherwise keep our current value how do I do this?
hash=VALUES(hash),
updated_at=VALUES(updated_at);
You can compare hash to VALUES(hash) before it gets updated, and use that when setting is_patch_file.
ON DUPLICATE KEY UPDATE
is_patch_file = hash != VALUES(hash),
hash = VALUES(hash),
updated_at = VALUES(updated_at)

mySQL trigger? causing Error Code: 1048 Column cannot be null

I have seen similar questions asked but never seen an answer that works for me. I have the following table and trigger definitions...
DROP TRIGGER IF EXISTS c_consumption.newRateHistory;
DROP TABLE IF EXISTS c_consumption.myrate;
DROP TABLE IF EXISTS c_consumption.myratehistory;
USE c_consumption;
CREATE TABLE `myrate` (
`consumerId` varchar(255) DEFAULT NULL,
`durationType` varchar(50) NOT NULL DEFAULT 'DAY',
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`itemId` varchar(50) NOT NULL,
`quantity` double NOT NULL DEFAULT 1.0,
`quantityType` varchar(100) NOT NULL DEFAULT 'GALLON',
`timePeriod` double NOT NULL DEFAULT 1.0,
PRIMARY KEY (`id`),
UNIQUE INDEX `UNIQUE_RATE`
(`itemId` ASC, `consumerId` ASC)
) ENGINE=InnoDB AUTO_INCREMENT=314 DEFAULT CHARSET=utf8;
CREATE TABLE `myratehistory` (
`consumerId` varchar(255) DEFAULT NULL,
`durationType` varchar(50) DEFAULT NULL,
`itemId` varchar(50) NOT NULL,
`quantity` double DEFAULT NULL,
`quantityType` varchar(100) DEFAULT NULL,
`status` varchar(20) NOT NULL DEFAULT 'CREATED',
`timePeriod` double DEFAULT NULL,
`timestamp` DATETIME NULL,
PRIMARY KEY (`itemId`, `consumerId`, `timestamp`)
) ENGINE=InnoDB AUTO_INCREMENT=314 DEFAULT CHARSET=utf8;
CREATE TRIGGER `newRateToHistory`
AFTER INSERT
ON myrate
FOR EACH ROW
INSERT INTO myratehistory
(
consumerId,
durationType,
itemId,
quantity,
quantityType,
status,
timePeriod,
timestamp
)
VALUES(
new.consumerId,
new.durationType,
new.itemId,
new.quantity,
new.quantityType,
'CREATED',
new.timePeriod,
now());
Note that consumerId CAN be null.
Next I run this SQL statement:
INSERT INTO c_consumption.myrate (
consumerId,
durationType,
itemId,
quantity,
quantityType,
timePeriod)
VALUES(
null,
'DAY',
'MyItem',
1.0,
'GALLON',
1.0);
I get the following message:
Error Code: 1048 Column 'consumerId' cannot be null
Obviously I am doing something wrong but I do not know what it is. Any help would be greatly appreciated.
Thanks!
ConsumerId is part of the primary key. No part of the primary key can be null.
Just a guess, why mysql allows a null-able column as part of the primary key I don't know
CREATE TABLE `myratehistory` (
[...]
PRIMARY KEY (`itemId`, `consumerId`, `timestamp`)
Your MySQL server is running in "strict" mode, which throws an error in case like yours are otherwise handled "gracefully" without strict mode.
As of MySQL 5.7.5, the default SQL mode includes STRICT_TRANS_TABLES, which is exactly the cause of your headache.
To change your server's mode, edit your my.cnf (or my.ini if you're running Windows) and set the mode to:
sql-mode=""
Then you must restart your mysql server like this:
service mysql reload
Or directly throw init.d process:
/etc/init.d/mysql reload
Hope it will help you.

SELECT LAST_INSERT_ID() Not working with BIGINT on MySQL 5.6.11

I have a BIGINT field as an auto increment and primary key on a MySQL Innodb table, running MySQL Community Server 5.6.11.
After calling a basic INSERT statement, and then calling SELECT LAST_INSERT_ID(), I'm always returned 0, even though the INSERT statement was sucessful.
Any ideas why this might be happening.
UPDATE: Here is my table definition
CREATE TABLE `Booking` (
`BookingId` bigint(20) NOT NULL AUTO_INCREMENT,
`HotelId` int(11) NOT NULL,
`AgentId` int(11) NOT NULL DEFAULT '0',
`BookedOn` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`LastChangedBy` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`BookingId`)
ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Here is my INSERT statement
INSERT INTO Booking
(
HotelId,
AgentId,
BookedOn,
LastChangedBy
)
VALUES
(
iHotelId,
iAgentId,
NOW(),
0
);
SELECT LAST_INSERT_ID() AS BookingId;