Accidentally specified weird sql query. What happened? - mysql

I ran this sql query in my database:
update payments set method = 'paysafecard' AND amount = 25 WHERE payment_id IN (1,2,3,4,5,...)
Of course i meant set method = 'paysafecard' , amount = 25
However I did it in phpmyadmin and it showed me that rows were affected. After running it again it showed 0 rows affected.
I don't know what may have changed in the database, what could this have done?
My table looks like this:
CREATE TABLE IF NOT EXISTS `payments` (
`payment_id` int(11) NOT NULL AUTO_INCREMENT,
`method_unique_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`method` enum('moneybookers','paypal','admin','wallet','voucher','sofortueberweisung','bitcoin','paysafecard','paymentwall') COLLATE utf8_unicode_ci NOT NULL,
`method_tid` int(11) DEFAULT NULL,
`uid` int(11) NOT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`plan` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`expires_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`amount` decimal(8,2) NOT NULL,
`currency` enum('EUR','USD','BTC') COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`payment_id`),
UNIQUE KEY `method` (`method`,`method_tid`),
UNIQUE KEY `method_unique_id` (`method_unique_id`,`method`),
KEY `expires_at` (`expires_at`),
KEY `uid` (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8030 ;
I am running
-- Server version: 5.1.41
-- PHP Version: 5.3.2-1ubuntu4.11

This would result in the method field being set to '0' for all of your records fitting the where clause.
It is interpreted as the following:
set method = ('paysafecard' AND amount = 25)
This is a logical AND, and results in a boolean value for these records(which will be parsed to the corresponding field of your column).

Related

Long running Mysql Query on Indexes and sort by clause

I have a very long running MySql query. The query simply joins two tables which are very huge
bizevents - Nearly 34 Million rows
bizevents_actions - Nearly 17 million rows
Here is the query:
select
bizevent0_.id as id1_37_,
bizevent0_.json as json2_37_,
bizevent0_.account_id as account_3_37_,
bizevent0_.createdBy as createdB4_37_,
bizevent0_.createdOn as createdO5_37_,
bizevent0_.description as descript6_37_,
bizevent0_.iconCss as iconCss7_37_,
bizevent0_.modifiedBy as modified8_37_,
bizevent0_.modifiedOn as modified9_37_,
bizevent0_.name as name10_37_,
bizevent0_.version as version11_37_,
bizevent0_.fired as fired12_37_,
bizevent0_.preCreateFired as preCrea13_37_,
bizevent0_.entityRefClazz as entityR14_37_,
bizevent0_.entityRefIdAsStr as entityR15_37_,
bizevent0_.entityRefIdType as entityR16_37_,
bizevent0_.entityRefName as entityR17_37_,
bizevent0_.entityRefType as entityR18_37_,
bizevent0_.entityRefVersion as entityR19_37_
from
BizEvent bizevent0_
left outer join BizEvent_actions actions1_ on
bizevent0_.id = actions1_.BizEvent_id
where
bizevent0_.createdOn >= '1969-12-31 19:00:01.0'
and (actions1_.action <> 'SoftLock'
and actions1_.targetRefClazz = 'com.biznuvo.core.orm.domain.org.EmployeeGroup'
and actions1_.targetRefIdAsStr = '1'
or actions1_.action <> 'SoftLock'
and actions1_.objectRefClazz = 'com.biznuvo.core.orm.domain.org.EmployeeGroup'
and actions1_.objectRefIdAsStr = '1')
order by
bizevent0_.createdOn;
Below are the table definitions -- As you see i have defined the indexes well enough on these two tables on all the search columns plus the sort column. But still my queries are running for very very long time. Appreciate any more ideas either with respective indexing.
-- bizevent definition
CREATE TABLE `bizevent` (
`id` bigint(20) NOT NULL,
`json` longtext,
`account_id` int(11) DEFAULT NULL,
`createdBy` varchar(50) NOT NULL,
`createdon` datetime(3) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
`iconCss` varchar(50) DEFAULT NULL,
`modifiedBy` varchar(50) NOT NULL,
`modifiedon` datetime(3) DEFAULT NULL,
`name` varchar(255) NOT NULL,
`version` int(11) NOT NULL,
`fired` bit(1) NOT NULL,
`preCreateFired` bit(1) NOT NULL,
`entityRefClazz` varchar(255) DEFAULT NULL,
`entityRefIdAsStr` varchar(255) DEFAULT NULL,
`entityRefIdType` varchar(25) DEFAULT NULL,
`entityRefName` varchar(255) DEFAULT NULL,
`entityRefType` varchar(50) DEFAULT NULL,
`entityRefVersion` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDXk9kxuuprilygwfwddr67xt1pw` (`createdon`),
KEY `IDXsf3ufmeg5t9ok7qkypppuey7y` (`entityRefIdAsStr`),
KEY `IDX5bxv4g72wxmjqshb770lvjcto` (`entityRefClazz`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- bizevent_actions definition
CREATE TABLE `bizevent_actions` (
`BizEvent_id` bigint(20) NOT NULL,
`action` varchar(255) DEFAULT NULL,
`objectBizType` varchar(255) DEFAULT NULL,
`objectName` varchar(255) DEFAULT NULL,
`objectRefClazz` varchar(255) DEFAULT NULL,
`objectRefIdAsStr` varchar(255) DEFAULT NULL,
`objectRefIdType` int(11) DEFAULT NULL,
`objectRefVersion` int(11) DEFAULT NULL,
`targetBizType` varchar(255) DEFAULT NULL,
`targetName` varchar(255) DEFAULT NULL,
`targetRefClazz` varchar(255) DEFAULT NULL,
`targetRefIdAsStr` varchar(255) DEFAULT NULL,
`targetRefIdType` int(11) DEFAULT NULL,
`targetRefVersion` int(11) DEFAULT NULL,
`embedJson` longtext,
`actions_ORDER` int(11) NOT NULL,
PRIMARY KEY (`BizEvent_id`,`actions_ORDER`),
KEY `IDXa21hhagjogn3lar1bn5obl48gll` (`action`),
KEY `IDX7agsatk8u8qvtj37vhotja0ce77` (`targetRefClazz`),
KEY `IDXa7tktl678kqu3tk8mmkt1mo8lbo` (`targetRefIdAsStr`),
KEY `IDXa22eevu7m820jeb2uekkt42pqeu` (`objectRefClazz`),
KEY `IDXa33ba772tpkl9ig8ptkfhk18ig6` (`objectRefIdAsStr`),
CONSTRAINT `FKr9qjs61id11n48tdn1cdp3wot` FOREIGN KEY (`BizEvent_id`) REFERENCES `bizevent` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;>
By the way we are using Amazon RDS 5.7.33 MySql version. 16 GB RAM and 4 vCPU.
I also did a Explain Extended on the query and below is what it shows. Appreciate any help.
Initially the search of the bizevent_actions didn;t have the indexes defined. I have defined the indexes for them and tried the query but of no use.
One technique that worked for me in a similar situation was abandoning the idea of JOIN completely and switching to queries by PK. More detailed: find out which table in join would give less rows on average if you use only that table and related filter to query; get the primary keys from that table and then query the other one using WHERE pk IN ().
In your case one example would be:
SELECT
bizevent0_.id as id1_37_,
bizevent0_.json as json2_37_,
bizevent0_.account_id as account_3_37_,
...
FROM BizEvent bizevent0_
WHERE
bizevent0_.createdOn >= '1969-12-31 19:00:01.0'
AND bizevent0_.id IN (
SELECT BizEvent_id
FROM BizEvent_actions actions1_
WHERE
actions1_.action <> 'SoftLock'
and actions1_.targetRefClazz = 'com.biznuvo.core.orm.domain.org.EmployeeGroup'
and actions1_.targetRefIdAsStr = '1'
or actions1_.action <> 'SoftLock'
and actions1_.objectRefClazz = 'com.biznuvo.core.orm.domain.org.EmployeeGroup'
and actions1_.objectRefIdAsStr = '1')
ORDER BY
bizevent0_.createdOn;
This assumes that you're not actually willing to select 33+ Mio rows from BizEvent though - your code with LEFT OUTER JOIN would have done exactly this.

Why do this query takes more than 180 secs to run?

CREATE TABLE `tvnotif` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pingId` int(11) DEFAULT NULL,
`token` varchar(45) COLLATE utf8_bin DEFAULT NULL,
`summary` varchar(45) COLLATE utf8_bin DEFAULT NULL,
`startTime` int(11) DEFAULT NULL,
`endTime` int(11) DEFAULT NULL,
`processed` int(1) DEFAULT '0',
`created` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `processedIndex` (`processed`),
KEY `summaryIndex` (`summary`),
KEY `tokenIndex` (`token`)
) ENGINE=InnoDB AUTO_INCREMENT=18297898 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE `vv_us` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`athleteid` int(11) DEFAULT NULL,
`token` varchar(45) COLLATE utf8_bin DEFAULT NULL,
`secret` varchar(45) COLLATE utf8_bin DEFAULT NULL,
`active` int(1) DEFAULT '1',
`created` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`type` varchar(45) COLLATE utf8_bin DEFAULT 'mc',
`step` varchar(45) COLLATE utf8_bin DEFAULT NULL,
`host` varchar(45) COLLATE utf8_bin DEFAULT NULL,
`server` mediumblob,
`tempcreds` mediumblob,
PRIMARY KEY (`id`),
KEY `activeIndex` (`active`),
KEY `typeIndex` (`type`)
) ENGINE=InnoDB AUTO_INCREMENT=33888 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
I am running a query which is mostly based on the table tvnotif which has at least 2 million rows of data in it, all the other tables are having less amount only. I added the index for the tables before that the query took 20 minutes to run and now its taking 160 secs.
EXPLAIN SELECT tvu.secret,COALESCE(php_timezone,"America/Los_Angeles") AS userTz,tn.*,tvu.athleteid,tvu.type FROM tvnotif AS tn
LEFT JOIN vv_us AS tvu ON tvu.token = tn.token
LEFT JOIN tbl_ath_pro AS tap ON tap.athleteid = tvu.athleteid
LEFT JOIN timezones AS tz ON tz.tz_id = tap.tz_id
WHERE tvu.active = 1 AND tn.summary = 'dailies' AND tn.processed = 0
LIMIT 300
The problem is probably your indexes... You have indexes on each field individually. What you need is a composite index on ALL 3 parts as a single index. Without, it can't pick the best one as you have 3 parts of the where clause.
Build a SINGLE index on ( processed, summary, token )
This way the query can jump directly to the processed records, directly to the summary value and then get those records and be done.
Additionally, your VV_US table should have an index on ( token, active ) so the join will be optimized on BOTH parts.

