Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
What is the difference between concurrency control and transaction isolation levels?
I understand each of them clearly, however, I am having some problems relating them to each other. Specifically, I see some overlap in their functions and I'm not sure when one should use one over the other. Or should both be used together?
Also what does it mean to say pessimistic locking with repeatable read? Doesn't repeatable read already imply that all values to be edited will be locked? So why is there still a need for pessimistic locking?
The issue arises because there are two models for concurrency control, which are sometimes mixed by SQL implementations.
locks, as in 2PL (Two Phase Locking)
versions, as in MVCC (Multiversion Concurrency Control)
Pessimistic means rows that are read are locked. Optimistic means rows that are read are not locked.
The classic 2PL implementation of Repeatable Read is always pessimistic. The multiversion implementation of Repeatable Read is optimistic. It does not lock the rows that are read for a SELECT statement and allows other transactions to modify the rows that have been read in a SELECT. Such changes are not visible to the transaction that performed the SELECT, until it is committed.
Concurrency control is a general term for any mechanism that handles issues that arise from concurrent connections.
Transaction isolation levels are a mechanism by which MySQL implements concurrency control.
See Consistent Nonlocking Reads for documentation on how MySQL implements REPEATABLE READ without pessimistic locking:
A consistent read does not set any locks on the tables it accesses, and therefore other sessions are free to modify those tables at the same time a consistent read is being performed on the table.
Suppose that you are running in the default REPEATABLE READ isolation level. When you issue a consistent read (that is, an ordinary SELECT statement), InnoDB gives your transaction a timepoint according to which your query sees the database. If another transaction deletes a row and commits after your timepoint was assigned, you do not see the row as having been deleted. Inserts and updates are treated similarly.
Related
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/
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 have a webservice that produces a lot of updates in my database. After, it will do some other things (like calculus, call another webservice, etc). At the end, it contacts the database again.
The problem is that the tables are locked during the entire webservice life. So if the "other things" takes longer, I can´t work with the tables for this time.
There is a way to lock just the register, not the tables ?
How can I avoid this situation ?
I´m using Hibernate and MYSQL.
Pro JPA 2 book says:
The reality is that very few applications actually need pessimistic locking, and those > that do only need it for a limited subset of queries. The rule is that if you think
you need pessimistic locking, think again. If you are in a situation
where you have a very high degree of write concurrency on the same
object(s) and the occurrence of optimistic failures is high, then you
might need pessimistic locking because the cost of retries can become
so prohibitively expensive that you are better off locking
pessimistically . If you absolutely cannot retry your transactions and
are willing to sacrifice some amount of scalability for it, this also
might lead you to use pessimistic locking.
so I suggest you think again about your need.
i´m using PESSIMISTIC_WRITE
The hibernate acquires exclusive locks by using ‘SELECT … FOR UPDATE‘ statements(when using pessimistic lock)
4:Connection.TRANSACTION_REPEATABLE_READ lock your selected data(during the transaction). so you do not need to use pessimistic_lock.
the pessimistic lock is usually used for repeateabe_read while the transaction isolation is not repeatable_read( when is Read Committed)
following links describe mysql locking mechanism
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html#isolevel_repeatable-read
There is a way to lock just the register, not the tables?
the selected row should be locked not the tables( check your selects)
What transaction isolation level are you using? Please refer the documentation to see how this affects locking and how this can be changed.
Check your application. Transactions should be as short as possible. Consider a redesign, if needed. You might even consider using BASE instead of ACID.
I was reading about database locking(pessimistic,optimistic) mechanism,
session 1:
t1: open transaction:
t2: sleep(3 sec)
t5: updte user set name='x' where id =1
session 2:
t2:update user set name='y' where id=1
my doubts are:
1. What will happen at t5
2. does It has to do any thing with Isolation level?if yes what will be the behavior in different isolation level.
3. Does database(mysql,oracle) only do pessimistic locking?
Let me answer your questions in a reverse order bacause this way I do not have to repeat certain parts.
Since optimistic locking means that the records read in a transaction are not locked, optimistic locks cannot be implemented. You should not really use the term optimistic lock, use optimistic concurrency control instead. The pessimistic locking strategy is the one that involves database level locks, which are implemented by all rdbms that use transactions - including mysql with innodb.
Mysql does not have any database level support for optimistic concurrency control. This does not mean that other rdbms do not support OCC either. You need to check out their manuals.
Isolation levels do not affect the outcome of the scenario described in the question, since there is no select there, only 2 atomic updates and the field referenced in the where clause is not updated.
Isolation levels mainly influence how data is read by transactions, not how they can update it.
The outcome of the scenario described in the question depends on which session issues the update first and how long that transaction is open. Whichever session executes the update first will make the change and sets an exclusive lock on the index record. The other transaction will not be able to execute the update until the first transaction completes. If the first transaction runs for a long time, then the other one may time out while waiting for the lock to be released.
can someone explain the need to lock tables and/or rows in mysql?
I am assuming that it to prevent multiple writes to the same field, is this the best practise?
First lets look a good document This is not a mysql related documentation, it's about postgreSQl, but it's one of the simplier and clear doc I've read on transaction. You'll understand MySQl transaction better after reading this link http://www.postgresql.org/docs/8.4/static/mvcc.html
When you're running a transaction 4 rules are applied (ACID):
Atomicity : all or nothing (rollback)
Coherence : coherent before, coherent after
Isolation: not impacted by others?
Durability : commit, if it's done, it's really done
In theses rules there's only one which is problematic, it's Isolation. using a transaction does not ensure a perfect isolation level. The previous link will explain you better what are the phantom-reads and suchs isolation problems between concurrent transactions. But to make it simple you should really use Row levels locks to prevent other transaction, running in the same time as you (and maybe comitting before you), to alter the same records. But with locks comes deadlocks...
Then when you'll try using nice transactions with locks you'll need to handle deadlocks and you'll need to handle the fact that transaction can fail and should be re-launched (simple for or while loops).
Edit:------------
Recent versions of InnoDb provides greater levels of isolation than previous ones. I've done some tests and I must admit that even the phantoms reads that should happen are now difficult to reproduce.
MySQL is on level 3 by default of the 4 levels of isolation explained in the PosgtreSQL document (where postgreSQL is in level 2 by default). This is REPEATABLE READS. That means you won't have Dirty reads and you won't have Non-repeatable reads. So someone modifying a row on which you made your select in your transaction will get an implicit LOCK (like if you had perform a select for update).
Warning: If you work with an older version of MySQL like 5.0 you're maybe in level 2, you'll need to perform the row lock using the 'FOR UPDATE' words!
We can always find some nice race conditions, working with aggregate queries it could be safer to be in the 4th level of isolation (by using LOCK IN SHARE MODE at the end of your query) if you do not want people adding rows while you're performing some tasks. I've been able to reproduce one serializable level problem but I won't explain here the complex example, really tricky race conditions.
There is a very nice example of race conditions that even serializable level cannot fix here : http://www.postgresql.org/docs/8.4/static/transaction-iso.html#MVCC-SERIALIZABILITY
When working with transactions the more important things are:
data used in your transaction must always be read INSIDE the transaction (re-read it if you had data from before the BEGIN)
understand why the high isolation level set implicit locks and may block some other queries ( and make them timeout)
try to avoid dead locks (try to lock tables in the same order) but handle them (retry a transaction aborted by MySQL)
try to freeze important source tables with serialization isolation level (LOCK IN SHARE MODE) when your application code assume that no insert or update should modify the dataset he's using (if not you will not have problems but your result will have ignored the concurrent changes)
It is not a best practice. Modern versions of MySQL support transactions with well defined semantics. Use transactions, and forget about locking stuff by hand.
The only new thing you'll have to deal with is that transaction commits may fail because of race conditions, but you'd be doing error checking with locks anyway, and it is easier to retry the logic that led to a transaction failure than to recover from errors in a non-transactional setup.
If you do get race conditions and failed commits, then you may want to fine-tune the isolation configuration for your transactions.
For example if you need to generate invoice numbers which are sequential and have no numbers missing - this is a requirement at least in the country I live in.
If you have a few web servers, then a few users might be buying stuff literally at the same time.
If you do select max(invoice_id)+1 from invoice to get the new invoice number, two web servers might do that at the same time (before the new invoice has been added), and get the same invoice number for the invoices they're trying to create.
If you use a mechanism such as "auto_increment", this is just meant to generate unique values, and makes no guarantees about not missing out numbers (if one transaction tries to insert a row, then does a rollback, the number is "lost"),
So the solution is to (a) lock the table (b) select max(invoice_id)+1 from invoice (c) do the insert (d) commit + unlock the table.
On another note, in MySQL you're best using InnoDB and using row-level locking. Doing a lock table command can implicitly commit the transaciton you're working on.
Take a look here for general introduction to what transactions are and how to use them.
Databases are designed to work in concurrent environments, so locking the tables and/or records helps to keep the transactions consistent.
So a record affected by one transaction should not be altered until this transaction commits or rolls back.