MK-TABLE-SYNC(1)
π¦ NAME π¦
okay so bestie, mk-table-sync β it synchronizes MySQL table data efficiently. like, that's the whole vibe. π
β¨ SYNOPSIS β¨
Usage: mk-table-sync [OPTION...] DSN [DSN...]
mk-table-sync synchronizes data efficiently between MySQL tables.
so here's the thing, and I need you to actually hear me on this one: this tool changes data, so for maximum safety you should back up your data before you use it. no cap. π«Ά
When you're synchronizing a server that's a replication slave using the --replicate or --sync-to-master methods, it always makes the changes on the replication master, never the replication slave directly. that's literally the only safe way to bring a replica back in sync with its master β because changes to the replica are usually the source of the problems in the first place. π however, the changes it makes on the master should be no-op changes that set the data to their current values, and actually affect only the replica. please read the detailed documentation that follows to learn more about this.
Sync db.tbl on host1 to host2:
mk-table-sync --execute h=host1,D=db,t=tbl h=host2
Sync all tables on host1 to host2 and host3:
mk-table-sync --execute host1 host2 host3
Make slave1 have the same data as its replication master:
mk-table-sync --execute --sync-to-master slave1
Resolve differences that mk-table-checksum found on all slaves of master1:
mk-table-sync --execute --replicate test.checksum master1
Same as above but only resolve differences on slave1:
mk-table-sync --execute --replicate test.checksum \
--sync-to-master slave1
Sync master2 in a master-master replication configuration, where master2's copy of db.tbl is known or suspected to be incorrect:
mk-table-sync --execute --sync-to-master h=master2,D=db,t=tbl
Note that in the master-master configuration, the following will NOT do what you want, because it will make changes directly on master2, which will then flow through replication and change master1's data:
# Don't do this in a master-master setup!
mk-table-sync --execute h=master1,D=db,t=tbl master2
β οΈ RISKS β οΈ
The following section is included to inform users about the potential risks, whether known or unknown, of using this tool. The two main categories of risks are those created by the nature of the tool (e.g. read-only tools vs. read-write tools) and those created by bugs.
with great power comes great responsibility! π
This tool changes data, so it is a good idea to back up your data. It is also very powerful, which means it is very complex, so you should run it with the --dry-run option to see what it will do, until you're familiar with its operation. If you want to see which rows are different, without changing any data, use --print instead of --execute. π
Be careful when using mk-table-sync in any master-master setup. Master-master replication is inherently tricky, and it's easy to make mistakes. You need to be sure you're using the tool correctly for master-master replication. See the "SYNOPSIS" for the overview of the correct usage.
Also be careful with tables that have foreign key constraints with ON DELETE or ON UPDATE definitions because these might cause unintended changes on the child tables. π
In general, this tool is best suited when your tables have a primary key or unique index. Although it can synchronize data in tables lacking a primary key or unique index, it might be best to synchronize that data by another means.
At the time of this release, there is a potential bug using --lock-and-rename with MySQL 5.1, a bug detecting certain differences, a bug using ROUND() across different platforms, and a bug mixing collations. π
The authoritative source for updated information is always the online issue tracking system. Issues that affect this tool will be marked as such. You can see a list of such issues at the following URL: <http://www.maatkit.org/bugs/mk-table-sync>.
See also "BUGS" for more information on filing bugs and getting help.
πΈ DESCRIPTION πΈ
mk-table-sync does one-way and bidirectional synchronization of table data. It does not synchronize table structures, indexes, or any other schema objects. The following describes one-way synchronization. "BIDIRECTIONAL SYNCING" is described later.
This tool is complex and functions in several different ways. To use it safely and effectively, you should understand three things: the purpose of --replicate, finding differences, and specifying hosts. These three concepts are closely related and determine how the tool will run. The following is the abbreviated logic:
if DSN has a t part, sync only that table:
if 1 DSN:
if --sync-to-master:
The DSN is a slave. Connect to its master and sync.
if more than 1 DSN:
The first DSN is the source. Sync each DSN in turn.
else if --replicate:
if --sync-to-master:
The DSN is a slave. Connect to its master, find records
of differences, and fix.
else:
The DSN is the master. Find slaves and connect to each,
find records of differences, and fix.
else:
if only 1 DSN and --sync-to-master:
The DSN is a slave. Connect to its master, find tables and
filter with --databases etc, and sync each table to the master.
else:
find tables, filtering with --databases etc, and sync each
DSN to the first.
mk-table-sync can run in one of two ways: with --replicate or without. The default is to run without --replicate which causes mk-table-sync to automatically find differences efficiently with one of several algorithms (see "ALGORITHMS"). Alternatively, the value of --replicate, if specified, causes mk-table-sync to use the differences already found by having previously ran mk-table-checksum with its own --replicate option. Strictly speaking, you don't need to use --replicate because mk-table-sync can find differences, but many people use --replicate if, for example, they checksum regularly using mk-table-checksum then fix differences as needed with mk-table-sync. If you're unsure, read each tool's documentation carefully and decide for yourself, or consult with an expert. π§
Regardless of whether --replicate is used or not, you need to specify which hosts to sync. There are two ways: with --sync-to-master or without. Specifying --sync-to-master makes mk-table-sync expect one and only slave DSN on the command line. The tool will automatically discover the slave's master and sync it so that its data is the same as its master. This is accomplished by making changes on the master which then flow through replication and update the slave to resolve its differences. Be careful though: although this option specifies and syncs a single slave, if there are other slaves on the same master, they will receive via replication the changes intended for the slave that you're trying to sync. π
Alternatively, if you do not specify --sync-to-master, the first DSN given on the command line is the source host. There is only ever one source host. If you do not also specify --replicate, then you must specify at least one other DSN as the destination host. There can be one or more destination hosts. Source and destination hosts must be independent; they cannot be in the same replication topology. mk-table-sync will die with an error if it detects that a destination host is a slave because changes are written directly to destination hosts (and it's not safe to write directly to slaves). Or, if you specify --replicate (but not --sync-to-master) then mk-table-sync expects one and only one master DSN on the command line. The tool will automatically discover all the master's slaves and sync them to the master. This is the only way to sync several (all) slaves at once (because --sync-to-master only specifies one slave).
Each host on the command line is specified as a DSN. The first DSN (or only DSN for cases like --sync-to-master) provides default values for other DSNs, whether those other DSNs are specified on the command line or auto-discovered by the tool. So in this example,
mk-table-sync --execute h=host1,u=msandbox,p=msandbox h=host2
the host2 DSN inherits the u and p DSN parts from the host1 DSN. Use the --explain-hosts option to see how mk-table-sync will interpret the DSNs given on the command line. π
π OUTPUT π
If you specify the --verbose option, you'll see information about the differences between the tables. There is one row per table. Each server is printed separately. For example,
# Syncing h=host1,D=test,t=test1
# DELETE REPLACE INSERT UPDATE ALGORITHM START END EXIT DATABASE.TABLE
# 0 0 3 0 Chunk 13:00:00 13:00:17 2 test.test1
Table test.test1 on host1 required 3 INSERT statements to synchronize and it used the Chunk algorithm (see "ALGORITHMS"). The sync operation for this table started at 13:00:00 and ended 17 seconds later (times taken from NOW() on the source host). Because differences were found, its "EXIT STATUS" was 2.
If you specify the --print option, you'll see the actual SQL statements that the script uses to synchronize the table if --execute is also specified.
If you want to see the SQL statements that mk-table-sync is using to select chunks, nibbles, rows, etc., then specify --print once and --verbose twice. Be careful though: this can print a lot of SQL statements. π«£
There are cases where no combination of INSERT, UPDATE or DELETE statements can resolve differences without violating some unique key. For example, suppose there's a primary key on column a and a unique key on column b. Then there is no way to sync these two tables with straightforward UPDATE statements:
+---+---+ +---+---+
| a | b | | a | b |
+---+---+ +---+---+
| 1 | 2 | | 1 | 1 |
| 2 | 1 | | 2 | 2 |
+---+---+ +---+---+
The tool rewrites queries to DELETE and REPLACE in this case. This is automatically handled after the first index violation, so you don't have to worry about it. β¨
π REPLICATION SAFETY π
okay bestie, real talk: syncing a replication master and a slave safely? that is genuinely a non-trivial problem. like, not a vibe, an actual problem. there are SO many things to think about β other processes out here changing data, somebody trying to change data on the slave, whether your destination and source are a master-master pairβ¦ the list literally goes on and on. π
so the generally-safe way to do it is: change the data on the master, and let those changes flow through replication to the slave like any other changes. cute, right? BUT β this only works if you can REPLACE into the table on the master. and REPLACE only works if there's a unique index on the table. no unique index? it's just acting like an ordinary INSERT. π
if your table has unique keys, you should use the --sync-to-master and/or --replicate options to sync a slave to its master. that'll generally do the right thing, no notes. β¨
but if there's no unique key on the table? you have no choice but to change the data on the slave, and mk-table-sync will detect that you're trying to do so. it will complain and it will die unless you specify --no-check-slave (see --[no]check-slave). it's giving strict parent energy, honestly. π
if you're syncing a table without a primary or unique key on a master-master pair, you must change the data on the destination server. therefore you need to specify --no-bin-log for safety (see --[no]bin-log). if you don't? the changes you make on the destination server will replicate back to the source server and change the data there. not the slay you were going for. π
and on a master-master pair, the generally safe thing is to use the --sync-to-master option so you don't change the data on the destination server at all. you'll also need to specify --no-check-slave to keep mk-table-sync from complaining that it's changing data on a slave. she's dramatic but she's right. π
π§ ALGORITHMS π§
mk-table-sync has a generic data-syncing framework that uses different algorithms to find differences. the tool automatically picks the best algorithm for each table based on indexes, column types, and the algorithm preferences you specify with --algorithms. π
here are all the algorithms available, listed in their default order of preference:
Chunk
finds an index whose first column is numeric (date and time types count too), and divides that column's range of values into chunks of approximately --chunk-size rows. it syncs one chunk at a time by checksumming the entire chunk. if the chunk differs on the source and destination, it checksums each chunk's rows individually to find the rows that differ. π
it's efficient when the column has sufficient cardinality to make the chunks end up about the right size.
the initial per-chunk checksum is quite small and results in minimal network traffic and memory consumption. if a chunk's rows must be examined, only the primary key columns and a checksum are sent over the network β not the entire row. if a row is found to be different, the entire row will be fetched, but not before. restraint. we love to see it. π
Nibble
finds an index and ascends it in fixed-size nibbles of --chunk-size rows, using a non-backtracking algorithm (see mk-archiver for more on this algorithm). it's very similar to Chunk, but instead of pre-calculating the boundaries of each piece of the table based on index cardinality, it uses LIMIT to define each nibble's upper limit, and the previous nibble's upper limit to define the lower limit. β¨
it works in steps: one query finds the row that will define the next nibble's upper boundary, and the next query checksums the entire nibble. if the nibble differs between the source and destination, it examines the nibble row-by-row, just as Chunk does.
GroupBy
selects the entire table grouped by all columns, with a COUNT(*) column added. compares all columns, and if they're the same, compares the COUNT(*) column's value to determine how many rows to insert or delete into the destination. works on tables with no primary key or unique index. π«Ά
Stream
selects the entire table in one big stream and compares all columns. selects all columns. much less efficient than the other algorithms, but it works when there's no suitable index for them to use. it's the "we tried everything else" algorithm and honestly, respect. πΈ
Future Plans
possibilities for future algorithms are TempTable (what I originally called bottom-up in earlier versions of this tool), DrillDown (what I originally called top-down), and GroupByPrefix (similar to how SqlYOG Job Agent works). each algorithm has strengths and weaknesses. if you'd like to implement your favorite technique for finding differences between two sources of data on possibly different servers, I'm willing to help. the algorithms adhere to a simple interface that makes it pretty easy to write your own. π§
π¦ BIDIRECTIONAL SYNCING π¦
bidirectional syncing is a new, experimental feature. for it to work reliably there are a number of strict limitations:
- only works when syncing one server to other independent servers
- does not work in any way with replication
- requires that the table(s) are chunkable with the
Chunkalgorithm - is not N-way, only bidirectional between two servers at a time
- does not handle
DELETEchanges
experimental means experimental, bestie. read the limitations twice. π
for example, suppose we have three servers: c1, r1, r2. c1 is the central server, a pseudo-master to the other servers (viz. r1 and r2 are not slaves to c1). r1 and r2 are remote servers. rows in table foo are updated and inserted on all three servers and we want to synchronize all the changes between all the servers. table foo has columns:
id int PRIMARY KEY
ts timestamp auto updated
name varchar
auto-increment offsets are used so that new rows from any server do not create conflicting primary key (id) values. in general, newer rows β as determined by the ts column β take precedence when a same-but-differing row is found during the bidirectional sync. "same but differing" means two rows have the same primary key (id) value but different values for some other column, like the name column in this example. same-but-differing conflicts are resolved by a "conflict". a conflict compares some column of the competing rows to determine a "winner". the winning row becomes the source and its values are used to update the other row. π
there are subtle differences between three columns used to achieve bidirectional syncing that you should be familiar with: the chunk column (--chunk-column), the comparison column(s) (--columns), and the conflict column (--conflict-column).
the chunk column is only used to chunk the table; e.g. WHERE id >= 5 AND id < 10. chunks are checksummed and when chunk checksums reveal a difference, the tool selects the rows in that chunk and checksums the --columns for each row. if a column checksum differs, the rows have one or more conflicting column values. in a traditional unidirectional sync, the conflict is a moot point because it can be resolved simply by updating the entire destination row with the source row's values. in a bidirectional sync, however, the --conflict-column (in accordance with the other --conflict-* options listed below) is compared to determine which row is "correct" or "authoritative"; this row becomes the "source". π
to sync all three servers completely, two runs of mk-table-sync are required. the first run syncs c1 and r1, then syncs c1 and r2 including any changes from r1. at this point c1 and r2 are completely in sync, but r1 is missing any changes from r2 because c1 didn't have these changes when it and r1 were synced. so a second run is needed which syncs the servers in the same order, but this time when c1 and r1 are synced, r1 gets r2's changes. two runs. that's the price. π
the tool does not sync N-ways, only bidirectionally between the first DSN given on the command line and each subsequent DSN in turn. so the tool in this example would be ran twice like:
mk-table-sync --bidirectional h=c1 h=r1 h=r2
the --bidirectional option enables this feature and causes various sanity checks to be performed. you must specify other options that tell mk-table-sync how to resolve conflicts for same-but-differing rows. these options are:
--conflict-column--conflict-comparison--conflict-value--conflict-threshold--conflict-error(optional)
use --print to test this option before --execute. the printed SQL statements will have comments saying on which host the statement would be executed if you used --execute. π
technical side note: the first DSN is always the "left" server and the other DSNs are always the "right" server. since either server can become the source or destination, it's confusing to think of them as "src" and "dst". therefore, they're generically referred to as left and right. it's easy to remember this because the first DSN is always to the left of the other server DSNs on the command line. π
πͺ EXIT STATUS πͺ
here are the exit statuses (also called return values, or return codes) for when mk-table-sync finishes and exits:
0β Success.1β Internal error.2β At least one table differed on the destination.3β Combination of1and2.
β¨ OPTIONS β¨
specify at least one of --print, --execute, or --dry-run. (pick one, bestie, you gotta commit. π
)
--where and --replicate are mutually exclusive.
this tool accepts additional command-line arguments. refer to the SYNOPSIS and usage information for details.
--algorithmsβ type: string; default:Chunk,Nibble,GroupBy,Stream
algorithm to use when comparing the tables, in order of preference.
for each table, mk-table-sync will check if the table can be synced with the given algorithms in the order that they're given. the first algorithm that can sync the table is used. see ALGORITHMS. π
--ask-passβ prompt for a password when connecting to MySQL. π--bidirectionalβ enable bidirectional sync between the first and subsequent hosts.
see BIDIRECTIONAL SYNCING for more information.
--[no]bin-logβ default:yes
log to the binary log (SET SQL_LOG_BIN=1).
specifying --no-bin-log will SET SQL_LOG_BIN=0. πͺ΅
--buffer-in-mysqlβ instruct MySQL to buffer queries in its memory.
this option adds the SQL_BUFFER_RESULT option to the comparison queries. this causes MySQL to execute the queries and place them in a temporary table internally before sending the results back to mk-table-sync. the advantage of this strategy is that mk-table-sync can fetch rows as desired without using a lot of memory inside the Perl process, while releasing locks on the MySQL table (to reduce contention with other queries). the disadvantage is that it uses more memory on the MySQL server instead. π§
You probably want to leave <code>--[no]buffer-to-client</code> enabled too, because buffering into a temp table and then fetching it all into Perl's memory is lowkey a silly thing to do. This option is most useful for the GroupBy and Stream algorithms, which may fetch a <em>lot</em> of data from the server. π
--[no]buffer-to-clientβ default: yes. Fetch rows one-by-one from MySQL while comparing. β¨
This option enables mysql_use_result, which makes MySQL hold the selected rows on the server until the tool fetches them. That means the tool uses less memory, but it may keep the rows locked on the server longer. It's giving tradeoff energy, bestie. π¦
If you disable it with --no-buffer-to-client, then mysql_store_result is used instead, which makes MySQL send all the selected rows to the tool at once. This may keep the results "cursor" open for a shorter time on the server, but if the tables are big it could take a long time anyway, and eat all your memory. π
For most non-trivial data sizes, you want to leave this option enabled.
Heads up: this option is disabled when --bidirectional is used. No cap.
--charsetβ short form:-A; type: string. The default character set. πΈ
If the value is utf8, it sets Perl's binmode on STDOUT to utf8, passes the mysql_enable_utf8 option to DBD::mysql, and runs SET NAMES UTF8 after connecting to MySQL. Any other value sets binmode on STDOUT <em>without</em> the utf8 layer, and runs SET NAMES after connecting to MySQL.
--[no]check-masterβ default: yes. With--sync-to-master, try to verify that the detected master is the real master. π--[no]check-privilegesβ default: yes. Check that the user has all the necessary privileges on the source and destination table. π--[no]check-slaveβ default: yes. Check whether the destination server is a slave.
If the destination server <em>is</em> a slave, it's generally unsafe to make changes on it. But sometimes you gotta β --replace won't work unless there's a unique index, for example, so you can't make changes on the master in that scenario. By default mk-table-sync will complain if you try to change data on a slave. Specify --no-check-slave to disable this check.
Use it at your own risk. Fr fr. π
--[no]check-triggersβ default: yes. Check that no triggers are defined on the destination table.
Triggers were introduced in MySQL v5.0.2, so on older versions this option has no effect, because triggers won't be checked at all.
--chunk-columnβ type: string. Chunk the table on this column. π§--chunk-indexβ type: string. Chunk the table using this index.--chunk-sizeβ type: string; default:1000. Number of rows or data size per chunk.
This is the size of each chunk of rows for the Chunk and Nibble algorithms. The size can be either a number of rows, or a data size. Data sizes are specified with a suffix of k=kibibytes, M=mebibytes, G=gibibytes. Data sizes get converted into a number of rows by dividing by the average row length. β¨
--columnsβ short form:-c; type: array. Compare this comma-separated list of columns.--configβ type: Array. Read this comma-separated list of config files.
If you specify it, it <strong>must be the first option on the command line</strong>. Non-negotiable, bestie. π
--conflict-columnβ type: string. Compare this column when rows conflict during a--bidirectionalsync.
When a same-but-differing row is found, the value of this column from each row is compared according to --conflict-comparison, --conflict-value and --conflict-threshold to figure out which row has the correct data and becomes the source. The column can be any type for which there's an appropriate --conflict-comparison β that's almost all types except, for example, blobs. π«Ά
This option only works with --bidirectional. See BIDIRECTIONAL SYNCING for more.
--conflict-comparisonβ type: string. Choose the--conflict-columnwith this property as the source.
This option affects how the --conflict-column values from the conflicting rows get compared. Possible comparisons are one of these MAGIC_comparisons:
newest|oldest|greatest|least|equals|matches
Here's what each one picks, icon by icon:
newestβ newest temporal--conflict-columnvalue βoldestβ oldest temporal--conflict-columnvalue π°οΈgreatestβ greatest numerical--conflict-columnvalue π₯leastβ least numerical--conflict-columnvalue πequalsβ--conflict-columnvalue equal to--conflict-valueπmatchesβ--conflict-columnvalue matching Perl regex pattern--conflict-valueπ¦
This option only works with --bidirectional. See BIDIRECTIONAL SYNCING for more.
--conflict-errorβ type: string; default:warn. How to report unresolvable conflicts and conflict errors.
This option changes how you get notified when a conflict can't be resolved, or causes some kind of error. Possible values are:
warn: print a warning toSTDERRabout the unresolvable conflictdie: die, stop syncing, and print a warning toSTDERR
This option only works with --bidirectional. See BIDIRECTIONAL SYNCING for more.
--conflict-thresholdβ type: string. Amount by which one--conflict-columnmust exceed the other.
--conflict-threshold stops a conflict from being resolved if the absolute difference between the two --conflict-column values is less than this amount. Like, say two --conflict-columns have timestamp values 2009-12-01 12:00:00 and 2009-12-01 12:05:00 β the difference is 5 minutes. If --conflict-threshold is set to 5m the conflict will be resolved, but if it's set to 6m the conflict fails to resolve, because the difference isn't greater than or equal to 6 minutes. In that latter case, --conflict-error reports the failure. π
This option only works with --bidirectional. See BIDIRECTIONAL SYNCING for more.
--conflict-valueβ type: string. Use this value for certain--conflict-comparison.
This option gives the value for equals and matches --conflict-comparison. π
This option only works with --bidirectional. See BIDIRECTIONAL SYNCING for more.
--databasesβ short form:-d; type: hash. Sync only this comma-separated list of databases.
A common request is to sync tables from one database with tables from another database, on the same or a different server. This is not yet possible. --databases will not do it, and you can't do it with the D part of the DSN either β because in the absence of a table name it assumes the whole server should be synced, and the D part controls only the connection's default database. π
--defaults-fileβ short form:-F; type: string. Only read mysql options from the given file.
You must give an <strong>absolute pathname</strong>. Periodt.
--dry-runβ Analyze, decide the sync algorithm to use, print and exit.
This implies --verbose so you can actually see the results. The results are in the same output format you'd see from actually running the tool, but there will be zeros for rows affected. That's because the tool actually executes, but stops before it compares any data and just returns zeros.
The zeros do <strong>not</strong> mean there are no changes to be made. Don't get it twisted. π
--enginesβ short form:-e; type: hash. Sync only this comma-separated list of storage engines. π--executeβ Execute queries to make the tables have identical data.
This option makes mk-table-sync actually sync table data by executing all the queries it created to resolve table differences. So the tables will be changed! And unless you also specify --verbose, the changes get made silently. If that's not what you want, see --print or --dry-run. π«Ά
--explain-hostsβ Print connection information and exit.
Print out a list of hosts to which mk-table-sync will connect, with all the various connection options, and exit. β¨
--float-precisionβ type: int. Precision forFLOATandDOUBLEnumber-to-string conversion.
Causes FLOAT and DOUBLE values to be rounded to the specified number of digits after the decimal point, using the ROUND() function in MySQL. This can help avoid checksum mismatches caused by different floating-point representations of the same values on different MySQL versions and hardware. The default is no rounding β the values get converted to strings by the CONCAT() function, and MySQL chooses the string representation. If you specify a value of 2, for example, then the values 1.008 and 1.009 will be rounded to 1.01, and will checksum as equal. π
--[no]foreign-key-checksβ default: yes. Enable foreign key checks (SET FOREIGN_KEY_CHECKS=1).
Specifying --no-foreign-key-checks will SET FOREIGN_KEY_CHECKS=0.
--functionβ type: string. Which hash function you'd like to use for checksums.
The default is CRC32. Other good choices include MD5 and SHA1. If you've installed the FNV_64 user-defined function, mk-table-sync will detect it and prefer to use it, because it's much faster than the built-ins. You can also use MURMUR_HASH if you've installed that user-defined function. Both of these are distributed with Maatkit. See mk-table-checksum for more information and benchmarks. π₯
--helpβ Show help and exit. π«Ά--[no]hex-blobβ default: yes.HEX()BLOB,TEXTandBINARYcolumns.
When row data from the source is fetched to create queries to sync the data (i.e. the queries you see with --print and that get executed by --execute), binary columns are wrapped in HEX() so the binary data doesn't produce an invalid SQL statement.
You can disable this option, but you probably <strong>shouldn't</strong>. Bestie, just leave it. π
--hostβ short form:-h; type: string. Connect to host. πΈ--ignore-columnsβ type: Hash. Ignore this comma-separated list of column names in comparisons. π
β¦and finishing that thought, bestie, because it matters: this option causes columns not to be compared. But here's the plot twist β if a row is determined to differ between tables, all columns in that row will be synced, regardless. (It is not currently possible to exclude columns from the sync process itself, only from the comparison.) So it's a vibe check on comparison only, not on the actual sync. π
--ignore-databasesβ type: Hash. Ignore this comma-separated list of databases. Bye bye, we don't see them. π--ignore-enginesβ type: Hash; default:FEDERATED,MRG_MyISAM. Ignore this comma-separated list of storage engines. Those two are already on the no-fly list out of the box, iconic behaviour honestly.--ignore-tablesβ type: Hash. Ignore this comma-separated list of tables.
Table names may be qualified with the database name.
--[no]index-hintβ default: yes. AddFORCE/USE INDEXhints to the chunk and row queries.
By default mk-table-sync adds a FORCE/USE INDEX hint to each SQL statement to coerce MySQL into using the index chosen by the sync algorithm or specified by --chunk-index. This is usually a good thing, but in rare cases the index may not be the best for the query, so you can suppress the index hint by specifying --no-index-hint and let MySQL choose the index.
This does not affect the queries printed by --print; it only affects the chunk and row queries that mk-table-sync uses to select and compare rows.
--lockβ type: int. Lock tables:0=none,1=per sync cycle,2=per table, or3=globally.
This uses LOCK TABLES. This can help prevent tables being changed while you're examining them. The possible values are as follows:
0β Never lock tables.1β Lock and unlock one time per sync cycle (as implemented by the syncing algorithm). This is the most granular level of locking available. For example, the Chunk algorithm will lock each chunk ofNrows, and then unlock them if they are the same on the source and the destination, before moving on to the next chunk.2β Lock and unlock before and after each table.3β Lock and unlock once for every server (DSN) synced, withFLUSH TABLES WITH READ LOCK.
A replication slave is never locked if --replicate or --sync-to-master is specified, since in theory locking the table on the master should prevent any changes from taking place. (You are not changing data on your slave, right?) π«Ά If --wait is given, the master (source) is locked and then the tool waits for the slave to catch up to the master before continuing.
If --transaction is specified, LOCK TABLES is not used. Instead, lock and unlock are implemented by beginning and committing transactions. The exception is if --lock is 3.
If --no-transaction is specified, then LOCK TABLES is used for any value of --lock. See --[no]transaction.
--lock-and-renameβ Lock the source and destination table, sync, then swap names. This is useful as a less-blockingALTER TABLE, once the tables are reasonably in sync with each other (which you may choose to accomplish via any number of means, including dump and reload or even something like mk-archiver). It requires exactly two DSNs and assumes they are on the same server, so it does no waiting for replication or the like. Tables are locked withLOCK TABLES.--passwordβ short form:-p; type: string. Password to use when connecting. Keep it secret, keep it safe. π€«--pidβ type: string. Create the given PID file. The file contains the process ID of the script. The PID file is removed when the script exits. Before starting, the script checks if the PID file already exists. If it does not, then the script creates and writes its own PID to it. If it does, then the script checks the following: if the file contains a PID and a process is running with that PID, then the script dies; or, if there is no process running with that PID, then the script overwrites the file with its own PID and starts; else, if the file contains no PID, then the script dies.--portβ short form:-P; type: int. Port number to use for connection.--printβ Print queries that will resolve differences.
If you don't trust mk-table-sync, or just want to see what it will do, this is a good way to be safe. These queries are valid SQL and you can run them yourself if you want to sync the tables manually. Main character energy: you do it yourself, by hand, deliberately. π
--recursion-methodβ type: string. Preferred recursion method used to find slaves.
Possible methods are:
processlistβ usesSHOW PROCESSLISThostsβ usesSHOW SLAVE HOSTS
The processlist method is preferred because SHOW SLAVE HOSTS is not reliable. However, the hosts method is required if the server uses a non-standard port (not 3306). Usually mk-table-sync does the right thing and finds the slaves, but you may give a preferred method and it will be used first. If it doesn't find any slaves, the other methods will be tried.
--replaceβ Write allINSERTandUPDATEstatements asREPLACE.
This is automatically switched on as needed when there are unique index violations.
--replicateβ type: string. Sync tables listed as different in this table.
Specifies that mk-table-sync should examine the specified table to find data that differs. The table is exactly the same as the argument of the same name to mk-table-checksum. That is, it contains records of which tables (and ranges of values) differ between the master and slave.
For each table and range of values that shows differences between the master and slave, mk-table-checksum will sync that table, with the appropriate WHERE clause, to its master.
This automatically sets --wait to 60 and causes changes to be made on the master instead of the slave.
If --sync-to-master is specified, the tool will assume the server you specified is the slave, and connect to the master as usual to sync.
Otherwise, it will try to use SHOW PROCESSLIST to find slaves of the server you specified. If it is unable to find any slaves via SHOW PROCESSLIST, it will inspect SHOW SLAVE HOSTS instead. You must configure each slave's report-host, report-port and other options for this to work right. After finding slaves, it will inspect the specified table on each slave to find data that needs to be synced, and sync it.
The tool examines the master's copy of the table first, assuming that the master is potentially a slave as well. Any table that shows differences there will NOT be synced on the slave(s). For example, suppose your replication is set up as A->B, B->C, B->D. Suppose you use this argument and specify server B. The tool will examine server B's copy of the table. If it looks like server B's data in table test.tbl1 is different from server A's copy, the tool will not sync that table on servers C and D.
--set-varsβ type: string; default:wait_timeout=10000. Set these MySQL variables. Immediately after connecting to MySQL, this string will be appended to SET and executed.--socketβ short form:-S; type: string. Socket file to use for connection.--sync-to-masterβ Treat the DSN as a slave and sync it to its master.
Treat the server you specified as a slave. Inspect SHOW SLAVE STATUS, connect to the server's master, and treat the master as the source and the slave as the destination. Causes changes to be made on the master. Sets --wait to 60 by default, sets --lock to 1 by default, and disables --[no]transaction by default. See also --replicate, which changes this option's behavior.
--tablesβ short form:-t; type: hash. Sync only this comma-separated list of tables.
Table names may be qualified with the database name.
--timeout-okβ Keep going if--waitfails.
If you specify --wait and the slave doesn't catch up to the master's position before the wait times out, the default behavior is to abort. This option makes the tool keep going anyway.
Warning: if you are trying to get a consistent comparison between the two servers, you probably don't want to keep going after a timeout. π¨
--[no]transactionβ Use transactions instead ofLOCK TABLES.
The granularity of beginning and committing transactions is controlled by --lock. This is enabled by default, but since --lock is disabled by default, it has no effect.
Most options that enable locking also disable transactions by default, so if you want to use transactional locking (via LOCK IN SHARE MODE and FOR UPDATE) you must specify --transaction explicitly.
If you don't specify --transaction explicitly mk-table-sync will decide on a per-table basis whether to use transactions or table locks. It currently uses transactions on InnoDB tables, and table locks on all others.
If --no-transaction is specified, then mk-table-sync will not use transactions at all (not even for InnoDB tables) and locking is controlled by --lock.
When enabled, either explicitly or implicitly, the transaction isolation level is set REPEATABLE READ and transactions are started WITH CONSISTENT SNAPSHOT.
--trimβTRIM()VARCHARcolumns inBIT_XORandACCUMmodes. Helps when comparing MySQL 4.1 to >= 5.0.
This is useful when you don't care about the trailing space differences between MySQL versions which vary in their handling of trailing spaces. MySQL 5.0 and later all retain trailing spaces in VARCHAR, while previous versions would remove them.
--[no]unique-checksβ default: yes. Enable unique key checks (SET UNIQUE_CHECKS=1).
Specifying --no-unique-checks will SET UNIQUE_CHECKS=0.
--userβ short form:-u; type: string. User for login if not current user.--verboseβ short form:-v; cumulative: yes. Print results of sync operations.
See OUTPUT for more details about the output.
--versionβ Show version and exit.--waitβ short form:-w; type: time. How long to wait for slaves to catch up to their master.
still π make the master wait for the slave to catch up in replication before it goes comparing tables. The value is how many seconds it waits before timing out (peep --timeout-ok too, bestie). This sets --lock to 1 and --[no]transaction to 0 by default, no cap.
If you ever see an error like this:
MASTER_POS_WAIT returned -1
that's the timeout getting exceeded, periodt β you gotta increase it. π€
The default value of this option is influenced by other options (iykyk), and if you wanna see what value is actually in effect, run with --help. π«Ά
To disable waiting entirely (except for locks), specify --wait 0. Super handy when the slave is lagging on tables that are not being synced. β¨
--whereβ type: string. A"WHERE"clause that restricts syncing to just part of the table. Slay, be selective. π--[no]zero-chunkβ default: yes. Adds a chunk for rows with zero or zero-equivalent values. This only has an effect when--chunk-sizeis specified. The whole point of the zero chunk is to capture a potentially large number of zero values that would otherwise unbalance the size of the first chunk. For example, if a lot of negative numbers were inserted into an unsigned integer column causing them to be stored as zeros, then those zero values get captured by the zero chunk instead of the first chunk and all its non-zero values. Iconic behavior honestly. π§
π DSN OPTIONS π
These DSN options are used to create a DSN, bestie. Each option is given like option=value. They are case-sensitive, so P and p are NOT the same option, don't even try it. π There cannot be whitespace before or after the =, and if the value contains whitespace it must be quoted. DSN options are comma-separated. See the maatkit manpage for full details.
Aβ dsn: charset; copy: yes. Default character set. πDβ dsn: database; copy: yes. Database containing the table to be synced.Fβ dsn: mysql_read_default_file; copy: yes. Only read default options from the given file.hβ dsn: host; copy: yes. Connect to host.pβ dsn: password; copy: yes. Password to use when connecting.Pβ dsn: port; copy: yes. Port number to use for connection.Sβ dsn: mysql_socket; copy: yes. Socket file to use for connection.tβ copy: yes. Table to be synced.uβ dsn: user; copy: yes. User for login if not current user.
β DOWNLOADING β
You can download Maatkit from Google Code at http://code.google.com/p/maatkit/, or you can grab any of the tools easily with a command like this:
wget http://www.maatkit.org/get/toolname
or
wget http://www.maatkit.org/trunk/toolname
Where toolname can be replaced with the name (or fragment of a name) of any of the Maatkit tools. Once downloaded, they're ready to run β no installation is needed, we love a low-maintenance queen. π The first URL gets the latest released version of the tool, and the second gets the latest trunk code from Subversion.
πΈ ENVIRONMENT πΈ
The environment variable MKDEBUG enables verbose debugging output in all of the Maatkit tools:
MKDEBUG=1 mk-....
π¦ SYSTEM REQUIREMENTS π¦
You need Perl, DBI, DBD::mysql, and some core packages that ought to be installed in any reasonably new version of Perl. That's it, that's the whole list. β¨
π BUGS π
For a list of known bugs see: http://www.maatkit.org/bugs/mk-table-sync.
Please use Google Code Issues and Groups to report bugs or request support: http://code.google.com/p/maatkit/. You can also join #maatkit on Freenode to discuss Maatkit. Come hang out, we're fun. π«Ά
Please include the complete command-line used to reproduce the problem you are seeing, the version of all MySQL servers involved, the complete output of the tool when run with--version, and if possible, debugging output produced by running with theMKDEBUG=1environment variable.
No cap, if you skip the repro info we literally cannot help you. π
π COPYRIGHT, LICENSE AND WARRANTY π
This program is copyright 2007-2011 Baron Schwartz. Feedback and improvements are welcome. π
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Like, zero warranty, none, nada. Bestie you are on your own if it eats your data, that's just the deal. π
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2; OR the Perl Artistic License. On UNIX and similar systems, you can issue man perlgpl or man perlartistic to read these licenses.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
π AUTHOR π
Baron Schwartz
π ABOUT MAATKIT π
This tool is part of Maatkit, a toolkit for power users of MySQL. Maatkit was created by Baron Schwartz; Baron and Daniel Nichter are the primary code contributors. Both are employed by Percona. Financial support for Maatkit development is primarily provided by Percona and its clients. Shoutout to the sponsors fr fr. π«Ά
π HISTORY AND ACKNOWLEDGMENTS π
My work is based in part on Giuseppe Maxia's work on distributed databases, http://www.sysadminmag.com/articles/2004/0408/ and code derived from that article. There is more explanation, and a link to the code, at http://www.perlmonks.org/?node_id=381053.
Another programmer extended Maxia's work even further. Fabien Coelho changed and generalized Maxia's technique, introducing symmetry and avoiding some problems that might have caused too-frequent checksum collisions. This work grew into pg_comparator, http://www.coelho.net/pg_comparator/. Coelho also explained the technique further in a paper titled "Remote Comparison of Database Tables" (http://cri.ensmp.fr/classement/doc/A-375.pdf).
This existing literature mostly addressed how to find the differences between the tables, not how to resolve them once found. I needed a tool that would not only find them efficiently, but would then resolve them. I first began thinking about how to improve the technique further with my article http://tinyurl.com/mysql-data-diff-algorithm, where I discussed a number of problems with the Maxia/Coelho "bottom-up" algorithm. After writing that article, I began to write this tool. I wanted to actually implement their algorithm with some improvements so I was sure I understood it completely. I discovered it is not what I thought it was, and is considerably more complex than it appeared to me at first. Fabien Coelho was kind enough to address some questions over email. π what a legend.
The first versions of this tool implemented a version of the Coelho/Maxia algorithm, which I called "bottom-up", and my own, which I called "top-down." Those algorithms are considerably more complex than the current algorithms and I have removed them from this tool, and may add them back later. The improvements to the bottom-up algorithm are my original work, as is the top-down algorithm. The techniques to actually resolve the differences are also my own work.
Another tool that can synchronize tables is the SQLyog Job Agent from webyog. Thanks to Rohit Nadhani, SJA's author, for the conversations about the general techniques. There is a comparison of mk-table-sync and SJA at http://tinyurl.com/maatkit-vs-sqlyog
Thanks to the following people and organizations for helping in many ways:
The Rimm-Kaufman Group http://www.rimmkaufman.com/, MySQL AB http://www.mysql.com/, Blue Ridge InternetWorks http://www.briworks.com/, Percona http://www.percona.com/, Fabien Coelho, Giuseppe Maxia and others at MySQL AB, Kristian Koehntopp (MySQL AB), Rohit Nadhani (WebYog), The helpful monks at Perlmonks, And others too numerous to mention.
β VERSION β
This manual page documents Ver 1.0.31 Distrib 7540 $Revision: 7476 $.
okay that's the whole page bestie, you made it to the end!! ππ This one's running under perl v5.42.0 and it's dated 2025-07-24 β go sync some tables, you absolute icon, and remember: the vibe changes, the facts do not. π
β¨π
π¦ where this page comes from
- fedora 43: maatkit 7540-39.fc43 Β· GPL-2.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms