游客发表
昨天我同事老张差点把生产库的订单表给搞崩了。他图省事,直接在SQL Server里写了个OPENQUERY去连MySQL,结果因为排序规则不一致,返回的中文全成了问号。这事让我想起一个被问过无数次的问题:mssql到底怎么连mysql?
办法其实不少,但最常用的就三条路。第一条是装MySQL官方提供的ODBC驱动,然后在SQL Server里配链接服务器。驱动下载完,在“链接服务器”里新建一个,Provider选“Microsoft OLE DB Provider for ODBC Drivers”,数据源填你配好的ODBC名字就行。这里有个坑——填完连接串后,记得在“服务器选项”里把“RPC”和“RPC Out”都设为True,不然你调存储过程时会被卡住。
第二条路是直接用OPENROWSET,适合临时查个数据。写法大概是这样的:
SELECT * FROM OPENROWSET('MSDASQL', 'Driver={ MySQL ODBC 8.0 Unicode Driver};Server=192.168.1.10;Port=3306;Database=testdb;User=root;Password=123456;Option=3', 'SELECT * FROM users')
注意那个“Option=3”,很多新手漏了它,结果中文乱码。这个参数是告诉驱动把返回结果按utf8处理,不写的话,MySQL默认的latin1会把你坑哭。
第三条路,也是我个人最推荐的——用SSIS或者写个小程序做ETL。别笑,真不是小题大做。当你要同步的数据量超过十万行,前两种方式会慢得让你怀疑人生。我见过有人用OPENQUERY拉一张五十万行的表,跑了四十分钟没跑完,最后DBA直接杀进程。为什么?因为MSSQL的查询引擎没办法把过滤条件下推到MySQL,它会把整张表拉过来再筛。SSIS里用ODBC源组件,至少还能走个分页读取。
说个真实案例。今年三月份我帮一个做电商的朋友处理过类似需求,他们用MSSQL做报表,但业务库在MySQL。刚开始也是用链接服务器,每天凌晨同步一次。后来数据量涨到两百万行,同步时间从十几分钟变成两个多小时,经常跟白天的业务高峰撞车。后来我建议他们改成增量同步——在MySQL那边建个更新时间戳字段,MSSQL这边用作业调度,每五分钟拉一次变化的数据。改完以后,同步时间降到二十秒以内,报表延迟从一天缩短到五分钟。
还有个容易忽略的细节:数据类型映射。MSSQL里的datetime跟MySQL的datetime范围不一样,MySQL的timestamp只能存到2038年,但SQL Server的datetime能存到9999年。你倒数据的时候,如果源表里有超出范围的值,驱动会直接报错。解决办法是提前在MySQL那边把字段类型改成datetime或者bigint存时间戳,别偷懒。
最后说点实在的。如果你只是偶尔查个数据,用OPENROWSET最省事;要是每天有固定同步任务,老老实实配链接服务器加作业调度;数据量大又要求实时性,别折腾链接服务器了,写个服务用批量接口同步。别信那些“万能解决方案”的帖子,适合自己的场景才是对的。
友情链接