1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu MySQL Administrator’s Bible- P8 pdf

50 405 1

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề MySQL Views
Chuyên ngành Information Technology / Database Management
Thể loại Document
Định dạng
Số trang 50
Dung lượng 1,61 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

IN THIS CHAPTERUnderstanding ACIDcompliance Using transactional statements Using isolation levels Explaining locking and deadlocks Recovering MySQL transactions When reading about relati

Trang 1

Note that updating the view presents a logical error Even if Benjamin had privileges to the basetables, updating the view would generate no warning or error, but produces incorrect results.

Changing a View Definition

There are two ways to change a view One method has already been discussed — using the

CREATE OR REPLACEwhen defining a view In addition, MySQL has anALTER VIEWcommand

ALTER VIEWworks much likeALTER TABLE TheSELECTstatement that defines the view mustalways be included in theALTER VIEWstatement, even if that part of the view definition is notbeing modified

You may have noticed that in theCREATE VIEWstatement, four different clauses may comebetween the wordsCREATEandVIEW:

CREATE [OR REPLACE]

[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]

[DEFINER = { user | CURRENT_USER} ] [SQL SECURITY { DEFINER | INVOKER }]

VIEW view_name [(column_list)]

AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]

Similarly, the syntax of theALTER VIEWstatement is:

ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]

[DEFINER = { user | CURRENT_USER} ] [SQL SECURITY { DEFINER | INVOKER }]

VIEW view_name [(column_list)]

AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]

Only the view’s definer or a user with theSUPERprivilege canALTERa view

Replication and Views

In both row- and statement-based replication, MySQL treats a view the same way it treats a basetable In statement-based replication,CREATE VIEW,ALTER VIEW, and DROP VIEWstatementsare written to the binary log, and thus replicated In row-based replication, the underlying data

is replicated

Thereplicate-do-tableandreplicate-ignore-tablereplication options are applied toviews and tables in both statement- and row-based replication, with the following outcomes:

Trang 2

■ A view that matches areplicate-do-tablepattern will be written to the binary log,and thus replicated.

■ A view that matches areplicate-ignore-tablepattern will not be written to thebinary log, and thus not be replicated

■ replicate-do-tableandreplicate-ignore-tablepatterns match the objectname only Therefore, those options will only be applied to views matching thepattern — even if the view references a matching table name

Summary

In this chapter, we have described:

■ How to create, change, and drop views

■ InvalidSELECTstatements in view definitions

■ Using views to limit field and row data for security purposes

■ How views can simplify and abstract queries

■ Performance implications of views

■ Using views as check constraints

■ How to update underlying base tables using an updatable view

■ Reasons a view may not be updatable

■ Logical errors that may occur when updating data using an updatable view

■ How replication handles views

Trang 3

IN THIS CHAPTERUnderstanding ACID

compliance Using transactional statements Using isolation levels

Explaining locking and deadlocks

Recovering MySQL transactions

When reading about relational database management systems

(RDBMSs), you will see the terms transaction and ACID

compliance A transaction is a set of SQL statements that are

executed as if they were one statement For a transaction to be finishedand save data changes permanently, all the statements in the transactionhave to be completed If a transaction is not completed for any reason,the changes to the dataset that the transaction already made are removed,placing the database in its original state before the transaction began

A transaction is a transaction only if it is ACID-compliant ACID is an

acronym that stands for atomicity, consistency, isolation, and durability Aproper implementation of these properties guarantees reliable processing ofdatabase transactions The properties of ACID are explained in detail in thenext section

To begin understanding what transactions are and why they are important,

it will be helpful to walk through an example of how transactions are used

The classic transaction example is the database system used by a bank

Consider the following situation: Ziesel wants to move $1,000 from herchecking account to the checking account of her neighbor Hudson, who isselling Ziesel his car

If Ziesel has an account id of 145356 and Hudson has an account id of

118254, the following two SQL statements might be used to accomplishthis bank transaction:

UPDATE checking SET balance = balance - 1000 WHERE id = 145356;

UPDATE checking SET balance = balance + 1000 WHERE id = 118254;

Trang 4

The inherent problem with this is that it takes two statements to accomplish the goal of movingthe money from one account to another What happens if the server experiences a system failurebetween execution of the first and second statement? The $1000 is lost somewhere — poorZiesel is left with $1000 less in her checking account and Hudson has the same amount ofmoney as when things started.

To keep this situation from happening, a transactional wrapper is used This tells the database

server that unless all the statements are completed the results of the statements should not besaved to the database To do this:

Revisiting the scenario of the server experiencing a system failure while executing the second

UPDATEstatement, this time after the server starts up it will realize the transaction was notfinished and issue aROLLBACK, which resets any changes left unfinished that were made beforesystem failure Wrapping both statements in a transaction means that either both statementshappen, or neither statement happens If there is a failure, Ziesel gets her money back and thetransaction can be executed again

