MySQL Transactional and Locking Statements
MySQL5.0 supports local transactions by statements like START TRANSACTION, SET AUTOCOMMIT, COMMIT and ROLLBACK. Transaction means a group of SQL Statements, which executes as a unit. And MySQL either executes all the statement successfully or it doesn?t execute anyone. This can be achieved by the commit and rollback. When all the statements executes successfully then you can commit it to effect the database permanently. But if any error has occurred then you can roll it back for cancellation it.START TRANSACTION, COMMIT and ROLLBACK
The general syntax of Start Transaction, commit and rollback is:
START TRANSACTION | BEGIN [WORK] COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE] ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE] SET AUTOCOMMIT = {0 | 1}
START TRANSACTION and BEGIN statement is used start a new transaction. And COMMIT is used to commit (saved) the current transaction means that makes the changes permanently. ROLLBACK is used to rolls back the current transaction means canceling the changes. SET AUTOCOMMIT statement is used to disable or enable the default autocommit mode for current transaction.
The optional keyword WORK is used to support for COMMIT and ROLLBACK. And CHAIN and RELEASE keyword are used to additional control over the completion of transaction. The AND CHAIN clause is used to start a new transaction when the current one ends. And this new one has the same isolation level. The RELEASE clause is used for disconnecting the server with current client connection after terminating the current transaction. By default MySQL in autocommit mode. When we are using a transaction safe storage engine like BDB, InnoDB then we can disable the autocommit mode by using the following statement :
mysql> SET AUTOCOMMIT=0; |
mysql> START TRANSACTION; mysql> UPDATE Emp SET Perks=Perks*1.03 WHERE Salary>15000; mysql> COMMIT; |
In MySQL some statements are available that we cannot be rolled back these include DDL (Data Definition Language) statements like create database, create table, drop database, drop table, alter table. Make sure you transaction does not include these type of statements. If you have issued a DDL statement early in transaction and another statement fails then you cannot the rolled back the full effect of the transaction by issuing the ROLLBACK statement.
SAVEPOINT and ROLLBACK TO SAVEPOINT
The general syntax of SAVEPOINT and ROLLBACK TO SAVEPOINT is :
SAVEPOINT savepoint_name
ROLLBACK [WORK] TO SAVEPOINT savepoint_name
RELEASE SAVEPOINT savepoint_name
SAVEPOINT statement is used to set a named transaction savepoint with any name. The ROLLBACK TO SAVEPOINT statement is used to roll back the transaction for the named savepoint. Means modification to the rows that we made in the current transaction after the savepoint, we are rolled back these modification. We can remove the named savepoint from the set of savepoints of the current transaction by using RELEASE SAVEPOINT. Example :
mysql> SELECT * FROM Emp; mysql> START TRANSACTION; mysql> UPDATE Emp mysql> SAVEPOINT sve_point; mysql> INSERT INTO Emp VALUES(10,'Chandan','Delhi','Designer',20000,965); mysql> ROLLBACK TO SAVEPOINT sve_point; mysql> INSERT INTO Emp VALUES(9,'Rajesh','Delhi','Developer',15000,965); mysql> COMMIT; mysql> SELECT * FROM Emp; |
The general syntax for locking and unlocking the tables is:
LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ... UNLOCK TABLES
The LOCK TABLES are used for locking the base table to current thread. If any other thread locked the table then this table is blocked until the all locks can be acquired. The UNLOCK TABLES is used to explicitly release the lock that?s held by the current thread. The current thread implicitly unlocks all tables if it issues another LOCK TABLES or if the connection to the server is closed. After getting a global read lock we can also used the UNLOCK TABLE with FLUSH TABLES WITH READ LOCK for releasing the lock. But for using the LOCK TABLES you need the LOCK TABLES and SELECT privileges for involved tables.
A table locking is used to protect only against inappropriate writes or read by other clients. If any client holds a lock even a read lock then the client can perform the operation of table level like DROP TABLE. But truncate operations cannot be performed because they are not transaction safe.
Uses of LOCK TABLES with transactional tables:
- As we discussed LOCK TABLES is not transaction safe and implicitly performs a commit operation on any active transactions before performing to lock the table. And beginning a transaction implicitly performs an UNLOCK TABLES.
- For using LOCK TABLES with transactional tables like InnoDB, we have to set AUTOCOMMIT=0 and we don?t call UNLOCK TABLES until we commit the transactional explicitly. If we are calling LOCK TABLES then InnoDB internally takes it own table lock and MySQL is also takes its own table lock. At the next commit InnoDB released its table lock but for releasing MySQL we have to call UNLOCK TABLES. But if we do AUTOCOMMIT =1 then InnoDB released the table lock immediately after calling of LOCK TABLES that?s why deadlocks can easily occur.
- ROLLBACK cannot release the MySQL non transactional table locks.
- FLUSH TABLES WITH READ LOCK is used to get the global lock rather than table lock.
mysql> LOCK TABLE Emp AS eealias WRITE; mysql> INSERT INTO Emp VALUES(9,'Rajesh','Delhi','Developer',15000,965); mysql> INSERT INTO Emp VALUES(9,'Rajesh','Delhi','Developer',15000,965); mysql> LOCK TABLE Emp AS ee READ; mysql> SELECT * FROM Emp; |
Table locking is deadlock free. You have to be aware if you are using a LOW_PRIORITY WRITE lock , that means only MySQL is waiting for thi particular lock until there no threads are available which want a READ lock. Any thread has obtained the WRITE lock and its waiting to obtain a lock for next table in lock table list then all other threads have to wait for WRITE lock to be released.
If we wish to terminate a thread which is waiting for a table lock then we can use KILL statement. The general syntax of KILL statement is:
KILL [CONNECTION | QUERY] thread_id
Each connection for mysqld running in a separate thread. By SHOW PROCESSLIST statement we can see which threads are running and we can kill the thread by KILL statement. KILL CONNECTION is same as the KILL statement with no modifier. It is used to terminate a connection associated with the given thread_id. KILL QUERY is used to terminate the statement that connection is currently executing but it leaves the connection itself intact. For getting the list of all threads you need the PROCESS privilege and for kill the all threads and statements then you need the SUPER privilege else you can see and kill only your threads and statements. Example :
mysql> SHOW PROCESSLIST \G; mysql> KILL 9; |
SET TRANSACTION
The general syntax of SET TRANSACTION is:
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
SET TRANSACTION is used to set the transaction isolation level for the global or the current session or for the next transaction. When we are using GLOBAL keyword then it sets the default transaction level global but you require the SUPER privilege for doing this. And SESSION keyword is used to set the default transaction level for all future transactions which performed on current connection.
- REPEATABLE READ ? It is the default isolation level for InnoDB tables. In this, all reads are consistent within a transaction.
- READ UNCOMMITTED ? It is used, where in one transaction queries are affected by uncommitted changes in another transaction.
- READ COMMITTED ? If we are using this setting then committed updates are visible in another transaction also.
- SERIALIZABLE ? In this setting updates are not allowed in other transactions.
Connection 1 mysql> BEGIN; mysql> SELECT * FROM Emp; |
Connection 2 mysql> INSERT INTO Emp VALUES(2,'Suman','Mumbai','Designer',20000,865); mysql> COMMIT; mysql> SELECT * FROM Emp; |
Connection 1 mysql> COMMIT; mysql> SELECT * FROM Emp; |
Connection 1 mysql> BEGIN; mysql> INSERT INTO Emp VALUES(3,'Chandan','Delhi','G Manager',30000,999); |
Connection 2 |
Connection 1 |
Connection 2 |
Connection 1 mysql> BEGIN; |
Connection 2 mysql> INSERT INTO Emp VALUES(3,'Chandan','Delhi','G Manager',25000,986); |
Connection 1 |
Connection 2 |
Connection 1 |
Connection 1 mysql> BEGIN; mysql> SELECT * FROM Emp; |
Connection 2 mysql> UPDATE Emp SET Salary=Salary*1.03; |
In the first connection we executes the SELECT statement that?s why the UPDATE is locked.
Connection 1 |
Connection 2 mysql> COMMIT; mysql> SELECT * FROM Emp; |
No comments:
Post a Comment