关于复制:故障分析-记一次-MySQL-复制故障-Errorcode1317

作者:侯晓阳爱可生 DBA 团队成员,次要负责 MySQL 故障解决和 SQL 审核优化。对技术执着,为客户负责。 本文起源:原创投稿 *爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。 问题背景MySQL 从库报错如下: 错误信息如下: ...Last_Errno:1317Last_Error:Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction 'a838ba08-c009-11e9-85e1-fa163ea2992d:31622919405' at master log master-bin.005599, end_log_pos 2297. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any....Last_SQL_Errno:1317Last_SQL_Error:Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction 'a838ba08-c009-11e9-85e1-fa163ea2992d:31622919405' at master log master-bin.005599, end_log_pos 2297. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.排查形式首先咱们先通过 performance_schema 查看一下造成报错的起因mysql> select * from performance_schema.replication_applier_status_by_worker; ...

March 4, 2021 · 1 min · jiezi

关于复制:技术分享-讨论MySQL-从库单表恢复

作者:胡呈清爱可生 DBA 团队成员,善于故障剖析、性能优化,集体博客:https://www.jianshu.com/u/a95...,欢送探讨。本文起源:原创投稿*爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。如果从库上表 t 数据与主库不统一,导致复制谬误,整个库的数据量很大,重做从库很慢,如何独自复原这张表的数据?通常认为是不能修复单表数据的,因为波及到各表状态不统一的问题。上面就列举备份单表复原到从库会面临的问题以及解决办法: 场景 1如果复制报错后,没有应用跳过谬误、复制过滤等办法修复主从复制。主库数据始终在更新,从库数据停滞在报错状态(假如 GTID 为 aaaa:1-100)。 修复步骤:在主库上备份表 t (假如备份快照 GTID 为 aaaa:1-10000);复原到从库;启动复制。这里的问题是复制起始位点是 aaaa:101,从库上表 t 的数据状态是当先其余表的。aaaa:101-10000 这些事务中只有有批改表 t 数据的事务,就会导致复制报错 ,比方主键抵触、记录不存在(而 aaaa:101 这个之前复制报错的事务必然是批改表 t 的事务) 解决办法:启动复制时跳过 aaaa:101-10000 这些事务中批改表 t 的事务。 正确的修复步骤:在主库上备份表 t (假如备份快照 GTID 为 aaaa:1-10000),复原到从库;设置复制过滤,过滤表 t:CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('db_name.t');启动复制,回放到 aaaa:10000 时进行复制(此时从库上所有表的数据都在同一状态,是统一的);START SLAVE UNTIL SQL_AFTER_GTIDS = 'aaaa:10000';删除复制过滤,失常启动复制。注意事项:这里要用 mysqldump --single-transaction --master-data=2,记录备份快照对应的 GTID 场景 2如果复制报错后,应用跳过谬误、复制过滤等方法修复了主从复制。主、从库数据始终在更新。 修复步骤:在主库上备份表 t (假如备份快照 GTID为 aaaa:1-10000);进行从库复制,GTID为 aaaa:1-20000;复原表 t 到从库;启动复制。这里的问题是复制起始位点是 aaaa:20001,aaaa:10000-20000 这些事务将不会在从库上回放,如果这外面有批改表 t 数据的事务,从库上将失落这部分数据。 ...

September 14, 2020 · 1 min · jiezi

对象的合并及拷贝