mysqld supports multiple storage engines Storage engines are the server components that are used to create and support database tables These storage engines have dif- ferent characteristics Some of them do not support transactions, including the MyISAM storage engine However, there are storage engines that do support transactions, including the InnoDB and Falcon storage engines There is more information about storage engines in Chapter 11, ‘‘Stor- age Engines.’’

Understanding ACID Compliance

As previously mentioned, ACID compliance is an acronym for the characteristics of a tionally safe database Enforcing atomicity, consistency, isolation, and durability is what ensuresthat a series of statements is indeed a transaction That is, it ensures that a series of statementseither completes with the resulting changes reliably stored, or, if interrupted, the set of state-

transac-ments is rolled back to where it began so the database is not changed.

Trang 5

Atomicity refers to concept that either all of the statements inside a transaction are completed, or

none of them are performed As with the previous example, in a banking system, the transfer

of funds can be completed or it could fail However, the transfer of funds is not allowed to failleaving the work half-done

The atomicity property guarantees that one account will not be debited unless the other account

is credited Each transaction is said to be atomic (indivisible) — even though there are actually

two statements, they act as if they are one statement If any part of the transaction fails, theentire transaction must fail

Consistency

The consistency property ensures that the database moves from one consistent state to another.

If the server were to fail while executing the transfer of money from Ziesel’s account to son’s account, the database would be left in an inconsistent state The only way to resolve thisinconsistency is to undo changes already made Before a transaction begins the database should

Hud-be in a consistent state Once the transaction either completes successfully or is rolled back thedatabase should still be in a consistent state

In a transactional system (ACID-compliant by definition), if one or more statements in thetransaction do not succeed, the entire transaction must be rolled back to a consistent state

If a transaction is successful, the database moves from one consistent state to another

Isolation

The isolation property specifies that data being modified for one transaction cannot be viewed

or modified by a second transaction until the completion of the first transaction This is tant to support concurrent execution of queries, which is critical in any modern database sys-tem With isolation, separate transactions can run at the same time without compromising theconsistency of the data In MySQL, the level of isolation that transactions have can be config-ured The meanings of different isolation levels and how to set the isolation level are discussed

impor-in more detail impor-in the section ‘‘Usimpor-ing Isolation Levels’’ later impor-in this chapter

Durability

Durability describes the principle that once a transaction has been successfully completed, the

results are recorded by the database server permanently After this point the transaction iscomplete, and the data changes must survive even if the database or operating system fails This

is important, because modern-day operating systems do not always perform operations diately If there is an operating system failure between the time that a transaction successfullycompletes and the time the data is actually written to the disk permanently, the database hasmarked the transaction as complete but the data has not been changed appropriately

Trang 6

imme-Many databases implement durability by writing complete transactions into a log that can be

played back to re-create the database state right before a failure A transaction is considered

successfully committed only after it has been written to this log, called a redo log.

Using Transactional Statements

Now that you have some theory under your belt it is time to see how you actually work withtransactions in MySQL It has been touched on previously, but it is important to understand thatwith MySQL you have a choice of the type of storage engine to use for each table To utilizetransactions the storage engine used for each table involved in the transaction must supporttransactions Failure to do so will lead to inconsistent results Five SQL commands are used towork with transactions We cover each of these in the following subsections

BEGIN, BEGIN WORK, and START TRANSACTION

BEGIN,BEGIN WORK, andSTART TRANSACTIONall can be used to start a transaction cally, bothBEGINandBEGIN WORKare aliases of theSTART TRANSACTIONcommand

Techni-If you execute any of these statements, it causes an implicitCOMMITof any previous pendingtransactions that are open by the client thread In addition, if you had previously executed a

LOCK TABLESstatement the tables will be unlocked just as though you had issued anUNLOCK TABLESstatement

Some statements cannot be rolled back, because they perform an implicit COMMIT when they complete These include DDL (Data Definition Lan- guage) statements like CREATE DATABASE, CREATE TABLE, DROP DATABASE, DROP TABLE, and ALTER TABLE If you have issued a DDL statement early in a transaction and another statement fails, you cannot roll back the transaction by issuing the ROLL- BACK statement Many of these statements also perform an implicit COMMIT when they begin, too For the full, up-to-date list of statements that perform an implicit COMMIT, see http://dev.mysql.com/doc/refman/6.0/en/implicit-commit.html.

Trang 7

A savepoint is a defined point in a transaction TheSAVEPOINTstatement is used to set a point with a name TheROLLBACK TO SAVEPOINTstatement is used to roll back the transac-tion to the named savepoint specified Instead of rolling back all the changes in the transaction,

save-ROLLBACK TO SAVEPOINT savepointnamerolls back modifications to rows made in the rent transaction after the savepoint atsavepointname The data is in the same state it was in atthe time the savepoint was reached by the transaction To remove the named savepoint from theset of defined savepoints in the current transaction, use theRELEASE SAVEPOINTcommand

