MySql trigger insert new entry with wrong timestamp - mysql

I have an old database with version 5.0.95 (which unfortunately I cannot upgrade).
In this database I have a table clientes_states:
CREATE TABLE `clientes_states` (
`id` int(11) NOT NULL auto_increment,
`client_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1239670 DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED;
For each change of a client state, a new entry is generated. From this reason this table is huge, which makes it complicated to achieve last state of all clients.
In order to access easily the current state of each client, I created the following table, and added a trigger:
CREATE TABLE `actual_clients_states` (
`id` int(11) NOT NULL auto_increment,
`client_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`updated_at` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `client_id` (`client_id`)
) ENGINE=InnoDB AUTO_INCREMENT=21022 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
CREATE TRIGGER clients_states_insert
AFTER INSERT
ON clientes_states FOR EACH ROW
INSERT INTO actual_clients_states (client_id, state_id)
VALUES (new.client_id, new.state_id)
ON DUPLICATE KEY UPDATE state_id=NEW.state_id;
I have two databases, one for testing and one for staging.
From some reason, the updated_at field is updated with wrong date (almost a month ago) on the staging server, but works fine on the testing server.
Any idea what might be the problem?

Related

How to avoid duplicate key error in mysql

I have a problem to get a next sequence id in my code. Though it was a legacy code i have to follow the same. Let me explain the logic which was followed.
CREATE TABLE `emp_seq` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1234 DEFAULT CHARSET=utf8
Above table used to get the next sequence id for the below table. and also emp_seq table will have only one entry for the id.
CREATE TABLE `emp_info` (
`id` BIGINT(8) UNSIGNED NOT NULL,
`name` VARCHAR(128) DEFAULT '',
`active` TINYINT(2) DEFAULT '1',
`level` MEDIUMINT(8) DEFAULT '100',
PRIMARY KEY (`id`),
KEY `level` (`level`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='employee information'
so whenever we trying to insert a new record to emp_info table, we are getting next sequence id from the table emp_seq by using below queries.
INSERT INTO emp_seq () VALUES ();
DELETE FROM emp_seq WHERE id < LAST_INSERT_ID;
Now the problem is, some times because of multiple asynchronous calls in the application, the same increment id has been shared to multiple records and trying to insert in the emp_info table and we are getting below error
"code":"ER_DUP_ENTRY","errno":1062,"sqlMessage":"Duplicate entry 1234 for key
Kindly help me how to resolve the issue.

Mysql Percona crushes the table while trying to create a unique index on fields where there is a generated one

CREATE TABLE tasks (
`user_id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(255) NOT NULL,
`code` VARCHAR(255) NOT NULL,
`params` JSON,
`hash` VARCHAR(32) GENERATED ALWAYS AS (MD5(`params`)),
`created_at` TIMESTAMP NULL DEFAULT NULL,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
CONSTRAINT `tasks_user_id_users_id_fk`
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
then i try to add a unique index on user_id and hash, i tried to do it during the table create, but there were a problem with the foreign key, so i decided to do it separately.
ALTER TABLE tasks
ADD UNIQUE INDEX `tasks_user_id_hash_unique_idx` (`user_id`, `hash`);
Then i get strange problem error 1146
Table '<dbname>.tasks' doesn't exist
Since then strange errors
1. I cannot delete it while it exists and i cannot do with it anything, cause it does not exist. After mysql reload I get the table deleted but if i try to create it again:
Error Code: 1813
Tablespace '<dbname>.tasks' exists.
I found the decision for unique field, i simply genereate md5( hash + user_id) UNIQUE. But How can I get rid of that problem which still exists and what is going on. It looks like a BUG in mysql Percona 5.7.14-7
so the right way to create the table
CREATE TABLE tasks (
`user_id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(255) NOT NULL,
`code` VARCHAR(255) NOT NULL,
`params` JSON,
`hash` VARCHAR(32) GENERATED ALWAYS AS (MD5(CONCAT(`params`,`user_id`))) UNIQUE,
`created_at` TIMESTAMP NULL DEFAULT NULL,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
CONSTRAINT `tasks_user_id_users_id_fk`
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
But, again, the question with the ghosts still exists after the first tries!

Partition on existing table with millions of records

I have table name builds it look likes
CREATE TABLE `builds` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`testplan_id` int(10) unsigned NOT NULL DEFAULT '0',
`name` varchar(100) NOT NULL DEFAULT 'undefined',
`creation_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`testplan_id`,`name`),
KEY `testplan_id` (`testplan_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2074288 DEFAULT CHARSET=utf8'
I want to create partitions on build based on creation_ts. I am trying
Alter Table builds PARTITION BY RANGE (TO_DAYS(creation_ts))
( PARTITION p1 values less than (TO_DAYS('2015-05-07'))
in phpMyadmin but it is showing error "unrecognised alter operation";
I am using MYSQL Server version: 5.7.11.

MySQL - how to lock a single row?

My aim is to create a system to book trips. My system is built in MySQL + PHP. I'm using InnoDB as engine in MySQL.
When an user choose which trip he wants to book, I want the ipothetic page "*.php" to lock one of those trip for some times (ex. 10 minutes) and after this time release it.
Which is the best way to lock the trip in the DB?
Notice that I didn't talk about rows or table because I'm asking for the easiest way to implement this kind of feature and I'm not sure if mines is that one. So I've tried to design a table to contain the trips, and look like this:
CREATE TABLE IF NOT EXISTS Trip (
id INT(1) NOT NULL AUTO_INCREMENT,
descr VARCHAR(50) NOT NULL,
quantity INT(2) NOT NULL DEFAULT 10,
PRIMARY KEY (id)
) Engine=InnoDB
This is your Ticket table
CREATE TABLE IF NOT EXISTS Trip (
id INT(1) NOT NULL AUTO_INCREMENT,
descr VARCHAR(50) NOT NULL,
quantity INT(2) NOT NULL DEFAULT 10,
PRIMARY KEY (id)
) Engine=InnoDB
Let me visualize your user table as this ( just for testing )
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` text COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=1 ;
Now You need add an extra table where you can track your users booking order ( Example like this )
CREATE TABLE IF NOT EXISTS `trip_track` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`trip_id` int(11) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=1 ;
Now Every time you insert a booking query you need to insert user_id,ticket_id and timestamp ( You can use date or Mysql's default time stamp )
Then whenever user tries to book any ticket use a Query to check the time difference between current time and the timestamp from the database
That's it! .. see? that's simple :)

MySQL Unique values for 2 or more dates

I'm using a barcode scanner to scan qr codes from tickets for an event, this will be posted to a database with the following structure:
CREATE TABLE IF NOT EXISTS `attendees` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attendeeguid` varchar(32) NOT NULL,
`scanned` int(1) NOT NULL DEFAULT '0',
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `attendeeguid` (`attendeeguid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;
Now this attendeeguid has to be unique, but if an event is 2 or more days, it should be possible to scan this attendeeguid again on another date. How can I do this?
I'm using MySQL and I'm using this in an Objective-C iOS App.