mysql lock tables causing certain inserts to fail randomly - php

I recently adding locking to a query to prevent a deadlock. This problem is solved, but now I am having a problem where inserts into one table are randomly failing with no cause. I
I have turned on the general query log to see exactly what is happening. Is there any other way to debug this to see exactly what is happening or have any ideas of the cause?
If I perform the following lock:
$this->db->query('LOCK TABLES '.$this->db->dbprefix('customers').' WRITE, '.$this->db->dbprefix('sales').' WRITE,
'.$this->db->dbprefix('store_accounts').' WRITE, '.$this->db->dbprefix('sales_payments').' WRITE, '.$this->db->dbprefix('sales_items').' WRITE,
'.$this->db->dbprefix('giftcards').' WRITE, '.$this->db->dbprefix('location_items').' WRITE,
'.$this->db->dbprefix('inventory').' WRITE, '.$this->db->dbprefix('sales_items_taxes').' WRITE,
'.$this->db->dbprefix('sales_item_kits').' WRITE, '.$this->db->dbprefix('sales_item_kits_taxes').' WRITE,'.$this->db->dbprefix('people').' READ,'.$this->db->dbprefix('items').' READ
,'.$this->db->dbprefix('employees_locations').' READ,'.$this->db->dbprefix('locations').' READ, '.$this->db->dbprefix('items_tier_prices').' READ
, '.$this->db->dbprefix('location_items_tier_prices').' READ, '.$this->db->dbprefix('items_taxes').' READ, '.$this->db->dbprefix('item_kits').' READ
, '.$this->db->dbprefix('location_item_kits').' READ, '.$this->db->dbprefix('item_kit_items').' READ, '.$this->db->dbprefix('employees').' READ , '.$this->db->dbprefix('item_kits_tier_prices').' READ
, '.$this->db->dbprefix('location_item_kits_tier_prices').' READ, '.$this->db->dbprefix('location_items_taxes').' READ
, '.$this->db->dbprefix('location_item_kits_taxes'). ' READ, '.$this->db->dbprefix('item_kits_taxes'). ' READ');
foreach($items as $line=>$item)
{
if (isset($item['item_id']))
{
$cur_item_info = $this->Item->get_info($item['item_id']);
$sales_items_data = array
(
'sale_id'=>$sale_id,
'item_id'=>$item['item_id'],
'line'=>$item['line'],
'description'=>$item['description'],
'serialnumber'=>$item['serialnumber'],
'quantity_purchased'=>$item['quantity'],
'discount_percent'=>$item['discount'],
'item_cost_price' => $cur_item_info->cost_price,
'item_unit_price'=>$item['price']
);
$this->db->insert('sales_items',$sales_items_data);
}
...
...
}
$this->db->query('UNLOCK TABLES');
Table:
+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_sales_items | CREATE TABLE `phppos_sales_items` (
`sale_id` int(10) NOT NULL DEFAULT '0',
`item_id` int(10) NOT NULL DEFAULT '0',
`description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`serialnumber` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`line` int(3) NOT NULL DEFAULT '0',
`quantity_purchased` decimal(23,10) NOT NULL DEFAULT '0.0000000000',
`item_cost_price` decimal(23,10) NOT NULL,
`item_unit_price` decimal(23,10) NOT NULL,
`discount_percent` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`sale_id`,`item_id`,`line`),
KEY `item_id` (`item_id`),
CONSTRAINT `phppos_sales_items_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `phppos_items` (`item_id`),
CONSTRAINT `phppos_sales_items_ibfk_2` FOREIGN KEY (`sale_id`) REFERENCES `phppos_sales` (`sale_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.06 sec)
Then insert into a bunch of tables but randomly I am getting an error where data does NOT make it into sales_items, but correctly makes it into other tables using the item_id foreign key...is there a scenario that can causes inserts to fail randomly because of the locks? I am going to turn on the general query log to see what is happening but I cannot track it down. This never happened before until I added the locking.

Turned out it was related to mysql 5.6 default strict mode setting. Not related to lock

Related

Insert common SQL query along with multiple functions

I'm inserting an SQL Template in a new database through PHP code using the mysqli->multi_query() function. This SQL Template contains something like:
CREATE TABLE `applicants` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_bin NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DELIMITER $$
CREATE FUNCTION `myFunctionExample`(`someField` INT(11), `someOtherField` VARCHAR(255) CHARSET utf8) RETURNS double(10,3)
BEGIN
.... MY SQL ....
RETURN ...;
END;
DELIMITER $$
CREATE FUNCTION `mySecondFunctionExample`(`someField` INT(11), `someOtherField` VARCHAR(255) CHARSET utf8) RETURNS double(10,3)
BEGIN
.... MY SQL ....
RETURN ...;
END;
I have two different problems:
When using PHP:
All the tables are created, no functions are created
When using PHPMyAdmin:
All the tables are created, only the first function is created
So it seems I have a problem separating the functions (?) and somehow mysqli->multi_query() is not creating the functions?
Solved.
With the help of #Uueerdo I end up realizing I might not need any limiters for my functions when creating them through PHP. I also found this thread Execute mysql "create function" statement with PHP that talks about not having to worry about delimiters in PHP.
So I just removed the DELIMITER $$ from my code and made sure I used ; to separate everything:
CREATE TABLE `applicants` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_bin NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE FUNCTION `myFunctionExample`(`someField` INT(11), `someOtherField` VARCHAR(255) CHARSET utf8) RETURNS double(10,3)
BEGIN
.... MY SQL ....
RETURN ...;
END;
CREATE FUNCTION `mySecondFunctionExample`(`someField` INT(11), `someOtherField` VARCHAR(255) CHARSET utf8) RETURNS double(10,3)
BEGIN
.... MY SQL ....
RETURN ...;
END;

Joomla Database import does not work

i made a backup of my joomla MySQL database using the export function of phpMyAdmin.
When i try to import this backup file, it gives me a lot of errors like "You have an error in your SQL syntax..." even if the SQL looks quite correct.
Here is a small part of the backup, which doesnt even work:
CREATE TABLE `jos_assets` (
`id` int(10) UNSIGNED NOT NULL COMMENT 'Primary Key',
`parent_id` int(11) NOT NULL DEFAULT '0'COMMENT AS `Nested set parent.`,
`lft` int(11) NOT NULL DEFAULT '0'COMMENT AS `Nested set lft.`,
`rgt` int(11) NOT NULL DEFAULT '0'COMMENT AS `Nested set rgt.`,
`level` int(10) UNSIGNED NOT NULL COMMENT 'The cached level in the nested tree.',
`name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'The unique name for the asset.\n',
`title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'The descriptive title for the asset.',
`rules` varchar(5120) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'JSON encoded access control.'
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
When i run this command, i get the following error message:
#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 'AS `Nested set parent.`,
`lft` int(11) NOT NULL DEFAULT '0'COMMENT AS `Nested ' at line 3
Can someone explain to me what is wrong here? This code was automatically generated by phpMyAdmin and it looks like valid SQL to me!
Im using:
phpMyAdmin version 4.5.5
PHP version 5.6.14
Server version 10.0.23-MariaDB-0+deb8u1
Joomla version 3.5.0
Ok guys i found out the problem myself:
It seems the line
COMMENT AS `Nested set parent.`,
is no valid SQL. Correct would be
COMMENT 'Nested set parent.',
like you can see in the other lines.
I dont know why phpMyAdmin creates a MySQL Dump with invalid SQL, but this caused the problem.

I have a .sql file and import it but I attempt throws an error which says it esiste the table but I'm just creating the database and table in this way

I have a .sql file and import it but I attempt throws an error which says that the table already exists but I'm just creating the database and table in this way
CREATE DATABASE `bancoproyectos2010` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `bancoproyectos2010`;
CREATE TABLE IF NOT EXISTS `accion` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`id_asun` int(2) DEFAULT NULL,
`id_es` int(2) DEFAULT NULL,
`id_prog` int(3) DEFAULT NULL,
`id_PE` int(3) DEFAULT NULL,
`num_acc` int(3) DEFAULT NULL,
`nombre_Accion` text,
PRIMARY KEY (`id`),
KEY `id_asun` (`id_asun`),
KEY `id_es` (`id_es`),
KEY `id_prog` (`id_prog`),
KEY `id_PE` (`id_PE`),
KEY `num_acc` (`num_acc`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=177 ;
throws me:
MySQL said:
1050 - Table 'bancoproyectos2010.acción' already exists
the database is created from scratch and when it reaches the table creates the .ibd file but does not appear in phpmyadmin but when trying to create a table from phpmyadmin also throws the error that already exists
1050 - Table 'bancoproyectos2010.acción' already exists
You can try this:
DROP TABLE IF EXISTS `accion`
REPAIR TABLE `accion`

PHP & MySQL, Good query is failing

I am having an odd issue with PHP and MySQL.
In attempt to create a table from PHP, I have pasted in the query I need, which executes successfully outside of the PHP environment, into PHP.
$CREATE_PAGES = "DROP TABLE IF EXISTS `MyDatabase`.`pages`;
CREATE TABLE `MyDatabase`.`pages` (
`Page_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Page_File` varchar(1000) NOT NULL,
`Page_Description` varchar(1000) NOT NULL,
`Page_Message` longtext NOT NULL,
PRIMARY KEY (`Page_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;";
$result= mysql_query($CREATE_PAGES,$link);
if(!($result)){
echo mysql_error();
echo $CREATE_PAGES;
}
Then I get the standard error message
. . . for the right syntax to use near 'CREATE TABLE `MyDatabase`.`pages` ( `Page_ID` int(10) unsigned NOT NULL' at line 2
However, the odd part is that when I echo the query $CREATE_PAGES I can copy and paste and it will execute just fine. How can it be a syntax error?
I know that it is not a connection error, I can pull data from another table in that database.
Is there something I am missing?
PHP call to mysql_query allows only one action at the time (as a part of SQL injection prvention I guess) so you have to split your query into two parts and call mysql_query twice.
The mysql_query() function can only execute one query at a time, whereas you can execute an arbitrary number at the command line.
From the documentation:
mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.
To overcome this:
$dropTable = "DROP TABLE IF EXISTS `MyDatabase`.`pages`";
mysql_query($dropTable, $link);
$createPages ="CREATE TABLE `MyDatabase`.`pages` (
`Page_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Page_File` varchar(1000) NOT NULL,
`Page_Description` varchar(1000) NOT NULL,
`Page_Message` longtext NOT NULL,
PRIMARY KEY (`Page_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;";
$result = mysql_query($createPages, $link);
if(!($result)) {
echo mysql_error();
}
From docs to mysql_query:
mysql_query() sends a unique query (multiple queries are not
supported) to the currently active database on the server that's
associated with the specified link_identifier.
mysql_query can only execute a single query, it doesn't support execution of multiple queries. It's also recommended to not end your query with a semicolon.
Look for more information in the PHP documentation.

What's wrong with this PHP-MySQL CREATE TABLE query?

First, I'm just starting to learn MySQL with PHP.
My query copy/paste directly from my IDE:
$query = "CREATE TABLE IF NOT EXISTS $table_messages (
id int(11) unsigned NOT NULL auto_increment,
show tinyint(1) unsigned NOT NULL default '0',
to varchar(255) NOT NULL default '',
from varchar(255) NOT NULL default '',
type varchar(255) NOT NULL default '',
message varchar(255) NOT NULL default '',
PRIMARY KEY(id)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1";
$result = mysql_query( $query, $link ) OR exit ( mysql_error() );
Results in this error:
You have an error in your SQL syntax;
near 'show tinyint(1) unsigned NOT
NULL default '0' , to varchar(255) N'
at line 4
... so I add one character to show (e.g. showz) and get this error:
You have an error in your SQL syntax;
near 'to varchar(255) NOT NULL
default '' , from varchar(255) NOT
NUL' at line 5
... so I add one character to to (e.g. toz) and get this error:
You have an error in your SQL syntax;
near 'from varchar(255) NOT NULL
default '' , type varchar(255) NOT NU'
at line 6
... so I add one character to from (e.g. fromz) and IT WORKS!?
What is going on? Lol
If this question is too blatantly obvious, I'll remove it if the community thinks it would be prudent, but in the meantime I'm stumped.
BTW, I've messed with spacing, case and other things without any success.
SHOW, TO and FROM are reserved MySQL keywords. You must quote them with backticks to make them work as column names:
$query = "CREATE TABLE IF NOT EXISTS $table_messages (
`id` int(11) unsigned NOT NULL auto_increment,
`show` tinyint(1) unsigned NOT NULL default '0' ,
`to` varchar(255) NOT NULL default '' ,
`from` varchar(255) NOT NULL default '' ,
`type` varchar(255) NOT NULL default '' ,
`message` varchar(255) NOT NULL default '' ,
PRIMARY KEY(id)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1";
It's usually good practice (though unneeded) to quote every column name this way to prevent accidental collisions with keywords as there are hundreds of them. For a full list, see http://dev.mysql.com/doc/refman/5.1/en/reserved-words.html.
You might be interested in this list of reserved words in MySQL statements. In short, if you want to use any of these as a column name (or anywhere in following queries), you have to quote them, usually in backticks:
`show` TINYINT(1) UNSIGNED NOT NULL,
...and later:
SELECT `show` FROM `varchar` WHERE `to`="France"
Just a stab in the dark, but are to and from reserved words in mysql? Could you either wrap those words in [] like [to] and [from] or, like you did, change the terms to toperson or fromperson?
This is not the answer to your problem, but it's the answer to "What's wrong with a PHP-MySQL CREATE TABLE query?" (for another googler)
Maybe not all versions of PHP are like this, but in my environment, non PDO commands like "mysql_query" throws an error when I try to make a table:
CREATE TABLE IF NOT EXISTS `actionlog`
Error:
You have an error in your SQL syntax
Works just fine with the PDO adapter.

Categories