cur-Here is an example showing the use of SAVEPOINTandRELEASE SAVEPOINT:

mysql> use test;

Database changed mysql> DROP TABLE IF EXISTS trans_test;

Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> CREATE TABLE trans_test (id INT PRIMARY KEY AUTO_INCREMENT, -> name VARCHAR(8)) ENGINE=InnoDB;

Query OK, 0 rows affected (0.12 sec) mysql> INSERT INTO trans_test (name) VALUES (’a’), (’b’);

Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT id,name FROM trans_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b | + + -+

2 rows in set (0.00 sec) mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec) mysql> UPDATE trans_test SET name=’z’ WHERE id = 1;

Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SAVEPOINT savepoint_one;

Query OK, 0 rows affected (0.00 sec) mysql> UPDATE trans_test SET name=’y’ WHERE id = 2;

Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0

Trang 8

mysql> SELECT id,name FROM trans_test;

+ + -+

| id | name | + + -+

| 1 | z |

| 2 | y | + + -+

2 rows in set (0.00 sec) mysql> ROLLBACK TO SAVEPOINT savepoint_one;

Query OK, 0 rows affected (0.00 sec) mysql> SELECT id,name FROM trans_test;

+ + -+

| id | name | + + -+

| 1 | z |

| 2 | b | + + -+

2 rows in set (0.00 sec) mysql> COMMIT;

Query OK, 0 rows affected (0.03 sec)

Notice that the first row still has aNAMEfield value of z, whereas the last row, whoseNAMEfieldvalue was changed toy, has reverted tol

AUTOCOMMIT

The use of theAUTOCOMMITstatement is another way to work with transactions ratherthan the more traditionalSTART TRANSACTIONorBEGIN To a transactional storageengine such as InnoDB or Falcon every statement is considered a transactional state-ment in itself ifAUTOCOMMITis enabled (AUTOCOMMIT = 1) The result of this is that if

AUTOCOMMITis enabled, which it is by default,mysqldwraps every statement withSTART TRANSACTIONandCOMMITstatements However, if you explicitly start a transaction with

START TRANSACTION, a new transaction is started andAUTOCOMMITis off for the newtransaction

After execution of a transaction using the START TRANSACTION and COMMIT commands mysqld reverts to the autocommit mode it was in before the transaction began This can cause unpredictable and undesirable results.

From our previous example of Ziesel and Hudson at the bank, here are the SQL statements weinitially used to update the two accounts:

UPDATE checking SET balance = balance - 1000 WHERE id = 145356; UPDATE checking SET balance = balance + 1000 WHERE id = 118254;

Trang 9

If you haveAUTOCOMMITenabled (which it is by default), here is whatmysqldactuallyexecutes:

mysql> SELECT id,name FROM trans_test;

+ + -+

| id | name | + + -+

| 1 | z |

| 2 | b | + + -+

2 rows in set (0.00 sec) mysql> SET AUTOCOMMIT=0;

Query OK, 0 rows affected (0.00 sec) mysql> UPDATE trans_test SET name=’a’ WHERE id=’1’;

Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> COMMIT;

Query OK, 0 rows affected (0.06 sec)

As you can see theSET AUTOCOMMIT=0statement works just as aBEGINorSTART TRANSACTIONstatement After theCOMMIT, a new transaction is started without needing

to useSTART TRANSACTION,BEGIN, orBEGIN WORK

Using Isolation Levels

Isolation levels determine how data is isolated among different transactions If you begin

a transaction, read a row from a table, change the row, read the same row from the table,and then commit, what do you see at each step? What does another transaction reading the

Trang 10

same row see at each step? The exact nature of what is isolated and under what conditions isdetermined by the isolation level.

In MySQL, the server can be set to a particular isolation level, and connections can also set theirisolation level, overriding the global isolation level For the purpose of defining isolation levels,

we will describe the behavior when all connections have the same isolation level as the server.After describing each level, we go into detailed examples of each isolation level

MySQL supports the four standard isolation levels:

■ READ UNCOMMITTED— This setting allows all transactions to see all uncommittedchanges, whether within their own transaction or in another transaction These are called

dirty reads — the data is said to be dirty because the change is not permanent yet Queries

inside one transaction are affected by uncommitted changes in another transaction This

is not desirable, and in fact violates ACID compliance Setting the isolation level toREAD UNCOMMITTEDgets rid of transaction support — though you can still wrap transactionswithSTART TRANSACTION,ROLLBACK, andCOMMIT, there is no isolation and thus yoursystem is no longer transactional

■ READ COMMITTED— Only data changed by committed transactions are visible to othertransactions However, within a transaction, dirty data can still be read This means iden-tical queries within a transaction can return differing results For example, if a transactionreads a row, changes the row, and reads the row again, both reads will produce differentdata, because the data was changed inside the transaction Other connections will see onlythe unchanged data, until the transaction is committed