MySql - Error Code: 1932. Table doesn't exist in engine

I am getting the error below on a mysql restart after adding an enum field to my existing table. Locks table and only a complete database restore fixes issue as I can't drop the table either.
Error Code: 1932. Table 'users' doesn't exist in engine
My table and data is as follows:
CREATE TABLE `users` (
`id` char(36) NOT NULL,
`name` varchar(191) NOT NULL,
`email` varchar(191) NOT NULL,
`password` varchar(191) NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users_email_unique` (`email`)
);
INSERT INTO `users` VALUES
(
'11111111-1111-1111-1111-111111111111',
'John Doe',
'user#email.com',
'password',
NOW(),
NOW()
);
Table above works until line below is executed and mysql is restarted.
ALTER TABLE users ADD `role` enum('test1', 'test2') AFTER `password`
I have also done a diff on the table structure of a before and after. Only line with comment gets added and locks the table.
CREATE TABLE `users2` (
`id` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`role` enum('test1','test2') COLLATE utf8mb4_unicode_ci DEFAULT NULL, -- only diff
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users1_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
This is where it gets weird. Line below adds role to the end of the table and doesn't lock the table.
ALTER TABLE users ADD `role` enum('test1', 'test2'); -- AFTER `password`
Seems the AFTER is the issue. Doesn't matter if I try a different position.
Any suggestions would be appreciated.
You can also assign the default value while adding the column.
ALTER TABLE users ADD `role` enum('test1', 'test2') DEFAULT 'test1' AFTER `password`;
So, NULL values will not allow and all the rows will be assigned with 'test1'.

data too long for this column mysql error

Here's my query:
update slcm.m_user_master set Is_Active = '1' where M_USER_ID = '1'
while updating table it showing message data too long for this column .
I have taken database IsActive database as bit.
this is table description
e Table
CREATE TABLE `m_user_master` (
`M_USER_ID` int(11) NOT NULL AUTO_INCREMENT,
`User_Type_ID` int(11) DEFAULT NULL,
`M_User_Name` varchar(50) DEFAULT NULL,
`M_User_Name_Hindi` varchar(50) DEFAULT NULL,
`User_Login_ID` varchar(30) DEFAULT NULL,
`User_Password` varchar(30) DEFAULT NULL,
`User_Mobile_No` int(12) DEFAULT NULL,
`User_Email_ID` varchar(50) DEFAULT NULL,
`Created_Date` datetime DEFAULT NULL,
`Updated_By` varchar(50) DEFAULT NULL,
`Updated_Date` datetime DEFAULT NULL,
`Is_Active` char(1) DEFAULT NULL,
`Active_From` datetime DEFAULT NULL,
`Active_To` datetime DEFAULT NULL,
`Created_By` varchar(50) DEFAULT NULL,
PRIMARY KEY (`M_USER_ID`),
KEY `FK_M_User_Master_M_User_Type_Master` (`User_Type_ID`),
CONSTRAINT `FK_M_User_Master_M_User_Type_Master` FOREIGN KEY (`User_Type_ID`) REFERENCES `m_user_type_master` (`User_Type_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8
Try the value for Is_Active without quotes like so:
update slcm.m_user_master set Is_Active = 1 where M_USER_ID = '1'
It's expecting a true/false (1/0) value which takes a single bit to store for Is_Active and it's getting a string instead which takes a byte or 8 bits to store. Hence the "too long" error.
update slcm.m_user_master set Is_Active = 1 where M_USER_ID = 1
and you can see this :
Return Bit Value as 1/0 and NOT True/False in SQL Server

Mysql: How to get a result for each day in between an start and an end date from a table that contains also a start and an end date?

I have a start date and an end date. For each day between start and end date I like to get a result, even if there are no results within my stats table.
The best suggestion to solve this is a stored procedure what creates a temporary table for each date (day) so that I could create a join.
BEGIN
declare d datetime;
create temporary table joindates (d date not null);
SET d = fkstartdate;
WHILE d <= fkenddate DO
insert into joindates (d) values (d);
set d = date_add(d, interval 1 day);
END WHILE;
SELECT * FROM `joindates` AS tempt LEFT JOIN `radacct` AS stats
ON stats.acctstarttime <= tempt.d AND (stats.acctstoptime >= tempt.d OR stats.acctstoptime IS NULL) AND calledstationid = calledstationid
ORDER BY tempt.d ASC;
drop temporary table joindates;
END
The join is not finalized now (just for testing). But as you see, the join would be perfect if the "radacct" table would use just one date col. Than I could easily create a JOIN by using the = operator for ON.
Now the "radacct" however is using acctstarttime and acctstoptime for there entries (I can not modify this table, is given by the radius server) both are datetime types.
So in my query I need all entries between my start and stop date where acctstarttime has started in the past or within my time period. And acctstoptime is within my time period, after my time period or NULL (active session).
The problem with my JOIN solution: Its slow as hell
Do you may have any faster query ideas please?
Thanks
Appendix1: It is very important that I get a result for each entry on each day that matches my period of days, even if acctstarttime to acctstoptime goes over multiple days. So that I always get all users online.
Appendix2:
As requested, the full table structure of "radacct" – the accounting table of the freeradius MySql module …
CREATE TABLE `radacct` (
`radacctid` bigint(21) NOT NULL AUTO_INCREMENT,
`acctsessionid` varchar(64) NOT NULL DEFAULT '',
`acctuniqueid` varchar(32) NOT NULL DEFAULT '',
`username` varchar(64) NOT NULL DEFAULT '',
`groupname` varchar(64) NOT NULL DEFAULT '',
`realm` varchar(64) DEFAULT '',
`nasipaddress` varchar(15) NOT NULL DEFAULT '',
`nasportid` varchar(15) DEFAULT NULL,
`nasporttype` varchar(32) DEFAULT NULL,
`acctstarttime` datetime DEFAULT NULL,
`acctstoptime` datetime DEFAULT NULL,
`acctsessiontime` int(12) unsigned DEFAULT NULL,
`acctauthentic` varchar(32) DEFAULT NULL,
`connectinfo_start` varchar(50) DEFAULT NULL,
`connectinfo_stop` varchar(50) DEFAULT NULL,
`acctinputoctets` bigint(20) DEFAULT NULL,
`acctoutputoctets` bigint(20) DEFAULT NULL,
`calledstationid` varchar(50) NOT NULL DEFAULT '',
`callingstationid` varchar(50) NOT NULL DEFAULT '',
`acctterminatecause` varchar(32) NOT NULL DEFAULT '',
`servicetype` varchar(32) DEFAULT NULL,
`framedprotocol` varchar(32) DEFAULT NULL,
`framedipaddress` varchar(15) NOT NULL DEFAULT '',
`acctstartdelay` int(12) unsigned DEFAULT NULL,
`acctstopdelay` int(12) unsigned DEFAULT NULL,
`xascendsessionsvrkey` varchar(10) DEFAULT NULL,
PRIMARY KEY (`radacctid`),
UNIQUE KEY `acctuniqueid` (`acctuniqueid`),
KEY `username` (`username`),
KEY `framedipaddress` (`framedipaddress`),
KEY `acctsessionid` (`acctsessionid`),
KEY `acctsessiontime` (`acctsessiontime`),
KEY `acctstarttime` (`acctstarttime`),
KEY `acctstoptime` (`acctstoptime`),
KEY `nasipaddress` (`nasipaddress`)
) ENGINE=InnoDB AUTO_INCREMENT=2041894 DEFAULT CHARSET=latin1