Is MySQL "thread safe" from a php script? - php

If I have a php script which calls INSERT, UPDATE, DELETE, etc on a MySQL connection, and that script gets called at uncontrolled times by a POST operation, is it always "safe" (ie, will not result in corrupt tables or collisions during requests)?
For example, if 500 requests come during a 1-second period.
If so, how does php/mysql achieve this?
If not, what does one need to do to guarantee "serial" access or safe simultaneous access?

MySQL uses locking (table-level for MyISAM or row-level for InnoDB), which does not allow 2 processes (2 calls to the script) to modify the same row. So the table won't crash*, but it's possible that MySQL can't handle the number of request in reasanoble time and the requests will wait. You should always optimize your queries to be as fast as possible.
*MyISAM could crash on insert/update intensive applications, but it has automatic recovery. However keep in mind that in such application, InnoDB has far better performance

is it always "safe" (ie, will not result in corrupt tables or collisions during requests)?
yes
If so, how does php/mysql achieve this?
table/row locks.

MySQL uses locks for Isoloation, and transactions for Atomicity. Transactions require InnoDB or BDB. InnoDB supports full ACID support.
Locks and transactions, combined, will resolve your concurrency issue.
By default, MySQL has implicit transactions.
Definitely learn about these features to see if they fit the bill. MyISAM uses table locking, whereas InnoDB provides row level locking, so one may serve your needs better than the other.

Usually databases are solid to collisions, however there are important operations those must be completed or discarded. Think about a cash deposit on a bank account.
In order to achieve this result you could be interested in using transactions:
PHP + MySQL transactions examples

Use transactions... See this

I think the terminology you are looking for is transactions and isolation levels. If these are set according to your requirement, you don't need to worry about collisions. Here is tutorial on how it works.

Related

Is there an alternate to transactions that allow executing multiple concurrent queries to a table & making sure the table is in consistent state?

I have an innodb table that I want to perform on some maintenance queries, those queries are going to happen on parallel threads, and they will include (in that order):
Select, update, select, delete, insert.
I want to only allow 1 single parallel thread to have access to that section, so is there something that would allow me to do this?:
mutex.block()
select
update
select
delete
insert
mutex.release()
This will be in php, and all queries will be executed using php's function mysqli_query.
I am hoping for an alternate to transactions, if nothing but transaction can be done here, then be it.
MySQL features table locks and locks (a kind of mutex).
PHP supports pretty much all POSIX locking mechanisms, such as mutexes and semaphores (but these are not available by default, see the related "Installing/Configuring" manual chapters).
But really, I see little reason why you would want to implement your own synchronisation mechanism: transactions exist for this purpose precisely, and are likely to be more efficient and reliable than anything home-brewed.
(if performance is your concern, then a database back-end may not be the right choice)

Data Blocking in PHP, MySQL

I'm writing a Queue Management System for a small clinic. There will be multiple users trying to do same thing, so these is a concurrency problem. I'm familiar with ACID guarantee and also understand notion of transaction. I know that two people can not change same data at the same time.
But here's my problem: I have a PHP function isFree($time) which determines if particular doctor is free for that time. I'm afraid that if both users try to call same function, both of them may get positive result and mess things up, so somehow I need to either queue concurrent users, or accept only one.
Easiest way to solve this problem would be to restrict, that my function can be called one at a time. I probably need some kind of flag or blocking system, but I have no exact idea on how to do it.
Or on the other hand, It would be even faster to only restrict those function calls, which may overlap. For example calling isFree($time) function for Monday and Tuesday at the same time won't cause any problems.
You're effectively asking for a lock.
I am guessing your queue system runs on MySQL for databases. if so, you can LOCK the table you're using (or on some database engines, the specific row you are using!). The structure is LOCK TABLES yourTableName READ.
This will effectively prevent anyone else from reading anything in the table until:
Your session is ended
You free the lock (using UNLOCK)
This is true for all database storage engines. InnoDB supports row-level locking through transactions. Instead of using a SELECT query, suffix it with FOR UPDATE to get a complete lock over the row(s) you just read.
This will hopefully shed more light on the locking mechanism of MySQL/innoDB. In order to free the lock, either UPDATE the row or commit the transaction.

Best MySQL storage engine to use for PHP session storage