READ COMMITTEDis the default isolation level for SQL Server and Oracle

■ REPEATABLE READ— The default isolation level for MySQL isREPEATABLE READ Atthe time of this writing, only the Falcon and InnoDB storage engines are transactional, sochanging isolation levels only applies to transactions that query tables that use Falcon orInnoDB

Using theREPEATABLE READisolation level, all reads within a transaction show the samedata values, even if a second transaction has committed a data change while the firsttransaction was still running If a transaction starts, reads a row, waits 60 seconds, andreads the same row again, both data reads will be the same — even if in those 60 secondsanother transaction has changed and committed data The first transaction has the samedata when it repeats the read Any transactions started after the data commit will see thenew data

REPEATABLE READmay not seem like a good idea — after all, if the data changes,shouldn’t a transaction be aware of that? The problem is that a transaction may takedifferent actions based on the values of the data Data values changing in the middle of

a transaction may lead to unexpected consequences Consider what would happen ifthe schema changed in the middle of a transaction, and the desired fields or tables cease

to exist!

■ SERIALIZABLE— In theSERIALIZABLEisolation level of MySQL, data reads areimplicitly run with a read lock (theLOCK IN SHARE MODEclause; see the example in the

Trang 11

‘‘Row-Level Locks’’ section later in this chapter) Other transactions can read the data, but

no transactions can update this data until all the read locks are released

READ UNCOMMITTEDis the easiest isolation level to implement and provides the fastest formance The problem withREAD UNCOMMITTEDis that it provides no isolation betweentransactions.READ COMMITTEDprovides some isolation and slightly slower performance, becauseonly committed data changes are seen by other transactions However,READ COMMITTEDdoesnot address the issue of data changing in the middle of a transaction.REPEATABLE READ

per-provides more isolation from a transaction, ensuring that data reads are the same throughoutthe transaction even if the data has been changed and committed by a different transaction The

SERIALIZABLEisolation level provides the slowest performance but also the most isolationbetween transactions

Themysqldisolation level is set by thetx_isolationsystem variable All connections to thedatabase default to using the isolation level set by the system variable If the system variable ischanged, new connections will use the new isolation level but existing connections continue touse the previous isolation level

In addition, isolation levels can be set per connection Though the flexibility of this system isnice, it does bring complexity in that you may have a server level setting of READ COMMITTED

and a connection with a session setting of READ UNCOMMITTED The connection with the

READ UNCOMMITTEDisolation setting will see uncommitted changes, even from connectionswith uncommitted transactions that changed data using theREAD COMMITTEDisolation level

In simpler terms, the isolation setting of the connection is the isolation setting used for anytransactions within that connection

To determine the isolation level of your connection:

mysql> SHOW SESSION VARIABLES LIKE ’tx_isolation’;

+ -+ -+

| Variable_name | Value | + -+ -+

| tx_isolation | READ-UNCOMMITTED | + -+ -+

1 row in set (0.00 sec) mysql> SELECT @@session.tx_isolation;

+ -+

| @@session.tx_isolation | + -+

| READ-UNCOMMITTED | + -+

1 row in set (0.00 sec) mysql> SELECT VARIABLE_NAME, VARIABLE_VALUE -> FROM INFORMATION_SCHEMA.SESSION_VARIABLES -> WHERE VARIABLE_NAME=’tx_isolation’;

Trang 12

| VARIABLE_NAME | VARIABLE_VALUE | + -+ -+

| TX_ISOLATION | READ-UNCOMMITTED | + -+ -+

1 row in set (0.07 sec)

To see the isolation level for the server:

mysql> SELECT @@global.tx_isolation;

+ -+

| @@global.tx_isolation | + -+

| REPEATABLE-READ | + -+

1 row in set (0.00 sec) mysql> SHOW SESSION GLOBAL VARIABLES LIKE ’tx%’;

+ -+ -+

| Variable_name | Value | + -+ -+

| tx_isolation | REPEATABLE-READ | + -+ -+

1 row in set (0.00 sec) mysql> SELECT VARIABLE_NAME, VARIABLE_VALUE -> FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -> WHERE VARIABLE_NAME=’tx_isolation’;

+ -+ -+

| VARIABLE_NAME | VARIABLE_VALUE | + -+ -+

| TX_ISOLATION | REPEATABLE-READ | + -+ -+

1 row in set (0.07 sec)

To change the server (global) or connection (session) isolation level you can execute either of thefollowingSETcommands:

