| Server IP : 39.106.62.82 / Your IP : 216.73.216.223 Web Server : nginx/1.14.1 System : Linux iz2ze1m0zmp2dk5c3j5ap5z 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 User : www ( 1000) PHP Version : 7.4.33 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /bin/ |
Upload File : |
#!/usr/bin/python
#
# Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
#
# 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 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
"""
This file contains the import database utility which allows users to import
metadata for objects in a database and data for tables.
"""
import multiprocessing
import os
import sys
import time
import re
from mysql.utilities.common.tools import check_python_version
from mysql.utilities.command import dbimport
from mysql.utilities.common.ip_parser import parse_connection
from mysql.utilities.common.messages import (WARN_OPT_ONLY_USED_WITH,
FILE_DOES_NOT_EXIST,
INSUFFICIENT_FILE_PERMISSIONS)
from mysql.utilities.common.options import (add_character_set_option,
add_engines, add_format_option,
add_no_headers_option,
add_skip_options, add_verbosity,
check_skip_options,
check_verbosity,
setup_common_options,
get_ssl_dict,
check_password_security)
from mysql.utilities.common.pattern_matching import (
REGEXP_QUALIFIED_OBJ_NAME,
REGEXP_QUALIFIED_OBJ_NAME_AQ)
from mysql.utilities.common.server import connect_servers
from mysql.utilities.common.tools import (check_connector_python,
print_elapsed_time)
from mysql.utilities.exception import FormatError, UtilError
# Check Python version compatibility
check_python_version()
# Constants
NAME = "MySQL Utilities - mysqldbimport "
DESCRIPTION = "mysqldbimport - import metadata and data from files"
USAGE = "%prog --server=user:pass@host:port:socket db1.csv db2.sql db3.grid"
_PERMITTED_IMPORTS = ["data", "definitions", "both"]
# Check for connector/python
if not check_connector_python():
sys.exit(1)
if __name__ == '__main__':
# Needed for freeze support to avoid RuntimeError when running as a Windows
# executable, otherwise ignored.
multiprocessing.freeze_support()
# Setup the command parser and setup server, help
parser = setup_common_options(os.path.basename(sys.argv[0]),
DESCRIPTION, USAGE)
# Setup utility-specific options:
# Add character set option
add_character_set_option(parser)
# Input format
add_format_option(parser, "the input file format in either sql (default), "
"grid, tab, csv, raw_csv or vertical format", "sql",
True, extra_formats=["raw_csv"])
# Import mode
parser.add_option("-i", "--import", action="store", dest="import_type",
default="definitions", help="control the import of "
"either 'data' = only the table data for the tables in "
"the database list, 'definitions' = import only the "
"definitions for the objects in the database list, or "
"'both' = import the metadata followed by the data "
"(default: import definitions)", type="choice",
choices=_PERMITTED_IMPORTS)
# Drop mode
parser.add_option("-d", "--drop-first", action="store_true", default=False,
help="drop database before importing.", dest="do_drop")
# Single insert mode
parser.add_option("-b", "--bulk-insert", action="store_true",
dest="bulk_insert", default=False, help="use bulk "
"insert statements for data (default:False)")
# No header option
add_no_headers_option(parser, restricted_formats=['tab', 'csv'],
help_msg="files do not contain column headers")
# Dryrun mode
parser.add_option("--dryrun", action="store_true", dest="dryrun",
default=False, help="import the files and generate the "
"statements but do not execute them - useful for "
"testing file validity")
# Add table for import raw csv files
parser.add_option("--table", action="store", dest="table", default=None,
help="destination table in the form: <db>.<table>.")
# Skip blobs for import
parser.add_option("--skip-blobs", action="store_true", dest="skip_blobs",
default=False, help="do not import blob data.")
# Skip replication commands
parser.add_option("--skip-rpl", action="store_true", dest="skip_rpl",
default=False, help="do not execute replication "
"commands.")
# Add skip generation of GTID statements
parser.add_option("--skip-gtid", action="store_true", default=False,
dest="skip_gtid", help="do not execute the GTID_PURGED "
"statements.")
# Add the skip common options
add_skip_options(parser)
# Add verbosity and quiet (silent) mode
add_verbosity(parser, True)
# Add engine options
add_engines(parser)
# Add multiprocessing option
parser.add_option("--multiprocess", action="store", dest="multiprocess",
type="int", default="1", help="use multiprocessing, "
"number of processes to use for concurrent execution. "
"Special values: 0 (number of processes equal to the "
"CPUs detected) and 1 (default - no concurrency).")
# Add autocommit option.
parser.add_option("--autocommit", action="store_true", dest="autocommit",
default=False, help="use autocommit, by default "
"autocommit is off and transactions are only committed "
"once at the end of each imported file.")
# Add max bulk insert option (to avoid broken pipe errors).
parser.add_option("--max-bulk-insert", action="store", type="int",
dest="max_bulk_insert",
help="maximum bulk insert size, by default 30000.")
# Now we process the rest of the arguments.
opt, args = parser.parse_args()
# Check security settings
check_password_security(opt, args)
# Warn if quiet and verbosity are both specified
check_verbosity(opt)
try:
skips = check_skip_options(opt.skip_objects)
except UtilError:
_, err, _ = sys.exc_info()
print("ERROR: {0}".format(err.errmsg))
sys.exit(1)
# Fail if no arguments
if len(args) == 0:
parser.error("You must specify at least one file to import.")
if opt.skip_blobs and opt.import_type != "data" and not opt.quiet:
print("# WARNING: --skip-blobs option ignored for metadata import.")
if "data" in skips and opt.import_type == "data":
print("ERROR: You cannot use --import=data and --skip-data when "
"importing table data.")
sys.exit(1)
if "create_db" in skips and opt.do_drop:
print("ERROR: You cannot combine --drop-first and --skip=create_db.")
exit(1)
# Check multiprocessing option.
if opt.multiprocess < 0:
parser.error("Number of processes '{0}' must be greater or equal than "
"zero.".format(opt.multiprocess))
num_cpu = multiprocessing.cpu_count()
if opt.multiprocess > num_cpu and not opt.quiet:
print("# WARNING: Number of processes '{0}' is greater than the "
"number of CPUs '{1}'.".format(opt.multiprocess, num_cpu))
# Warning if too many process are used.
num_files = len(args)
if opt.multiprocess > num_files and not opt.quiet:
print("# WARNING: Number of processes '{0}' is greater than the "
"number of files to import '{1}'.".format(opt.multiprocess,
num_files))
# Check max bulk insert option.
if opt.max_bulk_insert and opt.max_bulk_insert <= 1:
parser.error("Maximum bulk insert size '{0}' must be greater than "
"one.".format(opt.max_bulk_insert))
if opt.max_bulk_insert and not opt.bulk_insert and not opt.quiet:
print(WARN_OPT_ONLY_USED_WITH.format(opt="--max-bulk-insert",
used_with="--bulk-insert"))
# Set default value for max bulk insert.
max_bulk_size = opt.max_bulk_insert if opt.max_bulk_insert else 30000
# Set options for database operations.
options = {
"skip_tables": "tables" in skips,
"skip_views": "views" in skips,
"skip_triggers": "triggers" in skips,
"skip_procs": "procedures" in skips,
"skip_funcs": "functions" in skips,
"skip_events": "events" in skips,
"skip_grants": "grants" in skips,
"skip_create": "create_db" in skips,
"skip_data": "data" in skips,
"skip_blobs": opt.skip_blobs,
"format": opt.format,
"no_headers": opt.no_headers,
"single": not opt.bulk_insert,
"import_type": opt.import_type,
"dryrun": opt.dryrun,
"do_drop": opt.do_drop,
"quiet": opt.quiet,
"verbosity": opt.verbosity,
"debug": opt.verbosity >= 3,
"new_engine": opt.new_engine,
"def_engine": opt.def_engine,
"skip_rpl": opt.skip_rpl,
"skip_gtid": opt.skip_gtid,
"table": opt.table,
"charset": opt.charset,
"multiprocess": num_cpu if opt.multiprocess == 0 else opt.multiprocess,
"autocommit": opt.autocommit,
"max_bulk_insert": max_bulk_size,
}
# Parse server connection values
try:
options.update(get_ssl_dict(opt))
server_values = parse_connection(opt.server, None, options)
except FormatError:
_, err, _ = sys.exc_info()
parser.error("Server connection values invalid: {0}.".format(err))
except UtilError:
_, err, _ = sys.exc_info()
parser.error("Server connection values invalid: "
"{0}.".format(err.errmsg))
# Get the sql_mode set on source and destination server
conn_opts = {
'quiet': True,
'version': "5.1.30",
}
try:
servers = connect_servers(server_values, None, conn_opts)
server_sql_mode = servers[0].select_variable("SQL_MODE")
except UtilError:
server_sql_mode = ''
# Check values for --format=raw_csv
if opt.format == "raw_csv":
if not opt.table:
print("ERROR: You must provide --table while using "
"--format=raw_csv.")
sys.exit(1)
# Validate table name using format <db>.<table>
table_regex = REGEXP_QUALIFIED_OBJ_NAME
if "ANSI_QUOTES" in server_sql_mode:
table_regex = REGEXP_QUALIFIED_OBJ_NAME_AQ
table_re = re.compile(
r"{0}(?:\.){0}".format(table_regex)
)
if not table_re.match(opt.table):
parser.error("Invalid table name: {0}.".format(opt.table))
# Ignore --table for formats other than RAW_CSV.
if opt.table and opt.format != "raw_csv" and not opt.quiet:
print("WARNING: The --table option is only required for "
"--format=raw_csv (option ignored).")
# Build list of files to import
file_list = []
for file_name in args:
# Test if is a file
if not os.path.isfile(file_name):
parser.error(FILE_DOES_NOT_EXIST.format(path=file_name))
# Test if is readable
try:
with open(file_name, "r"):
pass
except IOError:
parser.error(
INSUFFICIENT_FILE_PERMISSIONS.format(permissions="read",
path=file_name))
file_list.append(file_name)
try:
# record start time
if opt.verbosity >= 3:
start_test = time.time()
# Import all specified files.
import_file_tasks = []
for file_name in file_list:
# Check multiprocess file import.
# Note: Multiprocessing is only applied at the file level,
# independently from the system (posix or not).
if options['multiprocess'] > 1:
# Create import file task.
import_task = {
'srv_con': server_values,
'file_name': file_name,
'options': options
}
import_file_tasks.append(import_task)
else:
# Import file (no concurrency at the file level).
dbimport.import_file(server_values, file_name, options)
# Import files concurrently.
if import_file_tasks:
# Create process pool.
workers_pool = multiprocessing.Pool(
processes=options['multiprocess']
)
# Concurrently import files.
workers_pool.map_async(dbimport.multiprocess_file_import_task,
import_file_tasks)
workers_pool.close()
workers_pool.join()
if opt.verbosity >= 3:
print_elapsed_time(start_test)
except UtilError:
_, err, _ = sys.exc_info()
print("ERROR: {0}".format(err.errmsg))
sys.exit(1)
sys.exit()