I want to use MySQL to store session variables. From what I understand this means that on every page request there will be one read and one write to the table.
Which MySQL storage engine is best suited for this task? MyISAM, InnoDB , MariaDB (which I don't see in PHPMyAdmin), Memory, or something else entirely?
"Best" means nothing. You need to express your constraints: do you need consistency? Durability? High-availability? Performance? A combination of all these properties? Can you afford to loose your sessions? Can they fit in memory? Do you need to support concurrent accesses to the same data?
Without more context, I would choose InnoDB which is the most balanced storage engine. It provides correct performance for OLTP applications, ACID transactions, good reliability, and sensible concurrency management. Session variables access will likely be done using primary keys, and this operation is very efficient with InnoDB.
Now if performance is really a constraint, I would rather use a NoSQL engine (i.e. not MySQL). To store session data, Redis usually does a very good job, and is easy enough to integrate and deploy.
Memory storage engine sounds to be the best option. Keep in mind that this is good for temporary sessions.
http://dev.mysql.com/doc/refman/5.0/en/memory-storage-engine.html
It depends on how you evaluate "betterness":
MyISAM is the most common (many shared hosting packages only let you use MyISAM). plus it is rather limited in the relationship control aspect, so you set it up really fast and easy. if you want portability and fast implementation across multiple hosting scenarios, MYISAM IS BEST.
InnoDB allows you to create relationships and saveguard data integrity by linking keys in different tables, which means more work but much more professional db design. many shared hosting packages do not implement InnoDB, therefore when exporting table structure from one environment to another, you might have some extra work to do. if you want realationship management and control, INNODB IS BEST.
As far as data portability is concerned, an InnoDB database will be completely accepted by MyISAM (because MyISAM does not check data integrity: "is there a user number 4 in the user database when i insert a new record in user_car, for example"). If you start out with MyISAM, exporting to a full-fledged InnoDB database will be a nightmare, even if your data has all keys, table data must be imported in the correct order (user and car, before user_car).
MariaDB? never, simply because less people use it, therefore you will have less support, as compared to MyISAM and InnoDB.
Bottom line clincher: INNODB.
If you do not wan't the overhead from a SQL connection consider using MemCached session sorage. See http://php.net/manual/en/memcached.sessions.php

How can I speed up INNODB queries comparable to MYISAM performance?

I have recently switched my database tables from MYISAM to INNODB and experience bad timeouts with queries, mostly inserts. One function I use previously took <2 seconds to insert, delete and update a large collection of records across ~30 MYISAM tables, but now that they are INNODB, the function causes a PHP timeout.
The timeout was set to 60 seconds. I have optimised my script enough that now, even though there are still many queries, they are combined together (multiple inserts, multiple deletes, etc) and the script now takes ~25 seconds, which is a substantial increase from what appeared to be at least 60 seconds.
This duration is still over 10x quicker when previously using MYISAM, is there any mistakes I could be making in the way I process these queries? Or are there any settings that could assist in the performance? Currently the MySQL is using the default settings of installation.
The queries are nothing special, DELETE ... WHERE ... simple logic, same with the INSERT and UPDATE queries.
Hard to say without knowing too much about your environment, but this might be more of a database tuning problem. InnoDB can be VERY slow on budget hardware where every write forces a true flush. (This affects writes, not reads.)
For instance, you may want to read up on options like:
innodb_flush_log_at_trx_commit=2
sync_binlog=0
By avoiding the flushes you may be able to speed up your application considerably, but at the cost of potential data loss if the server crashes.
If data loss is something you absolutely cannot live with, then the other option is to use better hardware.
Run explain for each query. That is, if the slow query is select foo from bar;, run explain select foo from bar;.
Examine the plan, and add indices as necessary. Re-run the explain, and make sure the indices are being used.
Innodb builds hash indexes which helps to speed up lookup by indexes by passing BTREE index and using hash, which is faster

How to solve problems with deadlocks in InnoDB engine?

I have heard about this problem and now I am looking for more specific information?
How does it happens, what are the reasons for that, detailed explanation of the mechanism of the deadlock to try to avoid it. How to detect the deadlock, solve it and protect the data from being corrupted because of it. The case is when using MySQL with PHP.
And can I mix the InnoDB and MyISAM? I intend to use innoDB for some majo rtables with many relationships and not that much data, as users, roles, privileges, companies, etc. and use MyISAM for tables that hold more data: customers data, actions data, etc. I would like to use only InnoDB, but the move from MyISAM scares me a bit in terms of speed and stability. And now this deadlocks :(
Deadlocks can occur if you've got two or more independent queries accessing the same resources (tables/rows) at the same time. A real world example:
Two mechanics are working on two cars. At some point during the repair, they both need a screwdriver and a hammer to loosen some badly stuck part. Mechanic A grabs the screwdriver, Mechanic B grabs the hammer, and now neither can continue, as the second tool they need is not available: they're deadlocked.
Now, humans are smart and one of the mechanics will be gracious and hand over their tool to the other: both can continue working. Databases are somewhat stupid, and neither query will be gracious and unlock whatever resource is causing the deadlock. At this point, the DBMS will turn Rambo and force a roll back (or just kill) one or more of the mutually locked queries. That will let one lucky query continue and proceed to get the locks/transactions it needs, and hopefully the aborted ones have smart enough applications handling them which will restart the transactions again later. On older/simpler DBMSs, the whole system would grind to a halt until the DBA went in and did some manual cleanup.
There's plenty of methods for coping with deadlocks, and avoiding them in the first place. One big one is to never lock resources in "random" orders. In our mechanics' case, both should reach for the screwdriver first, before reaching for the hammer. That way one can successfully working immediately, while the other one will know he has to wait.
As for mixing InnodB/MyISAM - MySQL fully supports mixing/matching table types in queries. You can select/join/update/insert/delete/alter in any order you want, just remember that doing anything to a MyISAM table within an InnoDB transaction will NOT make MyISAM magically transaction aware. The MyISAM portions will execute/commit immediately, and if you roll back the InnoDB side of things, MyISAM will not roll back as well.
The only major reason to stick with MyISAM these days is its support for fulltext indexing. Other than that, InnoDB will generally be the better choice, as it's got full transaction support and row-level locking.

Categories