SET @@{global|session}.tx_isolation= {read-uncommitted|

Trang 13

READ UNCOMMITED

Recall that theREAD UNCOMMITTEDisolation level provides no isolation, allowing dirty reads Tosee howREAD UNCOMMITTEDbehaves, open a connection, set the isolation level, and check tomake sure it is set appropriately:

mysql> SET @@session.tx_isolation=’READ-UNCOMMITTED’;

Query OK, 0 rows affected (0.00 sec) mysql> SHOW VARIABLES LIKE ’tx_isolation’;

+ -+ -+

| Variable_name | Value | + -+ -+

| tx_isolation | READ-UNCOMMITTED | + -+ -+

1 row in set (0.00 sec)

To make it easier to keep track of connections, change the prompt of this connection

to ‘my1> ’ — make sure there is one space after >:

mysql> prompt my1>

PROMPT set to ’my1> ’ my1>

Open a second connection without closing the first connection, and set the prompt and isolationlevel toREAD UNCOMMITTED Return to your first connection and perform the following:

my1> use test;

Database changed my1> CREATE TABLE isolation_test (id INT PRIMARY KEY AUTO_INCREMENT, -> name VARCHAR(8)) ENGINE=InnoDB;

Query OK, 0 rows affected (0.35 sec) my1> INSERT INTO isolation_test (name) -> VALUES (’a’),(’b’);

Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 my1> SELECT id,name FROM isolation_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b | + + -+

2 rows in set (0.00 sec)

Trang 14

Next execute the following commands in your second connection:

my2> use test;

Database changed my2> BEGIN;

Query OK, 0 rows affected (0.00 sec) my2> INSERT INTO isolation_test (name) VALUES (’c’),(’d’);

Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0

Returning to your first connection:

my1> SELECT id,name FROM isolation_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b |

| 3 | c |

| 4 | d | + + -+

4 rows in set (0.00 sec)

Notice that the first connection can read the uncommittedcanddvalues of connection two.This is the essence of theREAD UNCOMMITTEDisolation level

Returning to the second connection:

my2> ROLLBACK;

Query OK, 0 rows affected (0.01 sec)

Now that you have rolled the transaction back in the second connection, return to the first:

my1> SELECT id,name FROM isolation_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b | + + -+

2 rows in set (0.00 sec)

The first connection sees the data rolled back.READ UNCOMMITTEDcan provide for dictable results!

Trang 15

unpre-READ COMMITTED

As stated before, an isolation level of READ COMMITTEDeliminates dirty reads To see

an example you once again use two connections, setting the isolation level in both to

READ COMMITTED Once they are set and double-checked, do the following in the firstconnection:

my1> START TRANSACTION;

my1> SELECT id,name FROM isolation_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b | + + -+

2 rows in set (0.00 sec)

In the second connection:

Returning to your first connection:

my1> SELECT id,name FROM isolation_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b | + + -+

2 rows in set (0.00 sec)

Notice that this connection does not see the data changes the second connection made — thereare no dirty reads

Unfortunately, a second situation called an inconsistent read is possible An inconsistent read

is when a transaction reads data that has changed during transaction execution Though thechanged data was committed by another transaction, a transaction already in progress depends

on the data not being changed by another transaction

Trang 16

To show this, commit the changes made in the second connection:

my2> COMMIT;

Query OK, 0 rows affected (0.05 sec)

Returning to the first connection, check theisolation_testtable and you will see thenew data:

my1> SELECT id,name FROM isolation_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b |

| 3 | c |

| 4 | d | + + -+

4 rows in set (0.00 sec)

Once the transaction in the second connection was committed the results became visible

to the first connection, even though the first connection was already open and had already readthe data once, with the original values

REPEATABLE READ

With aREPEATABLE READisolation level there is no possibility of either dirty or inconsistentreads To prove this to yourself, repeat the previous example with thetx_isolationlevel set

toREPEATABLE READfor both connections

TheREPEATABLE READisolation level allows a transaction to see the same data for values it hasalready read regardless of whether or not the data has been changed Unfortunately, this leads to

a problem called a phantom read, because it reads data that no longer exists.

As an example, a company generates reports based on customer invoice data Set your tions to theREPEATABLE READisolation level, and in the first connection populate a table andstart a transaction:

connec-my1> CREATE TABLE invoice (customer_id INT NOT NULL, -> invoice_date DATE NOT NULL) ENGINE=InnoDB;

Query OK, 0 rows affected (0.38 sec) my1> INSERT INTO invoice (customer_id,invoice_date) -> VALUES (1,’2008-10-07’), (1,’2008-11-15’), (2,’2009-01-01’); Query OK, 3 rows affected (0.00 sec)

Records: 3 Duplicates: 0 Warnings: 0 my1> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

Trang 17

my1> SELECT customer_id, invoice_date -> FROM invoice WHERE invoice_date > ’2008-10-01’;

+ -+ -+

| customer_id | invoice_date | + -+ -+

| 1 | 2008-10-07 |

| 1 | 2008-11-15 |

| 2 | 2009-01-01 | + -+ -+

3 rows in set (0.00 sec)

The first connection represents a data processor — imagine that it processes the data for ing While this is going on, the following happens in a second connection:

| 2 | 2009-01-01 | + -+ -+

1 row in set (0.00 sec)

In the first connection, however, three rows of data appear:

my1> SELECT customer_id, invoice_date FROM invoice;

+ -+ -+

| customer_id | invoice_date | + -+ -+

| 1 | 2008-10-07 |

| 1 | 2008-11-15 |

| 2 | 2009-01-01 | + -+ -+

3 rows in set (0.00 sec)

The first transaction is still seeing the first two records, which have already been deleted It isdoing a phantom read of those two records

The phantom read was introduced by trying to fix the inconsistent read problem inREAD UNCOMMITTED However,READ UNCOMMITTEDstill allows other transactions to change the data.The ideal scenario is one where data read by one transaction cannot be modified by another atall This is theSERIALIZABLEisolation level

Trang 18

With theSERIALIZABLEisolation level, updates are not permitted by a transaction if anothertransaction has already read the data Set both connections to use theSERIALIZABLEisolationlevel, and in the first connection:

my1> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec) my1> SELECT id,name FROM isolation_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b |

