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.
Related
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.
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.
For a forum, should I use MyISAM or InnoDB for the table that stores the text?
I know that MyISAM supports full text searching, which sounds like it's what I should go for, but while reading, I've come across this very confusing sentence.
You should use InnoDB when
transactions are important, such as
for situations in which INSERTs and
SELECTs are being interleaved, such as
online message boards or forums.
Well, but for an "online message boards or forums" I would need good search to search through the text of each post, so doesn't it make more sense to use MyISAM? Can someone clarify what's most commonly used?
Apart from MySQL's native full text searching solution, which as you already identified requires the MyISAM storage engine, you may also want to consider the popular third-party search engines Sphinx and Apache Lucene, with which you can use InnoDB tables.
You could also stick to MySQL's solution, and use InnoDB storage for all tables except for one table which will simply hold the post_id and text_body. This is assuming that you only require full text searching for the content of forum posts.
In addition note that while the major deficiency of MyISAM is the lack of transaction support, there are other important issues as well for a production system. You may want to check the following article for further reading:
MySQL Performance Blog: Using MyISAM in production
Generally speaking, for non-critical data, I'd use InnoDB tuned for speed. (E.g., I wouldn't flush binary logs on every commit.) I'd only use MyISAM for things like logging tables.
As others have mentioned, you can use external search indexes if you need to do full text searches. They are more powerful and faster than MySQL's.
Regarding the part about transactions, it's a bit of a lie. You could do the same thing with MyISAM by locking tables for WRITE. If you are inserting into, say, three tables when posting a message, you could lock all three tables for WRITE, and the data would look consistent (assuming all three INSERTS succeeded).
But the problem with that is you are locking the entire table, which can slow down concurrent usage. In fact, that is one of InnoDB's major advantages over MyISAM: it has row-level locking.
In short: if you are unable to set up an external indexer, and your site does not experience too much traffic, then MyISAM will work fine despite it being less robust. You can emulate the consistency of transactions with table locks. (I do not mean to make it sound like the table locking is somehow equivalent to transactions.)
Otherwise, I'd use InnoDB with an external indexing service.
For any large volume of text I'd use InnoDB to store it and Sphinx to index it. It provides a lot more search features than what's built into mysql.
I am currently working on a very specialized PHP framework, which might have to handle large database transfers.
For example:
Take half of the whole user count; this should be every day's workspace for the framework.
So, if my framework is required by big projects, is it recommend to use single transactions with multiple queries (e.g. doing many things in 1 query with JOINs(?)), or is auto-commit preferred?
If possible, post some blog entries which have discussed this problem.
Thank you. ;)
MyISAM is transactionless, so autocommit does not affect it.
As for InnoDB, autocommit makes repeating queries hundreds of times as slow.
The best decision is of course doing everything set-based, but if you have to do queries in a loop, turn autocommit off.
Also note that "multiple queries" and "doing many things in one query with JOIN" are completely different things.
The latter is an atomic operation which succeeds or fails at once even on MyISAM.
Autocommit does not affect its performance as such: everything inside this query is always done in a single transaction.
Doing many things in one query is actually a preferred way to do many things.
Joins are not just useful they are necessary in any but the simplest of datastructures. To consider writing without them shows a fundamental lack of understanding of relational database design and access to me. Not to use joins would usually result in getting the wrong answer to your question in a select. You may get away without joins in inserts, updates and deletes, but they are often used and useful there as well.
Wordpress is using MyISAM storage engine. MyISAM does not support transactions.
How wordpress is maintaining transactions?
I mean if wordpress is having two database write operations, how does it ensure atomicity?
Well, as far as I can tell, it doesn't! The only reason there are not much problems with this is, that most write operations are done with a single insert or update (adding a comment, creating a new post...).
In general, most web applications I have seen so far, don't bother too much with transactions, atomicity or even referential integrity, which is quite sad. On the one hand it is sad that so many applications just rely on pure luck that nothing bad happens and on the other hand it might lead to the impression that all these techniques aren't that important when it comes to database stuff.
I would think the transaction would assure atomic correctness at the previous layer of abstraction. When a transaction is occurring it default locks what it is writing. I'm not sure though.