So I am trying to learn MySQL and I came across the isolation levels (SERIALIZED, REPEATABLE READ, READ COMMITED, READ UNCOMMITED)
I believe my question is quite simple, but I did not find any information in the web so here it goes:
If I change the default REPEATABLE READ to SERIALIZED or even from READ UNCOMMITED to another higher level of isolation does I have less probabilities of having deadlock problems?
Thanks in advance!
Actually, deadlocks between SELECT operations on the one hand and INSERT or UPDATE on the other hand will be less likely if you use the more permissive READ UNCOMMITTED isolation level for your SELECT operations.
If it's OK for your SELECT operations not to get the results of concurrent changes to your tables, use that.
The possibility of deadlocks is not affected by isolation level. Isolation level changes the behavior of read operations, but deadlock occurs due to write operations. However, isolation level sets fewer locks, hence it can help you to avoid certain lock types (e.g. gap locking).
These tips to avoid dead_lock are very helpful https://www.percona.com/community-blog/2018/09/24/minimize-mysql-deadlocks-3-steps/
Related
The following strategy seems to be working, but am I overlooking something? Why not do this always for read-intensive systems that for most queries don't need data consistency? Like for instance blogging / publication systems. Seems to me
Set the database-default to read-only mode. This will catch programming errors and probably give better read performance
-- MySQL / MariaDB schema creation example
-- in a read intensive system, default to read only for security and speed
SET GLOBAL TRANSACTION READ ONLY;
Set the database-default to the least strict transaction isolation level. This will prevent locking and probably increase read performance
-- MySQL / MariaDB schema creation example
-- if data integrity is not critical for most queries, choose maximum performance
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Override only for queries that do need write-access and / or higher transaction isolation levels.
In a read intensive system these extra query-statements around write-statements won't be noticeable
-- MySQL / MariaDB example
...
SET SESSION TRANSACTION READ WRITE;
UPDATE table_x SET field_y=10;
SET SESSION TRANSACTION READ ONLY;
...
I have never heard of a situation where READ UNCOMMITTED was the right thing to do. It seems clear that reading changes from other transactions that aren't committed yet — and may be rolled back — is likely to lead to a lot of phantom reads and other logic problems.
I would be in favor of setting the default transaction isolation level to READ COMMITTED, although this also depends on the application needs. Some applications require that they use REPEATABLE READ semantics by default. We can't say that one or the other of these is "better" because it depends what the application needs.
I am not aware that there's any performance advantage to setting a transaction access mode to READ ONLY. It prevents that transaction from changing any data, but in my opinion if you have code bugs such that you don't know if a given transaction is going to change data, then you have bigger problems.
InnoDB has a read-only mode that affects the whole instance, not individual transactions. Read about it here: https://dev.mysql.com/doc/refman/8.0/en/innodb-read-only-instance.html I doubt this would give significant performance benefits for an average application. It would have to be a very high-traffic application, so you have some bottleneck caused by some of the background threads that are disabled in InnoDB read-only mode. But in that type of application, you'd naturally need read-write mode.
So I am trying to understand more about the isolation levels and I read that the READ UNCOMMITED isolation level allows dirty readings which may lead to non-consistent readings. I also read that the
SELECT statements are performed in a nonlocking fashion
So my question is, does this type of isolation uses locks for other statements? For example, if I use the INSERT INTO statement does it acquire locks?
Thanks in advance!
Yes. Locks are still needed to ensure data transactions are atomic.
Also locks ensure that elements like auto_increments values only exist once.
I know that every single query sent to MySQL (with InnoDB as engine) is made as a separate transaction. However my concerns is about the default isolation level (Repeatable Read).
My question is: as SELECT query are sent one by one, what is the need to made the transaction in repeatable read ? In this case, InnoDB doesn't add overhead for nothing ?
For instance, in my Web Application, I have lot of single read queries but the accuracy doesn't matter: as an example, I can retreive the number of books at a given time, even if some modifications are being processed, because I precisely know that such number can evolve after my HTTP request.
In this case READ UNCOMMITED seems appropriate. Do I need to turn every similar transaction-with-single-request to such ISOLATION LEVEL or InnoDB handle it automatically?
Thanks.
First of all your question is a part of wider topic re performance tuning. It is hard to answer just like that - knowing only this. But i try to give you at least some overview.
The fact that Repeatable Read is good enough for most database, does not mean it is also best for you! That’s holly true!
BTW, I think only in MySQL this is at this level defaultly. In most database this is at Read Committed (e.g. Oracle). In my opinion it is enough for most cases.
My question is: as SELECT query are sent one by one, what is the need
to made the transaction in repeatable read ?
Basically no need. Repeatable read level ensure you are not allowing for dirty reads, not repeatable reads and phantom rows (but maybe this is a little different story). And basically these are when you run DMLs. So when query only pure SELECTs one by one -this simply does not apply to.
In this case, InnoDB doesn't add overhead for nothing ?
Another yep. It does not do it for nothing. In general ACID model in InnoDB is at cost of having data consistently stored without any doubts about data reliability. And this is not free of charge. It is simply trade off between performance and data consistency and reliability.
In more details MySQL uses special segments to store snapshots and old row values for rollback purposes. And refers to them if necessary. As I said it costs.
But also worth to mention that performance increase/decrease is visible much more when doing INSERT, UPDATE, DELETE. SELECT does not cost so much. But still.
If you do not need to do it, this is theoretically obvious benefit. How big? You need to assess it by yourself, measuring your query performance in your environment.
Cause many depends also on individual incl. scale, how many reads/writes are there, how often, reference application design, database and much, much more .
And with the same problem in different environments the answer could be simply different.
Another alternative here you could consider is to simply change engine to MyISAM (if you do not need any foreign keys for example). From my experience it is very good choice for heavy reads needs. Again all depends- but in many cases is faster than InnoDB. Of course less safer but if you are aware of possible threats - it is good solution.
In this case READ UNCOMMITED seems appropriate. Do I need to turn
every similar transaction-with-single-request to such ISOLATION LEVEL
or InnoDB handle it automatically?
You can set the isolation level globally, for the current session, or for the next transaction.
Set your transaction level globally for next sessions.
SET GLOBAL tx_isolation = 'READ-UNCOMMITTED';
http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html
I'm trying to generate a few graphs using the sysbench benchmark (default configuration) trying to show the relationship between deadlocks and isolation level in MySQL.
But I get some strage results: I was under the impression that repeatable read would have more deadlocks than read committed (which is the case), but significantly more than read uncommitted. In fact it turns out that read uncommitted has more deadlocks than either.
Is this normal? And if so, why?
Deadlock can happen in any isolation level. It's hard to tell without the actual tests, but I guess that in case of read commited / repeatable read, if you have to read a value of a row being updated, the value is being read from the rollback log, but in case of read uncommited rollback log is not used, so it the row is locked for update, the read has to wait for the actual value to be written. But it's a wild guess, having more deadlocks in read uncommited is a strange behaviour and most likely - implementation dependent. I would be interested if you could provide the actual tests, and if the test can be repeated in different versions of MySQL.
Whatever changes made to the MySQL database, are those changes readable within the same transaction? Or should I commit the transaction to read the changes?
I could easily test this. But putting a question in SO brings up a lot of good suggestions. Thanks for any input.
Assuming you're using InnoDB, the answer to your first question is generally yes, implying the answer to your second is generally no.
By default MySQL's InnoDB uses a technique called consistent non-locking reads:
The query sees the changes made by
transactions that committed before
that point of time, and no changes
made by later or uncommitted
transactions. The exception to this
rule is that the query sees the
changes made by earlier statements
within the same transaction.
That being said, there's a lot of stuff to know about transactions. You can change the isolation level of a transaction in order to control the transaction results more thoroughly.
The chapter on the InnoDB Transaction Model is a great place to start.