| 3 | c |

| 4 | d | + + -+

4 rows in set (0.00 sec)

In the second connection begin a transaction:

my2> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec) my2> UPDATE isolation_test SET name=’z’ WHERE id=1;

The query in your second connection hangs — it is waiting for the first connection to releasethe implicit read lock it has on the data If the second connection exceeds the lock wait timeoutvalue, you will see:

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

If your second connection has timed out, run theUPDATEagain, andCOMMITthe transaction inconnection one:

my1> COMMIT;

Query OK, 0 rows affected (0.00 sec)

Your second connection should show that the update completed Note the amount of timerequired to complete the update in connection two because of this locking:

Query OK, 1 row affected (14.09 sec) Rows matched: 1 Changed: 1 Warnings: 0

Trang 19

At this point both connections should see the update to the table — the first connection hascommitted, and any new transactions will see the new data Do not forget to commit yourtransaction in connection two:

my2> COMMIT;

Query OK, 0 rows affected (0.09 sec)

Although theSERIALIZABLEisolation level provides the most isolation available, it is oftenboth excessive and not efficient With both the InnoDB and Falcon storage engines techniquesare implemented such as next-key locking and multi-version concurrency control (see the nextsection) that effectively eliminate problems caused by phantom rows TheREPEATABLE READ

isolation will provide for better concurrency, so unless there is some special reason, this should

be the preferred isolation level Changing the isolation level is very rare and should only be donevery carefully

You can find a good article written by one of the book’s authors showing more examples of each isolation level at http://sheeri.com/node/144.

Multi-version concurrency control

TheREPEATABLE READisolation level can only occur if each transaction has its own virtualview of the data it reads and writes This is accomplished in InnoDB and Falcon by using

multi-version concurrency control (MVCC).

MVCC is a versioning system for data, just like there are version control systems for code (cvs,

Subversion,Mercurial, and so on) When a transaction starts, you can think of it as ing out a copy of the data as it is at the start of the transaction Note that the mechanics are notthe same, but the concept is — in version control systems, an actual local copy of code is made,which would be impossibly unwieldy on a system with many transactions and a large amount

check-of data Needless to say, MVCC has a very complex job when managing hundreds check-of concurrenttransactions

If a second transaction starts, it ‘‘checks out’’ its own copy of the data If the first transactionmakes changes and commits, the second transaction will not see the data The second trans-action can only work with the data it has There is no way to update the data that the secondtransaction sees, though the second transaction could issue aROLLBACKand start the transactionagain to see the new data

The drawback of MVCC is the cost of storing multiple versions of objects in the database Thebenefit is that queries are not blocked as they are in theSERIALIZABLEisolation level MVCCgreatly increases the concurrency ability for transactional storage engines

Trang 20

Explaining Locking and Deadlocks

Locks are used by a thread to keep other threads from modifying data in the area of thedatabase that is locked Locks are one way to enforce isolation — if a transaction cannot read orwrite data, it is isolated from other transactions There are two types of locks — read locks andwrite locks:

■ Read Lock — The locked data is reserved for reading by the current thread Otherthreads can read the locked data, but they cannot change the locked data A read lock isalso called a shared lock, because more than one thread can have a read lock on data

■ Write Lock — The locked data is reserved for writing by the current thread Otherthreads can neither read nor write the locked data A write lock is also called an exclusivelock, because only one thread at a time can have a write lock on data

There are three levels of locking:

■ Table Lock — The entire table is locked

■ Page Lock — The lock is set at the memory page level A page is a group of rows Theexact row count can vary depending on a number of factors but it will typically be a subset

of one entire table

■ Row Lock — The lock is set at the row level Each row being read or written to is locked

Different storage engines use different levels of locking We cover each of these locking levels inthe next three sections

A deadlock is when two transactions are simultaneously trying to access the same data in the

