Availability ArchitecturesIN THIS CHAPTER Scaling MySQL Synchronizing data Automating failover In these days of an online world where applications need to run all the time, and need to r
Trang 1mysql_version.h is not in the source package, but it is in the mysql-devel
package (the compilation process creates mysql_version.h later on) Unfortunately
mysql_priv.h is only in the source package, not the mysql-devel package, so you need to download both the source and the mysql-devel packages.
On an abstract level, making a custom system view in theINFORMATION_SCHEMAdatabaserequires:
■ The field definitions of the system view (that is, the structure of the system view) In ourexample, we define a system view namedMYSQL_HELLOwith a field defined asHELLO VARCHAR(64) NOT NULL DEFAULT `’
■ The function that populates the system view upon request (that is, the values in thesystem view) We will define a function to store the stringplugin: hello, information_schema!!!into theHELLOfield of ourMYSQL_HELLOsystem view
On a more technical level, to create the custom system view, you need to instantiate the
ST_SCHEMA_TABLEstruct and define two members One member,field_info, is an array
ofST_FIELD_INFOstructures, which define the fields in your system view The values in the
ST_FIELD_INFOstructure are defined in the source code in thesql/table.hheader file andexplained in Table 21-3
uint field_length; In string-type fields, the maximum
number of characters In other fields, the display length.
64 in our example, a string-type field
enum enum_field_types field_type;
Field data type MYSQL_TYPE_VARCHAR
uint field_flags; 0 means NOT NULL and SIGNED It
can be overridden by MY_I_S_MAYBE_NULL, MY_I_S_UNSIGNED, or both constants, separated by | (bitwise or).
0
const char* old_name; Old field name ‘‘Hello’’
uint open_method; How the table is opened One of
SKIP_OPEN_TABLE, OPEN_FRM_ONLY, or OPEN_FULL_TABLE.
SKIP_OPEN_TABLE
Trang 2Our example contains the following code to define the custom system view:
8 static ST_FIELD_INFO mysql_is_hello_field_info[]=
The next line of code is:
13 int schema_table_store_record(THD *thd, TABLE *table);
This line declares theschema_table_store_recordfunction, which we will use later to store
a row in a system view
The second member of ST_SCHEMA_TABLEthat we need to define is the function that populatesthe system view, called thefill_table:
22 TABLE *table= (TABLE *)tables->table;
23 const char *str = "plugin: hello, information_schema!!!";
In lines 15–17 we seeTHD *thdagain, pointing to the current session, andTABLE_LIST
*tables, which is an array of table instantiations of our ‘‘Hello’’ system view.COND *condis acondition that could be used by our plugin for filtering or optimization, though we will not use
it in this example
Trang 3Thestatusvariable is initialized as aninton line 20 At the end of the function (line 33),
statusis returned; a value of 1 indicates an error, and a value of 0 indicates success Then online 21,CHARSET_INFO *scsis initialized with the character set information This is needed toproperly store the field of our system view
On line 22,TABLE *tableis set as the handler to the instantiation of our system view We tialize thechar *stron line 23 with the string we will store in our system view This meansthat when we finally install the plugin, we will seestrin our system view:
ini-mysql> SELECT * FROM INFORMATION_SCHEMA.MYSQL_HELLO;
1 row in set (0.00 sec)
Lines 24–28 store the stringstr, its length, and the character setscs(defined on line 21) intothe first field (field[0]) of the row Lines 29–32 store the row into the instantiation of oursystem view for the current session If the function that stores the row is successful,statusgets
a value of 0 If there was an error,statusgets a value of 1.statusis returned on line 33,thus giving themysql_is_hello_fill_tablefunction a return value of 0 if it is successfuland 1 if there was an error
So far we have defined a system view in anST_FIELD_INFOarray and afill_tablefunction
to populate the system view We now need to create a plugin function to use these:
35 static int mysql_is_hello_plugin_init(void *p)
plugin_initfunction, we have a simpleplugin_deinitfunction as well:
42 static int mysql_is_hello_plugin_deinit(void *p)
Trang 4sim-At this point, we still have not created the plugin However, we have most of the parts we need
to make anINFORMATION_SCHEMAplugin, and can now create the code to define the pluginitself:
46 struct st_mysql_information_schema mysql_is_hello_plugin=
63 mysql_declare_plugin_end;
Lines 46–47 define the type descriptor for the plugin, which is set as part of the plugin in line
51 Line 50 defines the type of plugin as anINFORMATION_SCHEMAplugin Lines 52–55 definemetadata that appear after plugin installation in thePLUGINSsystem view as thePLUGIN_NAME,
PLUGIN_AUTHOR,PLUGIN_DESCRIPTION, andPLUGIN_LICENSEfields, respectively
Lines 56–57 point to the previously createdplugin_initandplugin_deinitfunctions, andline 58 defines the version metadata, which corresponds to the value ofPLUGIN_VERSIONinthePLUGINSsystem view Lines 59–61 are pointers to structures containing the status variables,system variables, and configuration options Our plugin does not have any of these, so we definethem asNULL
The entirety of the code is:
#include <mysql_priv.h>
#include <stdlib.h>
#include <ctype.h>
Trang 5int schema_table_store_record(THD *thd, TABLE *table);
int mysql_is_hello_fill_table(
THD *thd , TABLE_LIST *tables , COND *cond
) { int status;
CHARSET_INFO *scs= system_charset_info;
TABLE *table= (TABLE *)tables->table;
const char *str = "plugin: hello, information_schema!!!";
table->field[0]->store(
str , strlen(str) , scs
);
status = schema_table_store_record(
thd , table );
return status;
} static int mysql_is_hello_plugin_init(void *p) {
ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p;
schema->fields_info= mysql_is_hello_field_info;
schema->fill_table= mysql_is_hello_fill_table;
return 0;
} static int mysql_is_hello_plugin_deinit(void *p) {
return 0;
}
Trang 6struct st_mysql_information_schema mysql_is_hello_plugin=
{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
mysql_declare_plugin(mysql_is_hello) {
} mysql_declare_plugin_end;
Compiling the plugin
Now that the code has been created, we need to compile the plugin as a dynamic shared objectand then load it intomysqld In our example we will save the source code in a file named
mysql_is_hello.cc, and useg++to compile the source Table 21-4 shows the compile flags
we will use and their meanings
So the complete compile statement is:
shell> g++ -DMYSQL_DYNAMIC_PLUGIN –Wall – shared \ -I/path/to/mysql-6.0.x-source/include \
-I/path/to/mysql-6.0.x-source/sql \ -I/usr/include/mysql \
Trang 7error: stdlib.h: No such file or directory error: ctype.h: No such file or directory
you should specify the include path for stdlib.h and ctype.h with another -I flag.
Some architectures, such as AMD64, require shared libraries to be compiled with the –fPIC flag.
If your architecture requires this, you will see output similar to the following when you try to compile:
/usr/bin/ld: /tmp/ccNXOEqH.o: relocation R_X86_64_32S against `a local symbol’ can not be used when making a shared object;
recompile with – fPIC /tmp/ccNXOEqH.o: could not read symbols:
Bad value collect2: ld returned 1 exit status
In this case, simply add –fPIC to the list of compile flags and try to compile again.
TABLE 21-4
g ++ Compile Flags for Compiling a Plugin as a Dynamic Shared Object
-DMYSQL_DYNAMIC_
PLUGIN
-D indicates a constant; the constant is MYSQL_DYNAMIC_PLUGIN, which is required to compile the plugin as a dynamic shared object for mysqld.
-Wall -W indicates warnings should be shown; all specifies
showing all warnings.
-shared Compile as a shared, dynamically linked library.
6.0.x-source/include
-I/path/to/mysql-The include path for the my_global.h, my_dir.h, and mysql/plugin.h header files.
6.0.x-source/sql
-I/path/to/mysql-The include path for the mysql_priv.h header file.
-I/usr/include/mysql The include path for the mysql_version.h header file.
-o mysql_is_hello.so The output file The extension so is traditionally used
for shared objects.
If all goes well, a dynamic shared plugin will be created with a filename ofmysql_is_
hello.so
Trang 8Installing the plugin
MySQL plugins are installed inmysqldusing a MySQL extension to SQL Thus,mysqldmust
be running, and no downtime is required to install a plugin For security purposes,mysqldonlylooks for plugin libraries in the directory specified by the system variableplugin_dir:
mysql> SHOW VARIABLES LIKE ’plugin_dir’;
+ -+ -+
+ -+ -+
| plugin_dir | /usr/lib64/mysql/plugin | + -+ -+
1 row in set (0.01 sec)
For our example, we make sure the plugin directory exists, copy the plugin to themysqldgin directory, and ensure that the directory and plugin have appropriate permissions somysqld
plu-can load the plugin:
shell> mkdir /usr/lib64/mysql/plugin/
shell> cp mysql_is_hello.so /usr/lib64/mysql/plugin shell> sudo chown –R mysql:mysql /usr/lib64/mysql/plugin/
Now we use theINSTALL PLUGINstatement to install our plugin The syntax of INSTALL PLUGINis:
INSTALL PLUGIN plugin_name SONAME ’plugin_library’;
Theplugin_namewas set in the plugin metadata (on line 52 of our code) The
plugin_libraryis the name of the compiled plugin file (the complete path to the plugin file
isplugin_dir/plugin_library):
mysql> INSTALL PLUGIN MYSQL_HELLO SONAME ’mysql_is_hello.so’;
Query OK, 0 rows affected (0.00 sec)
And our plugin has successfully been installed:
mysql> SELECT * FROM INFORMATION_SCHEMA.MYSQL_HELLO;
1 row in set (0.00 sec)
We can now see our plugin in themysql.pluginsystem table and theINFORMATION_ SCHEMA.PLUGINSsystem view:
mysql> SELECT * FROM mysql.plugin -> WHERE name=’MYSQL_HELLO’\G
Trang 9*************************** 1 row ***************************
name: MYSQL_HELLO dl: mysql_is_hello.so
1 row in set (0.00 sec) mysql> SELECT * FROM INFORMATION_SCHEMA.PLUGINS -> WHERE PLUGIN_NAME=’MYSQL_HELLO’\G
*************************** 1 row ***************************
PLUGIN_NAME: MYSQL_HELLO PLUGIN_VERSION: 0.21
PLUGIN_STATUS: ACTIVE PLUGIN_TYPE: INFORMATION SCHEMA PLUGIN_TYPE_VERSION: 60006.0
PLUGIN_LIBRARY: mysql_is_hello.so PLUGIN_LIBRARY_VERSION: 1.0
PLUGIN_AUTHOR: Roland Bouman (http://rpbouman.blogspot.com/) PLUGIN_DESCRIPTION: Says hello.
PLUGIN_LICENSE: GPL
1 row in set (0.00 sec)
To uninstall the plugin, runUNINSTALL PLUGIN plugin_name:
mysql> UNINSTALL PLUGIN MYSQL_HELLO;
Query OK, 0 rows affected (0.00 sec)
The plugin is loaded when theINSTALL PLUGINis run If you want to change the plugin youhave to uninstall the plugin, change the plugin file, and re-install the plugin If the plugin filechanges or is removed while installed on a running server,mysqldwill most likely crash
Summary
This chapter described the information contained in the MySQL data dictionary, including:
■ All of the metadata in the system views of theINFORMATION_SCHEMAdatabase
■ ManySHOWstatements (see Chapter 4 for the remainder of theSHOWstatements that showmetadata)
■ Many of the system tables in themysqldatabase
■ Creating custom metadata asINFORMATION_SCHEMAplugins
Trang 11Availability Architectures
IN THIS CHAPTER
Scaling MySQL Synchronizing data Automating failover
In these days of an online world where applications need to run all the
time, and need to run quickly, scaling and high availability are very
important MySQL’s cost and three basic tenets of fast, reliable, and
easy-to-use have redefined the database market These days, those without
advanced training and large amounts of money can create successful cations with database backends In many ways, you can scale more andhave a higher availability just by using MySQL instead of another databaseproduct
Scaling and high availability are both very important to a successful
appli-cation Scaling means an application works with acceptable speed when there are one hundred users or one hundred million users High availabil-
ity means that the application is up and running for much of the time Not
all architectures that provide scaling will provide high availability, and viceversa
A simple way to scale is to upgrade your hardware to a configurationwith faster CPUs and disk, and more CPUs and RAM This is costly, and
only scales to a certain point This is called scaling up, or vertical scaling, because you are upgrading the hardware Horizontal scaling, or scaling out,
increases the maximum capacity of your database architecture by addingmore database servers
One of the best ways to scale is to make sure your queries are running asquickly as possible If a database can handle 2,000 writes per second, there
is no architectural solution that will allow the database to handle morethan that If a write query can run faster, the same database will be able tohandle more writes per second Query optimization, schema optimization,
Trang 12data reduction, and server tuning are ways to make a query run faster We cover data tion and query and schema optimization in Chapter 18 Server tuning is covered in Chapter 10.
reduc-If your queries are running as fast as they possibly can, but there is a large amount of data towade through, you may want to partition your data We discuss different ways to partition inChapter 15
This chapter goes through a number of technologies, which can be used for high availability orscalability:
is used Through measurement, planning, flexibility, and risk assessment, high availability andscalability can be achieved and maintained
Replication
The basics of replication, and how to set up replication, are discussed in detail in Chapter 16.Replication allows copies of data to be kept asynchronously on different servers In traditionalmaster/slave replication, where a master database server replicates to a slave database server, allwrites must occur on the master database server A write to a master server needs to propagate
Trang 13to any slaves, so there is no real way to reduce the number of writes to a machine using cation However, reads can be done on either the master or the slave, and because no data ischanged, nothing needs to propagate.
repli-If your application has a high ratio of reads to writes, you can move some or all of the load erated by reads a different server Thus, replication can be a scaling technique
gen-Replication can also be a technique for high availability If a master server cannot be reached, aslave can be promoted to be a master server The slave is already loaded with the data, so there
is no need to spend time restoring from a backup
One read slave
A machine can have many slaves, but a machine can have only one master The traditional ter/slave replication architecture can be represented by Figure 22-1
mas-FIGURE 22-1
db1 db2
If db1 cannot be accessed, an administrator will promote db2 to a master server This is often
called failover — a server failed, so the slave will be promoted Some administrators use the term
switchover when they are promoting a slave when the master has not failed, for instance if the
master needs to be taken offline for maintenance Unfortunately, MySQL does not ship with atool to automate slave promotion; however, automation is possible using scripts and heartbeattools MySQL Proxy or Linux-HA Heartbeat (described later in this chapter) can be used withreplication to achieve an automated failover solution
Promoting a new master
Promoting a slave is not a difficult task, though many steps are involved
Gather information
■ Determine if the slave to be promoted is read-only
■ Determine if the slave to be promoted has binary logging enabled
■ Decide if you want to reset the binary logs on the slave to be promoted — this willdelete any previous binary logs and reset the binary log to the first binary log (default is
mysql-bin.000001)
■ Check for other slaves that will need to be changed to replicate the new master
Trang 14Make sure the slave is caught up applying its relay logs
When the information has been gathered, make sure the slave’s SQL thread has caught up tothe slave’s I/O thread That is, make sure all the statements in the relay logs have been applied.Compare the parametersRead_Master_Log_Pos, the position at which the I/O thread has readfrom the master’s binary logs, andExec_Master_Log_Pos, which is the position at which theSQL thread has finished applying the logs:
mysql> show slave status\G
*************************** 1 row ***************************
Slave_IO_State: Reconnecting after a failed master event read
Master_Host: 192.168.1.1 Master_User: master_user Master_Port: 3306
Connect_Retry: 60 Master_Log_File: mysql-bin.000051 Read_Master_Log_Pos: 3253467
Relay_Log_File: slave-relay-bin.000072 Relay_Log_Pos: 3253613
Relay_Master_Log_File: mysql-bin.000051 Slave_IO_Running: No
Slave_SQL_Running: Yes Replicate_Do_DB:
Skip_Counter: 0 Exec_Master_Log_Pos: 3253467 Relay_Log_Space: 3253782 Until_Condition: None Until_Log_File:
Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File:
Last_IO_Errno: 2013 Last_IO_Error: error reconnecting to master
’master_user@192.168.1.1:3306’ - retry-time: 60 retries: 86400
Trang 15Last_SQL_Errno: 0 Last_SQL_Error:
1 row in set (0.00 sec)
In this sample,Read_Master_Log_PosandExec_Master_Log_Posare the same value(3253467) This shows that the slave has applied all of the logs it has read from the mas-ter, and is ready to become a master If theExec_Master_Log_Posis less than the
Read_Master_Log_Pos, you will need to wait until the slave SQL thread catches up before youpromote the slave to a master; otherwise there will have been transactions that completed on theold master that do not appear on the new master
Stop and reset the slave process
Stop the slave with theSTOP SLAVEcommand, and then ensure the slave will not accidentallybecome re-enabled and try to read from the master by clearing out the slave information Youcan do this with theRESET SLAVEcommand:
mysql> RESET SLAVE;
Query OK, 0 rows affected (0.52 sec) mysql> show slave status\G
*************************** 1 row ***************************
Slave_IO_State:
Master_Host: 192.168.1.1 Master_User: master_user Master_Port: 3306
Connect_Retry: 60 Master_Log_File:
Read_Master_Log_Pos: 4 Relay_Log_File: slave-relay-bin.000001 Relay_Log_Pos: 4
Relay_Master_Log_File:
Slave_IO_Running: No Slave_SQL_Running: No Replicate_Do_DB:
Skip_Counter: 0 Exec_Master_Log_Pos: 0 Relay_Log_Space: 126 Until_Condition: None Until_Log_File:
Trang 16Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File:
Last_IO_Errno: 2013 Last_IO_Error: error reconnecting to master
’master_user@192.168.1.1:3306’ - retry-time: 60 retries: 86400
Last_SQL_Errno: 0 Last_SQL_Error:
1 row in set (0.00 sec)
Note that though the connection parameters (Master_Host,Master_User, andMaster_ Port) have not changed, theSlave_IO_Statehas been reset, and so have the master logand relay log parameters (Master_Log_File,Read_Master_Log_Pos,Relay_Log_File,
Relay_Log_Pos,Relay_Master_Log_File,Exec_Master_Log_Pos, andRelay_Log_ Space) If you look at the data directory, you will note that themaster.infofile has disap-peared, and if you search where the relay logs are kept, you will note that therelay-log.info
file and relay logs are gone Although those files have been deleted, MySQL has the connectioninformation cached in memory To make the slave information truly disappear, themysqld
process needs to be restarted
You can find more information on the how the master.info and relay-log.info files relate to replication in Chapter 16.
Change configuration parameters
If the slave is set asread_only, you will want to change that so writes can occur once it is moted to be the new master If the slave does not have binary logging enabled, you will need
pro-to enable it with thebin-logparameter Though you can change theread_onlysystem able dynamically, changing thebin-logparameter requires amysqldrestart after updating the
vari-my.cnformy.iniconfiguration file
The read_only parameter is global, so only a user with the SUPER privilege can modify it If there are transactions that have locked tables (explicit locks or implicit locks because they are changing data or schema), setting read_only dynamically will wait until the locks are released before it is successful If you hold a table lock and try to set the read_only parameter, an error will occur.
Restart
If necessary, restart themysqldprocess, checking the error logs to ensure the process startswithout any problems Note that the slave configuration is truly gone now:
Trang 17mysql> show slave status\G Empty set (0.00 sec)
RESET MASTER
If you prefer, you can reset the binary logs for your new master This deletes all rent and previous binary logs, and resets the binary log to the first binary log (default is
cur-mysql-bin.000001), log position 4
Change any remaining slaves to replicate off the new master
Any other slaves that were replicating the old master now need to be changed to replicate thenew master This involves aSTOP SLAVEandCHANGE MASTER TOcommand In the event thatthe logs have been reset, theMASTER_LOG_FILEandMASTER_LOG_POSvariables are alreadyknown as the first binary log file, log position 4 In the event that the logs have not been reset,run theSHOW MASTER STATUScommand on the new master:
mysql> SHOW MASTER STATUS;
1 row in set (0.00 sec)
In this case, the value ofMASTER_LOG_FILEismysql-bin.000235and the value of MASTER_ LOG_POSis4 The log position value should be fairly low, because themysqldprocess on thenew master was just restarted, which rotates the binary logs
You may also choose to have the old master replicate the new master In this case, the sameprocedure applies: use theCHANGE MASTER TOcommand to replicate off the new master
Chapter 16 has more information about setting up replication
Slave promotion summary
To promote a slave to a master:
1 Gather information.
2 Make sure the slave is caught up applying its relay logs.
3 Stop the slave process withSTOP SLAVE
4 Ensure the old slave is no longer a slave by issuingRESET SLAVE
5 If necessary: Remove theread_onlyrestriction and enablelog-binin the configurationfile
6 If necessary: Restart themysqldprocess and double-check that the slave parameters havedisappeared
Trang 187 If desired:RESET MASTER.
8 Change any remaining slaves to replicate off the new master (if using many read slaves).
Many read slaves
With only one slave, there is a decision to be made Is db2 meant for scaling, or for high ability? If db2 is meant for high availability, it should be unused by the application until it istime to be promoted to be the master If db2 is meant for scalability, there is no failover server,because both the master and slave are necessary to handle the volume of read queries As well,there may be so many read queries that one slave cannot process them all For these cases, morethan one read slave can be defined
avail-One master database server can have many slaves replicating directly from it, as in Figure 22-2
FIGURE 22-2
db1
db2 db3
This is the simplest method for having more than one slave of a master Read queries can go toeither db1, db2, or db3, whereas write queries remain on db1 and propagate to db2 and db3.There are no tricks to setting up this sort of replication architecture; merely go through the pro-cess of creating db2 as a slave of db1 as described in Chapter 17, and then repeat the process tocreate db3 as a slave of db1
Perhaps db2 and db3 are both for scalability, accepting many read queries to take the load offdb1 Alternatively, db2 could be for scalability, accepting read queries, and db3 could be forhigh availability, ready to be promoted to the master should the need arise
Some applications use a replication relay slave, as in Figure 22-3
FIGURE 22-3
db1 db2
db3 db4
One reason for using this architecture is that if there are 10 or more slaves, it can be easier tohave the slaves connect to a non-master server to avoid the small extra bit of load that each
Trang 19slave produces For large setups with hundreds of slaves in a replication farm, replication relay
slaves are needed Another reason for this type of setup is that if something happens to db1, anddb2 is promoted to be a master, there is no need to change the replication setup for db3 anddb4, because they are already replicating db2 One of the biggest drawbacks of this architecture
is that problems with slave lag may be compounded
For this setup, db3 and db4 are set up as slaves of db2 in the usual way To set up db2 as arelay slave, it is set up as a slave of db1 in the usual way, with one addition in the configurationsetup:log-slave-updates This will ensure that the binary logs for db2 contain the changesthat replicate from db1
Master/master replication
Master/master replication, also called dual-master replication, is a way to scale reads As withall replication architectures, it is not a way to scale writes However, with master/master replica-tion, either of themysqldprocesses can accept writes, which will propagate to the other master.Figure 22-4 shows what a master/master replication architecture looks like
FIGURE 22-4
db1 db2
You set up master/master replication by setting up db1 to be a slave of db2, and setting up db2
to be a slave of db1 In addition, some extra parameters need to be set to ensure data integrity:
■ auto_increment_offset
■ auto_increment_increment
Having writes to more than one server can cause problems withauto_incrementfields If an
auto_incrementfield has used up to number 100, and there’s a write to db1 and db2 at thesame time, both will use 101 as the field value Replication will break on both servers because ofduplicate key errors Theauto_increment_offsetparameter is set with a number indicating
at what number theauto_incrementfield should start Theauto_increment_incrementisset with a number indicating by how much theauto_incrementvalue should be incremented.For example, if db1 is configured with:
auto_increment_offset=1 auto_increment_increment=10
and db2 is configured with:
auto_increment_offset=2 auto_increment_increment=10
Trang 20the first five consecutive inserts intoauto_incrementfields on db1 will have the values 1, 11,
21, 31, 41, and the first five consecutive inserts intoauto_incrementfields on db1 will havethe values 2, 12, 22, 32, 42
The advantage of this setup is that a load balancing solution can point to both db1 and db2,and if one of the servers is unavailable, the other can be used with no change in setup How-ever, the biggest disadvantage of this is that replication can get out of sync — that is, the data
on a slave may not match its master If there are writes to both db1 and db2, and they are out
of sync with each other, which has the ‘‘correct’’ data set? It is very likely that neither data set iscomplete and correct
The safest way to use this setup is to have one database be the primary database, and theother to be a failover server This is still not completely safe — as long as writes are allowed
on the failover server when the primary server is running, there is the possibility of havingdifferent data sets that cannot be resolved with each other (the ‘‘which has the correct data set?’’problem)
To get around this, put theread_onlyparameter on the failover database However, this turnsthe property of ‘‘using the failover with no change in setup’’ to ‘‘using the failover but having
to change a server variable.’’ In general, the only savings in a master/master replication setupare that both servers are set up appropriately to be a master and a slave — for example, bothservers already have binary logging enabled and are already replicating each other
We recommend having a master/slave setup where binary logging is enabled on both the master and slave — by doing that, the only additional step in a master/slave setup (instead of a master/master setup) is having to run the CHANGE MASTER TO command This extra step is well worth it to know which data set is the correct data set in case the two machines have different data.
Trang 21Although circular replication offers the capability of having a load balancing solution point tomore than two servers, it has the same major issue as master/master replication — that if morethan one server accepts writes, it can be impossible to tell which server has the ‘‘correct’’ dataset In addition, circular replication is not fault-tolerant — if db1 is unavailable, updates fromdb3 will not reach db2 even though they are both available.
Circular replication is not recommended; instead, use a master with more than one slave.
SAN
A SAN is a storage-area network It is a shared disk solution, similar to Oracle RAC A SAN is a
high availability technology; in the event that a database server is unavailable, another databaseserver can be attached to the SAN to read the data and logs for themysqldprocess Figure 22-6shows a high availability architecture using a SAN
FIGURE 22-6
db1 (mysqld)
data access over a network data, logsSANdb2
(mysqld)
An advantage of using a SAN instead of replication is that replication is asynchronous; SAN is
a shared disk solution, so you never have to worry that a transaction occurred on the primaryserver that did not make it to the secondary server As Figure 22-6 shows, though, the dataaccess occurs over a network, which is slower than reading from a local disk Another advantage
is that a shared disk means that only one copy of the data is kept, which can be critical for largedatabases
A SAN contains shared disk partitions that can be mounted on more than one machine A partition is mounted over a network — the network used depends on how a machine is connected to the SAN The network might be a standard TCP/IP network if Ethernet cables are used for connection or if the SAN is mounted across an existing Ethernet network such as a LAN A SAN can also be accessed via other means such as SCSI cables from the SAN to the machine(s) mounting partitions from the SAN Regardless of what type of network
is used to access a SAN, SAN access is slower than local disk access.
One of the biggest drawbacks of a SAN is that it is expensive, and may be prohibitively so One
of the biggest benefits of a SAN is unrelated to high availability or scaling — most SANs come
Trang 22with disk snapshot software, which makes consistent backups very quick with minimal locking(see the discussion of snapshots in Chapter 13).
Replication can be used with a SAN to provide read scalability MySQL Proxy or Linux-HAHeartbeat can be used with a SAN for automated failover
DRBD
DRBD stands for ‘‘distributed replicated block device.’’ A block device is what an operatingsystem reads blocks from and writes blocks to; it is a storage system DRBD can performsynchronous replication (‘‘replicated’’) of a storage system (‘‘block device) across two nodes(‘‘distributed’’) It is a free and open source Linux kernel module that is not maintained by Sun.DRBD information and downloads are available atwww.drbd.org
Sun does not develop DRBD, but support for DRBD can be purchased as an add-on to a MySQLEnterprise subscription This is a very convenient option for many organizations, because theycan get support for MySQL and a third-party high availability solution from the same place
A sample high availability architecture using DRBD is depicted in Figure 22-7
FIGURE 22-7
db1
data sync over a network data, logs data, logs
db2
The advantage of using DRBD instead of a SAN is that storage access is local to the server.However, as with replication, it takes time for the request to travel across the network from onemachine to another The advantage of using DRBD instead of replication for high availability isthat DRBD is synchronous One drawback of using DRBD instead of replication is that DRBDdoes not allow read scalability — the secondary node cannot use the DRBD device Having aprimary and secondarymysqldinstance using DRBD is very much like Oracle replication
MySQL and DRBD setup
These instructions are intended to show how MySQL and DRBD work together They are notstep-by-step technical instructions
The MySQL manual has good step-by-step instructions at http://dev.mysql.com/ doc/refman/6.0/en/ha-drbd.html
Trang 231 Install DRBD each machine.
2 Configure DRBD on each machine You must choose which machine (node) will be the
pri-mary and which will be the secondary (failover) You must also physically configure howthe machines will synchronize; if they synchronize over a regular network connection,they must be able to reach each other under normal circumstances
3 Create a DRBD block device, and mount it as a partition.
4 Configuremysqldto put its data and log files on the DRBD partition
Getting these four steps to work is not simple There is plenty of system and network tration overhead in setting up DRBD However, synchronous data sync without the expense of aSAN is usually worth the time invested
adminis-Thoughmysqldneeds to be installed and configured on both nodes, the data files from the mary node will be replicated synchronously to the secondary node
pri-Replication can be used with DRBD to provide read scalability
MySQL Proxy
MySQL Proxy is a technology that can be used for scaling or high availability It is a proxyserver that is transparent; there is not a way for an application or user to tell they are connected
to amysql-proxyprocess instead of directly to amysqldprocess It is written and maintained
by MySQL developers, including Jan Kneschke
MySQL Proxy is very powerful and flexible due to its simplicity It allows you to interceptqueries and results, adding functionality and changing whichmysqldprocess to send informa-tion to, what is sent tomysqld, and what is received frommysqld This is all done via a Luascript and a configuration file For step-by-step instructions on how to install and configureMySQL Proxy and a primer on Lua, see Appendix A We will go over the configurationparameters necessary to achieve scalability and high availability
Figure 22-8 shows how MySQL Proxy can fit into an architecture for high availability or bility
modified queries
modified queries results
results
Trang 24The end user connects tomysql-proxy, which may modify a query and send it to any of thebackend addresses specified (in this example, db1 or db2) The database server then sends theresults, which may be modified by the proxy before being sent back to the end user.
Scaling read queries
The easiest task to perform with themysql-proxyprocess is load balancing You do this bysimply setting theproxy-backend-addressesparameter(s) Likemysqld,mysql-proxycantake parameters on the command line or in a configuration file To configuremysql-proxyto
do load balancing ofdb1.company.comanddb2.company.com:
shell> mysql-proxy proxy-backend-addresses=db1.company.com:3306 \ proxy-backend-addresses=db2.company.com:3306 \
proxy-address=localhost:3306
A thread that connects to port 3306 on the server running themysql-proxyprocess will besent todb1.company.com If a second thread connects while the first is still running, it will
be sent todb2.company.com If the first thread is finished, the second thread will be send to
db1.company.com There is no Lua script needed for this type of load balancing
Load balancing in this way, by number of threads connecting viamysql-proxy, is usefulfor scaling reads If you are using a technology like replication to make slave servers that canprocess read queries, you can point the application at the server runningmysql-proxyandyour read queries are now load-balanced Adding and removing servers means that applicationcode does not need to change; the number ofproxy-backend-addressesspecified can beone server, two servers (as in our example), or more than two servers Note that adding orremoving a server from the proxy requiresmysql-proxyto be restarted
Automated failover
Themysql-proxyprocess can be used to automate failover To do this, there must be afailover server that is active (able to be used without any changes) and has the same data theprimary does Master/slave, master/master, and SAN architectures all would be appropriate The
mysql-proxyconfiguration is similar to the previous one, except we add a Lua script:
shell> mysql-proxy proxy-backend-addresses=db1.company.com:3306 \ proxy-backend-addresses=db2.company.com:3306 \
proxy-address=localhost:3306 \ proxy-lua-script=/path/to/luascript.lua
The Lua script we use (saved at/path/to/luascript.lua) will intercept the initial tion and any queries sent, and send the connection and queries to the first backend that is up
connec-Do not worry about understanding the code exactly, but you will likely be able to follow alongwith what is going on:
function connect_server() for i = 1, #proxy.backends do
Trang 25local s = proxy.backends[i]
if s.state ∼= proxy.BACKEND_STATE_DOWN then proxy.connection.backend_ndx = i
return end end end function read_query(packet) for i = 1, #proxy.backends do local s = proxy.backends[i]
if s.state ∼= proxy.BACKEND_STATE_DOWN then proxy.connection.backend_ndx = i
return end end end
(You can find this Lua script on the MySQL Forge athttp://forge.mysql.com/tools/
tool.php?id=125)
The Lua script is what makesmysql-proxyhandle automated failover However, it also handlesautomated failback — that is, when db1 is available again, all connections and queries will gothrough db1 Note that this is not desired behavior with a master/slave architecture, becausewhen the master is unavailable,mysql-proxywill failover to the slave, but if the master isavailable again,mysql-proxywill failback to the master — and now the slave may haveupdates that the master does not As well, even if you are using master/master replication or aSAN, you may not want automated failback
Lua
Lua is a lightweight programming language that has been around since 1993 As of the time ofthis writing, it is in version 6.0 The entire language is less than 200 kilobytes compiled, so it isvery small and very fast It is used by big applications such as Adobe Photoshop Lightroom Lua isalso used in a web server that has become very popular specifically because it is lightweight andfast —lighttpd It is probably more famous for being used in the popular online game World ofWarcraft
The fact that it is used in such a popular online game speaks of the ease-of-use of the syntax
For use in a proxy, it has everything we need — from the basics such as array data structures tomore complex features like string manipulation to the holy grail of I/O (logging, anyone?) For moreinformation about using Lua in the MySQL Proxy, see Appendix A You can find information aboutLua and the Lua community athttp://www.lua.organdhttp://www.lua-users.org