对象的合并及拷贝Object.assign()Object.assign() 方法用于对象的合并,将所有自身的(非继承的)可枚举属性的值从一个或多个源对象拷贝到目标对象。返回目标对象。目标对象自身也会改变。Object.assign(target, …sources)target: 目标对象。sources: 源对象。Object.assign() 合并拷贝属性的限制只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。Object.assign({b: ‘c’}, Object.defineProperty({}, ‘invisible’, { enumerable: false, value: ‘hello’ }))// { b: ‘c’ }参数类型1. 只有一个参数如果只有一个参数,Object.assign() 会直接返回该参数。let obj = {a: 1};Object.assign(obj) === obj // true如果该参数不是对象,则会先转成对象,然后返回。typeof Object.assign(2) // “object"由于 undefined 和 null 无法转成对象,所以如果它们作为参数,就会报错。Object.assign(undefined) // 报错Object.assign(null) // 报错2. 对象 + 非对象非对象参数都会转成对象,如果无法转成对象,就会跳过,不会报错。如果非对象参数为 undefined 和 null ,就会跳过,不会报错,返回的依旧是目标对象参数。let obj = {a: 1};Object.assign(obj, undefined) === obj // trueObject.assign(obj, null) === obj // true如果非对象参数为其他类型的值(即数值、字符串和布尔值),也不会报错。但是,除了字符串会以数组形式拷贝入目标对象,其他值都不会产生效果。这是因为只有字符串的包装对象,会产生可枚举属性。let v1 = ‘abc’;let v2 = true;let v3 = 10;let obj = Object.assign({}, v1, v2, v3);console.log(obj) // { “0”: “a”, “1”: “b”, “2”: “c” }3. 目标对象 + 源对象…(1) 属性值为 null 或 undefined 的属性会正常合并Object.assign() 不会跳过那些属性值为 null 或 undefined 的源对象。var o1 = { a: null, b: 1};var o2 = { c: undefined }; var obj = Object.assign({}, o1, o2);obj // {a: null, b: 1, c: undefined}(2) 同名属性的替换如果目标对象与源对象中的属性具有相同的键,则目标对象属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性。var o1 = { a: 1, b: 1, c: 1 };var o2 = { b: 2, c: 2 };var o3 = { c: 3 };var obj = Object.assign({}, o1, o2, o3);obj // { a: 1, b: 2, c: 3 }(3) 浅拷贝Object.assign() 方法实行的是浅拷贝,而不是深拷贝。拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。var obj1 = { a: 0 , b: { c: 0 } };var obj2 = Object.assign({}, obj1);obj2 // { a: 0, b: { c: 0 } };obj2.b.c = 3;obj1 // { a: 0, b: { c: 3 } };obj2 // { a: 0, b: { c: 3 } };(4) 数组的处理Object.assign() 可以用来处理数组,但是会把数组视为键值为数组下标的对象来合并,然而最终的返回形式也是数组。Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3]Object.assign({0:1,1:2,2:3},{0:4,1:5}) // {0: 4, 1: 5, 2: 3}(5) 存取器属性的处理Object.assign() 如果遇到存取器定义的属性,会只拷贝值。var obj = { foo: 1, get bar() { return 2; }};var copy = Object.assign({}, obj); copy // { foo: 1, bar: 2 }因此必须使用 Object.getOwnPropertyDescriptors() 方法配合 Object.defineProperties() 方法,就可以实现正确拷贝。但仅限于可拷贝 getter 和 setter ,对于属性的引用类型还是属于浅拷贝。var obj = { foo: { a : 0 }, get bar() { return 2; }};var target = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));Object.getOwnPropertyDescriptor(target, ‘bar’)// { get : ƒ bar(), set : undefined, enumerable : true, configurable : true } obj.foo.a = 6target.foo.a // 6常见用途1. 为对象添加属性class Point { constructor(x, y) { Object.assign(this, {x, y}); }}上面方法通过 Object.assign() 方法,将 x 属性和 y 属性添加到 Point 类的对象实例。2. 为对象添加方法Object.assign(SomeClass.prototype, { someMethod(arg1, arg2) { ··· }, anotherMethod() { ··· }});// 等同于下面的写法SomeClass.prototype.someMethod = function (arg1, arg2) { ··· };SomeClass.prototype.anotherMethod = function () { ··· };3. 浅克隆对象let obj = {a:5};function clone(origin) { return Object.assign({}, origin);}let aaa = clone(obj); // {a:5}不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。function clone(origin) { let originProto = Object.getPrototypeOf(origin); return Object.assign(Object.create(originProto), origin);}4. 合并多个对象let merge = (target, …sources) => Object.assign(target, …sources);如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。let merge = (…sources) => Object.assign({}, …sources);5. 为属性指定默认值const DEFAULTS = { a: 0, b: ‘ccc’};function copy(options) { options = Object.assign({}, DEFAULTS, options); // …}注意,由于存在浅拷贝的问题,DEFAULTS对象和options对象的所有属性的值,最好都是简单类型,不要指向另一个对象。否则,DEFAULTS对象的该属性很可能不起作用。参考链接:Object.assign()深拷贝1. JSON.parse(JSON.stringify(obj))var obj1 = { a: 0 , b: { c: 0}};var obj2 = JSON.parse(JSON.stringify(obj1));obj1.b.c = 4;obj2 // { a: 0, b: { c: 0}}但由于 JSON 的局限性,该方法也不是万能的。比如,如果对象的属性是 undefined、函数、symbol 或 XML 对象,该属性会被 JSON.stringify() 过滤掉,导致拷贝时会缺少属性。let obj = { name:‘dora’, sayHello:function(){ console.log(‘Hello World’); }}let cloneObj = JSON.parse(JSON.stringify(obj));console.log(cloneObj); // {name: “dora”}2. 利用递归对每一层都重新创建对象并赋值从而实现深拷贝function deepClone(source){ let targetObj = source.constructor === Array ? [] : {}; for(let keys in source){ if(source.hasOwnProperty(keys)){ if(source[keys] && typeof source[keys] === ‘object’){ targetObj[keys] = source[keys].constructor === Array ? [] : {}; targetObj[keys] = deepClone(source[keys]); }else{ targetObj[keys] = source[keys]; } } } return targetObj;}let obj = { a: { b: 1, c: 2 }, sayHello: function(){ console.log(‘Hello World’); } }let cloneObj = deepClone(obj);obj.a.b = 4obj // {a:{b: 4, c: 2},sayHello:ƒ ()}cloneObj // {a:{b: 1, c: 2},sayHello:ƒ ()} ...

January 17, 2019 · 3 min · jiezi