database, and each transaction has locked data that the other transaction needs to continue.Without being able to continue, the transactions will not release their existing lock on the data.More specifically, one transaction holds a lock on one set of rows and is requesting a lock

on another set of rows; those rows are locked by a second transaction that is simultaneouslyrequesting a lock on the rows locked by the first transaction

For example, consider the following timeline:

1 Transaction one (T1) requests a write lock on Table B, rows 23 and 78.

2 T1 receives a write lock on Table B, rows 23 and 78 No other transaction can read or

write these rows

3 Transaction two (T2) requests a write lock on Table A, rows 10 and 15.

4 T2 receives a write lock on Table A, rows 10 and 15 No other transaction can read or

write these rows

5 T1 requests a write lock on Table A, rows 10 and 15.

6 T1 waits for the write lock to be granted, which cannot happen until T2 releases its lock.

Trang 21

7 T2 requests a write lock on Table B, rows 23 and 78.

8 T2 waits for the write lock to be granted, which cannot happen until T1 releases its lock.

T1 and T2 are waiting for each other to release the lock, but neither will release its own lockbecause they are not done using it yet Figure 9-1 shows the stalemate happening

Transaction Two

Unless there is some intervention by the client or the database server, these two transactionswould wait forever for the other to release the lock The database server can manage the dead-lock by having what is called a lock wait time value What this means is that if the time that thelocks that are held by the transactions exceed the lock wait time value waiting to be released,one of the transactions is rolled back so the other transaction can complete The InnoDB storageengine will often recognize that a deadlock has occurred and kill one of the transactions beforethis limit is actually reached

There are three different lock wait timeout variables:

mysql> SHOW GLOBAL VARIABLES LIKE ’%lock_wait_timeout’;

+ -+ -+

| Variable_name | Value | + -+ -+

| falcon_lock_wait_timeout | 50 |

| innodb_lock_wait_timeout | 50 |

| table_lock_wait_timeout | 50 | + -+ -+

3 rows in set (0.00 sec)

These system variables can be set dynamically, and can be set on a GLOBAL or SESSION level The default values are, as shown, 50 seconds for table-level locks and row-level locks in Falcon and InnoDB.

Trang 22

Table-level locks

Using only table-level locking, if a query accesses the table it will lock the entire table It ispossible to request many table-level locks at one time; however, a table-level lock requestreleases all currently held table-level locks One benefit of this type of locking is that it entirelyeliminates deadlocking issues, because all locks are requested at the same time There is no way

to request a table-level lock, wait, and request another table-level lock without releasing thefirst table-level lock Another benefit is that only one lock is needed to change all the rows in

a table — larger tables require more overhead with more granular locking levels For example,

a thread updating a table with a million rows using row-level locking must acquire and release amillion locks, whereas updating the same table with table-level locking requires only one lock to

be acquired and released

The biggest disadvantage of table-level locking is that when a thread has locked a table with awrite lock, no other queries have access to the table If you have a table with a million rows andneed to modify one row, the entire table is inaccessible by other threads for the time it takes tomodify that one row TheLOCK TABLESandUNLOCK TABLEScommands are used bymysqld

to acquire and release table-level locks on any table, regardless of storage engine The MyISAMand MEMORY storage engines use table-level locking by default because it is the only level oflocking available to those storage engines

TheLOCK TABLESstatement tries to acquire table-level locks on one or more tables It implicitlyreleases all previously held locks by the thread:

LOCK TABLES tbl_name {READ | WRITE}[, tbl_name {READ | WRITE}, ];

TheUNLOCK TABLESstatement can be used to explicitly unlock all previously held locks by thethread:

UNLOCK TABLES;

The following example code shows how a read-locked table in one session will affect the sametable’s usage in a second session

To begin, set a prompt for the first connection and create a new table:

mysql> prompt my1>

PROMPT set to ’my1> ’ my1> use test;

Database changed my1> DROP TABLE IF EXISTS lock_test;

Query OK, 0 rows affected, 1 warning (0.00 sec) my1> CREATE TABLE lock_test (id INT PRIMARY KEY AUTO_INCREMENT, -> name VARCHAR(8)) ENGINE=MyISAM;

Query OK, 0 rows affected (0.37 sec) my1> INSERT INTO lock_test (name) VALUES (’a’);

Query OK, 1 row affected (0.00 sec)

Trang 23

my1> LOCK TABLES lock_test READ;

Query OK, 0 rows affected (0.00 sec) Open a second connection and execute the following:mysql> prompt my2> PROMPT set to ’my2> ’

my2> use test;

Database changed my2> SELECT id,name FROM lock_test;

+ + -+

| id | name | + + -+

| 1 | a | + + -+

1 row in set (0.00 sec) my2> INSERT INTO lock_test (name) VALUES (’b’);

When you enter theINSERTstatement it will not return a prompt This connection is nowblocked waiting for the first connect to release the read lock that it is holding on the table

