I'm freaking out. I work at a company that (incredibly stupidly) doesn't back up their MySQL database. I had to change one of the columns in a table "items" in order to raise the max character count for an item's description. I used the following command:
ALTER TABLE items CHANGE description description varchar(5000) NOT NULL;
But, after I entered this command, I got this error:
Error on rename of './company/#sql-b30_400ad' to './company/items' (errno: 150 - Foreign key constraint is incorrectly formed)
Now, the table is completely gone. Is there a way to access the "#sql-b30_400ad" table to recover it? I know there was a key removed from this table with the following method:
SET foreign_key_checks = 0;
ALTER TABLE items DROP KEY foreign_key_name;
SET foreign_key_checks = 1;
Is there any way to undo what happened, or to recover the temporary items table that was created for the ALTER command?
EDIT: The table uses the InnoDB engine
EDIT AGAIN: So I found out that since we use Amazon Web Service for our MySQL Server, AWS automatically backs it up daily, the last backup being conveniently 15 minutes before my error. My pants are brown and yellow now, but all is good and I extend my thanks to everyone who answered!
You can read documentation about the command :
check
repair
and the tool
mysqlcheck
myisamchk
...
My advice : But first of all if data are very important, for safety reason you may have to stop any read/write process on the disk, and may be stop the disk.
In future : Always make your own backup before any modification, even for these repair/check commands
mysqldump
mysqlhotcopy
check this
http://www.thegeekstuff.com/2014/04/recover-innodb-mysql/
Is it production DB or Development DB, I would not worry if it is development,
Check out unDROP tool for InnoDB. It allows to read records directly from InnoDB tablespace.
#sql-b30_400ad is a file with the new structure. So, split it with stream_parser and then extract records with c_parser. See https://twindb.com/undrop-tool-for-innodb/ , your case fits pretty well into the description.
Related
I have database with 300 tables without primary key, currently i want to add add primary key to the table with auto increment value because i am not able to edit or delete any data through MYSQL PHPMYADMIN. I know its possible, but it consist of billions of data.
Is there any problem for adding new primary key to all tables those tables not having primary key currently?.
Is there any issues will effect to existing queries written previously?.
What is best way to do it without effecting any ongoing process in live server?.
Is it possible to edit or delete sql table rows without adding primary key in the live server without effecting ongoing process in live server?. Please help me out.
Is there any problem for adding new primary key to all tables those tables not having
Is there any issues will effect to existing queries written previously?.primary key currently?
You can add the PK. But if your queries are build like
SELECT *
Then you will have an extra column and that may broke your other systems.
What is best way to do it without effecting any ongoing process in live server?.
You have to do it in a test server first.
Is it possible to edit or delete sql table rows without adding primary key in the live server without effecting ongoing process in live server?
If you have some process running they may have table lock so the table updates cant happen. That is why you should schedule a downtime for maintenance where you can do the changes. And as I said before you have to plan and test everything on the test server first.
I've downloaded a project from internet, that is supposed to let me draw some polygons, points and so on on the map, then save it on the PostgreSQL database. You can also upload KML files to show already drawn points,polygons, etc - that doesn't work as well.
The project is using PostGis + GeoServer.
The problem is, I don't know how to enable database in it to save the coordinates.
So far I did:
1)Install PostgreSQL
2)Install PostGis
3)Install GeoServer
4)Install WAMP
5)Create database called 'parking'
6) In the 'parking' I've run SQL queries like this :
-- After creating database
CREATE EXTENSION postgis;
-- CREATE SEQUENCE FOR TABLE parking_spaces
CREATE SEQUENCE public.sq_parking_spaces
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- TABLE parking_spaces
CREATE TABLE public.parking_spaces
(
id integer NOT NULL DEFAULT nextval('sq_parking_spaces'::regclass),
name character varying(80),
paid boolean,
spaces integer,
geometry geometry(Polygon,3857),
CONSTRAINT parking_spaces_pkey PRIMARY KEY (id)
)
-- CREATE SEQUENCE FOR TABLE parking_meters
CREATE SEQUENCE public.sq_parking_meters
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- TABLE parking_meter
CREATE TABLE public.parking_meters
(
id integer NOT NULL DEFAULT nextval('sq_parking_meters'::regclass),
name character varying(80),
geometry geometry(Point,3857),
CONSTRAINT parking_meters_pkey PRIMARY KEY (id)
)
What should be my next goal? How do I check the tables, using PgAdmin?
EDIT:
The question is how to properly connect PostgreSQL database to GeoServer? And how to give GeoServer full write access to layers?
In continuation to the links shared above, here are the generic steps to ensure that the configuration works well:
Make sure that WAMP is installed successfully and is working.
PostgreSQL is installed successfully and that you're able to run the queries using an admin interface.
Create a new user (who doesn't necessarily have to be a superuser):
https://www.postgresql.org/docs/9.1/static/app-createuser.html
GRANTpermissions for SELECT, INSERT, UPDATE and DELETE for this new user on your database: https://www.postgresql.org/docs/9.0/static/sql-grant.html
In the context of this particular problem, add Service Level Security for the application: http://docs.geoserver.org/stable/en/user/security/service.html
Ensure that you have the write access for the Layers. In loose terms, there will have to be one layer in Geoservices per table in the DB: http://docs.geoserver.org/stable/en/user/security/layer.html
Finally, when attempting to invoke WFS calls to the Services, the parameters in your jQuery must be set as described at the following link: https://gis.stackexchange.com/questions/21251/how-to-initialize-a-wfs-layer
Hope that helps.
From your commands above it doesn't appear as if you have added the geometry column to the geometry_columns table - use the AddGeometryColumn statement to do this.
The next thing to try is to work through the GeoServer tutorial on PostGIS.
To take the backup I follow the below procedure.
First I take the list of table in my DB using SHOW TABLES LIKE
Then take table structure using SHOW CREATE TABLE
Then Saving all table structure and its value in to the file.
Now Backup works fine.
While restoring I am facing the problem.
If some of tables contain foreign key constraint with reference of other table.
I am not able to create the table.
I found the problem because I am taking backup table by table .
For example there are 4 table
A,B,C,D
A - Contain Constraint with C
C - Contain constraint with D.
I Take the backup above table and store them into file like this order
A,B,C,D. while Restoring causing error.
My question is How to handle while backup the database if table contain constraints?
I searched lot but I was not able to get good solution. So, Please share how to do this or share if I any thing done wrong.
Thank you.
As for the update to this question, I temporarily disabled the key check now it's worked. this solution posted in this question
http://stackoverflow.com/questions/15501673/how-to-temporarily-disable-a-foreign-key-constraint-in-mysql
SET FOREIGN_KEY_CHECKS=1;
We have an automatic car plate reader which records plates of the cars enter to firm. My colleague asked me if we can instantly get the plate number of the car coming. The software uses MySQL and I have only database access. Cannot reach/edit PHP codes.
My offer is to check using a query periodically. For example for 10 seconds. But in this way it is possible to miss the cars coming in 5 seconds. Then decreasing interval increases request/response count which means extra load for the server. I do not want the script to run always. It should run only a new db row added. It shows the plate and exits.
How can I get last recorded row from the db right after inserting? I mean there should be trigger which runs my PHP script after insertion. But I do not know.
What I want is MySQL could run my PHP script after a new record.
If your table is MyISAM, I would stick to your initial idea. Getting the row count from a MyISAM table is instant. It only takes the reading of one single value as MyISAM maintains the row count at all times.
With InnoDB, this approach can still be acceptable. Assuming car_table.id is primary key, SELECT COUNT(id) FROM car_table only requires an index scan, which is very fast. You can improve on this idea by adding another indexed boolean column to your table:
ALTER car_table ADD COLUMN checked BOOLEAN NOT NULL DEFAULT 0, ADD INDEX (checked);
The default value ensures new cars will be inserted with this flag set to 0 without modifying the inserting statement. Then:
BEGIN TRANSACTION; -- make sure nobody interferes
SELECT COUNT(checked) FROM car_table WHERE checked = FALSE FOR UPDATE; -- this gets you the number of new, unchecked cars
UPDATE car_table SET checked = TRUE WHERE checked = FALSE; -- mark these cars as checked
COMMIT;
This way, you only scan a very small number of index entries at each polling.
A more advanced approach consists in adding newly created cars ID's into a side table, through a trigger. This side table is scanned every now and then, without locking the main table, and without altering its structure. Simply TRUNCATE this side table after each polling.
Finally, there is the option of triggering a UDF, as suggested by Panagiotis, but this seems to be an overkill in most situations.
Although this is not the greatest of designs and I have not implemented it, there is way to call an external script through sys_exec() UDF using a trigger as mentioned here:
B.5.11: Can triggers call an external application through a UDF?
Yes. For example, a trigger could invoke the sys_exec() UDF.
http://dev.mysql.com/doc/refman/5.1/en/faqs-triggers.html#qandaitem-B-5-1-11
Also have a look on this thread which is similar to your needs.
Invoking a PHP script from a MySQL trigger
This seems to be a simple problem, but after a while of searching I can't figure out the answer.
I currently have a MySQL table in my local database used by a webapp, and them same table on a database in a remote server. Right now, I'm using the CREATE TABLE IF NOT EXISTS command through PHP to create the table on the databases:
CREATE TABLE IF NOT EXISTS users (
`id` int(10) NOT NULL AUTO_INCREMENT,
`username` varchar(18) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
However, let's say I make a modification to the local database, adding a collumn, for example. It would be really annoying to have to go and change the remote database every time I change the local one. Is there an easier way to run code to create a table if it doesn't exist, and if it does exist, make sure it's structure matches that of the create table structure?
Here's an example, to make what I'm trying to convey a little clearer. Let's say on the local database I have a users table, and I decide that in my webapp I want to have another collumn, password. So I go to the local database and add a password collumn. Is there PHP/MySQL code I can run to check if the users table exists, and if it does, make sure it has a password collumn, and if not, add it?
What you are actually looking for are Migrations, e.g. you are looking for a Schema Management Tool that lets you manage your Database structure in versioned code diffs.
For instance, for your described scenario you would first create a script to create the table, e.g. 001_create_user_table.sql. Then you'd use the schema manager to connect and deploy these changes to your databases.
When you want to change or add something, you just write another script, for instance, 002_Add_Password_Column_To_User_Table.sql. Fill in just the code to do that change. Then run the schema manager again.
Typically, you tell the Schema Manager to go through all existing migrations files. On each run, the Schema manager will update a changelog table in the database, so when you run it, it will know which of your scripts it should apply.
The good thing is, you can add these migrations to your regular VCS, so you will always know which database schema you had at which version of your application. And you will have a proper changelog for them.
To directly answer your question you can create temporary procedures to detect field existence like using a query like this:
SHOW COLUMNS FROM table_name LIKE 'column_name';
However in the real world, database changes are general rolled into three scripts. A create script and two deltas one up and one down. Then the database is versioned so that you know at what state the database is in at any given time.
To specifically check for a password column you can use DESCRIBE:
$colExists = false;
$res = mysql_query('DESCRIBE `users`');
while ($row = mysql_fetch_assoc($res)) {
if ($row['Field'] == 'password') {
$colExists = true;
break;
}
}
if (!$colExists) {
// create column
}
However, you should check into replication or some other automated tool to see if they would be a better solution for you.
Follow these steps (you can easily implement this in PHP, I assumed that the name of the table is Foo)
1.) Run the following code:
desc Foo
2.) Based on the result of the first step you can make your create table command (and you should)
3.) Store your data from the existing table which will be replaced in a variable (Optional, you only need this if you can potentially use data from the old table)
4.) Modify the extracted rows from step 3.) so they will be compatible with your new definition (Optional, you only need this if you can potentially use data from the old table)
5.) Get the rows from your new Foo table
6.) Merge the results got in steps 4.) an 5.) (Optional, you only need this if you can potentially use data from the old table)
7.) Run a drop table for the old table
8.) Generate a replace into command to insert all your rows into the newly created Foo table (you can read more about this here)
After these steps, as a result, you will have the new version of the table. If your tables are too large, you can do a CREATE TABLE IF NOT EXISTS command and if that was not successful, run the alter command.
Also, you can make a library to do these steps and will use that in the future instead of solving the same problem several times.
EDIT:
You can connect the database using this function: mysql-connect (documentation here)
You can run a query using this function: mysql-query (documentation here)
Based on the first step you will get the field names (let's assume you store it in a variable called $bar) and you can use your result to generate your select command (connecting to the database where you have important data. It may be both):
$field_list = "1";
foreach ($bar as $key => $value)
$field_list.= ",".$bar[$key];
mysql_connect(/*connection data*/);
mysql_query("select ".$field_list." from Foo");
You can use your new resource to build up an insert command to insert all your important data after deletion recreation (about resources read more here, about how you can generate your insert you can read here, but I suggest that you should use replace into instead of insert which works like the insert, except that it replaces the row if it already exists, it's better here than an insert, read more here)
So, use mysql_connect and mysql_query, and the resource returned by the mysql_query function can be used for replace into later (I've linked now the URL's for everything you need, so I'm pretty sure you'll solve the problem.), apologies for being not specific enough before.