something like this in connection two at this point:my2> INSERT INTO lock_test (name) VALUES (’b’);

Query OK, 1 row affected (3 min 2.26 sec)

Notice that it took over three minutes to complete thisINSERTcommand, because it waited forthe lock to be released After connection two finishes theINSERTstatement, look at the table:

mysql> SELECT id,name FROM lock_test;

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b | + + -+

2 rows in set (0.00 sec)

The next part of the example shows the use of a write lock To begin, lock the table from yourfirst connection:

my1> LOCK TABLES lock_test WRITE;

Query OK, 0 rows affected (0.00 sec)

Trang 24

Once this is done, attempt to read data from thelock_testtable from your secondconnection:

my2> SELECT id,name FROM lock_test;

When you attempt to do this yourSELECTstatement will be blocked waiting for the release

of the write lock acquired by your first connection Go back to your first connection and releasethe write lock:

my1> UNLOCK TABLES;

Query OK, 0 rows affected (0.00 sec)

Once the write lock is released theSELECTstatement in your second connection finishes:

+ + -+

| id | name | + + -+

| 1 | a |

| 2 | b | + + -+

2 rows in set (22.34 sec)

Notice that theSELECTstatement could not be fulfilled until the write lock was released In thiscase it took 22.34 seconds to wait for the write lock to be released and perform theSELECT

In the first part of the example the second connection could see the data in the table the firstconnection had locked In the second part of the example the second connection could not evensee the data that was locked This is the fundamental difference between a read and write lock.Managing multiple table-level lock requests is a bit complicated If a thread requests either type

of table-level lock and no thread currently holds any locks on the table, the lock is immediatelyacquired by the thread If a lock cannot be acquired immediately, it is placed in a queue There

is one queue for table-level read locks, and another for table-level write locks

If a thread already has a write lock on a table, no locks can be acquired immediately If athread already has a read lock on a table, only another read lock can be acquired immediately.Table-level write locks have higher precedence than table-level read locks by default in MySQL.When a thread releases the final lock on a table, a lock on that table from the write lock queue

is acquired next Table-level locks in the read lock queue are acquired only after all the writelocks for that table are acquired and released

If your database server has a large number of INSERT,DELETE, orUPDATEstatements beingprocessed on a table that is using table-level locking, there is a real possibility thatSELECTstate-ments on that table will be waiting for a long period of time The write lock precedence behav-ior can be changed in many ways Write locks can be set as lower priority than read locks glob-ally by startingmysqldwith thelow-priority-updatesoption, or by issuing:

mysql> SET GLOBAL low_priority_updates=1;

Trang 25

Though this is a dynamic system variable, only new connections will use the new value To setall writes in a session as lower priorities than reads, use the following command:

mysql> SET SESSION low_priority_updates=1;

To set individual writes as lower priorities, use theLOW PRIORITYclause inINSERT,UPDATE,andDELETEstatements To set individual reads as higher priorities, use theHIGH PRIORITY

clause in aSELECTstatement See Chapter 4 for more details

Lock acquisition behavior can also be controlled with the max_write_lock_count and concurrent_insert system variables The MySQL manual has this tip and many ideas on how to work around table locking issues at http://dev.mysql.com/doc/

refman/6.0/en/table-locking.html.

Page-level locks

Page-level locking is when a memory page is locked This will lock a group of rows instead ofthe entire table The number of rows locked will vary based on a number of factors, includingthe amount of memory allocated to a page, the size of the rows, and amount of fragmentation.Going back to our previous example of a table with a million rows, assume a page-level lock

is used If a page consists of 1,000 rows, a lock would be placed on 1,000 rows at a time Any

of the other 999,000 rows (stored in 999 memory pages) could be used by other queries out waiting, because there is no lock for that data Unlike table-level locking, page-level lockingallows deadlocking to occur The BDB storage engine is the only storage engine using page-levellocking and it was removed frommysqldby version 5.1

with-Row-level locks

Row-level locking allows locks to be acquired on the row-by-row basis This will both block theminimal amount of table content and allow for the most concurrency on a table InnoDB andFalcon implement row-level locking Deadlocking can occur with row-level locking Following

is an example using the InnoDB storage engine

To demonstrate row-level locking, use theLOCK IN SHARE MODEclause of theSELECTstatement

to place a row-level lock on data To begin, open your first connection to the database serverand do the following:

mysql> prompt my1>

PROMPT set to ’my1> ’ my1> DROP TABLE IF EXISTS lock_test;

Query OK, 0 rows affected (0.00 sec) my1> CREATE TABLE lock_test (id INT PRIMARY KEY AUTO_INCREMENT, -> name VARCHAR(8)) ENGINE=InnoDB;

Query OK, 0 rows affected (0.38 sec)

Ngày đăng: 21/01/2014, 22:20

TỪ KHÓA LIÊN QUAN

w